Whamcloud - gitweb
LU-1267 lfsck: framework (1) for MDT-OST consistency 46/7146/25
authorFan Yong <fan.yong@intel.com>
Thu, 9 Jan 2014 17:35:32 +0000 (01:35 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 17 Jan 2014 04:17:45 +0000 (04:17 +0000)
1) New LFSCK component - lfsck_layout, its data structure, tracing
   file, lFSCK APIs, internal shared functions, and so on.

2) Extend the existing LFSCK:
2.1) new flag - LF_INCOMPLETE, for the case of some target (MDT/OST)
     not join the LFSCK or crashed during the LFSCK.
2.2) New status - LS_PARTIAL, corresponding to above LF_INCOMPLETE,
     if some target (MDT/OST) does not join the LFSCK processing or
     crashed during the LFSCK, when it finished, its status will be
     set as LS_PARTIAL.

3) Control the LFSCK speed by each component itself during the
   second-phase scanning.

4) Avoid lfsck engines to access freed lfsck_instance.

5) Some code cleanup.

Signed-off-by: Fan Yong <fan.yong@intel.com>
Change-Id: I6dc7bb881dc831f6c760be14aac2a066ad75ffec
Reviewed-on: http://review.whamcloud.com/7146
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/lustre_lfsck.h
lustre/lfsck/Makefile.in
lustre/lfsck/lfsck_bookmark.c
lustre/lfsck/lfsck_engine.c
lustre/lfsck/lfsck_internal.h
lustre/lfsck/lfsck_layout.c [new file with mode: 0644]
lustre/lfsck/lfsck_lib.c
lustre/lfsck/lfsck_namespace.c

index f75d507..a833018 100644 (file)
 #include <lu_object.h>
 #include <dt_object.h>
 
