From 789038c97ae1072874dcd6afcc9cd78e9c885368 Mon Sep 17 00:00:00 2001 From: Arshad Hussain Date: Sun, 7 Nov 2021 09:46:29 -0500 Subject: [PATCH] LU-15167 quota: fallocate send UID/GID for quota Calling fallocate() on a newly created file did not account quota usage properly because the OST object did not have a UID/GID assigned yet. Update the fallocate code in the OSC to always send the file UID/GID/PROJID to the OST so that the object ownership can be updated before space is allocated. Test-case: sanity-quota/78 added Fixes: 48457868a02a ("LU-3606 fallocate: Implement fallocate preallocate operation") Signed-off-by: Arshad Hussain Change-Id: I86d80a7f415a80100f7d2fb5f417cf47bf5b2900 Reviewed-on: https://review.whamcloud.com/45475 Reviewed-by: Andreas Dilger Reviewed-by: Bobi Jam Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/include/cl_object.h | 2 ++ lustre/llite/file.c | 8 ++++++++ lustre/lov/lov_io.c | 4 ++++ lustre/ofd/ofd_dev.c | 9 +++++---- lustre/osc/osc_io.c | 8 +++++++- lustre/tests/sanity-quota.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 68 insertions(+), 5 deletions(-) diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h index 145e683..d6b3c70 100644 --- a/lustre/include/cl_object.h +++ b/lustre/include/cl_object.h @@ -1870,6 +1870,8 @@ struct cl_io { int sa_falloc_mode; loff_t sa_falloc_offset; loff_t sa_falloc_end; + uid_t sa_falloc_uid; + gid_t sa_falloc_gid; } ci_setattr; struct cl_data_version_io { u64 dv_data_version; diff --git a/lustre/llite/file.c b/lustre/llite/file.c index c87deda..9e230b9 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -5360,6 +5360,14 @@ int cl_falloc(struct file *file, struct inode *inode, int mode, loff_t offset, io->u.ci_setattr.sa_falloc_offset = offset; 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", + from_kuid(&init_user_ns, inode->i_uid), + from_kgid(&init_user_ns, inode->i_gid)); + + 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); + if (io->u.ci_setattr.sa_falloc_end > size) { loff_t newsize = io->u.ci_setattr.sa_falloc_end; diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index b3fd6d8..2b37380 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -689,6 +689,10 @@ static void lov_io_sub_inherit(struct lov_io_sub *sub, struct lov_io *lio, if (cl_io_is_fallocate(io)) { io->u.ci_setattr.sa_falloc_offset = start; io->u.ci_setattr.sa_falloc_end = end; + io->u.ci_setattr.sa_falloc_uid = + parent->u.ci_setattr.sa_falloc_uid; + io->u.ci_setattr.sa_falloc_gid = + parent->u.ci_setattr.sa_falloc_gid; } if (cl_io_is_trunc(io)) { loff_t new_size = parent->u.ci_setattr.sa_attr.lvb_size; diff --git a/lustre/ofd/ofd_dev.c b/lustre/ofd/ofd_dev.c index 628e7c9..4858cf5 100644 --- a/lustre/ofd/ofd_dev.c +++ b/lustre/ofd/ofd_dev.c @@ -1961,6 +1961,7 @@ static int ofd_fallocate_hdl(struct tgt_session_info *tsi) struct ldlm_resource *res; struct ofd_object *fo; __u64 flags = 0; + __u64 valid; struct lustre_handle lh = { 0, }; int rc, mode; __u64 start, end; @@ -2017,8 +2018,9 @@ static int ofd_fallocate_hdl(struct tgt_session_info *tsi) if (IS_ERR(fo)) GOTO(out, rc = PTR_ERR(fo)); - la_from_obdo(&info->fti_attr, oa, - OBD_MD_FLMTIME | OBD_MD_FLATIME | OBD_MD_FLCTIME); + valid = OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLPROJID | + OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME; + la_from_obdo(&info->fti_attr, oa, valid); rc = ofd_object_fallocate(tsi->tsi_env, fo, start, end, mode, &info->fti_attr, oa); @@ -2027,8 +2029,7 @@ static int ofd_fallocate_hdl(struct tgt_session_info *tsi) rc = ofd_attr_get(tsi->tsi_env, fo, &info->fti_attr); if (rc == 0) - obdo_from_la(&repbody->oa, &info->fti_attr, - OFD_VALID_FLAGS); + obdo_from_la(&repbody->oa, &info->fti_attr, OFD_VALID_FLAGS); else rc = 0; diff --git a/lustre/osc/osc_io.c b/lustre/osc/osc_io.c index 84c1831..f74bd3f 100644 --- a/lustre/osc/osc_io.c +++ b/lustre/osc/osc_io.c @@ -678,7 +678,13 @@ static int osc_io_setattr_start(const struct lu_env *env, oa->o_size = io->u.ci_setattr.sa_falloc_offset; oa->o_blocks = io->u.ci_setattr.sa_falloc_end; - oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS; + oa->o_uid = io->u.ci_setattr.sa_falloc_uid; + oa->o_gid = io->u.ci_setattr.sa_falloc_gid; + oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS | + OBD_MD_FLUID | OBD_MD_FLGID; + + CDEBUG(D_INODE, "size %llu blocks %llu uid %u gid %u\n", + oa->o_size, oa->o_blocks, oa->o_uid, oa->o_gid); result = osc_fallocate_base(osc_export(cl2osc(obj)), oa, osc_async_upcall, cbargs, falloc_mode); diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index b630044..34d6452 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -4993,6 +4993,48 @@ test_77() } run_test 77 "lfs setquota should fail in Lustre mount with 'ro'" +test_78() +{ + (( $OST1_VERSION >= $(version_code 2.14.55) )) || + skip "need OST at least 2.14.55" + check_set_fallocate_or_skip + + setup_quota_test || error "setup quota failed with $?" + stack_trap cleanup_quota_test + + # enable ost quota + set_ost_qtype $QTYPE || error "enable ost quota failed" + + mkdir -p $DIR/$tdir || error "failed to create $tdir" + chown $TSTUSR $DIR/$tdir || error "failed to chown $tdir" + + # setup quota limit + $LFS setquota -u $TSTUSR -b25M -B25M $DIR/$tdir || + error "lfs setquota failed" + + # call fallocate + runas -u $TSTUSR -g $TSTUSR fallocate -l 204800 $DIR/$tdir/$tfile + + kbytes=$(lfs quota -u $TSTUSR $DIR | + awk -v pattern=$DIR 'match($0, pattern) {printf $2}') + 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 quota. 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 correctly" +} +run_test 78 "Check fallocate increase quota usage" + quota_fini() { do_nodes $(comma_list $(nodes_list)) \ -- 1.8.3.1