X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Flfsck%2Flfsck_namespace.c;h=2c8918e0434429c8afe6a76217b467f260162752;hb=12e311012ae337276dc3e7da3e7ad8d85d11e764;hp=3f49e3c16d506498f48a7b149c552e7653888d39;hpb=ddb28cadcaaf4a443aa341e450ae651863816ac8;p=fs%2Flustre-release.git diff --git a/lustre/lfsck/lfsck_namespace.c b/lustre/lfsck/lfsck_namespace.c index 3f49e3c..2c8918e 100644 --- a/lustre/lfsck/lfsck_namespace.c +++ b/lustre/lfsck/lfsck_namespace.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -46,72 +45,76 @@ 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); } /** @@ -134,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; } @@ -164,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)); @@ -315,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, @@ -473,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; @@ -598,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; } @@ -625,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); } @@ -650,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)); @@ -670,14 +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); lfsck_object_put(env, com->lc_obj); com->lc_obj = NULL; - dto = local_index_find_or_create(env, lfsck->li_los, lfsck->li_local_root, + dto = local_index_find_or_create(env, lfsck->li_los, root, lfsck_namespace_name, S_IFREG | S_IRUGO | S_IWUSR, &dt_lfsck_features); @@ -695,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; } @@ -702,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); } @@ -718,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 { @@ -739,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); @@ -769,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; @@ -790,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; @@ -809,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; } @@ -835,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; @@ -847,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; @@ -857,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) && @@ -932,6 +960,8 @@ again: nodata: if (bk->lb_param & LPF_DRYRUN) { + ns->ln_linkea_repaired++; + log = true; repaired = true; goto record; } @@ -964,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); @@ -990,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++; @@ -1007,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, @@ -1014,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); @@ -1029,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; @@ -1042,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); @@ -1071,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; @@ -1157,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" @@ -1173,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, @@ -1183,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, @@ -1190,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); @@ -1216,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; @@ -1243,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" @@ -1259,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, @@ -1270,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, @@ -1279,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; @@ -1292,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" @@ -1308,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, @@ -1319,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, @@ -1326,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 = <a->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; @@ -1354,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); @@ -1415,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++; @@ -1434,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; @@ -1449,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); @@ -1469,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(); @@ -1481,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, @@ -1517,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; @@ -1534,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); @@ -1550,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); @@ -1571,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: @@ -1592,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; }