Whamcloud - gitweb
LU-11872 quota: add get/set project support for non-dir/file 06/44006/7
authorWang Shilong <wshilong@ddn.com>
Tue, 22 Jun 2021 12:09:29 +0000 (20:09 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 8 Jul 2021 02:06:39 +0000 (02:06 +0000)
Add ablity to get/set non-dir/file's project ID and state.

Signed-off-by: Wang Shilong <wshilong@ddn.com>
Change-Id: Ib8eee09254f9751797b5deb7f753c34eb2c0d5a5
Reviewed-on: https://review.whamcloud.com/44006
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Alexander Zarochentsev <alexander.zarochentsev@hpe.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/uapi/linux/lustre/lustre_user.h
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/tests/sanity-quota.sh
lustre/utils/lfs_project.c

index b56e079..495335b 100644 (file)
@@ -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_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
 /*
 
 #ifndef        FS_IOC_FSGETXATTR
 /*
@@ -2669,6 +2670,21 @@ struct lu_pcc_state {
        char    pccs_path[PATH_MAX];
 };
 
        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 */
 struct fid_array {
        __u32 fa_nr;
        /* make header's size equal lu_fid */
index 95fd4b2..9e01428 100644 (file)
@@ -2132,6 +2132,8 @@ migrate_free:
                RETURN(ll_ioctl_fsgetxattr(inode, cmd, arg));
        case FS_IOC_FSSETXATTR:
                RETURN(ll_ioctl_fssetxattr(inode, cmd, arg));
                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;
        case LL_IOC_PCC_DETACH_BY_FID: {
                struct lu_pcc_detach_fid *detach;
                struct lu_fid *fid;
index 47fe6d5..6f25a6a 100644 (file)
@@ -3405,7 +3405,8 @@ int ll_ioctl_fsgetxattr(struct inode *inode, unsigned int cmd,
        RETURN(0);
 }
 
        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
 {
        /*
         * 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 (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)) {
                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 {
                        return -EINVAL;
        } else {
-               if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT)
+               if (xflags & FS_XFLAG_PROJINHERIT)
                        return -EINVAL;
        }
 
        return 0;
 }
 
                        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 md_op_data *op_data;
        struct ptlrpc_request *req = NULL;
-       struct fsxattr fsxattr;
        struct cl_object *obj;
        unsigned int inode_flags;
        int rc = 0;
 
        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);
 
        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));
 
        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);
        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_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);
        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 */
        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 };
 
                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:
        }
 
 out_fsxattr:
@@ -3483,6 +3475,85 @@ out_fsxattr:
        RETURN(rc);
 }
 
        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)
 {
 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));
                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: {
        case BLKSSZGET:
                RETURN(put_user(PAGE_SIZE, (int __user *)arg));
        case LL_IOC_HEAT_GET: {
index 9c37101..0c60ef2 100644 (file)
@@ -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_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_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,
 
 int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry,
                             __u64 flags, struct lov_user_md *lum,
index 142e08f..6147564 100644 (file)
@@ -2704,7 +2704,8 @@ int ll_iocontrol(struct inode *inode, struct file *file,
                if (flags & LUSTRE_PROJINHERIT_FL)
                        fa.fsx_xflags = FS_XFLAG_PROJINHERIT;
 
                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);
 
                if (rc)
                        RETURN(rc);
 
index 40e8d89..73b0132 100755 (executable)
@@ -3839,18 +3839,15 @@ test_57() {
        local dir="$DIR/$tdir/dir"
        mkdir -p $dir
        mkfifo $dir/pipe
        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
        #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)
        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
 }
 
        cleanup_quota_test
 }
@@ -4240,16 +4237,22 @@ test_64() {
 
        touch $dir1/file
        ln -s $dir1/file $dir1/file_link
 
        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
 }
 
        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
 
 test_65() {
        local SIZE=10 # MB
index 8471c6d..ccf1c1a 100644 (file)
@@ -47,6 +47,7 @@
 #include <libcfs/util/list.h>
 #include <libcfs/util/ioctl.h>
 #include <sys/ioctl.h>
 #include <libcfs/util/list.h>
 #include <libcfs/util/ioctl.h>
 #include <sys/ioctl.h>
+#include <libgen.h>
 
 #include "lfs_project.h"
 #include <lustre/lustreapi.h>
 
 #include "lfs_project.h"
 #include <lustre/lustreapi.h>
@@ -81,57 +82,71 @@ lfs_project_item_alloc(struct list_head *head, const char *pathname)
        return 0;
 }
 
        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));
 
        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 */
        }
 
        /* 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));
 
        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));
        }
 
        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
 }
 
 static int
@@ -141,7 +156,7 @@ project_check_one(const char *pathname, struct project_handle_control *phc)
        int ret;
        struct stat st;
 
        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;
 
        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;
 
        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;
 
        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;
        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;
 
        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;
 
        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));
        if (ret)
                fprintf(stderr, "%s: failed to set xattr for '%s': %s\n",
                        progname, pathname, strerror(errno));
-out:
        close(fd);
        return ret;
 }
        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;
        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;
 
        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;
 
        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));
        if (ret)
                fprintf(stderr, "%s: failed to set xattr for '%s': %s\n",
                        progname, pathname, strerror(errno));