+enum lfsck_status {
+       /* The lfsck file is new created, for new MDT, upgrading from old disk,
+        * or re-creating the lfsck file manually. */
+       LS_INIT                 = 0,
+
+       /* The first-step system scanning. */
+       LS_SCANNING_PHASE1      = 1,
+
+       /* The second-step system scanning. */
+       LS_SCANNING_PHASE2      = 2,
+
+       /* The LFSCK processing has completed for all objects. */
+       LS_COMPLETED            = 3,
+
+       /* The LFSCK exited automatically for failure, will not auto restart. */
+       LS_FAILED               = 4,
+
+       /* The LFSCK is stopped manually, will not auto restart. */
+       LS_STOPPED              = 5,
+
+       /* LFSCK is paused automatically when umount,
+        * will be restarted automatically when remount. */
+       LS_PAUSED               = 6,
+
+       /* System crashed during the LFSCK,
+        * will be restarted automatically after recovery. */
+       LS_CRASHED              = 7,
+
+       /* Some OST/MDT failed during the LFSCK, or not join the LFSCK. */
+       LS_PARTIAL              = 8,
+
+       LS_MAX
+};
+
 struct lfsck_start_param {
        struct lfsck_start      *lsp_start;
        struct ldlm_namespace   *lsp_namespace;
@@ -55,6 +89,6 @@ int lfsck_stop(const struct lu_env *env, struct dt_device *key,
 int lfsck_get_speed(struct dt_device *key, void *buf, int len);
 int lfsck_set_speed(struct dt_device *key, int val);
 
-int lfsck_dump(struct dt_device *key, void *buf, int len, __u16 type);
+int lfsck_dump(struct dt_device *key, void *buf, int len, enum lfsck_type type);
 
 #endif /* _LUSTRE_LFSCK_H */
index a703886..c2f5f32 100644 (file)
@@ -1,4 +1,5 @@
 MODULES := lfsck
 lfsck-objs := lfsck_lib.o lfsck_engine.o lfsck_bookmark.o lfsck_namespace.o
+lfsck-objs += lfsck_layout.o
 
 @INCLUDE_RULES@
index d56d5fd..8275bf1 100644 (file)
@@ -74,9 +74,9 @@ static int lfsck_bookmark_load(const struct lu_env *env,
 
                lfsck_bookmark_le_to_cpu(bm, &lfsck->li_bookmark_disk);
                if (bm->lb_magic != LFSCK_BOOKMARK_MAGIC) {
-                       CWARN("%.16s: invalid lfsck_bookmark magic "
-                             "0x%x != 0x%x\n", lfsck_lfsck2name(lfsck),
-                             bm->lb_magic, LFSCK_BOOKMARK_MAGIC);
+                       CWARN("%s: invalid lfsck_bookmark magic %#x != %#x\n",
+                             lfsck_lfsck2name(lfsck), bm->lb_magic,
+                             LFSCK_BOOKMARK_MAGIC);
                        /* Process it as new lfsck_bookmark. */
                        rc = -ENODATA;
                }
@@ -85,7 +85,7 @@ static int lfsck_bookmark_load(const struct lu_env *env,
                        /* return -ENODATA for empty lfsck_bookmark. */
                        rc = -ENODATA;
                else
-                       CERROR("%.16s: fail to load lfsck_bookmark, "
+                       CERROR("%s: fail to load lfsck_bookmark: "
                               "expected = %d, rc = %d\n",
                               lfsck_lfsck2name(lfsck), len, rc);
        }
@@ -106,22 +106,22 @@ int lfsck_bookmark_store(const struct lu_env *env, struct lfsck_instance *lfsck)
        handle = dt_trans_create(env, lfsck->li_bottom);
        if (IS_ERR(handle)) {
                rc = PTR_ERR(handle);
-               CERROR("%.16s: fail to create trans for storing "
-                      "lfsck_bookmark: %d\n,", lfsck_lfsck2name(lfsck), rc);
+               CERROR("%s: fail to create trans for storing lfsck_bookmark: "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
                RETURN(rc);
        }
 
        rc = dt_declare_record_write(env, obj, len, 0, handle);
        if (rc != 0) {
-               CERROR("%.16s: fail to declare trans for storing "
-                      "lfsck_bookmark: %d\n,", lfsck_lfsck2name(lfsck), rc);
+               CERROR("%s: fail to declare trans for storing lfsck_bookmark: "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
                GOTO(out, rc);
        }
 
        rc = dt_trans_start_local(env, lfsck->li_bottom, handle);
        if (rc != 0) {
-               CERROR("%.16s: fail to start trans for storing "
-                      "lfsck_bookmark: %d\n,", lfsck_lfsck2name(lfsck), rc);
+               CERROR("%s: fail to start trans for storing lfsck_bookmark: "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
                GOTO(out, rc);
        }
 
@@ -129,7 +129,7 @@ int lfsck_bookmark_store(const struct lu_env *env, struct lfsck_instance *lfsck)
                             lfsck_buf_get(env, &lfsck->li_bookmark_disk, len),
                             &pos, handle);
        if (rc != 0)
-               CERROR("%.16s: fail to store lfsck_bookmark, expected = %d, "
+               CERROR("%s: fail to store lfsck_bookmark: expected = %d, "
                       "rc = %d\n", lfsck_lfsck2name(lfsck), len, rc);
 
        GOTO(out, rc);
@@ -166,7 +166,12 @@ int lfsck_bookmark_setup(const struct lu_env *env,
        if (IS_ERR(root))
                RETURN(PTR_ERR(root));
 
-       dt_try_as_dir(env, root);
+       if (unlikely(!dt_try_as_dir(env, root))) {
+               lu_object_put(env, &root->do_lu);
+
+               RETURN(-ENOTDIR);
+       }
+
        obj = local_file_find_or_create(env, lfsck->li_los, root,
                                        lfsck_bookmark_name,
                                        S_IFREG | S_IRUGO | S_IWUSR);
index e55c04f..7f8e3fc 100644 (file)
@@ -361,38 +361,33 @@ checkpoint:
 
 int lfsck_master_engine(void *args)
 {
-       struct lu_env            env;
-       struct lfsck_instance   *lfsck    = (struct lfsck_instance *)args;
-       struct ptlrpc_thread    *thread   = &lfsck->li_thread;
-       struct dt_object        *oit_obj  = lfsck->li_obj_oit;
-       const struct dt_it_ops  *oit_iops = &oit_obj->do_index_ops->dio_it;
-       struct dt_it            *oit_di;
-       int                      rc;
+       struct lfsck_thread_args *lta      = args;
+       struct lu_env            *env      = &lta->lta_env;
+       struct lfsck_instance    *lfsck    = lta->lta_lfsck;
+       struct ptlrpc_thread     *thread   = &lfsck->li_thread;
+       struct dt_object         *oit_obj  = lfsck->li_obj_oit;
+       const struct dt_it_ops   *oit_iops = &oit_obj->do_index_ops->dio_it;
+       struct dt_it             *oit_di;
+       int                       rc;
        ENTRY;
 
-       rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD);
-       if (rc != 0) {
-               CERROR("%s: LFSCK, fail to init env, rc = %d\n",
-                      lfsck_lfsck2name(lfsck), rc);
-               GOTO(noenv, rc);
-       }
-
-       oit_di = oit_iops->init(&env, oit_obj, lfsck->li_args_oit, BYPASS_CAPA);
+       oit_di = oit_iops->init(env, oit_obj, lfsck->li_args_oit, BYPASS_CAPA);
        if (IS_ERR(oit_di)) {
                rc = PTR_ERR(oit_di);
-               CERROR("%s: LFSCK, fail to init iteration, rc = %d\n",
+               CERROR("%s: LFSCK, fail to init iteration: rc = %d\n",
                       lfsck_lfsck2name(lfsck), rc);
-               GOTO(fini_env, rc);
+
+               GOTO(fini_args, rc);
        }
 
        spin_lock(&lfsck->li_lock);
        lfsck->li_di_oit = oit_di;
        spin_unlock(&lfsck->li_lock);
-       rc = lfsck_prep(&env, lfsck);
+       rc = lfsck_prep(env, lfsck);
        if (rc != 0)
                GOTO(fini_oit, rc);
 
-       CDEBUG(D_LFSCK, "LFSCK entry: oit_flags = 0x%x, dir_flags = 0x%x, "
+       CDEBUG(D_LFSCK, "LFSCK entry: oit_flags = %#x, dir_flags = %#x, "
               "oit_cookie = "LPU64", dir_cookie = "LPU64", parent = "DFID
               ", pid = %d\n", lfsck->li_args_oit, lfsck->li_args_dir,
               lfsck->li_pos_current.lp_oit_cookie,
@@ -407,11 +402,11 @@ int lfsck_master_engine(void *args)
 
        if (!cfs_list_empty(&lfsck->li_list_scan) ||
            cfs_list_empty(&lfsck->li_list_double_scan))
-               rc = lfsck_master_oit_engine(&env, lfsck);
+               rc = lfsck_master_oit_engine(env, lfsck);
        else
                rc = 1;
 
-       CDEBUG(D_LFSCK, "LFSCK exit: oit_flags = 0x%x, dir_flags = 0x%x, "
+       CDEBUG(D_LFSCK, "LFSCK exit: oit_flags = %#x, dir_flags = %#x, "
               "oit_cookie = "LPU64", dir_cookie = "LPU64", parent = "DFID
               ", pid = %d, rc = %d\n", lfsck->li_args_oit, lfsck->li_args_dir,
               lfsck->li_pos_current.lp_oit_cookie,
@@ -420,29 +415,28 @@ int lfsck_master_engine(void *args)
               current_pid(), rc);
 
        if (!OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH))
-               rc = lfsck_post(&env, lfsck, rc);
+               rc = lfsck_post(env, lfsck, rc);
+
        if (lfsck->li_di_dir != NULL)
-               lfsck_close_dir(&env, lfsck);
+               lfsck_close_dir(env, lfsck);
 
 fini_oit:
-       lfsck_di_oit_put(&env, lfsck);
-       oit_iops->fini(&env, oit_di);
+       lfsck_di_oit_put(env, lfsck);
+       oit_iops->fini(env, oit_di);
        if (rc == 1) {
                if (!cfs_list_empty(&lfsck->li_list_double_scan))
-                       rc = lfsck_double_scan(&env, lfsck);
+                       rc = lfsck_double_scan(env, lfsck);
                else
                        rc = 0;
        }
 
        /* XXX: Purge the pinned objects in the future. */
 
-fini_env:
-       lu_env_fini(&env);
-
-noenv:
+fini_args:
        spin_lock(&lfsck->li_lock);
        thread_set_flags(thread, SVC_STOPPED);
-       wake_up_all(&thread->t_ctl_waitq);
        spin_unlock(&lfsck->li_lock);
+       wake_up_all(&thread->t_ctl_waitq);
+       lfsck_thread_args_fini(lta);
        return rc;
 }
index b316731..3676341 100644 (file)
@@ -36,6 +36,7 @@
 #include <lustre/lustre_lfsck_user.h>
 #include <lustre/lustre_user.h>
 #include <lustre/lustre_idl.h>
+#include <lustre_lfsck.h>
 #include <obd.h>
 #include <lu_object.h>
 #include <dt_object.h>
 #define LFSCK_NAMEENTRY_REMOVED        2 /* The entry has been removed. */
 #define LFSCK_NAMEENTRY_RECREATED      3 /* The entry has been recreated. */
 
-enum lfsck_status {
-       /* The lfsck file is new created, for new MDT, upgrading from old disk,
-        * or re-creating the lfsck file manually. */
-       LS_INIT                 = 0,
-
-       /* The first-step system scanning. */
-       LS_SCANNING_PHASE1      = 1,
-
-       /* The second-step system scanning. */
-       LS_SCANNING_PHASE2      = 2,
-
-       /* The LFSCK processing has completed for all objects. */
-       LS_COMPLETED            = 3,
-
-       /* The LFSCK exited automatically for failure, will not auto restart. */
-       LS_FAILED               = 4,
-
-       /* The LFSCK is stopped manually, will not auto restart. */
-       LS_STOPPED              = 5,
-
-       /* LFSCK is paused automatically when umount,
-        * will be restarted automatically when remount. */
-       LS_PAUSED               = 6,
-
-       /* System crashed during the LFSCK,
-        * will be restarted automatically after recovery. */
-       LS_CRASHED              = 7,
-};
-
 enum lfsck_flags {
        /* Finish the first cycle scanning. */
-       LF_SCANNED_ONCE = 0x00000001ULL,
+       LF_SCANNED_ONCE         = 0x00000001ULL,
 
        /* There is some namespace inconsistency. */
-       LF_INCONSISTENT = 0x00000002ULL,
+       LF_INCONSISTENT         = 0x00000002ULL,
 
        /* The device is upgraded from 1.8 format. */
-       LF_UPGRADE      = 0x00000004ULL,
+       LF_UPGRADE              = 0x00000004ULL,
+
+       /* The server ever restarted during the LFSCK, and may miss to process
+        * some objects check/repair. */
+       LF_INCOMPLETE           = 0x00000008ULL,
 };
 
 struct lfsck_position {
@@ -196,6 +172,78 @@ struct lfsck_namespace {
        __u64   ln_reserved[2];
 };
 
+enum lfsck_layout_inconsistency_type {
+       LLIT_NONE                       = 0,
+       LLIT_DANGLING                   = 1,
+       LLIT_UNMATCHED_PAIR             = 2,
+       LLIT_MULTIPLE_REFERENCED        = 3,
+       LLIT_ORPHAN                     = 4,
+       LLIT_INCONSISTENT_OWNER         = 5,
+       LLIT_OTHERS                     = 6,
+       LLIT_MAX                        = LLIT_OTHERS
+};
+
+struct lfsck_layout {
+       /* Magic number to detect that this struct contains valid data. */
+       __u32   ll_magic;
+
+       /* See 'enum lfsck_status'. */
+       __u32   ll_status;
+
+       /* See 'enum lfsck_flags'. */
+       __u32   ll_flags;
+
+       /* How many completed LFSCK runs on the device. */
+       __u32   ll_success_count;
+
+       /*  How long the LFSCK phase1 has run in seconds. */
+       __u32   ll_run_time_phase1;
+
+       /*  How long the LFSCK phase2 has run in seconds. */
+       __u32   ll_run_time_phase2;
+
+       /* Time for the last LFSCK completed in seconds since epoch. */
+       __u64   ll_time_last_complete;
+
+       /* Time for the latest LFSCK ran in seconds since epoch. */
+       __u64   ll_time_latest_start;
+
+       /* Time for the last LFSCK checkpoint in seconds since epoch. */
+       __u64   ll_time_last_checkpoint;
+
+       /* Position for the latest LFSCK started from. */
+       __u64   ll_pos_latest_start;
+
+       /* Position for the last LFSCK checkpoint. */
+       __u64   ll_pos_last_checkpoint;
+
+       /* Position for the first should be updated object. */
+       __u64   ll_pos_first_inconsistent;
+
+       /* How many objects have been checked. */
+       __u64   ll_objs_checked_phase1;
+
+       /* How many objects failed to be processed. */
+       __u64   ll_objs_failed_phase1;
+
+       /* How many objects have been double scanned. */
+       __u64   ll_objs_checked_phase2;
+
+       /* How many objects failed to be processed during double scan. */
+       __u64   ll_objs_failed_phase2;
+
+       /* kinds of inconsistency have been repaired.
+        * ll_objs_repaired[type - 1] is the count for the given @type. */
+       __u64   ll_objs_repaired[LLIT_MAX];
+
+       /* How many objects have been skipped because of related
+        * MDT(s)/OST(s) do not participate in the LFSCK */
+       __u64   ll_objs_skipped;
+
+       /* For further using. 256-bytes aligned now. */
+       __u64   ll_reserved[12];
+};
+
 struct lfsck_component;
 
 struct lfsck_operations {
@@ -252,10 +300,21 @@ struct lfsck_component {
        struct lfsck_operations *lc_ops;
        void                    *lc_file_ram;
        void                    *lc_file_disk;
+
+       /* The time for last checkpoint, jiffies */
+       cfs_time_t               lc_time_last_checkpoint;
+
+       /* The time for next checkpoint, jiffies */
+       cfs_time_t               lc_time_next_checkpoint;
+
        __u32                    lc_file_size;
 
        /* How many objects have been checked since last checkpoint. */
        __u32                    lc_new_checked;
+
+       /* How many objects have been scanned since last sleep. */
+       __u32                    lc_new_scanned;
+
        unsigned int             lc_journal:1;
        __u16                    lc_type;
 };
@@ -346,6 +405,12 @@ enum lfsck_linkea_flags {
        LLF_REPAIR_FAILED       = 0x02,
 };
 
+struct lfsck_thread_args {
+       struct lu_env            lta_env;
+       struct lfsck_instance   *lta_lfsck;
+       struct lfsck_component  *lta_com;
+};
+
 struct lfsck_thread_info {
        struct lu_name          lti_name;
        struct lu_buf           lti_buf;
@@ -366,8 +431,11 @@ struct lfsck_thread_info {
 };
 
 /* lfsck_lib.c */
+const char *lfsck_status2names(enum lfsck_status status);
 void lfsck_component_cleanup(const struct lu_env *env,
                             struct lfsck_component *com);
+void lfsck_instance_cleanup(const struct lu_env *env,
+                           struct lfsck_instance *lfsck);
 int lfsck_bits_dump(char **buf, int *len, int bits, const char *names[],
                    const char *prefix);
 int lfsck_time_dump(char **buf, int *len, __u64 time, const char *prefix);
@@ -376,8 +444,12 @@ int lfsck_pos_dump(char **buf, int *len, struct lfsck_position *pos,
 void lfsck_pos_fill(const struct lu_env *env, struct lfsck_instance *lfsck,
                    struct lfsck_position *pos, bool init);
 void lfsck_control_speed(struct lfsck_instance *lfsck);
+void lfsck_control_speed_by_self(struct lfsck_component *com);
 int lfsck_reset(const struct lu_env *env, struct lfsck_instance *lfsck,
                bool init);
+struct lfsck_thread_args *lfsck_thread_args_init(struct lfsck_instance *lfsck,
+                                                struct lfsck_component *com);
+void lfsck_thread_args_fini(struct lfsck_thread_args *lta);
 void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck,
                bool new_checked);
 int lfsck_checkpoint(const struct lu_env *env, struct lfsck_instance *lfsck);
@@ -403,7 +475,9 @@ int lfsck_bookmark_setup(const struct lu_env *env,
 int lfsck_namespace_setup(const struct lu_env *env,
                          struct lfsck_instance *lfsck);
 
-extern const char *lfsck_status_names[];
+/* lfsck_layout.c */
+int lfsck_layout_setup(const struct lu_env *env, struct lfsck_instance *lfsck);
+
 extern const char *lfsck_flags_names[];
 extern const char *lfsck_param_names[];
 extern struct lu_context_key lfsck_thread_key;
@@ -551,6 +625,43 @@ static inline void lfsck_object_put(const struct lu_env *env,
        lu_object_put(env, &obj->do_lu);
 }
 
+static inline struct lfsck_component *
+lfsck_component_get(struct lfsck_component *com)
+{
+       atomic_inc(&com->lc_ref);
+
+       return com;
+}
+
+static inline void lfsck_component_put(const struct lu_env *env,
+                                      struct lfsck_component *com)
+{
+       if (atomic_dec_and_test(&com->lc_ref)) {
+               if (com->lc_obj != NULL)
+                       lu_object_put_nocache(env, &com->lc_obj->do_lu);
+               if (com->lc_file_ram != NULL)
+                       OBD_FREE(com->lc_file_ram, com->lc_file_size);
+               if (com->lc_file_disk != NULL)
+                       OBD_FREE(com->lc_file_disk, com->lc_file_size);
+               OBD_FREE_PTR(com);
+       }
+}
+
+static inline struct lfsck_instance *
+lfsck_instance_get(struct lfsck_instance *lfsck)
+{
+       atomic_inc(&lfsck->li_ref);
+
+       return lfsck;
+}
+
+static inline void lfsck_instance_put(const struct lu_env *env,
+                                     struct lfsck_instance *lfsck)
+{
+       if (atomic_dec_and_test(&lfsck->li_ref))
+               lfsck_instance_cleanup(env, lfsck);
+}
+
 static inline mdsno_t lfsck_dev_idx(struct dt_device *dev)
 {
        return dev->dd_lu_dev.ld_site->ld_seq_site->ss_node_id;
diff --git a/lustre/lfsck/lfsck_layout.c b/lustre/lfsck/lfsck_layout.c
new file mode 100644 (file)
index 0000000..402cca7
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2 for more details.  A copy is
+ * included in the COPYING file that accompanied this code.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2013, Intel Corporation.
+ */
+/*
+ * lustre/lfsck/lfsck_layout.c
+ *
+ * Author: Fan, Yong <fan.yong@intel.com>
+ */
+
+#ifndef EXPORT_SYMTAB
+# define EXPORT_SYMTAB
+#endif
+#define DEBUG_SUBSYSTEM S_LFSCK
+
+#include <linux/bitops.h>
+
+#include <lustre/lustre_idl.h>
+#include <lu_object.h>
+#include <dt_object.h>
+#include <lustre_linkea.h>
+#include <lustre_fid.h>
+#include <lustre_lib.h>
+#include <lustre_net.h>
+#include <lustre/lustre_user.h>
+
+#include "lfsck_internal.h"
+
+#define LFSCK_LAYOUT_MAGIC             0xB173AE14
+
+static const char lfsck_layout_name[] = "lfsck_layout";
+
+static void lfsck_layout_le_to_cpu(struct lfsck_layout *des,
+                                  const struct lfsck_layout *src)
+{
+       int i;
+
+       des->ll_magic = le32_to_cpu(src->ll_magic);
+       des->ll_status = le32_to_cpu(src->ll_status);
+       des->ll_flags = le32_to_cpu(src->ll_flags);
+       des->ll_success_count = le32_to_cpu(src->ll_success_count);
+       des->ll_run_time_phase1 = le32_to_cpu(src->ll_run_time_phase1);
+       des->ll_run_time_phase2 = le32_to_cpu(src->ll_run_time_phase2);
+       des->ll_time_last_complete = le64_to_cpu(src->ll_time_last_complete);
+       des->ll_time_latest_start = le64_to_cpu(src->ll_time_latest_start);
+       des->ll_time_last_checkpoint =
+                               le64_to_cpu(src->ll_time_last_checkpoint);
+       des->ll_pos_latest_start = le64_to_cpu(src->ll_pos_latest_start);
+       des->ll_pos_last_checkpoint = le64_to_cpu(src->ll_pos_last_checkpoint);
+       des->ll_pos_first_inconsistent =
+                       le64_to_cpu(src->ll_pos_first_inconsistent);
+       des->ll_objs_checked_phase1 = le64_to_cpu(src->ll_objs_checked_phase1);
+       des->ll_objs_failed_phase1 = le64_to_cpu(src->ll_objs_failed_phase1);
+       des->ll_objs_checked_phase2 = le64_to_cpu(src->ll_objs_checked_phase2);
+       des->ll_objs_failed_phase2 = le64_to_cpu(src->ll_objs_failed_phase2);
+       for (i = 0; i < LLIT_MAX; i++)
+               des->ll_objs_repaired[i] =
+                               le64_to_cpu(src->ll_objs_repaired[i]);
+       des->ll_objs_skipped = le64_to_cpu(src->ll_objs_skipped);
+}
+
+static void lfsck_layout_cpu_to_le(struct lfsck_layout *des,
+                                  const struct lfsck_layout *src)
+{
+       int i;
+
+       des->ll_magic = cpu_to_le32(src->ll_magic);
+       des->ll_status = cpu_to_le32(src->ll_status);
+       des->ll_flags = cpu_to_le32(src->ll_flags);
+       des->ll_success_count = cpu_to_le32(src->ll_success_count);
+       des->ll_run_time_phase1 = cpu_to_le32(src->ll_run_time_phase1);
+       des->ll_run_time_phase2 = cpu_to_le32(src->ll_run_time_phase2);
+       des->ll_time_last_complete = cpu_to_le64(src->ll_time_last_complete);
+       des->ll_time_latest_start = cpu_to_le64(src->ll_time_latest_start);
+       des->ll_time_last_checkpoint =
+                               cpu_to_le64(src->ll_time_last_checkpoint);
+       des->ll_pos_latest_start = cpu_to_le64(src->ll_pos_latest_start);
+       des->ll_pos_last_checkpoint = cpu_to_le64(src->ll_pos_last_checkpoint);
+       des->ll_pos_first_inconsistent =
+                       cpu_to_le64(src->ll_pos_first_inconsistent);
+       des->ll_objs_checked_phase1 = cpu_to_le64(src->ll_objs_checked_phase1);
+       des->ll_objs_failed_phase1 = cpu_to_le64(src->ll_objs_failed_phase1);
+       des->ll_objs_checked_phase2 = cpu_to_le64(src->ll_objs_checked_phase2);
+       des->ll_objs_failed_phase2 = cpu_to_le64(src->ll_objs_failed_phase2);
+       for (i = 0; i < LLIT_MAX; i++)
+               des->ll_objs_repaired[i] =
+                               cpu_to_le64(src->ll_objs_repaired[i]);
+       des->ll_objs_skipped = cpu_to_le64(src->ll_objs_skipped);
+}
+
+/**
+ * \retval +ve: the lfsck_layout is broken, the caller should reset it.
+ * \retval 0: succeed.
+ * \retval -ve: failed cases.
+ */
+static int lfsck_layout_load(const struct lu_env *env,
+                            struct lfsck_component *com)
+{
+       struct lfsck_layout             *lo     = com->lc_file_ram;
+       const struct dt_body_operations *dbo    = com->lc_obj->do_body_ops;
+       ssize_t                          size   = com->lc_file_size;
+       loff_t                           pos    = 0;
+       int                              rc;
+
+       rc = dbo->dbo_read(env, com->lc_obj,
+                          lfsck_buf_get(env, com->lc_file_disk, size), &pos,
+                          BYPASS_CAPA);
+       if (rc == 0) {
+               return -ENOENT;
+       } else if (rc < 0) {
+               CWARN("%s: failed to load lfsck_layout: rc = %d\n",
+                     lfsck_lfsck2name(com->lc_lfsck), rc);
+               return rc;
+       } else if (rc != size) {
+               CWARN("%s: crashed lfsck_layout, to be reset: rc = %d\n",
+                     lfsck_lfsck2name(com->lc_lfsck), rc);
+               return 1;
+       }
+
+       lfsck_layout_le_to_cpu(lo, com->lc_file_disk);
+       if (lo->ll_magic != LFSCK_LAYOUT_MAGIC) {
+               CWARN("%s: invalid lfsck_layout magic %#x != %#x, "
+                     "to be reset\n", lfsck_lfsck2name(com->lc_lfsck),
+                     lo->ll_magic, LFSCK_LAYOUT_MAGIC);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int lfsck_layout_store(const struct lu_env *env,
+                             struct lfsck_component *com)
+{
+       struct dt_object         *obj           = com->lc_obj;
+       struct lfsck_instance    *lfsck         = com->lc_lfsck;
+       struct lfsck_layout      *lo            = com->lc_file_disk;
+       struct thandle           *handle;
+       ssize_t                   size          = com->lc_file_size;
+       loff_t                    pos           = 0;
+       int                       rc;
+       ENTRY;
+
+       lfsck_layout_cpu_to_le(lo, com->lc_file_ram);
+       handle = dt_trans_create(env, lfsck->li_bottom);
+       if (IS_ERR(handle)) {
+               rc = PTR_ERR(handle);
+               CERROR("%s: fail to create trans for storing lfsck_layout: "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
+               RETURN(rc);
+       }
+
+       rc = dt_declare_record_write(env, obj, size, pos, handle);
+       if (rc != 0) {
+               CERROR("%s: fail to declare trans for storing lfsck_layout(1): "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
+               GOTO(out, rc);
+       }
+
+       rc = dt_trans_start_local(env, lfsck->li_bottom, handle);
+       if (rc != 0) {
+               CERROR("%s: fail to start trans for storing lfsck_layout: "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
+               GOTO(out, rc);
+       }
+
+       rc = dt_record_write(env, obj, lfsck_buf_get(env, lo, size), &pos,
+                            handle);
+       if (rc != 0)
+               CERROR("%s: fail to store lfsck_layout(1): size = %d, "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), (int)size, rc);
+
+       GOTO(out, rc);
+
+out:
+       dt_trans_stop(env, lfsck->li_bottom, handle);
+
+       return rc;
+}
+
+static int lfsck_layout_init(const struct lu_env *env,
+                            struct lfsck_component *com)
+{
+       struct lfsck_layout *lo = com->lc_file_ram;
+       int rc;
+
+       memset(lo, 0, com->lc_file_size);
+       lo->ll_magic = LFSCK_LAYOUT_MAGIC;
+       lo->ll_status = LS_INIT;
+       down_write(&com->lc_sem);
+       rc = lfsck_layout_store(env, com);
+       up_write(&com->lc_sem);
+
+       return rc;
+}
+
+/* layout APIs */
+/* XXX: Some to be implemented in other patch(es). */
+
+static int lfsck_layout_reset(const struct lu_env *env,
+                             struct lfsck_component *com, bool init)
+{
+       struct lfsck_layout     *lo    = com->lc_file_ram;
+       int                      rc;
+
+       down_write(&com->lc_sem);
+       if (init) {
+               memset(lo, 0, com->lc_file_size);
+       } else {
+               __u32 count = lo->ll_success_count;
+               __u64 last_time = lo->ll_time_last_complete;
+
+               memset(lo, 0, com->lc_file_size);
+               lo->ll_success_count = count;
+               lo->ll_time_last_complete = last_time;
+       }
+
+       lo->ll_magic = LFSCK_LAYOUT_MAGIC;
+       lo->ll_status = LS_INIT;
+
+       rc = lfsck_layout_store(env, com);
+       up_write(&com->lc_sem);
+
+       return rc;
+}
+
+static void lfsck_layout_fail(const struct lu_env *env,
+                             struct lfsck_component *com, bool new_checked)
+{
+}
+
+static int lfsck_layout_checkpoint(const struct lu_env *env,
+                                  struct lfsck_component *com, bool init)
+{
+       return 0;
+}
+
+static int lfsck_layout_master_prep(const struct lu_env *env,
+                                   struct lfsck_component *com)
+{
+       return 0;
+}
+
+static int lfsck_layout_slave_prep(const struct lu_env *env,
+                                  struct lfsck_component *com)
+{
+       return 0;
+}
+
+static int lfsck_layout_master_exec_oit(const struct lu_env *env,
+                                       struct lfsck_component *com,
+                                       struct dt_object *obj)
+{
+       return 0;
+}
+
+static int lfsck_layout_slave_exec_oit(const struct lu_env *env,
+                                      struct lfsck_component *com,
+                                      struct dt_object *obj)
+{
+       return 0;
+}
+
+static int lfsck_layout_exec_dir(const struct lu_env *env,
+                                struct lfsck_component *com,
+                                struct dt_object *obj,
+                                struct lu_dirent *ent)
+{
+       return 0;
+}
+
+static int lfsck_layout_master_post(const struct lu_env *env,
+                                   struct lfsck_component *com,
+                                   int result, bool init)
+{
+       return 0;
+}
+
+static int lfsck_layout_slave_post(const struct lu_env *env,
+                                  struct lfsck_component *com,
+                                  int result, bool init)
+{
+       return 0;
+}
+
+static int lfsck_layout_dump(const struct lu_env *env,
+                            struct lfsck_component *com, char *buf, int len)
+{
+       return 0;
+}
+
+static int lfsck_layout_master_double_scan(const struct lu_env *env,
+                                          struct lfsck_component *com)
+{
+       return 0;
+}
+
+static int lfsck_layout_slave_double_scan(const struct lu_env *env,
+                                         struct lfsck_component *com)
+{
+       return 0;
+}
+
+static struct lfsck_operations lfsck_layout_master_ops = {
+       .lfsck_reset            = lfsck_layout_reset,
+       .lfsck_fail             = lfsck_layout_fail,
+       .lfsck_checkpoint       = lfsck_layout_checkpoint,
+       .lfsck_prep             = lfsck_layout_master_prep,
+       .lfsck_exec_oit         = lfsck_layout_master_exec_oit,
+       .lfsck_exec_dir         = lfsck_layout_exec_dir,
+       .lfsck_post             = lfsck_layout_master_post,
+       .lfsck_dump             = lfsck_layout_dump,
+       .lfsck_double_scan      = lfsck_layout_master_double_scan,
+};
+
+static struct lfsck_operations lfsck_layout_slave_ops = {
+       .lfsck_reset            = lfsck_layout_reset,
+       .lfsck_fail             = lfsck_layout_fail,
+       .lfsck_checkpoint       = lfsck_layout_checkpoint,
+       .lfsck_prep             = lfsck_layout_slave_prep,
+       .lfsck_exec_oit         = lfsck_layout_slave_exec_oit,
+       .lfsck_exec_dir         = lfsck_layout_exec_dir,
+       .lfsck_post             = lfsck_layout_slave_post,
+       .lfsck_dump             = lfsck_layout_dump,
+       .lfsck_double_scan      = lfsck_layout_slave_double_scan,
+};
+
+int lfsck_layout_setup(const struct lu_env *env, struct lfsck_instance *lfsck)
+{
+       struct lfsck_component  *com;
+       struct lfsck_layout     *lo;
+       struct dt_object        *root = NULL;
+       struct dt_object        *obj;
+       int                      rc;
+       ENTRY;
+
+       OBD_ALLOC_PTR(com);
+       if (com == NULL)
+               RETURN(-ENOMEM);
+
+       INIT_LIST_HEAD(&com->lc_link);
+       INIT_LIST_HEAD(&com->lc_link_dir);
+       init_rwsem(&com->lc_sem);
+       atomic_set(&com->lc_ref, 1);
+       com->lc_lfsck = lfsck;
+       com->lc_type = LT_LAYOUT;
+       if (lfsck->li_master)
+               com->lc_ops = &lfsck_layout_master_ops;
+       else
+               com->lc_ops = &lfsck_layout_slave_ops;
+       com->lc_file_size = sizeof(*lo);
+       OBD_ALLOC(com->lc_file_ram, com->lc_file_size);
+       if (com->lc_file_ram == NULL)
+               GOTO(out, rc = -ENOMEM);
+
+       OBD_ALLOC(com->lc_file_disk, com->lc_file_size);
+       if (com->lc_file_disk == NULL)
+               GOTO(out, rc = -ENOMEM);
+
+       root = dt_locate(env, lfsck->li_bottom, &lfsck->li_local_root_fid);
+       if (IS_ERR(root))
+               GOTO(out, rc = PTR_ERR(root));
+
+       if (unlikely(!dt_try_as_dir(env, root)))
+               GOTO(out, rc = -ENOTDIR);
+
+       obj = local_file_find_or_create(env, lfsck->li_los, root,
+                                       lfsck_layout_name,
+                                       S_IFREG | S_IRUGO | S_IWUSR);
+       if (IS_ERR(obj))
+               GOTO(out, rc = PTR_ERR(obj));
+
+       com->lc_obj = obj;
+       rc = lfsck_layout_load(env, com);
+       if (rc > 0)
+               rc = lfsck_layout_reset(env, com, true);
+       else if (rc == -ENOENT)
+               rc = lfsck_layout_init(env, com);
+
+       if (rc != 0)
+               GOTO(out, rc);
+
+       lo = com->lc_file_ram;
+       switch (lo->ll_status) {
+       case LS_INIT:
+       case LS_COMPLETED:
+       case LS_FAILED:
+       case LS_STOPPED:
+       case LS_PARTIAL:
+               spin_lock(&lfsck->li_lock);
+               list_add_tail(&com->lc_link, &lfsck->li_list_idle);
+               spin_unlock(&lfsck->li_lock);
+               break;
+       default:
+               CERROR("%s: unknown lfsck_layout status: rc = %u\n",
+                      lfsck_lfsck2name(lfsck), lo->ll_status);
+               /* fall through */
+       case LS_SCANNING_PHASE1:
+       case LS_SCANNING_PHASE2:
+               /* No need to store the status to disk right now.
+                * If the system crashed before the status stored,
+                * it will be loaded back when next time. */
+               lo->ll_status = LS_CRASHED;
+               lo->ll_flags |= LF_INCOMPLETE;
+               /* fall through */
+       case LS_PAUSED:
+       case LS_CRASHED:
+               spin_lock(&lfsck->li_lock);
+               list_add_tail(&com->lc_link, &lfsck->li_list_scan);
+               spin_unlock(&lfsck->li_lock);
+               break;
+       }
+
+       GOTO(out, rc = 0);
+
+out:
+       if (root != NULL && !IS_ERR(root))
+               lu_object_put(env, &root->do_lu);
+
+       if (rc != 0)
+               lfsck_component_cleanup(env, com);
+
+       return rc;
+}
index a4c963c..37efbcc 100644 (file)
@@ -60,48 +60,39 @@ LU_KEY_INIT_GENERIC(lfsck);
 static CFS_LIST_HEAD(lfsck_instance_list);
 static DEFINE_SPINLOCK(lfsck_instance_lock);
 
-const char *lfsck_status_names[] = {
-       "init",
-       "scanning-phase1",
-       "scanning-phase2",
-       "completed",
-       "failed",
-       "stopped",
-       "paused",
-       "crashed",
-       NULL
+static const char *lfsck_status_names[] = {
+       [LS_INIT]               = "init",
+       [LS_SCANNING_PHASE1]    = "scanning-phase1",
+       [LS_SCANNING_PHASE2]    = "scanning-phase2",
+       [LS_COMPLETED]          = "completed",
+       [LS_FAILED]             = "failed",
+       [LS_STOPPED]            = "stopped",
+       [LS_PAUSED]             = "paused",
+       [LS_CRASHED]            = "crashed",
+       [LS_PARTIAL]            = "partial"
 };
 
 const char *lfsck_flags_names[] = {
        "scanned-once",
        "inconsistent",
        "upgrade",
+       "incomplete",
        NULL
 };
 
 const char *lfsck_param_names[] = {
+       NULL,
        "failout",
        "dryrun",
        NULL
 };
 
-static inline void lfsck_component_get(struct lfsck_component *com)
+const char *lfsck_status2names(enum lfsck_status status)
 {
-       atomic_inc(&com->lc_ref);
-}
+       if (unlikely(status < 0 || status >= LS_MAX))
+               return "unknown";
 
-static inline void lfsck_component_put(const struct lu_env *env,
-                                      struct lfsck_component *com)
-{
-       if (atomic_dec_and_test(&com->lc_ref)) {
-               if (com->lc_obj != NULL)
-                       lu_object_put_nocache(env, &com->lc_obj->do_lu);
-               if (com->lc_file_ram != NULL)
-                       OBD_FREE(com->lc_file_ram, com->lc_file_size);
-               if (com->lc_file_disk != NULL)
-                       OBD_FREE(com->lc_file_disk, com->lc_file_size);
-               OBD_FREE_PTR(com);
-       }
+       return lfsck_status_names[status];
 }
 
 static inline struct lfsck_component *
@@ -151,8 +142,8 @@ void lfsck_component_cleanup(const struct lu_env *env,
        lfsck_component_put(env, com);
 }
 
-static void lfsck_instance_cleanup(const struct lu_env *env,
-                                  struct lfsck_instance *lfsck)
+void lfsck_instance_cleanup(const struct lu_env *env,
+                           struct lfsck_instance *lfsck)
 {
        struct ptlrpc_thread    *thread = &lfsck->li_thread;
        struct lfsck_component  *com;
@@ -204,18 +195,6 @@ static void lfsck_instance_cleanup(const struct lu_env *env,
        OBD_FREE_PTR(lfsck);
 }
 
-static inline void lfsck_instance_get(struct lfsck_instance *lfsck)
-{
-       atomic_inc(&lfsck->li_ref);
-}
-
-static inline void lfsck_instance_put(const struct lu_env *env,
-                                     struct lfsck_instance *lfsck)
-{
-       if (atomic_dec_and_test(&lfsck->li_ref))
-               lfsck_instance_cleanup(env, lfsck);
-}
-
 static inline struct lfsck_instance *lfsck_instance_find(struct dt_device *key,
                                                         bool ref, bool unlink)
 {
@@ -270,13 +249,15 @@ int lfsck_bits_dump(char **buf, int *len, int bits, const char *names[],
        for (i = 0, flag = 1; bits != 0; i++, flag = 1 << i) {
                if (flag & bits) {
                        bits &= ~flag;
-                       rc = snprintf(*buf, *len, "%s%c", names[i],
-                                     bits != 0 ? ',' : '\n');
-                       if (rc <= 0)
-                               return -ENOSPC;
-
-                       *buf += rc;
-                       *len -= rc;
+                       if (names[i] != NULL) {
+                               rc = snprintf(*buf, *len, "%s%c", names[i],
+                                             bits != 0 ? ',' : '\n');
+                               if (rc <= 0)
+                                       return -ENOSPC;
+
+                               *buf += rc;
+                               *len -= rc;
+                       }
                }
        }
        return save - *len;
@@ -350,7 +331,7 @@ void lfsck_pos_fill(const struct lu_env *env, struct lfsck_instance *lfsck,
                        fid_zero(&pos->lp_dir_parent);
                        pos->lp_dir_cookie = 0;
                } else {
-                       pos->lp_dir_parent = *lu_object_fid(&dto->do_lu);
+                       pos->lp_dir_parent = *lfsck_dto2fid(dto);
                }
        } else {
                fid_zero(&pos->lp_dir_parent);
@@ -382,20 +363,31 @@ void lfsck_control_speed(struct lfsck_instance *lfsck)
 
        if (lfsck->li_sleep_jif > 0 &&
            lfsck->li_new_scanned >= lfsck->li_sleep_rate) {
-               spin_lock(&lfsck->li_lock);
-               if (likely(lfsck->li_sleep_jif > 0 &&
-                          lfsck->li_new_scanned >= lfsck->li_sleep_rate)) {
-                       lwi = LWI_TIMEOUT_INTR(lfsck->li_sleep_jif, NULL,
-                                              LWI_ON_SIGNAL_NOOP, NULL);
-                       spin_unlock(&lfsck->li_lock);
-
-                       l_wait_event(thread->t_ctl_waitq,
-                                    !thread_is_running(thread),
-                                    &lwi);
-                       lfsck->li_new_scanned = 0;
-               } else {
-                       spin_unlock(&lfsck->li_lock);
-               }
+               lwi = LWI_TIMEOUT_INTR(lfsck->li_sleep_jif, NULL,
+                                      LWI_ON_SIGNAL_NOOP, NULL);
+
+               l_wait_event(thread->t_ctl_waitq,
+                            !thread_is_running(thread),
+                            &lwi);
+               lfsck->li_new_scanned = 0;
+       }
+}
+
+void lfsck_control_speed_by_self(struct lfsck_component *com)
+{
+       struct lfsck_instance   *lfsck  = com->lc_lfsck;
+       struct ptlrpc_thread    *thread = &lfsck->li_thread;
+       struct l_wait_info       lwi;
+
+       if (lfsck->li_sleep_jif > 0 &&
+           com->lc_new_scanned >= lfsck->li_sleep_rate) {
+               lwi = LWI_TIMEOUT_INTR(lfsck->li_sleep_jif, NULL,
+                                      LWI_ON_SIGNAL_NOOP, NULL);
+
+               l_wait_event(thread->t_ctl_waitq,
+                            !thread_is_running(thread),
+                            &lwi);
+               com->lc_new_scanned = 0;
        }
 }
 
@@ -496,6 +488,38 @@ static int lfsck_needs_scan_dir(const struct lu_env *env,
        return 0;
 }
 
+struct lfsck_thread_args *lfsck_thread_args_init(struct lfsck_instance *lfsck,
+                                                struct lfsck_component *com)
+{
+       struct lfsck_thread_args *lta;
+       int                       rc;
+
+       OBD_ALLOC_PTR(lta);
+       if (lta == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       rc = lu_env_init(&lta->lta_env, LCT_MD_THREAD | LCT_DT_THREAD);
+       if (rc != 0) {
+               OBD_FREE_PTR(lta);
+               return ERR_PTR(rc);
+       }
+
+       lta->lta_lfsck = lfsck_instance_get(lfsck);
+       if (com != NULL)
+               lta->lta_com = lfsck_component_get(com);
+
+       return lta;
+}
+
+void lfsck_thread_args_fini(struct lfsck_thread_args *lta)
+{
+       if (lta->lta_com != NULL)
+               lfsck_component_put(&lta->lta_env, lta->lta_com);
+       lfsck_instance_put(&lta->lta_env, lta->lta_lfsck);
+       lu_env_fini(&lta->lta_env);
+       OBD_FREE_PTR(lta);
+}
+
 /* LFSCK wrap functions */
 
 void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck,
@@ -511,7 +535,8 @@ void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck,
 int lfsck_checkpoint(const struct lu_env *env, struct lfsck_instance *lfsck)
 {
        struct lfsck_component *com;
-       int                     rc;
+       int                     rc  = 0;
+       int                     rc1 = 0;
 
        if (likely(cfs_time_beforeq(cfs_time_current(),
                                    lfsck->li_time_next_checkpoint)))
@@ -521,13 +546,13 @@ int lfsck_checkpoint(const struct lu_env *env, struct lfsck_instance *lfsck)
        cfs_list_for_each_entry(com, &lfsck->li_list_scan, lc_link) {
                rc = com->lc_ops->lfsck_checkpoint(env, com, false);
                if (rc != 0)
-                       return rc;;
+                       rc1 = rc;
        }
 
        lfsck->li_time_last_checkpoint = cfs_time_current();
        lfsck->li_time_next_checkpoint = lfsck->li_time_last_checkpoint +
                                cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL);
-       return 0;
+       return rc1 != 0 ? rc1 : rc;
 }
 
 int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck)
@@ -553,7 +578,7 @@ int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck)
 
                rc = com->lc_ops->lfsck_prep(env, com);
                if (rc != 0)
-                       RETURN(rc);
+                       GOTO(out, rc);
 
                if ((pos == NULL) ||
                    (!lfsck_pos_is_zero(&com->lc_pos_start) &&
@@ -725,18 +750,21 @@ int lfsck_post(const struct lu_env *env, struct lfsck_instance *lfsck,
 {
        struct lfsck_component *com;
        struct lfsck_component *next;
-       int                     rc;
+       int                     rc  = 0;
+       int                     rc1 = 0;
 
        lfsck_pos_fill(env, lfsck, &lfsck->li_pos_current, false);
        cfs_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)
-                       return rc;
+                       rc1 = rc;
        }
 
        lfsck->li_time_last_checkpoint = cfs_time_current();
        lfsck->li_time_next_checkpoint = lfsck->li_time_last_checkpoint +
                                cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL);
+
+       /* Ignore some component post failure to make other can go ahead. */
        return result;
 }
 
@@ -767,22 +795,22 @@ int lfsck_get_speed(struct dt_device *key, void *buf, int len)
        int                     rc;
        ENTRY;
 
-       lfsck = lfsck_instance_find(key, true, false);
-       if (unlikely(lfsck == NULL))
-               RETURN(-ENODEV);
-
        rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD);
        if (rc != 0)
-               GOTO(out, rc);
+               RETURN(rc);
 
-       rc = snprintf(buf, len, "%u\n", lfsck->li_bookmark_ram.lb_speed_limit);
-       lu_env_fini(&env);
+       lfsck = lfsck_instance_find(key, true, false);
+       if (likely(lfsck != NULL)) {
+               rc = snprintf(buf, len, "%u\n",
+                             lfsck->li_bookmark_ram.lb_speed_limit);
+               lfsck_instance_put(&env, lfsck);
+       } else {
+               rc = -ENODEV;
+       }
 
-       GOTO(out, rc);
+       lu_env_fini(&env);
 
-out:
-       lfsck_instance_put(&env, lfsck);
-       return rc;
+       RETURN(rc);
 }
 EXPORT_SYMBOL(lfsck_get_speed);
 
@@ -793,74 +821,75 @@ int lfsck_set_speed(struct dt_device *key, int val)
        int                     rc;
        ENTRY;
 
-       lfsck = lfsck_instance_find(key, true, false);
-       if (unlikely(lfsck == NULL))
-               RETURN(-ENODEV);
-
        rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD);
        if (rc != 0)
-               GOTO(out, rc);
+               RETURN(rc);
 
-       mutex_lock(&lfsck->li_mutex);
-       __lfsck_set_speed(lfsck, val);
-       rc = lfsck_bookmark_store(&env, lfsck);
-       mutex_unlock(&lfsck->li_mutex);
-       lu_env_fini(&env);
+       lfsck = lfsck_instance_find(key, true, false);
+       if (likely(lfsck != NULL)) {
+               mutex_lock(&lfsck->li_mutex);
+               __lfsck_set_speed(lfsck, val);
+               rc = lfsck_bookmark_store(&env, lfsck);
+               mutex_unlock(&lfsck->li_mutex);
+               lfsck_instance_put(&env, lfsck);
+       } else {
+               rc = -ENODEV;
+       }
 
-       GOTO(out, rc);
+       lu_env_fini(&env);
 
-out:
-       lfsck_instance_put(&env, lfsck);
-       return rc;
+       RETURN(rc);
 }
 EXPORT_SYMBOL(lfsck_set_speed);
 
-int lfsck_dump(struct dt_device *key, void *buf, int len, __u16 type)
+int lfsck_dump(struct dt_device *key, void *buf, int len, enum lfsck_type type)
 {
        struct lu_env           env;
        struct lfsck_instance  *lfsck;
-       struct lfsck_component *com   = NULL;
+       struct lfsck_component *com;
        int                     rc;
        ENTRY;
 
-       lfsck = lfsck_instance_find(key, true, false);
-       if (unlikely(lfsck == NULL))
-               RETURN(-ENODEV);
-
-       com = lfsck_component_find(lfsck, type);
-       if (com == NULL)
-               GOTO(out, rc = -ENOTSUPP);
-
        rc = lu_env_init(&env, LCT_MD_THREAD | LCT_DT_THREAD);
        if (rc != 0)
-               GOTO(out, rc);
+               RETURN(rc);
 
-       rc = com->lc_ops->lfsck_dump(&env, com, buf, len);
-       lu_env_fini(&env);
+       lfsck = lfsck_instance_find(key, true, false);
+       if (likely(lfsck != NULL)) {
+               com = lfsck_component_find(lfsck, type);
+               if (likely(com != NULL)) {
+                       rc = com->lc_ops->lfsck_dump(&env, com, buf, len);
+                       lfsck_component_put(&env, com);
+               } else {
+                       rc = -ENOTSUPP;
+               }
 
-       GOTO(out, rc);
+               lfsck_instance_put(&env, lfsck);
+       } else {
+               rc = -ENODEV;
+       }
 
-out:
-       if (com != NULL)
-               lfsck_component_put(&env, com);
-       lfsck_instance_put(&env, lfsck);
-       return rc;
+       lu_env_fini(&env);
+
+       RETURN(rc);
 }
 EXPORT_SYMBOL(lfsck_dump);
 
 int lfsck_start(const struct lu_env *env, struct dt_device *key,
                struct lfsck_start_param *lsp)
 {
-       struct lfsck_start     *start  = lsp->lsp_start;
-       struct lfsck_instance  *lfsck;
-       struct lfsck_bookmark  *bk;
-       struct ptlrpc_thread   *thread;
-       struct lfsck_component *com;
-       struct l_wait_info      lwi    = { 0 };
-       bool                    dirty  = false;
-       long                    rc     = 0;
-       __u16                   valid  = 0;
-       __u16                   flags  = 0;
+       struct lfsck_start              *start  = lsp->lsp_start;
+       struct lfsck_instance           *lfsck;
+       struct lfsck_bookmark           *bk;
+       struct ptlrpc_thread            *thread;
+       struct lfsck_component          *com;
+       struct l_wait_info               lwi    = { 0 };
+       struct lfsck_thread_args        *lta;
+       bool                             dirty  = false;
+       long                             rc     = 0;
+       __u16                            valid  = 0;
+       __u16                            flags  = 0;
+       __u16                            type   = 1;
        ENTRY;
 
        lfsck = lfsck_instance_find(key, true, false);
@@ -878,10 +907,27 @@ int lfsck_start(const struct lu_env *env, struct dt_device *key,
        mutex_lock(&lfsck->li_mutex);
        spin_lock(&lfsck->li_lock);
        if (!thread_is_init(thread) && !thread_is_stopped(thread)) {
+               rc = -EALREADY;
+               while (start->ls_active != 0) {
+                       if (type & start->ls_active) {
+                               com = __lfsck_component_find(lfsck, type,
+                                                       &lfsck->li_list_scan);
+                               if (com == NULL)
+                                       com = __lfsck_component_find(lfsck,
+                                               type,
+                                               &lfsck->li_list_double_scan);
+                               if (com == NULL) {
+                                       rc = -EBUSY;
+                                       break;
+                               } else {
+                                       start->ls_active &= ~type;
+                               }
+                       }
+                       type <<= 1;
+               }
                spin_unlock(&lfsck->li_lock);
-               GOTO(out, rc = -EALREADY);
+               GOTO(out, rc);
        }
-
        spin_unlock(&lfsck->li_lock);
 
        lfsck->li_namespace = lsp->lsp_namespace;
@@ -944,7 +990,6 @@ int lfsck_start(const struct lu_env *env, struct dt_device *key,
 
        if (start->ls_active != 0) {
                struct lfsck_component *next;
-               __u16 type = 1;
 
                if (start->ls_active == LFSCK_TYPES_ALL)
                        start->ls_active = LFSCK_TYPES_SUPPORTED;
@@ -1009,10 +1054,15 @@ trigger:
 
        lfsck->li_args_oit = (flags << DT_OTABLE_IT_FLAGS_SHIFT) | valid;
        thread_set_flags(thread, 0);
-       rc = PTR_ERR(kthread_run(lfsck_master_engine, lfsck, "lfsck"));
+       lta = lfsck_thread_args_init(lfsck, NULL);
+       if (IS_ERR(lta))
+               GOTO(out, rc = PTR_ERR(lta));
+
+       rc = PTR_ERR(kthread_run(lfsck_master_engine, lta, "lfsck"));
        if (IS_ERR_VALUE(rc)) {
-               CERROR("%s: cannot start LFSCK thread, rc = %ld\n",
+               CERROR("%s: cannot start LFSCK thread: rc = %ld\n",
                       lfsck_lfsck2name(lfsck), rc);
+               lfsck_thread_args_fini(lta);
        } else {
                rc = 0;
                l_wait_event(thread->t_ctl_waitq,
@@ -1113,8 +1163,10 @@ int lfsck_register(const struct lu_env *env, struct dt_device *key,
        if (IS_ERR(root))
                GOTO(out, rc = PTR_ERR(root));
 
+       if (unlikely(!dt_try_as_dir(env, root)))
+               GOTO(out, rc = -ENOTDIR);
+
        lfsck->li_local_root_fid = *fid;
-        dt_try_as_dir(env, root);
        if (master) {
                lfsck->li_master = 1;
                if (lfsck_dev_idx(lfsck->li_bottom) == 0) {
@@ -1152,6 +1204,10 @@ int lfsck_register(const struct lu_env *env, struct dt_device *key,
                        GOTO(out, rc);
        }
 
+       rc = lfsck_layout_setup(env, lfsck);
+       if (rc < 0)
+               GOTO(out, rc);
+
        /* XXX: more LFSCK components initialization to be added here. */
 
 add:
index 3cc043d..d1ba149 100644 (file)
@@ -134,16 +134,15 @@ static int lfsck_namespace_load(const struct lu_env *env,
                lfsck_namespace_le_to_cpu(ns,
                                (struct lfsck_namespace *)com->lc_file_disk);
                if (ns->ln_magic != LFSCK_NAMESPACE_MAGIC) {
-                       CWARN("%.16s: invalid lfsck_namespace magic "
-                             "0x%x != 0x%x\n",
-                             lfsck_lfsck2name(com->lc_lfsck),
-                             ns->ln_magic, LFSCK_NAMESPACE_MAGIC);
+                       CWARN("%s: invalid lfsck_namespace magic %#x != %#x\n",
+                             lfsck_lfsck2name(com->lc_lfsck), ns->ln_magic,
+                             LFSCK_NAMESPACE_MAGIC);
                        rc = 1;
                } else {
                        rc = 0;
                }
        } else if (rc != -ENODATA) {
-               CERROR("%.16s: fail to load lfsck_namespace, expected = %d, "
+               CERROR("%s: fail to load lfsck_namespace: expected = %d, "
                       "rc = %d\n", lfsck_lfsck2name(com->lc_lfsck), len, rc);
                if (rc >= 0)
                        rc = 1;
@@ -166,8 +165,8 @@ static int lfsck_namespace_store(const struct lu_env *env,
        handle = dt_trans_create(env, lfsck->li_bottom);
        if (IS_ERR(handle)) {
                rc = PTR_ERR(handle);
-               CERROR("%.16s: fail to create trans for storing "
-                      "lfsck_namespace: %d\n,", lfsck_lfsck2name(lfsck), rc);
+               CERROR("%s: fail to create trans for storing lfsck_namespace: "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
                RETURN(rc);
        }
 
@@ -175,15 +174,15 @@ static int lfsck_namespace_store(const struct lu_env *env,
                                  lfsck_buf_get(env, com->lc_file_disk, len),
                                  XATTR_NAME_LFSCK_NAMESPACE, 0, handle);
        if (rc != 0) {
-               CERROR("%.16s: fail to declare trans for storing "
-                      "lfsck_namespace: %d\n,", lfsck_lfsck2name(lfsck), rc);
+               CERROR("%s: fail to declare trans for storing lfsck_namespace: "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
                GOTO(out, rc);
        }
 
        rc = dt_trans_start_local(env, lfsck->li_bottom, handle);
        if (rc != 0) {
-               CERROR("%.16s: fail to start trans for storing "
-                      "lfsck_namespace: %d\n,", lfsck_lfsck2name(lfsck), rc);
+               CERROR("%s: fail to start trans for storing lfsck_namespace: "
+                      "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
                GOTO(out, rc);
        }
 
@@ -193,7 +192,7 @@ static int lfsck_namespace_store(const struct lu_env *env,
                          init ? LU_XATTR_CREATE : LU_XATTR_REPLACE,
                          handle, BYPASS_CAPA);
        if (rc != 0)
-               CERROR("%.16s: fail to store lfsck_namespace, len = %d, "
+               CERROR("%s: fail to store lfsck_namespace: len = %d, "
                       "rc = %d\n", lfsck_lfsck2name(lfsck), len, rc);
 
        GOTO(out, rc);
@@ -206,7 +205,7 @@ out:
 static int lfsck_namespace_init(const struct lu_env *env,
                                struct lfsck_component *com)
 {
-       struct lfsck_namespace *ns = (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace *ns = com->lc_file_ram;
        int rc;
 
        memset(ns, 0, sizeof(*ns));
@@ -316,7 +315,7 @@ static int lfsck_namespace_update(const struct lu_env *env,
                rc = dt_delete(env, obj, (const struct dt_key *)key, handle,
                               BYPASS_CAPA);
                if (rc != 0) {
-                       CERROR("%s: fail to insert "DFID", rc = %d\n",
+                       CERROR("%s: fail to insert "DFID": rc = %d\n",
                               lfsck_lfsck2name(com->lc_lfsck), PFID(fid), rc);
                        GOTO(out, rc);
                }
@@ -473,8 +472,7 @@ static int lfsck_namespace_double_scan_one(const struct lu_env *env,
        struct lu_fid            *cfid    = &info->lti_fid2;
        struct lfsck_instance   *lfsck    = com->lc_lfsck;
        struct lfsck_bookmark   *bk       = &lfsck->li_bookmark_ram;
-       struct lfsck_namespace  *ns       =
-                               (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace  *ns       = com->lc_file_ram;
        struct linkea_data       ldata    = { 0 };
        struct thandle          *handle   = NULL;
        bool                     locked   = false;
@@ -625,7 +623,7 @@ stop:
                if (rc == 0 && !lfsck_is_dead_obj(child) &&
                    ldata.ld_leh != NULL &&
                    ldata.ld_leh->leh_reccount != la->la_nlink)
-                       CWARN("%.16s: the object "DFID" linkEA entry count %u "
+                       CWARN("%s: the object "DFID" linkEA entry count %u "
                              "may not match its hardlink count %u\n",
                              lfsck_lfsck2name(lfsck), PFID(cfid),
                              ldata.ld_leh->leh_reccount, la->la_nlink);
@@ -650,8 +648,7 @@ static int lfsck_namespace_reset(const struct lu_env *env,
                                 struct lfsck_component *com, bool init)
 {
        struct lfsck_instance   *lfsck = com->lc_lfsck;
-       struct lfsck_namespace  *ns    =
-                               (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace  *ns    = com->lc_file_ram;
        struct dt_object        *root;
        struct dt_object        *dto;
        int                      rc;
@@ -661,7 +658,10 @@ static int lfsck_namespace_reset(const struct lu_env *env,
        if (IS_ERR(root))
                RETURN(PTR_ERR(root));
 
-       dt_try_as_dir(env, root);
+       if (unlikely(!dt_try_as_dir(env, root))) {
+               lu_object_put(env, &root->do_lu);
+               RETURN(-ENOTDIR);
+       }
 
        down_write(&com->lc_sem);
        if (init) {
@@ -710,7 +710,7 @@ static void
 lfsck_namespace_fail(const struct lu_env *env, struct lfsck_component *com,
                     bool new_checked)
 {
-       struct lfsck_namespace *ns = (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace *ns = com->lc_file_ram;
 
        down_write(&com->lc_sem);
        if (new_checked)
@@ -726,8 +726,7 @@ static int lfsck_namespace_checkpoint(const struct lu_env *env,
                                      struct lfsck_component *com, bool init)
 {
        struct lfsck_instance   *lfsck = com->lc_lfsck;
-       struct lfsck_namespace  *ns    =
-                               (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace  *ns    = com->lc_file_ram;
        int                      rc;
 
        if (com->lc_new_checked == 0 && !init)
@@ -756,8 +755,7 @@ static int lfsck_namespace_prep(const struct lu_env *env,
                                struct lfsck_component *com)
 {
        struct lfsck_instance   *lfsck  = com->lc_lfsck;
-       struct lfsck_namespace  *ns     =
-                               (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace  *ns     = com->lc_file_ram;
        struct lfsck_position   *pos    = &com->lc_pos_start;
 
        if (ns->ln_status == LS_COMPLETED) {
@@ -843,11 +841,9 @@ static int lfsck_namespace_exec_dir(const struct lu_env *env,
        struct lu_attr             *la       = &info->lti_la;
        struct lfsck_instance      *lfsck    = com->lc_lfsck;
        struct lfsck_bookmark      *bk       = &lfsck->li_bookmark_ram;
-       struct lfsck_namespace     *ns       =
-                               (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace     *ns       = com->lc_file_ram;
        struct linkea_data          ldata    = { 0 };
-       const struct lu_fid        *pfid     =
-                               lu_object_fid(&lfsck->li_obj_dir->do_lu);
+       const struct lu_fid        *pfid     = lfsck_dto2fid(lfsck->li_obj_dir);
        const struct lu_fid        *cfid     = lfsck_dto2fid(obj);
        const struct lu_name       *cname;
        struct thandle             *handle   = NULL;
@@ -1043,8 +1039,7 @@ static int lfsck_namespace_post(const struct lu_env *env,
                                int result, bool init)
 {
        struct lfsck_instance   *lfsck = com->lc_lfsck;
-       struct lfsck_namespace  *ns    =
-                               (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace  *ns    = com->lc_file_ram;
        int                      rc;
 
        down_write(&com->lc_sem);
@@ -1096,8 +1091,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
 {
        struct lfsck_instance   *lfsck = com->lc_lfsck;
        struct lfsck_bookmark   *bk    = &lfsck->li_bookmark_ram;
-       struct lfsck_namespace  *ns    =
-                               (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace  *ns    = com->lc_file_ram;
        int                      save  = len;
        int                      ret   = -ENOSPC;
        int                      rc;
@@ -1105,12 +1099,12 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
        down_read(&com->lc_sem);
        rc = snprintf(buf, len,
                      "name: lfsck_namespace\n"
-                     "magic: 0x%x\n"
+                     "magic: %#x\n"
                      "version: %d\n"
                      "status: %s\n",
                      ns->ln_magic,
                      bk->lb_version,
-                     lfsck_status_names[ns->ln_status]);
+                     lfsck_status2names(ns->ln_status));
        if (rc <= 0)
                goto out;
 
@@ -1230,7 +1224,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                                pos.lp_dir_cookie = 0;
                        } else {
                                pos.lp_dir_parent =
-                               *lu_object_fid(&lfsck->li_obj_dir->do_lu);
+                                       *lfsck_dto2fid(lfsck->li_obj_dir);
                        }
                } else {
                        fid_zero(&pos.lp_dir_parent);
@@ -1359,8 +1353,7 @@ static int lfsck_namespace_double_scan(const struct lu_env *env,
        struct lfsck_instance   *lfsck  = com->lc_lfsck;
        struct ptlrpc_thread    *thread = &lfsck->li_thread;
        struct lfsck_bookmark   *bk     = &lfsck->li_bookmark_ram;
-       struct lfsck_namespace  *ns     =
-                               (struct lfsck_namespace *)com->lc_file_ram;
+       struct lfsck_namespace  *ns     = com->lc_file_ram;
        struct dt_object        *obj    = com->lc_obj;
        const struct dt_it_ops  *iops   = &obj->do_index_ops->dio_it;
        struct dt_object        *target;
@@ -1371,9 +1364,10 @@ static int lfsck_namespace_double_scan(const struct lu_env *env,
        __u8                     flags = 0;
        ENTRY;
 
-       lfsck->li_new_scanned = 0;
-       lfsck->li_time_last_checkpoint = cfs_time_current();
-       lfsck->li_time_next_checkpoint = lfsck->li_time_last_checkpoint +
+       com->lc_new_checked = 0;
+       com->lc_new_scanned = 0;
+       com->lc_time_last_checkpoint = cfs_time_current();
+       com->lc_time_next_checkpoint = com->lc_time_last_checkpoint +
                                cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL);
 
        di = iops->init(env, obj, 0, BYPASS_CAPA);
@@ -1429,8 +1423,8 @@ static int lfsck_namespace_double_scan(const struct lu_env *env,
                lfsck_object_put(env, target);
 
 checkpoint:
-               lfsck->li_new_scanned++;
                com->lc_new_checked++;
+               com->lc_new_scanned++;
                ns->ln_fid_latest_scanned_phase2 = fid;
                if (rc > 0)
                        ns->ln_objs_repaired_phase2++;
@@ -1448,13 +1442,13 @@ checkpoint:
                if (rc < 0 && bk->lb_param & LPF_FAILOUT)
                        GOTO(put, rc);
 
-               if (unlikely(cfs_time_beforeq(lfsck->li_time_next_checkpoint,
+               if (unlikely(cfs_time_beforeq(com->lc_time_next_checkpoint,
                                              cfs_time_current())) &&
                    com->lc_new_checked != 0) {
                        down_write(&com->lc_sem);
                        ns->ln_run_time_phase2 +=
                                cfs_duration_sec(cfs_time_current() +
-                               HALF_SEC - lfsck->li_time_last_checkpoint);
+                               HALF_SEC - com->lc_time_last_checkpoint);
                        ns->ln_time_last_checkpoint = cfs_time_current_sec();
                        ns->ln_objs_checked_phase2 += com->lc_new_checked;
                        com->lc_new_checked = 0;
@@ -1463,13 +1457,13 @@ checkpoint:
                        if (rc != 0)
                                GOTO(put, rc);
 
-                       lfsck->li_time_last_checkpoint = cfs_time_current();
-                       lfsck->li_time_next_checkpoint =
-                               lfsck->li_time_last_checkpoint +
+                       com->lc_time_last_checkpoint = cfs_time_current();
+                       com->lc_time_next_checkpoint =
+                               com->lc_time_last_checkpoint +
                                cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL);
                }
 
-               lfsck_control_speed(lfsck);
+               lfsck_control_speed_by_self(com);
                if (unlikely(!thread_is_running(thread)))
                        GOTO(put, rc = 0);
 
@@ -1495,8 +1489,7 @@ fini:
                com->lc_journal = 0;
                ns->ln_status = LS_COMPLETED;
                if (!(bk->lb_param & LPF_DRYRUN))
-                       ns->ln_flags &=
-                       ~(LF_SCANNED_ONCE | LF_INCONSISTENT | LF_UPGRADE);
+                       ns->ln_flags &= ~(LF_SCANNED_ONCE | LF_INCONSISTENT);
                ns->ln_time_last_complete = ns->ln_time_last_checkpoint;
                ns->ln_success_count++;
        } else if (rc == 0) {
@@ -1569,7 +1562,9 @@ int lfsck_namespace_setup(const struct lu_env *env,
        if (IS_ERR(root))
                GOTO(out, rc = PTR_ERR(root));
 
-       dt_try_as_dir(env, root);
+       if (unlikely(!dt_try_as_dir(env, root)))
+               GOTO(out, rc = -ENOTDIR);
+
        obj = local_index_find_or_create(env, lfsck->li_los, root,
                                         lfsck_namespace_name,
                                         S_IFREG | S_IRUGO | S_IWUSR,
@@ -1590,16 +1585,18 @@ int lfsck_namespace_setup(const struct lu_env *env,
        if (rc != 0)
                GOTO(out, rc);
 
-       ns = (struct lfsck_namespace *)com->lc_file_ram;
+       ns = com->lc_file_ram;
        switch (ns->ln_status) {
        case LS_INIT:
        case LS_COMPLETED:
        case LS_FAILED:
        case LS_STOPPED:
+               spin_lock(&lfsck->li_lock);
                cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle);
+               spin_unlock(&lfsck->li_lock);
                break;
        default:
-               CERROR("%s: unknown lfsck_namespace status: %u\n",
+               CERROR("%s: unknown lfsck_namespace status: rc = %u\n",
                       lfsck_lfsck2name(lfsck), ns->ln_status);
                /* fall through */
        case LS_SCANNING_PHASE1:
@@ -1611,8 +1608,10 @@ int lfsck_namespace_setup(const struct lu_env *env,
                /* fall through */
        case LS_PAUSED:
        case LS_CRASHED:
+               spin_lock(&lfsck->li_lock);
                cfs_list_add_tail(&com->lc_link, &lfsck->li_list_scan);
                cfs_list_add_tail(&com->lc_link_dir, &lfsck->li_list_dir);
+               spin_unlock(&lfsck->li_lock);
                break;
        }