From: Wang Shilong Date: Tue, 22 Jun 2021 12:09:29 +0000 (+0800) Subject: LU-11872 quota: add get/set project support for non-dir/file X-Git-Tag: 2.14.53~60 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=b31792b0e72425c8c7850d69837f08c9f3e95a9c LU-11872 quota: add get/set project support for non-dir/file Add ablity to get/set non-dir/file's project ID and state. Signed-off-by: Wang Shilong Change-Id: Ib8eee09254f9751797b5deb7f753c34eb2c0d5a5 Reviewed-on: https://review.whamcloud.com/44006 Tested-by: jenkins Reviewed-by: Andreas Dilger Reviewed-by: Alexander Zarochentsev Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index b56e079..495335b 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -633,6 +633,7 @@ struct ll_ioc_lease_id { #define LL_IOC_PCC_DETACH _IOW('f', 252, struct lu_pcc_detach) #define LL_IOC_PCC_DETACH_BY_FID _IOW('f', 252, struct lu_pcc_detach_fid) #define LL_IOC_PCC_STATE _IOR('f', 252, struct lu_pcc_state) +#define LL_IOC_PROJECT _IOW('f', 253, struct lu_project) #ifndef FS_IOC_FSGETXATTR /* @@ -2669,6 +2670,21 @@ struct lu_pcc_state { char pccs_path[PATH_MAX]; }; +enum lu_project_type { + LU_PROJECT_NONE = 0, + LU_PROJECT_SET, + LU_PROJECT_GET, + LU_PROJECT_MAX +}; + +struct lu_project { + __u32 project_type; /* enum lu_project_type */ + __u32 project_id; + __u32 project_xflags; + __u32 project_reserved; + char project_name[NAME_MAX + 1]; +}; + struct fid_array { __u32 fa_nr; /* make header's size equal lu_fid */ diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 95fd4b2..9e01428 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -2132,6 +2132,8 @@ migrate_free: RETURN(ll_ioctl_fsgetxattr(inode, cmd, arg)); case FS_IOC_FSSETXATTR: RETURN(ll_ioctl_fssetxattr(inode, cmd, arg)); + case LL_IOC_PROJECT: + RETURN(ll_ioctl_project(file, cmd, arg)); case LL_IOC_PCC_DETACH_BY_FID: { struct lu_pcc_detach_fid *detach; struct lu_fid *fid; diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 47fe6d5..6f25a6a 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -3405,7 +3405,8 @@ int ll_ioctl_fsgetxattr(struct inode *inode, unsigned int cmd, RETURN(0); } -int ll_ioctl_check_project(struct inode *inode, struct fsxattr *fa) +int ll_ioctl_check_project(struct inode *inode, __u32 xflags, + __u32 projid) { /* * Project Quota ID state is only allowed to change from within the init @@ -3415,36 +3416,29 @@ int ll_ioctl_check_project(struct inode *inode, struct fsxattr *fa) if (current_user_ns() == &init_user_ns) return 0; - if (ll_i2info(inode)->lli_projid != fa->fsx_projid) + if (ll_i2info(inode)->lli_projid != projid) return -EINVAL; if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags)) { - if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT)) + if (!(xflags & FS_XFLAG_PROJINHERIT)) return -EINVAL; } else { - if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) + if (xflags & FS_XFLAG_PROJINHERIT) return -EINVAL; } return 0; } -int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd, - unsigned long arg) +static int ll_set_project(struct inode *inode, __u32 xflags, __u32 projid) { struct md_op_data *op_data; struct ptlrpc_request *req = NULL; - struct fsxattr fsxattr; struct cl_object *obj; unsigned int inode_flags; int rc = 0; - if (copy_from_user(&fsxattr, - (const struct fsxattr __user *)arg, - sizeof(fsxattr))) - RETURN(-EFAULT); - - rc = ll_ioctl_check_project(inode, &fsxattr); + rc = ll_ioctl_check_project(inode, xflags, projid); if (rc) RETURN(rc); @@ -3453,11 +3447,11 @@ int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd, if (IS_ERR(op_data)) RETURN(PTR_ERR(op_data)); - inode_flags = ll_xflags_to_inode_flags(fsxattr.fsx_xflags); + inode_flags = ll_xflags_to_inode_flags(xflags); op_data->op_attr_flags = ll_inode_to_ext_flags(inode_flags); - if (fsxattr.fsx_xflags & FS_XFLAG_PROJINHERIT) + if (xflags & FS_XFLAG_PROJINHERIT) op_data->op_attr_flags |= LUSTRE_PROJINHERIT_FL; - op_data->op_projid = fsxattr.fsx_projid; + op_data->op_projid = projid; op_data->op_xvalid |= OP_XVALID_PROJID | OP_XVALID_FLAGS; rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL, 0, &req); ptlrpc_req_finished(req); @@ -3466,16 +3460,14 @@ int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd, ll_update_inode_flags(inode, op_data->op_attr_flags); /* Avoid OST RPC if this is only ioctl setting project inherit flag */ - if (fsxattr.fsx_xflags == 0 || - fsxattr.fsx_xflags == FS_XFLAG_PROJINHERIT) + if (xflags == 0 || xflags == FS_XFLAG_PROJINHERIT) GOTO(out_fsxattr, rc); obj = ll_i2info(inode)->lli_clob; if (obj) { struct iattr attr = { 0 }; - rc = cl_setattr_ost(obj, &attr, OP_XVALID_FLAGS, - fsxattr.fsx_xflags); + rc = cl_setattr_ost(obj, &attr, OP_XVALID_FLAGS, xflags); } out_fsxattr: @@ -3483,6 +3475,85 @@ out_fsxattr: RETURN(rc); } +int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd, + unsigned long arg) +{ + struct fsxattr fsxattr; + + ENTRY; + + if (copy_from_user(&fsxattr, + (const struct fsxattr __user *)arg, + sizeof(fsxattr))) + RETURN(-EFAULT); + + RETURN(ll_set_project(inode, fsxattr.fsx_xflags, + fsxattr.fsx_projid)); +} + +int ll_ioctl_project(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct lu_project lu_project; + struct dentry *dentry = file_dentry(file); + struct inode *inode = file_inode(file); + struct dentry *child_dentry = NULL; + int rc = 0, name_len; + + if (copy_from_user(&lu_project, + (const struct lu_project __user *)arg, + sizeof(lu_project))) + RETURN(-EFAULT); + + /* apply child dentry if name is valid */ + name_len = strnlen(lu_project.project_name, NAME_MAX); + if (name_len > 0 && name_len <= NAME_MAX) { + inode_lock(inode); + child_dentry = lookup_one_len(lu_project.project_name, + dentry, name_len); + inode_unlock(inode); + if (IS_ERR(child_dentry)) { + rc = PTR_ERR(child_dentry); + goto out; + } + inode = child_dentry->d_inode; + if (!inode) { + rc = -ENOENT; + goto out; + } + } else if (name_len > NAME_MAX) { + rc = -EINVAL; + goto out; + } + + switch (lu_project.project_type) { + case LU_PROJECT_SET: + rc = ll_set_project(inode, lu_project.project_xflags, + lu_project.project_id); + break; + case LU_PROJECT_GET: + lu_project.project_xflags = + ll_inode_flags_to_xflags(inode->i_flags); + if (test_bit(LLIF_PROJECT_INHERIT, + &ll_i2info(inode)->lli_flags)) + lu_project.project_xflags |= FS_XFLAG_PROJINHERIT; + lu_project.project_id = ll_i2info(inode)->lli_projid; + if (copy_to_user((struct lu_project __user *)arg, + &lu_project, sizeof(lu_project))) { + rc = -EFAULT; + goto out; + } + break; + default: + rc = -EINVAL; + break; + } +out: + if (!IS_ERR_OR_NULL(child_dentry)) + dput(child_dentry); + RETURN(rc); +} + static long ll_file_unlock_lease(struct file *file, struct ll_ioc_lease *ioc, unsigned long arg) { @@ -4134,6 +4205,8 @@ out_ladvise: RETURN(ll_ioctl_fsgetxattr(inode, cmd, arg)); case FS_IOC_FSSETXATTR: RETURN(ll_ioctl_fssetxattr(inode, cmd, arg)); + case LL_IOC_PROJECT: + RETURN(ll_ioctl_project(file, cmd, arg)); case BLKSSZGET: RETURN(put_user(PAGE_SIZE, (int __user *)arg)); case LL_IOC_HEAT_GET: { diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 9c37101..0c60ef2 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -1154,11 +1154,13 @@ int ll_migrate(struct inode *parent, struct file *file, int ll_get_fid_by_name(struct inode *parent, const char *name, int namelen, struct lu_fid *fid, struct inode **inode); int ll_inode_permission(struct inode *inode, int mask); -int ll_ioctl_check_project(struct inode *inode, struct fsxattr *fa); +int ll_ioctl_check_project(struct inode *inode, __u32 xflags, __u32 projid); int ll_ioctl_fsgetxattr(struct inode *inode, unsigned int cmd, unsigned long arg); int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd, unsigned long arg); +int ll_ioctl_project(struct file *file, unsigned int cmd, + unsigned long arg); int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, __u64 flags, struct lov_user_md *lum, diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 142e08f..6147564 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -2704,7 +2704,8 @@ int ll_iocontrol(struct inode *inode, struct file *file, if (flags & LUSTRE_PROJINHERIT_FL) fa.fsx_xflags = FS_XFLAG_PROJINHERIT; - rc = ll_ioctl_check_project(inode, &fa); + rc = ll_ioctl_check_project(inode, fa.fsx_xflags, + fa.fsx_projid); if (rc) RETURN(rc); diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 40e8d89..73b0132 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -3839,18 +3839,15 @@ test_57() { local dir="$DIR/$tdir/dir" mkdir -p $dir mkfifo $dir/pipe - #try to change pipe file should not hang and return failure - wait_update_facet client "$LFS project -sp 1 $dir/pipe 2>&1 | - awk -F ':' '{ print \\\$2 }'" \ - " unable to get xattr for fifo '$dir/pipe'" || return 1 #command can process further if it hit some errors + $LFS project -sp 1 $dir/pipe touch $dir/aaa $dir/bbb mkdir $dir/subdir -p touch $dir/subdir/aaa $dir/subdir/bbb #create one invalid link file ln -s $dir/not_exist_file $dir/ccc local cnt=$(lfs project -r $dir 2>/dev/null | wc -l) - [ $cnt -eq 5 ] || error "expected 5 got $cnt" + [ $cnt -eq 7 ] || error "expected 7 got $cnt" cleanup_quota_test } @@ -4240,16 +4237,22 @@ test_64() { touch $dir1/file ln -s $dir1/file $dir1/file_link + mkfifo $dir1/fifo - $LFS project -sp $TSTPRJID $dir1/file_link >&/dev/null && - error "set symlink file's project should fail" + $LFS project -srp $TSTPRJID $dir1 >&/dev/null || + error "set project should succeed" - $LFS project $TSTPRJID $dir1/file_link >&/dev/null && - error "get symlink file's project should fail" + used=$(getquota -p $TSTPRJID global curinodes) + [ $used -eq 4 ] || error "expected 4 got $used" + $LFS project -rC $dir1 >&/dev/null || + error "clear project should succeed" + + used=$(getquota -p $TSTPRJID global curinodes) + [ $used -eq 0 ] || error "expected 0 got $used" cleanup_quota_test } -run_test 64 "lfs project on symlink files should fail" +run_test 64 "lfs project on non dir/files should succeed" test_65() { local SIZE=10 # MB diff --git a/lustre/utils/lfs_project.c b/lustre/utils/lfs_project.c index 8471c6d..ccf1c1a 100644 --- a/lustre/utils/lfs_project.c +++ b/lustre/utils/lfs_project.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "lfs_project.h" #include @@ -81,57 +82,71 @@ lfs_project_item_alloc(struct list_head *head, const char *pathname) return 0; } -static const char *mode_to_type(mode_t mode) +static int project_get_fsxattr(const char *pathname, struct fsxattr *fsx, + struct stat *st, char *ret_bname) { - switch (mode & S_IFMT) { - case S_IFDIR: return "dir"; - case S_IFREG: return "regular"; - case S_IFLNK: return "symlink"; - case S_IFCHR: return "char device"; - case S_IFBLK: return "block device"; - case S_IFIFO: return "fifo"; - case S_IFSOCK: return "sock"; - } - - return "unknown"; -} - -static int project_get_xattr(const char *pathname, struct fsxattr *fsx, - struct stat *st) -{ - int ret, fd; + int ret = 0, fd = -1; + char dname_path[PATH_MAX + 1] = { 0 }; + char bname_path[PATH_MAX + 1] = { 0 }; + char *dname, *bname; + struct lu_project lu_project = { 0 }; ret = lstat(pathname, st); if (ret) { fprintf(stderr, "%s: failed to stat '%s': %s\n", progname, pathname, strerror(errno)); - return -errno; + ret = -errno; + goto out; } /* currently, only file and dir supported */ - if (!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode)) { - errno = ENOTSUP; - fprintf(stderr, "%s: unable to get xattr for %s '%s': %s\n", - progname, mode_to_type(st->st_mode), pathname, - strerror(errno)); - return -errno; - } + if (!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode)) + goto new_api; fd = open(pathname, O_RDONLY | O_NOCTTY | O_NDELAY); if (fd < 0) { fprintf(stderr, "%s: failed to open '%s': %s\n", progname, pathname, strerror(errno)); - return -errno; + ret = -errno; + goto out; } ret = ioctl(fd, FS_IOC_FSGETXATTR, fsx); if (ret) { fprintf(stderr, "%s: failed to get xattr for '%s': %s\n", progname, pathname, strerror(errno)); - close(fd); - return -errno; + ret = -errno; + } + goto out; +new_api: + strncpy(dname_path, pathname, PATH_MAX); + strncpy(bname_path, pathname, PATH_MAX); + dname = dirname(dname_path); + bname = basename(bname_path); + fd = open(dname, O_RDONLY | O_NOCTTY | O_NDELAY); + if (fd < 0) { + ret = -errno; + goto out; + } + lu_project.project_type = LU_PROJECT_GET; + if (bname) { + strncpy(lu_project.project_name, bname, NAME_MAX); + if (ret_bname) + strncpy(ret_bname, bname, NAME_MAX); + } + ret = ioctl(fd, LL_IOC_PROJECT, &lu_project); + if (ret) { + fprintf(stderr, "%s: failed to get xattr for '%s': %s\n", + progname, pathname, strerror(errno)); + ret = -errno; + } else { + fsx->fsx_xflags = lu_project.project_xflags; + fsx->fsx_projid = lu_project.project_id; } - return fd; +out: + if (ret && fd >= 0) + close(fd); + return ret ? ret : fd; } static int @@ -141,7 +156,7 @@ project_check_one(const char *pathname, struct project_handle_control *phc) int ret; struct stat st; - ret = project_get_xattr(pathname, &fsx, &st); + ret = project_get_fsxattr(pathname, &fsx, &st, NULL); if (ret < 0) return ret; @@ -181,7 +196,7 @@ project_list_one(const char *pathname, struct project_handle_control *phc) struct stat st; int ret; - ret = project_get_xattr(pathname, &fsx, &st); + ret = project_get_fsxattr(pathname, &fsx, &st, NULL); if (ret < 0) return ret; @@ -199,8 +214,10 @@ project_set_one(const char *pathname, struct project_handle_control *phc) struct fsxattr fsx; struct stat st; int fd, ret = 0; + char bname[NAME_MAX + 1] = { 0 }; + struct lu_project lp = { 0 }; - fd = project_get_xattr(pathname, &fsx, &st); + fd = project_get_fsxattr(pathname, &fsx, &st, bname); if (fd < 0) return fd; @@ -213,11 +230,20 @@ project_set_one(const char *pathname, struct project_handle_control *phc) if (phc->set_projid) fsx.fsx_projid = phc->projid; - ret = ioctl(fd, FS_IOC_FSSETXATTR, &fsx); + if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) { + ret = ioctl(fd, FS_IOC_FSSETXATTR, &fsx); + } else { + lp.project_xflags = fsx.fsx_xflags; + lp.project_id = fsx.fsx_projid; + lp.project_type = LU_PROJECT_SET; + strncpy(lp.project_name, bname, NAME_MAX); + lp.project_name[NAME_MAX] = '\0'; + ret = ioctl(fd, LL_IOC_PROJECT, &lp); + } +out: if (ret) fprintf(stderr, "%s: failed to set xattr for '%s': %s\n", progname, pathname, strerror(errno)); -out: close(fd); return ret; } @@ -228,8 +254,10 @@ project_clear_one(const char *pathname, struct project_handle_control *phc) struct fsxattr fsx; struct stat st; int ret = 0, fd; + char bname[NAME_MAX + 1] = { 0 }; + struct lu_project lp = { 0 }; - fd = project_get_xattr(pathname, &fsx, &st); + fd = project_get_fsxattr(pathname, &fsx, &st, bname); if (fd < 0) return fd; @@ -241,7 +269,16 @@ project_clear_one(const char *pathname, struct project_handle_control *phc) if (!phc->keep_projid) fsx.fsx_projid = 0; - ret = ioctl(fd, FS_IOC_FSSETXATTR, &fsx); + if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) { + ret = ioctl(fd, FS_IOC_FSSETXATTR, &fsx); + } else { + lp.project_xflags = fsx.fsx_xflags; + lp.project_id = fsx.fsx_projid; + lp.project_type = LU_PROJECT_SET; + strncpy(lp.project_name, bname, NAME_MAX); + lp.project_name[NAME_MAX] = '\0'; + ret = ioctl(fd, LL_IOC_PROJECT, &lp); + } if (ret) fprintf(stderr, "%s: failed to set xattr for '%s': %s\n", progname, pathname, strerror(errno));