struct mdd_object *tobj,
const struct lu_attr *spattr,
const struct lu_attr *tpattr,
- const struct lu_attr *attr)
+ const struct lu_attr *attr,
+ bool nsonly)
{
int rc;
ENTRY;
- if (!mdd_object_remote(sobj)) {
+ if (!nsonly && !mdd_object_remote(sobj)) {
mdd_read_lock(env, sobj, DT_SRC_CHILD);
if (sobj->mod_count > 0) {
CDEBUG(D_INFO, "%s: "DFID" is opened, count %d\n",
LASSERT(ldata->ld_leh != NULL);
/*
- * If linkEA is overflow, it means there are some unknown name entries
- * under unknown parents, which will prevent the migration.
+ * If linkEA is overflow, switch to ns-only migrate
*/
if (unlikely(ldata->ld_leh->leh_overflow_time))
- RETURN(-EOVERFLOW);
+ RETURN(+EOVERFLOW);
rc = mdd_fld_lookup(env, mdd, mdd_object_fid(sobj), &source_mdt_index);
if (rc)
RETURN(rc);
rc = mdd_migrate_sanity_check(env, mdd, spobj, tpobj, sobj, tobj,
- spattr, tpattr, attr);
+ spattr, tpattr, attr,
+ spec->sp_migrate_nsonly);
+ if (rc == -EBUSY && !spec->sp_migrate_nsonly) {
+ spec->sp_migrate_nsonly = 1;
+ CWARN("%s: "DFID"/%s is open, migrate only dentry\n",
+ mdd2obd_dev(mdd)->obd_name, PFID(mdd_object_fid(spobj)),
+ sname->ln_name);
+ rc = mdd_migrate_sanity_check(env, mdd, spobj, tpobj, sobj,
+ tobj, spattr, tpattr, attr,
+ spec->sp_migrate_nsonly);
+ }
if (rc)
RETURN(rc);
if (info->mti_spec.sp_migrate_close) {
/* try to hold open_sem so that nobody else can open the file */
if (!down_write_trylock(&sobj->mot_open_sem)) {
- /* close anyway */
- mdd_migrate_close(info, sobj);
- GOTO(unlock_source, rc = -EBUSY);
+ /* migrate only dentry */
+ if (!info->mti_spec.sp_migrate_nsonly)
+ CWARN("%s: "DFID"/%s is open, migrate only dentry\n",
+ mdt2obd_dev(mdt)->obd_name,
+ PFID(mdt_object_fid(spobj)),
+ rr->rr_name.ln_name);
+ info->mti_spec.sp_migrate_nsonly = 1;
+
} else {
open_sem_locked = true;
- rc = mdd_migrate_close(info, sobj);
- if (rc && rc != -ESTALE)
- GOTO(unlock_open_sem, rc);
}
+ rc = mdd_migrate_close(info, sobj);
+ if (rc && rc != -ESTALE)
+ GOTO(unlock_open_sem, rc);
}
tobj = mdt_object_find(env, mdt, rr->rr_fid2);
error "(2) Fail to hard link"
cancel_lru_locks mdc
- if [ $MDSCOUNT -ge 2 ]; then
+
+ local linked_file_migrate=false
+ (( $MDS1_VERSION >= $(version_code 2.16.50) )) &&
+ linked_file_migrate=true
+
+ if (( $MDSCOUNT >= 2 )) && $linked_file_migrate; then
+ $LFS migrate -m 1 $DIR/$tdir/guard 2>/dev/null ||
+ error "(3.1) Migrate should succeed"
+
+ echo "The object with linkEA overflow should NOT be migrated"
+ local newfid=$($LFS path2fid $DIR/$tdir/guard/f0)
+ [ "$newfid" == "$oldfid" ] ||
+ error "(3.2) The file with overflowed LinkEA should not migrate: $newfid != $oldfid"
+ fi
+ if (( $MDSCOUNT >= 2 )) && ! $linked_file_migrate; then
$LFS migrate -m 1 $DIR/$tdir/guard 2>/dev/null &&
error "(3.1) Migrate should fail"
echo "Remove 100 hard links to save space for the missed linkEA entries"
unlinkmany $DIR/$tdir/foo/ttttttttttt 100 || error "(4) Fail to unlink"
- if [ $MDSCOUNT -ge 2 ]; then
+ if (( $MDSCOUNT >= 2 )) && $linked_file_migrate; then
+ $LFS migrate -m 1 $DIR/$tdir/guard 2>/dev/null ||
+ error "(5.1) Migrate should succeed"
+
+ # The overflow timestamp is still there, so migration
+ # should not migrate the file with LinkEA overflow timestamp
+ # but migrate only name
+ local newfid=$($LFS path2fid $DIR/$tdir/guard/f0)
+ [ "$newfid" == "$oldfid" ] ||
+ error "(5.2) The file should not migrate: $newfid != $oldfid"
+ fi
+ if (( $MDSCOUNT >= 2 )) && ! $linked_file_migrate; then
$LFS migrate -m 1 $DIR/$tdir/guard 2>/dev/null &&
error "(5.1) Migrate should fail"
error "$file is not on MDT${MDTIDX}"
done
+ if (($MDS1_VERSION >= $(version_code 2.16.50) )); then
+ echo "Migrate a dir with an open file"
+ touch $migrate_dir/foo
+ local foo_fid=$($LFS path2fid $migrate_dir/foo)
+ $MULTIOP $migrate_dir/foo o_c &
+ local bg_pid=$!
+ sleep 1
+
+ $LFS migrate -m 0 $migrate_dir || {
+ kill -USR1 $bg_pid
+ error "migrate a dir with an open file fails"
+ }
+
+ kill -USR1 $bg_pid
+ wait $bg_pid || error "multiop fails"
+
+ local foo_fid_new=$($LFS path2fid $migrate_dir/foo)
+ [[ "$foo_fid" == "$foo_fid_new" ]] ||
+ error "migrate should skip an open file $foo_fid != $foo_fid_new"
+
+ for file in $(find $migrate_dir); do
+ [[ $file == "$migrate_dir/foo" ]] && continue
+ mdt_index=$($LFS getstripe -m $file)
+ [[ "$mdt_index" == "0" ]] ||
+ error "$file is not on MDT0"
+ done
+ fi
+
rm -rf $DIR/$tdir || error "rm dir failed after migration"
}
run_test 230c "check directory accessiblity if migration failed"
cp /etc/passwd $DIR1/$tdir/$tfile
- #migrate open file should fails
+ # attempt to migrate an open file
multiop_bg_pause $DIR2/$tdir/$tfile O_c || error "open $file failed"
pid=$!
# give multiop a chance to open
sleep 1
- $LFS migrate -m $MDTIDX $DIR1/$tdir &&
- error "migrate open files should failed with open files"
+ local open_file_migrate=false
+ (($MDS1_VERSION >= $(version_code 2.16.50) )) && open_file_migrate=true
- kill -USR1 $pid
+ if $open_file_migrate; then
+ local oldfid=$($LFS path2fid $DIR1/$tdir/$tfile)
+
+ $LFS migrate -m $MDTIDX $DIR1/$tdir ||
+ error "migrate open files should not fail"
+
+ kill -USR1 $pid
+
+ local newfid=$($LFS path2fid $DIR1/$tdir/$tfile)
+
+ [[ "$oldfid" == "$newfid" ]] ||
+ error "FID of the open file changed from $oldfid to $newfid"
- $LFS migrate -m $MDTIDX $DIR1/$tdir ||
+ else
+ $LFS migrate -m $MDTIDX $DIR1/$tdir &&
+ error "migrate open files should failed with open files"
+
+ kill -USR1 $pid
+
+ $LFS migrate -m $MDTIDX $DIR1/$tdir ||
error "migrate remote dir error"
+ fi
echo "Finish migration, then checking.."
for file in $(find $DIR1/$tdir); do
+ $open_file_migrate && [[ "$file" == "$DIR1/$tdir/$tfile" ]] &&
+ continue
mdt_index=$($LFS getstripe -m $file)
[ $mdt_index == $MDTIDX ] ||
error "$file is not on MDT${MDTIDX}"