Whamcloud - gitweb
LU-169 lov: add generation number to LOV EA
authorJohann Lombardi <johann@whamcloud.com>
Thu, 15 Dec 2011 00:00:00 +0000 (01:00 +0100)
committerOleg Drokin <green@whamcloud.com>
Sun, 8 Jan 2012 02:55:08 +0000 (21:55 -0500)
This patch shrinks lov_mds_md_v*::lmm_stripe_count to 16 bits and use
the remaining 16 bits to store a generation number for the layout.
This generation will be used in conjunction the layout lock to allow
clients to detect when the file layout has changed.
The layout generation starts at 0 and will be bumped each time the
file layout is altered.
For backward compatibility, the layout generation is set to 0 when the
layout is sent to a client that does not support
OBD_CONNECT_LAYOUTLOCK.

This patch also stores OBD_INCOMPAT_LMM_VER in the MDS last_rcvd file
to prevent older versions of Lustre that cannot deal with a 16-bit
lmm_stripe from mounting the filesystem and exporting layouts to older
clients without setting the layout to 0.  This flag will be set in the
last_rcvd file only once we start modifying file layouts, but at least
the current version should not be confused by a 16-bit stripe count
and a non-zero generation.

Signed-off-by: Jacques-Charles Lafoucriere <jacques-charles.lafoucriere@cea.fr>
Change-Id: Ic40083227057eba565287d1a10890875b8a96c13
Signed-off-by: Johann Lombardi <johann@whamcloud.com>
Reviewed-on: http://review.whamcloud.com/1866
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
30 files changed:
lustre/cmm/cmm_object.c
lustre/include/lustre/liblustreapi.h
lustre/include/lustre/lustre_idl.h
lustre/include/lustre/lustre_user.h
lustre/include/lustre_disk.h
lustre/include/md_object.h
lustre/include/obd.h
lustre/include/obd_lov.h
lustre/lclient/lcommon_misc.c
lustre/lov/lov_ea.c
lustre/lov/lov_internal.h
lustre/lov/lov_pack.c
lustre/lov/lov_qos.c
lustre/mdd/mdd_dir.c
lustre/mdd/mdd_internal.h
lustre/mdd/mdd_lov.c
lustre/mdd/mdd_object.c
lustre/mds/mds_lov.c
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_internal.h
lustre/mdt/mdt_lib.c
lustre/mdt/mdt_open.c
lustre/mdt/mdt_reint.c
lustre/obdclass/debug.c
lustre/ptlrpc/pack_generic.c
lustre/ptlrpc/wiretest.c
lustre/tests/sanity.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c
lustre/utils/wiretest.c

index 01e9244..7d757e9 100644 (file)
@@ -594,6 +594,17 @@ static int cml_unlink(const struct lu_env *env, struct md_object *mo_p,
         RETURN(rc);
 }
 
