gfs2: convert to fileattr
authorMiklos Szeredi <mszeredi@redhat.com>
Wed, 7 Apr 2021 12:36:43 +0000 (14:36 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Mon, 12 Apr 2021 13:04:29 +0000 (15:04 +0200)
Use the fileattr API to let the VFS handle locking, permission checking and
conversion.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Cc: Andreas Gruenbacher <agruenba@redhat.com>
fs/gfs2/file.c
fs/gfs2/inode.c
fs/gfs2/inode.h

index 2d500f90cdacf3ae539ad7ab1905be79def0491d..b46714d4810793a4b0a33b4a87b909fa9d9241cf 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/dlm_plock.h>
 #include <linux/delay.h>
 #include <linux/backing-dev.h>
+#include <linux/fileattr.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -153,14 +154,17 @@ static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
        return fsflags;
 }
 
-static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
+int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa)
 {
-       struct inode *inode = file_inode(filp);
+       struct inode *inode = d_inode(dentry);
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int error;
        u32 fsflags;
 
+       if (d_is_special(dentry))
+               return -ENOTTY;
+
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
        error = gfs2_glock_nq(&gh);
        if (error)
@@ -168,8 +172,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
 
        fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
 
-       if (put_user(fsflags, ptr))
-               error = -EFAULT;
+       fileattr_fill_flags(fa, fsflags);
 
        gfs2_glock_dq(&gh);
 out_uninit:
@@ -213,33 +216,19 @@ void gfs2_set_inode_flags(struct inode *inode)
  * @fsflags: The FS_* inode flags passed in
  *
  */
-static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
+static int do_gfs2_set_flags(struct inode *inode, u32 reqflags, u32 mask,
                             const u32 fsflags)
 {
-       struct inode *inode = file_inode(filp);
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct buffer_head *bh;
        struct gfs2_holder gh;
        int error;
-       u32 new_flags, flags, oldflags;
-
-       error = mnt_want_write_file(filp);
-       if (error)
-               return error;
+       u32 new_flags, flags;
 
        error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        if (error)
-               goto out_drop_write;
-
-       oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
-       error = vfs_ioc_setflags_prepare(inode, oldflags, fsflags);
-       if (error)
-               goto out;
-
-       error = -EACCES;
-       if (!inode_owner_or_capable(&init_user_ns, inode))
-               goto out;
+               return error;
 
        error = 0;
        flags = ip->i_diskflags;
@@ -252,9 +241,6 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
                goto out;
        if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY))
                goto out;
-       if (((new_flags ^ flags) & GFS2_DIF_IMMUTABLE) &&
-           !capable(CAP_LINUX_IMMUTABLE))
-               goto out;
        if (!IS_IMMUTABLE(inode)) {
                error = gfs2_permission(&init_user_ns, inode, MAY_WRITE);
                if (error)
@@ -291,20 +277,22 @@ out_trans_end:
        gfs2_trans_end(sdp);
 out:
        gfs2_glock_dq_uninit(&gh);
-out_drop_write:
-       mnt_drop_write_file(filp);
        return error;
 }
 
-static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
+int gfs2_fileattr_set(struct user_namespace *mnt_userns,
+                     struct dentry *dentry, struct fileattr *fa)
 {
-       struct inode *inode = file_inode(filp);
-       u32 fsflags, gfsflags = 0;
+       struct inode *inode = d_inode(dentry);
+       u32 fsflags = fa->flags, gfsflags = 0;
        u32 mask;
        int i;
 
-       if (get_user(fsflags, ptr))
-               return -EFAULT;
+       if (d_is_special(dentry))
+               return -ENOTTY;
+
+       if (fileattr_has_fsx(fa))
+               return -EOPNOTSUPP;
 
        for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++) {
                if (fsflags & fsflag_gfs2flag[i].fsflag) {
@@ -325,7 +313,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
                mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
        }
 
-       return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
+       return do_gfs2_set_flags(inode, gfsflags, mask, fsflags);
 }
 
 static int gfs2_getlabel(struct file *filp, char __user *label)
@@ -342,10 +330,6 @@ static int gfs2_getlabel(struct file *filp, char __user *label)
 static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        switch(cmd) {
-       case FS_IOC_GETFLAGS:
-               return gfs2_get_flags(filp, (u32 __user *)arg);
-       case FS_IOC_SETFLAGS:
-               return gfs2_set_flags(filp, (u32 __user *)arg);
        case FITRIM:
                return gfs2_fitrim(filp, (void __user *)arg);
        case FS_IOC_GETFSLABEL:
@@ -359,13 +343,6 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 static long gfs2_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        switch(cmd) {
-       /* These are just misnamed, they actually get/put from/to user an int */
-       case FS_IOC32_GETFLAGS:
-               cmd = FS_IOC_GETFLAGS;
-               break;
-       case FS_IOC32_SETFLAGS:
-               cmd = FS_IOC_SETFLAGS;
-               break;
        /* Keep this list in sync with gfs2_ioctl */
        case FITRIM:
        case FS_IOC_GETFSLABEL:
index c9775d5c659497a0209dbc621faf2ce5bc901201..6a63607ac52678c81f6295c75d73242a1ea6ba2b 100644 (file)
@@ -2157,6 +2157,8 @@ static const struct inode_operations gfs2_file_iops = {
        .get_acl = gfs2_get_acl,
        .set_acl = gfs2_set_acl,
        .update_time = gfs2_update_time,
+       .fileattr_get = gfs2_fileattr_get,
+       .fileattr_set = gfs2_fileattr_set,
 };
 
 static const struct inode_operations gfs2_dir_iops = {
@@ -2178,6 +2180,8 @@ static const struct inode_operations gfs2_dir_iops = {
        .set_acl = gfs2_set_acl,
        .update_time = gfs2_update_time,
        .atomic_open = gfs2_atomic_open,
+       .fileattr_get = gfs2_fileattr_get,
+       .fileattr_set = gfs2_fileattr_set,
 };
 
 static const struct inode_operations gfs2_symlink_iops = {
index c447bd5b3017ea7334a6cd9a6f970fce2434bb90..9e898660eae06bca8c4f00d80ccbb83e3ece7271 100644 (file)
@@ -111,6 +111,9 @@ extern loff_t gfs2_seek_hole(struct file *file, loff_t offset);
 extern const struct file_operations gfs2_file_fops_nolock;
 extern const struct file_operations gfs2_dir_fops_nolock;
 
+extern int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa);
+extern int gfs2_fileattr_set(struct user_namespace *mnt_userns,
+                            struct dentry *dentry, struct fileattr *fa);
 extern void gfs2_set_inode_flags(struct inode *inode);
  
 #ifdef CONFIG_GFS2_FS_LOCKING_DLM