Whamcloud - gitweb
LU-7091 mdd: refresh nlink after update linkea 36/16236/13
authorDi Wang <di.wang@intel.com>
Wed, 7 Oct 2015 04:31:53 +0000 (21:31 -0700)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 28 Oct 2015 13:48:31 +0000 (13:48 +0000)
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 <di.wang@intel.com>
Change-Id: Icfb4ffc666855f0c7f35f004ecc864c422610135
Reviewed-on: http://review.whamcloud.com/16236
Tested-by: Jenkins
Reviewed-by: John L. Hammond <john.hammond@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/mdd/mdd_dir.c
lustre/mdd/mdd_internal.h
lustre/mdt/mdt_reint.c
lustre/tests/sanity.sh

index 658a4d7..185dad9 100644 (file)
@@ -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);
index aaebfdc..12929d6 100644 (file)
@@ -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 {
index 6480510..7b4af4a 100644 (file)
@@ -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)
index 60da933..0ecc031 100755 (executable)
@@ -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()
 {