]> git.hungrycats.org Git - linux/commitdiff
[XFS] Implement several additional inode flags - immutable, append-only, etc; contrib...
authorNathan Scott <nathans@sgi.com>
Mon, 15 Sep 2003 07:39:24 +0000 (02:39 -0500)
committerStephen Lord <lord@kernel.bkbits.net>
Mon, 15 Sep 2003 07:39:24 +0000 (02:39 -0500)
SGI Modid: 2.5.x-xfs:slinx:158362a

17 files changed:
fs/xfs/linux/xfs_globals.c
fs/xfs/linux/xfs_ioctl.c
fs/xfs/linux/xfs_iops.c
fs/xfs/linux/xfs_linux.h
fs/xfs/linux/xfs_super.c
fs/xfs/linux/xfs_sysctl.c
fs/xfs/linux/xfs_sysctl.h
fs/xfs/linux/xfs_vnode.c
fs/xfs/xfs_acl.c
fs/xfs/xfs_cap.c
fs/xfs/xfs_dinode.h
fs/xfs/xfs_fs.h
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_vnodeops.c
fs/xfs/xfsidbg.c

index 2509bfbe06b4c81a60f63927e0dcb479cbc8462b..ef99bdf05ff1298091cf4764c856c6e920100648 100644 (file)
@@ -59,6 +59,8 @@ xfs_param_t xfs_params = {
        .error_level    = {     0,      3,      11      },
        .sync_interval  = {     HZ,     30*HZ,  60*HZ   },
        .stats_clear    = {     0,      0,      1       },
+       .inherit_sync   = {     0,      1,      1       },
+       .inherit_nodump = {     0,      1,      1       },
 };
 
 /*
index 55691b0879d41a1bb620f451e5db1ac861bef9fc..d3860a6f85626b9d889487b964f2905a0d2fb1a3 100644 (file)
 #include <linux/namei.h>
 #include <linux/pagemap.h>
 
+/*
+ * ioctl commands that are used by Linux filesystems
+ */
+#define XFS_IOC_GETXFLAGS      _IOR('f', 1, long)
+#define XFS_IOC_SETXFLAGS      _IOW('f', 2, long)
+#define XFS_IOC_GETVERSION     _IOR('v', 1, long)
+
 
 /*
  * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
@@ -328,6 +335,17 @@ xfs_open_by_handle(
        if (permflag & O_TRUNC)
                permflag |= 2;
 
+       if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
+           (permflag & FMODE_WRITE) && IS_APPEND(inode)) {
+               iput(inode);
+               return -XFS_ERROR(EPERM);
+       }
+
+       if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
+               iput(inode);
+               return -XFS_ERROR(EACCES);
+       }
+
        /* Can't write directories. */
        if ( S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) {
                iput(inode);
@@ -429,6 +447,11 @@ xfs_fssetdm_by_handle(
        if (error)
                return -error;
 
+       if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+               VN_RELE(vp);
+               return -XFS_ERROR(EPERM);
+       }
+
        if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) {
                VN_RELE(vp);
                return -XFS_ERROR(EFAULT);
@@ -514,11 +537,19 @@ xfs_attrmulti_by_handle(
                                        NULL, ops[i].am_error);
                        break;
                case ATTR_OP_SET:
+                       if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+                               ops[i].am_error = EPERM;
+                               break;
+                       }
                        VOP_ATTR_SET(vp,ops[i].am_attrname, ops[i].am_attrvalue,
                                        ops[i].am_length, ops[i].am_flags,
                                        NULL, ops[i].am_error);
                        break;
                case ATTR_OP_REMOVE:
+                       if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+                               ops[i].am_error = EPERM;
+                               break;
+                       }
                        VOP_ATTR_REMOVE(vp, ops[i].am_attrname, ops[i].am_flags,
                                        NULL, ops[i].am_error);
                        break;
