Merge tag 'io_uring-5.14-2021-08-13' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / fs / ocfs2 / ioctl.c
index 50c9b30..f59461d 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/mount.h>
 #include <linux/blkdev.h>
 #include <linux/compat.h>
+#include <linux/fileattr.h>
 
 #include <cluster/masklog.h>
 
@@ -61,8 +62,10 @@ static inline int o2info_coherent(struct ocfs2_info_request *req)
        return (!(req->ir_flags & OCFS2_INFO_FL_NON_COHERENT));
 }
 
-static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
+int ocfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa)
 {
+       struct inode *inode = d_inode(dentry);
+       unsigned int flags;
        int status;
 
        status = ocfs2_inode_lock(inode, NULL, 0);
@@ -71,15 +74,19 @@ static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
                return status;
        }
        ocfs2_get_inode_flags(OCFS2_I(inode));
-       *flags = OCFS2_I(inode)->ip_attr;
+       flags = OCFS2_I(inode)->ip_attr;
        ocfs2_inode_unlock(inode, 0);
 
+       fileattr_fill_flags(fa, flags & OCFS2_FL_VISIBLE);
+
        return status;
 }
 
-static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
-                               unsigned mask)
+int ocfs2_fileattr_set(struct user_namespace *mnt_userns,
+                      struct dentry *dentry, struct fileattr *fa)
 {
+       struct inode *inode = d_inode(dentry);
+       unsigned int flags = fa->flags;
        struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode);
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        handle_t *handle = NULL;
@@ -87,7 +94,8 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
        unsigned oldflags;
        int status;
 
-       inode_lock(inode);
+       if (fileattr_has_fsx(fa))
+               return -EOPNOTSUPP;
 
        status = ocfs2_inode_lock(inode, &bh, 1);
        if (status < 0) {
@@ -95,19 +103,17 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
                goto bail;
        }
 
-       status = -EACCES;
-       if (!inode_owner_or_capable(&init_user_ns, inode))
-               goto bail_unlock;
-
        if (!S_ISDIR(inode->i_mode))
                flags &= ~OCFS2_DIRSYNC_FL;
 
        oldflags = ocfs2_inode->ip_attr;
-       flags = flags & mask;
-       flags |= oldflags & ~mask;
+       flags = flags & OCFS2_FL_MODIFIABLE;
+       flags |= oldflags & ~OCFS2_FL_MODIFIABLE;
 
-       status = vfs_ioc_setflags_prepare(inode, oldflags, flags);
-       if (status)
+       /* Check already done by VFS, but repeat with ocfs lock */
+       status = -EPERM;
+       if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
+           !capable(CAP_LINUX_IMMUTABLE))
                goto bail_unlock;
 
        handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
@@ -129,8 +135,6 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
 bail_unlock:
        ocfs2_inode_unlock(inode, 1);
 bail:
-       inode_unlock(inode);
-
        brelse(bh);
 
        return status;
@@ -836,7 +840,6 @@ bail:
 long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
-       unsigned int flags;
        int new_clusters;
        int status;
        struct ocfs2_space_resv sr;
@@ -849,24 +852,6 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        void __user *argp = (void __user *)arg;
 
        switch (cmd) {
-       case OCFS2_IOC_GETFLAGS:
-               status = ocfs2_get_inode_attr(inode, &flags);
-               if (status < 0)
-                       return status;
-
-               flags &= OCFS2_FL_VISIBLE;
-               return put_user(flags, (int __user *) arg);
-       case OCFS2_IOC_SETFLAGS:
-               if (get_user(flags, (int __user *) arg))
-                       return -EFAULT;
-
-               status = mnt_want_write_file(filp);
-               if (status)
-                       return status;
-               status = ocfs2_set_inode_attr(inode, flags,
-                       OCFS2_FL_MODIFIABLE);
-               mnt_drop_write_file(filp);
-               return status;
        case OCFS2_IOC_RESVSP:
        case OCFS2_IOC_RESVSP64:
        case OCFS2_IOC_UNRESVSP:
@@ -959,12 +944,6 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        void __user *argp = (void __user *)arg;
 
        switch (cmd) {
-       case OCFS2_IOC32_GETFLAGS:
-               cmd = OCFS2_IOC_GETFLAGS;
-               break;
-       case OCFS2_IOC32_SETFLAGS:
-               cmd = OCFS2_IOC_SETFLAGS;
-               break;
        case OCFS2_IOC_RESVSP:
        case OCFS2_IOC_RESVSP64:
        case OCFS2_IOC_UNRESVSP: