Whamcloud - gitweb
LU-5519 lfsck: LFSCK code framework adjustment (2)
[fs/lustre-release.git] / lustre / lfsck / lfsck_engine.c
index 8398230..322c122 100644 (file)
@@ -93,19 +93,6 @@ static void lfsck_di_dir_put(const struct lu_env *env, struct lfsck_instance *lf
        iops->put(env, di);
 }
 
-static void lfsck_close_dir(const struct lu_env *env,
-                           struct lfsck_instance *lfsck)
-{
-       struct dt_object        *dir_obj  = lfsck->li_obj_dir;
-       const struct dt_it_ops  *dir_iops = &dir_obj->do_index_ops->dio_it;
-       struct dt_it            *dir_di   = lfsck->li_di_dir;
-
-       lfsck_di_dir_put(env, lfsck);
-       dir_iops->fini(env, dir_di);
-       lfsck->li_obj_dir = NULL;
-       lfsck_object_put(env, dir_obj);
-}
-
 static int lfsck_update_lma(const struct lu_env *env,
                            struct lfsck_instance *lfsck, struct dt_object *obj)
 {
@@ -298,6 +285,77 @@ out:
        return rc;
 }
 
+static int lfsck_load_stripe_lmv(const struct lu_env *env,
+                                struct lfsck_instance *lfsck,
+                                struct dt_object *obj)
+{
+       struct lmv_mds_md_v1    *lmv    = &lfsck_env_info(env)->lti_lmv;
+       struct lfsck_lmv        *llmv;
+       int                      rc;
+       ENTRY;
+
+       LASSERT(lfsck->li_obj_dir == NULL);
+       LASSERT(lfsck->li_lmv == NULL);
+
+       rc = lfsck_read_stripe_lmv(env, obj, lmv);
+       if (rc == -ENODATA) {
+               lfsck->li_obj_dir = lfsck_object_get(obj);
+
+               RETURN(0);
+       }
+
+       if (rc < 0)
+               RETURN(rc);
+
+       OBD_ALLOC_PTR(llmv);
+       if (llmv == NULL)
+               RETURN(-ENOMEM);
+
+       if (lmv->lmv_magic == LMV_MAGIC) {
+               struct lfsck_slave_lmv_rec      *lslr;
+               __u32                            stripes;
+
+               llmv->ll_lmv_master = 1;
+               if (lmv->lmv_stripe_count < 1)
+                       stripes = LFSCK_LMV_DEF_STRIPES;
+               else if (lmv->lmv_stripe_count > LFSCK_LMV_MAX_STRIPES)
+                       stripes = LFSCK_LMV_MAX_STRIPES;
+               else
+                       stripes = lmv->lmv_stripe_count;
+
+               OBD_ALLOC_LARGE(lslr, sizeof(*lslr) * stripes);
+               if (lslr == NULL) {
+                       OBD_FREE_PTR(llmv);
+
+                       RETURN(-ENOMEM);
+               }
+
+               /* Find the object against the bottom device. */
+               obj = lfsck_object_find_by_dev(env, lfsck->li_bottom,
+                                              lfsck_dto2fid(obj));
+               if (IS_ERR(obj)) {
+                       OBD_FREE_LARGE(lslr, sizeof(*lslr) * stripes);
+                       OBD_FREE_PTR(llmv);
+
+                       RETURN(PTR_ERR(obj));
+               }
+
+               llmv->ll_stripes_allocated = stripes;
+               llmv->ll_hash_type = LMV_HASH_TYPE_UNKNOWN;
+               llmv->ll_lslr = lslr;
+               lfsck->li_obj_dir = obj;
+       } else {
+               llmv->ll_lmv_slave = 1;
+               lfsck->li_obj_dir = lfsck_object_get(obj);
+       }
+
+       llmv->ll_lmv = *lmv;
+       atomic_set(&llmv->ll_ref, 1);
+       lfsck->li_lmv = llmv;
+
+       RETURN(0);
+}
+
 /* LFSCK wrap functions */
 
 static void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck,
@@ -310,6 +368,97 @@ static void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck,
        }
 }
 