@@ -566,6 +597,7 @@ xfs_ioc_fsgeometry(
 STATIC int
 xfs_ioc_xattr(
        vnode_t                 *vp,
+       xfs_inode_t             *ip,
        struct file             *filp,
        unsigned int            cmd,
        unsigned long           arg);
@@ -648,10 +680,13 @@ xfs_ioctl(
        case XFS_IOC_FSGEOMETRY:
                return xfs_ioc_fsgeometry(mp, arg);
 
+       case XFS_IOC_GETVERSION:
+       case XFS_IOC_GETXFLAGS:
+       case XFS_IOC_SETXFLAGS:
        case XFS_IOC_FSGETXATTR:
        case XFS_IOC_FSSETXATTR:
        case XFS_IOC_FSGETXATTRA:
-               return xfs_ioc_xattr(vp, filp, cmd, arg);
+               return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
 
        case XFS_IOC_FSSETDM: {
                struct fsdmidata        dmi;
@@ -837,6 +872,9 @@ xfs_ioc_space(
        int                     attr_flags = 0;
        int                     error;
 
+       if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
+               return -XFS_ERROR(EPERM);
+
        if (filp->f_flags & O_RDONLY)
                return -XFS_ERROR(EBADF);
 
@@ -957,9 +995,50 @@ xfs_ioc_fsgeometry(
        return 0;
 }
 
+/*
+ * Linux extended inode flags interface.
+ */
+#define LINUX_XFLAG_SYNC       0x00000008 /* Synchronous updates */
+#define LINUX_XFLAG_IMMUTABLE  0x00000010 /* Immutable file */
+#define LINUX_XFLAG_APPEND     0x00000020 /* writes to file may only append */
+#define LINUX_XFLAG_NODUMP     0x00000040 /* do not dump file */
+#define LINUX_XFLAG_NOATIME    0x00000080 /* do not update atime */
+
+STATIC unsigned int
+xfs_merge_ioc_xflags(
+       unsigned int    flags,
+       unsigned int    start)
+{
+       unsigned int    xflags = start;
+
+       if (flags & LINUX_XFLAG_IMMUTABLE)
+               xflags |= XFS_XFLAG_IMMUTABLE;
+       else
+               xflags &= ~XFS_XFLAG_IMMUTABLE;
+       if (flags & LINUX_XFLAG_APPEND)
+               xflags |= XFS_XFLAG_APPEND;
+       else
+               xflags &= ~XFS_XFLAG_APPEND;
+       if (flags & LINUX_XFLAG_SYNC)
+               xflags |= XFS_XFLAG_SYNC;
+       else
+               xflags &= ~XFS_XFLAG_SYNC;
+       if (flags & LINUX_XFLAG_NOATIME)
+               xflags |= XFS_XFLAG_NOATIME;
+       else
+               xflags &= ~XFS_XFLAG_NOATIME;
+       if (flags & LINUX_XFLAG_NODUMP)
+               xflags |= XFS_XFLAG_NODUMP;
+       else
+               xflags &= ~XFS_XFLAG_NODUMP;
+
+       return xflags;
+}
+
 STATIC int
 xfs_ioc_xattr(
        vnode_t                 *vp,
+       xfs_inode_t             *ip,
        struct file             *filp,
        unsigned int            cmd,
        unsigned long           arg)
@@ -967,6 +1046,8 @@ xfs_ioc_xattr(
        struct fsxattr          fa;
        vattr_t                 va;
        int                     error;
+       int                     attr_flags;
+       unsigned int            flags;
 
        switch (cmd) {
        case XFS_IOC_FSGETXATTR: {
@@ -985,24 +1066,24 @@ xfs_ioc_xattr(
        }
 
        case XFS_IOC_FSSETXATTR: {
-               int             attr_flags = 0;
-
                if (copy_from_user(&fa, (struct fsxattr *)arg, sizeof(fa)))
                        return -XFS_ERROR(EFAULT);
 
+               attr_flags = 0;
+               if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
+                       attr_flags |= ATTR_NONBLOCK;
+
                va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE;
                va.va_xflags  = fa.fsx_xflags;
                va.va_extsize = fa.fsx_extsize;
 
-               if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
-                       attr_flags |= ATTR_NONBLOCK;
-
                VOP_SETATTR(vp, &va, attr_flags, NULL, error);
+               if (!error)
+                       vn_revalidate(vp);      /* update Linux inode flags */
                return -error;
        }
 
        case XFS_IOC_FSGETXATTRA: {
-
                va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS;
                VOP_GETATTR(vp, &va, 0, NULL, error);
                if (error)
@@ -1017,9 +1098,54 @@ xfs_ioc_xattr(
                return 0;
        }
 
+       case XFS_IOC_GETXFLAGS: {
+               flags = 0;
+               if (ip->i_d.di_flags & XFS_XFLAG_IMMUTABLE)
+                       flags |= LINUX_XFLAG_IMMUTABLE;
+               if (ip->i_d.di_flags & XFS_XFLAG_APPEND)
+                       flags |= LINUX_XFLAG_APPEND;
+               if (ip->i_d.di_flags & XFS_XFLAG_SYNC)
+                       flags |= LINUX_XFLAG_SYNC;
+               if (ip->i_d.di_flags & XFS_XFLAG_NOATIME)
+                       flags |= LINUX_XFLAG_NOATIME;
+               if (ip->i_d.di_flags & XFS_XFLAG_NODUMP)
+                       flags |= LINUX_XFLAG_NODUMP;
+               if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags)))
+                       return -XFS_ERROR(EFAULT);
+               return 0;
+       }
+
+       case XFS_IOC_SETXFLAGS: {
+               if (copy_from_user(&flags, (unsigned int *)arg, sizeof(flags)))
+                       return -XFS_ERROR(EFAULT);
+
+               if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
+                             LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \
+                             LINUX_XFLAG_SYNC))
+                       return -XFS_ERROR(EOPNOTSUPP);
+
+               attr_flags = 0;
+               if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
+                       attr_flags |= ATTR_NONBLOCK;
+
+               va.va_mask = XFS_AT_XFLAGS;
+               va.va_xflags = xfs_merge_ioc_xflags(flags, ip->i_d.di_flags);
+
+               VOP_SETATTR(vp, &va, attr_flags, NULL, error);
+               if (!error)
+                       vn_revalidate(vp);      /* update Linux inode flags */
+               return -error;
+       }
+
+       case XFS_IOC_GETVERSION: {
+               flags = LINVFS_GET_IP(vp)->i_generation;
+               if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags)))
+                       return -XFS_ERROR(EFAULT);
+               return 0;
+       }
+
        default:
                return -ENOTTY;