+/** Call mdo_lum_lmm_cmp() on next layer */
+static int cml_lum_lmm_cmp(const struct lu_env *env, struct md_object *mo_c,
+                           const struct md_op_spec *spec, struct md_attr *ma)
+{
+        int rc;
+        ENTRY;
+
+        rc = mdo_lum_lmm_cmp(env, md_object_next(mo_c), spec, ma);
+        RETURN(rc);
+}
+
 /**
  * \ingroup cmm
  * Get mode of object.
@@ -880,6 +891,7 @@ static const struct md_dir_operations cml_dir_ops = {
         .mdo_create      = cml_create,
         .mdo_link        = cml_link,
         .mdo_unlink      = cml_unlink,
+        .mdo_lum_lmm_cmp = cml_lum_lmm_cmp,
         .mdo_name_insert = cml_name_insert,
         .mdo_rename      = cml_rename,
         .mdo_rename_tgt  = cml_rename_tgt,
@@ -1126,6 +1138,12 @@ static int cmr_file_unlock(const struct lu_env *env, struct md_object *mo,
         return -EREMOTE;
 }
 
+static int cmr_lum_lmm_cmp(const struct lu_env *env, struct md_object *mo_c,
+                           const struct md_op_spec *spec, struct md_attr *ma)
+{
+        return -EREMOTE;
+}
+
 /** Set of md_object_operations for cmr. */
 static const struct md_object_operations cmr_mo_ops = {
         .moo_permission    = cmr_permission,
@@ -1527,6 +1545,7 @@ static const struct md_dir_operations cmr_dir_ops = {
         .mdo_create      = cmr_create,
         .mdo_link        = cmr_link,
         .mdo_unlink      = cmr_unlink,
+        .mdo_lum_lmm_cmp = cmr_lum_lmm_cmp,
         .mdo_rename      = cmr_rename,
         .mdo_rename_tgt  = cmr_rename_tgt
 };
index 87c058a..68d8bff 100644 (file)
@@ -100,14 +100,15 @@ extern int llapi_file_get_stripe(const char *path, struct lov_user_md *lum);
 #define HAVE_LLAPI_FILE_LOOKUP
 extern int llapi_file_lookup(int dirfd, const char *name);
 
-#define VERBOSE_COUNT   0x1
-#define VERBOSE_SIZE    0x2
-#define VERBOSE_OFFSET  0x4
-#define VERBOSE_POOL    0x8
-#define VERBOSE_DETAIL  0x10
-#define VERBOSE_OBJID   0x20
-#define VERBOSE_ALL     (VERBOSE_COUNT | VERBOSE_SIZE | VERBOSE_OFFSET | \
-                         VERBOSE_POOL | VERBOSE_OBJID)
+#define VERBOSE_COUNT      0x1
+#define VERBOSE_SIZE       0x2
+#define VERBOSE_OFFSET     0x4
+#define VERBOSE_POOL       0x8
+#define VERBOSE_DETAIL     0x10
+#define VERBOSE_OBJID      0x20
+#define VERBOSE_GENERATION 0x40
+#define VERBOSE_ALL        (VERBOSE_COUNT | VERBOSE_SIZE | VERBOSE_OFFSET | \
+                            VERBOSE_POOL | VERBOSE_OBJID | VERBOSE_GENERATION)
 
 struct find_param {
         unsigned int maxdepth;
index c7b341e..0a3948a 100644 (file)
@@ -1317,7 +1317,9 @@ struct lov_mds_md_v1 {            /* LOV EA mds/wire data (little-endian) */
         __u64 lmm_object_id;      /* LOV object ID */
         __u64 lmm_object_seq;     /* LOV object seq number */
         __u32 lmm_stripe_size;    /* size of stripe in bytes */
-        __u32 lmm_stripe_count;   /* num stripes in use for this object */
+        /* lmm_stripe_count used to be __u32 */
+        __u16 lmm_stripe_count;   /* num stripes in use for this object */
+        __u16 lmm_layout_gen;     /* layout generation number */
         struct lov_ost_data_v1 lmm_objects[0]; /* per-stripe data */
 };
 
@@ -1346,7 +1348,9 @@ struct lov_mds_md_v3 {            /* LOV EA mds/wire data (little-endian) */
         __u64 lmm_object_id;      /* LOV object ID */
         __u64 lmm_object_seq;     /* LOV object seq number */
         __u32 lmm_stripe_size;    /* size of stripe in bytes */
-        __u32 lmm_stripe_count;   /* num stripes in use for this object */
+        /* lmm_stripe_count used to be __u32 */
+        __u16 lmm_stripe_count;   /* num stripes in use for this object */
+        __u16 lmm_layout_gen;     /* layout generation number */
         char  lmm_pool_name[LOV_MAXPOOLNAME]; /* must be 32bit aligned */
         struct lov_ost_data_v1 lmm_objects[0]; /* per-stripe data */
 };
@@ -2143,6 +2147,7 @@ enum seq_op {
  *
  * (max buffer size - lov+rpc header) / sizeof(struct lov_ost_data_v1) */
 #define LOV_MAX_STRIPE_COUNT 2000  /* ((12 * 4096 - 256) / 24) */
+#define LOV_ALL_STRIPES       0xffff /* only valid for directories */
 #define LOV_V1_INSANE_STRIPE_COUNT 65532 /* maximum stripe count bz13933 */
 
 #define LOV_MAX_UUID_BUFFER_SIZE  8192
index d371b8d..1b2176a 100644 (file)
@@ -200,6 +200,7 @@ struct lov_user_ost_data_v1 {     /* per-stripe data structure */
 } __attribute__((packed));
 
 #define lov_user_md lov_user_md_v1
+#define lmm_stripe_offset u.lum_stripe_offset
 struct lov_user_md_v1 {           /* LOV EA user data (host-endian) */
         __u32 lmm_magic;          /* magic number = LOV_USER_MAGIC_V1 */
         __u32 lmm_pattern;        /* LOV_PATTERN_RAID0, LOV_PATTERN_RAID1 */
@@ -207,7 +208,12 @@ struct lov_user_md_v1 {           /* LOV EA user data (host-endian) */
         __u64 lmm_object_seq;     /* LOV object seq */
         __u32 lmm_stripe_size;    /* size of stripe in bytes */
         __u16 lmm_stripe_count;   /* num stripes in use for this object */
-        __u16 lmm_stripe_offset;  /* starting stripe offset in lmm_objects */
+        union {
+                __u16 lum_stripe_offset;  /* starting stripe offset in
+                                           * lmm_objects, use when writing */
+                __u16 lum_layout_gen;     /* layout generation number
+                                           * used when reading */
+        } u;
         struct lov_user_ost_data_v1 lmm_objects[0]; /* per-stripe data */
 } __attribute__((packed,  __may_alias__));
 
@@ -218,7 +224,12 @@ struct lov_user_md_v3 {           /* LOV EA user data (host-endian) */
         __u64 lmm_object_seq;     /* LOV object seq */
         __u32 lmm_stripe_size;    /* size of stripe in bytes */
         __u16 lmm_stripe_count;   /* num stripes in use for this object */
-        __u16 lmm_stripe_offset;  /* starting stripe offset in lmm_objects */
+        union {
+                __u16 lum_stripe_offset;  /* starting stripe offset in
+                                           * lmm_objects, use when writing */
+                __u16 lum_layout_gen;     /* layout generation number
+                                           * used when reading */
+        } u;
         char  lmm_pool_name[LOV_MAXPOOLNAME]; /* pool name */
         struct lov_user_ost_data_v1 lmm_objects[0]; /* per-stripe data */
 } __attribute__((packed));
index 17e04e5..2e4edcb 100644 (file)
@@ -274,7 +274,12 @@ struct lustre_mount_data {
 #define OBD_INCOMPAT_IAM_DIR    0x00000040
 /** LMA attribute contains per-inode incompatible flags */
 #define OBD_INCOMPAT_LMA        0x00000080
-
+/** lmm_stripe_count has been shrunk from __u32 to __u16 and the remaining 16
+ * bits are now used to store a generation. Once we start changing the layout
+ * and bumping the generation, old versions expecting a 32-bit lmm_stripe_count
+ * will be confused by interpreting stripe_count | gen << 16 as the actual
+ * stripe count */
+#define OBD_INCOMPAT_LMM_VER    0x00000100
 
 /* Data stored per server at the head of the last_rcvd file.  In le32 order.
    This should be common to filter_internal.h, lustre_mds.h */
index f55856c..f44453a 100644 (file)
@@ -127,7 +127,7 @@ enum ma_valid {
         MA_LMV       = (1 << 4),
         MA_ACL_DEF   = (1 << 5),
         MA_LOV_DEF   = (1 << 6),
-/* (Layout lock will used #7 here) */
+        MA_LAY_GEN   = (1 << 7),
         MA_HSM       = (1 << 8),
         MA_SOM       = (1 << 9),
         MA_PFID      = (1 << 10)
@@ -170,18 +170,19 @@ struct md_attr {
         __u64                   ma_need;
         __u64                   ma_attr_flags;
         struct lu_attr          ma_attr;
+        struct lu_fid           ma_pfid;
+        struct md_hsm           ma_hsm;
         struct lov_mds_md      *ma_lmm;
-        int                     ma_lmm_size;
         struct lmv_stripe_md   *ma_lmv;
-        int                     ma_lmv_size;
         void                   *ma_acl;
-        int                     ma_acl_size;
         struct llog_cookie     *ma_cookie;
-        int                     ma_cookie_size;
         struct lustre_capa     *ma_capa;
-        struct md_hsm           ma_hsm;
         struct md_som_data     *ma_som;
-        struct lu_fid           ma_pfid;
+        int                     ma_lmm_size;
+        int                     ma_lmv_size;
+        int                     ma_acl_size;
+        int                     ma_cookie_size;
+        __u16                   ma_layout_gen;
 };
 
 /** Additional parameters for create */
@@ -327,6 +328,13 @@ struct md_dir_operations {
                           struct md_object *cobj, const struct lu_name *lname,
                           struct md_attr *ma);
 
+        /** This method is used to compare a requested layout to an existing
+         * layout (struct lov_mds_md_v1/3 vs struct lov_mds_md_v1/3) */
+        int (*mdo_lum_lmm_cmp)(const struct lu_env *env,
+                               struct md_object *cobj,
+                               const struct md_op_spec *spec,
+                               struct md_attr *ma);
+
         /** partial ops for cross-ref case */
         int (*mdo_name_insert)(const struct lu_env *env,
                                struct md_object *obj,
@@ -852,6 +860,15 @@ static inline int mdo_unlink(const struct lu_env *env,
         return c->mo_dir_ops->mdo_unlink(env, p, c, lname, ma);
 }
 
+static inline int mdo_lum_lmm_cmp(const struct lu_env *env,
+                                  struct md_object *c,
+                                  const struct md_op_spec *spec,
+                                  struct md_attr *ma)
+{
+        LASSERT(c->mo_dir_ops->mdo_lum_lmm_cmp);
+        return c->mo_dir_ops->mdo_lum_lmm_cmp(env, c, spec, ma);
+}
+
 static inline int mdo_name_insert(const struct lu_env *env,
                                   struct md_object *p,
                                   const struct lu_name *lname,
index e670dba..58fdbd7 100644 (file)
@@ -144,7 +144,8 @@ struct lov_stripe_md {
                 __u32 lw_magic;
                 __u32 lw_stripe_size;      /* size of the stripe */
                 __u32 lw_pattern;          /* striping pattern (RAID0, RAID1) */
-                unsigned lw_stripe_count;  /* number of objects being striped over */
+                __u16 lw_stripe_count;  /* number of objects being striped over */
+                __u16 lw_layout_gen;       /* generation of the layout */
                 char  lw_pool_name[LOV_MAXPOOLNAME]; /* pool name */
         } lsm_wire;
 
@@ -154,6 +155,7 @@ struct lov_stripe_md {
 #define lsm_object_id    lsm_wire.lw_object_id
 #define lsm_object_seq   lsm_wire.lw_object_seq
 #define lsm_magic        lsm_wire.lw_magic
+#define lsm_layout_gen   lsm_wire.lw_layout_gen
 #define lsm_stripe_size  lsm_wire.lw_stripe_size
 #define lsm_pattern      lsm_wire.lw_pattern
 #define lsm_stripe_count lsm_wire.lw_stripe_count
@@ -205,6 +207,57 @@ static inline int lov_stripe_md_cmp(struct lov_stripe_md *m1,
         return memcmp(&m1->lsm_wire, &m2->lsm_wire, sizeof m1->lsm_wire);
 }
 
+static inline int lov_lum_lsm_cmp(struct lov_user_md *lum,
+                                  struct lov_stripe_md  *lsm)
+{
+        if (lsm->lsm_magic != lum->lmm_magic)
+                return 1;
+        if ((lsm->lsm_stripe_count != 0) && (lum->lmm_stripe_count != 0) &&
+            (lsm->lsm_stripe_count != lum->lmm_stripe_count))
+                return 2;
+        if ((lsm->lsm_stripe_size != 0) && (lum->lmm_stripe_size != 0) &&
+            (lsm->lsm_stripe_size != lum->lmm_stripe_size))
+                return 3;
+        if ((lsm->lsm_pattern != 0) && (lum->lmm_pattern != 0) &&
+            (lsm->lsm_pattern != lum->lmm_pattern))
+                return 4;
+        if ((lsm->lsm_magic == LOV_MAGIC_V3) &&
+            (strncmp(lsm->lsm_pool_name,
+                     ((struct lov_user_md_v3 *)lum)->lmm_pool_name,
+                     LOV_MAXPOOLNAME) != 0))
+                return 5;
+        return 0;
+}
+
+static inline int lov_lum_swab_if_needed(struct lov_user_md_v3 *lumv3,
+                                         int *lmm_magic,
+                                         struct lov_user_md *lum)
+{
+        if (lum && cfs_copy_from_user(lumv3, lum,sizeof(struct lov_user_md_v1)))
+                return -EFAULT;
+
+        *lmm_magic = lumv3->lmm_magic;
+
+        if (*lmm_magic == __swab32(LOV_USER_MAGIC_V1)) {
+                lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lumv3);
+                *lmm_magic = LOV_USER_MAGIC_V1;
+        } else if (*lmm_magic == LOV_USER_MAGIC_V3) {
+                if (lum && cfs_copy_from_user(lumv3, lum, sizeof(*lumv3)))
+                        return -EFAULT;
+        } else if (*lmm_magic == __swab32(LOV_USER_MAGIC_V3)) {
+                if (lum && cfs_copy_from_user(lumv3, lum, sizeof(*lumv3)))
+                        return -EFAULT;
+                lustre_swab_lov_user_md_v3(lumv3);
+                *lmm_magic = LOV_USER_MAGIC_V3;
+        } else if (*lmm_magic != LOV_USER_MAGIC_V1) {
+                CDEBUG(D_IOCTL,
+                       "bad userland LOV MAGIC: %#08x != %#08x nor %#08x\n",
+                       *lmm_magic, LOV_USER_MAGIC_V1, LOV_USER_MAGIC_V3);
+                       return -EINVAL;
+        }
+        return 0;
+}
+
 void lov_stripe_lock(struct lov_stripe_md *md);
 void lov_stripe_unlock(struct lov_stripe_md *md);
 
@@ -1587,7 +1640,7 @@ struct lsm_operations {
         void (*lsm_stripe_by_offset)(struct lov_stripe_md *, int *, obd_off *,
                                      obd_off *);
         int (*lsm_lmm_verify) (struct lov_mds_md *lmm, int lmm_bytes,
-                               int *stripe_count);
+                               __u16 *stripe_count);
         int (*lsm_unpackmd) (struct lov_obd *lov, struct lov_stripe_md *lsm,
                              struct lov_mds_md *lmm);
 };
index 35b322f..b9904a4 100644 (file)
 #ifndef _OBD_LOV_H__
 #define _OBD_LOV_H__
 
-static inline int lov_stripe_md_size(int stripes)
+static inline int lov_stripe_md_size(__u16 stripes)
 {
         return sizeof(struct lov_stripe_md) + stripes*sizeof(struct lov_oinfo*);
 }
 
-static inline __u32 lov_mds_md_size(int stripes, __u32 lmm_magic)
+static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic)
 {
         if (lmm_magic == LOV_MAGIC_V3)
                 return sizeof(struct lov_mds_md_v3) +
index 33847b3..92e564f 100644 (file)
@@ -59,7 +59,7 @@ int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp)
         __u32 valsize = sizeof(struct lov_desc);
         int rc, easize, def_easize, cookiesize;
         struct lov_desc desc;
-        __u32 stripes;
+        __u16 stripes;
         ENTRY;
 
         rc = obd_get_info(dt_exp, sizeof(KEY_LOVDESC), KEY_LOVDESC,
index 25017a2..0c4abe9 100755 (executable)
@@ -66,7 +66,7 @@ struct lovea_unpack_args {
 };
 
 static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes,
-                                 int stripe_count)
+                                 __u16 stripe_count)
 {
 
         if (stripe_count == 0 || stripe_count > LOV_V1_INSANE_STRIPE_COUNT) {
@@ -97,13 +97,13 @@ static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes,
         return 0;
 }
 
-struct lov_stripe_md *lsm_alloc_plain(int stripe_count, int *size)
+struct lov_stripe_md *lsm_alloc_plain(__u16 stripe_count, int *size)
 {
         struct lov_stripe_md *lsm;
-        int i, oinfo_ptrs_size;
-        struct lov_oinfo *loi;
+        struct lov_oinfo     *loi;
+        int                   i, oinfo_ptrs_size;
 
-        LASSERT(stripe_count > 0);
+        LASSERT(stripe_count <= LOV_MAX_STRIPE_COUNT);
 
         oinfo_ptrs_size = sizeof(struct lov_oinfo *) * stripe_count;
         *size = sizeof(struct lov_stripe_md) + oinfo_ptrs_size;
@@ -119,7 +119,6 @@ struct lov_stripe_md *lsm_alloc_plain(int stripe_count, int *size)
                 lsm->lsm_oinfo[i] = loi;
         }
         lsm->lsm_stripe_count = stripe_count;
-        lsm->lsm_pool_name[0] = '\0';
         return lsm;
 
 err:
@@ -131,7 +130,7 @@ err:
 
 void lsm_free_plain(struct lov_stripe_md *lsm)
 {
-        int stripe_count = lsm->lsm_stripe_count;
+        __u16 stripe_count = lsm->lsm_stripe_count;
         int i;
 
         for (i = 0; i < stripe_count; i++)
@@ -152,6 +151,7 @@ static void lsm_unpackmd_common(struct lov_stripe_md *lsm,
         lsm->lsm_object_seq = le64_to_cpu(lmm->lmm_object_seq);
         lsm->lsm_stripe_size = le32_to_cpu(lmm->lmm_stripe_size);
         lsm->lsm_pattern = le32_to_cpu(lmm->lmm_pattern);
+        lsm->lsm_layout_gen = le16_to_cpu(lmm->lmm_layout_gen);
         lsm->lsm_pool_name[0] = '\0';
 }
 
@@ -201,7 +201,7 @@ static void lov_tgt_maxbytes(struct lov_tgt_desc *tgt, __u64 *stripe_maxbytes)
 }
 
 static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes,
-                             int *stripe_count)
+                             __u16 *stripe_count)
 {
         if (lmm_bytes < sizeof(*lmm)) {
                 CERROR("lov_mds_md_v1 too small: %d, need at least %d\n",
@@ -209,7 +209,7 @@ static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes,
                 return -EINVAL;
         }
 
-        *stripe_count = le32_to_cpu(lmm->lmm_stripe_count);
+        *stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
 
         if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V1)) {
                 CERROR("LOV EA V1 too small: %d, need %d\n",
@@ -268,7 +268,7 @@ const struct lsm_operations lsm_v1_ops = {
 };
 
 static int lsm_lmm_verify_v3(struct lov_mds_md *lmmv1, int lmm_bytes,
-                             int *stripe_count)
+                             __u16 *stripe_count)
 {
         struct lov_mds_md_v3 *lmm;
 
@@ -280,7 +280,7 @@ static int lsm_lmm_verify_v3(struct lov_mds_md *lmmv1, int lmm_bytes,
                 return -EINVAL;
         }
 
-        *stripe_count = le32_to_cpu(lmm->lmm_stripe_count);
+        *stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
 
         if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V3)) {
                 CERROR("LOV EA V3 too small: %d, need %d\n",
index 8d3fd4d..5b1e369 100644 (file)
@@ -264,7 +264,7 @@ void lov_fix_desc_stripe_size(__u64 *val);
 void lov_fix_desc_stripe_count(__u32 *val);
 void lov_fix_desc_pattern(__u32 *val);
 void lov_fix_desc_qos_maxage(__u32 *val);
-__u32 lov_get_stripecnt(struct lov_obd *lov, __u32 magic, __u32 stripe_count);
+__u16 lov_get_stripecnt(struct lov_obd *lov, __u32 magic, __u16 stripe_count);
 int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
                     struct obd_connect_data *data);
 int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg);
@@ -288,7 +288,7 @@ int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp,
               struct lov_user_md *lump);
 int lov_getstripe(struct obd_export *exp,
                   struct lov_stripe_md *lsm, struct lov_user_md *lump);
-int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count,
+int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count,
                     int pattern, int magic);
 void lov_free_memmd(struct lov_stripe_md **lsmp);
 
@@ -297,7 +297,7 @@ void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm);
 void lov_dump_lmm(int level, void *lmm);
 
 /* lov_ea.c */
