* 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
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;
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;
bool is_dir;
bool tobj_ref = 0;
bool tobj_locked = 0;
+ bool change_projid = false;
unsigned cl_flags = 0;
int rc, rc2;
ENTRY;
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);
/* 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);
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 &&