From: Fan Yong Date: Mon, 10 Nov 2014 09:46:33 +0000 (+0800) Subject: LU-6109 lfsck: check FID validity before locating object X-Git-Tag: 2.6.94~3 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=4d408c9aed9adaf1f4e2ea87851728a1cf662594;hp=f1a2e6107c124d010d89973cfd716fbd17b689f0 LU-6109 lfsck: check FID validity before locating object It is possible that the FID from iteration or linkEA is corrupted. The LFSCK needs to check its validity before locating the object with it to avoid falling into hung or other unexpected status. Signed-off-by: Fan Yong Change-Id: I1df8d085bf5abf926d03882457cb8b221633d3aa Reviewed-on: http://review.whamcloud.com/13511 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev --- diff --git a/lustre/lfsck/lfsck_engine.c b/lustre/lfsck/lfsck_engine.c index 9c06357..8eb6f02 100644 --- a/lustre/lfsck/lfsck_engine.c +++ b/lustre/lfsck/lfsck_engine.c @@ -933,6 +933,13 @@ static int lfsck_master_oit_engine(const struct lu_env *env, goto checkpoint; } + if (unlikely(!fid_is_sane(fid))) { + CDEBUG(D_LFSCK, "%s: OIT scan find invalid FID "DFID + ", skip it\n", + lfsck_lfsck2name(lfsck), PFID(fid)); + goto checkpoint; + } + if (fid_is_idif(fid)) { __u32 idx1 = fid_idif_ost_idx(fid); diff --git a/lustre/lfsck/lfsck_namespace.c b/lustre/lfsck/lfsck_namespace.c index af77f24..6e29717 100644 --- a/lustre/lfsck/lfsck_namespace.c +++ b/lustre/lfsck/lfsck_namespace.c @@ -584,6 +584,9 @@ int lfsck_namespace_trace_update(const struct lu_env *env, LASSERT(flags != 0); + if (unlikely(!fid_is_sane(fid))) + RETURN(0); + idx = lfsck_sub_trace_file_fid2idx(fid); obj = com->lc_sub_trace_objs[idx].lsto_obj; mutex_lock(&com->lc_sub_trace_objs[idx].lsto_mutex); @@ -4947,7 +4950,7 @@ static int lfsck_namespace_assistant_handler_p1(const struct lu_env *env, bool bad_hash = false; int idx = 0; int count = 0; - int rc; + int rc = 0; enum lfsck_namespace_inconsistency_type type = LNIT_NONE; ENTRY; @@ -4972,6 +4975,24 @@ static int lfsck_namespace_assistant_handler_p1(const struct lu_env *env, GOTO(out, rc); } + if (unlikely(!fid_is_sane(&lnr->lnr_fid))) { + CDEBUG(D_LFSCK, "%s: dir scan find invalid FID "DFID + " for the name entry %.*s under "DFID"\n", + lfsck_lfsck2name(lfsck), PFID(&lnr->lnr_fid), + lnr->lnr_namelen, lnr->lnr_name, PFID(pfid)); + + if (strcmp(lnr->lnr_name, dotdot) != 0) + /* invalid FID means bad name entry, remove it. */ + type = LNIT_BAD_DIRENT; + else + /* If the parent FID is invalid, we cannot remove + * the ".." entry directly. */ + rc = lfsck_namespace_trace_update(env, com, pfid, + LNTF_CHECK_PARENT, true); + + GOTO(out, rc); + } + if (unlikely(lnr->lnr_dir_cookie == MDS_DIR_END_OFF)) { rc = lfsck_namespace_striped_dir_rescan(env, com, lnr); diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 0465afb..58a1e1a 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -4406,13 +4406,19 @@ static int osd_ea_lookup_rec(const struct lu_env *env, struct osd_object *obj, /* done with de, release bh */ brelse(bh); if (rc != 0) { - if (unlikely(ino == osd_remote_parent_ino(dev))) + if (unlikely(ino == osd_remote_parent_ino(dev))) { + const char *name = (const char *)key; + /* If the parent is on remote MDT, and there * is no FID-in-dirent, then we have to get * the parent FID from the linkEA. */ - rc = osd_get_pfid_from_linkea(env, obj, fid); - else + if (likely(strlen(name) == 2 && + name[0] == '.' && name[1] == '.')) + rc = osd_get_pfid_from_linkea(env, obj, + fid); + } else { rc = osd_ea_fid_get(env, obj, ino, fid, id); + } } else { osd_id_gen(id, ino, OSD_OII_NOGEN); } @@ -5656,7 +5662,11 @@ static inline int osd_it_ea_rec(const struct lu_env *env, /* If the parent is on remote MDT, and there * is no FID-in-dirent, then we have to get * the parent FID from the linkEA. */ - osd_get_pfid_from_linkea(env, obj, fid); + if (!fid_is_sane(fid) && + it->oie_dirent->oied_namelen == 2 && + it->oie_dirent->oied_name[0] == '.' && + it->oie_dirent->oied_name[1] == '.') + osd_get_pfid_from_linkea(env, obj, fid); } else { rc = osd_dirent_check_repair(env, obj, it, fid, id, &attr); @@ -5664,19 +5674,21 @@ static inline int osd_it_ea_rec(const struct lu_env *env, } else { attr &= ~LU_DIRENT_ATTRS_MASK; if (!fid_is_sane(fid)) { - if (OBD_FAIL_CHECK(OBD_FAIL_FID_LOOKUP) && - likely(it->oie_dirent->oied_namelen != 2 || - it->oie_dirent->oied_name[0] != '.' || - it->oie_dirent->oied_name[1] != '.')) - RETURN(-ENOENT); - - if (unlikely(ino == osd_remote_parent_ino(dev))) + if (it->oie_dirent->oied_namelen == 2 && + it->oie_dirent->oied_name[0] == '.' && + it->oie_dirent->oied_name[1] == '.') { /* If the parent is on remote MDT, and there * is no FID-in-dirent, then we have to get * the parent FID from the linkEA. */ - rc = osd_get_pfid_from_linkea(env, obj, fid); - else + if (ino == osd_remote_parent_ino(dev)) + rc = osd_get_pfid_from_linkea(env, obj, + fid); + } else { + if (OBD_FAIL_CHECK(OBD_FAIL_FID_LOOKUP)) + RETURN(-ENOENT); + rc = osd_ea_fid_get(env, obj, ino, fid, id); + } } else { osd_id_gen(id, ino, OSD_OII_NOGEN); }