Whamcloud - gitweb
LU-15167 quota: fallocate send UID/GID for quota 75/45475/5
authorArshad Hussain <arshad.hussain@aeoncomputing.com>
Sun, 7 Nov 2021 14:46:29 +0000 (09:46 -0500)
committerOleg Drokin <green@whamcloud.com>
Mon, 13 Dec 2021 03:52:18 +0000 (03:52 +0000)
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 <arshad.hussain@aeoncomputing.com>
Change-Id: I86d80a7f415a80100f7d2fb5f417cf47bf5b2900
Reviewed-on: https://review.whamcloud.com/45475
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/cl_object.h
lustre/llite/file.c
lustre/lov/lov_io.c
lustre/ofd/ofd_dev.c
lustre/osc/osc_io.c
lustre/tests/sanity-quota.sh

index 145e683..d6b3c70 100644 (file)
@@ -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;
index c87deda..9e230b9 100644 (file)
@@ -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;
 
index b3fd6d8..2b37380 100644 (file)
@@ -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;
index 628e7c9..4858cf5 100644 (file)
@@ -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;
 
index 84c1831..f74bd3f 100644 (file)
@@ -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);
index b630044..34d6452 100755 (executable)
@@ -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)) \