-struct lov_stripe_md *lsm_alloc_plain(int stripe_count, int *size);
+struct lov_stripe_md *lsm_alloc_plain(__u16 stripe_count, int *size);
 void lsm_free_plain(struct lov_stripe_md *lsm);
 
 int lovea_destroy_object(struct lov_obd *lov, struct lov_stripe_md *lsm,
index a3b94ff..7022b8d 100644 (file)
@@ -65,9 +65,10 @@ static void lov_dump_lmm_common(int level, void *lmmp)
                (__u64)le64_to_cpu(lmm->lmm_object_id),
                le32_to_cpu(lmm->lmm_magic),
                le32_to_cpu(lmm->lmm_pattern));
-        CDEBUG(level,"stripe_size %u, stripe_count %u\n",
+        CDEBUG(level,"stripe_size %u, stripe_count %u, layout_gen %u\n",
                le32_to_cpu(lmm->lmm_stripe_size),
-               le32_to_cpu(lmm->lmm_stripe_count));
+               le16_to_cpu(lmm->lmm_stripe_count),
+               le16_to_cpu(lmm->lmm_layout_gen));
 }
 
 static void lov_dump_lmm_objects(int level, struct lov_ost_data *lod,
@@ -92,7 +93,7 @@ void lov_dump_lmm_v1(int level, struct lov_mds_md_v1 *lmm)
 {
         lov_dump_lmm_common(level, lmm);
         lov_dump_lmm_objects(level, lmm->lmm_objects,
-                             le32_to_cpu(lmm->lmm_stripe_count));
+                             le16_to_cpu(lmm->lmm_stripe_count));
 }
 
 void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm)
@@ -100,7 +101,7 @@ void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm)
         lov_dump_lmm_common(level, lmm);
         CDEBUG(level,"pool_name "LOV_POOLNAMEF"\n", lmm->lmm_pool_name);
         lov_dump_lmm_objects(level, lmm->lmm_objects,
-                             le32_to_cpu(lmm->lmm_stripe_count));
+                             le16_to_cpu(lmm->lmm_stripe_count));
 }
 
 void lov_dump_lmm(int level, void *lmm)
@@ -140,7 +141,7 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
         struct lov_obd *lov = &obd->u.lov;
         struct lov_mds_md_v1 *lmmv1;
         struct lov_mds_md_v3 *lmmv3;
