Whamcloud - gitweb
LU-18757 client: Set UID/GID/PROJID on OST for OST_PUNCH RPC 47/58647/2
authorMarc Vef <mvef@whamcloud.com>
Wed, 2 Apr 2025 19:49:59 +0000 (21:49 +0200)
committerOleg Drokin <green@whamcloud.com>
Wed, 16 Apr 2025 20:41:56 +0000 (20:41 +0000)
The OST_PUNCH RPC (as generated by "truncate -s" commands) does not
set the UID/GID/PROJID stored on an OST object. This is because the
obdo fields and corresponding valid flags are not set on the client
and OST sides.

This patch adds support for setting UID/GID/PROJID on the
corresponding OST objects for operations that send the OST_PUNCH RPC.

Sanity-sec test_75 is added to check that the IDs are set on the OST
objects.

Signed-off-by: Marc Vef <mvef@whamcloud.com>
Change-Id: I9baabbe9e523c98523fa30d387197e1faf38199a
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58647
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/cl_object.h
lustre/llite/file.c
lustre/llite/lcommon_cl.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/lov/lov_io.c
lustre/ofd/ofd_dev.c
lustre/osc/osc_io.c
lustre/tests/sanity-sec.sh

index d7237e7..bd63a16 100644 (file)
@@ -1793,9 +1793,10 @@ 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;
-                       __u32                    sa_falloc_projid;
+                       /* id fields used for truncate/fallocate */
+                       uid_t                    sa_attr_uid;
+                       gid_t                    sa_attr_gid;
+                       __u32                    sa_attr_projid;
                } ci_setattr;
                struct cl_data_version_io {
                        u64 dv_data_version;
index 549cbf6..e3b4a90 100644 (file)
@@ -3096,8 +3096,8 @@ static ssize_t ll_lov_setstripe(struct inode *inode, struct file *file,
                    ll_i2info(inode)->lli_clob) {
                        struct iattr attr = { 0 };
 
-                       rc = cl_setattr_ost(ll_i2info(inode)->lli_clob, &attr,
-                                           OP_XVALID_FLAGS, LUSTRE_ENCRYPT_FL);
+                       rc = cl_setattr_ost(inode, &attr, OP_XVALID_FLAGS,
+                                           LUSTRE_ENCRYPT_FL);
                }
        }
        cl_lov_delay_create_clear(&file->f_flags);
