Commit 88b631cb authored by Miklos Szeredi's avatar Miklos Szeredi
Browse files

gfs2: convert to fileattr



Use the fileattr API to let the VFS handle locking, permission checking and
conversion.

Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
Cc: Andreas Gruenbacher <agruenba@redhat.com>
parent 9b1bb01c
Loading
Loading
Loading
Loading
+20 −43
Original line number Diff line number Diff line
@@ -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 @@ 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) {
@@ -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:
+4 −0
Original line number Diff line number Diff line
@@ -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 = {
+3 −0
Original line number Diff line number Diff line
@@ -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