X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Flfsck%2Flfsck_namespace.c;h=931ffa29a18eaa6a982f1b38d9ab977e13625e18;hp=bfbed00ff7a966bbd918e52c8e03a74839830bec;hb=445da16c2ac0475b1c1077c822800b68cdbb7ce3;hpb=5434d9402f6deb46f25bcf4c92726711b9d77d00 diff --git a/lustre/lfsck/lfsck_namespace.c b/lustre/lfsck/lfsck_namespace.c index bfbed00..931ffa2 100644 --- a/lustre/lfsck/lfsck_namespace.c +++ b/lustre/lfsck/lfsck_namespace.c @@ -248,7 +248,7 @@ static void lfsck_namespace_record_failure(const struct lu_env *env, ns->ln_pos_first_inconsistent = pos; CDEBUG(D_LFSCK, "%s: namespace LFSCK hit first non-repaired " - "inconsistency at the pos ["LPU64", "DFID", "LPX64"]\n", + "inconsistency at the pos [%llu, "DFID", %#llx]\n", lfsck_lfsck2name(lfsck), ns->ln_pos_first_inconsistent.lp_oit_cookie, PFID(&ns->ln_pos_first_inconsistent.lp_dir_parent), @@ -271,7 +271,7 @@ static int lfsck_namespace_load_bitmap(const struct lu_env *env, struct dt_object *obj = com->lc_obj; struct lfsck_assistant_data *lad = com->lc_data; struct lfsck_namespace *ns = com->lc_file_ram; - cfs_bitmap_t *bitmap = lad->lad_bitmap; + struct cfs_bitmap *bitmap = lad->lad_bitmap; ssize_t size; __u32 nbits; int rc; @@ -288,7 +288,7 @@ static int lfsck_namespace_load_bitmap(const struct lu_env *env, if (nbits > bitmap->size) { __u32 new_bits = bitmap->size; - cfs_bitmap_t *new_bitmap; + struct cfs_bitmap *new_bitmap; while (new_bits < nbits) new_bits <<= 1; @@ -327,12 +327,6 @@ static int lfsck_namespace_load_bitmap(const struct lu_env *env, /** * Load namespace LFSCK statistics information from the trace file. * - * For old release (Lustre-2.6 or older), the statistics information was - * stored as XATTR_NAME_LFSCK_NAMESPACE_OLD EA. But in Lustre-2.7, we need - * more statistics information. To avoid confusing old MDT when downgrade, - * Lustre-2.7 stores the namespace LFSCK statistics information as new - * XATTR_NAME_LFSCK_NAMESPACE EA. - * * \param[in] env pointer to the thread context * \param[in] com pointer to the lfsck component * @@ -367,35 +361,24 @@ static int lfsck_namespace_load(const struct lu_env *env, lfsck_lfsck2name(com->lc_lfsck), len, rc); if (rc >= 0) rc = -ESTALE; - } else { - /* Check whether it is old trace file or not. - * If yes, it should be reset via returning -ESTALE. */ - rc = dt_xattr_get(env, com->lc_obj, - lfsck_buf_get(env, com->lc_file_disk, len), - XATTR_NAME_LFSCK_NAMESPACE_OLD); - if (rc >= 0) - rc = -ESTALE; } return rc; } static int lfsck_namespace_store(const struct lu_env *env, - struct lfsck_component *com, bool init) + struct lfsck_component *com) { struct dt_object *obj = com->lc_obj; struct lfsck_instance *lfsck = com->lc_lfsck; struct lfsck_namespace *ns = com->lc_file_ram; struct lfsck_assistant_data *lad = com->lc_data; struct dt_device *dev = lfsck_obj2dev(obj); - cfs_bitmap_t *bitmap = NULL; + struct cfs_bitmap *bitmap = NULL; struct thandle *handle; __u32 nbits = 0; int len = com->lc_file_size; int rc; -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 8, 53, 0) - struct lu_buf tbuf = { &len, sizeof(len) }; -#endif ENTRY; if (lad != NULL) { @@ -427,20 +410,6 @@ static int lfsck_namespace_store(const struct lu_env *env, GOTO(out, rc); } -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 8, 53, 0) - /* To be compatible with old Lustre-2.x MDT (x <= 6), generate dummy - * XATTR_NAME_LFSCK_NAMESPACE_OLD EA, then when downgrade to Lustre-2.x, - * the old LFSCK will find "invalid" XATTR_NAME_LFSCK_NAMESPACE_OLD EA, - * then reset the namespace LFSCK trace file. */ - if (init) { - rc = dt_declare_xattr_set(env, obj, &tbuf, - XATTR_NAME_LFSCK_NAMESPACE_OLD, - LU_XATTR_CREATE, handle); - if (rc != 0) - GOTO(out, rc); - } -#endif - rc = dt_trans_start_local(env, dev, handle); if (rc != 0) GOTO(out, rc); @@ -453,13 +422,6 @@ static int lfsck_namespace_store(const struct lu_env *env, lfsck_buf_get(env, bitmap->data, nbits >> 3), XATTR_NAME_LFSCK_BITMAP, 0, handle); -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 8, 53, 0) - if (rc == 0 && init) - rc = dt_xattr_set(env, obj, &tbuf, - XATTR_NAME_LFSCK_NAMESPACE_OLD, - LU_XATTR_CREATE, handle); -#endif - GOTO(out, rc); out: @@ -540,7 +502,7 @@ static int lfsck_namespace_init(const struct lu_env *env, ns->ln_magic = LFSCK_NAMESPACE_MAGIC; ns->ln_status = LS_INIT; down_write(&com->lc_sem); - rc = lfsck_namespace_store(env, com, true); + rc = lfsck_namespace_store(env, com); up_write(&com->lc_sem); if (rc == 0) rc = lfsck_namespace_load_sub_trace_files(env, com, true); @@ -696,11 +658,9 @@ static int lfsck_declare_namespace_exec_dir(const struct lu_env *env, /* For destroying all invalid linkEA entries. */ rc = dt_declare_xattr_del(env, obj, XATTR_NAME_LINK, handle); - if (rc != 0) - return rc; - - /* For insert new linkEA entry. */ - rc = dt_declare_xattr_set(env, obj, + if (rc == 0) + /* For insert new linkEA entry. */ + rc = dt_declare_xattr_set(env, obj, lfsck_buf_get_const(env, NULL, DEFAULT_LINKEA_SIZE), XATTR_NAME_LINK, 0, handle); return rc; @@ -721,7 +681,10 @@ int __lfsck_links_read(const struct lu_env *env, struct dt_object *obj, if (rc == -ERANGE) { /* Buf was too small, figure out what we need. */ rc = dt_xattr_get(env, obj, &LU_BUF_NULL, XATTR_NAME_LINK); - if (rc <= 0) + if (unlikely(rc == 0)) + return -ENODATA; + + if (rc < 0) return rc; lu_buf_realloc(ldata->ld_buf, rc); @@ -731,6 +694,9 @@ int __lfsck_links_read(const struct lu_env *env, struct dt_object *obj, rc = dt_xattr_get(env, obj, ldata->ld_buf, XATTR_NAME_LINK); } + if (unlikely(rc == 0)) + return -ENODATA; + if (rc > 0) rc = linkea_init(ldata); @@ -814,16 +780,59 @@ static int lfsck_links_write(const struct lu_env *env, struct dt_object *obj, return dt_xattr_set(env, obj, buf, XATTR_NAME_LINK, 0, handle); } -static void lfsck_namespace_unpack_linkea_entry(struct linkea_data *ldata, - struct lu_name *cname, - struct lu_fid *pfid, - char *buf) +static int lfsck_namespace_unpack_linkea_entry(struct linkea_data *ldata, + struct lu_name *cname, + struct lu_fid *pfid, + char *buf, const int buflen) { linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, cname, pfid); + if (unlikely(ldata->ld_reclen <= 0 || + ldata->ld_reclen + sizeof(struct link_ea_header) > + ldata->ld_leh->leh_len || + cname->ln_namelen <= 0 || + cname->ln_namelen > NAME_MAX || + cname->ln_namelen >= buflen || + !fid_is_sane(pfid))) + return -EINVAL; + /* To guarantee the 'name' is terminated with '0'. */ memcpy(buf, cname->ln_name, cname->ln_namelen); buf[cname->ln_namelen] = 0; cname->ln_name = buf; + + return 0; +} + +static void lfsck_linkea_del_buf(struct linkea_data *ldata, + const struct lu_name *lname) +{ + LASSERT(ldata->ld_leh != NULL && ldata->ld_lee != NULL); + + /* If current record is corrupted, all the subsequent + * records will be dropped. */ + if (unlikely(ldata->ld_reclen <= 0 || + ldata->ld_reclen + sizeof(struct link_ea_header) > + ldata->ld_leh->leh_len)) { + void *ptr = ldata->ld_lee; + + ldata->ld_leh->leh_len = sizeof(struct link_ea_header); + ldata->ld_leh->leh_reccount = 0; + linkea_first_entry(ldata); + while (ldata->ld_lee != NULL && + (char *)ldata->ld_lee < (char *)ptr) { + int reclen = (ldata->ld_lee->lee_reclen[0] << 8) | + ldata->ld_lee->lee_reclen[1]; + + ldata->ld_leh->leh_len += reclen; + ldata->ld_leh->leh_reccount++; + ldata->ld_lee = (struct link_ea_entry *) + ((char *)ldata->ld_lee + reclen); + } + + ldata->ld_lee = NULL; + } else { + linkea_del_buf(ldata, lname); + } } static int lfsck_namespace_filter_linkea_entry(struct linkea_data *ldata, @@ -847,7 +856,7 @@ static int lfsck_namespace_filter_linkea_entry(struct linkea_data *ldata, if (!remove) break; - linkea_del_buf(ldata, cname); + lfsck_linkea_del_buf(ldata, cname); } else { linkea_next_entry(ldata); } @@ -915,7 +924,7 @@ static int lfsck_namespace_insert_orphan(const struct lu_env *env, struct thandle *th = NULL; struct lfsck_lock_handle *pllh = &info->lti_llh; struct lustre_handle clh = { 0 }; - struct linkea_data ldata = { NULL }; + struct linkea_data ldata2 = { NULL }; struct lu_buf linkea_buf; int namelen; int idx = 0; @@ -968,11 +977,11 @@ again: cname->ln_name = info->lti_key; cname->ln_namelen = namelen; - rc = linkea_data_new(&ldata, &info->lti_linkea_buf2); + rc = linkea_data_new(&ldata2, &info->lti_linkea_buf2); if (rc != 0) GOTO(log, rc); - rc = linkea_add_buf(&ldata, cname, pfid); + rc = linkea_add_buf(&ldata2, cname, pfid); if (rc != 0) GOTO(log, rc); @@ -982,8 +991,8 @@ again: if (rc != 0) GOTO(log, rc); - lfsck_buf_init(&linkea_buf, ldata.ld_buf->lb_buf, - ldata.ld_leh->leh_len); + lfsck_buf_init(&linkea_buf, ldata2.ld_buf->lb_buf, + ldata2.ld_leh->leh_len); th = dt_trans_create(env, dev); if (IS_ERR(th)) GOTO(log, rc = PTR_ERR(th)); @@ -1035,9 +1044,10 @@ again: GOTO(stop, rc); dt_write_lock(env, orphan, 0); - rc = lfsck_links_read(env, orphan, &ldata); + rc = lfsck_links_read2(env, orphan, &ldata2); if (likely((rc == -ENODATA) || (rc == -EINVAL) || - (rc == 0 && ldata.ld_leh->leh_reccount == 0))) { + (rc == 0 && ldata2.ld_leh != NULL && + ldata2.ld_leh->leh_reccount == 0))) { if (lfsck->li_bookmark_ram.lb_param & LPF_DRYRUN) GOTO(unlock, rc = 1); @@ -1059,7 +1069,7 @@ again: th); } else { if (rc == 0 && count != NULL) - *count = ldata.ld_leh->leh_reccount; + *count = ldata2.ld_leh->leh_reccount; GOTO(unlock, rc); } @@ -1548,6 +1558,7 @@ static int lfsck_namespace_shrink_linkea(const struct lu_env *env, struct lustre_handle lh = { 0 }; struct linkea_data ldata_new = { NULL }; struct lu_buf linkea_buf; + int buflen = 0; int rc = 0; ENTRY; @@ -1558,20 +1569,26 @@ static int lfsck_namespace_shrink_linkea(const struct lu_env *env, GOTO(log, rc); if (next) - linkea_del_buf(ldata, cname); + lfsck_linkea_del_buf(ldata, cname); else lfsck_namespace_filter_linkea_entry(ldata, cname, pfid, true); - lfsck_buf_init(&linkea_buf, ldata->ld_buf->lb_buf, - ldata->ld_leh->leh_len); + if (ldata->ld_leh->leh_reccount > 0) { + lfsck_buf_init(&linkea_buf, ldata->ld_buf->lb_buf, + ldata->ld_leh->leh_len); + buflen = linkea_buf.lb_len; + } again: th = dt_trans_create(env, dev); if (IS_ERR(th)) GOTO(unlock1, rc = PTR_ERR(th)); - rc = dt_declare_xattr_set(env, obj, &linkea_buf, - XATTR_NAME_LINK, 0, th); + if (buflen != 0) + rc = dt_declare_xattr_set(env, obj, &linkea_buf, + XATTR_NAME_LINK, 0, th); + else + rc = dt_declare_xattr_del(env, obj, XATTR_NAME_LINK, th); if (rc != 0) GOTO(stop, rc); @@ -1585,7 +1602,8 @@ again: rc = lfsck_links_read2(env, obj, &ldata_new); if (rc != 0) - GOTO(unlock2, rc); + GOTO(unlock2, + rc = (rc == -ENODATA ? 0 : rc)); /* The specified linkEA entry has been removed by race. */ rc = linkea_links_find(&ldata_new, cname, pfid); @@ -1596,12 +1614,12 @@ again: GOTO(unlock2, rc = 1); if (next) - linkea_del_buf(&ldata_new, cname); + lfsck_linkea_del_buf(&ldata_new, cname); else lfsck_namespace_filter_linkea_entry(&ldata_new, cname, pfid, true); - if (linkea_buf.lb_len < ldata_new.ld_leh->leh_len) { + if (buflen < ldata_new.ld_leh->leh_len) { dt_write_unlock(env, obj); dt_trans_stop(env, dev, th); lfsck_buf_init(&linkea_buf, ldata_new.ld_buf->lb_buf, @@ -1609,9 +1627,14 @@ again: goto again; } - lfsck_buf_init(&linkea_buf, ldata_new.ld_buf->lb_buf, - ldata_new.ld_leh->leh_len); - rc = dt_xattr_set(env, obj, &linkea_buf, XATTR_NAME_LINK, 0, th); + if (ldata_new.ld_leh->leh_reccount > 0) { + lfsck_buf_init(&linkea_buf, ldata_new.ld_buf->lb_buf, + ldata_new.ld_leh->leh_len); + rc = dt_xattr_set(env, obj, &linkea_buf, + XATTR_NAME_LINK, 0, th); + } else { + rc = dt_xattr_del(env, obj, XATTR_NAME_LINK, th); + } GOTO(unlock2, rc = (rc == 0 ? 1 : rc)); @@ -2079,7 +2102,7 @@ int lfsck_namespace_repair_dirent(const struct lu_env *env, GOTO(stop, rc); } - if (dec) { + if (dec && S_ISDIR(type)) { rc = dt_declare_ref_del(env, parent, th); if (rc != 0) GOTO(stop, rc); @@ -2120,7 +2143,7 @@ int lfsck_namespace_repair_dirent(const struct lu_env *env, GOTO(unlock2, rc); } - if (dec) { + if (dec && S_ISDIR(type)) { rc = dt_ref_del(env, parent, th); if (rc != 0) GOTO(unlock2, rc); @@ -2357,6 +2380,7 @@ lfsck_namespace_dsd_orphan(const struct lu_env *env, * \param[out] type to tell the caller what the inconsistency is * \param[in] retry if found inconsistency, but the caller does not hold * ldlm lock on the @child, then set @retry as true + * \param[in] unknown set if does not know how to repair the inconsistency * * \retval positive number for repaired cases * \retval 0 if nothing to be repaired @@ -2370,7 +2394,7 @@ lfsck_namespace_dsd_single(const struct lu_env *env, struct linkea_data *ldata, struct lustre_handle *lh, enum lfsck_namespace_inconsistency_type *type, - bool *retry) + bool *retry, bool *unknown) { struct lfsck_thread_info *info = lfsck_env_info(env); struct lu_name *cname = &info->lti_name; @@ -2383,9 +2407,11 @@ lfsck_namespace_dsd_single(const struct lu_env *env, int rc = 0; ENTRY; - lfsck_namespace_unpack_linkea_entry(ldata, cname, &tfid, info->lti_key); + rc = lfsck_namespace_unpack_linkea_entry(ldata, cname, &tfid, + info->lti_key, + sizeof(info->lti_key)); /* The unique linkEA entry with bad parent will be handled as orphan. */ - if (!fid_is_sane(&tfid)) { + if (rc != 0) { if (!lustre_handle_is_used(lh) && retry != NULL) *retry = true; else @@ -2479,7 +2505,7 @@ lost_parent: } GOTO(out, rc); - } + } /* !dt_object_exists(parent) */ /* The unique linkEA entry with bad parent will be handled as orphan. */ if (unlikely(!dt_try_as_dir(env, parent))) { @@ -2565,7 +2591,7 @@ lost_parent: } GOTO(out, rc); - } + } /* rc == -ENOENT */ if (rc != 0) GOTO(out, rc); @@ -2590,8 +2616,18 @@ lost_parent: GOTO(out, rc); } - if (fid_is_zero(pfid)) + /* Zero FID may because the remote directroy object has invalid linkEA, + * or lost linkEA. Under such case, the LFSCK on this MDT does not know + * how to repair the inconsistency, but the namespace LFSCK on the MDT + * where its name entry resides may has more information (name, FID) to + * repair such inconsistency. So here, keep the inconsistency to avoid + * some imporper repairing. */ + if (fid_is_zero(pfid)) { + if (unknown) + *unknown = true; + GOTO(out, rc = 0); + } /* The ".." name entry is wrong, update it. */ if (!lu_fid_eq(pfid, lfsck_dto2fid(parent))) { @@ -2633,6 +2669,7 @@ out: * \param[in,out] lh ldlm lock handler for the given @child * \param[out] type to tell the caller what the inconsistency is * \param[in] lpf true if the ".." entry is under lost+found/MDTxxxx/ + * \param[in] unknown set if does not know how to repair the inconsistency * * \retval positive number for repaired cases * \retval 0 if nothing to be repaired @@ -2646,7 +2683,7 @@ lfsck_namespace_dsd_multiple(const struct lu_env *env, struct linkea_data *ldata, struct lustre_handle *lh, enum lfsck_namespace_inconsistency_type *type, - bool lpf) + bool lpf, bool *unknown) { struct lfsck_thread_info *info = lfsck_env_info(env); struct lu_name *cname = &info->lti_name; @@ -2659,24 +2696,24 @@ lfsck_namespace_dsd_multiple(const struct lu_env *env, struct dt_object *parent = NULL; struct linkea_data ldata_new = { NULL }; int dirent_count = 0; - int linkea_count = 0; int rc = 0; bool once = true; ENTRY; again: while (ldata->ld_lee != NULL) { - lfsck_namespace_unpack_linkea_entry(ldata, cname, &tfid, - info->lti_key); - /* Drop repeated linkEA entries. */ - lfsck_namespace_filter_linkea_entry(ldata, cname, &tfid, true); + rc = lfsck_namespace_unpack_linkea_entry(ldata, cname, &tfid, + info->lti_key, + sizeof(info->lti_key)); /* Drop invalid linkEA entry. */ - if (!fid_is_sane(&tfid)) { - linkea_del_buf(ldata, cname); - linkea_count++; + if (rc != 0) { + lfsck_linkea_del_buf(ldata, cname); continue; } + /* Drop repeated linkEA entries. */ + lfsck_namespace_filter_linkea_entry(ldata, cname, &tfid, true); + /* If current dotdot is the .lustre/lost+found/MDTxxxx/, * then it is possible that: the directry object has ever * been lost, but its name entry was there. In the former @@ -2706,8 +2743,7 @@ again: * there is still other chance to make the * child to be visible via other parent, then * remove this linkEA entry. */ - linkea_del_buf(ldata, cname); - linkea_count++; + lfsck_linkea_del_buf(ldata, cname); continue; } @@ -2717,8 +2753,7 @@ again: /* The linkEA entry with bad parent will be removed. */ if (unlikely(!dt_try_as_dir(env, parent))) { lfsck_object_put(env, parent); - linkea_del_buf(ldata, cname); - linkea_count++; + lfsck_linkea_del_buf(ldata, cname); continue; } @@ -2739,6 +2774,10 @@ again: if (lu_fid_eq(&tfid, cfid)) { lfsck_object_put(env, parent); + /* If the parent (that is declared via linkEA entry) + * directory contains the specified child, but such + * parent does not match the dotdot name entry, then + * trust the linkEA. */ if (!lu_fid_eq(pfid, pfid2)) { *type = LNIT_UNMATCHED_PAIRS; rc = lfsck_namespace_repair_unmatched_pairs(env, @@ -2764,15 +2803,15 @@ rebuild: if (rc < 0) RETURN(rc); - linkea_del_buf(ldata, cname); - linkea_count++; + lfsck_linkea_del_buf(ldata, cname); linkea_first_entry(ldata); /* There may be some invalid dangling name entries under * other parent directories, remove all of them. */ while (ldata->ld_lee != NULL) { - lfsck_namespace_unpack_linkea_entry(ldata, - cname, &tfid, info->lti_key); - if (!fid_is_sane(&tfid)) + rc = lfsck_namespace_unpack_linkea_entry(ldata, + cname, &tfid, info->lti_key, + sizeof(info->lti_key)); + if (rc != 0) goto next; parent = lfsck_object_find_bottom(env, lfsck, @@ -2805,13 +2844,13 @@ rebuild: dirent_count += rc; next: - linkea_del_buf(ldata, cname); + lfsck_linkea_del_buf(ldata, cname); } ns->ln_dirent_repaired += dirent_count; RETURN(rc); - } + } /* lu_fid_eq(&tfid, lfsck_dto2fid(child)) */ lfsck_ibits_unlock(lh, LCK_EX); /* The name entry references another MDT-object that may be @@ -2826,17 +2865,13 @@ next: if (rc > 0) goto rebuild; - linkea_del_buf(ldata, cname); - } + lfsck_linkea_del_buf(ldata, cname); + } /* while (ldata->ld_lee != NULL) */ linkea_first_entry(ldata); if (ldata->ld_leh->leh_reccount == 1) { rc = lfsck_namespace_dsd_single(env, com, child, pfid, ldata, - lh, type, NULL); - - if (rc == 0 && fid_is_zero(pfid) && linkea_count > 0) - rc = lfsck_namespace_rebuild_linkea(env, com, child, - ldata); + lh, type, NULL, unknown); RETURN(rc); } @@ -2909,7 +2944,6 @@ static int lfsck_namespace_repair_nlink(const struct lu_env *env, ENTRY; LASSERT(!dt_object_remote(obj)); - LASSERT(S_ISREG(lfsck_object_type(obj))); rc = lfsck_ibits_lock(env, lfsck, obj, &lh, MDS_INODELOCK_UPDATE, LCK_PW); @@ -3170,13 +3204,13 @@ lock: } GOTO(out, rc); - } + } /* rc != 0 */ linkea_first_entry(&ldata); /* This is the most common case: the object has unique linkEA entry. */ if (ldata.ld_leh->leh_reccount == 1) { rc = lfsck_namespace_dsd_single(env, com, child, pfid, &ldata, - &lh, &type, &retry); + &lh, &type, &retry, &unknown); if (retry) { LASSERT(!lustre_handle_is_used(&lh)); @@ -3208,7 +3242,7 @@ lock: * but the LFSCK cannot aware that at that time, then it adds * the bad linkEA entry for further processing. */ rc = lfsck_namespace_dsd_multiple(env, com, child, pfid, &ldata, - &lh, &type, lpf); + &lh, &type, lpf, &unknown); GOTO(out, rc); @@ -3289,13 +3323,42 @@ static int lfsck_namespace_double_scan_one(const struct lu_env *env, rc = lfsck_links_read(env, child, &ldata); dt_read_unlock(env, child); + + if (rc == -EINVAL) { + struct lustre_handle lh = { 0 }; + + rc = lfsck_ibits_lock(env, com->lc_lfsck, child, &lh, + MDS_INODELOCK_UPDATE | + MDS_INODELOCK_XATTR, LCK_EX); + if (rc == 0) { + rc = lfsck_namespace_links_remove(env, com, child); + lfsck_ibits_unlock(&lh, LCK_EX); + } + + GOTO(out, rc = (rc == -ENOENT ? 0 : rc)); + } + if (rc != 0) GOTO(out, rc); linkea_first_entry(&ldata); while (ldata.ld_lee != NULL) { - lfsck_namespace_unpack_linkea_entry(&ldata, cname, pfid, - info->lti_key); + rc = lfsck_namespace_unpack_linkea_entry(&ldata, cname, pfid, + info->lti_key, + sizeof(info->lti_key)); + /* Invalid PFID in the linkEA entry. */ + if (rc != 0) { + rc = lfsck_namespace_shrink_linkea(env, com, child, + &ldata, cname, pfid, true); + if (rc < 0) + GOTO(out, rc); + + if (rc > 0) + repaired = true; + + continue; + } + rc = lfsck_namespace_filter_linkea_entry(&ldata, cname, pfid, false); /* Found repeated linkEA entries */ @@ -3313,19 +3376,6 @@ static int lfsck_namespace_double_scan_one(const struct lu_env *env, /* fall through */ } - /* Invalid PFID in the linkEA entry. */ - if (!fid_is_sane(pfid)) { - rc = lfsck_namespace_shrink_linkea(env, com, child, - &ldata, cname, pfid, true); - if (rc < 0) - GOTO(out, rc); - - if (rc > 0) - repaired = true; - - continue; - } - parent = lfsck_object_find_bottom(env, lfsck, pfid); if (IS_ERR(parent)) GOTO(out, rc = PTR_ERR(parent)); @@ -3396,7 +3446,7 @@ lost_parent: repaired = true; continue; - } + } /* !dt_object_exists(parent) */ /* The linkEA entry with bad parent will be removed. */ if (unlikely(!dt_try_as_dir(env, parent))) { @@ -3456,6 +3506,8 @@ lost_parent: continue; } + /* The following handles -ENOENT case */ + rc = dt_attr_get(env, child, la); if (rc != 0) GOTO(out, rc); @@ -3551,11 +3603,8 @@ out: if (rc < 0 && rc != -ENODATA) return rc; - if (rc == 0) { - LASSERT(ldata.ld_leh != NULL); - + if (rc == 0 && ldata.ld_leh != NULL) count = ldata.ld_leh->leh_reccount; - } if (count == 0) { /* If the LFSCK is marked as LF_INCOMPLETE, then means some @@ -3584,10 +3633,23 @@ out: return rc; if (la->la_nlink != 0 && la->la_nlink != count) { - rc = lfsck_namespace_repair_nlink(env, com, child, la); - if (rc > 0) { - ns->ln_objs_nlink_repaired++; - rc = 0; + if (unlikely(!S_ISREG(lfsck_object_type(child)) && + !S_ISLNK(lfsck_object_type(child)))) { + CDEBUG(D_LFSCK, "%s: namespace LFSCK finds " + "the object "DFID"'s nlink count %d " + "does not match linkEA count %d, " + "type %o, skip it.\n", + lfsck_lfsck2name(lfsck), + PFID(lfsck_dto2fid(child)), + la->la_nlink, count, + lfsck_object_type(child)); + } else { + rc = lfsck_namespace_repair_nlink(env, com, + child, la); + if (rc > 0) { + ns->ln_objs_nlink_repaired++; + rc = 0; + } } } } @@ -3610,76 +3672,76 @@ static void lfsck_namespace_dump_statistics(struct seq_file *m, __u32 time_phase1, __u32 time_phase2) { - 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" - "directories: "LPU64"\n" - "dirent_repaired: "LPU64"\n" - "linkea_repaired: "LPU64"\n" - "nlinks_repaired: "LPU64"\n" - "multiple_linked_checked: "LPU64"\n" - "multiple_linked_repaired: "LPU64"\n" - "unknown_inconsistency: "LPU64"\n" - "unmatched_pairs_repaired: "LPU64"\n" - "dangling_repaired: "LPU64"\n" - "multiple_referenced_repaired: "LPU64"\n" - "bad_file_type_repaired: "LPU64"\n" - "lost_dirent_repaired: "LPU64"\n" - "local_lost_found_scanned: "LPU64"\n" - "local_lost_found_moved: "LPU64"\n" - "local_lost_found_skipped: "LPU64"\n" - "local_lost_found_failed: "LPU64"\n" - "striped_dirs_scanned: "LPU64"\n" - "striped_dirs_repaired: "LPU64"\n" - "striped_dirs_failed: "LPU64"\n" - "striped_dirs_disabled: "LPU64"\n" - "striped_dirs_skipped: "LPU64"\n" - "striped_shards_scanned: "LPU64"\n" - "striped_shards_repaired: "LPU64"\n" - "striped_shards_failed: "LPU64"\n" - "striped_shards_skipped: "LPU64"\n" - "name_hash_repaired: "LPU64"\n" - "success_count: %u\n" - "run_time_phase1: %u seconds\n" - "run_time_phase2: %u seconds\n", - checked_phase1, - checked_phase2, - ns->ln_items_repaired, - ns->ln_objs_repaired_phase2, - ns->ln_items_failed, - ns->ln_objs_failed_phase2, - ns->ln_dirs_checked, - ns->ln_dirent_repaired, - ns->ln_linkea_repaired, - ns->ln_objs_nlink_repaired, - ns->ln_mul_linked_checked, - ns->ln_mul_linked_repaired, - ns->ln_unknown_inconsistency, - ns->ln_unmatched_pairs_repaired, - ns->ln_dangling_repaired, - ns->ln_mul_ref_repaired, - ns->ln_bad_type_repaired, - ns->ln_lost_dirent_repaired, - ns->ln_local_lpf_scanned, - ns->ln_local_lpf_moved, - ns->ln_local_lpf_skipped, - ns->ln_local_lpf_failed, - ns->ln_striped_dirs_scanned, - ns->ln_striped_dirs_repaired, - ns->ln_striped_dirs_failed, - ns->ln_striped_dirs_disabled, - ns->ln_striped_dirs_skipped, - ns->ln_striped_shards_scanned, - ns->ln_striped_shards_repaired, - ns->ln_striped_shards_failed, - ns->ln_striped_shards_skipped, - ns->ln_name_hash_repaired, - ns->ln_success_count, - time_phase1, - time_phase2); + seq_printf(m, "checked_phase1: %llu\n" + "checked_phase2: %llu\n" + "updated_phase1: %llu\n" + "updated_phase2: %llu\n" + "failed_phase1: %llu\n" + "failed_phase2: %llu\n" + "directories: %llu\n" + "dirent_repaired: %llu\n" + "linkea_repaired: %llu\n" + "nlinks_repaired: %llu\n" + "multiple_linked_checked: %llu\n" + "multiple_linked_repaired: %llu\n" + "unknown_inconsistency: %llu\n" + "unmatched_pairs_repaired: %llu\n" + "dangling_repaired: %llu\n" + "multiple_referenced_repaired: %llu\n" + "bad_file_type_repaired: %llu\n" + "lost_dirent_repaired: %llu\n" + "local_lost_found_scanned: %llu\n" + "local_lost_found_moved: %llu\n" + "local_lost_found_skipped: %llu\n" + "local_lost_found_failed: %llu\n" + "striped_dirs_scanned: %llu\n" + "striped_dirs_repaired: %llu\n" + "striped_dirs_failed: %llu\n" + "striped_dirs_disabled: %llu\n" + "striped_dirs_skipped: %llu\n" + "striped_shards_scanned: %llu\n" + "striped_shards_repaired: %llu\n" + "striped_shards_failed: %llu\n" + "striped_shards_skipped: %llu\n" + "name_hash_repaired: %llu\n" + "success_count: %u\n" + "run_time_phase1: %u seconds\n" + "run_time_phase2: %u seconds\n", + checked_phase1, + checked_phase2, + ns->ln_items_repaired, + ns->ln_objs_repaired_phase2, + ns->ln_items_failed, + ns->ln_objs_failed_phase2, + ns->ln_dirs_checked, + ns->ln_dirent_repaired, + ns->ln_linkea_repaired, + ns->ln_objs_nlink_repaired, + ns->ln_mul_linked_checked, + ns->ln_mul_linked_repaired, + ns->ln_unknown_inconsistency, + ns->ln_unmatched_pairs_repaired, + ns->ln_dangling_repaired, + ns->ln_mul_ref_repaired, + ns->ln_bad_type_repaired, + ns->ln_lost_dirent_repaired, + ns->ln_local_lpf_scanned, + ns->ln_local_lpf_moved, + ns->ln_local_lpf_skipped, + ns->ln_local_lpf_failed, + ns->ln_striped_dirs_scanned, + ns->ln_striped_dirs_repaired, + ns->ln_striped_dirs_failed, + ns->ln_striped_dirs_disabled, + ns->ln_striped_dirs_skipped, + ns->ln_striped_shards_scanned, + ns->ln_striped_shards_repaired, + ns->ln_striped_shards_failed, + ns->ln_striped_shards_skipped, + ns->ln_name_hash_repaired, + ns->ln_success_count, + time_phase1, + time_phase2); } static void lfsck_namespace_release_lmv(const struct lu_env *env, @@ -3781,7 +3843,7 @@ static int lfsck_namespace_reset(const struct lu_env *env, lad->lad_incomplete = 0; CFS_RESET_BITMAP(lad->lad_bitmap); - rc = lfsck_namespace_store(env, com, true); + rc = lfsck_namespace_store(env, com); GOTO(out, rc); @@ -3926,15 +3988,15 @@ static int lfsck_namespace_checkpoint(const struct lu_env *env, com->lc_new_checked = 0; } - rc = lfsck_namespace_store(env, com, false); + rc = lfsck_namespace_store(env, com); up_write(&com->lc_sem); log: - 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, + CDEBUG(D_LFSCK, "%s: namespace LFSCK checkpoint at the pos [%llu" + ", "DFID", %#llx], status = %d: 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); + lfsck->li_pos_current.lp_dir_cookie, ns->ln_status, rc); return rc > 0 ? 0 : rc; } @@ -4032,8 +4094,8 @@ static int lfsck_namespace_prep(const struct lu_env *env, rc = lfsck_start_assistant(env, com, lsp); - CDEBUG(D_LFSCK, "%s: namespace LFSCK prep done, start pos ["LPU64", " - DFID", "LPX64"]: rc = %d\n", + CDEBUG(D_LFSCK, "%s: namespace LFSCK prep done, start pos [%llu, " + DFID", %#llx]: rc = %d\n", lfsck_lfsck2name(lfsck), pos->lp_oit_cookie, PFID(&pos->lp_dir_parent), pos->lp_dir_cookie, rc); @@ -4234,7 +4296,7 @@ static int lfsck_namespace_post(const struct lu_env *env, com->lc_new_checked = 0; } - rc = lfsck_namespace_store(env, com, false); + rc = lfsck_namespace_store(env, com); up_write(&com->lc_sem); CDEBUG(D_LFSCK, "%s: namespace LFSCK post done: rc = %d\n", @@ -4243,14 +4305,13 @@ static int lfsck_namespace_post(const struct lu_env *env, RETURN(rc); } -static int +static void lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, 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 rc; down_read(&com->lc_sem); seq_printf(m, "name: lfsck_namespace\n" @@ -4259,45 +4320,25 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, "status: %s\n", ns->ln_magic, bk->lb_version, - lfsck_status2names(ns->ln_status)); + lfsck_status2name(ns->ln_status)); - rc = lfsck_bits_dump(m, ns->ln_flags, lfsck_flags_names, "flags"); - if (rc < 0) - goto out; + lfsck_bits_dump(m, ns->ln_flags, lfsck_flags_names, "flags"); - rc = lfsck_bits_dump(m, bk->lb_param, lfsck_param_names, "param"); - if (rc < 0) - goto out; + lfsck_bits_dump(m, bk->lb_param, lfsck_param_names, "param"); - rc = lfsck_time_dump(m, ns->ln_time_last_complete, - "last_completed"); - if (rc < 0) - goto out; + lfsck_time_dump(m, ns->ln_time_last_complete, "last_completed"); - rc = lfsck_time_dump(m, ns->ln_time_latest_start, - "latest_start"); - if (rc < 0) - goto out; + lfsck_time_dump(m, ns->ln_time_latest_start, "latest_start"); - rc = lfsck_time_dump(m, ns->ln_time_last_checkpoint, - "last_checkpoint"); - if (rc < 0) - goto out; + lfsck_time_dump(m, ns->ln_time_last_checkpoint, "last_checkpoint"); - rc = lfsck_pos_dump(m, &ns->ln_pos_latest_start, - "latest_start_position"); - if (rc < 0) - goto out; + lfsck_pos_dump(m, &ns->ln_pos_latest_start, "latest_start_position"); - rc = lfsck_pos_dump(m, &ns->ln_pos_last_checkpoint, - "last_checkpoint_position"); - if (rc < 0) - goto out; + lfsck_pos_dump(m, &ns->ln_pos_last_checkpoint, + "last_checkpoint_position"); - rc = lfsck_pos_dump(m, &ns->ln_pos_first_inconsistent, - "first_failure_position"); - if (rc < 0) - goto out; + lfsck_pos_dump(m, &ns->ln_pos_first_inconsistent, + "first_failure_position"); if (ns->ln_status == LS_SCANNING_PHASE1) { struct lfsck_position pos; @@ -4318,14 +4359,14 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, do_div(speed, rtime); lfsck_namespace_dump_statistics(m, ns, checked, 0, rtime, 0); - seq_printf(m, "average_speed_phase1: "LPU64" items/sec\n" - "average_speed_phase2: N/A\n" - "average_speed_total: "LPU64" items/sec\n" - "real_time_speed_phase1: "LPU64" items/sec\n" - "real_time_speed_phase2: N/A\n", - speed, - speed, - new_checked); + seq_printf(m, "average_speed_phase1: %llu items/sec\n" + "average_speed_phase2: N/A\n" + "average_speed_total: %llu items/sec\n" + "real_time_speed_phase1: %llu items/sec\n" + "real_time_speed_phase2: N/A\n", + speed, + speed, + new_checked); LASSERT(lfsck->li_di_oit != NULL); @@ -4388,17 +4429,17 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, lfsck_namespace_dump_statistics(m, ns, ns->ln_items_checked, checked, ns->ln_run_time_phase1, rtime); - seq_printf(m, "average_speed_phase1: "LPU64" items/sec\n" - "average_speed_phase2: "LPU64" objs/sec\n" - "average_speed_total: "LPU64" items/sec\n" - "real_time_speed_phase1: N/A\n" - "real_time_speed_phase2: "LPU64" objs/sec\n" - "current_position: "DFID"\n", - speed1, - speed2, - speed0, - new_checked, - PFID(&ns->ln_fid_latest_scanned_phase2)); + seq_printf(m, "average_speed_phase1: %llu items/sec\n" + "average_speed_phase2: %llu objs/sec\n" + "average_speed_total: %llu items/sec\n" + "real_time_speed_phase1: N/A\n" + "real_time_speed_phase2: %llu objs/sec\n" + "current_position: "DFID"\n", + speed1, + speed2, + speed0, + new_checked, + PFID(&ns->ln_fid_latest_scanned_phase2)); } else { __u64 speed1 = ns->ln_items_checked; __u64 speed2 = ns->ln_objs_checked_phase2; @@ -4422,19 +4463,18 @@ lfsck_namespace_dump(const struct lu_env *env, struct lfsck_component *com, ns->ln_objs_checked_phase2, ns->ln_run_time_phase1, ns->ln_run_time_phase2); - seq_printf(m, "average_speed_phase1: "LPU64" items/sec\n" - "average_speed_phase2: "LPU64" objs/sec\n" - "average_speed_total: "LPU64" items/sec\n" - "real_time_speed_phase1: N/A\n" - "real_time_speed_phase2: N/A\n" - "current_position: N/A\n", - speed1, - speed2, - speed0); + seq_printf(m, "average_speed_phase1: %llu items/sec\n" + "average_speed_phase2: %llu objs/sec\n" + "average_speed_total: %llu items/sec\n" + "real_time_speed_phase1: N/A\n" + "real_time_speed_phase2: N/A\n" + "current_position: N/A\n", + speed1, + speed2, + speed0); } -out: + up_read(&com->lc_sem); - return 0; } static int lfsck_namespace_double_scan(const struct lu_env *env, @@ -4726,12 +4766,81 @@ log: RETURN(0); } +static void lfsck_namespace_repaired(struct lfsck_namespace *ns, __u64 *count) +{ + *count += ns->ln_objs_nlink_repaired; + *count += ns->ln_dirent_repaired; + *count += ns->ln_linkea_repaired; + *count += ns->ln_mul_linked_repaired; + *count += ns->ln_unmatched_pairs_repaired; + *count += ns->ln_dangling_repaired; + *count += ns->ln_mul_ref_repaired; + *count += ns->ln_bad_type_repaired; + *count += ns->ln_lost_dirent_repaired; + *count += ns->ln_striped_dirs_disabled; + *count += ns->ln_striped_dirs_repaired; + *count += ns->ln_striped_shards_repaired; + *count += ns->ln_name_hash_repaired; + *count += ns->ln_local_lpf_moved; +} + +static int lfsck_namespace_query_all(const struct lu_env *env, + struct lfsck_component *com, + __u32 *mdts_count, __u64 *repaired) +{ + struct lfsck_namespace *ns = com->lc_file_ram; + struct lfsck_tgt_descs *ltds = &com->lc_lfsck->li_mdt_descs; + struct lfsck_tgt_desc *ltd; + int idx; + int rc; + ENTRY; + + rc = lfsck_query_all(env, com); + if (rc != 0) + RETURN(rc); + + down_read(<ds->ltd_rw_sem); + cfs_foreach_bit(ltds->ltd_tgts_bitmap, idx) { + ltd = lfsck_ltd2tgt(ltds, idx); + LASSERT(ltd != NULL); + + mdts_count[ltd->ltd_namespace_status]++; + *repaired += ltd->ltd_namespace_repaired; + } + up_read(<ds->ltd_rw_sem); + + down_read(&com->lc_sem); + mdts_count[ns->ln_status]++; + lfsck_namespace_repaired(ns, repaired); + up_read(&com->lc_sem); + + RETURN(0); +} + static int lfsck_namespace_query(const struct lu_env *env, - struct lfsck_component *com) + struct lfsck_component *com, + struct lfsck_request *req, + struct lfsck_reply *rep, + struct lfsck_query *que, int idx) { struct lfsck_namespace *ns = com->lc_file_ram; + int rc = 0; - return ns->ln_status; + if (que != NULL) { + LASSERT(com->lc_lfsck->li_master); + + rc = lfsck_namespace_query_all(env, com, + que->lu_mdts_count[idx], + &que->lu_repaired[idx]); + } else { + down_read(&com->lc_sem); + rep->lr_status = ns->ln_status; + if (req->lr_flags & LEF_QUERY_ALL) + lfsck_namespace_repaired(ns, &rep->lr_repaired); + up_read(&com->lc_sem); + } + + return rc; } static struct lfsck_operations lfsck_namespace_ops = { @@ -5311,7 +5420,7 @@ nodata: LASSERT(newdata); rc = dt_xattr_del(env, obj, XATTR_NAME_LINK, handle); - if (rc != 0) + if (rc != 0 && rc != -ENOENT && rc != -ENODATA) GOTO(stop, rc); } @@ -5435,7 +5544,8 @@ out: break; } - if (count == 1 && S_ISREG(lfsck_object_type(obj))) + if (obj != NULL && count == 1 && + S_ISREG(lfsck_object_type(obj))) dt_attr_get(env, obj, la); } @@ -5457,15 +5567,14 @@ trace: if (!(bk->lb_param & LPF_FAILOUT)) rc = 0; } else { - if (log) - CDEBUG(D_LFSCK, "%s: namespace LFSCK assistant " - "repaired the entry: "DFID", parent "DFID - ", name %.*s\n", lfsck_lfsck2name(lfsck), - PFID(&lnr->lnr_fid), PFID(pfid), - lnr->lnr_namelen, lnr->lnr_name); - if (repaired) { ns->ln_items_repaired++; + if (log) + CDEBUG(D_LFSCK, "%s: namespace LFSCK assistant " + "repaired the entry: "DFID", parent "DFID + ", name %.*s\n", lfsck_lfsck2name(lfsck), + PFID(&lnr->lnr_fid), PFID(pfid), + lnr->lnr_namelen, lnr->lnr_name); switch (type) { case LNIT_DANGLING: @@ -5492,8 +5601,17 @@ trace: ns->ln_name_hash_repaired++; /* Not count repeatedly. */ - if (!repaired) + if (!repaired) { ns->ln_items_repaired++; + if (log) + CDEBUG(D_LFSCK, "%s: namespace LFSCK " + "assistant repaired the entry: " + DFID", parent "DFID + ", name %.*s\n", + lfsck_lfsck2name(lfsck), + PFID(&lnr->lnr_fid), PFID(pfid), + lnr->lnr_namelen, lnr->lnr_name); + } if (bk->lb_param & LPF_DRYRUN && lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) @@ -6065,7 +6183,7 @@ checkpoint: ns->ln_time_last_checkpoint = cfs_time_current_sec(); ns->ln_objs_checked_phase2 += com->lc_new_checked; com->lc_new_checked = 0; - rc = lfsck_namespace_store(env, com, false); + rc = lfsck_namespace_store(env, com); up_write(&com->lc_sem); if (rc != 0) GOTO(put, rc); @@ -6148,6 +6266,10 @@ static void lfsck_namespace_assistant_fill_pos(const struct lu_env *env, struct lfsck_assistant_data *lad = com->lc_data; struct lfsck_namespace_req *lnr; + if (((struct lfsck_namespace *)(com->lc_file_ram))->ln_status != + LS_SCANNING_PHASE1) + return; + if (list_empty(&lad->lad_req_list)) return; @@ -6191,7 +6313,7 @@ static int lfsck_namespace_double_scan_result(const struct lu_env *env, ns->ln_status = LS_FAILED; } - rc = lfsck_namespace_store(env, com, false); + rc = lfsck_namespace_store(env, com); up_write(&com->lc_sem); return rc;