Skip to content

Commit

Permalink
gfs2: convert to fileattr
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Miklos Szeredi committed Apr 12, 2021
1 parent 9b1bb01 commit 88b631c
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 43 deletions.
63 changes: 20 additions & 43 deletions fs/gfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -153,23 +154,25 @@ 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)
goto out_uninit;

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:
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -291,20 +277,22 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
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) {
Expand All @@ -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)
Expand All @@ -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:
Expand All @@ -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:
Expand Down
4 changes: 4 additions & 0 deletions fs/gfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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 = {
Expand Down
3 changes: 3 additions & 0 deletions fs/gfs2/inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 88b631c

Please sign in to comment.