-        int stripe_count;
+        __u16 stripe_count;
         struct lov_ost_data_v1 *lmm_objects;
         int lmm_size, lmm_magic;
         int i;
@@ -192,7 +193,7 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
                 RETURN(lmm_size);
 
         if (*lmmp && !lsm) {
-                stripe_count = le32_to_cpu((*lmmp)->lmm_stripe_count);
+                stripe_count = le16_to_cpu((*lmmp)->lmm_stripe_count);
                 lmm_size = lov_mds_md_size(stripe_count, lmm_magic);
                 OBD_FREE_LARGE(*lmmp, lmm_size);
                 *lmmp = NULL;
@@ -224,8 +225,9 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
         lmmv1->lmm_object_id = cpu_to_le64(lsm->lsm_object_id);
         lmmv1->lmm_object_seq = cpu_to_le64(lsm->lsm_object_seq);
         lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size);
-        lmmv1->lmm_stripe_count = cpu_to_le32(stripe_count);
+        lmmv1->lmm_stripe_count = cpu_to_le16(stripe_count);
         lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern);
+        lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen);
         if (lsm->lsm_magic == LOV_MAGIC_V3) {
                 strncpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name,
                         LOV_MAXPOOLNAME);
@@ -249,7 +251,7 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 }
 
 /* Find the max stripecount we should use */
-__u32 lov_get_stripecnt(struct lov_obd *lov, __u32 magic, __u32 stripe_count)
+__u16 lov_get_stripecnt(struct lov_obd *lov, __u32 magic, __u16 stripe_count)
 {
         __u32 max_stripes = LOV_MAX_STRIPE_COUNT_OLD;
 
@@ -274,7 +276,7 @@ __u32 lov_get_stripecnt(struct lov_obd *lov, __u32 magic, __u32 stripe_count)
 }
 
 
-static int lov_verify_lmm(void *lmm, int lmm_bytes, int *stripe_count)
+static int lov_verify_lmm(void *lmm, int lmm_bytes, __u16 *stripe_count)
 {
         int rc;
 
@@ -302,7 +304,7 @@ static int lov_verify_lmm(void *lmm, int lmm_bytes, int *stripe_count)
         return rc;
 }
 