+static void lfsck_close_dir(const struct lu_env *env,
+                           struct lfsck_instance *lfsck,
+                           int result)
+{
+       struct lfsck_component *com;
+       ENTRY;
+
+       if (lfsck->li_lmv != NULL) {
+               lfsck->li_lmv->ll_exit_value = result;
+               if (lfsck->li_obj_dir != NULL) {
+                       list_for_each_entry(com, &lfsck->li_list_dir,
+                                           lc_link_dir) {
+                               com->lc_ops->lfsck_close_dir(env, com);
+                       }
+               }
+
+               lfsck_lmv_put(env, lfsck->li_lmv);
+               lfsck->li_lmv = NULL;
+       }
+
+       if (lfsck->li_di_dir != NULL) {
+               const struct dt_it_ops  *dir_iops =
+                               &lfsck->li_obj_dir->do_index_ops->dio_it;
+               struct dt_it            *dir_di   = lfsck->li_di_dir;
+
+               lfsck_di_dir_put(env, lfsck);
+               dir_iops->fini(env, dir_di);
+       }
+
+       if (lfsck->li_obj_dir != NULL) {
+               struct dt_object        *dir_obj  = lfsck->li_obj_dir;
+
+               lfsck->li_obj_dir = NULL;
+               lfsck_object_put(env, dir_obj);
+       }
+
+       EXIT;
+}
+
+static int lfsck_open_dir(const struct lu_env *env,
+                         struct lfsck_instance *lfsck, __u64 cookie)
+{
+       struct dt_object        *obj    = lfsck->li_obj_dir;
+       struct dt_it            *di     = lfsck->li_di_dir;
+       struct lfsck_component  *com;
+       const struct dt_it_ops  *iops;
+       int                      rc     = 0;
+       ENTRY;
+
+       LASSERT(obj != NULL);
+       LASSERT(di == NULL);
+
+       if (unlikely(!dt_try_as_dir(env, obj)))
+               GOTO(out, rc = -ENOTDIR);
+
+       list_for_each_entry(com, &lfsck->li_list_dir, lc_link_dir) {
+               rc = com->lc_ops->lfsck_open_dir(env, com);
+               if (rc != 0)
+                       GOTO(out, rc);
+       }
+
+       iops = &obj->do_index_ops->dio_it;
+       di = iops->init(env, obj, lfsck->li_args_dir, BYPASS_CAPA);
+       if (IS_ERR(di))
+               GOTO(out, rc = PTR_ERR(di));
+
+       rc = iops->load(env, di, cookie);
+       if (rc == 0 || (rc > 0 && cookie > 0))
+               rc = iops->next(env, di);
+       else if (rc > 0)
+               rc = 0;
+
+       if (rc != 0) {
+               iops->put(env, di);
+               iops->fini(env, di);
+       } else {
+               lfsck->li_cookie_dir = iops->store(env, di);
+               spin_lock(&lfsck->li_lock);
+               lfsck->li_di_dir = di;
+               spin_unlock(&lfsck->li_lock);
+       }
+
+       GOTO(out, rc);
+
+out:
+       if (rc != 0)
+               lfsck_close_dir(env, lfsck, rc);
+
+       return rc;
+}
+
 static int lfsck_checkpoint(const struct lu_env *env,
                            struct lfsck_instance *lfsck)
 {
@@ -343,7 +492,6 @@ static int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck,
        struct lfsck_position  *pos     = NULL;
        const struct dt_it_ops *iops    =
                                &lfsck->li_obj_oit->do_index_ops->dio_it;
-       struct dt_it           *di;
        int                     rc;
        ENTRY;
 
@@ -394,45 +542,28 @@ static int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck,
            unlikely(!S_ISDIR(lfsck_object_type(obj))))
                GOTO(out, rc = 0);
 