-
        }
 }
 
index cb9bcdda6d015919c29f65cba174331a109e4022..11c1736bf4f764574e44a6996156b1b53b5e0d77 100644 (file)
@@ -638,6 +638,9 @@ linvfs_setxattr(
                return error;
        }
 
+       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+               return -EPERM;
+
        /* Convert Linux syscall to XFS internal ATTR flags */
        if (flags & XATTR_CREATE)
                xflags |= ATTR_CREATE;
@@ -787,6 +790,9 @@ linvfs_removexattr(
                return error;
        }
 
+        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+               return -EPERM;
+
        if (strncmp(name, xfs_namespaces[ROOT_NAMES].name,
                        xfs_namespaces[ROOT_NAMES].namelen) == 0) {
                if (!capable(CAP_SYS_ADMIN))
index fe259b0c32f11bc5854d24b0c175de4ed66171f1..f319e8368ef5c34ce059a3f326852953b07b4774 100644 (file)
@@ -96,6 +96,8 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
 #define xfs_error_level                xfs_params.error_level.val
 #define xfs_syncd_interval     xfs_params.sync_interval.val
 #define xfs_stats_clear                xfs_params.stats_clear.val
+#define xfs_inherit_sync       xfs_params.inherit_sync.val
+#define xfs_inherit_nodump     xfs_params.inherit_nodump.val
 
 #define NBPP           PAGE_SIZE
 #define DPPSHFT                (PAGE_SHIFT - 9)
index 1bd4b3a4a60450b31307af49d9493d1f88d0d7e1..76ca5aec56d22f3ce3899378804479acbebb59df 100644 (file)
@@ -187,7 +187,22 @@ xfs_revalidate_inode(
        inode->i_mtime.tv_nsec  = ip->i_d.di_mtime.t_nsec;
        inode->i_ctime.tv_sec   = ip->i_d.di_ctime.t_sec;
        inode->i_ctime.tv_nsec  = ip->i_d.di_ctime.t_nsec;
-
+       if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE)
+               inode->i_flags |= S_IMMUTABLE;
+       else
+               inode->i_flags &= ~S_IMMUTABLE;
+       if (ip->i_d.di_flags & XFS_DIFLAG_APPEND)
+               inode->i_flags |= S_APPEND;
+       else
+               inode->i_flags &= ~S_APPEND;
+       if (ip->i_d.di_flags & XFS_DIFLAG_SYNC)
+               inode->i_flags |= S_SYNC;
+       else
+               inode->i_flags &= ~S_SYNC;
+       if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME)
+               inode->i_flags |= S_NOATIME;
+       else
+               inode->i_flags &= ~S_NOATIME;
        vp->v_flag &= ~VMODIFIED;
 }
 
