Whamcloud - gitweb
LU-13176 mdd: rename file with different project ID 60/45660/8
authorHongchao Zhang <hongchao@whamcloud.com>
Tue, 11 Jan 2022 15:12:55 +0000 (23:12 +0800)
committerOleg Drokin <green@whamcloud.com>
Mon, 31 Jan 2022 01:37:44 +0000 (01:37 +0000)
This patch relaxes the limitation for rename between different
proeject IDs, and it will allow the normal file rename between
directories with different project IDs.

Signed-off-by: Hongchao Zhang <hongchao@whamcloud.com>
Change-Id: I4a2c21248d1e12ad1d00430e11e5dd50fe5eaf60
Reviewed-on: https://review.whamcloud.com/45660
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/mdd/mdd_dir.c
lustre/tests/sanity-quota.sh

index 7448147..51f5a7e 100644 (file)
@@ -2842,10 +2842,11 @@ static int mdd_rename_sanity_check(const struct lu_env *env,
         * into our tree when the project IDs are the same; otherwise
         * tree quota mechanism would be circumvented.
         */
-       if (((tpattr->la_flags & LUSTRE_PROJINHERIT_FL) &&
+       if ((((tpattr->la_flags & LUSTRE_PROJINHERIT_FL) &&
            tpattr->la_projid != cattr->la_projid) ||
            ((pattr->la_flags & LUSTRE_PROJINHERIT_FL) &&
-           (pattr->la_projid != tpattr->la_projid)))
+           (pattr->la_projid != tpattr->la_projid))) &&
+           S_ISDIR(cattr->la_mode))
                RETURN(-EXDEV);
 
        /* we prevent an encrypted file from being renamed
@@ -2888,7 +2889,7 @@ static int mdd_declare_rename(const struct lu_env *env,
                              const struct lu_name *sname,
                              const struct lu_name *tname,
                              struct md_attr *ma,
-                             struct linkea_data *ldata,
+                             struct linkea_data *ldata, bool change_projid,
                              struct thandle *handle)
 {
        struct lu_attr *la = &mdd_env_info(env)->mdi_la_for_fix;
@@ -2942,6 +2943,8 @@ static int mdd_declare_rename(const struct lu_env *env,
                return rc;
 
        la->la_valid = LA_CTIME;
+       if (change_projid)
+               la->la_valid |= LA_PROJID;
        rc = mdo_declare_attr_set(env, mdd_sobj, la, handle);
        if (rc)
                return rc;
@@ -3035,6 +3038,7 @@ static int mdd_rename(const struct lu_env *env,
        bool is_dir;
        bool tobj_ref = 0;
        bool tobj_locked = 0;
+       bool change_projid = false;
        unsigned cl_flags = 0;
        int rc, rc2;
        ENTRY;
@@ -3117,8 +3121,13 @@ static int mdd_rename(const struct lu_env *env,
        if (rc)
                GOTO(stop, rc);
 
+       if (tpattr->la_projid != cattr->la_projid &&
+           tpattr->la_flags & LUSTRE_PROJINHERIT_FL)
+               change_projid = true;
+
        rc = mdd_declare_rename(env, mdd, mdd_spobj, mdd_tpobj, mdd_sobj,
-                               mdd_tobj, lsname, ltname, ma, ldata, handle);
+                               mdd_tobj, lsname, ltname, ma, ldata,
+                               change_projid, handle);
        if (rc)
                GOTO(stop, rc);
 
@@ -3163,6 +3172,11 @@ static int mdd_rename(const struct lu_env *env,
 
        /* XXX: mdd_sobj must be local one if it is NOT NULL. */
        la->la_valid = LA_CTIME;
+       if (change_projid) {
+               /* mdd_update_time honors other valid flags except TIME ones */
+               la->la_valid |= LA_PROJID;
+               la->la_projid = tpattr->la_projid;
+       }
        rc = mdd_update_time(env, mdd_sobj, cattr, la, handle);
        if (rc)
                GOTO(fixup_tpobj, rc);
index f2a8490..89ba55e 100755 (executable)
@@ -3647,19 +3647,64 @@ run_test 51 "Test project accounting with mv/cp"
 test_52() {
        ! is_project_quota_supported &&
                skip "Project quota is not supported"
+
+       (( MDS1_VERSION >= $(version_code 2.14.55) )) ||
+               skip "Need MDS version at least 2.14.55"
+
        setup_quota_test || error "setup quota failed with $?"
-       local dir="$DIR/$tdir/dir"
-       mkdir $dir && change_project -sp 1 $dir
 
-       touch $DIR/$tdir/file
-       #Try renaming a file into the project.  This should fail.
-       for num in $(seq 1 2000); do
-               mrename $DIR/$tdir/file $dir/file >&/dev/null &&
-                       error "rename should fail"
-       done
-       return 0
+       local dir1=$DIR/$tdir/t52_dir1
+       local dir2=$DIR/$tdir/t52_dir2
+
+       mkdir $dir1 || error "failed to mkdir $dir1"
+       mkdir $dir2 || error "failed to mkdir $dir2"
+
+       $LFS project -sp 1000 $dir1 || error "fail to set project on $dir1"
+       $LFS project -sp 1001 $dir2 || error "fail to set project on $dir2"
+
+       $DD if=/dev/zero of=/$dir1/$tfile bs=1M count=100 ||
+               error "failed to create and write $tdir1/$tfile"
+
+       cancel_lru_locks osc
+       sync; sync_all_data || true
+
+       local attrs=($(lsattr -p $dir1/$tfile))
+       (( ${attrs[0]} == 1000 )) ||
+               error "project ID on $dir1/$tfile is not inherited"
+
+       $LFS quota -p 1000 $DIR
+       $LFS quota -p 1001 $DIR
+
+       local prev_used=$(getquota -p 1000 global curspace)
+       local prev_used2=$(getquota -p 1001 global curspace)
+
+       mrename $dir1 $dir2/tdir || log "rename directory return $?"
+
+       local inum_before=$(ls -i $dir1/$tfile | awk '{print $1}')
+       mrename $dir1/$tfile $dir2/$tfile || error "failed to rename file"
+       local inum_after=$(ls -i $dir2/$tfile | awk '{print $1}')
+
+       attrs=($(lsattr -p $dir2/$tfile))
+       (( ${attrs[0]} == 1001 )) ||
+               error "project ID is not updated after rename"
+
+       (( $inum_before == $inum_after )) ||
+               error "inode is changed after rename: $inum_before, $inum_after"
+
+       sync_all_data || true
+
+       $LFS quota -p 1000 $DIR
+       $LFS quota -p 1001 $DIR
+
+       local new_used=$(getquota -p 1000 global curspace)
+       local new_used2=$(getquota -p 1001 global curspace)
+
+       (( $prev_used >= $new_used + 102400 )) ||
+               error "quota is not deducted from old project ID"
+       (( $prev_used2 <= $new_used2 - 102400 )) ||
+               error "quota is not added for the new project ID"
 }
-run_test 52 "Rename across different project ID"
+run_test 52 "Rename normal file across project ID"
 
 test_53() {
        ! is_project_quota_supported &&