-int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count,
+int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count,
                     int pattern, int magic)
 {
         int i, lsm_size;
@@ -322,6 +324,7 @@ int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count,
         (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES * stripe_count;
         (*lsmp)->lsm_pattern = pattern;
         (*lsmp)->lsm_pool_name[0] = '\0';
+        (*lsmp)->lsm_layout_gen = 0;
         (*lsmp)->lsm_oinfo[0]->loi_ost_idx = ~0;
 
         for (i = 0; i < stripe_count; i++)
@@ -349,7 +352,8 @@ int lov_unpackmd(struct obd_export *exp,  struct lov_stripe_md **lsmp,
 {
         struct obd_device *obd = class_exp2obd(exp);
         struct lov_obd *lov = &obd->u.lov;
-        int rc = 0, stripe_count, lsm_size;
+        int rc = 0, lsm_size;
+        __u16 stripe_count;
         __u32 magic;
         ENTRY;
 
@@ -405,32 +409,13 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
         struct lov_user_md_v3 *lumv3 = (struct lov_user_md_v3 *)&buffer[0];
         struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&buffer[0];
         int lmm_magic;
-        int stripe_count;
+        __u16 stripe_count;
         int rc;
         ENTRY;
 
-        if (cfs_copy_from_user(lumv3, lump, sizeof(struct lov_user_md_v1)))
-                RETURN(-EFAULT);
-
-        lmm_magic = lumv1->lmm_magic;
-
-        if (lmm_magic == __swab32(LOV_USER_MAGIC_V1)) {
-                lustre_swab_lov_user_md_v1(lumv1);
-                lmm_magic = LOV_USER_MAGIC_V1;
-        } else if (lmm_magic == LOV_USER_MAGIC_V3) {
-                if (cfs_copy_from_user(lumv3, lump, sizeof(*lumv3)))
-                        RETURN(-EFAULT);
-        } else if (lmm_magic == __swab32(LOV_USER_MAGIC_V3)) {
-                if (cfs_copy_from_user(lumv3, lump, sizeof(*lumv3)))
-                        RETURN(-EFAULT);
-                lustre_swab_lov_user_md_v3(lumv3);
-                lmm_magic = LOV_USER_MAGIC_V3;
-        } else if (lmm_magic != LOV_USER_MAGIC_V1) {
-                CDEBUG(D_IOCTL,
-                       "bad userland LOV MAGIC: %#08x != %#08x nor %#08x\n",
-                       lmm_magic, LOV_USER_MAGIC_V1, LOV_USER_MAGIC_V3);
-                       RETURN(-EINVAL);
-        }
+        rc = lov_lum_swab_if_needed(lumv3, &lmm_magic, lump);
+        if (rc)
+                RETURN(rc);
 
         /* in the rest of the tests, as *lumv1 and lumv3 have the same
          * fields, we use lumv1 to avoid code duplication */
@@ -669,7 +654,8 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm,
          * So we have to re-order the data before copy to user.
          */
         lum.lmm_stripe_count = lmmk->lmm_stripe_count;
-        ((struct lov_user_md*)lmmk)->lmm_stripe_offset = 0;
+        lum.u.lum_layout_gen = lmmk->lmm_layout_gen;
+        ((struct lov_user_md*)lmmk)->u.lum_layout_gen = lum.u.lum_layout_gen;
         ((struct lov_user_md*)lmmk)->lmm_stripe_count = lum.lmm_stripe_count;
         if (cfs_copy_to_user(lump, lmmk, lmm_size))
                 rc = -EFAULT;
index d114aa3..1602a11 100644 (file)
@@ -505,7 +505,7 @@ static int lov_check_and_create_object(struct lov_obd *lov, int ost_idx,
                                        struct lov_request *req,
                                        struct obd_trans_info *oti)
 {
-        int stripe;
+        __u16 stripe;
         int rc = -EIO;
         ENTRY;
 
@@ -1005,7 +1005,7 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set)
         LASSERT(src_oa->o_valid & OBD_MD_FLGROUP);
 
         if (set->set_oi->oi_md == NULL) {
-                __u32 stripes_def = lov_get_stripecnt(lov, LOV_MAGIC, 0);
+                __u16 stripes_def = lov_get_stripecnt(lov, LOV_MAGIC, 0);
 
                 /* If the MDS file was truncated up to some size, stripe over
                  * enough OSTs to allow the file to be created at that size.
@@ -1046,6 +1046,7 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set)
         lsm = set->set_oi->oi_md;
         lsm->lsm_object_id = src_oa->o_id;
         lsm->lsm_object_seq = src_oa->o_seq;
+        lsm->lsm_layout_gen = 0; /* actual generation set in mdd_lov_create() */
 
         if (!lsm->lsm_stripe_size)
                 lsm->lsm_stripe_size = lov->desc.ld_default_stripe_size;
index 9365542..a2693a3 100644 (file)
@@ -1561,7 +1561,6 @@ static int mdd_create_data(const struct lu_env *env, struct md_object *pobj,
         struct mdd_device *mdd = mdo2mdd(cobj);
         struct mdd_object *mdd_pobj = md2mdd_obj(pobj);
         struct mdd_object *son = md2mdd_obj(cobj);
-        struct lu_attr    *attr = &ma->ma_attr;
         struct lov_mds_md *lmm = NULL;
         int                lmm_size = 0;
         struct thandle    *handle;
@@ -1575,8 +1574,8 @@ static int mdd_create_data(const struct lu_env *env, struct md_object *pobj,
         if (!md_should_create(spec->sp_cr_flags))
                 RETURN(0);
         lmm_size = ma->ma_lmm_size;
-        rc = mdd_lov_create(env, mdd, mdd_pobj, son, &lmm, &lmm_size,
-                            spec, attr);
+
+        rc = mdd_lov_create(env, mdd, mdd_pobj, son, &lmm, &lmm_size, spec, ma);
         if (rc)
                 RETURN(rc);
 
@@ -1621,6 +1620,8 @@ stop:
         mdd_trans_stop(env, mdd, rc, handle);
 out_free:
         /* Finish mdd_lov_create() stuff. */
+        /* if no_create == 0 (not replay), we free lmm allocated by
+         * mdd_lov_create() */
         mdd_lov_create_finish(env, mdd, lmm, lmm_size, spec);
         RETURN(rc);
 }
@@ -2015,7 +2016,7 @@ static int mdd_create(const struct lu_env *env,
         if (S_ISREG(attr->la_mode)) {
                 lmm_size = ma->ma_lmm_size;
                 rc = mdd_lov_create(env, mdd, mdd_pobj, son, &lmm, &lmm_size,
-                                    spec, attr);
+                                    spec, ma);
                 if (rc)
                         GOTO(out_pending, rc);
         }
@@ -3004,6 +3005,7 @@ const struct md_dir_operations mdd_dir_ops = {
         .mdo_rename        = mdd_rename,
         .mdo_link          = mdd_link,
         .mdo_unlink        = mdd_unlink,
+        .mdo_lum_lmm_cmp   = mdd_lum_lmm_cmp,
         .mdo_name_insert   = mdd_name_insert,
         .mdo_name_remove   = mdd_name_remove,
         .mdo_rename_tgt    = mdd_rename_tgt,
index 4080998..84b6b04 100644 (file)
@@ -200,7 +200,7 @@ int mdd_lov_set_md(const struct lu_env *env, struct mdd_object *pobj,
 int mdd_lov_create(const struct lu_env *env, struct mdd_device *mdd,
                    struct mdd_object *parent, struct mdd_object *child,
                    struct lov_mds_md **lmm, int *lmm_size,
-                   const struct md_op_spec *spec, struct lu_attr *la);
+                   const struct md_op_spec *spec, struct md_attr *ma);
 int mdd_lov_objid_prepare(struct mdd_device *mdd, struct lov_mds_md *lmm);
 int mdd_declare_lov_objid_update(const struct lu_env *, struct mdd_device *,
                                  struct thandle *);
@@ -213,6 +213,8 @@ int mdd_file_lock(const struct lu_env *env, struct md_object *obj,
                   struct lustre_handle *lockh);
 int mdd_file_unlock(const struct lu_env *env, struct md_object *obj,
                     struct lov_mds_md *lmm, struct lustre_handle *lockh);
+int mdd_lum_lmm_cmp(const struct lu_env *env, struct md_object *cobj,
+                    const struct md_op_spec *spec, struct md_attr *ma);
 int mdd_get_md(const struct lu_env *env, struct mdd_object *obj,
                void *md, int *md_size, const char *name);
 int mdd_get_md_locked(const struct lu_env *env, struct mdd_object *obj,
index e9a1417..2f36e73 100644 (file)
@@ -281,8 +281,9 @@ static int mdd_lov_set_dir_md(const struct lu_env *env,
         LASSERT(S_ISDIR(mdd_object_type(obj)));
         lum = (struct lov_user_md*)buf->lb_buf;
 
-        /* if { size, offset, count } = { 0, -1, 0 } and no pool (i.e. all default
-         * values specified) then delete default striping from dir. */
+        /* if { size, offset, count } = { 0, -1, 0 } and no pool
+         * (i.e. all default values specified) then delete default
+         * striping from dir. */
         if (LOVEA_DELETE_VALUES(lum->lmm_stripe_size, lum->lmm_stripe_count,
                                 lum->lmm_stripe_offset) &&
             lum->lmm_magic != LOV_USER_MAGIC_V3) {
@@ -348,7 +349,8 @@ int mdd_lov_set_md(const struct lu_env *env, struct mdd_object *pobj,
                         if (rc > 0) {
                                 buf = mdd_buf_get(env, lmm, size);
                                 rc = mdd_xattr_set_txn(env, child, buf,
-                                               XATTR_NAME_LOV, 0, handle);
+                                                       XATTR_NAME_LOV, 0,
+                                                       handle);
                                 if (rc)
                                         CERROR("error on copy stripe info: rc "
                                                 "= %d\n", rc);
@@ -404,7 +406,7 @@ void mdd_lov_create_finish(const struct lu_env *env, struct mdd_device *mdd,
 int mdd_lov_create(const struct lu_env *env, struct mdd_device *mdd,
                    struct mdd_object *parent, struct mdd_object *child,
                    struct lov_mds_md **lmm, int *lmm_size,
-                   const struct md_op_spec *spec, struct lu_attr *la)
+                   const struct md_op_spec *spec, struct md_attr *ma)
 {
         struct obd_device     *obd = mdd2obd_dev(mdd);
         struct obd_export     *lov_exp = obd->u.mds.mds_lov_exp;
@@ -414,6 +416,7 @@ int mdd_lov_create(const struct lu_env *env, struct mdd_device *mdd,
         const void            *eadata = spec->u.sp_ea.eadata;
         __u64                  create_flags = spec->sp_cr_flags;
         struct obd_trans_info *oti = &mdd_env_info(env)->mti_oti;
+        struct lu_attr        *la = &ma->ma_attr;
         int                    rc = 0;
         ENTRY;
 
@@ -458,11 +461,13 @@ int mdd_lov_create(const struct lu_env *env, struct mdd_device *mdd,
                                            0, &lsm, (void*)eadata);
                         if (rc)
                                 GOTO(out_oti, rc);
-                } else if (parent != NULL) {
+                } else {
                         /* get lov ea from parent and set to lov */
                         struct lov_mds_md *_lmm;
                         int _lmm_size;
 
+                        LASSERT(parent != NULL);
+
                         _lmm_size = mdd_lov_mdsize(env, mdd);
                         _lmm = mdd_max_lmm_get(env, mdd);
 
@@ -491,6 +496,19 @@ int mdd_lov_create(const struct lu_env *env, struct mdd_device *mdd,
                         }
                         GOTO(out_oti, rc);
                 }
+
+                if (ma->ma_valid & MA_LAY_GEN)
+                        /* If we already have a lsm, the file is not new and we
+                         * are about to change the layout, so we have to bump
+                         * the generation. It is worth noting that old versions
+                         * will be confused by a non-zero gen, that's why
+                         * OBD_INCOMPAT_LMM_VER has been introduced */
+                        lsm->lsm_layout_gen = ma->ma_layout_gen + 1;
+                else
+                        /* Start with a null generation for backward
+                         * compatiblity with old versions */
+                        lsm->lsm_layout_gen = 0;
+
                 LASSERT_SEQ_IS_MDT(lsm->lsm_object_seq);
         } else {
                 LASSERT(eadata != NULL);
@@ -499,6 +517,10 @@ int mdd_lov_create(const struct lu_env *env, struct mdd_device *mdd,
                 if (rc)
                         GOTO(out_oti, rc);
 
+                if (ma->ma_valid & MA_LAY_GEN)
+                        lsm->lsm_layout_gen = ma->ma_layout_gen;
+                else
+                        lsm->lsm_layout_gen = 0;
         }
 
         lsm->lsm_object_id = fid_ver_oid(mdd_object_fid(child));
@@ -683,7 +705,8 @@ int mdd_declare_unlink_log(const struct lu_env *env, struct mdd_object *obj,
                            struct md_attr *ma, struct thandle *handle)
 {
         struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
-        int rc, stripe, i;
+        int rc, i;
+        __u16 stripe;
 
         LASSERT(obj);
         LASSERT(ma);
@@ -705,10 +728,9 @@ int mdd_declare_unlink_log(const struct lu_env *env, struct mdd_object *obj,
                 return -EINVAL;
         }
 
-        if ((int)le32_to_cpu(ma->ma_lmm->lmm_stripe_count) < 0)
+        stripe = le16_to_cpu(ma->ma_lmm->lmm_stripe_count);
+        if (stripe == LOV_ALL_STRIPES);
                 stripe = mdd2obd_dev(mdd)->u.mds.mds_lov_desc.ld_tgt_count;
-        else
-                stripe = le32_to_cpu(ma->ma_lmm->lmm_stripe_count);
 
         for (i = 0; i < stripe; i++) {
                 rc = mdd_declare_llog_record(env, mdd,
@@ -1037,3 +1059,37 @@ int mdd_file_unlock(const struct lu_env *env, struct md_object *obj,
 
         RETURN(rc);
 }
+
+/* file lov is in ma->ma_lmm */
+/* requested lov is in info->mti_spec.u.sp_ea.eadata */
+int mdd_lum_lmm_cmp(const struct lu_env *env, struct md_object *cobj,
+                    const struct md_op_spec *spec, struct md_attr *ma)
+{
+        struct obd_export *lov_exp =
+                mdd2obd_dev(mdo2mdd(cobj))->u.mds.mds_lov_exp;
+        struct lov_mds_md *lmm = ma->ma_lmm;
+        struct lov_user_md_v3 *lum =
+                (struct lov_user_md_v3 *)(spec->u.sp_ea.eadata);
+        struct lov_stripe_md *lsm = NULL;
+        int lmm_magic, rc;
+        ENTRY;
+
+        rc = obd_unpackmd(lov_exp, &lsm, lmm,
+                          lov_mds_md_size(lmm->lmm_stripe_count,
+                                          lmm->lmm_magic));
+        ma->ma_layout_gen = lsm->lsm_layout_gen;
+        ma->ma_valid |= MA_LAY_GEN;
+
+        rc = lov_lum_swab_if_needed(lum, &lmm_magic, NULL);
+        if (rc)
+                GOTO(out, rc);
+
+        rc = lov_lum_lsm_cmp((struct lov_user_md *)lum, lsm);
+        if (rc)
+                GOTO(out, rc);  /* keep GOTO to for traces */
+
+out:
+        /* free lsm */
+        obd_unpackmd(lov_exp, &lsm, NULL, 0);
+        return rc;
+}
index 9c85d46..ace6de2 100644 (file)
@@ -626,7 +626,8 @@ static int __mdd_lmm_get(const struct lu_env *env,
                 rc = mdd_get_default_md(mdd_obj, ma->ma_lmm);
         if (rc > 0) {
                 ma->ma_lmm_size = rc;
-                ma->ma_valid |= MA_LOV;
+                ma->ma_layout_gen = ma->ma_lmm->lmm_layout_gen;
+                ma->ma_valid |= MA_LOV | MA_LAY_GEN;
                 rc = 0;
         }
         RETURN(rc);
@@ -1485,7 +1486,7 @@ static int mdd_declare_attr_set(const struct lu_env *env,
                                 struct thandle *handle)
 {
         struct lu_buf  *buf = &mdd_env_info(env)->mti_buf;
-        int             rc, stripe, i;
+        int             rc, i;
 
         rc = mdo_declare_attr_set(env, obj, &ma->ma_attr, handle);
         if (rc)
@@ -1515,6 +1516,8 @@ static int mdd_declare_attr_set(const struct lu_env *env,
 
         /* basically the log is the same as in unlink case */
         if (lmm) {
+                __u16 stripe;
+
                 if (le32_to_cpu(lmm->lmm_magic) != LOV_MAGIC_V1 &&
                                 le32_to_cpu(lmm->lmm_magic) != LOV_MAGIC_V3) {
                         CERROR("%s: invalid LOV_MAGIC %08x on object "DFID"\n",
@@ -1524,9 +1527,14 @@ static int mdd_declare_attr_set(const struct lu_env *env,
                         return -EINVAL;
                 }
 
-                stripe = mdd2obd_dev(mdd)->u.mds.mds_lov_desc.ld_tgt_count;
-                if ((int)le32_to_cpu(lmm->lmm_stripe_count) >= 0)
-                        stripe = le32_to_cpu(lmm->lmm_stripe_count);
+                stripe = le16_to_cpu(lmm->lmm_stripe_count);
+                if (stripe == LOV_ALL_STRIPES) {
+                        struct lov_desc *ldesc;
+
+                        ldesc = &mdd->mdd_obd_dev->u.mds.mds_lov_desc;
+                        LASSERT(ldesc != NULL);
+                        stripe = ldesc->ld_tgt_count;
+                }
 
                 for (i = 0; i < stripe; i++) {
                         rc = mdd_declare_llog_record(env, mdd,
index df26eda..83174ca 100644 (file)
@@ -234,7 +234,7 @@ static int mds_lov_objinit(struct mds_obd *mds, __u32 index)
 int mds_lov_prepare_objids(struct obd_device *obd, struct lov_mds_md *lmm)
 {
         struct lov_ost_data_v1 *data;
-        __u32 count;
+        __u16 count;
         int rc = 0;
         __u32 j;
 
@@ -244,11 +244,11 @@ int mds_lov_prepare_objids(struct obd_device *obd, struct lov_mds_md *lmm)
 
         switch (le32_to_cpu(lmm->lmm_magic)) {
                 case LOV_MAGIC_V1:
-                        count = le32_to_cpu(((struct lov_mds_md_v1*)lmm)->lmm_stripe_count);
+                        count = le16_to_cpu(((struct lov_mds_md_v1*)lmm)->lmm_stripe_count);
                         data = &(((struct lov_mds_md_v1*)lmm)->lmm_objects[0]);
                         break;
                 case LOV_MAGIC_V3:
-                        count = le32_to_cpu(((struct lov_mds_md_v3*)lmm)->lmm_stripe_count);
+                        count = le16_to_cpu(((struct lov_mds_md_v3*)lmm)->lmm_stripe_count);
                         data = &(((struct lov_mds_md_v3*)lmm)->lmm_objects[0]);
                         break;
                 default:
@@ -277,7 +277,7 @@ EXPORT_SYMBOL(mds_lov_prepare_objids);
  * after use
  */
 static int mds_log_lost_precreated(struct obd_device *obd,
-                                   struct lov_stripe_md **lsmp, int *stripes,
+                                   struct lov_stripe_md **lsmp, __u16 *stripes,
                                    obd_id id, obd_count count, int idx)
 {
         struct lov_stripe_md *lsm = *lsmp;
@@ -308,7 +308,7 @@ void mds_lov_update_objids(struct obd_device *obd, struct lov_mds_md *lmm)
         int j;
         struct lov_ost_data_v1 *obj;
         struct lov_stripe_md *lsm = NULL;
-        int stripes = 0;
+        __u16 stripes = 0;
         int count;
         ENTRY;
 
@@ -318,11 +318,11 @@ void mds_lov_update_objids(struct obd_device *obd, struct lov_mds_md *lmm)
 
         switch (le32_to_cpu(lmm->lmm_magic)) {
                 case LOV_MAGIC_V1:
-                        count = le32_to_cpu(((struct lov_mds_md_v1*)lmm)->lmm_stripe_count);
+                        count = le16_to_cpu(((struct lov_mds_md_v1*)lmm)->lmm_stripe_count);
                         obj = ((struct lov_mds_md_v1*)lmm)->lmm_objects;
                         break;
                 case LOV_MAGIC_V3:
-                        count = le32_to_cpu(((struct lov_mds_md_v3*)lmm)->lmm_stripe_count);
+                        count = le16_to_cpu(((struct lov_mds_md_v3*)lmm)->lmm_stripe_count);
                         obj = ((struct lov_mds_md_v3*)lmm)->lmm_objects;
                         break;
                 default:
index 956a04b..37dd329 100644 (file)
@@ -469,6 +469,32 @@ static inline int mdt_body_has_lov(const struct lu_attr *la,
                 (S_ISDIR(la->la_mode) && (body->valid & OBD_MD_FLDIREA )) );
 }
 
+void mdt_client_compatibility(struct mdt_thread_info *info)
+{
+        struct mdt_body       *body;
+        struct ptlrpc_request *req = mdt_info_req(info);
+        struct obd_export     *exp = req->rq_export;
+        struct md_attr        *ma = &info->mti_attr;
+        struct lu_attr        *la = &ma->ma_attr;
+        ENTRY;
+
+        if (exp->exp_connect_flags & OBD_CONNECT_LAYOUTLOCK)
+                /* the client can deal with 16-bit lmm_stripe_count */
+                RETURN_EXIT;
+
+        body = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
+
+        if (!mdt_body_has_lov(la, body))
+                RETURN_EXIT;
+
+        /* now we have a reply with a lov for a client not compatible with the
+         * layout lock so we have to clean the layout generation number */
+        if (S_ISREG(la->la_mode))
+                ma->ma_lmm->lmm_layout_gen = 0;
+        EXIT;
+}
+
+
 static int mdt_getattr_internal(struct mdt_thread_info *info,
                                 struct mdt_object *o, int ma_need)
 {
@@ -740,6 +766,7 @@ out_shrink:
         if (rc == 0)
                 mdt_counter_incr(req->rq_export, LPROC_MDT_GETATTR);
 
+        mdt_client_compatibility(info);
         mdt_shrink_reply(info);
         return rc;
 }
@@ -1108,6 +1135,7 @@ static int mdt_getattr_name(struct mdt_thread_info *info)
         mdt_exit_ucred(info);
         EXIT;
 out_shrink:
+        mdt_client_compatibility(info);
         mdt_shrink_reply(info);
         return rc;
 }
@@ -1562,6 +1590,7 @@ static int mdt_reint_internal(struct mdt_thread_info *info,
 out_ucred:
         mdt_exit_ucred(info);
 out_shrink:
+        mdt_client_compatibility(info);
         mdt_shrink_reply(info);
         return rc;
 }
@@ -3325,6 +3354,7 @@ static int mdt_intent_getattr(enum mdt_it_code opcode,
 out_ucred:
         mdt_exit_ucred(info);
 out_shrink:
+        mdt_client_compatibility(info);
         mdt_shrink_reply(info);
         return rc;
 }
index f4a1a31..acb7c78 100644 (file)
@@ -177,7 +177,8 @@ struct mdt_device {
 #define MDT_SERVICE_WATCHDOG_FACTOR     (2)
 #define MDT_ROCOMPAT_SUPP       (OBD_ROCOMPAT_LOVOBJID)
 #define MDT_INCOMPAT_SUPP       (OBD_INCOMPAT_MDT | OBD_INCOMPAT_COMMON_LR | \
-                                 OBD_INCOMPAT_FID | OBD_INCOMPAT_IAM_DIR)
+                                 OBD_INCOMPAT_FID | OBD_INCOMPAT_IAM_DIR | \
+                                 OBD_INCOMPAT_LMM_VER)
 #define MDT_COS_DEFAULT         (0)
 
 struct mdt_object {
@@ -522,6 +523,8 @@ void mdt_object_unlock_put(struct mdt_thread_info *,
                            struct mdt_lock_handle *,
                            int decref);
 
+void mdt_client_compatibility(struct mdt_thread_info *info);
+
 int mdt_close_unpack(struct mdt_thread_info *info);
 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op);
 int mdt_reint_rec(struct mdt_thread_info *, struct mdt_lock_handle *);
index 0dea2bb..c8da922 100644 (file)
@@ -528,23 +528,24 @@ int mdt_init_ucred_reint(struct mdt_thread_info *info)
 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
 {
         const struct lov_ost_data_v1 *lod;
-        int i;
-        __s16 stripe_count =
-                le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
+        int                           i;
+        __u16                         count;
+
+        count = le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
 
         CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
                le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
                le32_to_cpu(lmm->lmm_pattern));
         CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
-               le32_to_cpu(lmm->lmm_stripe_size),
-               le32_to_cpu(lmm->lmm_stripe_count));
-        LASSERT(stripe_count <= (__s16)LOV_MAX_STRIPE_COUNT);
-        for (i = 0, lod = lmm->lmm_objects; i < stripe_count; i++, lod++) {
+               le32_to_cpu(lmm->lmm_stripe_size), count);
+        if (count == LOV_ALL_STRIPES)
+                return;
+        LASSERT(count <= LOV_MAX_STRIPE_COUNT);
+        for (i = 0, lod = lmm->lmm_objects; i < count; i++, lod++)
                 CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
                        i, le32_to_cpu(lod->l_ost_idx),
                        le64_to_cpu(lod->l_object_seq),
                        le64_to_cpu(lod->l_object_id));
-        }
 }
 
 void mdt_shrink_reply(struct mdt_thread_info *info)
index 0292633..90b26b2 100644 (file)
@@ -1579,6 +1579,7 @@ int mdt_close(struct mdt_thread_info *info)
                              info->mti_mdt->mdt_max_cookiesize);
         rc = req_capsule_server_pack(info->mti_pill);
         if (mdt_check_resent(info, mdt_reconstruct_generic, NULL)) {
+                mdt_client_compatibility(info);
                 if (rc == 0)
                         mdt_shrink_reply(info);
                 RETURN(lustre_msg_get_status(req->rq_repmsg));
@@ -1629,8 +1630,10 @@ int mdt_close(struct mdt_thread_info *info)
                 mdt_empty_transno(info);
                 mdt_object_put(info->mti_env, o);
         }
-        if (repbody != NULL)
+        if (repbody != NULL) {
+                mdt_client_compatibility(info);
                 mdt_shrink_reply(info);
+        }
 
         if (OBD_FAIL_CHECK(OBD_FAIL_MDS_CLOSE_PACK))
                 RETURN(err_serious(-ENOMEM));
index ec2e5d8..3a11435 100644 (file)
@@ -597,6 +597,7 @@ out:
         if (rc == 0)
                 mdt_counter_incr(req->rq_export, LPROC_MDT_SETATTR);
 
+        mdt_client_compatibility(info);
         mdt_shrink_reply(info);
         return rc;
 }
index b321f94..15c97f1 100644 (file)
@@ -65,10 +65,11 @@ EXPORT_SYMBOL(dump_lniobuf);
 void dump_lsm(int level, struct lov_stripe_md *lsm)
 {
         CDEBUG(level, "lsm %p, objid "LPX64", maxbytes "LPX64", magic 0x%08X, "
-               "stripe_size %u, stripe_count %u pool "LOV_POOLNAMEF"\n", lsm,
+               "stripe_size %u, stripe_count %u, "
+               "layout_gen %u, pool ["LOV_POOLNAMEF"]\n", lsm,
                lsm->lsm_object_id, lsm->lsm_maxbytes, lsm->lsm_magic,
                lsm->lsm_stripe_size, lsm->lsm_stripe_count,
-               lsm->lsm_pool_name);
+               lsm->lsm_layout_gen, lsm->lsm_pool_name);
 }
 
 #define LPDS sizeof(__u64)
index 562e95f..be37b20 100644 (file)
@@ -1944,7 +1944,8 @@ static void print_lum (struct lov_user_md *lum)
         CDEBUG(D_OTHER, "\tlmm_object_gr: "LPU64"\n", lum->lmm_object_seq);
         CDEBUG(D_OTHER, "\tlmm_stripe_size: %#x\n", lum->lmm_stripe_size);
         CDEBUG(D_OTHER, "\tlmm_stripe_count: %#x\n", lum->lmm_stripe_count);
-        CDEBUG(D_OTHER, "\tlmm_stripe_offset: %#x\n", lum->lmm_stripe_offset);
+        CDEBUG(D_OTHER, "\tlmm_stripe_offset/lmm_layout_gen: %#x\n",
+               lum->u.lum_stripe_offset);
 }
 
 static void lustre_swab_lov_user_md_common(struct lov_user_md_v1 *lum)
@@ -1956,7 +1957,7 @@ static void lustre_swab_lov_user_md_common(struct lov_user_md_v1 *lum)
         __swab64s(&lum->lmm_object_seq);
         __swab32s(&lum->lmm_stripe_size);
         __swab16s(&lum->lmm_stripe_count);
-        __swab16s(&lum->lmm_stripe_offset);
+        __swab16s(&lum->u.lum_stripe_offset);
         print_lum(lum);
         EXIT;
 }
@@ -1987,7 +1988,8 @@ void lustre_swab_lov_mds_md(struct lov_mds_md *lmm)
         __swab64s(&lmm->lmm_object_id);
         __swab64s(&lmm->lmm_object_seq);
         __swab32s(&lmm->lmm_stripe_size);
-        __swab32s(&lmm->lmm_stripe_count);
+        __swab16s(&lmm->lmm_stripe_count);
+        __swab16s(&lmm->lmm_layout_gen);
         EXIT;
 }
 
index 002e61a..ac6c9d8 100644 (file)
@@ -68,8 +68,8 @@ void lustre_assert_wire_constants(void)
 {
         /* Wire protocol assertions generated by 'wirecheck'
          * (make -C lustre/utils newwiretest)
-         * running on Linux RHEL5 2.6.18-238.9.1 #1 SMP i686 i386 GNU/Linux
-         * with gcc version 4.1.1 20070105 (Red Hat 4.1.1-52) */
+         * running on Linux centos5 2.6.18-238.9.1.el5-head #2 SMP Wed Jun 29 18:35:58 CEST 2011 x86_
+         * with gcc version 4.1.2 20080704 (Red Hat 4.1.2-46) */
 
 
         /* Constants... */
@@ -383,6 +383,12 @@ void lustre_assert_wire_constants(void)
                  (long long)SEC_CTX_FINI);
         LASSERTF(SEC_LAST_OPC == 804, "found %lld\n",
                  (long long)SEC_LAST_OPC);
+        LASSERTF(LDF_EMPTY == 1, " found %lld\n",
+                 (long long)LDF_EMPTY);
+        LASSERTF(LDF_COLLIDE == 2, " found %lld\n",
+                 (long long)LDF_COLLIDE);
+        LASSERTF(LU_PAGE_SIZE == 4096, " found %lld\n",
+                 (long long)LU_PAGE_SIZE);
         /* Sizes and Offsets */
 
         /* Checks for struct obd_uuid */
@@ -1090,9 +1096,9 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)offsetof(struct obdo, o_gid_h));
         LASSERTF((int)sizeof(((struct obdo *)0)->o_gid_h) == 4, "found %lld\n",
                  (long long)(int)sizeof(((struct obdo *)0)->o_gid_h));
-        LASSERTF((int)offsetof(struct obdo, o_padding_3) == 176, "found %lld\n",
+        LASSERTF((int)offsetof(struct obdo, o_padding_3) == 176, " found %lld\n",
                  (long long)(int)offsetof(struct obdo, o_padding_3));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_padding_3) == 8, "found %lld\n",
+        LASSERTF((int)sizeof(((struct obdo *)0)->o_padding_3) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct obdo *)0)->o_padding_3));
         LASSERTF((int)offsetof(struct obdo, o_padding_4) == 184, "found %lld\n",
                  (long long)(int)offsetof(struct obdo, o_padding_4));
@@ -1267,8 +1273,12 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_size));
         LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_stripe_count) == 28, "found %lld\n",
                  (long long)(int)offsetof(struct lov_mds_md_v1, lmm_stripe_count));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count) == 4, "found %lld\n",
+        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count) == 2, " found %lld\n",
                  (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count));
+        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_layout_gen) == 30, "found %lld\n",
+                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_layout_gen));
+        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_layout_gen) == 2, " found %lld\n",
+                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_layout_gen));
         LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_objects[0]) == 32, "found %lld\n",
                  (long long)(int)offsetof(struct lov_mds_md_v1, lmm_objects[0]));
         LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects[0]) == 24, "found %lld\n",