index 34041998ba39071ab7b46f242f36a59eaad861f3..1b731f95b1edf8e637df41bfb2b66b6a4f9d7a78 100644 (file)
@@ -97,6 +97,16 @@ STATIC ctl_table xfs_table[] = {
        &sysctl_intvec, NULL, 
        &xfs_params.sync_interval.min, &xfs_params.sync_interval.max},
 
+       {XFS_INHERIT_SYNC, "inherit_sync", &xfs_params.inherit_sync.val,
+       sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
+       &sysctl_intvec, NULL,
+       &xfs_params.inherit_sync.min, &xfs_params.inherit_sync.max},
+
+       {XFS_INHERIT_NODUMP, "inherit_nodump", &xfs_params.inherit_nodump.val,
+       sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
+       &sysctl_intvec, NULL,
+       &xfs_params.inherit_nodump.min, &xfs_params.inherit_nodump.max},
+
        /* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
        {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
index 45bc8a0a8f42b3714415b5b957b7476b0959dda0..0b6e690172aa6f67728940d10b26ed9f25296eb9 100644 (file)
@@ -55,6 +55,8 @@ typedef struct xfs_param {
        xfs_sysctl_val_t error_level;   /* Degree of reporting for problems  */
        xfs_sysctl_val_t sync_interval; /* time between sync calls           */
        xfs_sysctl_val_t stats_clear;   /* Reset all XFS statistics to zero. */
+       xfs_sysctl_val_t inherit_sync;  /* Inherit the "sync" inode flag. */
+       xfs_sysctl_val_t inherit_nodump;/* Inherit the "nodump" inode flag. */
 } xfs_param_t;
 
 /*
@@ -73,13 +75,15 @@ typedef struct xfs_param {
  */
 
 enum {
-       XFS_RESTRICT_CHOWN = 1,
-       XFS_SGID_INHERIT = 2,
-       XFS_SYMLINK_MODE = 3,
-       XFS_PANIC_MASK = 4,
-       XFS_ERRLEVEL = 5,
-       XFS_SYNC_INTERVAL = 6,
-       XFS_STATS_CLEAR = 7,
+       XFS_RESTRICT_CHOWN = 3,
+       XFS_SGID_INHERIT = 4,
+       XFS_SYMLINK_MODE = 5,
+       XFS_PANIC_MASK = 6,
+       XFS_ERRLEVEL = 7,
+       XFS_SYNC_INTERVAL = 8,
+       XFS_STATS_CLEAR = 12,
+       XFS_INHERIT_SYNC = 13,
+       XFS_INHERIT_NODUMP = 14,
 };
 
 extern xfs_param_t     xfs_params;
index fd0d0fca194d626f797c46c4aa42f92fd32667f6..92a1a488e372d350f54234667a8b8087538f9344 100644 (file)
@@ -213,6 +213,22 @@ vn_revalidate(
                inode->i_ctime      = va.va_ctime;
                inode->i_atime      = va.va_atime;
                i_size_write(inode, va.va_size);
+               if (va.va_xflags & XFS_XFLAG_IMMUTABLE)
+                       inode->i_flags |= S_IMMUTABLE;
+               else
+                       inode->i_flags &= ~S_IMMUTABLE;
+               if (va.va_xflags & XFS_XFLAG_APPEND)
+                       inode->i_flags |= S_APPEND;
+               else
+                       inode->i_flags &= ~S_APPEND;
+               if (va.va_xflags & XFS_XFLAG_SYNC)
+                       inode->i_flags |= S_SYNC;
+               else
+                       inode->i_flags &= ~S_SYNC;
+               if (va.va_xflags & XFS_XFLAG_NOATIME)
+                       inode->i_flags |= S_NOATIME;
+               else
+                       inode->i_flags &= ~S_NOATIME;
                VUNMODIFY(vp);
        }
        return -error;
