From 88c26912a3237fb63923bbb7c7b09111f9f30bbe Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Tue, 11 Jan 2022 23:12:55 +0800 Subject: [PATCH] LU-13176 mdd: rename file with different project ID 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 Change-Id: I4a2c21248d1e12ad1d00430e11e5dd50fe5eaf60 Reviewed-on: https://review.whamcloud.com/45660 Reviewed-by: Andreas Dilger Tested-by: jenkins Tested-by: Maloo Reviewed-by: Li Dongyang Reviewed-by: Oleg Drokin --- lustre/mdd/mdd_dir.c | 22 ++++++++++++--- lustre/tests/sanity-quota.sh | 65 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/lustre/mdd/mdd_dir.c b/lustre/mdd/mdd_dir.c index 7448147..51f5a7e 100644 --- a/lustre/mdd/mdd_dir.c +++ b/lustre/mdd/mdd_dir.c @@ -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); diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index f2a8490..89ba55e 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -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 && -- 1.8.3.1