fallocate() was not accounting for projectid quota usage.
This was happening due to two reasons. 1) the projectid
was not properly passed to md_op_data in ll_set_project()
and 2) the OBD_MD_FLPROJID flag was not set receive the
projctid.
This patch addresses the above reasons.
Test-case: sanity-quota/78a added
Fixes:
48457868a02a ("LU-3606 fallocate: Implement fallocate preallocate operation")
Signed-off-by: Arshad Hussain <arshad.hussain@aeoncomputing.com>
Change-Id: I3ed44e7ef7ca8fe49a08133449c33b62b1eff500
Reviewed-on: https://review.whamcloud.com/46676
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Hongchao Zhang <hongchao@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
loff_t sa_falloc_end;
uid_t sa_falloc_uid;
gid_t sa_falloc_gid;
+ __u32 sa_falloc_projid;
} ci_setattr;
struct cl_data_version_io {
u64 dv_data_version;
GOTO(out, rc);
}
- fmkey.lfik_oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
+ fmkey.lfik_oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLPROJID;
obdo_from_inode(&fmkey.lfik_oa, inode, OBD_MD_FLSIZE);
obdo_set_parent_fid(&fmkey.lfik_oa, &ll_i2info(inode)->lli_fid);
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 cl_object *obj;
unsigned int inode_flags;
int rc = 0;
op_data->op_attr_flags = ll_inode_to_ext_flags(inode_flags);
if (xflags & FS_XFLAG_PROJINHERIT)
op_data->op_attr_flags |= LUSTRE_PROJINHERIT_FL;
+
+ /* pass projid to md_op_data */
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);
int cl_falloc(struct file *file, struct inode *inode, int mode, loff_t offset,
loff_t len)
{
+ loff_t size = i_size_read(inode);
struct lu_env *env;
struct cl_io *io;
__u16 refcheck;
int rc;
- loff_t size = i_size_read(inode);
ENTRY;
io->u.ci_setattr.sa_falloc_end = offset + len;
io->u.ci_setattr.sa_subtype = CL_SETATTR_FALLOCATE;
- CDEBUG(D_INODE, "UID %u GID %u\n",
+ CDEBUG(D_INODE, "UID %u GID %u PRJID %u\n",
from_kuid(&init_user_ns, inode->i_uid),
- from_kgid(&init_user_ns, inode->i_gid));
+ from_kgid(&init_user_ns, inode->i_gid),
+ ll_i2info(inode)->lli_projid);
io->u.ci_setattr.sa_falloc_uid = from_kuid(&init_user_ns, inode->i_uid);
io->u.ci_setattr.sa_falloc_gid = from_kgid(&init_user_ns, inode->i_gid);
+ io->u.ci_setattr.sa_falloc_projid = ll_i2info(inode)->lli_projid;
if (io->u.ci_setattr.sa_falloc_end > size) {
loff_t newsize = io->u.ci_setattr.sa_falloc_end;
{
struct inode *inode;
struct obdo *oa;
- u64 valid_flags = OBD_MD_FLTYPE | OBD_MD_FLUID | OBD_MD_FLGID;
+ u64 valid_flags = OBD_MD_FLTYPE | OBD_MD_FLUID | OBD_MD_FLGID |
+ OBD_MD_FLPROJID;
oa = attr->cra_oa;
inode = vvp_object_inode(obj);
parent->u.ci_setattr.sa_falloc_uid;
io->u.ci_setattr.sa_falloc_gid =
parent->u.ci_setattr.sa_falloc_gid;
+ io->u.ci_setattr.sa_falloc_projid =
+ parent->u.ci_setattr.sa_falloc_projid;
}
if (cl_io_is_trunc(io)) {
loff_t new_size = parent->u.ci_setattr.sa_attr.lvb_size;
oa->o_blocks = io->u.ci_setattr.sa_falloc_end;
oa->o_uid = io->u.ci_setattr.sa_falloc_uid;
oa->o_gid = io->u.ci_setattr.sa_falloc_gid;
+ oa->o_projid = io->u.ci_setattr.sa_falloc_projid;
oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
- OBD_MD_FLUID | OBD_MD_FLGID;
+ OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLPROJID;
- CDEBUG(D_INODE, "size %llu blocks %llu uid %u gid %u\n",
- oa->o_size, oa->o_blocks, oa->o_uid, oa->o_gid);
+ CDEBUG(D_INODE,
+ "size %llu blocks %llu uid %u gid %u prjid %u\n",
+ oa->o_size, oa->o_blocks, oa->o_uid, oa->o_gid,
+ oa->o_projid);
result = osc_fallocate_base(osc_export(cl2osc(obj)),
oa, osc_async_upcall,
cbargs, falloc_mode);
}
run_test 78 "Check fallocate increase quota usage"
+test_78a()
+{
+ (( $CLIENT_VERSION >= $(version_code 2.15.0) )) ||
+ skip "need client at least 2.15.0"
+ (( $OST1_VERSION >= $(version_code 2.15.0) )) ||
+ skip "need OST at least 2.15.0"
+ check_set_fallocate_or_skip
+
+ setup_quota_test || error "setup quota failed with $?"
+
+ # enable ost quota
+ set_ost_qtype $QTYPE || error "enable ost quota failed"
+
+ mkdir -p $DIR/$tdir || error "failed to create $tdir"
+
+ local projectid=5200 # Random project id to test
+
+ change_project -sp $projectid $DIR/$tdir
+
+ # setup quota limit
+ $LFS setquota -p $projectid -b25M -B25M $DIR/$tdir ||
+ error "lfs setquota project failed"
+
+ # call fallocate
+ fallocate -l 204800 $DIR/$tdir/$tfile
+
+ # Get curspace (kbytes) for $projectid
+ local kbytes=$(getquota -p $projectid global curspace)
+
+ echo "kbytes returned:$kbytes"
+
+ # For file size of 204800. We should be having roughly 200 kbytes
+ # returned. Anything alarmingly low (50 taken as arbitrary value)
+ # would bail out this TC. Also this also avoids $kbytes of 0
+ # to be used in calculation below.
+ (( $kbytes > 50 )) ||
+ error "fallocate did not use projectid. kbytes returned:$kbytes"
+
+ local expect_lo=$(($kbytes * 95 / 100)) # 5% below
+ local expect_hi=$(($kbytes * 105 / 100)) # 5% above
+
+ # Verify kbytes is 200 (204800/1024). With a permited 5% drift
+ (( $kbytes >= $expect_lo && $kbytes <= $expect_hi )) ||
+ error "fallocate did not use quota projectid correctly"
+}
+run_test 78a "Check fallocate increase projectid usage"
+
test_79()
{
local qpool="qpool1"