@@ -1300,8 +1310,12 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_stripe_size));
         LASSERTF((int)offsetof(struct lov_mds_md_v3, lmm_stripe_count) == 28, "found %lld\n",
                  (long long)(int)offsetof(struct lov_mds_md_v3, lmm_stripe_count));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_stripe_count) == 4, "found %lld\n",
+        LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_stripe_count) == 2, " found %lld\n",
                  (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_stripe_count));
+        LASSERTF((int)offsetof(struct lov_mds_md_v3, lmm_layout_gen) == 30, "found %lld\n",
+                 (long long)(int)offsetof(struct lov_mds_md_v3, lmm_layout_gen));
+        LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_layout_gen) == 2, " found %lld\n",
+                 (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_layout_gen));
         CLASSERT(LOV_MAXPOOLNAME == 16);
         LASSERTF((int)offsetof(struct lov_mds_md_v3, lmm_pool_name[16]) == 48, "found %lld\n",
                  (long long)(int)offsetof(struct lov_mds_md_v3, lmm_pool_name[16]));
index ffa3e79..d426214 100644 (file)
@@ -1347,7 +1347,7 @@ check_seq_oid()
         [ "$FSTYPE" != "ldiskfs" ] && skip "can not check trusted.fid FSTYPE=$FSTYPE" && return 0
 
         # check the trusted.fid attribute of the OST objects of the file
