Whamcloud - gitweb
LU-5519 lfsck: LFSCK code framework adjustment (2) 45/11845/13
authorFan Yong <fan.yong@intel.com>
Wed, 27 Aug 2014 15:44:02 +0000 (23:44 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 30 Oct 2014 02:14:00 +0000 (02:14 +0000)
Enhance LFSCK code framework for striped directory verification,
including:

1) New lfsck component APIs: lfsck_operations::lfsck_open_dir()
   and lfsck_operations::lfsck_close_dir().
1.1) The namespace LFSCK uses lfsck_open_dir() to initialize the
     LMV EA verification environment.
1.2) The namespace LFSCK uses lfsck_close_dir() to indicate the
     end of the scanning the striped directory.

2) When create orphan parent, the LMV EA should be considered.

3) Data structure definition and extention.

4) Other code cleanup.

Signed-off-by: Fan Yong <fan.yong@intel.com>
Change-Id: I01e14645796c3fa3269c5f3cdcbb755ccb455d7e
Reviewed-on: http://review.whamcloud.com/11845
Tested-by: Jenkins
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
15 files changed:
lustre/include/lustre/lustre_idl.h
lustre/include/lustre_lmv.h
lustre/lfsck/Makefile.in
lustre/lfsck/lfsck_engine.c
lustre/lfsck/lfsck_internal.h
lustre/lfsck/lfsck_lib.c
lustre/lfsck/lfsck_namespace.c
lustre/lfsck/lfsck_striped_dir.c [new file with mode: 0644]
lustre/lmv/lmv_intent.c
lustre/lmv/lmv_internal.h
lustre/lmv/lmv_obd.c
lustre/ptlrpc/pack_generic.c
lustre/ptlrpc/wiretest.c
lustre/utils/wirecheck.c
lustre/utils/wiretest.c

index 0ebe6b1..8ca9fc8 100644 (file)
@@ -3554,11 +3554,18 @@ struct lfsck_request {
        __u16           lr_active;
        __u16           lr_param;
        __u16           lr_async_windows;
-       __u32           lr_flags2;
+       union {
+               __u32   lr_flags2;
+               __u32   lr_layout_version;
+       };
        struct lu_fid   lr_fid;
        struct lu_fid   lr_fid2;
-       struct lu_fid   lr_fid3;
-       __u64           lr_padding_2;
+       union {
+               struct lu_fid   lr_fid3;
+               char            lr_pool_name[LOV_MAXPOOLNAME];
+       };
+       __u32           lr_stripe_count;
+       __u32           lr_hash_type;
        __u64           lr_padding_3;
 };
 
index acd4e4e..bb05b34 100644 (file)
@@ -117,4 +117,70 @@ static inline void lmv_le_to_cpu(union lmv_mds_md *lmv_dst,
        }
 }
 
+/* This hash is only for testing purpose */
+static inline unsigned int
+lmv_hash_all_chars(unsigned int count, const char *name, int namelen)
+{
+       unsigned int c = 0;
+       const unsigned char *p = (const unsigned char *)name;
+
+       while (--namelen >= 0)
+               c += p[namelen];
+
+       c = c % count;
+
+       return c;
+}
+
+static inline unsigned int
+lmv_hash_fnv1a(unsigned int count, const char *name, int namelen)
+{
+       __u64   hash;
+
+       hash = lustre_hash_fnv_1a_64(name, namelen);
+
+       hash = hash % count;
+
+       return hash;
+}
+
+static inline int lmv_name_to_stripe_index(__u32 lmv_hash_type,
+                                          unsigned int stripe_count,
+                                          const char *name, int namelen)
+{
+       int     idx;
+       __u32   hash_type = lmv_hash_type & LMV_HASH_TYPE_MASK;
+
+       LASSERT(namelen > 0);
+       if (stripe_count <= 1)
+               return 0;
+
+       /* for migrating object, always start from 0 stripe */
+       if (lmv_hash_type & LMV_HASH_FLAG_MIGRATION)
+               return 0;
+
+       switch (hash_type) {
+       case LMV_HASH_TYPE_ALL_CHARS:
+               idx = lmv_hash_all_chars(stripe_count, name, namelen);
+               break;
+       case LMV_HASH_TYPE_FNV_1A_64:
+               idx = lmv_hash_fnv1a(stripe_count, name, namelen);
+               break;
+       default:
+               idx = -EBADFD;
+               break;
+       }
+
+       CDEBUG(D_INFO, "name %.*s hash_type %d idx %d\n", namelen, name,
+              hash_type, idx);
+
+       return idx;
+}
+
+static inline bool lmv_is_known_hash_type(__u32 type)
+{
+       return (type & LMV_HASH_TYPE_MASK) == LMV_HASH_TYPE_FNV_1A_64 ||
+              (type & LMV_HASH_TYPE_MASK) == LMV_HASH_TYPE_ALL_CHARS;
+}
+
 #endif
index c2f5f32..a6c115e 100644 (file)
@@ -1,5 +1,5 @@
 MODULES := lfsck
 lfsck-objs := lfsck_lib.o lfsck_engine.o lfsck_bookmark.o lfsck_namespace.o
-lfsck-objs += lfsck_layout.o
+lfsck-objs += lfsck_layout.o lfsck_striped_dir.o
 
 @INCLUDE_RULES@
index 8398230..322c122 100644 (file)
@@ -93,19 +93,6 @@ static void lfsck_di_dir_put(const struct lu_env *env, struct lfsck_instance *lf
        iops->put(env, di);
 }
 
-static void lfsck_close_dir(const struct lu_env *env,
-                           struct lfsck_instance *lfsck)
-{
-       struct dt_object        *dir_obj  = lfsck->li_obj_dir;
-       const struct dt_it_ops  *dir_iops = &dir_obj->do_index_ops->dio_it;
-       struct dt_it            *dir_di   = lfsck->li_di_dir;
-
-       lfsck_di_dir_put(env, lfsck);
-       dir_iops->fini(env, dir_di);
-       lfsck->li_obj_dir = NULL;
-       lfsck_object_put(env, dir_obj);
-}
-
 static int lfsck_update_lma(const struct lu_env *env,
                            struct lfsck_instance *lfsck, struct dt_object *obj)
 {
@@ -298,6 +285,77 @@ out:
        return rc;
 }
 
+static int lfsck_load_stripe_lmv(const struct lu_env *env,
+                                struct lfsck_instance *lfsck,
+                                struct dt_object *obj)
+{
+       struct lmv_mds_md_v1    *lmv    = &lfsck_env_info(env)->lti_lmv;
+       struct lfsck_lmv        *llmv;
+       int                      rc;
+       ENTRY;
+
+       LASSERT(lfsck->li_obj_dir == NULL);
+       LASSERT(lfsck->li_lmv == NULL);
+
+       rc = lfsck_read_stripe_lmv(env, obj, lmv);
+       if (rc == -ENODATA) {
+               lfsck->li_obj_dir = lfsck_object_get(obj);
+
+               RETURN(0);
+       }
+
+       if (rc < 0)
+               RETURN(rc);
+
+       OBD_ALLOC_PTR(llmv);
+       if (llmv == NULL)
+               RETURN(-ENOMEM);
+
+       if (lmv->lmv_magic == LMV_MAGIC) {
+               struct lfsck_slave_lmv_rec      *lslr;
+               __u32                            stripes;
+
+               llmv->ll_lmv_master = 1;
+               if (lmv->lmv_stripe_count < 1)
+                       stripes = LFSCK_LMV_DEF_STRIPES;
+               else if (lmv->lmv_stripe_count > LFSCK_LMV_MAX_STRIPES)
+                       stripes = LFSCK_LMV_MAX_STRIPES;
+               else
+                       stripes = lmv->lmv_stripe_count;
+
+               OBD_ALLOC_LARGE(lslr, sizeof(*lslr) * stripes);
+               if (lslr == NULL) {
+                       OBD_FREE_PTR(llmv);
+
+                       RETURN(-ENOMEM);
+               }
+
+               /* Find the object against the bottom device. */
+               obj = lfsck_object_find_by_dev(env, lfsck->li_bottom,
+                                              lfsck_dto2fid(obj));
+               if (IS_ERR(obj)) {
+                       OBD_FREE_LARGE(lslr, sizeof(*lslr) * stripes);
+                       OBD_FREE_PTR(llmv);
+
+                       RETURN(PTR_ERR(obj));
+               }
+
+               llmv->ll_stripes_allocated = stripes;
+               llmv->ll_hash_type = LMV_HASH_TYPE_UNKNOWN;
+               llmv->ll_lslr = lslr;
+               lfsck->li_obj_dir = obj;
+       } else {
+               llmv->ll_lmv_slave = 1;
+               lfsck->li_obj_dir = lfsck_object_get(obj);
+       }
+
+       llmv->ll_lmv = *lmv;
+       atomic_set(&llmv->ll_ref, 1);
+       lfsck->li_lmv = llmv;
+
+       RETURN(0);
+}
+
 /* LFSCK wrap functions */
 
 static void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck,
@@ -310,6 +368,97 @@ static void lfsck_fail(const struct lu_env *env, struct lfsck_instance *lfsck,
        }
 }
 
