X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Flfsck%2Flfsck_namespace.c;h=da21ef3c81d857014326de7beff2fb4e455e0347;hp=4dccb70bf3b4c95e176f931a670f23266122d7e1;hb=7be4f1cf3adaa225fcbe7f9c00335ad2fc23f837;hpb=d46286bdfb704cc56972863cb067244b8bb6df43 diff --git a/lustre/lfsck/lfsck_namespace.c b/lustre/lfsck/lfsck_namespace.c index 4dccb70..da21ef3 100644 --- a/lustre/lfsck/lfsck_namespace.c +++ b/lustre/lfsck/lfsck_namespace.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -138,16 +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("%s: invalid lfsck_namespace magic %#x != %#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("%s: 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,42 +167,34 @@ 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("%s: fail to create trans for storing lfsck_namespace: " - "rc = %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("%s: fail to declare trans for storing lfsck_namespace: " - "rc = %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("%s: fail to start trans for storing lfsck_namespace: " - "rc = %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("%s: 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; } @@ -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, @@ -535,9 +524,7 @@ again: goto shrink; parent = lfsck_object_find(env, lfsck, pfid); - if (parent == NULL) - goto shrink; - else if (IS_ERR(parent)) + if (IS_ERR(parent)) GOTO(stop, rc = PTR_ERR(parent)); if (!dt_object_exists(parent)) @@ -600,9 +587,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; } @@ -627,10 +616,10 @@ stop: if (rc == 0 && !lfsck_is_dead_obj(child) && ldata.ld_leh != NULL && ldata.ld_leh->leh_reccount != la->la_nlink) - CWARN("%s: the object "DFID" linkEA entry count %u " - "may not match its hardlink count %u\n", - lfsck_lfsck2name(lfsck), PFID(cfid), - ldata.ld_leh->leh_reccount, la->la_nlink); + 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); } @@ -660,12 +649,10 @@ static int lfsck_namespace_reset(const struct lu_env *env, root = dt_locate(env, lfsck->li_bottom, &lfsck->li_local_root_fid); if (IS_ERR(root)) - RETURN(PTR_ERR(root)); + GOTO(log, rc = PTR_ERR(root)); - if (unlikely(!dt_try_as_dir(env, root))) { - lu_object_put(env, &root->do_lu); - RETURN(-ENOTDIR); - } + if (unlikely(!dt_try_as_dir(env, root))) + GOTO(put, rc = -ENOTDIR); down_write(&com->lc_sem); if (init) { @@ -706,7 +693,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; } @@ -720,9 +712,17 @@ lfsck_namespace_fail(const struct lu_env *env, struct lfsck_component *com, 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); } @@ -737,7 +737,6 @@ static int lfsck_namespace_checkpoint(const struct lu_env *env, return 0; down_write(&com->lc_sem); - if (init) { ns->ln_pos_latest_start = lfsck->li_pos_current; } else { @@ -750,8 +749,14 @@ 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; } @@ -770,12 +775,15 @@ static int lfsck_namespace_prep(const struct lu_env *env, if (rc == 0) rc = lfsck_set_param(env, lfsck, lsp->lsp_start, true); - if (rc != 0) + 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); @@ -783,11 +791,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; @@ -804,16 +811,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; @@ -823,8 +830,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; } @@ -859,6 +870,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; @@ -947,6 +959,7 @@ again: nodata: if (bk->lb_param & LPF_DRYRUN) { ns->ln_linkea_repaired++; + log = true; repaired = true; goto record; } @@ -980,6 +993,7 @@ nodata: count = ldata.ld_leh->leh_reccount; ns->ln_linkea_repaired++; + log = true; repaired = true; } else { GOTO(stop, rc); @@ -1006,6 +1020,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++; @@ -1023,6 +1044,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, @@ -1055,7 +1081,6 @@ static int lfsck_namespace_post(const struct lu_env *env, int rc; down_write(&com->lc_sem); - spin_lock(&lfsck->li_lock); if (!init) ns->ln_pos_last_checkpoint = lfsck->li_pos_current; @@ -1063,23 +1088,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) { ns->ln_status = lfsck->li_status; if (ns->ln_status == 0) ns->ln_status = LS_STOPPED; if (ns->ln_status != LS_PAUSED) { - 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); } } 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); @@ -1092,72 +1114,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 = com->lc_file_ram; - int save = len; - int ret = -ENOSPC; int rc; down_read(&com->lc_sem); - rc = snprintf(buf, len, - "name: lfsck_namespace\n" - "magic: %#x\n" - "version: %d\n" - "status: %s\n", - ns->ln_magic, - bk->lb_version, - lfsck_status2names(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; @@ -1177,15 +1193,14 @@ 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" @@ -1195,8 +1210,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, @@ -1214,11 +1229,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); @@ -1247,9 +1257,7 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, 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; @@ -1267,15 +1275,14 @@ 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" @@ -1285,8 +1292,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, @@ -1307,11 +1314,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; @@ -1320,15 +1322,14 @@ 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" @@ -1338,8 +1339,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, @@ -1358,17 +1359,10 @@ 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_main(void *args) @@ -1390,6 +1384,9 @@ static int lfsck_namespace_double_scan_main(void *args) __u8 flags = 0; ENTRY; + 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(); @@ -1429,10 +1426,7 @@ static int lfsck_namespace_double_scan_main(void *args) fid_be_to_cpu(&fid, (const struct lu_fid *)key); target = lfsck_object_find(env, lfsck, &fid); down_write(&com->lc_sem); - if (target == NULL) { - rc = 0; - goto checkpoint; - } else if (IS_ERR(target)) { + if (IS_ERR(target)) { rc = PTR_ERR(target); goto checkpoint; } @@ -1527,6 +1521,9 @@ out: ns->ln_status = LS_FAILED; } + 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)) @@ -1552,22 +1549,23 @@ static int lfsck_namespace_double_scan(const struct lu_env *env, lta = lfsck_thread_args_init(lfsck, com, NULL); if (IS_ERR(lta)) - RETURN(PTR_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)) { - rc = PTR_ERR(task); - CERROR("%s: cannot start LFSCK namespace thread: rc = %d\n", - lfsck_lfsck2name(lfsck), rc); atomic_dec(&lfsck->li_double_scan_count); lfsck_thread_args_fini(lta); - } else { - rc = 0; + GOTO(out, rc = PTR_ERR(task)); } - RETURN(rc); + 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, @@ -1599,6 +1597,86 @@ static struct lfsck_operations lfsck_namespace_ops = { .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) { @@ -1615,12 +1693,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); @@ -1665,11 +1743,11 @@ int lfsck_namespace_setup(const struct lu_env *env, case LS_FAILED: case LS_STOPPED: spin_lock(&lfsck->li_lock); - cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle); + list_add_tail(&com->lc_link, &lfsck->li_list_idle); spin_unlock(&lfsck->li_lock); break; default: - CERROR("%s: unknown lfsck_namespace status: rc = %u\n", + CERROR("%s: unknown lfsck_namespace status %d\n", lfsck_lfsck2name(lfsck), ns->ln_status); /* fall through */ case LS_SCANNING_PHASE1: @@ -1682,8 +1760,8 @@ int lfsck_namespace_setup(const struct lu_env *env, case LS_PAUSED: case LS_CRASHED: spin_lock(&lfsck->li_lock); - cfs_list_add_tail(&com->lc_link, &lfsck->li_list_scan); - cfs_list_add_tail(&com->lc_link_dir, &lfsck->li_list_dir); + 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; } @@ -1693,7 +1771,10 @@ int lfsck_namespace_setup(const struct lu_env *env, out: if (root != NULL && !IS_ERR(root)) lu_object_put(env, &root->do_lu); - if (rc != 0) + 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; }