-        for (( i=0, j=19; i < ${lmm[8]}; i++, j+=4 )); do
+        for (( i=0, j=21; i < ${lmm[8]}; i++, j+=4 )); do
                 local obdidx=${lmm[$j]}
                 local devnum=$((obdidx + 1))
                 local objid=${lmm[$((j+1))]}
index 683556d..70e3b0f 100644 (file)
@@ -797,6 +797,7 @@ static int lfs_getstripe(int argc, char **argv)
         struct option long_opts[] = {
                 {"count", 0, 0, 'c'},
                 {"directory", 0, 0, 'd'},
+                {"generation", 0, 0, 'g'},
                 {"index", 0, 0, 'i'},
                 {"mdt", 0, 0, 'M'},
                 {"offset", 0, 0, 'o'},
@@ -814,7 +815,7 @@ static int lfs_getstripe(int argc, char **argv)
 
         param.maxdepth = 1;
         optind = 0;
-        while ((c = getopt_long(argc, argv, "cdhiMoO:pqrRsv",
+        while ((c = getopt_long(argc, argv, "cdghiMoO:pqrRsv",
                                 long_opts, NULL)) != -1) {
                 switch (c) {
                 case 'O':
@@ -863,6 +864,12 @@ static int lfs_getstripe(int argc, char **argv)
                                 param.maxdepth = 0;
                         }
                         break;
+                case 'g':
+                        if (!(param.verbose & VERBOSE_DETAIL)) {
+                                param.verbose |= VERBOSE_GENERATION;
+                                param.maxdepth = 0;
+                        }
+                        break;
                 case 'M':
                         param.get_mdt_index = 1;
                         break;
index 88a0cd2..386bbd6 100644 (file)
@@ -1698,6 +1698,14 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path,
                              lum->lmm_pattern, nl);
         }
 
+        if ((verbose & VERBOSE_GENERATION) && !is_dir) {
+                if (verbose & ~VERBOSE_GENERATION)
+                        llapi_printf(LLAPI_MSG_NORMAL, "%slayout_gen:     ",
+                                     prefix);
+                llapi_printf(LLAPI_MSG_NORMAL, "%u%c",
+                             (int)lum->u.lum_layout_gen, nl);
+        }
+
         if (verbose & VERBOSE_OFFSET) {
                 if (verbose & ~VERBOSE_OFFSET)
                         llapi_printf(LLAPI_MSG_NORMAL, "%sstripe_offset:  ",
@@ -1926,7 +1934,7 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds)
         /* Check if file is accepted. */
         if (param->atime) {
                 ret = find_value_cmp(st->st_atime, param->atime,
-                                     param->asign, param->exclude_atime, 
+                                     param->asign, param->exclude_atime,
                                      24 * 60 * 60, mds);
                 if (ret < 0)
                         return ret;
@@ -1935,7 +1943,7 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds)
 
         if (param->mtime) {
                 ret = find_value_cmp(st->st_mtime, param->mtime,
-                                     param->msign, param->exclude_mtime, 
+                                     param->msign, param->exclude_mtime,
                                      24 * 60 * 60, mds);
                 if (ret < 0)
                         return ret;
index 21dc04f..7d10667 100644 (file)
@@ -65,8 +65,8 @@ void lustre_assert_wire_constants(void)
 {
         /* Wire protocol assertions generated by 'wirecheck'
          * (make -C lustre/utils newwiretest)
-         * running on Linux RHEL5 2.6.18-238.9.1 #1 SMP i686 i386 GNU/Linux
-         * with gcc version 4.1.1 20070105 (Red Hat 4.1.1-52) */
+         * running on Linux centos5 2.6.18-238.9.1.el5-head #2 SMP Wed Jun 29 18:35:58 CEST 2011 x86_
+         * with gcc version 4.1.2 20080704 (Red Hat 4.1.2-46) */
 
 
         /* Constants... */
@@ -380,6 +380,13 @@ void lustre_assert_wire_constants(void)
                  (long long)SEC_CTX_FINI);
         LASSERTF(SEC_LAST_OPC == 804, "found %lld\n",
                  (long long)SEC_LAST_OPC);
+        LASSERTF(LDF_EMPTY == 1, " found %lld\n",
+                 (long long)LDF_EMPTY);
+        LASSERTF(LDF_COLLIDE == 2, " found %lld\n",
+                 (long long)LDF_COLLIDE);
+        LASSERTF(LU_PAGE_SIZE == 4096, " found %lld\n",
+                 (long long)LU_PAGE_SIZE);
+
         /* Sizes and Offsets */
 
         /* Checks for struct obd_uuid */
@@ -1087,9 +1094,9 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)offsetof(struct obdo, o_gid_h));
         LASSERTF((int)sizeof(((struct obdo *)0)->o_gid_h) == 4, "found %lld\n",
                  (long long)(int)sizeof(((struct obdo *)0)->o_gid_h));
-        LASSERTF((int)offsetof(struct obdo, o_padding_3) == 176, "found %lld\n",
+        LASSERTF((int)offsetof(struct obdo, o_padding_3) == 176, " found %lld\n",
                  (long long)(int)offsetof(struct obdo, o_padding_3));
-        LASSERTF((int)sizeof(((struct obdo *)0)->o_padding_3) == 8, "found %lld\n",
+        LASSERTF((int)sizeof(((struct obdo *)0)->o_padding_3) == 8, " found %lld\n",
                  (long long)(int)sizeof(((struct obdo *)0)->o_padding_3));
         LASSERTF((int)offsetof(struct obdo, o_padding_4) == 184, "found %lld\n",
                  (long long)(int)offsetof(struct obdo, o_padding_4));
@@ -1264,8 +1271,12 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_size));
         LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_stripe_count) == 28, "found %lld\n",
                  (long long)(int)offsetof(struct lov_mds_md_v1, lmm_stripe_count));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count) == 4, "found %lld\n",