index 950b50b9b6cf49939062fafd1bf5dccc5fc335ce..596d9400b9e174c5c466b7803350b3c2538338e6 100644 (file)
@@ -388,6 +388,8 @@ xfs_acl_allow_set(
        vattr_t         va;
        int             error;
 
+       if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
+               return EPERM;
        if (kind == _ACL_TYPE_DEFAULT && vp->v_type != VDIR)
                return ENOTDIR;
        if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
index 61731d7573a43dad0de3f58a0efd3b21c51aada0..638dbe5be62f2da91a80b67f4d55550f338fa74d 100644 (file)
@@ -192,6 +192,8 @@ xfs_cap_allow_set(
 
        if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
                return EROFS;
+       if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
+               return EPERM;
        if ((error = _MAC_VACCESS(vp, NULL, VWRITE)))
                return error;
        va.va_mask = XFS_AT_UID;
index 0af61bc72bd54ee65669143483b27cc7f8aea1c5..86968706bae71f6671edba4fe1c348e850a0d669 100644 (file)
@@ -471,13 +471,21 @@ xfs_dinode_t *xfs_buf_to_dinode(struct xfs_buf *bp);
  * There should be a one-to-one correspondence between these flags and the
  * XFS_XFLAG_s.
  */
-#define XFS_DIFLAG_REALTIME_BIT        0       /* file's blocks come from rt area */
-#define XFS_DIFLAG_PREALLOC_BIT        1       /* file space has been preallocated */
-#define        XFS_DIFLAG_NEWRTBM_BIT  2       /* for rtbitmap inode, new format */
-#define XFS_DIFLAG_REALTIME     (1 << XFS_DIFLAG_REALTIME_BIT)
-#define XFS_DIFLAG_PREALLOC    (1 << XFS_DIFLAG_PREALLOC_BIT)
-#define        XFS_DIFLAG_NEWRTBM      (1 << XFS_DIFLAG_NEWRTBM_BIT)
-#define XFS_DIFLAG_ALL  \
-       (XFS_DIFLAG_REALTIME|XFS_DIFLAG_PREALLOC|XFS_DIFLAG_NEWRTBM)
+#define XFS_DIFLAG_REALTIME_BIT  0     /* file's blocks come from rt area */
+#define XFS_DIFLAG_PREALLOC_BIT  1     /* file space has been preallocated */
+#define XFS_DIFLAG_NEWRTBM_BIT   2     /* for rtbitmap inode, new format */
+#define XFS_DIFLAG_IMMUTABLE_BIT 3     /* inode is immutable */
+#define XFS_DIFLAG_APPEND_BIT    4     /* inode is append-only */
+#define XFS_DIFLAG_SYNC_BIT      5     /* inode is written synchronously */
+#define XFS_DIFLAG_NOATIME_BIT   6     /* do not update atime */
+#define XFS_DIFLAG_NODUMP_BIT    7     /* do not dump */
+#define XFS_DIFLAG_REALTIME      (1 << XFS_DIFLAG_REALTIME_BIT)
+#define XFS_DIFLAG_PREALLOC      (1 << XFS_DIFLAG_PREALLOC_BIT)
+#define XFS_DIFLAG_NEWRTBM       (1 << XFS_DIFLAG_NEWRTBM_BIT)
+#define XFS_DIFLAG_IMMUTABLE     (1 << XFS_DIFLAG_IMMUTABLE_BIT)
+#define XFS_DIFLAG_APPEND        (1 << XFS_DIFLAG_APPEND_BIT)
+#define XFS_DIFLAG_SYNC          (1 << XFS_DIFLAG_SYNC_BIT)
+#define XFS_DIFLAG_NOATIME       (1 << XFS_DIFLAG_NOATIME_BIT)
+#define XFS_DIFLAG_NODUMP        (1 << XFS_DIFLAG_NODUMP_BIT)
 
 #endif /* __XFS_DINODE_H__ */
index d52e8146239c20f58708af1a9c6a9978fb37b2fe..c2c3cc118f97095e21230eb6d9cee91167079db8 100644 (file)
@@ -69,12 +69,14 @@ struct fsxattr {
  * There should be a one-to-one correspondence between these flags and the
  * XFS_DIFLAG_s.
  */
-#define XFS_XFLAG_REALTIME     0x00000001
-#define XFS_XFLAG_PREALLOC     0x00000002
+#define XFS_XFLAG_REALTIME     0x00000001      /* data in realtime volume */
+#define XFS_XFLAG_PREALLOC     0x00000002      /* preallocated file extents */
+#define XFS_XFLAG_IMMUTABLE    0x00000008      /* file cannot be modified */
+#define XFS_XFLAG_APPEND       0x00000010      /* all writes append */
+#define XFS_XFLAG_SYNC         0x00000020      /* all writes synchronous */
+#define XFS_XFLAG_NOATIME      0x00000040      /* do not update access time */
+#define XFS_XFLAG_NODUMP       0x00000080      /* do not include in backups */
 #define XFS_XFLAG_HASATTR      0x80000000      /* no DIFLAG for this   */
-#define XFS_XFLAG_ALL          \
-       ( XFS_XFLAG_REALTIME|XFS_XFLAG_PREALLOC|XFS_XFLAG_HASATTR )
-
 
 /*
  * Structure for XFS_IOC_GETBMAP.
index fe426e94b351a37b143ac07bd85f0311874cf429..2f95078422e299bed9981d9e2f6e37c23c2b56f1 100644 (file)
@@ -1114,7 +1114,7 @@ xfs_dilocate(
        agbno = XFS_AGINO_TO_AGBNO(mp, agino);
        if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
            ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
-#ifdef DEBUG
+#if 0
                if (agno >= mp->m_sb.sb_agcount) {
                        xfs_fs_cmn_err(CE_ALERT, mp,
                                        "xfs_dilocate: agno (%d) >= "
index 22d43d5d2bb3d2bedfec53b9b7758b8784796be7..da144b220a07622babfd05f71e24d521748b2dd9 100644 (file)
@@ -1197,6 +1197,8 @@ xfs_ialloc(
        ip->i_d.di_dmevmask = 0;
        ip->i_d.di_dmstate = 0;
        ip->i_d.di_flags = 0;
+       if ((pip->i_d.di_flags & XFS_DIFLAG_NODUMP) && xfs_inherit_nodump)
+               ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
        flags = XFS_ILOG_CORE;
        switch (mode & IFMT) {
        case IFIFO:
@@ -1210,6 +1212,8 @@ xfs_ialloc(
                break;
        case IFREG:
        case IFDIR:
+               if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) && xfs_inherit_sync)
+                       ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
        case IFLNK:
                ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
                ip->i_df.if_flags = XFS_IFEXTENTS;
@@ -3500,6 +3504,9 @@ xfs_iaccess(
                if (IS_RDONLY(inode) &&
                    (S_ISREG(imode) || S_ISDIR(imode) || S_ISLNK(imode)))
                        return XFS_ERROR(EROFS);
+
+               if (IS_IMMUTABLE(inode))
+                       return XFS_ERROR(EACCES);
        }
 
        /*
@@ -3623,7 +3630,7 @@ xfs_ichgtime(xfs_inode_t *ip,
         * Don't update access timestamps on reads if mounted "noatime"
         * Throw it away if anyone asks us.
         */
-       if (ip->i_mount->m_flags & XFS_MOUNT_NOATIME &&
+       if ((ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) &&
            ((flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG))
                        == XFS_ICHGTIME_ACC))
                return;
index 50836e4864b4552715c6a004d6415bc077307ed1..8d09bfb2a9664fa57597ded973e3dec9d672f92f 100644 (file)
@@ -156,13 +156,23 @@ xfs_bulkstat_one(
        /*
         * convert di_flags to bs_xflags.
         */
-       di_flags=INT_GET(dic->di_flags, arch);
+       di_flags = INT_GET(dic->di_flags, arch);
 
        buf->bs_xflags =
                ((di_flags & XFS_DIFLAG_REALTIME) ?
                        XFS_XFLAG_REALTIME : 0) |
                ((di_flags & XFS_DIFLAG_PREALLOC) ?
                        XFS_XFLAG_PREALLOC : 0) |
+               ((di_flags & XFS_DIFLAG_IMMUTABLE) ?
+                       XFS_XFLAG_IMMUTABLE : 0) |
+               ((di_flags & XFS_DIFLAG_APPEND) ?
+                       XFS_XFLAG_APPEND : 0) |
+               ((di_flags & XFS_DIFLAG_SYNC) ?
+                       XFS_XFLAG_SYNC : 0) |
+               ((di_flags & XFS_DIFLAG_NOATIME) ?
+                       XFS_XFLAG_NOATIME : 0) |
+               ((di_flags & XFS_DIFLAG_NODUMP) ?
+                       XFS_XFLAG_NODUMP : 0) |
                (XFS_CFORK_Q_ARCH(dic, arch) ?
                        XFS_XFLAG_HASATTR : 0);
 
index 270af19d6e5747ffd25dc7b72ce59301f89a1b8a..9f6622c28b48cc4f56e2b07e715041cf3faa9d9a 100644 (file)
@@ -265,6 +265,16 @@ xfs_getattr(
                        XFS_XFLAG_REALTIME : 0) |
                ((ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) ?
                        XFS_XFLAG_PREALLOC : 0) |
+               ((ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) ?
+                       XFS_XFLAG_IMMUTABLE : 0) |
+               ((ip->i_d.di_flags & XFS_DIFLAG_APPEND) ?
+                       XFS_XFLAG_APPEND : 0) |
+               ((ip->i_d.di_flags & XFS_DIFLAG_SYNC) ?
+                       XFS_XFLAG_SYNC : 0) |
+               ((ip->i_d.di_flags & XFS_DIFLAG_NOATIME) ?
+                       XFS_XFLAG_NOATIME : 0) |
+               ((ip->i_d.di_flags & XFS_DIFLAG_NODUMP) ?
+                       XFS_XFLAG_NODUMP: 0) |
                (XFS_IFORK_Q(ip) ?
                        XFS_XFLAG_HASATTR : 0);
        vap->va_extsize = ip->i_d.di_extsize << mp->m_sb.sb_blocklog;
@@ -647,6 +657,20 @@ xfs_setattr(
                                goto error_return;
                        }
                }
+
+               /*
+                * Can't modify an immutable/append-only file unless
+                * we have appropriate permission.
+                */
+               if ((mask & XFS_AT_XFLAGS) &&
+                   (ip->i_d.di_flags &
+                               (XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) ||
+                    (vap->va_xflags &
+                               (XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) &&
+                   !capable(CAP_LINUX_IMMUTABLE)) {
+                       code = XFS_ERROR(EPERM);
+                       goto error_return;
+               }
        }
 
        /*
@@ -832,6 +856,16 @@ xfs_setattr(
                                ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
                                ip->i_iocore.io_flags |= XFS_IOCORE_RT;
                        }
+                       if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
+                               ip->i_d.di_flags |= XFS_DIFLAG_IMMUTABLE;
+                       if (vap->va_xflags & XFS_XFLAG_APPEND)
+                               ip->i_d.di_flags |= XFS_DIFLAG_APPEND;
+                       if (vap->va_xflags & XFS_XFLAG_SYNC)
+                               ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+                       if (vap->va_xflags & XFS_XFLAG_NOATIME)
+                               ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
+                       if (vap->va_xflags & XFS_XFLAG_NODUMP)
+                               ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
                        /* can't set PREALLOC this way, just ignore it */
                }
                xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
@@ -1634,7 +1668,7 @@ xfs_release(
                if ((((ip->i_d.di_mode & IFMT) == IFREG) &&
                     ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) &&
                     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
-                   (!(ip->i_d.di_flags & XFS_DIFLAG_PREALLOC))) {
+                   (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)))) {
                        if ((error = xfs_inactive_free_eofblocks(mp, ip)))
                                return (error);
                        /* Update linux inode block count after free above */
@@ -1709,7 +1743,7 @@ xfs_inactive(
                if ((((ip->i_d.di_mode & IFMT) == IFREG) &&
                     ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) &&
                     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
-                   (!(ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) ||
+                   (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)) ||
                     (ip->i_delayed_blks != 0))) {
                        if ((error = xfs_inactive_free_eofblocks(mp, ip)))
                                return (VN_INACTIVE_CACHE);
index f0a98f284541804128acbdf34f246bb28a739b18..1f7daff612f4ae7ba9bbeef7d2b4a4329ff8a7b3 100644 (file)
@@ -3021,6 +3021,12 @@ xfs_prdinode_core(xfs_dinode_core_t *dip, int convert)
        static char *diflags[] = {
                "realtime",             /* XFS_DIFLAG_REALTIME */
                "prealloc",             /* XFS_DIFLAG_PREALLOC */
+               "newrtbm",              /* XFS_DIFLAG_NEWRTBM */
+               "immutable",            /* XFS_DIFLAG_IMMUTABLE */
+               "append",               /* XFS_DIFLAG_APPEND */
+               "sync",                 /* XFS_DIFLAG_SYNC */
+               "noatime",              /* XFS_DIFLAG_NOATIME */
+               "nodump",               /* XFS_DIFLAG_NODUMP */
                NULL
        };