From 1addb410788f0415a85bef72afff8533ac9da012 Mon Sep 17 00:00:00 2001 From: Mr NeilBrown Date: Wed, 7 Dec 2022 18:55:57 +1100 Subject: [PATCH] LU-15969 llite: add support for ->fileattr_get/set From Linux 5.13, FS_IOC_SETFLAGS and GETFLAGS aren't passed down to the filesystem, we need ->fileattr_get/set inode_operations instead. Signed-off-by: Mr NeilBrown Change-Id: I7c13640012f3e3b6176bcdcc78a07f30e0667cbb Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50649 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Shaun Tancheff Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- lustre/autoconf/lustre-core.m4 | 28 ++++++ lustre/llite/file.c | 12 ++- lustre/llite/llite_internal.h | 8 ++ lustre/llite/llite_lib.c | 200 ++++++++++++++++++++++++++--------------- lustre/llite/namei.c | 4 + 5 files changed, 179 insertions(+), 73 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 2c766c1..30cd1f8 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -3147,6 +3147,31 @@ AC_DEFUN([LC_HAVE_USER_NAMESPACE_ARG], [ ]) # LC_HAVE_USER_NAMESPACE_ARG # +# LC_HAVE_FILEATTR_GET +# +# kernel 5.13 4c5b479975212065ef39786e115fde42847e95a9 +# vfs: add fileattr ops +# Add inode operations to replace FS_IOC_[SG]ETFLAGS ioctl +# The type signature of ->fileattr_set is not stable for the +# first few iterations, so don't commit to a particular signature +# here. Hopefully we will only want to support the final version. +# +AC_DEFUN([LC_HAVE_FILEATTR_GET], [ +tmp_flags="$EXTRA_KCFLAGS" +EXTRA_KCFLAGS="-Werror" +LB_CHECK_COMPILE([if 'inode_operations' has fileattr_get (and fileattr_set)], +fileattr_set, [ + #include +],[ + ((struct inode_operations *)1)->fileattr_get(NULL, NULL); +],[ + AC_DEFINE(HAVE_FILEATTR_GET, 1, + ['inode_operations' has fileattr_get and fileattr_set]) +]) +EXTRA_KCFLAGS="$tmp_flags" +]) # LC_HAVE_FILEATTR_GET + +# # LC_HAVE_GET_ACL_RCU_ARG # # kernel 5.15 commit 0cad6246621b5887d5b33fea84219d2a71f2f99a @@ -4123,6 +4148,9 @@ AC_DEFUN([LC_PROG_LINUX_RESULTS], [ # 5.12 LC_HAVE_USER_NAMESPACE_ARG + # 5.13 + LC_HAVE_FILEATTR_GET + # 5.15 LC_HAVE_GET_ACL_RCU_ARG diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 6c4073e..e56aa36 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -3770,6 +3770,7 @@ static int ll_lock_noexpand(struct file *file, int flags) return 0; } +#ifndef HAVE_FILEATTR_GET int ll_ioctl_fsgetxattr(struct inode *inode, unsigned int cmd, void __user *uarg) { @@ -3787,6 +3788,7 @@ int ll_ioctl_fsgetxattr(struct inode *inode, unsigned int cmd, RETURN(0); } +#endif int ll_ioctl_check_project(struct inode *inode, __u32 xflags, __u32 projid) @@ -3822,7 +3824,7 @@ int ll_ioctl_check_project(struct inode *inode, __u32 xflags, return 0; } -static int ll_set_project(struct inode *inode, __u32 xflags, __u32 projid) +int ll_set_project(struct inode *inode, __u32 xflags, __u32 projid) { struct ptlrpc_request *req = NULL; struct md_op_data *op_data; @@ -3872,6 +3874,7 @@ out_fsxattr: RETURN(rc); } +#ifndef HAVE_FILEATTR_GET int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd, void __user *uarg) { @@ -3885,6 +3888,7 @@ int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd, RETURN(ll_set_project(inode, fsxattr.fsx_xflags, fsxattr.fsx_projid)); } +#endif int ll_ioctl_project(struct file *file, unsigned int cmd, void __user *uarg) { @@ -4304,8 +4308,10 @@ out: case LL_IOC_LOV_GETSTRIPE: case LL_IOC_LOV_GETSTRIPE_NEW: RETURN(ll_file_getstripe(inode, uarg, 0)); +#ifndef HAVE_FILEATTR_GET case LL_IOC_GROUP_LOCK: RETURN(ll_get_grouplock(inode, file, arg)); +#endif case LL_IOC_GROUP_UNLOCK: RETURN(ll_put_grouplock(inode, file, arg)); case LL_IOC_DATA_VERSION: { @@ -5953,6 +5959,10 @@ const struct inode_operations ll_file_inode_operations = { #ifdef HAVE_IOP_SET_ACL .set_acl = ll_set_acl, #endif +#ifdef HAVE_FILEATTR_GET + .fileattr_get = ll_fileattr_get, + .fileattr_set = ll_fileattr_set, +#endif }; const struct file_operations *ll_select_file_operations(struct ll_sb_info *sbi) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index c493fb5..792442f 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -1238,10 +1238,13 @@ int ll_get_fid_by_name(struct inode *parent, const char *name, int ll_inode_permission(struct user_namespace *mnt_userns, struct inode *inode, int mask); int ll_ioctl_check_project(struct inode *inode, __u32 xflags, __u32 projid); +int ll_set_project(struct inode *inode, __u32 xflags, __u32 projid); +#ifndef HAVE_FILEATTR_GET int ll_ioctl_fsgetxattr(struct inode *inode, unsigned int cmd, void __user *uarg); int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd, void __user *uarg); +#endif int ll_ioctl_project(struct file *file, unsigned int cmd, void __user *uarg); int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, __u64 flags, struct lov_user_md *lum, @@ -1317,6 +1320,11 @@ void ll_update_dir_depth(struct inode *dir, struct inode *inode); int ll_read_inode2(struct inode *inode, void *opaque); void ll_truncate_inode_pages_final(struct inode *inode, struct cl_io *io); void ll_delete_inode(struct inode *inode); +#ifdef HAVE_FILEATTR_GET +int ll_fileattr_get(struct dentry *dentry, struct fileattr *fa); +int ll_fileattr_set(struct user_namespace *mnt_userns, + struct dentry *dentry, struct fileattr *fa); +#endif int ll_iocontrol(struct inode *inode, struct file *file, unsigned int cmd, void __user *uarg); int ll_flush_ctx(struct inode *inode); diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index f525b96..dd522a4 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -50,6 +50,9 @@ #include #include #include +#ifdef HAVE_FILEATTR_GET +#include +#endif #ifndef HAVE_CPUS_READ_LOCK #include @@ -2987,16 +2990,127 @@ void ll_delete_inode(struct inode *inode) ll_clear_inode(inode); clear_inode(inode); - EXIT; + EXIT; } +static int fileattr_get(struct inode *inode, int *flags, + u32 *xflags, + u32 *projid) +{ + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ptlrpc_request *req = NULL; + struct md_op_data *op_data; + struct mdt_body *body; + int rc; + + ENTRY; + op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, + 0, 0, LUSTRE_OPC_ANY, + NULL); + if (IS_ERR(op_data)) + RETURN(PTR_ERR(op_data)); + + op_data->op_valid = OBD_MD_FLFLAGS; + rc = md_getattr(sbi->ll_md_exp, op_data, &req); + ll_finish_md_op_data(op_data); + if (rc) { + CERROR("%s: failure inode "DFID": rc = %d\n", + sbi->ll_md_exp->exp_obd->obd_name, + PFID(ll_inode2fid(inode)), rc); + RETURN(-abs(rc)); + } + + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + + *flags = body->mbo_flags; + /* if Lustre specific LUSTRE_ENCRYPT_FL flag is set, also set + * ext4 equivalent to please lsattr and other e2fsprogs tools + */ + if (*flags & LUSTRE_ENCRYPT_FL) + *flags |= STATX_ATTR_ENCRYPTED; + + ptlrpc_req_finished(req); + + *xflags = ll_inode_flags_to_xflags(inode->i_flags); + if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags)) + *xflags |= FS_XFLAG_PROJINHERIT; + *projid = ll_i2info(inode)->lli_projid; + + RETURN(0); +} + +static int fileattr_set(struct inode *inode, int flags) +{ + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ptlrpc_request *req = NULL; + struct md_op_data *op_data; + struct cl_object *obj; + struct fsxattr fa = { 0 }; + struct iattr *attr; + int rc; + + ENTRY; + fa.fsx_projid = ll_i2info(inode)->lli_projid; + if (flags & LUSTRE_PROJINHERIT_FL) + fa.fsx_xflags = FS_XFLAG_PROJINHERIT; + + rc = ll_ioctl_check_project(inode, fa.fsx_xflags, + fa.fsx_projid); + if (rc) + RETURN(rc); + + op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, + LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + RETURN(PTR_ERR(op_data)); + + op_data->op_attr_flags = flags; + op_data->op_xvalid |= OP_XVALID_FLAGS; + rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, &req); + ll_finish_md_op_data(op_data); + ptlrpc_req_finished(req); + if (rc) + RETURN(rc); + + ll_update_inode_flags(inode, flags); + + obj = ll_i2info(inode)->lli_clob; + if (obj == NULL) + RETURN(0); + + OBD_ALLOC_PTR(attr); + if (attr == NULL) + RETURN(-ENOMEM); + + rc = cl_setattr_ost(obj, attr, OP_XVALID_FLAGS, flags); + + OBD_FREE_PTR(attr); + RETURN(rc); +} + +#ifdef HAVE_FILEATTR_GET +int ll_fileattr_get(struct dentry *dentry, struct fileattr *fa) +{ + return fileattr_get(d_inode(dentry), &fa->flags, + &fa->fsx_xflags, &fa->fsx_projid); +} + +int ll_fileattr_set(struct user_namespace *mnt_userns, + struct dentry *dentry, struct fileattr *fa) +{ + if (fa->fsx_valid) + return ll_set_project(d_inode(dentry), fa->fsx_xflags, + fa->fsx_projid); + else + return fileattr_set(d_inode(dentry), fa->flags); +} +#endif /* HAVE_FILEATTR_GET */ + /* ioctl commands shared between files and directories */ int ll_iocontrol(struct inode *inode, struct file *file, unsigned int cmd, void __user *uarg) { - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ptlrpc_request *req = NULL; - int rc, flags = 0; + int rc; ENTRY; switch (cmd) { @@ -3005,91 +3119,33 @@ int ll_iocontrol(struct inode *inode, struct file *file, case LL_IOC_GETVERSION: case FS_IOC_GETVERSION: RETURN(put_user(inode->i_generation, (int __user *)uarg)); + +#ifndef HAVE_FILEATTR_GET case FS_IOC_GETFLAGS: { - struct mdt_body *body; - struct md_op_data *op_data; + u32 xflags = 0, projid = 0; + int flags = 0; if (!ll_access_ok(uarg, sizeof(int))) RETURN(-EFAULT); - - op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - RETURN(PTR_ERR(op_data)); - - op_data->op_valid = OBD_MD_FLFLAGS; - rc = md_getattr(sbi->ll_md_exp, op_data, &req); - ll_finish_md_op_data(op_data); - if (rc) { - CERROR("%s: failure inode "DFID": rc = %d\n", - sbi->ll_md_exp->exp_obd->obd_name, - PFID(ll_inode2fid(inode)), rc); - RETURN(-abs(rc)); - } - - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - - flags = body->mbo_flags; - /* if Lustre specific LUSTRE_ENCRYPT_FL flag is set, also set - * ext4 equivalent to please lsattr and other e2fsprogs tools - */ - if (flags & LUSTRE_ENCRYPT_FL) - flags |= STATX_ATTR_ENCRYPTED; - - ptlrpc_req_finished(req); + rc = fileattr_get(file->f_inode, &flags, &xflags, &projid); + if (rc) + RETURN(rc); RETURN(put_user(flags, (int __user *)uarg)); } case FS_IOC_SETFLAGS: { - struct iattr *attr; - struct md_op_data *op_data; - struct cl_object *obj; - struct fsxattr fa = { 0 }; + int flags = 0; if (get_user(flags, (int __user *)uarg)) RETURN(-EFAULT); - fa.fsx_projid = ll_i2info(inode)->lli_projid; - if (flags & LUSTRE_PROJINHERIT_FL) - fa.fsx_xflags = FS_XFLAG_PROJINHERIT; - - rc = ll_ioctl_check_project(inode, fa.fsx_xflags, - fa.fsx_projid); - if (rc) - RETURN(rc); - - op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - RETURN(PTR_ERR(op_data)); - - op_data->op_attr_flags = flags; - op_data->op_xvalid |= OP_XVALID_FLAGS; - rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, &req); - ll_finish_md_op_data(op_data); - ptlrpc_req_finished(req); - if (rc) - RETURN(rc); - - ll_update_inode_flags(inode, flags); - - obj = ll_i2info(inode)->lli_clob; - if (obj == NULL) - RETURN(0); - - OBD_ALLOC_PTR(attr); - if (attr == NULL) - RETURN(-ENOMEM); - - rc = cl_setattr_ost(obj, attr, OP_XVALID_FLAGS, flags); - - OBD_FREE_PTR(attr); - RETURN(rc); + RETURN(fileattr_set(file->f_inode, flags)); } case FS_IOC_FSGETXATTR: RETURN(ll_ioctl_fsgetxattr(inode, cmd, uarg)); case FS_IOC_FSSETXATTR: RETURN(ll_ioctl_fssetxattr(inode, cmd, uarg)); +#endif /* HAVE_FILEATTR_GET */ case LL_IOC_PROJECT: RETURN(ll_ioctl_project(file, cmd, uarg)); case IOC_OBD_STATFS: diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index eb06ecd..cd59429 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -2187,6 +2187,10 @@ const struct inode_operations ll_dir_inode_operations = { #ifdef HAVE_IOP_SET_ACL .set_acl = ll_set_acl, #endif +#ifdef HAVE_FILEATTR_GET + .fileattr_get = ll_fileattr_get, + .fileattr_set = ll_fileattr_set, +#endif }; const struct inode_operations ll_special_inode_operations = { -- 1.8.3.1