From 14ff7815a4658d3c626d5fbdb975659966b5aee4 Mon Sep 17 00:00:00 2001 From: Di Wang Date: Tue, 6 Oct 2015 21:31:53 -0700 Subject: [PATCH] LU-7091 mdd: refresh nlink after update linkea It should refresh nlink after update linkea, because it might decrease the nlink of source object, otherwise it might try to delete the stripeEA with wrong nlink. And also before migration, it should check if all of the parents of the migrating object are in the target MDT, only checking if these parents parent are remote is not enough. Signed-off-by: wang di Change-Id: Icfb4ffc666855f0c7f35f004ecc864c422610135 Reviewed-on: http://review.whamcloud.com/16236 Tested-by: Jenkins Reviewed-by: John L. Hammond Tested-by: Maloo Reviewed-by: Niu Yawei Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- lustre/mdd/mdd_dir.c | 54 +++++++++++++++++++++++++++++++---------------- lustre/mdd/mdd_internal.h | 1 + lustre/mdt/mdt_reint.c | 20 +++++++++++++----- lustre/tests/sanity.sh | 49 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 100 insertions(+), 24 deletions(-) diff --git a/lustre/mdd/mdd_dir.c b/lustre/mdd/mdd_dir.c index 658a4d7..185dad9 100644 --- a/lustre/mdd/mdd_dir.c +++ b/lustre/mdd/mdd_dir.c @@ -3925,6 +3925,12 @@ static int mdd_migrate_update_name(const struct lu_env *env, lname, ldata, handle); if (rc != 0) GOTO(stop_trans, rc); + + /* linkea update might decrease the source object + * nlink, let's get the attr again after ref_del */ + rc = mdd_la_get(env, mdd_sobj, so_attr); + if (rc != 0) + GOTO(stop_trans, rc); } if (S_ISREG(so_attr->la_mode)) { @@ -4004,6 +4010,24 @@ stop_trans: RETURN(rc); } +static int mdd_fld_lookup(const struct lu_env *env, struct mdd_device *mdd, + const struct lu_fid *fid, __u32 *mdt_index) +{ + struct lu_seq_range *range = &mdd_env_info(env)->mti_range; + struct seq_server_site *ss; + int rc; + + ss = mdd->mdd_md_dev.md_lu_dev.ld_site->ld_seq_site; + + range->lsr_flags = LU_SEQ_RANGE_MDT; + rc = fld_server_lookup(env, ss->ss_server_fld, fid->f_seq, range); + if (rc != 0) + return rc; + + *mdt_index = range->lsr_index; + + return 0; +} /** * Check whether we should migrate the file/dir * return val @@ -4020,11 +4044,12 @@ static int mdd_migrate_sanity_check(const struct lu_env *env, { struct mdd_thread_info *info = mdd_env_info(env); struct linkea_data *ldata = &info->mti_link_data; + struct mdd_device *mdd = mdo2mdd(&pobj->mod_obj); int mgr_easize; struct lu_buf *mgr_buf; int count; int rc; - + __u64 mdt_index; ENTRY; mgr_easize = lmv_mds_md_size(2, LMV_MAGIC_V1); @@ -4073,39 +4098,33 @@ static int mdd_migrate_sanity_check(const struct lu_env *env, RETURN(rc); } + mdt_index = mdd->mdd_md_dev.md_lu_dev.ld_site->ld_seq_site->ss_node_id; /* If there are still links locally, then the file will not be * migrated. */ LASSERT(ldata->ld_leh != NULL); ldata->ld_lee = (struct link_ea_entry *)(ldata->ld_leh + 1); for (count = 0; count < ldata->ld_leh->leh_reccount; count++) { - struct mdd_device *mdd = mdo2mdd(&sobj->mod_obj); - struct mdd_object *lpobj; struct lu_name lname; struct lu_fid fid; + __u32 parent_mdt_index; linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, &lname, &fid); ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee + ldata->ld_reclen); - lpobj = mdd_object_find(env, mdd, &fid); - if (IS_ERR(lpobj)) { - CWARN("%s: cannot find obj "DFID": rc = %ld\n", - mdd2obd_dev(mdd)->obd_name, PFID(&fid), - PTR_ERR(lpobj)); - continue; - } - if (!mdd_object_exists(lpobj) || mdd_object_remote(lpobj)) { - CDEBUG(D_INFO, DFID"%.*s: is on remote MDT.\n", - PFID(&fid), lname.ln_namelen, lname.ln_name); - mdd_object_put(env, lpobj); + rc = mdd_fld_lookup(env, mdd, &fid, &parent_mdt_index); + if (rc != 0) + RETURN(rc); + + /* Migrate the object only if none of its parents are on the + * current MDT. */ + if (parent_mdt_index != mdt_index) continue; - } CDEBUG(D_INFO, DFID"still has local entry %.*s "DFID"\n", PFID(mdd_object_fid(sobj)), lname.ln_namelen, lname.ln_name, PFID(&fid)); - mdd_object_put(env, lpobj); rc = 1; break; } @@ -4120,7 +4139,7 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *pobj, struct mdd_object *mdd_pobj = md2mdd_obj(pobj); struct mdd_device *mdd = mdo2mdd(pobj); struct mdd_object *mdd_sobj = md2mdd_obj(sobj); - struct mdd_object *mdd_tobj = NULL; + struct mdd_object *mdd_tobj = md2mdd_obj(tobj); struct lu_attr *so_attr = MDD_ENV_VAR(env, cattr); struct lu_attr *pattr = MDD_ENV_VAR(env, pattr); int rc; @@ -4176,7 +4195,6 @@ static int mdd_migrate(const struct lu_env *env, struct md_object *pobj, /* step 1: Check whether the orphan object has been created, and create * orphan object on the remote MDT if needed */ - mdd_tobj = md2mdd_obj(tobj); if (!mdd_object_exists(mdd_tobj)) { rc = mdd_migrate_create(env, mdd_pobj, mdd_sobj, mdd_tobj, lname, so_attr); diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index aaebfdc..12929d6 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -159,6 +159,7 @@ struct mdd_thread_info { struct md_op_spec mti_spec; struct dt_insert_rec mti_dt_rec; struct lfsck_request mti_lr; + struct lu_seq_range mti_range; }; enum mdd_links_add_overflow { diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index 6480510..7b4af4a 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -1296,27 +1296,33 @@ static int mdt_lock_objects_in_linkea(struct mdt_thread_info *info, linkea_entry_unpack(ldata.ld_lee, &ldata.ld_reclen, &name, &fid); - ldata.ld_lee = (struct link_ea_entry *)((char *)ldata.ld_lee + - ldata.ld_reclen); mdt_pobj = mdt_object_find(info->mti_env, mdt, &fid); if (IS_ERR(mdt_pobj)) { CWARN("%s: cannot find obj "DFID": rc = %ld\n", mdt_obd_name(mdt), PFID(&fid), PTR_ERR(mdt_pobj)); - continue; + goto next; } if (!mdt_object_exists(mdt_pobj)) { CDEBUG(D_INFO, "%s: obj "DFID" does not exist\n", mdt_obd_name(mdt), PFID(&fid)); mdt_object_put(info->mti_env, mdt_pobj); - continue; + goto next; + } + + /* Check if the object already exists in the list */ + list_for_each_entry(mll, lock_list, mll_list) { + if (mll->mll_obj == mdt_pobj) { + mdt_object_put(info->mti_env, mdt_pobj); + goto next; + } } if (mdt_pobj == pobj) { CDEBUG(D_INFO, "%s: skipping parent obj "DFID"\n", mdt_obd_name(mdt), PFID(&fid)); mdt_object_put(info->mti_env, mdt_pobj); - continue; + goto next; } OBD_ALLOC_PTR(mll); @@ -1344,6 +1350,10 @@ static int mdt_lock_objects_in_linkea(struct mdt_thread_info *info, INIT_LIST_HEAD(&mll->mll_list); mll->mll_obj = mdt_pobj; list_add_tail(&mll->mll_list, lock_list); +next: + ldata.ld_lee = (struct link_ea_entry *)((char *)ldata.ld_lee + + ldata.ld_reclen); + } out: if (rc != 0) diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 60da933..0ecc031 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -12996,7 +12996,54 @@ test_230e() { rm -rf $DIR/$tdir || error "rm dir failed after migration" } -run_test 230e "migrate mulitple link files" +run_test 230e "migrate mulitple local link files" + +test_230f() { + [ $PARALLEL == "yes" ] && skip "skip parallel run" && return + [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return + local a_fid + local ln_fid + + mkdir -p $DIR/$tdir + mkdir $DIR/$tdir/migrate_dir + $LFS mkdir -i1 $DIR/$tdir/other_dir + touch $DIR/$tdir/migrate_dir/a + ln $DIR/$tdir/migrate_dir/a $DIR/$tdir/other_dir/ln1 + ln $DIR/$tdir/migrate_dir/a $DIR/$tdir/other_dir/ln2 + + # a should be migrated to MDT1, since no other links on MDT0 + $LFS migrate -m 1 $DIR/$tdir/migrate_dir || + error "migrate dir fails" + mdt_index=$($LFS getstripe -M $DIR/$tdir/migrate_dir) + [ $mdt_index == 1 ] || error "migrate_dir is not on MDT1" + mdt_index=$($LFS getstripe -M $DIR/$tdir/migrate_dir/a) + [ $mdt_index == 1 ] || error "a is not on MDT1" + + # a should stay on MDT1, because it is a mulitple link file + $LFS migrate -m 0 $DIR/$tdir/migrate_dir || + error "migrate dir fails" + mdt_index=$($LFS getstripe -M $DIR/$tdir/migrate_dir/a) + [ $mdt_index == 1 ] || error "a is not on MDT1" + + $LFS migrate -m 1 $DIR/$tdir/migrate_dir || + error "migrate dir fails" + + a_fid=$($LFS path2fid $DIR/$tdir/migrate_dir/a) + ln_fid=$($LFS path2fid $DIR/$tdir/other_dir/ln1) + [ "$a_fid" = "$ln_fid" ] || error "different fid after migrate to MDT1" + + rm -rf $DIR/$tdir/other_dir/ln1 || error "unlink ln1 fails" + rm -rf $DIR/$tdir/other_dir/ln2 || error "unlink ln2 fails" + + # a should be migrated to MDT0, since no other links on MDT1 + $LFS migrate -m 0 $DIR/$tdir/migrate_dir || + error "migrate dir fails" + mdt_index=$($LFS getstripe -M $DIR/$tdir/migrate_dir/a) + [ $mdt_index == 0 ] || error "a is not on MDT0" + + rm -rf $DIR/$tdir || error "rm dir failed after migration" +} +run_test 230f "migrate mulitple remote link files" test_231a() { -- 1.8.3.1