-       if (unlikely(!dt_try_as_dir(env, obj)))
-               GOTO(out, rc = -ENOTDIR);
+       rc = lfsck_load_stripe_lmv(env, lfsck, obj);
+       if (rc == 0) {
+               /* For the master MDT-object of a striped directory,
+                * reset the iteration from the directory beginning. */
+               if (lfsck->li_lmv != NULL && lfsck->li_lmv->ll_lmv_master)
+                       pos->lp_dir_cookie = 0;
 
-       /* Init the namespace-based directory traverse. */
-       iops = &obj->do_index_ops->dio_it;
-       di = iops->init(env, obj, lfsck->li_args_dir, BYPASS_CAPA);
-       if (IS_ERR(di))
-               GOTO(out, rc = PTR_ERR(di));
-
-       LASSERT(pos->lp_dir_cookie < MDS_DIR_END_OFF);
-
-       rc = iops->load(env, di, pos->lp_dir_cookie);
-       if ((rc == 0) || (rc > 0 && pos->lp_dir_cookie > 0))
-               rc = iops->next(env, di);
-       else if (rc > 0)
-               rc = 0;
-
-       if (rc != 0) {
-               iops->put(env, di);
-               iops->fini(env, di);
-               GOTO(out, rc);
+               rc = lfsck_open_dir(env, lfsck, pos->lp_dir_cookie);
        }
 
-       lfsck->li_obj_dir = lfsck_object_get(obj);
-       lfsck->li_cookie_dir = iops->store(env, di);
-       spin_lock(&lfsck->li_lock);
-       lfsck->li_di_dir = di;
-       spin_unlock(&lfsck->li_lock);
-
-       GOTO(out, rc = 0);
+       GOTO(out, rc);
 
 out:
        if (obj != NULL)
                lfsck_object_put(env, obj);
 
-       if (rc < 0) {
+       if (rc != 0) {
+               lfsck_close_dir(env, lfsck, rc);
                list_for_each_entry_safe(com, next, &lfsck->li_list_scan,
-                                        lc_link)
+                                        lc_link) {
                        com->lc_ops->lfsck_post(env, com, rc, true);
+               }
 
                return rc;
        }
@@ -456,8 +587,6 @@ static int lfsck_exec_oit(const struct lu_env *env,
                          struct lfsck_instance *lfsck, struct dt_object *obj)
 {
        struct lfsck_component *com;
-       const struct dt_it_ops *iops;
-       struct dt_it           *di;
        int                     rc;
        ENTRY;
 
@@ -473,38 +602,20 @@ static int lfsck_exec_oit(const struct lu_env *env,
        if (rc <= 0)
                GOTO(out, rc);
 
-       if (unlikely(!dt_try_as_dir(env, obj)))
-               GOTO(out, rc = -ENOTDIR);
-
-       iops = &obj->do_index_ops->dio_it;
-       di = iops->init(env, obj, lfsck->li_args_dir, BYPASS_CAPA);
-       if (IS_ERR(di))
-               GOTO(out, rc = PTR_ERR(di));
-
-       rc = iops->load(env, di, 0);
+       rc = lfsck_load_stripe_lmv(env, lfsck, obj);
        if (rc == 0)
-               rc = iops->next(env, di);
-       else if (rc > 0)
-               rc = 0;
+               rc = lfsck_open_dir(env, lfsck, 0);
 
-       if (rc != 0) {
-               iops->put(env, di);
-               iops->fini(env, di);
-               GOTO(out, rc);
-       }
-
-       lfsck->li_obj_dir = lfsck_object_get(obj);
-       lfsck->li_cookie_dir = iops->store(env, di);
-       spin_lock(&lfsck->li_lock);
-       lfsck->li_di_dir = di;
-       spin_unlock(&lfsck->li_lock);
-
-       GOTO(out, rc = 0);
+       GOTO(out, rc);
 
 out:
        if (rc < 0)
                lfsck_fail(env, lfsck, false);
-       return (rc > 0 ? 0 : rc);
+
+       if (rc != 0)
+               lfsck_close_dir(env, lfsck, rc);
+
+       return rc > 0 ? 0 : rc;
 }
 
 static int lfsck_exec_dir(const struct lu_env *env,
@@ -531,6 +642,7 @@ static int lfsck_post(const struct lu_env *env, struct lfsck_instance *lfsck,
        int                     rc1 = 0;
 
        lfsck_pos_fill(env, lfsck, &lfsck->li_pos_checkpoint, false);
+       lfsck_close_dir(env, lfsck, result);
        list_for_each_entry_safe(com, next, &lfsck->li_list_scan, lc_link) {
                rc = com->lc_ops->lfsck_post(env, com, result, false);
                if (rc != 0)
@@ -699,7 +811,7 @@ checkpoint:
        } while (rc == 0);
 
        if (rc > 0 && !lfsck->li_oit_over)
-               lfsck_close_dir(env, lfsck);
+               lfsck_close_dir(env, lfsck, rc);
 
        RETURN(rc);
 }
@@ -975,9 +1087,8 @@ int lfsck_master_engine(void *args)
 
        if (!OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH))
                rc = lfsck_post(env, lfsck, rc);
-
-       if (lfsck->li_di_dir != NULL)
-               lfsck_close_dir(env, lfsck);
+       else
+               lfsck_close_dir(env, lfsck, rc);
 
 fini_oit:
        lfsck_di_oit_put(env, lfsck);