Whamcloud - gitweb
LU-11418 mdd: delete name if orphan doesn't exist 61/33661/7
authorLai Siyao <lai.siyao@intel.com>
Tue, 23 Oct 2018 11:17:20 +0000 (19:17 +0800)
committerOleg Drokin <green@whamcloud.com>
Wed, 23 Jan 2019 09:17:54 +0000 (09:17 +0000)
mdd_orphan_destroy() should delete name if orphan object doesn't
exist, otherwise the orphan clean thread will try to destroy this
orphan in dead loop.

add sanity test_811.

Signed-off-by: Lai Siyao <lai.siyao@whamcloud.com>
Change-Id: Id22b2fab0ac87dfb81ca9f01d8ed0338f1b12120
Reviewed-on: https://review.whamcloud.com/33661
Tested-by: Jenkins
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Hongchao Zhang <hongchao@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/obd_support.h
lustre/mdd/mdd_orphans.c
lustre/tests/sanity.sh

index 3239ba8..60d7c9b 100644 (file)
@@ -250,6 +250,7 @@ extern char obd_jobid_var[];
 #define OBD_FAIL_MDS_TRACK_OVERFLOW     0x162
 #define OBD_FAIL_MDS_LOV_CREATE_RACE    0x163
 #define OBD_FAIL_MDS_HSM_CDT_DELAY      0x164
+#define OBD_FAIL_MDS_ORPHAN_DELETE      0x165
 
 /* layout lock */
 #define OBD_FAIL_MDS_NO_LL_GETATTR      0x170
index 7b99a93..0b33f40 100644 (file)
@@ -210,13 +210,13 @@ int mdd_orphan_declare_delete(const struct lu_env *env, struct mdd_object *obj,
        if (rc)
                return rc;
 
+       if (!mdd_object_exists(obj))
+               return -ENOENT;
+
         rc = mdo_declare_ref_del(env, obj, th);
         if (rc)
                 return rc;
 
-       if (!lu_object_exists(&obj->mod_obj.mo_lu))
-               return -ENOENT;
-
         if (S_ISDIR(mdd_object_type(obj))) {
                 rc = mdo_declare_ref_del(env, obj, th);
                 if (rc)
@@ -244,7 +244,7 @@ int mdd_orphan_delete(const struct lu_env *env, struct mdd_object *obj,
        struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
        struct dt_object *dor = mdd->mdd_orphans;
        struct dt_key *key;
-       int rc;
+       int rc = 0;
 
        ENTRY;
 
@@ -257,12 +257,16 @@ int mdd_orphan_delete(const struct lu_env *env, struct mdd_object *obj,
        key = mdd_orphan_key_fill(env, mdo2fid(obj));
        dt_write_lock(env, mdd->mdd_orphans, MOR_TGT_ORPHAN);
 
+       if (OBD_FAIL_CHECK(OBD_FAIL_MDS_ORPHAN_DELETE))
+               goto ref_del;
+
        rc = dt_delete(env, mdd->mdd_orphans, key, th);
        if (rc == -ENOENT) {
                key = mdd_orphan_key_fill_20(env, mdo2fid(obj));
                rc = dt_delete(env, mdd->mdd_orphans, key, th);
        }
 
+ref_del:
        if (!rc) {
                /* lov objects will be destroyed by caller */
                mdo_ref_del(env, obj, th);
@@ -286,6 +290,7 @@ static int mdd_orphan_destroy(const struct lu_env *env, struct mdd_object *obj,
 {
        struct thandle *th = NULL;
        struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
+       bool orphan_exists = true;
        int rc = 0;
        ENTRY;
 
@@ -298,23 +303,31 @@ static int mdd_orphan_destroy(const struct lu_env *env, struct mdd_object *obj,
                RETURN(rc);
        }
 
+       mdd_write_lock(env, obj, MOR_TGT_CHILD);
        rc = mdd_orphan_declare_delete(env, obj, th);
-       if (rc)
-               GOTO(stop, rc);
-
-       rc = mdo_declare_destroy(env, obj, th);
-       if (rc)
-               GOTO(stop, rc);
+       if (rc == -ENOENT)
+               orphan_exists = false;
+       else if (rc)
+               GOTO(unlock, rc);
+
+       if (orphan_exists) {
+               rc = mdo_declare_destroy(env, obj, th);
+               if (rc)
+                       GOTO(unlock, rc);
+       }
 
        rc = mdd_trans_start(env, mdd, th);
        if (rc)
-               GOTO(stop, rc);
+               GOTO(unlock, rc);
 
-       mdd_write_lock(env, obj, MOR_TGT_CHILD);
        if (likely(obj->mod_count == 0)) {
                dt_write_lock(env, mdd->mdd_orphans, MOR_TGT_ORPHAN);
                rc = dt_delete(env, mdd->mdd_orphans, key, th);
-               if (rc == 0) {
+               if (rc) {
+                       CERROR("%s: could not delete orphan "DFID": rc = %d\n",
+                              mdd2obd_dev(mdd)->obd_name, PFID(mdo2fid(obj)),
+                              rc);
+               } else if (orphan_exists) {
                        mdo_ref_del(env, obj, th);
                        if (S_ISDIR(mdd_object_type(obj))) {
                                mdo_ref_del(env, obj, th);
@@ -322,15 +335,15 @@ static int mdd_orphan_destroy(const struct lu_env *env, struct mdd_object *obj,
                        }
                        rc = mdo_destroy(env, obj, th);
                } else {
-                       CERROR("%s: could not delete orphan "DFID": rc = %d\n",
-                              mdd2obd_dev(mdd)->obd_name, PFID(mdo2fid(obj)),
-                              rc);
+                       CWARN("%s: orphan %s "DFID" doesn't exist\n",
+                             mdd2obd_dev(mdd)->obd_name, (char *)key,
+                             PFID(mdo2fid(obj)));
                }
                dt_write_unlock(env, mdd->mdd_orphans);
        }
+unlock:
        mdd_write_unlock(env, obj);
 
-stop:
        rc = mdd_trans_stop(env, mdd, 0, th);
 
        RETURN(rc);
index 198646b..a378f38 100755 (executable)
@@ -20069,6 +20069,23 @@ test_810() {
 }
 run_test 810 "partial page writes on ZFS (LU-11663)"
 
+test_811() {
+       [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.56) ] &&
+               skip "Need MDS version at least 2.11.56"
+
+       #define OBD_FAIL_MDS_ORPHAN_DELETE      0x165
+       do_facet mds1 $LCTL set_param fail_loc=0x165
+       $MULTIOP $DIR/$tfile Ouc || error "multiop failed"
+
+       stop mds1
+       start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS
+
+       sleep 5
+       [[ $(do_facet mds1 pgrep orph_.*-MDD | wc -l) -eq 0 ]] ||
+               error "MDD orphan cleanup thread not quit"
+}
+run_test 811 "orphan name stub can be cleaned up in startup"
+
 #
 # tests that do cleanup/setup should be run at the end
 #