vfs: create a generic checking and prep function for FS_IOC_SETFLAGS
Create a generic function to check incoming FS_IOC_SETFLAGS flag values and later prepare the inode for updates so that we can standardize the implementations that follow ext4's flag values. Note that the efivarfs implementation no longer fails a no-op SETFLAGS without CAP_LINUX_IMMUTABLE since that's the behavior in ext*. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Christoph Hellwig <hch@lst.de> Acked-by: David Sterba <dsterba@suse.com> Reviewed-by: Bob Peterson <rpeterso@redhat.com>
This commit is contained in:
@@ -357,11 +357,28 @@ static ssize_t orangefs_file_write_iter(struct kiocb *iocb,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int orangefs_getflags(struct inode *inode, unsigned long *uval)
|
||||
{
|
||||
__u64 val = 0;
|
||||
int ret;
|
||||
|
||||
ret = orangefs_inode_getxattr(inode,
|
||||
"user.pvfs2.meta_hint",
|
||||
&val, sizeof(val));
|
||||
if (ret < 0 && ret != -ENODATA)
|
||||
return ret;
|
||||
else if (ret == -ENODATA)
|
||||
val = 0;
|
||||
*uval = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a miscellaneous operation on a file.
|
||||
*/
|
||||
static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
int ret = -ENOTTY;
|
||||
__u64 val = 0;
|
||||
unsigned long uval;
|
||||
@@ -375,20 +392,16 @@ static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
||||
* and append flags
|
||||
*/
|
||||
if (cmd == FS_IOC_GETFLAGS) {
|
||||
val = 0;
|
||||
ret = orangefs_inode_getxattr(file_inode(file),
|
||||
"user.pvfs2.meta_hint",
|
||||
&val, sizeof(val));
|
||||
if (ret < 0 && ret != -ENODATA)
|
||||
ret = orangefs_getflags(inode, &uval);
|
||||
if (ret)
|
||||
return ret;
|
||||
else if (ret == -ENODATA)
|
||||
val = 0;
|
||||
uval = val;
|
||||
gossip_debug(GOSSIP_FILE_DEBUG,
|
||||
"orangefs_ioctl: FS_IOC_GETFLAGS: %llu\n",
|
||||
(unsigned long long)uval);
|
||||
return put_user(uval, (int __user *)arg);
|
||||
} else if (cmd == FS_IOC_SETFLAGS) {
|
||||
unsigned long old_uval;
|
||||
|
||||
ret = 0;
|
||||
if (get_user(uval, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
@@ -404,11 +417,17 @@ static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
||||
gossip_err("orangefs_ioctl: the FS_IOC_SETFLAGS only supports setting one of FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NOATIME_FL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = orangefs_getflags(inode, &old_uval);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = vfs_ioc_setflags_prepare(inode, old_uval, uval);
|
||||
if (ret)
|
||||
return ret;
|
||||
val = uval;
|
||||
gossip_debug(GOSSIP_FILE_DEBUG,
|
||||
"orangefs_ioctl: FS_IOC_SETFLAGS: %llu\n",
|
||||
(unsigned long long)val);
|
||||
ret = orangefs_inode_setxattr(file_inode(file),
|
||||
ret = orangefs_inode_setxattr(inode,
|
||||
"user.pvfs2.meta_hint",
|
||||
&val, sizeof(val), 0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user