+        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count) == 2, " found %lld\n",
                  (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_stripe_count));
+        LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_layout_gen) == 30, "found %lld\n",
+                 (long long)(int)offsetof(struct lov_mds_md_v1, lmm_layout_gen));
+        LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_layout_gen) == 2, " found %lld\n",
+                 (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_layout_gen));
         LASSERTF((int)offsetof(struct lov_mds_md_v1, lmm_objects[0]) == 32, "found %lld\n",
                  (long long)(int)offsetof(struct lov_mds_md_v1, lmm_objects[0]));
         LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects[0]) == 24, "found %lld\n",
@@ -1297,8 +1308,12 @@ void lustre_assert_wire_constants(void)
                  (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_stripe_size));
         LASSERTF((int)offsetof(struct lov_mds_md_v3, lmm_stripe_count) == 28, "found %lld\n",
                  (long long)(int)offsetof(struct lov_mds_md_v3, lmm_stripe_count));
-        LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_stripe_count) == 4, "found %lld\n",
+        LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_stripe_count) == 2, " found %lld\n",
                  (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_stripe_count));
+        LASSERTF((int)offsetof(struct lov_mds_md_v3, lmm_layout_gen) == 30, "found %lld\n",
+                 (long long)(int)offsetof(struct lov_mds_md_v3, lmm_layout_gen));
+        LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_layout_gen) == 2, " found %lld\n",
+                 (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_layout_gen));
         CLASSERT(LOV_MAXPOOLNAME == 16);
         LASSERTF((int)offsetof(struct lov_mds_md_v3, lmm_pool_name[16]) == 48, "found %lld\n",
                  (long long)(int)offsetof(struct lov_mds_md_v3, lmm_pool_name[16]));
@@ -3851,4 +3866,3 @@ void lustre_assert_wire_constants(void)
         LASSERTF((int)sizeof(((struct hsm_user_state *)0)->hus_in_progress_location) == 16, "found %lld\n",
                  (long long)(int)sizeof(((struct hsm_user_state *)0)->hus_in_progress_location));
 }
-