Whamcloud - gitweb
LU-6109 lfsck: check FID validity before locating object 11/13511/4
authorFan Yong <fan.yong@intel.com>
Mon, 10 Nov 2014 09:46:33 +0000 (17:46 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Sun, 8 Feb 2015 02:48:35 +0000 (02:48 +0000)
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 <fan.yong@intel.com>
Change-Id: I1df8d085bf5abf926d03882457cb8b221633d3aa
Reviewed-on: http://review.whamcloud.com/13511
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
lustre/lfsck/lfsck_engine.c
lustre/lfsck/lfsck_namespace.c
lustre/osd-ldiskfs/osd_handler.c

index 9c06357..8eb6f02 100644 (file)
@@ -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);
 
index af77f24..6e29717 100644 (file)
@@ -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);
 
index 0465afb..58a1e1a 100644 (file)
@@ -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);
                }