+static void lfsck_close_dir(const struct lu_env *env,
+                           struct lfsck_instance *lfsck,
+                           int result)
+{
+       struct lfsck_component *com;
+       ENTRY;
+
+       if (lfsck->li_lmv != NULL) {
+               lfsck->li_lmv->ll_exit_value = result;
+               if (lfsck->li_obj_dir != NULL) {
+                       list_for_each_entry(com, &lfsck->li_list_dir,
+                                           lc_link_dir) {
+                               com->lc_ops->lfsck_close_dir(env, com);
+                       }
+               }
+
+               lfsck_lmv_put(env, lfsck->li_lmv);
+               lfsck->li_lmv = NULL;
+       }
+
+       if (lfsck->li_di_dir != NULL) {
+               const struct dt_it_ops  *dir_iops =
+                               &lfsck->li_obj_dir->do_index_ops->dio_it;
+               struct dt_it            *dir_di   = lfsck->li_di_dir;
+
+               lfsck_di_dir_put(env, lfsck);
+               dir_iops->fini(env, dir_di);
+       }
+
+       if (lfsck->li_obj_dir != NULL) {
+               struct dt_object        *dir_obj  = lfsck->li_obj_dir;
+
+               lfsck->li_obj_dir = NULL;
+               lfsck_object_put(env, dir_obj);
+       }
+
+       EXIT;
+}
+
+static int lfsck_open_dir(const struct lu_env *env,
+                         struct lfsck_instance *lfsck, __u64 cookie)
+{
+       struct dt_object        *obj    = lfsck->li_obj_dir;
+       struct dt_it            *di     = lfsck->li_di_dir;
+       struct lfsck_component  *com;
+       const struct dt_it_ops  *iops;
+       int                      rc     = 0;
+       ENTRY;
+
+       LASSERT(obj != NULL);
+       LASSERT(di == NULL);
+
+       if (unlikely(!dt_try_as_dir(env, obj)))
+               GOTO(out, rc = -ENOTDIR);
+
+       list_for_each_entry(com, &lfsck->li_list_dir, lc_link_dir) {
+               rc = com->lc_ops->lfsck_open_dir(env, com);
+               if (rc != 0)
+                       GOTO(out, rc);
+       }
+
+       iops = &obj->do_index_ops->dio_it;
+       di = iops->init(env, obj, lfsck->li_args_dir, BYPASS_CAPA);
+       if (IS_ERR(di))
+               GOTO(out, rc = PTR_ERR(di));
+
+       rc = iops->load(env, di, cookie);
+       if (rc == 0 || (rc > 0 && cookie > 0))
+               rc = iops->next(env, di);
+       else if (rc > 0)
+               rc = 0;
+
+       if (rc != 0) {
+               iops->put(env, di);
+               iops->fini(env, di);
+       } else {
+               lfsck->li_cookie_dir = iops->store(env, di);
+               spin_lock(&lfsck->li_lock);
+               lfsck->li_di_dir = di;
+               spin_unlock(&lfsck->li_lock);
+       }
+
+       GOTO(out, rc);
+
+out:
+       if (rc != 0)
+               lfsck_close_dir(env, lfsck, rc);
+
+       return rc;
+}
+
 static int lfsck_checkpoint(const struct lu_env *env,
                            struct lfsck_instance *lfsck)
 {
@@ -343,7 +492,6 @@ static int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck,
        struct lfsck_position  *pos     = NULL;
        const struct dt_it_ops *iops    =
                                &lfsck->li_obj_oit->do_index_ops->dio_it;
-       struct dt_it           *di;
        int                     rc;
        ENTRY;
 
@@ -394,45 +542,28 @@ static int lfsck_prep(const struct lu_env *env, struct lfsck_instance *lfsck,
            unlikely(!S_ISDIR(lfsck_object_type(obj))))
                GOTO(out, rc = 0);
 
-       if (unlikely(!dt_try_as_dir(env, obj)))
-               GOTO(out, rc = -ENOTDIR);
+       rc = lfsck_load_stripe_lmv(env, lfsck, obj);
+       if (rc == 0) {
+               /* For the master MDT-object of a striped directory,
+                * reset the iteration from the directory beginning. */
+               if (lfsck->li_lmv != NULL && lfsck->li_lmv->ll_lmv_master)
+                       pos->lp_dir_cookie = 0;
 
-       /* Init the namespace-based directory traverse. */
-       iops = &obj->do_index_ops->dio_it;
-       di = iops->init(env, obj, lfsck->li_args_dir, BYPASS_CAPA);
-       if (IS_ERR(di))
-               GOTO(out, rc = PTR_ERR(di));
-
-       LASSERT(pos->lp_dir_cookie < MDS_DIR_END_OFF);
-
-       rc = iops->load(env, di, pos->lp_dir_cookie);
-       if ((rc == 0) || (rc > 0 && pos->lp_dir_cookie > 0))
-               rc = iops->next(env, di);
-       else if (rc > 0)
-               rc = 0;
-
-       if (rc != 0) {
-               iops->put(env, di);
-               iops->fini(env, di);
-               GOTO(out, rc);
+               rc = lfsck_open_dir(env, lfsck, pos->lp_dir_cookie);
        }
 
-       lfsck->li_obj_dir = lfsck_object_get(obj);
-       lfsck->li_cookie_dir = iops->store(env, di);
-       spin_lock(&lfsck->li_lock);
-       lfsck->li_di_dir = di;
-       spin_unlock(&lfsck->li_lock);
-
-       GOTO(out, rc = 0);
+       GOTO(out, rc);
 
 out:
        if (obj != NULL)
                lfsck_object_put(env, obj);
 
-       if (rc < 0) {
+       if (rc != 0) {
+               lfsck_close_dir(env, lfsck, rc);
                list_for_each_entry_safe(com, next, &lfsck->li_list_scan,
-                                        lc_link)
+                                        lc_link) {
                        com->lc_ops->lfsck_post(env, com, rc, true);
+               }
 
                return rc;
        }
@@ -456,8 +587,6 @@ static int lfsck_exec_oit(const struct lu_env *env,
                          struct lfsck_instance *lfsck, struct dt_object *obj)
 {
        struct lfsck_component *com;
-       const struct dt_it_ops *iops;
-       struct dt_it           *di;
        int                     rc;
        ENTRY;
 
@@ -473,38 +602,20 @@ static int lfsck_exec_oit(const struct lu_env *env,
        if (rc <= 0)
                GOTO(out, rc);
 
-       if (unlikely(!dt_try_as_dir(env, obj)))
-               GOTO(out, rc = -ENOTDIR);
-
-       iops = &obj->do_index_ops->dio_it;
-       di = iops->init(env, obj, lfsck->li_args_dir, BYPASS_CAPA);
-       if (IS_ERR(di))
-               GOTO(out, rc = PTR_ERR(di));
-
-       rc = iops->load(env, di, 0);
+       rc = lfsck_load_stripe_lmv(env, lfsck, obj);
        if (rc == 0)
-               rc = iops->next(env, di);
-       else if (rc > 0)
-               rc = 0;
+               rc = lfsck_open_dir(env, lfsck, 0);
 
-       if (rc != 0) {
-               iops->put(env, di);
-               iops->fini(env, di);
-               GOTO(out, rc);
-       }
-
-       lfsck->li_obj_dir = lfsck_object_get(obj);
-       lfsck->li_cookie_dir = iops->store(env, di);
-       spin_lock(&lfsck->li_lock);
-       lfsck->li_di_dir = di;
-       spin_unlock(&lfsck->li_lock);
-
-       GOTO(out, rc = 0);
+       GOTO(out, rc);
 
 out:
        if (rc < 0)
                lfsck_fail(env, lfsck, false);
-       return (rc > 0 ? 0 : rc);
+
+       if (rc != 0)
+               lfsck_close_dir(env, lfsck, rc);
+
+       return rc > 0 ? 0 : rc;
 }
 
 static int lfsck_exec_dir(const struct lu_env *env,
@@ -531,6 +642,7 @@ static int lfsck_post(const struct lu_env *env, struct lfsck_instance *lfsck,
        int                     rc1 = 0;
 
        lfsck_pos_fill(env, lfsck, &lfsck->li_pos_checkpoint, false);
+       lfsck_close_dir(env, lfsck, result);
        list_for_each_entry_safe(com, next, &lfsck->li_list_scan, lc_link) {
                rc = com->lc_ops->lfsck_post(env, com, result, false);
                if (rc != 0)
@@ -699,7 +811,7 @@ checkpoint:
        } while (rc == 0);
 
        if (rc > 0 && !lfsck->li_oit_over)
-               lfsck_close_dir(env, lfsck);
+               lfsck_close_dir(env, lfsck, rc);
 
        RETURN(rc);
 }
@@ -975,9 +1087,8 @@ int lfsck_master_engine(void *args)
 
        if (!OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH))
                rc = lfsck_post(env, lfsck, rc);
-
-       if (lfsck->li_di_dir != NULL)
-               lfsck_close_dir(env, lfsck);
+       else
+               lfsck_close_dir(env, lfsck, rc);
 
 fini_oit:
        lfsck_di_oit_put(env, lfsck);
index 1ce764e..ab035aa 100644 (file)
@@ -234,13 +234,47 @@ struct lfsck_namespace {
        /* How many objects under /lost+found failed to be processed. */
        __u64   ln_local_lpf_failed;
 
+       /* How many striped directories (master) have been scanned. */
+       __u64   ln_striped_dirs_scanned;
+
+       /* How many striped directories (master) have been repaired. */
+       __u64   ln_striped_dirs_repaired;
+
+       /* How many striped directories (master) failed verification. */
+       __u64   ln_striped_dirs_failed;
+
+       /* How many striped directories (master) has been disabled. */
+       __u64   ln_striped_dirs_disabled;
+
+       /* How many striped directory's (master) have been skipped
+        * (for shards verification) because of lost master LMV EA. */
+       __u64   ln_striped_dirs_skipped;
+
+       /* How many striped directory's shards (slave) have been scanned. */
+       __u64   ln_striped_shards_scanned;
+
+       /* How many striped directory's shards (slave) have been repaired. */
+       __u64   ln_striped_shards_repaired;
+
+       /* How many striped directory's shards (slave) failed verification. */
+       __u64   ln_striped_shards_failed;
+
+       /* How many striped directory's shards (slave) have been skipped
+        * (for name hash verification) because do not know whether the slave
+        * LMV EA is valid or not. */
+       __u64   ln_striped_shards_skipped;
+
+       /* How many name entries under striped directory with bad name
+        * hash have been repaired. */
+       __u64   ln_name_hash_repaired;
+
        /* The size of MDT targets bitmap with nbits. Such bitmap records
         * the MDTs that contain non-verified MDT-objects. */
        __u32   ln_bitmap_size;
 
        __u32   ln_reserved_1;
        /* For further using. 256-bytes aligned now. */
-       __u64   ln_reserved[25];
+       __u64   ln_reserved[15];
 };
 
 enum lfsck_layout_inconsistency_type {
@@ -337,6 +371,12 @@ struct lfsck_operations {
                           struct lfsck_component *com,
                           bool new_checked);
 
+       void (*lfsck_close_dir)(const struct lu_env *env,
+                               struct lfsck_component *com);
+
+       int (*lfsck_open_dir)(const struct lu_env *env,
+                             struct lfsck_component *com);
+
        int (*lfsck_checkpoint)(const struct lu_env *env,
                                struct lfsck_component *com,
                                bool init);
@@ -474,6 +514,36 @@ struct lfsck_component {
        __u16                    lc_type;
 };
 
+#define LFSCK_LMV_MAX_STRIPES  LMV_MAX_STRIPE_COUNT
+#define LFSCK_LMV_DEF_STRIPES  4
+
+struct lfsck_slave_lmv_rec {
+       struct lu_fid   lslr_fid;
+       __u32           lslr_stripe_count;
+       __u32           lslr_index; /* the index in name or in slave lmv */
+       __u32           lslr_hash_type;
+       __u32           lslr_flags;
+};
+
+struct lfsck_lmv {
+       struct lmv_mds_md_v1             ll_lmv;
+       atomic_t                         ll_ref;
+       int                              ll_stripes_allocated;
+       int                              ll_stripes_filled;
+       int                              ll_exit_value;
+       __u32                            ll_max_stripe_count;
+       __u32                            ll_max_filled_off;
+       __u32                            ll_hash_type;
+       unsigned int                     ll_lmv_master:1,
+                                        ll_lmv_slave:1,
+                                        ll_lmv_verified:1,
+                                        ll_lmv_updated:1,
+                                        ll_inline:1,
+                                        ll_failed:1,
+                                        ll_ignore:1;
+       struct lfsck_slave_lmv_rec      *ll_lslr;
+};
+
 struct lfsck_instance {
        struct mutex              li_mutex;
        spinlock_t                li_lock;
@@ -522,6 +592,8 @@ struct lfsck_instance {
        struct lfsck_position     li_pos_current;
        struct lfsck_position     li_pos_checkpoint;
 
+       struct lfsck_lmv         *li_lmv;
+
        /* Obj for otable-based iteration */
        struct dt_object         *li_obj_oit;
 
@@ -595,6 +667,7 @@ struct lfsck_assistant_req {
 struct lfsck_namespace_req {
        struct lfsck_assistant_req       lnr_lar;
        struct dt_object                *lnr_obj;
+       struct lfsck_lmv                *lnr_lmv;
        struct lu_fid                    lnr_fid;
        __u64                            lnr_oit_cookie;
        __u64                            lnr_dir_cookie;
@@ -697,6 +770,7 @@ struct lfsck_thread_info {
        /* There will be '\0' at the end of the name. */
        char            lti_key[sizeof(struct lu_dirent) + NAME_MAX + 1];
        char                    lti_tmpbuf[LFSCK_TMPBUF_LEN];
+       char                    lti_tmpbuf2[LFSCK_TMPBUF_LEN];
        struct lfsck_request    lti_lr;
        struct lfsck_async_interpret_args lti_laia;
        struct lfsck_async_interpret_args lti_laia2;
@@ -714,6 +788,10 @@ struct lfsck_thread_info {
        struct dt_insert_rec    lti_dt_rec;
        struct lu_object_conf   lti_conf;
        struct lu_seq_range     lti_range;
+       struct lmv_mds_md_v1    lti_lmv;
+       struct lmv_mds_md_v1    lti_lmv2;
+       struct lmv_mds_md_v1    lti_lmv3;
+       struct lmv_mds_md_v1    lti_lmv4;
 };
 
 /* lfsck_lib.c */
@@ -822,6 +900,25 @@ int lfsck_update_name_entry(const struct lu_env *env,
 int lfsck_namespace_setup(const struct lu_env *env,
                          struct lfsck_instance *lfsck);
 
+/* lfsck_striped_dir.c */
+void lfsck_lmv_put(const struct lu_env *env, struct lfsck_lmv *llmv);
+int lfsck_read_stripe_lmv(const struct lu_env *env, struct dt_object *obj,
+                         struct lmv_mds_md_v1 *lmv);
+int lfsck_shard_name_to_index(const struct lu_env *env, const char *name,
+                             int namelen, __u16 type,
+                             const struct lu_fid *fid);
+bool lfsck_is_valid_slave_name_entry(const struct lu_env *env,
+                                    struct lfsck_lmv *llmv,
+                                    const char *name, int namelen);
+int lfsck_namespace_check_name(const struct lu_env *env,
+                              struct dt_object *parent,
+                              struct dt_object *child,
+                              const struct lu_name *cname);
+int lfsck_namespace_verify_stripe_slave(const struct lu_env *env,
+                                       struct lfsck_component *com,
+                                       struct dt_object *obj,
+                                       struct lfsck_lmv *llmv);
+
 /* lfsck_layout.c */
 int lfsck_layout_setup(const struct lu_env *env, struct lfsck_instance *lfsck);
 
@@ -831,6 +928,12 @@ extern const char *lfsck_flags_names[];
 extern const char *lfsck_param_names[];
 extern struct lu_context_key lfsck_thread_key;
 
+static inline bool name_is_dot_or_dotdot(const char *name, int namelen)
+{
+       return name[0] == '.' &&
+              (namelen == 1 || (namelen == 2 && name[1] == '.'));
+}
+
 static inline struct dt_device *lfsck_obj2dt_dev(struct dt_object *obj)
 {
        return container_of0(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev);
@@ -1154,4 +1257,31 @@ static inline int lfsck_links_read2(const struct lu_env *env,
        return __lfsck_links_read(env, obj, ldata);
 }
 
+static inline struct lfsck_lmv *lfsck_lmv_get(struct lfsck_lmv *llmv)
+{
+       if (llmv != NULL)
+               atomic_inc(&llmv->ll_ref);
+
+       return llmv;
+}
+
+static inline void lfsck_lmv_header_le_to_cpu(struct lmv_mds_md_v1 *dst,
+                                             const struct lmv_mds_md_v1 *src)
+{
+       dst->lmv_magic = le32_to_cpu(src->lmv_magic);
+       dst->lmv_stripe_count = le32_to_cpu(src->lmv_stripe_count);
+       dst->lmv_master_mdt_index = le32_to_cpu(src->lmv_master_mdt_index);
+       dst->lmv_hash_type = le32_to_cpu(src->lmv_hash_type);
+       dst->lmv_layout_version = le32_to_cpu(src->lmv_layout_version);
+}
+
+static inline void lfsck_lmv_header_cpu_to_le(struct lmv_mds_md_v1 *dst,
+                                             const struct lmv_mds_md_v1 *src)
+{
+       dst->lmv_magic = cpu_to_le32(src->lmv_magic);
+       dst->lmv_stripe_count = cpu_to_le32(src->lmv_stripe_count);
+       dst->lmv_master_mdt_index = cpu_to_le32(src->lmv_master_mdt_index);
+       dst->lmv_hash_type = cpu_to_le32(src->lmv_hash_type);
+       dst->lmv_layout_version = cpu_to_le32(src->lmv_layout_version);
+}
 #endif /* _LFSCK_INTERNAL_H */
index 127a87a..12dbeb5 100644 (file)
@@ -935,13 +935,8 @@ static int lfsck_scan_lpf_bad_entries(const struct lu_env *env,
                        break;
 
                ent->lde_namelen = le16_to_cpu(ent->lde_namelen);
-               if (ent->lde_name[0] == '.') {
-                       if (ent->lde_namelen == 1)
-                               goto next;
-
-                       if (ent->lde_namelen == 2 && ent->lde_name[1] == '.')
-                               goto next;
-               }
+               if (name_is_dot_or_dotdot(ent->lde_name, ent->lde_namelen))
+                       goto next;
 
                /* name length must be strlen("MDTxxxx") */
                if (ent->lde_namelen != 7)
index 6ef4cc7..143ce77 100644 (file)
@@ -64,8 +64,8 @@ lfsck_namespace_assistant_req_init(struct lfsck_instance *lfsck,
                return ERR_PTR(-ENOMEM);
 
        INIT_LIST_HEAD(&lnr->lnr_lar.lar_list);
-       lu_object_get(&lfsck->li_obj_dir->do_lu);
-       lnr->lnr_obj = lfsck->li_obj_dir;
+       lnr->lnr_obj = lfsck_object_get(lfsck->li_obj_dir);
+       lnr->lnr_lmv = lfsck_lmv_get(lfsck->li_lmv);
        lnr->lnr_fid = ent->lde_fid;
        lnr->lnr_oit_cookie = lfsck->li_pos_current.lp_oit_cookie;
        lnr->lnr_dir_cookie = ent->lde_hash;
@@ -84,6 +84,9 @@ static void lfsck_namespace_assistant_req_fini(const struct lu_env *env,
        struct lfsck_namespace_req *lnr =
                        container_of0(lar, struct lfsck_namespace_req, lnr_lar);
 
+       if (lnr->lnr_lmv != NULL)
+               lfsck_lmv_put(env, lnr->lnr_lmv);
+
        lu_object_put(env, &lnr->lnr_obj->do_lu);
        OBD_FREE(lnr, lnr->lnr_size);
 }
@@ -131,6 +134,25 @@ static void lfsck_namespace_le_to_cpu(struct lfsck_namespace *dst,
        dst->ln_bad_type_repaired = le64_to_cpu(src->ln_bad_type_repaired);
        dst->ln_lost_dirent_repaired =
                                le64_to_cpu(src->ln_lost_dirent_repaired);
+       dst->ln_striped_dirs_scanned =
+                               le64_to_cpu(src->ln_striped_dirs_scanned);
+       dst->ln_striped_dirs_repaired =
+                               le64_to_cpu(src->ln_striped_dirs_repaired);
+       dst->ln_striped_dirs_failed =
+                               le64_to_cpu(src->ln_striped_dirs_failed);
+       dst->ln_striped_dirs_disabled =
+                               le64_to_cpu(src->ln_striped_dirs_disabled);
+       dst->ln_striped_dirs_skipped =
+                               le64_to_cpu(src->ln_striped_dirs_skipped);
+       dst->ln_striped_shards_scanned =
+                               le64_to_cpu(src->ln_striped_shards_scanned);
+       dst->ln_striped_shards_repaired =
+                               le64_to_cpu(src->ln_striped_shards_repaired);
+       dst->ln_striped_shards_failed =
+                               le64_to_cpu(src->ln_striped_shards_failed);
+       dst->ln_striped_shards_skipped =
+                               le64_to_cpu(src->ln_striped_shards_skipped);
+       dst->ln_name_hash_repaired = le64_to_cpu(src->ln_name_hash_repaired);
        dst->ln_local_lpf_scanned = le64_to_cpu(src->ln_local_lpf_scanned);
        dst->ln_local_lpf_moved = le64_to_cpu(src->ln_local_lpf_moved);
        dst->ln_local_lpf_skipped = le64_to_cpu(src->ln_local_lpf_skipped);
@@ -181,6 +203,25 @@ static void lfsck_namespace_cpu_to_le(struct lfsck_namespace *dst,
        dst->ln_bad_type_repaired = cpu_to_le64(src->ln_bad_type_repaired);
        dst->ln_lost_dirent_repaired =
                                cpu_to_le64(src->ln_lost_dirent_repaired);
+       dst->ln_striped_dirs_scanned =
+                               cpu_to_le64(src->ln_striped_dirs_scanned);
+       dst->ln_striped_dirs_repaired =
+                               cpu_to_le64(src->ln_striped_dirs_repaired);
+       dst->ln_striped_dirs_failed =
+                               cpu_to_le64(src->ln_striped_dirs_failed);
+       dst->ln_striped_dirs_disabled =
+                               cpu_to_le64(src->ln_striped_dirs_disabled);
+       dst->ln_striped_dirs_skipped =
+                               cpu_to_le64(src->ln_striped_dirs_skipped);
+       dst->ln_striped_shards_scanned =
+                               cpu_to_le64(src->ln_striped_shards_scanned);
+       dst->ln_striped_shards_repaired =
+                               cpu_to_le64(src->ln_striped_shards_repaired);
+       dst->ln_striped_shards_failed =
+                               cpu_to_le64(src->ln_striped_shards_failed);
+       dst->ln_striped_shards_skipped =
+                               cpu_to_le64(src->ln_striped_shards_skipped);
+       dst->ln_name_hash_repaired = cpu_to_le64(src->ln_name_hash_repaired);
        dst->ln_local_lpf_scanned = cpu_to_le64(src->ln_local_lpf_scanned);
        dst->ln_local_lpf_moved = cpu_to_le64(src->ln_local_lpf_moved);
        dst->ln_local_lpf_skipped = cpu_to_le64(src->ln_local_lpf_skipped);
@@ -728,6 +769,8 @@ static int lfsck_namespace_filter_linkea_entry(struct linkea_data *ldata,
  *  type "O":          The MDT-object has no linkEA, and there is no name
  *                     entry that references the MDT-object.
  *
+ *  type "S":          The orphan MDT-object is a shard of a striped directory
+ *
  * \see lfsck_layout_recreate_parent() for more types.
  *
  * The orphan name will be like:
@@ -1088,6 +1131,8 @@ log:
  *
  * \see lfsck_layout_recreate_parent() for more types.
  *
+ * \param[in] lmv      pointer to master LMV EA that will be set to the orphan
+ *
  * \retval             positive number for repaired cases
  * \retval             0 if needs to repair nothing
  * \retval             negative error number on failure
@@ -1095,7 +1140,8 @@ log:
 static int lfsck_namespace_create_orphan_remote(const struct lu_env *env,
                                                struct lfsck_component *com,
                                                struct dt_object *orphan,
-                                               __u32 type)
+                                               __u32 type,
+                                               struct lmv_mds_md_v1 *lmv)
 {
        struct lfsck_thread_info        *info   = lfsck_env_info(env);
        struct lfsck_request            *lr     = &info->lti_lr;
@@ -1144,6 +1190,13 @@ static int lfsck_namespace_create_orphan_remote(const struct lu_env *env,
        lr->lr_active = LFSCK_TYPE_NAMESPACE;
        lr->lr_fid = *fid;
        lr->lr_type = type;
+       if (lmv != NULL) {
+               lr->lr_hash_type = lmv->lmv_hash_type;
+               lr->lr_stripe_count = lmv->lmv_stripe_count;
+               lr->lr_layout_version = lmv->lmv_layout_version;
+               memcpy(lr->lr_pool_name, lmv->lmv_pool_name,
+                      sizeof(lr->lr_pool_name));
+       }
 
        ptlrpc_request_set_replen(req);
        rc = ptlrpc_queue_wait(req);
@@ -1187,13 +1240,16 @@ out:
  *
  * \see lfsck_layout_recreate_parent() for more types.
  *
+ * \param[in] lmv      pointer to master LMV EA that will be set to the orphan
+ *
  * \retval             positive number for repaired cases
  * \retval             negative error number on failure
  */
 static int lfsck_namespace_create_orphan_local(const struct lu_env *env,
                                               struct lfsck_component *com,
                                               struct dt_object *orphan,
-                                              __u32 type)
+                                              __u32 type,
+                                              struct lmv_mds_md_v1 *lmv)
 {
        struct lfsck_thread_info        *info   = lfsck_env_info(env);
        struct lu_attr                  *la     = &info->lti_la;
@@ -1202,6 +1258,7 @@ static int lfsck_namespace_create_orphan_local(const struct lu_env *env,
        struct lu_name                  *cname  = &info->lti_name2;
        struct dt_insert_rec            *rec    = &info->lti_dt_rec;
        struct lu_fid                   *tfid   = &info->lti_fid;
+       struct lmv_mds_md_v1            *lmv2   = &info->lti_lmv2;
        const struct lu_fid             *cfid   = lfsck_dto2fid(orphan);
        const struct lu_fid             *pfid;
        struct lfsck_instance           *lfsck  = com->lc_lfsck;
@@ -1212,6 +1269,7 @@ static int lfsck_namespace_create_orphan_local(const struct lu_env *env,
        struct lustre_handle             lh     = { 0 };
        struct linkea_data               ldata  = { 0 };
        struct lu_buf                    linkea_buf;
+       struct lu_buf                    lmv_buf;
        char                             name[32];
        int                              namelen;
        int                              idx    = 0;
@@ -1288,6 +1346,17 @@ static int lfsck_namespace_create_orphan_local(const struct lu_env *env,
        if (rc != 0)
                GOTO(stop, rc);
 
+       if (lmv != NULL) {
+               lmv->lmv_magic = LMV_MAGIC;
+               lmv->lmv_master_mdt_index = lfsck_dev_idx(dev);
+               lfsck_lmv_header_cpu_to_le(lmv2, lmv);
+               lfsck_buf_init(&lmv_buf, lmv2, sizeof(*lmv2));
+               rc = dt_declare_xattr_set(env, child, &lmv_buf,
+                                         XATTR_NAME_LMV, 0, th);
+               if (rc != 0)
+                       GOTO(stop, rc);
+       }
+
        lfsck_buf_init(&linkea_buf, ldata.ld_buf->lb_buf,
                       ldata.ld_leh->leh_len);
        rc = dt_declare_xattr_set(env, child, &linkea_buf,
@@ -1337,6 +1406,13 @@ static int lfsck_namespace_create_orphan_local(const struct lu_env *env,
                        GOTO(unlock2, rc);
        }
 
+       if (lmv != NULL) {
+               rc = dt_xattr_set(env, child, &lmv_buf, XATTR_NAME_LMV, 0,
+                                 th, BYPASS_CAPA);
+               if (rc != 0)
+                       GOTO(unlock2, rc);
+       }
+
        rc = dt_xattr_set(env, child, &linkea_buf,
                          XATTR_NAME_LINK, 0, th, BYPASS_CAPA);
        dt_write_unlock(env, child);
@@ -1394,23 +1470,26 @@ log:
  *
  * \see lfsck_layout_recreate_parent() for more types.
  *
+ * \param[in] lmv      pointer to master LMV EA that will be set to the orphan
+ *
  * \retval             positive number for repaired cases
  * \retval             0 if needs to repair nothing
  * \retval             negative error number on failure
  */
 static int lfsck_namespace_create_orphan(const struct lu_env *env,
                                         struct lfsck_component *com,
-                                        struct dt_object *orphan)
+                                        struct dt_object *orphan,
+                                        struct lmv_mds_md_v1 *lmv)
 {
        struct lfsck_namespace *ns = com->lc_file_ram;
        int                     rc;
 
        if (dt_object_remote(orphan))
                rc = lfsck_namespace_create_orphan_remote(env, com, orphan,
-                                                         S_IFDIR);
+                                                         S_IFDIR, lmv);
        else
                rc = lfsck_namespace_create_orphan_local(env, com, orphan,
-                                                        S_IFDIR);
+                                                        S_IFDIR, lmv);
 
        if (rc != 0)
                ns->ln_flags |= LF_INCONSISTENT;
@@ -2264,6 +2343,7 @@ lfsck_namespace_dsd_single(const struct lu_env *env,
        struct lfsck_namespace   *ns            = com->lc_file_ram;
        struct lfsck_instance    *lfsck         = com->lc_lfsck;
        struct dt_object         *parent        = NULL;
+       struct lmv_mds_md_v1     *lmv;
        int                       rc            = 0;
        ENTRY;
 
@@ -2308,8 +2388,33 @@ lfsck_namespace_dsd_single(const struct lu_env *env,
                lfsck_ibits_unlock(lh, LCK_EX);
 
 lost_parent:
+               lmv = &info->lti_lmv;
+               rc = lfsck_read_stripe_lmv(env, child, lmv);
+               if (rc != 0 && rc != -ENODATA)
+                       GOTO(out, rc);
+
+               if (rc == -ENODATA || lmv->lmv_magic != LMV_MAGIC_STRIPE) {
+                       lmv = NULL;
+               } else if (lfsck_shard_name_to_index(env,
+                                       cname->ln_name, cname->ln_namelen,
+                                       S_IFDIR, cfid) < 0) {
+                       /* It is an invalid name entry, we
+                        * cannot trust the parent also. */
+                       rc = lfsck_namespace_shrink_linkea(env, com, child,
+                                               ldata, cname, tfid, true);
+                       if (rc < 0)
+                               GOTO(out, rc);
+
+                       snprintf(info->lti_tmpbuf, sizeof(info->lti_tmpbuf),
+                                "-"DFID, PFID(pfid));
+                       rc = lfsck_namespace_insert_orphan(env, com, child,
+                                               info->lti_tmpbuf, "S", NULL);
+
+                       GOTO(out, rc);
+               }
+
                /* Create the lost parent as an orphan. */
-               rc = lfsck_namespace_create_orphan(env, com, parent);
+               rc = lfsck_namespace_create_orphan(env, com, parent, lmv);
                if (rc >= 0) {
                        /* Add the missing name entry to the parent. */
                        rc = lfsck_namespace_insert_normal(env, com, parent,
@@ -2371,6 +2476,28 @@ lost_parent:
                }
 
                lfsck_ibits_unlock(lh, LCK_EX);
+               rc = lfsck_namespace_check_name(env, parent, child, cname);
+               if (rc == -ENOENT)
+                       goto lost_parent;
+
+               if (rc < 0)
+                       GOTO(out, rc);
+
+               /* It is an invalid name entry, drop it. */
+               if (unlikely(rc > 0)) {
+                       rc = lfsck_namespace_shrink_linkea(env, com, child,
+                                               ldata, cname, tfid, true);
+                       if (rc >= 0) {
+                               snprintf(info->lti_tmpbuf,
+                                        sizeof(info->lti_tmpbuf),
+                                        "-"DFID, PFID(pfid));
+                               rc = lfsck_namespace_insert_orphan(env, com,
+                                       child, info->lti_tmpbuf, "D", NULL);
+                       }
+
+                       GOTO(out, rc);
+               }
+
                /* Add the missing name entry back to the namespace. */
                rc = lfsck_namespace_insert_normal(env, com, parent, child,
                                                   cname->ln_name);
@@ -3172,7 +3299,7 @@ lost_parent:
 
                                /* Create the lost parent as an orphan. */
                                rc = lfsck_namespace_create_orphan(env, com,
-                                                                  parent);
+                                                               parent, NULL);
                                if (rc < 0) {
                                        lfsck_object_put(env, parent);
 
@@ -3303,6 +3430,30 @@ lost_parent:
                        GOTO(out, rc = 0);
                }
 
+               rc = lfsck_namespace_check_name(env, parent, child, cname);
+               if (rc == -ENOENT)
+                       goto lost_parent;
+
+               if (rc < 0) {
+                       lfsck_object_put(env, parent);
+
+                       GOTO(out, rc);
+               }
+
+               /* It is an invalid name entry, drop it. */
+               if (unlikely(rc > 0)) {
+                       lfsck_object_put(env, parent);
+                       rc = lfsck_namespace_shrink_linkea(env, com, child,
+                                               &ldata, cname, pfid, true);
+                       if (rc < 0)
+                               GOTO(out, rc);
+
+                       if (rc > 0)
+                               repaired = true;
+
+                       continue;
+               }
+
                /* Add the missing name entry back to the namespace. */
                rc = lfsck_namespace_insert_normal(env, com, parent, child,
                                                   cname->ln_name);
@@ -3421,6 +3572,16 @@ static void lfsck_namespace_dump_statistics(struct seq_file *m,
                      "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",
@@ -3446,6 +3607,16 @@ static void lfsck_namespace_dump_statistics(struct seq_file *m,
                      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);
@@ -3535,6 +3706,90 @@ lfsck_namespace_fail(const struct lu_env *env, struct lfsck_component *com,
        up_write(&com->lc_sem);
 }
 
+static void lfsck_namespace_close_dir(const struct lu_env *env,
+                                     struct lfsck_component *com)
+{
+       struct lfsck_namespace          *ns     = com->lc_file_ram;
+       struct lfsck_assistant_data     *lad    = com->lc_data;
+       struct lfsck_instance           *lfsck  = com->lc_lfsck;
+       struct lfsck_lmv                *llmv   = lfsck->li_lmv;
+       struct lfsck_namespace_req      *lnr;
+       __u32                            size   =
+                               sizeof(*lnr) + LFSCK_TMPBUF_LEN;
+       bool                             wakeup = false;
+       ENTRY;
+
+       if (llmv == NULL)
+               RETURN_EXIT;
+
+       OBD_ALLOC(lnr, size);
+       if (lnr == NULL) {
+               ns->ln_striped_dirs_skipped++;
+
+               RETURN_EXIT;
+       }
+
+       /* Generate a dummy request to indicate that all shards' name entry
+        * in this striped directory has been scanned for the first time. */
+       INIT_LIST_HEAD(&lnr->lnr_lar.lar_list);
+       lnr->lnr_obj = lfsck_object_get(lfsck->li_obj_dir);
+       lnr->lnr_lmv = lfsck_lmv_get(llmv);
+       lnr->lnr_fid = *lfsck_dto2fid(lfsck->li_obj_dir);
+       lnr->lnr_oit_cookie = lfsck->li_pos_current.lp_oit_cookie;
+       lnr->lnr_dir_cookie = MDS_DIR_END_OFF;
+       lnr->lnr_size = size;
+
+       spin_lock(&lad->lad_lock);
+       if (lad->lad_assistant_status < 0) {
+               spin_unlock(&lad->lad_lock);
+               lfsck_namespace_assistant_req_fini(env, &lnr->lnr_lar);
+               ns->ln_striped_dirs_skipped++;
+
+               RETURN_EXIT;
+       }
+
+       list_add_tail(&lnr->lnr_lar.lar_list, &lad->lad_req_list);
+       if (lad->lad_prefetched == 0)
+               wakeup = true;
+
+       lad->lad_prefetched++;
+       spin_unlock(&lad->lad_lock);
+       if (wakeup)
+               wake_up_all(&lad->lad_thread.t_ctl_waitq);
+
+       EXIT;
+}
+
+static int lfsck_namespace_open_dir(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_lmv        *llmv   = lfsck->li_lmv;
+       int                      rc     = 0;
+       ENTRY;
+
+       if (llmv == NULL)
+               RETURN(0);
+
+       if (llmv->ll_lmv_master) {
+               struct lmv_mds_md_v1 *lmv = &llmv->ll_lmv;
+
+               if (lmv->lmv_master_mdt_index !=
+                   lfsck_dev_idx(lfsck->li_bottom)) {
+                       lmv->lmv_master_mdt_index =
+                               lfsck_dev_idx(lfsck->li_bottom);
+                       ns->ln_flags |= LF_INCONSISTENT;
+                       llmv->ll_lmv_updated = 1;
+               }
+       } else {
+               rc = lfsck_namespace_verify_stripe_slave(env, com,
+                                       lfsck->li_obj_dir, llmv);
+       }
+
+       RETURN(rc > 0 ? 0 : rc);
+}
+
 static int lfsck_namespace_checkpoint(const struct lu_env *env,
                                      struct lfsck_component *com, bool init)
 {
@@ -3631,6 +3886,16 @@ static int lfsck_namespace_prep(const struct lu_env *env,
                        ns->ln_mul_ref_repaired = 0;
                        ns->ln_bad_type_repaired = 0;
                        ns->ln_lost_dirent_repaired = 0;
+                       ns->ln_striped_dirs_scanned = 0;
+                       ns->ln_striped_dirs_repaired = 0;
+                       ns->ln_striped_dirs_failed = 0;
+                       ns->ln_striped_dirs_disabled = 0;
+                       ns->ln_striped_dirs_skipped = 0;
+                       ns->ln_striped_shards_scanned = 0;
+                       ns->ln_striped_shards_repaired = 0;
+                       ns->ln_striped_shards_failed = 0;
+                       ns->ln_striped_shards_skipped = 0;
+                       ns->ln_name_hash_repaired = 0;
                        fid_zero(&ns->ln_fid_latest_scanned_phase2);
                        if (list_empty(&com->lc_link_dir))
                                list_add_tail(&com->lc_link_dir,
@@ -4150,6 +4415,7 @@ static int lfsck_namespace_in_notify(const struct lu_env *env,
        switch (lr->lr_event) {
        case LE_CREATE_ORPHAN: {
                struct dt_object *orphan = NULL;
+               struct lmv_mds_md_v1 *lmv;
 
                CDEBUG(D_LFSCK, "%s: namespace LFSCK handling notify from "
                       "MDT %x to create orphan"DFID" with type %o\n",
@@ -4163,8 +4429,20 @@ static int lfsck_namespace_in_notify(const struct lu_env *env,
                if (dt_object_exists(orphan))
                        GOTO(out_create, rc = -EEXIST);
 
+               if (lr->lr_stripe_count > 0) {
+                       lmv = &lfsck_env_info(env)->lti_lmv;
+                       memset(lmv, 0, sizeof(*lmv));
+                       lmv->lmv_hash_type = lr->lr_hash_type;
+                       lmv->lmv_stripe_count = lr->lr_stripe_count;
+                       lmv->lmv_layout_version = lr->lr_layout_version;
+                       memcpy(lmv->lmv_pool_name, lr->lr_pool_name,
+                              sizeof(lmv->lmv_pool_name));
+               } else {
+                       lmv = NULL;
+               }
+
                rc = lfsck_namespace_create_orphan_local(env, com, orphan,
-                                                        lr->lr_type);
+                                                        lr->lr_type, lmv);
 
                GOTO(out_create, rc = (rc == 1) ? 0 : rc);
 
@@ -4332,6 +4610,8 @@ static int lfsck_namespace_query(const struct lu_env *env,
 static struct lfsck_operations lfsck_namespace_ops = {
        .lfsck_reset            = lfsck_namespace_reset,
        .lfsck_fail             = lfsck_namespace_fail,
+       .lfsck_close_dir        = lfsck_namespace_close_dir,
+       .lfsck_open_dir         = lfsck_namespace_open_dir,
        .lfsck_checkpoint       = lfsck_namespace_checkpoint,
        .lfsck_prep             = lfsck_namespace_prep,
        .lfsck_exec_oit         = lfsck_namespace_exec_oit,
@@ -4379,11 +4659,13 @@ int lfsck_namespace_repair_dangling(const struct lu_env *env,
        struct dt_allocation_hint       *hint   = &info->lti_hint;
        struct dt_object_format         *dof    = &info->lti_dof;
        struct dt_insert_rec            *rec    = &info->lti_dt_rec;
+       struct lmv_mds_md_v1            *lmv2   = &info->lti_lmv2;
        struct dt_object                *parent = lnr->lnr_obj;
        const struct lu_name            *cname;
        struct linkea_data               ldata  = { 0 };
        struct lustre_handle             lh     = { 0 };
        struct lu_buf                    linkea_buf;
+       struct lu_buf                    lmv_buf;
        struct lfsck_instance           *lfsck  = com->lc_lfsck;
        struct lfsck_bookmark           *bk     = &lfsck->li_bookmark_ram;
        struct dt_device                *dev    = lfsck_obj2dt_dev(child);
@@ -4471,9 +4753,31 @@ int lfsck_namespace_repair_dangling(const struct lu_env *env,
                rc = dt_declare_ref_add(env, child, th);
                if (rc != 0)
                        GOTO(stop, rc);
+
+               /* 5a. generate slave LMV EA. */
+               if (lnr->lnr_lmv != NULL && lnr->lnr_lmv->ll_lmv_master) {
+                       int idx;
+
+                       idx = lfsck_shard_name_to_index(env,
+                                       lnr->lnr_name, lnr->lnr_namelen,
+                                       type, lfsck_dto2fid(child));
+                       if (unlikely(idx < 0))
+                               GOTO(stop, rc = idx);
+
+                       *lmv2 = lnr->lnr_lmv->ll_lmv;
+                       lmv2->lmv_magic = LMV_MAGIC_STRIPE;
+                       lmv2->lmv_master_mdt_index = idx;
+
+                       lfsck_lmv_header_cpu_to_le(lmv2, lmv2);
+                       lfsck_buf_init(&lmv_buf, lmv2, sizeof(*lmv2));
+                       rc = dt_declare_xattr_set(env, child, &lmv_buf,
+                                                 XATTR_NAME_LMV, 0, th);
+                       if (rc != 0)
+                               GOTO(stop, rc);
+               }
        }
 
-       /* 5a. insert linkEA for child */
+       /* 6a. insert linkEA for child */
        lfsck_buf_init(&linkea_buf, ldata.ld_buf->lb_buf,
                       ldata.ld_leh->leh_len);
        rc = dt_declare_xattr_set(env, child, &linkea_buf,
@@ -4515,9 +4819,17 @@ int lfsck_namespace_repair_dangling(const struct lu_env *env,
                rc = dt_ref_add(env, child, th);
                if (rc != 0)
                        GOTO(unlock, rc);
+
+               /* 5b. generate slave LMV EA. */
+               if (lnr->lnr_lmv != NULL && lnr->lnr_lmv->ll_lmv_master) {
+                       rc = dt_xattr_set(env, child, &lmv_buf, XATTR_NAME_LMV,
+                                         0, th, BYPASS_CAPA);
+                       if (rc != 0)
+                               GOTO(unlock, rc);
+               }
        }
 
-       /* 5b. insert linkEA for child. */
+       /* 6b. insert linkEA for child. */
        rc = dt_xattr_set(env, child, &linkea_buf,
                          XATTR_NAME_LINK, 0, th, BYPASS_CAPA);
 
@@ -4647,6 +4959,13 @@ static int lfsck_namespace_assistant_handler_p1(const struct lu_env *env,
 dangling:
                rc = lfsck_namespace_check_exist(env, dir, obj, lnr->lnr_name);
                if (rc == 0) {
+                       if (!lfsck_is_valid_slave_name_entry(env, lnr->lnr_lmv,
+                                       lnr->lnr_name, lnr->lnr_namelen)) {
+                               type = LNIT_BAD_DIRENT;
+
+                               GOTO(out, rc);
+                       }
+
                        type = LNIT_DANGLING;
                        rc = lfsck_namespace_repair_dangling(env, com,
                                                             obj, lnr);
@@ -4717,6 +5036,16 @@ again:
 
                ns->ln_flags |= LF_INCONSISTENT;
 
+               /* If the name entry hash does not match the slave striped
+                * directory, and the name entry does not match also, then
+                * it is quite possible that name entry is corrupted. */
+               if (!lfsck_is_valid_slave_name_entry(env, lnr->lnr_lmv,
+                                       lnr->lnr_name, lnr->lnr_namelen)) {
+                       type = LNIT_BAD_DIRENT;
+
+                       GOTO(stop, rc = 0);
+               }
+
                /* If the file type stored in the name entry does not match
                 * the file type claimed by the object, and the object does
                 * not recognize the name entry, then it is quite possible
@@ -5203,9 +5532,7 @@ static void lfsck_namespace_scan_local_lpf(const struct lu_env *env,
                }
 
                /* skip dot and dotdot entries */
-               if (ent->lde_name[0] == '.' &&
-                   (ent->lde_namelen == 1 ||
-                    (ent->lde_namelen == 2 && ent->lde_name[1] == '.')))
+               if (name_is_dot_or_dotdot(ent->lde_name, ent->lde_namelen))
                        goto next;
 
                if (!fid_seq_in_fldb(fid_seq(&ent->lde_fid)))
@@ -5350,7 +5677,7 @@ static int lfsck_namespace_assistant_handler_p2(const struct lu_env *env,
                        goto checkpoint;
                }
 
-               target = lfsck_object_find(env, lfsck, &fid);
+               target = lfsck_object_find_by_dev(env, lfsck->li_bottom, &fid);
                if (IS_ERR(target)) {
                        rc = PTR_ERR(target);
                        goto checkpoint;
diff --git a/lustre/lfsck/lfsck_striped_dir.c b/lustre/lfsck/lfsck_striped_dir.c
new file mode 100644 (file)
index 0000000..8a5d5de
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2 for more details.  A copy is
+ * included in the COPYING file that accompanied this code.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2014, Intel Corporation.
+ */
+/*
+ * lustre/lfsck/lfsck_striped_dir.c
+ *
+ * Author: Fan, Yong <fan.yong@intel.com>
+ */
+
+#define DEBUG_SUBSYSTEM S_LFSCK
+
+#include <lustre/lustre_idl.h>
+#include <lu_object.h>
+#include <dt_object.h>
+#include <md_object.h>
+#include <lustre_fid.h>
+#include <lustre_lib.h>
+#include <lustre_net.h>
+#include <lustre_lmv.h>
+#include <lustre/lustre_user.h>
+
+#include "lfsck_internal.h"
+
+void lfsck_lmv_put(const struct lu_env *env, struct lfsck_lmv *llmv)
+{
+       if (llmv != NULL && atomic_dec_and_test(&llmv->ll_ref)) {
+               if (llmv->ll_lslr != NULL)
+                       OBD_FREE_LARGE(llmv->ll_lslr,
+                               sizeof(struct lfsck_slave_lmv_rec) *
+                               llmv->ll_stripes_allocated);
+
+               OBD_FREE_PTR(llmv);
+       }
+}
+
+static inline bool lfsck_is_valid_slave_lmv(struct lmv_mds_md_v1 *lmv)
+{
+       return lmv->lmv_stripe_count >= 1 &&
+              lmv->lmv_stripe_count <= LFSCK_LMV_MAX_STRIPES &&
+              lmv->lmv_stripe_count > lmv->lmv_master_mdt_index &&
+              lmv_is_known_hash_type(lmv->lmv_hash_type);
+}
+
+int lfsck_read_stripe_lmv(const struct lu_env *env, struct dt_object *obj,
+                         struct lmv_mds_md_v1 *lmv)
+{
+       struct dt_object *bottom;
+       int               rc;
+
+       /* Currently, we only store the LMV header on disk. It is the LOD's
+        * duty to iterate the master MDT-object's directory to compose the
+        * integrated LMV EA. But here, we only want to load the LMV header,
+        * so we need to bypass LOD to avoid unnecessary iteration in LOD. */
+       bottom = lu2dt(container_of0(obj->do_lu.lo_header->loh_layers.prev,
+                                    struct lu_object, lo_linkage));
+       if (unlikely(bottom == NULL))
+               return -ENOENT;
+
+       dt_read_lock(env, bottom, 0);
+       rc = dt_xattr_get(env, bottom, lfsck_buf_get(env, lmv, sizeof(*lmv)),
+                         XATTR_NAME_LMV, BYPASS_CAPA);
+       dt_read_unlock(env, bottom);
+       if (rc != sizeof(*lmv))
+               return rc > 0 ? -EINVAL : rc;
+
+       lfsck_lmv_header_le_to_cpu(lmv, lmv);
+       if ((lmv->lmv_magic == LMV_MAGIC &&
+            !(lmv->lmv_hash_type & LMV_HASH_FLAG_MIGRATION)) ||
+           (lmv->lmv_magic == LMV_MAGIC_STRIPE &&
+            !(lmv->lmv_hash_type & LMV_HASH_FLAG_DEAD)))
+               return 0;
+
+       return -ENODATA;
+}
+
+/**
+ * Parse the shard's index from the given shard name.
+ *
+ * The valid shard name/type should be:
+ * 1) The type must be S_IFDIR
+ * 2) The name should be $FID:$index
+ * 3) the index should within valid range.
+ *
+ * \param[in] env      pointer to the thread context
+ * \param[in] name     the shard name
+ * \param[in] namelen  the name length
+ * \param[in] type     the entry's type
+ * \param[in] fid      the entry's FID
+ *
+ * \retval             zero or positive number for the index from the name
+ * \retval             negative error number on failure
+ */
+int lfsck_shard_name_to_index(const struct lu_env *env, const char *name,
+                             int namelen, __u16 type, const struct lu_fid *fid)
+{
+       char    *name2  = lfsck_env_info(env)->lti_tmpbuf2;
+       int      len;
+       int      idx    = 0;
+
+       if (!S_ISDIR(type))
+               return -ENOTDIR;
+
+       LASSERT(name != name2);
+
+       len = snprintf(name2, sizeof(lfsck_env_info(env)->lti_tmpbuf2),
+                      DFID":", PFID(fid));
+       if (namelen < len + 1 || memcmp(name, name2, len) != 0)
+               return -EINVAL;
+
+       do {
+               if (!isdigit(name[len]))
+                       return -EINVAL;
+
+               idx = idx * 10 + name[len++] - '0';
+       } while (len < namelen);
+
+       if (idx >= LFSCK_LMV_MAX_STRIPES)
+               return -EINVAL;
+
+       return idx;
+}
+
+bool lfsck_is_valid_slave_name_entry(const struct lu_env *env,
+                                    struct lfsck_lmv *llmv,
+                                    const char *name, int namelen)
+{
+       struct lmv_mds_md_v1    *lmv;
+       int                      idx;
+
+       if (llmv == NULL || !llmv->ll_lmv_slave || !llmv->ll_lmv_verified)
+               return true;
+
+       lmv = &llmv->ll_lmv;
+       idx = lmv_name_to_stripe_index(lmv->lmv_hash_type,
+                                      lmv->lmv_stripe_count,
+                                      name, namelen);
+       if (unlikely(idx != lmv->lmv_master_mdt_index))
+               return false;
+
+       return true;
+}
+
+/**
+ * Check whether the given name is a valid entry under the @parent.
+ *
+ * If the @parent is a striped directory then the @child should one
+ * shard of the striped directory, its name should be $FID:$index.
+ *
+ * If the @parent is a shard of a striped directory, then the name hash
+ * should match the MDT, otherwise it is invalid.
+ *
+ * \param[in] env      pointer to the thread context
+ * \param[in] parent   the parent directory
+ * \param[in] child    the child object to be checked
+ * \param[in] cname    the name for the @child in the parent directory
+ *
+ * \retval             positive number for invalid name entry
+ * \retval             0 if the name is valid or uncertain
+ * \retval             negative error number on failure
+ */
+int lfsck_namespace_check_name(const struct lu_env *env,
+                              struct dt_object *parent,
+                              struct dt_object *child,
+                              const struct lu_name *cname)
+{
+       struct lmv_mds_md_v1    *lmv = &lfsck_env_info(env)->lti_lmv;
+       int                      idx;
+       int                      rc;
+
+       rc = lfsck_read_stripe_lmv(env, parent, lmv);
+       if (rc != 0)
+               RETURN(rc == -ENODATA ? 0 : rc);
+
+       if (lmv->lmv_magic == LMV_MAGIC_STRIPE) {
+               if (!lfsck_is_valid_slave_lmv(lmv))
+                       return 0;
+
+               idx = lmv_name_to_stripe_index(lmv->lmv_hash_type,
+                                              lmv->lmv_stripe_count,
+                                              cname->ln_name,
+                                              cname->ln_namelen);
+               if (unlikely(idx != lmv->lmv_master_mdt_index))
+                       return 1;
+       } else if (lfsck_shard_name_to_index(env, cname->ln_name,
+                       cname->ln_namelen, lfsck_object_type(child),
+                       lfsck_dto2fid(child)) < 0) {
+               return 1;
+       }
+
+       return 0;
+}
+
+int lfsck_namespace_verify_stripe_slave(const struct lu_env *env,
+                                       struct lfsck_component *com,
+                                       struct dt_object *obj,
+                                       struct lfsck_lmv *llmv)
+{
+       /* XXX: TBD */
+       return 0;
+}
index 08592bf..41f36df 100644 (file)
@@ -416,7 +416,7 @@ lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data,
 
        /* Both migrating dir and unknown hash dir need to try
         * all of sub-stripes */
-       if (lsm != NULL && !lmv_is_known_hash_type(lsm)) {
+       if (lsm != NULL && !lmv_is_known_hash_type(lsm->lsm_md_hash_type)) {
                struct lmv_oinfo *oinfo;
 
                oinfo = &lsm->lsm_md_oinfo[0];
index 637c5a2..1110718 100644 (file)
@@ -135,10 +135,6 @@ static inline int lmv_stripe_md_size(int stripe_count)
        return sizeof(*lsm) + stripe_count * sizeof(lsm->lsm_md_oinfo[0]);
 }
 
-int lmv_name_to_stripe_index(enum lmv_hash_type hashtype,
-                            unsigned int max_mdt_index,
-                            const char *name, int namelen);
-
 static inline const struct lmv_oinfo *
 lsm_name_to_stripe_info(const struct lmv_stripe_md *lsm, const char *name,
                        int namelen)
@@ -159,15 +155,9 @@ lsm_name_to_stripe_info(const struct lmv_stripe_md *lsm, const char *name,
        return &lsm->lsm_md_oinfo[stripe_index];
 }
 
-static inline bool lmv_is_known_hash_type(const struct lmv_stripe_md *lsm)
-{
-       return lsm->lsm_md_hash_type == LMV_HASH_TYPE_FNV_1A_64 ||
-              lsm->lsm_md_hash_type == LMV_HASH_TYPE_ALL_CHARS;
-}
-
 static inline bool lmv_need_try_all_stripes(const struct lmv_stripe_md *lsm)
 {
-       return !lmv_is_known_hash_type(lsm) ||
+       return !lmv_is_known_hash_type(lsm->lsm_md_hash_type) ||
               lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION;
 }
 
index d744c78..fd78bd2 100644 (file)
 #include <lustre_ioctl.h>
 #include "lmv_internal.h"
 
-/* This hash is only for testing purpose */
-static inline unsigned int
-lmv_hash_all_chars(unsigned int count, const char *name, int namelen)
-{
-       unsigned int c = 0;
-       const unsigned char *p = (const unsigned char *)name;
-
-       while (--namelen >= 0)
-               c += p[namelen];
-
-       c = c % count;
-
-       return c;
-}
-
-static inline unsigned int
-lmv_hash_fnv1a(unsigned int count, const char *name, int namelen)
-{
-       __u64   hash;
-
-       hash = lustre_hash_fnv_1a_64(name, namelen);
-
-       hash = hash % count;
-
-       return hash;
-}
-
-int lmv_name_to_stripe_index(__u32 lmv_hash_type, unsigned int stripe_count,
-                            const char *name, int namelen)
-{
-       int     idx;
-       __u32   hash_type = lmv_hash_type & LMV_HASH_TYPE_MASK;
-
-       LASSERT(namelen > 0);
-       if (stripe_count <= 1)
-               return 0;
-
-       /* for migrating object, always start from 0 stripe */
-       if (lmv_hash_type & LMV_HASH_FLAG_MIGRATION)
-               return 0;
-
-       switch (hash_type) {
-       case LMV_HASH_TYPE_ALL_CHARS:
-               idx = lmv_hash_all_chars(stripe_count, name, namelen);
-               break;
-       case LMV_HASH_TYPE_FNV_1A_64:
-               idx = lmv_hash_fnv1a(stripe_count, name, namelen);
-               break;
-       default:
-               idx = -EBADFD;
-               break;
-       }
-
-       CDEBUG(D_INFO, "name %.*s hash_type %d idx %d\n", namelen, name,
-              hash_type, idx);
-
-       return idx;
-}
-
 static void lmv_activate_target(struct lmv_obd *lmv,
                                 struct lmv_tgt_desc *tgt,
                                 int activate)
@@ -2654,7 +2595,7 @@ retry_unlink:
                 * name from stripe 0, but migrating dir is already handled
                 * inside lmv_locate_target_for_name(), so we only check
                 * unknown hash type directory here */
-               if (!lmv_is_known_hash_type(lsm)) {
+               if (!lmv_is_known_hash_type(lsm->lsm_md_hash_type)) {
                        struct lmv_oinfo *oinfo;
 
                        oinfo = &lsm->lsm_md_oinfo[stripe_index];
index e5cab71..6ce2fe7 100644 (file)
@@ -2653,7 +2653,8 @@ void lustre_swab_lfsck_request(struct lfsck_request *lr)
        lustre_swab_lu_fid(&lr->lr_fid);
        lustre_swab_lu_fid(&lr->lr_fid2);
        lustre_swab_lu_fid(&lr->lr_fid3);
-       CLASSERT(offsetof(typeof(*lr), lr_padding_2) != 0);
+       __swab32s(&lr->lr_stripe_count);
+       __swab32s(&lr->lr_hash_type);
        CLASSERT(offsetof(typeof(*lr), lr_padding_3) != 0);
 }
 EXPORT_SYMBOL(lustre_swab_lfsck_request);
index a0caec0..f6c1cec 100644 (file)
@@ -4677,10 +4677,14 @@ void lustre_assert_wire_constants(void)
                 (long long)(int)offsetof(struct lfsck_request, lr_fid3));
        LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_fid3) == 16, "found %lld\n",
                 (long long)(int)sizeof(((struct lfsck_request *)0)->lr_fid3));
-       LASSERTF((int)offsetof(struct lfsck_request, lr_padding_2) == 80, "found %lld\n",
-                (long long)(int)offsetof(struct lfsck_request, lr_padding_2));
-       LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_padding_2) == 8, "found %lld\n",
-                (long long)(int)sizeof(((struct lfsck_request *)0)->lr_padding_2));
+       LASSERTF((int)offsetof(struct lfsck_request, lr_stripe_count) == 80, "found %lld\n",
+                (long long)(int)offsetof(struct lfsck_request, lr_stripe_count));
+       LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_stripe_count) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct lfsck_request *)0)->lr_stripe_count));
+       LASSERTF((int)offsetof(struct lfsck_request, lr_hash_type) == 84, "found %lld\n",
+                (long long)(int)offsetof(struct lfsck_request, lr_hash_type));
+       LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_hash_type) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct lfsck_request *)0)->lr_hash_type));
        LASSERTF((int)offsetof(struct lfsck_request, lr_padding_3) == 88, "found %lld\n",
                 (long long)(int)offsetof(struct lfsck_request, lr_padding_3));
        LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_padding_3) == 8, "found %lld\n",
index 5e6f93d..c144785 100644 (file)
@@ -2130,7 +2130,8 @@ static void check_lfsck_request(void)
        CHECK_MEMBER(lfsck_request, lr_fid);
        CHECK_MEMBER(lfsck_request, lr_fid2);
        CHECK_MEMBER(lfsck_request, lr_fid3);
-       CHECK_MEMBER(lfsck_request, lr_padding_2);
+       CHECK_MEMBER(lfsck_request, lr_stripe_count);
+       CHECK_MEMBER(lfsck_request, lr_hash_type);
        CHECK_MEMBER(lfsck_request, lr_padding_3);
 
        CHECK_VALUE_X(LFSCK_TYPE_SCRUB);
index f08f453..d58cca0 100644 (file)
@@ -4689,10 +4689,14 @@ void lustre_assert_wire_constants(void)
                 (long long)(int)offsetof(struct lfsck_request, lr_fid3));
        LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_fid3) == 16, "found %lld\n",
                 (long long)(int)sizeof(((struct lfsck_request *)0)->lr_fid3));
-       LASSERTF((int)offsetof(struct lfsck_request, lr_padding_2) == 80, "found %lld\n",
-                (long long)(int)offsetof(struct lfsck_request, lr_padding_2));
-       LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_padding_2) == 8, "found %lld\n",
-                (long long)(int)sizeof(((struct lfsck_request *)0)->lr_padding_2));
+       LASSERTF((int)offsetof(struct lfsck_request, lr_stripe_count) == 80, "found %lld\n",
+                (long long)(int)offsetof(struct lfsck_request, lr_stripe_count));
+       LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_stripe_count) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct lfsck_request *)0)->lr_stripe_count));
+       LASSERTF((int)offsetof(struct lfsck_request, lr_hash_type) == 84, "found %lld\n",
+                (long long)(int)offsetof(struct lfsck_request, lr_hash_type));
+       LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_hash_type) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct lfsck_request *)0)->lr_hash_type));
        LASSERTF((int)offsetof(struct lfsck_request, lr_padding_3) == 88, "found %lld\n",
                 (long long)(int)offsetof(struct lfsck_request, lr_padding_3));
        LASSERTF((int)sizeof(((struct lfsck_request *)0)->lr_padding_3) == 8, "found %lld\n",