From 9adc02c016d2c0c1211274cb407637f9b49b4e09 Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Thu, 10 Sep 2020 05:50:11 +0800 Subject: [PATCH 1/1] LU-11631 mdd: migrate symlink for cross-MDT rename If symlink rename is cross MDTs, it's ineffective to turn this symlink into a remote object, instead migrate it to where target MDT is. The following changes are made: * change migration code to allow source and target have different name. * if symlink is renamed to other MDT, and it doesn't have other hard link and target doesn't exist, migrate it to target MDT. * remove mdd_rename_order() which is obsolete. Add sanity 24G. Signed-off-by: Lai Siyao Change-Id: Ib5fafe3122172ac582bbcc907c72a9f391baf0e1 Reviewed-on: https://review.whamcloud.com/39897 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Mike Pershin --- lustre/mdd/mdd_dir.c | 393 +++++++++++++++++++++++++++---------------------- lustre/tests/sanity.sh | 17 +++ 2 files changed, 231 insertions(+), 179 deletions(-) diff --git a/lustre/mdd/mdd_dir.c b/lustre/mdd/mdd_dir.c index 134982d..3f13460 100644 --- a/lustre/mdd/mdd_dir.c +++ b/lustre/mdd/mdd_dir.c @@ -2763,49 +2763,6 @@ out_free: return rc; } -/* - * Get locks on parents in proper order - * RETURN: < 0 - error, rename_order if successful - */ -enum rename_order { - MDD_RN_SAME, - MDD_RN_SRCTGT, - MDD_RN_TGTSRC -}; - -static int mdd_rename_order(const struct lu_env *env, - struct mdd_device *mdd, - struct mdd_object *src_pobj, - const struct lu_attr *pattr, - struct mdd_object *tgt_pobj) -{ - /* order of locking, 1 - tgt-src, 0 - src-tgt*/ - int rc; - - ENTRY; - if (src_pobj == tgt_pobj) - RETURN(MDD_RN_SAME); - - /* compared the parent child relationship of src_p & tgt_p */ - if (lu_fid_eq(&mdd->mdd_root_fid, mdd_object_fid(src_pobj))) { - rc = MDD_RN_SRCTGT; - } else if (lu_fid_eq(&mdd->mdd_root_fid, mdd_object_fid(tgt_pobj))) { - rc = MDD_RN_TGTSRC; - } else { - rc = mdd_is_parent(env, mdd, src_pobj, pattr, - mdd_object_fid(tgt_pobj)); - if (rc == -EREMOTE) - rc = 0; - - if (rc == 1) - rc = MDD_RN_TGTSRC; - else if (rc == 0) - rc = MDD_RN_SRCTGT; - } - - RETURN(rc); -} - /* has not mdd_write{read}_lock on any obj yet. */ static int mdd_rename_sanity_check(const struct lu_env *env, struct mdd_object *src_pobj, @@ -2978,6 +2935,16 @@ static int mdd_declare_rename(const struct lu_env *env, return rc; } +static int mdd_migrate_object(const struct lu_env *env, + struct mdd_object *spobj, + struct mdd_object *tpobj, + struct mdd_object *sobj, + struct mdd_object *tobj, + const struct lu_name *sname, + const struct lu_name *tname, + struct md_op_spec *spec, + struct md_attr *ma); + /* src object can be remote that is why we use only fid and type of object */ static int mdd_rename(const struct lu_env *env, struct md_object *src_pobj, struct md_object *tgt_pobj, @@ -3022,6 +2989,31 @@ static int mdd_rename(const struct lu_env *env, if (rc) GOTO(out_pending, rc); + /* if rename is cross MDTs, migrate symlink if it doesn't have other + * hard links, and target doesn't exist. + */ + if (mdd_object_remote(mdd_sobj) && S_ISLNK(cattr->la_mode) && + cattr->la_nlink == 1 && !tobj) { + struct md_op_spec *spec = &mdd_env_info(env)->mti_spec; + struct lu_device *ld = &mdd->mdd_md_dev.md_lu_dev; + struct lu_fid tfid; + + rc = ld->ld_ops->ldo_fid_alloc(env, ld, &tfid, &tgt_pobj->mo_lu, + NULL); + if (rc < 0) + GOTO(out_pending, rc); + + mdd_tobj = mdd_object_find(env, mdd, &tfid); + if (IS_ERR(mdd_tobj)) + GOTO(out_pending, rc = PTR_ERR(mdd_tobj)); + + memset(spec, 0, sizeof(*spec)); + rc = mdd_migrate_object(env, mdd_spobj, mdd_tpobj, mdd_sobj, + mdd_tobj, lsname, ltname, spec, ma); + mdd_object_put(env, mdd_tobj); + GOTO(out_pending, rc); + } + rc = mdd_la_get(env, mdd_spobj, pattr); if (rc) GOTO(out_pending, rc); @@ -3050,11 +3042,6 @@ static int mdd_rename(const struct lu_env *env, if (rc < 0) GOTO(out_pending, rc); - /* FIXME: Should consider tobj and sobj too in rename_lock. */ - rc = mdd_rename_order(env, mdd, mdd_spobj, pattr, mdd_tpobj); - if (rc < 0) - GOTO(out_pending, rc); - handle = mdd_trans_create(env, mdd); if (IS_ERR(handle)) GOTO(out_pending, rc = PTR_ERR(handle)); @@ -3643,7 +3630,8 @@ static int mdd_migrate_linkea_prepare(const struct lu_env *env, struct mdd_object *spobj, struct mdd_object *tpobj, struct mdd_object *sobj, - const struct lu_name *lname, + const struct lu_name *sname, + const struct lu_name *tname, const struct lu_attr *attr, struct linkea_data *ldata) { @@ -3653,8 +3641,8 @@ static int mdd_migrate_linkea_prepare(const struct lu_env *env, ENTRY; memset(ldata, 0, sizeof(*ldata)); - rc = mdd_linkea_prepare(env, sobj, mdd_object_fid(spobj), lname, - mdd_object_fid(tpobj), lname, 1, 0, ldata); + rc = mdd_linkea_prepare(env, sobj, mdd_object_fid(spobj), sname, + mdd_object_fid(tpobj), tname, 1, 0, ldata); if (rc) RETURN(rc); @@ -3680,7 +3668,7 @@ static int mdd_migrate_linkea_prepare(const struct lu_env *env, if (rc) RETURN(rc); - rc = mdd_iterate_linkea(env, sobj, NULL, lname, mdd_object_fid(tpobj), + rc = mdd_iterate_linkea(env, sobj, NULL, tname, mdd_object_fid(tpobj), ldata, &source_mdt_index, NULL, mdd_is_link_on_source_mdt); RETURN(rc); @@ -3690,7 +3678,8 @@ static int mdd_declare_migrate_update(const struct lu_env *env, struct mdd_object *spobj, struct mdd_object *tpobj, struct mdd_object *obj, - const struct lu_name *lname, + const struct lu_name *sname, + const struct lu_name *tname, struct lu_attr *attr, struct lu_attr *spattr, struct lu_attr *tpattr, @@ -3702,7 +3691,7 @@ static int mdd_declare_migrate_update(const struct lu_env *env, struct lu_attr *la = &info->mti_la_for_fix; int rc; - rc = mdo_declare_index_delete(env, spobj, lname->ln_name, handle); + rc = mdo_declare_index_delete(env, spobj, sname->ln_name, handle); if (rc) return rc; @@ -3714,7 +3703,7 @@ static int mdd_declare_migrate_update(const struct lu_env *env, rc = mdo_declare_index_insert(env, tpobj, mdd_object_fid(obj), attr->la_mode & S_IFMT, - lname->ln_name, handle); + tname->ln_name, handle); if (rc) return rc; @@ -3747,7 +3736,8 @@ static int mdd_declare_migrate_create(const struct lu_env *env, struct mdd_object *tpobj, struct mdd_object *sobj, struct mdd_object *tobj, - const struct lu_name *lname, + const struct lu_name *sname, + const struct lu_name *tname, struct lu_attr *spattr, struct lu_attr *tpattr, struct lu_attr *attr, @@ -3784,7 +3774,7 @@ static int mdd_declare_migrate_create(const struct lu_env *env, mdd_object_make_hint(env, tpobj, tobj, attr, spec, hint); rc = mdd_declare_create(env, mdo2mdd(&tpobj->mod_obj), tpobj, tobj, - lname, attr, handle, spec, ldata, NULL, NULL, + tname, attr, handle, spec, ldata, NULL, NULL, NULL, hint); if (rc) return rc; @@ -3844,7 +3834,7 @@ static int mdd_declare_migrate_create(const struct lu_env *env, } if (!S_ISDIR(attr->la_mode)) { - rc = mdd_iterate_linkea(env, sobj, tobj, lname, + rc = mdd_iterate_linkea(env, sobj, tobj, tname, mdd_object_fid(tpobj), ldata, NULL, handle, mdd_declare_update_link); if (rc) @@ -3867,8 +3857,9 @@ static int mdd_declare_migrate_create(const struct lu_env *env, return rc; } - rc = mdd_declare_migrate_update(env, spobj, tpobj, tobj, lname, attr, - spattr, tpattr, ldata, ma, handle); + rc = mdd_declare_migrate_update(env, spobj, tpobj, tobj, sname, tname, + attr, spattr, tpattr, ldata, ma, + handle); return rc; } @@ -3879,7 +3870,8 @@ static int mdd_migrate_update(const struct lu_env *env, struct mdd_object *spobj, struct mdd_object *tpobj, struct mdd_object *obj, - const struct lu_name *lname, + const struct lu_name *sname, + const struct lu_name *tname, struct lu_attr *attr, struct lu_attr *spattr, struct lu_attr *tpattr, @@ -3893,18 +3885,18 @@ static int mdd_migrate_update(const struct lu_env *env, ENTRY; - CDEBUG(D_INFO, "update "DFID"/%s to "DFID"/"DFID"\n", - PFID(mdd_object_fid(spobj)), lname->ln_name, - PFID(mdd_object_fid(tpobj)), PFID(mdd_object_fid(obj))); + CDEBUG(D_INFO, "update "DFID" from "DFID"/%s to "DFID"/%s\n", + PFID(mdd_object_fid(obj)), PFID(mdd_object_fid(spobj)), + sname->ln_name, PFID(mdd_object_fid(tpobj)), tname->ln_name); - rc = __mdd_index_delete(env, spobj, lname->ln_name, + rc = __mdd_index_delete(env, spobj, sname->ln_name, S_ISDIR(attr->la_mode), handle); if (rc) RETURN(rc); rc = __mdd_index_insert(env, tpobj, mdd_object_fid(obj), attr->la_mode & S_IFMT, - lname->ln_name, handle); + tname->ln_name, handle); if (rc) RETURN(rc); @@ -3960,7 +3952,8 @@ static int mdd_migrate_create(const struct lu_env *env, struct mdd_object *tpobj, struct mdd_object *sobj, struct mdd_object *tobj, - const struct lu_name *lname, + const struct lu_name *sname, + const struct lu_name *tname, struct lu_attr *spattr, struct lu_attr *tpattr, struct lu_attr *attr, @@ -4032,7 +4025,7 @@ static int mdd_migrate_create(const struct lu_env *env, /* update links FID */ if (!S_ISDIR(attr->la_mode)) { - rc = mdd_iterate_linkea(env, sobj, tobj, lname, + rc = mdd_iterate_linkea(env, sobj, tobj, tname, mdd_object_fid(tpobj), ldata, NULL, handle, mdd_update_link); if (rc) @@ -4054,7 +4047,7 @@ static int mdd_migrate_create(const struct lu_env *env, RETURN(rc); } - rc = mdd_migrate_update(env, spobj, tpobj, tobj, lname, attr, + rc = mdd_migrate_update(env, spobj, tpobj, tobj, sname, tname, attr, spattr, tpattr, ldata, ma, handle); RETURN(rc); @@ -4103,7 +4096,7 @@ static int mdd_migrate_cmd_check(struct mdd_device *mdd, } /** - * Migrate directory or file. + * Internal function to migrate directory or file between MDTs. * * migrate source to target in following steps: * 1. create target, append source stripes after target's if it's directory, @@ -4112,39 +4105,38 @@ static int mdd_migrate_cmd_check(struct mdd_device *mdd, * update file linkea, and destroy source if it's not needed any more. * * \param[in] env execution environment - * \param[in] md_pobj parent master object - * \param[in] md_sobj source object - * \param[in] lname file name - * \param[in] md_tobj target object + * \param[in] spobj source parent object + * \param[in] tpobj target parent object + * \param[in] sobj source object + * \param[in] tobj target object + * \param[in] sname source file name + * \param[in] tname target file name * \param[in] spec target creation spec * \param[in] ma used to update \a pobj mtime and ctime * * \retval 0 on success * \retval -errno on failure */ -static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj, - struct md_object *md_sobj, const struct lu_name *lname, - struct md_object *md_tobj, struct md_op_spec *spec, - struct md_attr *ma) +static int mdd_migrate_object(const struct lu_env *env, + struct mdd_object *spobj, + struct mdd_object *tpobj, + struct mdd_object *sobj, + struct mdd_object *tobj, + const struct lu_name *sname, + const struct lu_name *tname, + struct md_op_spec *spec, + struct md_attr *ma) { - struct mdd_device *mdd = mdo2mdd(md_pobj); struct mdd_thread_info *info = mdd_env_info(env); - struct mdd_object *pobj = md2mdd_obj(md_pobj); - struct mdd_object *sobj = md2mdd_obj(md_sobj); - struct mdd_object *tobj = md2mdd_obj(md_tobj); - struct mdd_object *spobj = NULL; - struct mdd_object *tpobj = NULL; + struct mdd_device *mdd = mdo2mdd(&spobj->mod_obj); struct lu_attr *spattr = &info->mti_pattr; struct lu_attr *tpattr = &info->mti_tpattr; struct lu_attr *attr = &info->mti_cattr; struct linkea_data *ldata = &info->mti_link_data; struct dt_allocation_hint *hint = &info->mti_hint; - struct lu_fid *fid = &info->mti_fid2; - struct lu_buf pbuf = { NULL }; struct lu_buf sbuf = { NULL }; struct lmv_mds_md_v1 *lmv; struct thandle *handle; - bool nsonly = false; int rc; ENTRY; @@ -4153,74 +4145,15 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj, if (rc) RETURN(rc); - /* locate source and target stripe on pobj, which are the real parent */ - rc = mdd_stripe_get(env, pobj, &pbuf, XATTR_NAME_LMV); - if (rc < 0 && rc != -ENODATA) - RETURN(rc); - - lmv = pbuf.lb_buf; - if (lmv) { - int index; - - if (!lmv_is_sane(lmv)) - GOTO(out, rc = -EBADF); - - /* locate target parent stripe */ - /* fail check here to make sure top dir migration succeed. */ - if (lmv_is_migrating(lmv) && - OBD_FAIL_CHECK_RESET(OBD_FAIL_MIGRATE_ENTRIES, 0)) - GOTO(out, rc = -EIO); - - index = lmv_name_to_stripe_index(lmv, lname->ln_name, - lname->ln_namelen); - if (index < 0) - GOTO(out, rc = index); - - fid_le_to_cpu(fid, &lmv->lmv_stripe_fids[index]); - tpobj = mdd_object_find(env, mdd, fid); - if (IS_ERR(tpobj)) - GOTO(out, rc = PTR_ERR(tpobj)); - - /* locate source parent stripe */ - if (lmv_is_layout_changing(lmv)) { - index = lmv_name_to_stripe_index_old(lmv, - lname->ln_name, - lname->ln_namelen); - if (index < 0) - GOTO(out, rc = index); - - fid_le_to_cpu(fid, &lmv->lmv_stripe_fids[index]); - spobj = mdd_object_find(env, mdd, fid); - if (IS_ERR(spobj)) - GOTO(out, rc = PTR_ERR(spobj)); - - /* parent stripe unchanged */ - if (spobj == tpobj) { - if (!lmv_is_restriping(lmv)) - GOTO(out, rc = -EINVAL); - GOTO(out, rc = -EALREADY); - } - nsonly = spec->sp_migrate_nsonly; - } else { - spobj = tpobj; - mdd_object_get(spobj); - } - } else { - tpobj = pobj; - spobj = pobj; - mdd_object_get(tpobj); - mdd_object_get(spobj); - } - rc = mdd_la_get(env, spobj, spattr); if (rc) - GOTO(out, rc); + RETURN(rc); rc = mdd_la_get(env, tpobj, tpattr); if (rc) - GOTO(out, rc); + RETURN(rc); - if (S_ISDIR(attr->la_mode) && !nsonly) { + if (S_ISDIR(attr->la_mode) && !spec->sp_migrate_nsonly) { struct lmv_user_md_v1 *lum = spec->u.sp_ea.eadata; LASSERT(lum); @@ -4241,7 +4174,7 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj, GOTO(out, rc = -EBADF); if (lmv_is_migrating(lmv)) { rc = mdd_migrate_cmd_check(mdd, lmv, lum, - lname); + sname); GOTO(out, rc); } } @@ -4250,8 +4183,8 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj, GOTO(out, rc = -EALREADY); /* update namespace only if @sobj is on MDT where @tpobj is. */ - if (!mdd_object_remote(tpobj)) - nsonly = true; + if (!mdd_object_remote(tpobj) && !mdd_object_remote(sobj)) + spec->sp_migrate_nsonly = true; if (S_ISLNK(attr->la_mode)) { lu_buf_check_and_alloc(&sbuf, attr->la_size + 1); @@ -4270,11 +4203,11 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj, } /* linkea needs update upon FID or parent stripe change */ - rc = mdd_migrate_linkea_prepare(env, mdd, spobj, tpobj, sobj, lname, - attr, ldata); + rc = mdd_migrate_linkea_prepare(env, mdd, spobj, tpobj, sobj, sname, + tname, attr, ldata); if (rc > 0) /* update namespace only if @sobj has link on its MDT. */ - nsonly = true; + spec->sp_migrate_nsonly = true; else if (rc < 0) GOTO(out, rc); @@ -4287,53 +4220,155 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj, if (IS_ERR(handle)) GOTO(out, rc = PTR_ERR(handle)); - if (nsonly) - rc = mdd_declare_migrate_update(env, spobj, tpobj, sobj, lname, - attr, spattr, tpattr, ldata, ma, - handle); + if (spec->sp_migrate_nsonly) + rc = mdd_declare_migrate_update(env, spobj, tpobj, sobj, sname, + tname, attr, spattr, tpattr, + ldata, ma, handle); else rc = mdd_declare_migrate_create(env, spobj, tpobj, sobj, tobj, - lname, spattr, tpattr, attr, - &sbuf, ldata, ma, spec, hint, - handle); + sname, tname, spattr, tpattr, + attr, &sbuf, ldata, ma, spec, + hint, handle); if (rc) - GOTO(stop_trans, rc); + GOTO(stop, rc); - rc = mdd_declare_changelog_store(env, mdd, CL_MIGRATE, lname, NULL, + rc = mdd_declare_changelog_store(env, mdd, CL_MIGRATE, tname, sname, handle); if (rc) - GOTO(stop_trans, rc); + GOTO(stop, rc); rc = mdd_trans_start(env, mdd, handle); if (rc) - GOTO(stop_trans, rc); + GOTO(stop, rc); - if (nsonly) - rc = mdd_migrate_update(env, spobj, tpobj, sobj, lname, attr, - spattr, tpattr, ldata, ma, handle); + if (spec->sp_migrate_nsonly) + rc = mdd_migrate_update(env, spobj, tpobj, sobj, sname, tname, + attr, spattr, tpattr, ldata, ma, + handle); else - rc = mdd_migrate_create(env, spobj, tpobj, sobj, tobj, lname, - spattr, tpattr, attr, &sbuf, ldata, ma, - spec, hint, handle); + rc = mdd_migrate_create(env, spobj, tpobj, sobj, tobj, sname, + tname, spattr, tpattr, attr, &sbuf, + ldata, ma, spec, hint, handle); if (rc) - GOTO(stop_trans, rc); + GOTO(stop, rc); rc = mdd_changelog_ns_store(env, mdd, CL_MIGRATE, 0, - nsonly ? sobj : tobj, mdd_object_fid(spobj), - mdd_object_fid(sobj), mdd_object_fid(tpobj), - lname, lname, handle); + spec->sp_migrate_nsonly ? sobj : tobj, + mdd_object_fid(spobj), mdd_object_fid(sobj), + mdd_object_fid(tpobj), tname, sname, + handle); if (rc) - GOTO(stop_trans, rc); + GOTO(stop, rc); EXIT; -stop_trans: +stop: rc = mdd_trans_stop(env, mdd, rc, handle); out: + lu_buf_free(&sbuf); + + return rc; +} + +/** + * Migrate directory or file between MDTs. + * + * \param[in] env execution environment + * \param[in] md_pobj parent master object + * \param[in] md_sobj source object + * \param[in] lname file name + * \param[in] md_tobj target object + * \param[in] spec target creation spec + * \param[in] ma used to update \a pobj mtime and ctime + * + * \retval 0 on success + * \retval -errno on failure + */ +static int mdd_migrate(const struct lu_env *env, struct md_object *md_pobj, + struct md_object *md_sobj, const struct lu_name *lname, + struct md_object *md_tobj, struct md_op_spec *spec, + struct md_attr *ma) +{ + struct mdd_thread_info *info = mdd_env_info(env); + struct mdd_device *mdd = mdo2mdd(md_pobj); + struct mdd_object *pobj = md2mdd_obj(md_pobj); + struct mdd_object *sobj = md2mdd_obj(md_sobj); + struct mdd_object *tobj = md2mdd_obj(md_tobj); + struct mdd_object *spobj = NULL; + struct mdd_object *tpobj = NULL; + struct lu_buf pbuf = { NULL }; + struct lu_fid *fid = &info->mti_fid2; + struct lmv_mds_md_v1 *lmv; + int rc; + + ENTRY; + + /* locate source and target stripe on pobj, which are the real parent */ + rc = mdd_stripe_get(env, pobj, &pbuf, XATTR_NAME_LMV); + if (rc < 0 && rc != -ENODATA) + RETURN(rc); + + lmv = pbuf.lb_buf; + if (lmv) { + int index; + + if (!lmv_is_sane(lmv)) + GOTO(out, rc = -EBADF); + + /* locate target parent stripe */ + /* fail check here to make sure top dir migration succeed. */ + if (lmv_is_migrating(lmv) && + OBD_FAIL_CHECK_RESET(OBD_FAIL_MIGRATE_ENTRIES, 0)) + GOTO(out, rc = -EIO); + + index = lmv_name_to_stripe_index(lmv, lname->ln_name, + lname->ln_namelen); + if (index < 0) + GOTO(out, rc = index); + + fid_le_to_cpu(fid, &lmv->lmv_stripe_fids[index]); + tpobj = mdd_object_find(env, mdd, fid); + if (IS_ERR(tpobj)) + GOTO(out, rc = PTR_ERR(tpobj)); + + /* locate source parent stripe */ + if (lmv_is_layout_changing(lmv)) { + index = lmv_name_to_stripe_index_old(lmv, + lname->ln_name, + lname->ln_namelen); + if (index < 0) + GOTO(out, rc = index); + + fid_le_to_cpu(fid, &lmv->lmv_stripe_fids[index]); + spobj = mdd_object_find(env, mdd, fid); + if (IS_ERR(spobj)) + GOTO(out, rc = PTR_ERR(spobj)); + + /* parent stripe unchanged */ + if (spobj == tpobj) { + if (!lmv_is_restriping(lmv)) + GOTO(out, rc = -EINVAL); + GOTO(out, rc = -EALREADY); + } + } else { + spobj = tpobj; + mdd_object_get(spobj); + } + } else { + tpobj = pobj; + spobj = pobj; + mdd_object_get(tpobj); + mdd_object_get(spobj); + } + + rc = mdd_migrate_object(env, spobj, tpobj, sobj, tobj, lname, lname, + spec, ma); + GOTO(out, rc); + +out: if (!IS_ERR_OR_NULL(spobj)) mdd_object_put(env, spobj); if (!IS_ERR_OR_NULL(tpobj)) mdd_object_put(env, tpobj); - lu_buf_free(&sbuf); lu_buf_free(&pbuf); return rc; diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 70a40dd..d0c70f2 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -1445,6 +1445,23 @@ test_24F () { } run_test 24F "hash order vs readdir (LU-11330)" +test_24G () { + [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" + + local ino1 + local ino2 + + $LFS mkdir -i 0 $DIR/$tdir-0 || error "mkdir $tdir-0" + $LFS mkdir -i 1 $DIR/$tdir-1 || error "mkdir $tdir-1" + touch $DIR/$tdir-0/f1 || error "touch f1" + ln -s $DIR/$tdir-0/f1 $DIR/$tdir-0/s1 || error "ln s1" + ino1=$(stat -c%i $DIR/$tdir-0/s1) + mv $DIR/$tdir-0/s1 $DIR/$tdir-1 || error "mv s1" + ino2=$(stat -c%i $DIR/$tdir-1/s1) + [ $ino1 -ne $ino2 ] || error "s1 should be migrated" +} +run_test 24G "migrate symlink in rename" + test_25a() { echo '== symlink sanity =============================================' -- 1.8.3.1