gfs2: convert to fileattr
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>
This commit is contained in:
parent
9b1bb01c8a
commit
88b631cbfb
@ -25,6 +25,7 @@
|
|||||||
#include <linux/dlm_plock.h>
|
#include <linux/dlm_plock.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/backing-dev.h>
|
#include <linux/backing-dev.h>
|
||||||
|
#include <linux/fileattr.h>
|
||||||
|
|
||||||
#include "gfs2.h"
|
#include "gfs2.h"
|
||||||
#include "incore.h"
|
#include "incore.h"
|
||||||
@ -153,14 +154,17 @@ static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
|
|||||||
return fsflags;
|
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_inode *ip = GFS2_I(inode);
|
||||||
struct gfs2_holder gh;
|
struct gfs2_holder gh;
|
||||||
int error;
|
int error;
|
||||||
u32 fsflags;
|
u32 fsflags;
|
||||||
|
|
||||||
|
if (d_is_special(dentry))
|
||||||
|
return -ENOTTY;
|
||||||
|
|
||||||
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
|
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
|
||||||
error = gfs2_glock_nq(&gh);
|
error = gfs2_glock_nq(&gh);
|
||||||
if (error)
|
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);
|
fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
|
||||||
|
|
||||||
if (put_user(fsflags, ptr))
|
fileattr_fill_flags(fa, fsflags);
|
||||||
error = -EFAULT;
|
|
||||||
|
|
||||||
gfs2_glock_dq(&gh);
|
gfs2_glock_dq(&gh);
|
||||||
out_uninit:
|
out_uninit:
|
||||||
@ -213,33 +216,19 @@ void gfs2_set_inode_flags(struct inode *inode)
|
|||||||
* @fsflags: The FS_* inode flags passed in
|
* @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)
|
const u32 fsflags)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(filp);
|
|
||||||
struct gfs2_inode *ip = GFS2_I(inode);
|
struct gfs2_inode *ip = GFS2_I(inode);
|
||||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct gfs2_holder gh;
|
struct gfs2_holder gh;
|
||||||
int error;
|
int error;
|
||||||
u32 new_flags, flags, oldflags;
|
u32 new_flags, flags;
|
||||||
|
|
||||||
error = mnt_want_write_file(filp);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
|
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_drop_write;
|
return error;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
flags = ip->i_diskflags;
|
flags = ip->i_diskflags;
|
||||||
@ -252,9 +241,6 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
|
|||||||
goto out;
|
goto out;
|
||||||
if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY))
|
if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY))
|
||||||
goto out;
|
goto out;
|
||||||
if (((new_flags ^ flags) & GFS2_DIF_IMMUTABLE) &&
|
|
||||||
!capable(CAP_LINUX_IMMUTABLE))
|
|
||||||
goto out;
|
|
||||||
if (!IS_IMMUTABLE(inode)) {
|
if (!IS_IMMUTABLE(inode)) {
|
||||||
error = gfs2_permission(&init_user_ns, inode, MAY_WRITE);
|
error = gfs2_permission(&init_user_ns, inode, MAY_WRITE);
|
||||||
if (error)
|
if (error)
|
||||||
@ -291,20 +277,22 @@ out_trans_end:
|
|||||||
gfs2_trans_end(sdp);
|
gfs2_trans_end(sdp);
|
||||||
out:
|
out:
|
||||||
gfs2_glock_dq_uninit(&gh);
|
gfs2_glock_dq_uninit(&gh);
|
||||||
out_drop_write:
|
|
||||||
mnt_drop_write_file(filp);
|
|
||||||
return error;
|
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);
|
struct inode *inode = d_inode(dentry);
|
||||||
u32 fsflags, gfsflags = 0;
|
u32 fsflags = fa->flags, gfsflags = 0;
|
||||||
u32 mask;
|
u32 mask;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (get_user(fsflags, ptr))
|
if (d_is_special(dentry))
|
||||||
return -EFAULT;
|
return -ENOTTY;
|
||||||
|
|
||||||
|
if (fileattr_has_fsx(fa))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++) {
|
for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++) {
|
||||||
if (fsflags & fsflag_gfs2flag[i].fsflag) {
|
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);
|
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)
|
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)
|
static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
switch(cmd) {
|
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:
|
case FITRIM:
|
||||||
return gfs2_fitrim(filp, (void __user *)arg);
|
return gfs2_fitrim(filp, (void __user *)arg);
|
||||||
case FS_IOC_GETFSLABEL:
|
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)
|
static long gfs2_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
switch(cmd) {
|
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 */
|
/* Keep this list in sync with gfs2_ioctl */
|
||||||
case FITRIM:
|
case FITRIM:
|
||||||
case FS_IOC_GETFSLABEL:
|
case FS_IOC_GETFSLABEL:
|
||||||
|
@ -2157,6 +2157,8 @@ static const struct inode_operations gfs2_file_iops = {
|
|||||||
.get_acl = gfs2_get_acl,
|
.get_acl = gfs2_get_acl,
|
||||||
.set_acl = gfs2_set_acl,
|
.set_acl = gfs2_set_acl,
|
||||||
.update_time = gfs2_update_time,
|
.update_time = gfs2_update_time,
|
||||||
|
.fileattr_get = gfs2_fileattr_get,
|
||||||
|
.fileattr_set = gfs2_fileattr_set,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct inode_operations gfs2_dir_iops = {
|
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,
|
.set_acl = gfs2_set_acl,
|
||||||
.update_time = gfs2_update_time,
|
.update_time = gfs2_update_time,
|
||||||
.atomic_open = gfs2_atomic_open,
|
.atomic_open = gfs2_atomic_open,
|
||||||
|
.fileattr_get = gfs2_fileattr_get,
|
||||||
|
.fileattr_set = gfs2_fileattr_set,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct inode_operations gfs2_symlink_iops = {
|
static const struct inode_operations gfs2_symlink_iops = {
|
||||||
|
@ -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_file_fops_nolock;
|
||||||
extern const struct file_operations gfs2_dir_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);
|
extern void gfs2_set_inode_flags(struct inode *inode);
|
||||||
|
|
||||||
#ifdef CONFIG_GFS2_FS_LOCKING_DLM
|
#ifdef CONFIG_GFS2_FS_LOCKING_DLM
|
||||||
|
Loading…
Reference in New Issue
Block a user