@@ -4269,7 +4269,6 @@ int ll_set_project(struct inode *inode, __u32 xflags, __u32 projid)
 {
        struct ptlrpc_request *req = NULL;
        struct md_op_data *op_data;
-       struct cl_object *obj;
        int rc = 0;
 
        CDEBUG(D_QUOTA, DFID" xflags=%x projid=%u\n",
@@ -4299,11 +4298,10 @@ int ll_set_project(struct inode *inode, __u32 xflags, __u32 projid)
        if (xflags == 0 || xflags == FS_XFLAG_PROJINHERIT)
                GOTO(out_fsxattr, rc);
 
-       obj = ll_i2info(inode)->lli_clob;
-       if (obj) {
+       if (ll_i2info(inode)->lli_clob) {
                struct iattr attr = { 0 };
 
-               rc = cl_setattr_ost(obj, &attr, OP_XVALID_FLAGS, xflags);
+               rc = cl_setattr_ost(inode, &attr, OP_XVALID_FLAGS, xflags);
        }
 
 out_fsxattr:
@@ -6492,9 +6490,9 @@ static int cl_falloc(struct file *file, struct inode *inode, int mode,
               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;
+       io->u.ci_setattr.sa_attr_uid = from_kuid(&init_user_ns, inode->i_uid);
+       io->u.ci_setattr.sa_attr_gid = from_kgid(&init_user_ns, inode->i_gid);
+       io->u.ci_setattr.sa_attr_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;
index d83f892..7e7733e 100644 (file)
@@ -46,16 +46,19 @@ __u16 cl_inode_fini_refcheck;
  */
 static DEFINE_MUTEX(cl_inode_fini_guard);
 
-int cl_setattr_ost(struct cl_object *obj, const struct iattr *attr,
+int cl_setattr_ost(struct inode *inode, const struct iattr *attr,
                   enum op_xvalid xvalid, unsigned int attr_flags)
 {
+       struct cl_object *obj;
        struct lu_env *env;
-       struct cl_io  *io;
+       struct cl_io *io;
        int result;
        __u16 refcheck;
 
        ENTRY;
 
+       obj = ll_i2info(inode)->lli_clob;
+
        env = cl_env_get(&refcheck);
        if (IS_ERR(env))
                RETURN(PTR_ERR(env));
@@ -72,8 +75,14 @@ int cl_setattr_ost(struct cl_object *obj, const struct iattr *attr,
        io->u.ci_setattr.sa_avalid = attr->ia_valid;
        io->u.ci_setattr.sa_xvalid = xvalid;
        io->u.ci_setattr.sa_parent_fid = lu_object_fid(&obj->co_lu);
-       if (attr->ia_valid & ATTR_SIZE)
+       if (attr->ia_valid & ATTR_SIZE) {
                io->u.ci_setattr.sa_subtype = CL_SETATTR_TRUNC;
+               io->u.ci_setattr.sa_attr_uid =
+                       from_kuid(&init_user_ns, current_uid());
+               io->u.ci_setattr.sa_attr_gid =
+                       from_kgid(&init_user_ns, current_gid());
+               io->u.ci_setattr.sa_attr_projid = ll_i2info(inode)->lli_projid;
+       }
 again:
        if (attr->ia_valid & ATTR_FILE)
                ll_io_set_mirror(io, attr->ia_file);
index ff10cb5..006bfc0 100644 (file)
@@ -2116,7 +2116,7 @@ int ll_page_sync_io(const struct lu_env *env, struct cl_io *io,
 int ll_getparent(struct file *file, struct getparent __user *arg);
 
 /* lcommon_cl.c */
-int cl_setattr_ost(struct cl_object *obj, const struct iattr *attr,
+int cl_setattr_ost(struct inode *inode, const struct iattr *attr,
                   enum op_xvalid xvalid, unsigned int attr_flags);
 
 extern struct lu_env *cl_inode_fini_env;
index 56dff93..7b64959 100644 (file)
@@ -2448,7 +2448,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr,
                                        attr->ia_size = ref_attr.cat_size;
                                }
                        }
-                       rc = cl_setattr_ost(lli->lli_clob, attr, xvalid, flags);
+                       rc = cl_setattr_ost(inode, attr, xvalid, flags);
                }
        }
 
@@ -3256,7 +3256,6 @@ static int fileattr_set(struct inode *inode, int flags)
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ptlrpc_request *req = NULL;
        struct md_op_data *op_data;
-       struct cl_object *obj;
        struct fsxattr fa = { 0 };
        struct iattr *attr;
        int rc;
@@ -3286,15 +3285,14 @@ static int fileattr_set(struct inode *inode, int flags)
 
        ll_update_inode_flags(inode, flags);
 
-       obj = ll_i2info(inode)->lli_clob;
-       if (obj == NULL)
+       if (!ll_i2info(inode)->lli_clob)
                RETURN(0);
 
        OBD_ALLOC_PTR(attr);
        if (attr == NULL)
                RETURN(-ENOMEM);
 
-       rc = cl_setattr_ost(obj, attr, OP_XVALID_FLAGS, flags);
+       rc = cl_setattr_ost(inode, attr, OP_XVALID_FLAGS, flags);
 
        OBD_FREE_PTR(attr);
        RETURN(rc);
index dcf41b5..bc0669a 100644 (file)
@@ -715,12 +715,12 @@ 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;
-                       io->u.ci_setattr.sa_falloc_projid =
-                               parent->u.ci_setattr.sa_falloc_projid;
+                       io->u.ci_setattr.sa_attr_uid =
+                               parent->u.ci_setattr.sa_attr_uid;
+                       io->u.ci_setattr.sa_attr_gid =
+                               parent->u.ci_setattr.sa_attr_gid;
+                       io->u.ci_setattr.sa_attr_projid =
+                               parent->u.ci_setattr.sa_attr_projid;
                }
                if (cl_io_is_trunc(io)) {
                        loff_t new_size = parent->u.ci_setattr.sa_attr.lvb_size;
@@ -728,6 +728,12 @@ static void lov_io_sub_inherit(struct lov_io_sub *sub, struct lov_io *lio,
                        new_size = lov_size_to_stripe(lsm, index, new_size,
                                                      stripe);
                        io->u.ci_setattr.sa_attr.lvb_size = new_size;
+                       io->u.ci_setattr.sa_attr_uid =
+                               parent->u.ci_setattr.sa_attr_uid;
+                       io->u.ci_setattr.sa_attr_gid =
+                               parent->u.ci_setattr.sa_attr_gid;
+                       io->u.ci_setattr.sa_attr_projid =
+                               parent->u.ci_setattr.sa_attr_projid;
                }
                lov_lsm2layout(lsm, lsm->lsm_entries[index],
                               &io->u.ci_setattr.sa_layout);
index 47c2d0a..253d68d 100644 (file)
@@ -2105,7 +2105,8 @@ static int ofd_punch_hdl(struct tgt_session_info *tsi)
                GOTO(out, rc = PTR_ERR(fo));
 
        la_from_obdo(&info->fti_attr, oa,
-                    OBD_MD_FLMTIME | OBD_MD_FLATIME | OBD_MD_FLCTIME);
+                    OBD_MD_FLMTIME | OBD_MD_FLATIME | OBD_MD_FLCTIME |
+                            OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLPROJID);
        info->fti_attr.la_size = start;
        info->fti_attr.la_valid |= LA_SIZE;
 
index 40f76f0..ca0d9d3 100644 (file)
@@ -663,9 +663,9 @@ 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_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_uid = io->u.ci_setattr.sa_attr_uid;
+                       oa->o_gid = io->u.ci_setattr.sa_attr_gid;
+                       oa->o_projid = io->u.ci_setattr.sa_attr_projid;
                        oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
                                OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLPROJID;
 
@@ -679,7 +679,12 @@ static int osc_io_setattr_start(const struct lu_env *env,
                } else if (ia_avalid & ATTR_SIZE) {
                        oa->o_size = size;
                        oa->o_blocks = OBD_OBJECT_EOF;
-                       oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
+                       oa->o_uid = io->u.ci_setattr.sa_attr_uid;
+                       oa->o_gid = io->u.ci_setattr.sa_attr_gid;
+                       oa->o_projid = io->u.ci_setattr.sa_attr_projid;
+                       oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
+                                      OBD_MD_FLUID | OBD_MD_FLGID |
+                                      OBD_MD_FLPROJID;
                        result = osc_punch_send(osc_export(cl2osc(obj)),
                                                oa, osc_async_upcall, cbargs);
                } else {
index 055dd7d..413712a 100755 (executable)
@@ -7705,6 +7705,72 @@ test_74() {
 }
 run_test 74 "Set nodemap deny_mount flag"
 
+check_ost_object_ids() {
+       local file=$1
+       local expected_uid=$2
+       local expected_gid=$3
+       local expected_projid=$4
+       local objdump=$DIR/$tdir/objdump
+
+       mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+
+       # Get the OST object path. We assume the file has one stripe on ost1
+       local fids=($($LFS getstripe $file | grep 0x))
+       local fid="${fids[3]}:${fids[2]}:0"
+       local objpath=$(ost_fid2_objpath ost1 $fid)
+
+       do_facet ost1 "$DEBUGFS -c -R 'stat $objpath' $(ostdevname 1)" | \
+               grep "Project" > $objdump
+       local obj_uid=$(awk '{print $2}' $objdump)
+       local obj_gid=$(awk '{print $4}' $objdump)
+       local obj_projid=$(awk '{print $6}' $objdump)
+       echo "OST object ids and size for file '$file': $(cat $objdump)"
+
+       [[ "$obj_uid" == "$expected_uid" ]] ||
+               error "uid is not set to expected value $expected_uid"
+       [[ "$obj_gid" == "$expected_gid" ]] ||
+               error "gid is not set to expected value $expected_gid"
+       [[ "$obj_projid" == "$expected_projid" ]] ||
+               error "projid is not set to expected value $expected_projid"
+}
+
+test_75() {
+       local tfile_write=$DIR/$tdir/${tfile}_write
+       local tfile_trunc=$DIR/$tdir/${tfile}_trunc
+       local testdir_projid=42
+
+       (( $OST1_VERSION >= $(version_code 2.16.53) &&
+               $CLIENT_VERSION >= $(version_code 2.16.53) )) ||
+               skip "Both client and OST need at least 2.16.53"
+
+       [[ "$ost1_FSTYPE" == ldiskfs ]] ||
+               skip "ldiskfs only test (using debugfs)"
+
+       # setup
+       mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+       $LFS project -s -p $testdir_projid $DIR/$tdir ||
+               error "lfs project failed"
+       chown $USER0 $DIR/$tdir || error "chown Failed"
+
+       # Sanity check IDs with OST_WRITE RPC
+       $RUNAS_CMD -u $ID0 $LFS setstripe -c 1 -i 0 $tfile_write
+       $RUNAS_CMD -u $ID0 dd if=/dev/urandom of=$tfile_write bs=1M count=1 && \
+               sync
+
+       # OST_PUNCH RPC (via truncate) setting OST object IDs correctly
+       $RUNAS_CMD -u $ID0 $LFS setstripe -c 1 -i 0 $tfile_trunc
+       $RUNAS_CMD -u $ID0 $TRUNCATE $tfile_trunc 1048576 && sync
+
+       # wait for asynchronous MDS-OST sync and force flush to OST
+       sync_all_data
+       wait_mds_ost_sync || error "wait_mds_ost_sync failed"
+       do_facet ost1 "sync; sync"
+
+       check_ost_object_ids $tfile_write $ID0 $ID0 $testdir_projid
+       check_ost_object_ids $tfile_trunc $ID0 $ID0 $testdir_projid
+}
+run_test 75 "check uid/gid/projid are set on OST for OST_PUNCH RPC"
+
 log "cleanup: ======================================================"
 
 sec_unsetup() {