Whamcloud - gitweb
LU-4788 lfsck: replace cfs_list_t with list_head
[fs/lustre-release.git] / lustre / lfsck / lfsck_namespace.c
index a3a3948..2c8918e 100644 (file)
  * Author: Fan, Yong <fan.yong@intel.com>
  */
 
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
 #define DEBUG_SUBSYSTEM S_LFSCK
 
 #include <lustre/lustre_idl.h>
 #include <lu_object.h>
 #include <dt_object.h>
 #include <md_object.h>
-#include <lustre_linkea.h>
 #include <lustre_fid.h>
 #include <lustre_lib.h>
 #include <lustre_net.h>
 
 static const char lfsck_namespace_name[] = "lfsck_namespace";
 
-static void lfsck_namespace_le_to_cpu(struct lfsck_namespace *des,
+static void lfsck_namespace_le_to_cpu(struct lfsck_namespace *dst,
                                      struct lfsck_namespace *src)
 {
-       des->ln_magic = le32_to_cpu(src->ln_magic);
-       des->ln_status = le32_to_cpu(src->ln_status);
-       des->ln_flags = le32_to_cpu(src->ln_flags);
-       des->ln_success_count = le32_to_cpu(src->ln_success_count);
-       des->ln_run_time_phase1 = le32_to_cpu(src->ln_run_time_phase1);
-       des->ln_run_time_phase2 = le32_to_cpu(src->ln_run_time_phase2);
-       des->ln_time_last_complete = le64_to_cpu(src->ln_time_last_complete);
-       des->ln_time_latest_start = le64_to_cpu(src->ln_time_latest_start);
-       des->ln_time_last_checkpoint =
+       dst->ln_magic = le32_to_cpu(src->ln_magic);
+       dst->ln_status = le32_to_cpu(src->ln_status);
+       dst->ln_flags = le32_to_cpu(src->ln_flags);
+       dst->ln_success_count = le32_to_cpu(src->ln_success_count);
+       dst->ln_run_time_phase1 = le32_to_cpu(src->ln_run_time_phase1);
+       dst->ln_run_time_phase2 = le32_to_cpu(src->ln_run_time_phase2);
+       dst->ln_time_last_complete = le64_to_cpu(src->ln_time_last_complete);
+       dst->ln_time_latest_start = le64_to_cpu(src->ln_time_latest_start);
+       dst->ln_time_last_checkpoint =
                                le64_to_cpu(src->ln_time_last_checkpoint);
-       lfsck_position_le_to_cpu(&des->ln_pos_latest_start,
+       lfsck_position_le_to_cpu(&dst->ln_pos_latest_start,
                                 &src->ln_pos_latest_start);
-       lfsck_position_le_to_cpu(&des->ln_pos_last_checkpoint,
+       lfsck_position_le_to_cpu(&dst->ln_pos_last_checkpoint,
                                 &src->ln_pos_last_checkpoint);
-       lfsck_position_le_to_cpu(&des->ln_pos_first_inconsistent,
+       lfsck_position_le_to_cpu(&dst->ln_pos_first_inconsistent,
                                 &src->ln_pos_first_inconsistent);
-       des->ln_items_checked = le64_to_cpu(src->ln_items_checked);
-       des->ln_items_repaired = le64_to_cpu(src->ln_items_repaired);
-       des->ln_items_failed = le64_to_cpu(src->ln_items_failed);
-       des->ln_dirs_checked = le64_to_cpu(src->ln_dirs_checked);
-       des->ln_mlinked_checked = le64_to_cpu(src->ln_mlinked_checked);
-       des->ln_objs_checked_phase2 = le64_to_cpu(src->ln_objs_checked_phase2);
-       des->ln_objs_repaired_phase2 =
+       dst->ln_items_checked = le64_to_cpu(src->ln_items_checked);
+       dst->ln_items_repaired = le64_to_cpu(src->ln_items_repaired);
+       dst->ln_items_failed = le64_to_cpu(src->ln_items_failed);
+       dst->ln_dirs_checked = le64_to_cpu(src->ln_dirs_checked);
+       dst->ln_mlinked_checked = le64_to_cpu(src->ln_mlinked_checked);
+       dst->ln_objs_checked_phase2 = le64_to_cpu(src->ln_objs_checked_phase2);
+       dst->ln_objs_repaired_phase2 =
                                le64_to_cpu(src->ln_objs_repaired_phase2);
-       des->ln_objs_failed_phase2 = le64_to_cpu(src->ln_objs_failed_phase2);
-       des->ln_objs_nlink_repaired = le64_to_cpu(src->ln_objs_nlink_repaired);
-       des->ln_objs_lost_found = le64_to_cpu(src->ln_objs_lost_found);
-       fid_le_to_cpu(&des->ln_fid_latest_scanned_phase2,
+       dst->ln_objs_failed_phase2 = le64_to_cpu(src->ln_objs_failed_phase2);
+       dst->ln_objs_nlink_repaired = le64_to_cpu(src->ln_objs_nlink_repaired);
+       dst->ln_objs_lost_found = le64_to_cpu(src->ln_objs_lost_found);
+       fid_le_to_cpu(&dst->ln_fid_latest_scanned_phase2,
                      &src->ln_fid_latest_scanned_phase2);
+       dst->ln_dirent_repaired = le64_to_cpu(src->ln_dirent_repaired);
+       dst->ln_linkea_repaired = le64_to_cpu(src->ln_linkea_repaired);
 }
 
-static void lfsck_namespace_cpu_to_le(struct lfsck_namespace *des,
+static void lfsck_namespace_cpu_to_le(struct lfsck_namespace *dst,
                                      struct lfsck_namespace *src)
 {
-       des->ln_magic = cpu_to_le32(src->ln_magic);
-       des->ln_status = cpu_to_le32(src->ln_status);
-       des->ln_flags = cpu_to_le32(src->ln_flags);
-       des->ln_success_count = cpu_to_le32(src->ln_success_count);
-       des->ln_run_time_phase1 = cpu_to_le32(src->ln_run_time_phase1);
-       des->ln_run_time_phase2 = cpu_to_le32(src->ln_run_time_phase2);
-       des->ln_time_last_complete = cpu_to_le64(src->ln_time_last_complete);
-       des->ln_time_latest_start = cpu_to_le64(src->ln_time_latest_start);
-       des->ln_time_last_checkpoint =
+       dst->ln_magic = cpu_to_le32(src->ln_magic);
+       dst->ln_status = cpu_to_le32(src->ln_status);
+       dst->ln_flags = cpu_to_le32(src->ln_flags);
+       dst->ln_success_count = cpu_to_le32(src->ln_success_count);
+       dst->ln_run_time_phase1 = cpu_to_le32(src->ln_run_time_phase1);
+       dst->ln_run_time_phase2 = cpu_to_le32(src->ln_run_time_phase2);
+       dst->ln_time_last_complete = cpu_to_le64(src->ln_time_last_complete);
+       dst->ln_time_latest_start = cpu_to_le64(src->ln_time_latest_start);
+       dst->ln_time_last_checkpoint =
                                cpu_to_le64(src->ln_time_last_checkpoint);
-       lfsck_position_cpu_to_le(&des->ln_pos_latest_start,
+       lfsck_position_cpu_to_le(&dst->ln_pos_latest_start,
                                 &src->ln_pos_latest_start);
-       lfsck_position_cpu_to_le(&des->ln_pos_last_checkpoint,
+       lfsck_position_cpu_to_le(&dst->ln_pos_last_checkpoint,
                                 &src->ln_pos_last_checkpoint);
-       lfsck_position_cpu_to_le(&des->ln_pos_first_inconsistent,
+       lfsck_position_cpu_to_le(&dst->ln_pos_first_inconsistent,
                                 &src->ln_pos_first_inconsistent);
-       des->ln_items_checked = cpu_to_le64(src->ln_items_checked);
-       des->ln_items_repaired = cpu_to_le64(src->ln_items_repaired);
-       des->ln_items_failed = cpu_to_le64(src->ln_items_failed);
-       des->ln_dirs_checked = cpu_to_le64(src->ln_dirs_checked);
-       des->ln_mlinked_checked = cpu_to_le64(src->ln_mlinked_checked);
-       des->ln_objs_checked_phase2 = cpu_to_le64(src->ln_objs_checked_phase2);
-       des->ln_objs_repaired_phase2 =
+       dst->ln_items_checked = cpu_to_le64(src->ln_items_checked);
+       dst->ln_items_repaired = cpu_to_le64(src->ln_items_repaired);
+       dst->ln_items_failed = cpu_to_le64(src->ln_items_failed);
+       dst->ln_dirs_checked = cpu_to_le64(src->ln_dirs_checked);
+       dst->ln_mlinked_checked = cpu_to_le64(src->ln_mlinked_checked);
+       dst->ln_objs_checked_phase2 = cpu_to_le64(src->ln_objs_checked_phase2);
+       dst->ln_objs_repaired_phase2 =
                                cpu_to_le64(src->ln_objs_repaired_phase2);
-       des->ln_objs_failed_phase2 = cpu_to_le64(src->ln_objs_failed_phase2);
-       des->ln_objs_nlink_repaired = cpu_to_le64(src->ln_objs_nlink_repaired);
-       des->ln_objs_lost_found = cpu_to_le64(src->ln_objs_lost_found);
-       fid_cpu_to_le(&des->ln_fid_latest_scanned_phase2,
+       dst->ln_objs_failed_phase2 = cpu_to_le64(src->ln_objs_failed_phase2);
+       dst->ln_objs_nlink_repaired = cpu_to_le64(src->ln_objs_nlink_repaired);
+       dst->ln_objs_lost_found = cpu_to_le64(src->ln_objs_lost_found);
+       fid_cpu_to_le(&dst->ln_fid_latest_scanned_phase2,
                      &src->ln_fid_latest_scanned_phase2);
+       dst->ln_dirent_repaired = cpu_to_le64(src->ln_dirent_repaired);
+       dst->ln_linkea_repaired = cpu_to_le64(src->ln_linkea_repaired);
 }
 
 /**
@@ -137,17 +137,17 @@ 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);
+                       CDEBUG(D_LFSCK, "%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, "
-                      "rc = %d\n", lfsck_lfsck2name(com->lc_lfsck), len, rc);
+               CDEBUG(D_LFSCK, "%s: fail to load lfsck_namespace, "
+                      "expected = %d: rc = %d\n",
+                      lfsck_lfsck2name(com->lc_lfsck), len, rc);
                if (rc >= 0)
                        rc = 1;
        }
@@ -167,49 +167,41 @@ static int lfsck_namespace_store(const struct lu_env *env,
        lfsck_namespace_cpu_to_le((struct lfsck_namespace *)com->lc_file_disk,
                                  (struct lfsck_namespace *)com->lc_file_ram);
        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);
-               RETURN(rc);
-       }
+       if (IS_ERR(handle))
+               GOTO(log, rc = PTR_ERR(handle));
 
        rc = dt_declare_xattr_set(env, obj,
                                  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);
+       if (rc != 0)
                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);
+       if (rc != 0)
                GOTO(out, rc);
-       }
 
        rc = dt_xattr_set(env, obj,
                          lfsck_buf_get(env, com->lc_file_disk, len),
                          XATTR_NAME_LFSCK_NAMESPACE,
                          init ? LU_XATTR_CREATE : LU_XATTR_REPLACE,
                          handle, BYPASS_CAPA);
-       if (rc != 0)
-               CERROR("%.16s: fail to store lfsck_namespace, len = %d, "
-                      "rc = %d\n", lfsck_lfsck2name(lfsck), len, rc);
 
        GOTO(out, rc);
 
 out:
        dt_trans_stop(env, lfsck->li_bottom, handle);
+
+log:
+       if (rc != 0)
+               CDEBUG(D_LFSCK, "%s: fail to store lfsck_namespace: rc = %d\n",
+                      lfsck_lfsck2name(lfsck), rc);
        return rc;
 }
 
 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));
@@ -318,11 +310,8 @@ static int lfsck_namespace_update(const struct lu_env *env,
        if (exist) {
                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",
-                              lfsck_lfsck2name(com->lc_lfsck), PFID(fid), rc);
+               if (rc != 0)
                        GOTO(out, rc);
-               }
        }
 
        rc = dt_insert(env, obj, (const struct dt_rec *)&flags,
@@ -476,8 +465,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;
@@ -601,9 +589,11 @@ shrink:
                if (bk->lb_param & LPF_DRYRUN)
                        RETURN(1);
 
-               CDEBUG(D_LFSCK, "Remove linkEA: "DFID"[%.*s], "DFID"\n",
-                      PFID(lfsck_dto2fid(child)), cname->ln_namelen, cname->ln_name,
-                      PFID(pfid));
+               CDEBUG(D_LFSCK, "%s: namespace LFSCK remove invalid linkEA "
+                     "for the object: "DFID", parent "DFID", name %.*s\n",
+                     lfsck_lfsck2name(lfsck), PFID(lfsck_dto2fid(child)),
+                     PFID(pfid), cname->ln_namelen, cname->ln_name);
+
                linkea_del_buf(&ldata, cname);
                update = true;
        }
@@ -628,10 +618,10 @@ 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 "
-                             "may not match its hardlink count %u\n",
-                             lfsck_lfsck2name(lfsck), PFID(cfid),
-                             ldata.ld_leh->leh_reccount, la->la_nlink);
+                       CDEBUG(D_LFSCK, "%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);
 
                dt_write_unlock(env, child);
        }
@@ -653,12 +643,19 @@ 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;
        ENTRY;
 
+       root = dt_locate(env, lfsck->li_bottom, &lfsck->li_local_root_fid);
+       if (IS_ERR(root))
+               GOTO(log, rc = PTR_ERR(root));
+
+       if (unlikely(!dt_try_as_dir(env, root)))
+               GOTO(put, rc = -ENOTDIR);
+
        down_write(&com->lc_sem);
        if (init) {
                memset(ns, 0, sizeof(*ns));
@@ -673,12 +670,14 @@ static int lfsck_namespace_reset(const struct lu_env *env,
        ns->ln_magic = LFSCK_NAMESPACE_MAGIC;
        ns->ln_status = LS_INIT;
 
-       rc = local_object_unlink(env, lfsck->li_bottom, lfsck->li_local_root,
+       rc = local_object_unlink(env, lfsck->li_bottom, root,
                                 lfsck_namespace_name);
        if (rc != 0)
                GOTO(out, rc);
 
-       dto = local_index_find_or_create(env, lfsck->li_los, lfsck->li_local_root,
+       lfsck_object_put(env, com->lc_obj);
+       com->lc_obj = NULL;
+       dto = local_index_find_or_create(env, lfsck->li_los, root,
                                         lfsck_namespace_name,
                                         S_IFREG | S_IRUGO | S_IWUSR,
                                         &dt_lfsck_features);
@@ -696,6 +695,12 @@ static int lfsck_namespace_reset(const struct lu_env *env,
 
 out:
        up_write(&com->lc_sem);
+
+put:
+       lu_object_put(env, &root->do_lu);
+log:
+       CDEBUG(D_LFSCK, "%s: namespace LFSCK reset: rc = %d\n",
+              lfsck_lfsck2name(lfsck), rc);
        return rc;
 }
 
@@ -703,15 +708,23 @@ 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)
                com->lc_new_checked++;
        ns->ln_items_failed++;
-       if (lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent))
+       if (lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) {
                lfsck_pos_fill(env, com->lc_lfsck,
                               &ns->ln_pos_first_inconsistent, false);
+
+               CDEBUG(D_LFSCK, "%s: namespace LFSCK hit first non-repaired "
+                      "inconsistency at the pos ["LPU64", "DFID", "LPX64"]\n",
+                      lfsck_lfsck2name(com->lc_lfsck),
+                      ns->ln_pos_first_inconsistent.lp_oit_cookie,
+                      PFID(&ns->ln_pos_first_inconsistent.lp_dir_parent),
+                      ns->ln_pos_first_inconsistent.lp_dir_cookie);
+       }
        up_write(&com->lc_sem);
 }
 
@@ -719,15 +732,13 @@ 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)
                return 0;
 
        down_write(&com->lc_sem);
-
        if (init) {
                ns->ln_pos_latest_start = lfsck->li_pos_current;
        } else {
@@ -740,29 +751,41 @@ static int lfsck_namespace_checkpoint(const struct lu_env *env,
        }
 
        rc = lfsck_namespace_store(env, com, false);
-
        up_write(&com->lc_sem);
+
+       CDEBUG(D_LFSCK, "%s: namespace LFSCK checkpoint at the pos ["LPU64
+              ", "DFID", "LPX64"]: rc = %d\n", lfsck_lfsck2name(lfsck),
+              lfsck->li_pos_current.lp_oit_cookie,
+              PFID(&lfsck->li_pos_current.lp_dir_parent),
+              lfsck->li_pos_current.lp_dir_cookie, rc);
+
        return rc;
 }
 
 static int lfsck_namespace_prep(const struct lu_env *env,
-                               struct lfsck_component *com)
+                               struct lfsck_component *com,
+                               struct lfsck_start_param *lsp)
 {
        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) {
                int rc;
 
                rc = lfsck_namespace_reset(env, com, false);
-               if (rc != 0)
+               if (rc == 0)
+                       rc = lfsck_set_param(env, lfsck, lsp->lsp_start, true);
+
+               if (rc != 0) {
+                       CDEBUG(D_LFSCK, "%s: namespace LFSCK prep failed: "
+                              "rc = %d\n", lfsck_lfsck2name(lfsck), rc);
+
                        return rc;
+               }
        }
 
        down_write(&com->lc_sem);
-
        ns->ln_time_latest_start = cfs_time_current_sec();
 
        spin_lock(&lfsck->li_lock);
@@ -770,11 +793,10 @@ static int lfsck_namespace_prep(const struct lu_env *env,
                if (!lfsck->li_drop_dryrun ||
                    lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) {
                        ns->ln_status = LS_SCANNING_PHASE2;
-                       cfs_list_del_init(&com->lc_link);
-                       cfs_list_add_tail(&com->lc_link,
-                                         &lfsck->li_list_double_scan);
-                       if (!cfs_list_empty(&com->lc_link_dir))
-                               cfs_list_del_init(&com->lc_link_dir);
+                       list_move_tail(&com->lc_link,
+                                      &lfsck->li_list_double_scan);
+                       if (!list_empty(&com->lc_link_dir))
+                               list_del_init(&com->lc_link_dir);
                        lfsck_pos_set_zero(pos);
                } else {
                        ns->ln_status = LS_SCANNING_PHASE1;
@@ -791,16 +813,16 @@ static int lfsck_namespace_prep(const struct lu_env *env,
                        ns->ln_objs_nlink_repaired = 0;
                        ns->ln_objs_lost_found = 0;
                        fid_zero(&ns->ln_fid_latest_scanned_phase2);
-                       if (cfs_list_empty(&com->lc_link_dir))
-                               cfs_list_add_tail(&com->lc_link_dir,
-                                                 &lfsck->li_list_dir);
+                       if (list_empty(&com->lc_link_dir))
+                               list_add_tail(&com->lc_link_dir,
+                                             &lfsck->li_list_dir);
                        *pos = ns->ln_pos_first_inconsistent;
                }
        } else {
                ns->ln_status = LS_SCANNING_PHASE1;
-               if (cfs_list_empty(&com->lc_link_dir))
-                       cfs_list_add_tail(&com->lc_link_dir,
-                                         &lfsck->li_list_dir);
+               if (list_empty(&com->lc_link_dir))
+                       list_add_tail(&com->lc_link_dir,
+                                     &lfsck->li_list_dir);
                if (!lfsck->li_drop_dryrun ||
                    lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) {
                        *pos = ns->ln_pos_last_checkpoint;
@@ -810,8 +832,12 @@ static int lfsck_namespace_prep(const struct lu_env *env,
                }
        }
        spin_unlock(&lfsck->li_lock);
-
        up_write(&com->lc_sem);
+
+       CDEBUG(D_LFSCK, "%s: namespace LFSCK prep done, start pos ["LPU64", "
+              DFID", "LPX64"]\n", lfsck_lfsck2name(lfsck), pos->lp_oit_cookie,
+              PFID(&pos->lp_dir_parent), pos->lp_dir_cookie);
+
        return 0;
 }
 
@@ -836,11 +862,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;
@@ -848,6 +872,7 @@ static int lfsck_namespace_exec_dir(const struct lu_env *env,
        bool                        locked   = false;
        bool                        remove;
        bool                        newdata;
+       bool                        log      = false;
        int                         count    = 0;
        int                         rc;
        ENTRY;
@@ -858,16 +883,18 @@ static int lfsck_namespace_exec_dir(const struct lu_env *env,
 
        if (ent->lde_attrs & LUDA_UPGRADE) {
                ns->ln_flags |= LF_UPGRADE;
+               ns->ln_dirent_repaired++;
                repaired = true;
        } else if (ent->lde_attrs & LUDA_REPAIR) {
                ns->ln_flags |= LF_INCONSISTENT;
+               ns->ln_dirent_repaired++;
                repaired = true;
        }
 
        if (ent->lde_name[0] == '.' &&
            (ent->lde_namelen == 1 ||
             (ent->lde_namelen == 2 && ent->lde_name[1] == '.') ||
-            fid_is_dot_lustre(&ent->lde_fid)))
+            fid_seq_is_dot_lustre(fid_seq(&ent->lde_fid))))
                GOTO(out, rc = 0);
 
        if (!(bk->lb_param & LPF_DRYRUN) &&
@@ -933,6 +960,8 @@ again:
 
 nodata:
                if (bk->lb_param & LPF_DRYRUN) {
+                       ns->ln_linkea_repaired++;
+                       log = true;
                        repaired = true;
                        goto record;
                }
@@ -965,6 +994,8 @@ nodata:
                        GOTO(stop, rc);
 
                count = ldata.ld_leh->leh_reccount;
+               ns->ln_linkea_repaired++;
+               log = true;
                repaired = true;
        } else {
                GOTO(stop, rc);
@@ -991,6 +1022,13 @@ record:
 
                dt_trans_stop(env, lfsck->li_next, handle);
                handle = NULL;
+
+               if (log)
+                       CDEBUG(D_LFSCK, "%s: namespace LFSCK repaired "
+                             "linkEA for the object: "DFID", parent "
+                             DFID", name %.*s\n",
+                             lfsck_lfsck2name(lfsck), PFID(cfid), PFID(pfid),
+                             ent->lde_namelen, ent->lde_name);
        }
 
        ns->ln_mlinked_checked++;
@@ -1008,6 +1046,11 @@ stop:
 
 out:
        if (rc < 0) {
+               CDEBUG(D_LFSCK, "%s: namespace LFSCK exec_dir failed, "
+                      "parent "DFID", child name %.*s, child FID "DFID
+                      ": rc = %d\n", lfsck_lfsck2name(lfsck), PFID(pfid),
+                      ent->lde_namelen, ent->lde_name, PFID(cfid), rc);
+
                ns->ln_items_failed++;
                if (lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent))
                        lfsck_pos_fill(env, lfsck,
@@ -1015,10 +1058,16 @@ out:
                if (!(bk->lb_param & LPF_FAILOUT))
                        rc = 0;
        } else {
-               if (repaired)
+               if (repaired) {
                        ns->ln_items_repaired++;
-               else
+                       if (bk->lb_param & LPF_DRYRUN &&
+                           lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent))
+                               lfsck_pos_fill(env, lfsck,
+                                              &ns->ln_pos_first_inconsistent,
+                                              false);
+               } else {
                        com->lc_journal = 0;
+               }
                rc = 0;
        }
        up_write(&com->lc_sem);
@@ -1030,12 +1079,10 @@ 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);
-
        spin_lock(&lfsck->li_lock);
        if (!init)
                ns->ln_pos_last_checkpoint = lfsck->li_pos_current;
@@ -1043,23 +1090,20 @@ static int lfsck_namespace_post(const struct lu_env *env,
                ns->ln_status = LS_SCANNING_PHASE2;
                ns->ln_flags |= LF_SCANNED_ONCE;
                ns->ln_flags &= ~LF_UPGRADE;
-               cfs_list_del_init(&com->lc_link);
-               cfs_list_del_init(&com->lc_link_dir);
-               cfs_list_add_tail(&com->lc_link, &lfsck->li_list_double_scan);
+               list_del_init(&com->lc_link_dir);
+               list_move_tail(&com->lc_link, &lfsck->li_list_double_scan);
        } else if (result == 0) {
-               if (lfsck->li_paused) {
-                       ns->ln_status = LS_PAUSED;
-               } else {
+               ns->ln_status = lfsck->li_status;
+               if (ns->ln_status == 0)
                        ns->ln_status = LS_STOPPED;
-                       cfs_list_del_init(&com->lc_link);
-                       cfs_list_del_init(&com->lc_link_dir);
-                       cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle);
+               if (ns->ln_status != LS_PAUSED) {
+                       list_del_init(&com->lc_link_dir);
+                       list_move_tail(&com->lc_link, &lfsck->li_list_idle);
                }
        } else {
                ns->ln_status = LS_FAILED;
-               cfs_list_del_init(&com->lc_link);
-               cfs_list_del_init(&com->lc_link_dir);
-               cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle);
+               list_del_init(&com->lc_link_dir);
+               list_move_tail(&com->lc_link, &lfsck->li_list_idle);
        }
        spin_unlock(&lfsck->li_lock);
 
@@ -1072,73 +1116,66 @@ static int lfsck_namespace_post(const struct lu_env *env,
        }
 
        rc = lfsck_namespace_store(env, com, false);
-
        up_write(&com->lc_sem);
+
+       CDEBUG(D_LFSCK, "%s: namespace LFSCK post done: rc = %d\n",
+              lfsck_lfsck2name(lfsck), rc);
+
        return rc;
 }
 
 static int
 lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
-                    char *buf, int len)
+                    struct seq_file *m)
 {
        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;
-       int                      save  = len;
-       int                      ret   = -ENOSPC;
+       struct lfsck_namespace  *ns    = com->lc_file_ram;
        int                      rc;
 
        down_read(&com->lc_sem);
-       rc = snprintf(buf, len,
-                     "name: lfsck_namespace\n"
-                     "magic: 0x%x\n"
-                     "version: %d\n"
-                     "status: %s\n",
-                     ns->ln_magic,
-                     bk->lb_version,
-                     lfsck_status_names[ns->ln_status]);
-       if (rc <= 0)
-               goto out;
-
-       buf += rc;
-       len -= rc;
-       rc = lfsck_bits_dump(&buf, &len, ns->ln_flags, lfsck_flags_names,
-                            "flags");
+       seq_printf(m, "name: lfsck_namespace\n"
+                  "magic: %#x\n"
+                  "version: %d\n"
+                  "status: %s\n",
+                  ns->ln_magic,
+                  bk->lb_version,
+                  lfsck_status2names(ns->ln_status));
+
+       rc = lfsck_bits_dump(m, ns->ln_flags, lfsck_flags_names, "flags");
        if (rc < 0)
                goto out;
 
-       rc = lfsck_bits_dump(&buf, &len, bk->lb_param, lfsck_param_names,
-                            "param");
+       rc = lfsck_bits_dump(m, bk->lb_param, lfsck_param_names, "param");
        if (rc < 0)
                goto out;
 
-       rc = lfsck_time_dump(&buf, &len, ns->ln_time_last_complete,
+       rc = lfsck_time_dump(m, ns->ln_time_last_complete,
                             "time_since_last_completed");
        if (rc < 0)
                goto out;
 
-       rc = lfsck_time_dump(&buf, &len, ns->ln_time_latest_start,
+       rc = lfsck_time_dump(m, ns->ln_time_latest_start,
                             "time_since_latest_start");
        if (rc < 0)
                goto out;
 
-       rc = lfsck_time_dump(&buf, &len, ns->ln_time_last_checkpoint,
+       rc = lfsck_time_dump(m, ns->ln_time_last_checkpoint,
                             "time_since_last_checkpoint");
        if (rc < 0)
                goto out;
 
-       rc = lfsck_pos_dump(&buf, &len, &ns->ln_pos_latest_start,
+       rc = lfsck_pos_dump(m, &ns->ln_pos_latest_start,
                            "latest_start_position");
        if (rc < 0)
                goto out;
 
-       rc = lfsck_pos_dump(&buf, &len, &ns->ln_pos_last_checkpoint,
+       rc = lfsck_pos_dump(m, &ns->ln_pos_last_checkpoint,
                            "last_checkpoint_position");
        if (rc < 0)
                goto out;
 
-       rc = lfsck_pos_dump(&buf, &len, &ns->ln_pos_first_inconsistent,
+       rc = lfsck_pos_dump(m, &ns->ln_pos_first_inconsistent,
                            "first_failure_position");
        if (rc < 0)
                goto out;
@@ -1150,7 +1187,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                                          lfsck->li_time_last_checkpoint;
                __u64 checked = ns->ln_items_checked + com->lc_new_checked;
                __u64 speed = checked;
-               __u64 new_checked = com->lc_new_checked * CFS_HZ;
+               __u64 new_checked = com->lc_new_checked * HZ;
                __u32 rtime = ns->ln_run_time_phase1 +
                              cfs_duration_sec(duration + HALF_SEC);
 
@@ -1158,15 +1195,16 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                        do_div(new_checked, duration);
                if (rtime != 0)
                        do_div(speed, rtime);
-               rc = snprintf(buf, len,
-                             "checked_phase1: "LPU64"\n"
+               seq_printf(m, "checked_phase1: "LPU64"\n"
                              "checked_phase2: "LPU64"\n"
                              "updated_phase1: "LPU64"\n"
                              "updated_phase2: "LPU64"\n"
                              "failed_phase1: "LPU64"\n"
                              "failed_phase2: "LPU64"\n"
-                             "dirs: "LPU64"\n"
-                             "M-linked: "LPU64"\n"
+                             "directories: "LPU64"\n"
+                             "multi_linked_files: "LPU64"\n"
+                             "dirent_repaired: "LPU64"\n"
+                             "linkea_repaired: "LPU64"\n"
                              "nlinks_repaired: "LPU64"\n"
                              "lost_found: "LPU64"\n"
                              "success_count: %u\n"
@@ -1174,8 +1212,8 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                              "run_time_phase2: %u seconds\n"
                              "average_speed_phase1: "LPU64" items/sec\n"
                              "average_speed_phase2: N/A\n"
-                             "real-time_speed_phase1: "LPU64" items/sec\n"
-                             "real-time_speed_phase2: N/A\n",
+                             "real_time_speed_phase1: "LPU64" items/sec\n"
+                             "real_time_speed_phase2: N/A\n",
                              checked,
                              ns->ln_objs_checked_phase2,
                              ns->ln_items_repaired,
@@ -1184,6 +1222,8 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                              ns->ln_objs_failed_phase2,
                              ns->ln_dirs_checked,
                              ns->ln_mlinked_checked,
+                             ns->ln_dirent_repaired,
+                             ns->ln_linkea_repaired,
                              ns->ln_objs_nlink_repaired,
                              ns->ln_objs_lost_found,
                              ns->ln_success_count,
@@ -1191,11 +1231,6 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                              ns->ln_run_time_phase2,
                              speed,
                              new_checked);
-               if (rc <= 0)
-                       goto out;
-
-               buf += rc;
-               len -= rc;
 
                LASSERT(lfsck->li_di_oit != NULL);
 
@@ -1217,16 +1252,14 @@ 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);
                        pos.lp_dir_cookie = 0;
                }
                spin_unlock(&lfsck->li_lock);
-               rc = lfsck_pos_dump(&buf, &len, &pos, "current_position");
-               if (rc <= 0)
-                       goto out;
+               lfsck_pos_dump(m, &pos, "current_position");
        } else if (ns->ln_status == LS_SCANNING_PHASE2) {
                cfs_duration_t duration = cfs_time_current() -
                                          lfsck->li_time_last_checkpoint;
@@ -1234,7 +1267,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                                com->lc_new_checked;
                __u64 speed1 = ns->ln_items_checked;
                __u64 speed2 = checked;
-               __u64 new_checked = com->lc_new_checked * CFS_HZ;
+               __u64 new_checked = com->lc_new_checked * HZ;
                __u32 rtime = ns->ln_run_time_phase2 +
                              cfs_duration_sec(duration + HALF_SEC);
 
@@ -1244,15 +1277,16 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                        do_div(speed1, ns->ln_run_time_phase1);
                if (rtime != 0)
                        do_div(speed2, rtime);
-               rc = snprintf(buf, len,
-                             "checked_phase1: "LPU64"\n"
+               seq_printf(m, "checked_phase1: "LPU64"\n"
                              "checked_phase2: "LPU64"\n"
                              "updated_phase1: "LPU64"\n"
                              "updated_phase2: "LPU64"\n"
                              "failed_phase1: "LPU64"\n"
                              "failed_phase2: "LPU64"\n"
-                             "dirs: "LPU64"\n"
-                             "M-linked: "LPU64"\n"
+                             "directories: "LPU64"\n"
+                             "multi_linked_files: "LPU64"\n"
+                             "dirent_repaired: "LPU64"\n"
+                             "linkea_repaired: "LPU64"\n"
                              "nlinks_repaired: "LPU64"\n"
                              "lost_found: "LPU64"\n"
                              "success_count: %u\n"
@@ -1260,8 +1294,8 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                              "run_time_phase2: %u seconds\n"
                              "average_speed_phase1: "LPU64" items/sec\n"
                              "average_speed_phase2: "LPU64" objs/sec\n"
-                             "real-time_speed_phase1: N/A\n"
-                             "real-time_speed_phase2: "LPU64" objs/sec\n"
+                             "real_time_speed_phase1: N/A\n"
+                             "real_time_speed_phase2: "LPU64" objs/sec\n"
                              "current_position: "DFID"\n",
                              ns->ln_items_checked,
                              checked,
@@ -1271,6 +1305,8 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                              ns->ln_objs_failed_phase2,
                              ns->ln_dirs_checked,
                              ns->ln_mlinked_checked,
+                             ns->ln_dirent_repaired,
+                             ns->ln_linkea_repaired,
                              ns->ln_objs_nlink_repaired,
                              ns->ln_objs_lost_found,
                              ns->ln_success_count,
@@ -1280,11 +1316,6 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                              speed2,
                              new_checked,
                              PFID(&ns->ln_fid_latest_scanned_phase2));
-               if (rc <= 0)
-                       goto out;
-
-               buf += rc;
-               len -= rc;
        } else {
                __u64 speed1 = ns->ln_items_checked;
                __u64 speed2 = ns->ln_objs_checked_phase2;
@@ -1293,15 +1324,16 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                        do_div(speed1, ns->ln_run_time_phase1);
                if (ns->ln_run_time_phase2 != 0)
                        do_div(speed2, ns->ln_run_time_phase2);
-               rc = snprintf(buf, len,
-                             "checked_phase1: "LPU64"\n"
+               seq_printf(m, "checked_phase1: "LPU64"\n"
                              "checked_phase2: "LPU64"\n"
                              "updated_phase1: "LPU64"\n"
                              "updated_phase2: "LPU64"\n"
                              "failed_phase1: "LPU64"\n"
                              "failed_phase2: "LPU64"\n"
-                             "dirs: "LPU64"\n"
-                             "M-linked: "LPU64"\n"
+                             "directories: "LPU64"\n"
+                             "multi_linked_files: "LPU64"\n"
+                             "dirent_repaired: "LPU64"\n"
+                             "linkea_repaired: "LPU64"\n"
                              "nlinks_repaired: "LPU64"\n"
                              "lost_found: "LPU64"\n"
                              "success_count: %u\n"
@@ -1309,8 +1341,8 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                              "run_time_phase2: %u seconds\n"
                              "average_speed_phase1: "LPU64" items/sec\n"
                              "average_speed_phase2: "LPU64" objs/sec\n"
-                             "real-time_speed_phase1: N/A\n"
-                             "real-time_speed_phase2: N/A\n"
+                             "real_time_speed_phase1: N/A\n"
+                             "real_time_speed_phase2: N/A\n"
                              "current_position: N/A\n",
                              ns->ln_items_checked,
                              ns->ln_objs_checked_phase2,
@@ -1320,6 +1352,8 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                              ns->ln_objs_failed_phase2,
                              ns->ln_dirs_checked,
                              ns->ln_mlinked_checked,
+                             ns->ln_dirent_repaired,
+                             ns->ln_linkea_repaired,
                              ns->ln_objs_nlink_repaired,
                              ns->ln_objs_lost_found,
                              ns->ln_success_count,
@@ -1327,27 +1361,21 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com,
                              ns->ln_run_time_phase2,
                              speed1,
                              speed2);
-               if (rc <= 0)
-                       goto out;
-
-               buf += rc;
-               len -= rc;
        }
-       ret = save - len;
-
 out:
        up_read(&com->lc_sem);
-       return ret;
+       return 0;
 }
 
-static int lfsck_namespace_double_scan(const struct lu_env *env,
-                                      struct lfsck_component *com)
+static int lfsck_namespace_double_scan_main(void *args)
 {
+       struct lfsck_thread_args *lta   = args;
+       const struct lu_env     *env    = &lta->lta_env;
+       struct lfsck_component  *com    = lta->lta_com;
        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;
@@ -1355,17 +1383,21 @@ static int lfsck_namespace_double_scan(const struct lu_env *env,
        struct dt_key           *key;
        struct lu_fid            fid;
        int                      rc;
-       __u8                     flags;
+       __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 +
+       CDEBUG(D_LFSCK, "%s: namespace LFSCK phase2 scan start\n",
+              lfsck_lfsck2name(lfsck));
+
+       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);
        if (IS_ERR(di))
-               RETURN(PTR_ERR(di));
+               GOTO(out, rc = PTR_ERR(di));
 
        fid_cpu_to_be(&fid, &ns->ln_fid_latest_scanned_phase2);
        rc = iops->get(env, di, (const struct dt_key *)&fid);
@@ -1416,8 +1448,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++;
@@ -1435,13 +1467,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;
@@ -1450,13 +1482,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);
 
@@ -1470,8 +1502,9 @@ put:
 
 fini:
        iops->fini(env, di);
-       down_write(&com->lc_sem);
 
+out:
+       down_write(&com->lc_sem);
        ns->ln_run_time_phase2 += cfs_duration_sec(cfs_time_current() +
                                HALF_SEC - lfsck->li_time_last_checkpoint);
        ns->ln_time_last_checkpoint = cfs_time_current_sec();
@@ -1482,32 +1515,79 @@ 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) {
-               if (lfsck->li_paused)
-                       ns->ln_status = LS_PAUSED;
-               else
+               ns->ln_status = lfsck->li_status;
+               if (ns->ln_status == 0)
                        ns->ln_status = LS_STOPPED;
        } else {
                ns->ln_status = LS_FAILED;
        }
 
-       if (ns->ln_status != LS_PAUSED) {
-               spin_lock(&lfsck->li_lock);
-               cfs_list_del_init(&com->lc_link);
-               cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle);
-               spin_unlock(&lfsck->li_lock);
-       }
+       CDEBUG(D_LFSCK, "%s: namespace LFSCK phase2 scan finished, status %d: "
+             "rc = %d\n", lfsck_lfsck2name(lfsck), ns->ln_status, rc);
 
        rc = lfsck_namespace_store(env, com, false);
-
        up_write(&com->lc_sem);
+       if (atomic_dec_and_test(&lfsck->li_double_scan_count))
+               wake_up_all(&thread->t_ctl_waitq);
+
+       lfsck_thread_args_fini(lta);
+
+       return rc;
+}
+
+static int lfsck_namespace_double_scan(const struct lu_env *env,
+                                      struct lfsck_component *com)
+{
+       struct lfsck_instance           *lfsck = com->lc_lfsck;
+       struct lfsck_namespace          *ns    = com->lc_file_ram;
+       struct lfsck_thread_args        *lta;
+       struct task_struct              *task;
+       int                              rc;
+       ENTRY;
+
+       if (unlikely(ns->ln_status != LS_SCANNING_PHASE2))
+               RETURN(0);
+
+       lta = lfsck_thread_args_init(lfsck, com, NULL);
+       if (IS_ERR(lta))
+               GOTO(out, rc = PTR_ERR(lta));
+
+       atomic_inc(&lfsck->li_double_scan_count);
+       task = kthread_run(lfsck_namespace_double_scan_main, lta,
+                          "lfsck_namespace");
+       if (IS_ERR(task)) {
+               atomic_dec(&lfsck->li_double_scan_count);
+               lfsck_thread_args_fini(lta);
+               GOTO(out, rc = PTR_ERR(task));
+       }
+
+       RETURN(0);
+
+out:
+       CERROR("%s: cannot start LFSCK namespace thread: rc = %d\n",
+              lfsck_lfsck2name(lfsck), rc);
        return rc;
 }
 
+static int lfsck_namespace_in_notify(const struct lu_env *env,
+                                    struct lfsck_component *com,
+                                    struct lfsck_request *lr)
+{
+       return 0;
+}
+
+static int lfsck_namespace_query(const struct lu_env *env,
+                                struct lfsck_component *com)
+{
+       struct lfsck_namespace *ns = com->lc_file_ram;
+
+       return ns->ln_status;
+}
+
 static struct lfsck_operations lfsck_namespace_ops = {
        .lfsck_reset            = lfsck_namespace_reset,
        .lfsck_fail             = lfsck_namespace_fail,
@@ -1518,13 +1598,96 @@ static struct lfsck_operations lfsck_namespace_ops = {
        .lfsck_post             = lfsck_namespace_post,
        .lfsck_dump             = lfsck_namespace_dump,
        .lfsck_double_scan      = lfsck_namespace_double_scan,
+       .lfsck_in_notify        = lfsck_namespace_in_notify,
+       .lfsck_query            = lfsck_namespace_query,
 };
 
+/**
+ * Verify the specified linkEA entry for the given directory object.
+ * If the object has no such linkEA entry or it has more other linkEA
+ * entries, then re-generate the linkEA with the given information.
+ *
+ * \param[in] env      pointer to the thread context
+ * \param[in] dev      pointer to the dt_device
+ * \param[in] obj      pointer to the dt_object to be handled
+ * \param[in] cname    the name for the child in the parent directory
+ * \param[in] pfid     the parent directory's FID for the linkEA
+ *
+ * \retval             0 for success
+ * \retval             negative error number on failure
+ */
+int lfsck_verify_linkea(const struct lu_env *env, struct dt_device *dev,
+                       struct dt_object *obj, const struct lu_name *cname,
+                       const struct lu_fid *pfid)
+{
+       struct linkea_data       ldata  = { 0 };
+       struct lu_buf            linkea_buf;
+       struct thandle          *th;
+       int                      rc;
+       int                      fl     = LU_XATTR_CREATE;
+       bool                     dirty  = false;
+       ENTRY;
+
+       LASSERT(S_ISDIR(lfsck_object_type(obj)));
+
+       rc = lfsck_links_read(env, obj, &ldata);
+       if (rc == -ENODATA) {
+               dirty = true;
+       } else if (rc == 0) {
+               fl = LU_XATTR_REPLACE;
+               if (ldata.ld_leh->leh_reccount != 1) {
+                       dirty = true;
+               } else {
+                       rc = linkea_links_find(&ldata, cname, pfid);
+                       if (rc != 0)
+                               dirty = true;
+               }
+       }
+
+       if (!dirty)
+               RETURN(rc);
+
+       rc = linkea_data_new(&ldata, &lfsck_env_info(env)->lti_linkea_buf);
+       if (rc != 0)
+               RETURN(rc);
+
+       rc = linkea_add_buf(&ldata, cname, pfid);
+       if (rc != 0)
+               RETURN(rc);
+
+       linkea_buf.lb_buf = ldata.ld_buf->lb_buf;
+       linkea_buf.lb_len = ldata.ld_leh->leh_len;
+       th = dt_trans_create(env, dev);
+       if (IS_ERR(th))
+               RETURN(PTR_ERR(th));
+
+       rc = dt_declare_xattr_set(env, obj, &linkea_buf,
+                                 XATTR_NAME_LINK, fl, th);
+       if (rc != 0)
+               GOTO(stop, rc = PTR_ERR(th));
+
+       rc = dt_trans_start_local(env, dev, th);
+       if (rc != 0)
+               GOTO(stop, rc);
+
+       dt_write_lock(env, obj, 0);
+       rc = dt_xattr_set(env, obj, &linkea_buf,
+                         XATTR_NAME_LINK, fl, th, BYPASS_CAPA);
+       dt_write_unlock(env, obj);
+
+       GOTO(stop, rc);
+
+stop:
+       dt_trans_stop(env, dev, th);
+       return rc;
+}
+
 int lfsck_namespace_setup(const struct lu_env *env,
                          struct lfsck_instance *lfsck)
 {
        struct lfsck_component  *com;
        struct lfsck_namespace  *ns;
+       struct dt_object        *root = NULL;
        struct dt_object        *obj;
        int                      rc;
        ENTRY;
@@ -1535,12 +1698,12 @@ int lfsck_namespace_setup(const struct lu_env *env,
        if (com == NULL)
                RETURN(-ENOMEM);
 
-       CFS_INIT_LIST_HEAD(&com->lc_link);
-       CFS_INIT_LIST_HEAD(&com->lc_link_dir);
+       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_NAMESPACE;
+       com->lc_type = LFSCK_TYPE_NAMESPACE;
        com->lc_ops = &lfsck_namespace_ops;
        com->lc_file_size = sizeof(struct lfsck_namespace);
        OBD_ALLOC(com->lc_file_ram, com->lc_file_size);
@@ -1551,8 +1714,14 @@ int lfsck_namespace_setup(const struct lu_env *env,
        if (com->lc_file_disk == NULL)
                GOTO(out, rc = -ENOMEM);
 
-       obj = local_index_find_or_create(env, lfsck->li_los,
-                                        lfsck->li_local_root,
+       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_index_find_or_create(env, lfsck->li_los, root,
                                         lfsck_namespace_name,
                                         S_IFREG | S_IRUGO | S_IWUSR,
                                         &dt_lfsck_features);
@@ -1572,16 +1741,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:
-               cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle);
+               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_namespace status: %u\n",
+               CERROR("%s: unknown lfsck_namespace status %d\n",
                       lfsck_lfsck2name(lfsck), ns->ln_status);
                /* fall through */
        case LS_SCANNING_PHASE1:
@@ -1593,15 +1764,22 @@ int lfsck_namespace_setup(const struct lu_env *env,
                /* fall through */
        case LS_PAUSED:
        case LS_CRASHED:
-               cfs_list_add_tail(&com->lc_link, &lfsck->li_list_scan);
-               cfs_list_add_tail(&com->lc_link_dir, &lfsck->li_list_dir);
+               spin_lock(&lfsck->li_lock);
+               list_add_tail(&com->lc_link, &lfsck->li_list_scan);
+               list_add_tail(&com->lc_link_dir, &lfsck->li_list_dir);
+               spin_unlock(&lfsck->li_lock);
                break;
        }
 
        GOTO(out, rc = 0);
 
 out:
-       if (rc != 0)
+       if (root != NULL && !IS_ERR(root))
+               lu_object_put(env, &root->do_lu);
+       if (rc != 0) {
                lfsck_component_cleanup(env, com);
+               CERROR("%s: fail to init namespace LFSCK component: rc = %d\n",
+                      lfsck_lfsck2name(lfsck), rc);
+       }
        return rc;
 }