@@ -1562,7 +1562,7 @@ struct mdt_rec_setattr {
__u32 sa_attr_flags;
__u32 sa_mode;
__u32 sa_bias; /* some operation flags */
- __u32 sa_padding_3;
+ __u32 sa_projid;
__u32 sa_padding_4;
__u32 sa_padding_5;
};
@@ -1590,7 +1590,8 @@ struct mdt_rec_setattr {
#define MDS_ATTR_FROM_OPEN 0x4000ULL /* = 16384, called from open path,
* ie O_TRUNC
*/
-#define MDS_ATTR_BLOCKS 0x8000ULL /* = 32768 */
+#define MDS_ATTR_BLOCKS 0x8000ULL /* = 32768 */
+#define MDS_ATTR_PROJID 0x10000ULL /* = 65536 */
#define MDS_FMODE_CLOSED 00000000
#define MDS_FMODE_EXEC 00000004
@@ -165,6 +165,9 @@ struct cl_attr {
/* nlink of the directory */
__u64 cat_nlink;
+
+ /* Project identifier for quota purpose. */
+ u32 cat_projid;
};
/**
@@ -178,7 +181,8 @@ enum cl_attr_valid {
CAT_CTIME = 1 << 5,
CAT_BLOCKS = 1 << 6,
CAT_UID = 1 << 7,
- CAT_GID = 1 << 8
+ CAT_GID = BIT(8),
+ CAT_PROJID = BIT(9),
};
/**
@@ -670,6 +670,7 @@ enum op_xvalid {
OP_XVALID_BLOCKS = BIT(1), /* 0x0002 */
OP_XVALID_OWNEROVERRIDE = BIT(2), /* 0x0004 */
OP_XVALID_FLAGS = BIT(3), /* 0x0008 */
+ OP_XVALID_PROJID = BIT(4), /* 0x0010 */
};
struct lu_context;
@@ -770,6 +771,8 @@ struct md_op_data {
/* default stripe offset */
__u32 op_default_stripe_offset;
+
+ u32 op_projid;
};
struct md_callback {
@@ -1667,7 +1667,10 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return rc;
}
-
+ case FS_IOC_FSGETXATTR:
+ return ll_ioctl_fsgetxattr(inode, cmd, arg);
+ case FS_IOC_FSSETXATTR:
+ return ll_ioctl_fssetxattr(inode, cmd, arg);
default:
return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL,
(void __user *)arg);
@@ -2148,6 +2148,59 @@ static int ll_ladvise(struct inode *inode, struct file *file, __u64 flags,
return rc;
}
+int ll_ioctl_fsgetxattr(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;
+
+ fsxattr.fsx_projid = ll_i2info(inode)->lli_projid;
+ if (copy_to_user((struct fsxattr __user *)arg,
+ &fsxattr, sizeof(fsxattr)))
+ return -EFAULT;
+
+ return 0;
+}
+
+int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
+ unsigned long arg)
+{
+ struct ptlrpc_request *req = NULL;
+ struct md_op_data *op_data;
+ struct fsxattr fsxattr;
+ int rc = 0;
+
+ /* only root could change project ID */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ 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);
+
+ if (copy_from_user(&fsxattr,
+ (const struct fsxattr __user *)arg,
+ sizeof(fsxattr))) {
+ rc = -EFAULT;
+ goto out_fsxattr;
+ }
+
+ op_data->op_projid = fsxattr.fsx_projid;
+ op_data->op_xvalid |= OP_XVALID_PROJID;
+ rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL,
+ 0, &req);
+ ptlrpc_req_finished(req);
+
+out_fsxattr:
+ ll_finish_md_op_data(op_data);
+ return rc;
+}
+
static long
ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
@@ -2532,6 +2585,10 @@ static int ll_ladvise(struct inode *inode, struct file *file, __u64 flags,
kfree(ladvise_hdr);
return rc;
}
+ case FS_IOC_FSGETXATTR:
+ return ll_ioctl_fsgetxattr(inode, cmd, arg);
+ case FS_IOC_FSSETXATTR:
+ return ll_ioctl_fssetxattr(inode, cmd, arg);
default: {
int err;
@@ -808,7 +808,10 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
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_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_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry,
__u64 flags, struct lov_user_md *lum,
int lum_size);
@@ -95,6 +95,7 @@ static int vvp_attr_get(const struct lu_env *env, struct cl_object *obj,
attr->cat_blocks = inode->i_blocks;
attr->cat_uid = from_kuid(&init_user_ns, inode->i_uid);
attr->cat_gid = from_kgid(&init_user_ns, inode->i_gid);
+ attr->cat_projid = ll_i2info(inode)->lli_projid;
/* KMS is not known by this layer */
return 0; /* layers below have to fill in the rest */
}
@@ -116,8 +117,10 @@ static int vvp_attr_update(const struct lu_env *env, struct cl_object *obj,
inode->i_ctime.tv_sec = attr->cat_ctime;
if (0 && valid & CAT_SIZE)
i_size_write(inode, attr->cat_size);
+ if (valid & CAT_PROJID)
+ ll_i2info(inode)->lli_projid = attr->cat_projid;
/* not currently necessary */
- if (0 && valid & (CAT_UID | CAT_GID | CAT_SIZE))
+ if (0 && valid & (CAT_UID | CAT_GID | CAT_SIZE | CAT_PROJID))
mark_inode_dirty(inode);
return 0;
}
@@ -305,6 +305,8 @@ static inline u64 attr_pack(unsigned int ia_valid, enum op_xvalid ia_xvalid)
if (ia_xvalid & OP_XVALID_OWNEROVERRIDE)
/* NFSD hack (see bug 5781) */
sa_valid |= MDS_OPEN_OWNEROVERRIDE;
+ if (ia_xvalid & OP_XVALID_PROJID)
+ sa_valid |= MDS_ATTR_PROJID;
return sa_valid;
}
@@ -323,6 +325,7 @@ static void mdc_setattr_pack_rec(struct mdt_rec_setattr *rec,
rec->sa_mode = op_data->op_attr.ia_mode;
rec->sa_uid = from_kuid(&init_user_ns, op_data->op_attr.ia_uid);
rec->sa_gid = from_kgid(&init_user_ns, op_data->op_attr.ia_gid);
+ rec->sa_projid = op_data->op_projid;
rec->sa_size = op_data->op_attr.ia_size;
rec->sa_blocks = op_data->op_attr_blocks;
rec->sa_atime = op_data->op_attr.ia_atime.tv_sec;
@@ -2467,6 +2467,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
qid[USRQUOTA] = attr->cat_uid;
qid[GRPQUOTA] = attr->cat_gid;
+ qid[PRJQUOTA] = attr->cat_projid;
if (rc == 0)
rc = osc_quota_chkdq(cli, qid);
if (rc)
@@ -1474,14 +1474,15 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
return -EPROTO;
}
- /* set/clear over quota flag for a uid/gid */
+ /* set/clear over quota flag for a uid/gid/projid */
if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE &&
body->oa.o_valid & OBD_MD_FLALLQUOTA) {
- unsigned int qid[MAXQUOTAS] = { body->oa.o_uid, body->oa.o_gid };
+ unsigned int qid[MAXQUOTAS] = { body->oa.o_uid, body->oa.o_gid,
+ body->oa.o_projid };
- CDEBUG(D_QUOTA, "setdq for [%u %u] with valid %#llx, flags %x\n",
- body->oa.o_uid, body->oa.o_gid, body->oa.o_valid,
- body->oa.o_flags);
+ CDEBUG(D_QUOTA, "setdq for [%u %u %u] with valid %#llx, flags %x\n",
+ body->oa.o_uid, body->oa.o_gid, body->oa.o_projid,
+ body->oa.o_valid, body->oa.o_flags);
osc_quota_setdq(cli, qid, body->oa.o_valid, body->oa.o_flags);
}
@@ -253,6 +253,9 @@ void lustre_assert_wire_constants(void)
(long long)MDS_ATTR_FROM_OPEN);
LASSERTF(MDS_ATTR_BLOCKS == 0x0000000000008000ULL, "found 0x%.16llxULL\n",
(long long)MDS_ATTR_BLOCKS);
+ LASSERTF(MDS_ATTR_PROJID == 0x0000000000010000ULL, "found 0x%.16llxULL\n",
+ (long long)MDS_ATTR_PROJID);
+
LASSERTF(FLD_QUERY == 900, "found %lld\n",
(long long)FLD_QUERY);
LASSERTF(FLD_FIRST_OPC == 900, "found %lld\n",
@@ -2080,10 +2083,10 @@ void lustre_assert_wire_constants(void)
(long long)(int)offsetof(struct mdt_rec_setattr, sa_bias));
LASSERTF((int)sizeof(((struct mdt_rec_setattr *)0)->sa_bias) == 4, "found %lld\n",
(long long)(int)sizeof(((struct mdt_rec_setattr *)0)->sa_bias));
- LASSERTF((int)offsetof(struct mdt_rec_setattr, sa_padding_3) == 124, "found %lld\n",
- (long long)(int)offsetof(struct mdt_rec_setattr, sa_padding_3));
- LASSERTF((int)sizeof(((struct mdt_rec_setattr *)0)->sa_padding_3) == 4, "found %lld\n",
- (long long)(int)sizeof(((struct mdt_rec_setattr *)0)->sa_padding_3));
+ LASSERTF((int)offsetof(struct mdt_rec_setattr, sa_projid) == 124, "found %lld\n",
+ (long long)(int)offsetof(struct mdt_rec_setattr, sa_projid));
+ LASSERTF((int)sizeof(((struct mdt_rec_setattr *)0)->sa_projid) == 4, "found %lld\n",
+ (long long)(int)sizeof(((struct mdt_rec_setattr *)0)->sa_projid));
LASSERTF((int)offsetof(struct mdt_rec_setattr, sa_padding_4) == 128, "found %lld\n",
(long long)(int)offsetof(struct mdt_rec_setattr, sa_padding_4));
LASSERTF((int)sizeof(((struct mdt_rec_setattr *)0)->sa_padding_4) == 4, "found %lld\n",