@@ -2098,6 +2098,8 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long 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;
@@ -3314,7 +3314,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
@@ -3324,36 +3325,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 ptlrpc_request *req = NULL;
struct md_op_data *op_data;
- 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;
@@ -3362,11 +3356,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;
rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL,
0, &req);
@@ -3377,16 +3371,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;
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:
@@ -3395,6 +3387,83 @@ int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
return rc;
}
+int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
+ unsigned long arg)
+{
+ struct fsxattr fsxattr;
+
+ 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)
{
@@ -4063,6 +4132,8 @@ static int ll_heat_set(struct inode *inode, enum lu_heat_flag flags)
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: {
@@ -1157,11 +1157,14 @@ 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,
int lum_size);
@@ -2615,7 +2615,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;
@@ -375,6 +375,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)
#define LL_STATFS_LMV 1
#define LL_STATFS_LOV 2
@@ -2311,6 +2312,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 */