Whamcloud - gitweb
LU-11691 lov: Limit layout size to max ea size 71/34171/4
authorPatrick Farrell <pfarrell@whamcloud.com>
Fri, 29 Mar 2019 19:00:53 +0000 (15:00 -0400)
committerOleg Drokin <green@whamcloud.com>
Tue, 30 Apr 2019 03:36:30 +0000 (03:36 +0000)
The layout code does not currently prevent the creation of
layouts which (once instantiated) will exceed the maximum
xattr size.

This patch modifies the code which calculates the maximum
allowed stripe count for a component to also evaluate the
full size of new layouts and report a count of zero if the
new layout is too large.  The server will then return
 -E2BIG to the client asking for such a layout.

Unfortunately, it's not practical to test this without
overstriping.  LU-9846 adds tests for this.

Signed-off-by: Patrick Farrell <pfarrell@whamcloud.com>
Change-Id: I2ead7702780b2600cf09485e06393ee9bcfb4a1e
Reviewed-on: https://review.whamcloud.com/34171
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Jian Yu <yujian@whamcloud.com>
Tested-by: Jenkins
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/lod/lod_lov.c
lustre/lod/lod_qos.c

index 7434374..a990505 100644 (file)
@@ -857,6 +857,11 @@ static int lod_gen_component_ea(const struct lu_env *env,
                objs = &v3->lmm_objects[0];
        }
        stripe_count = lod_comp_entry_stripe_count(lo, lod_comp, is_dir);
+       if (stripe_count == 0 && !is_dir &&
+           !(lod_comp->llc_pattern & LOV_PATTERN_F_RELEASED) &&
+           !(lod_comp->llc_pattern & LOV_PATTERN_MDT))
+               RETURN(-E2BIG);
+
        if (!is_dir && lo->ldo_is_composite)
                lod_comp_shrink_stripe_count(lod_comp, &stripe_count);
 
@@ -1330,6 +1335,10 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo,
                        if (objs[0].l_ost_idx != (__u32)-1UL) {
                                stripe_count = lod_comp_entry_stripe_count(
                                                        lo, lod_comp, false);
+                               if (stripe_count == 0 &&
+                                   !(lod_comp->llc_pattern & LOV_PATTERN_F_RELEASED) &&
+                                   !(lod_comp->llc_pattern & LOV_PATTERN_MDT))
+                                       GOTO(out, rc = -E2BIG);
                                /**
                                 * load the user specified ost list, when this
                                 * component is instantiated later, it will be
index f840150..3749b38 100644 (file)
@@ -1732,12 +1732,15 @@ out_nolock:
 }
 
 /**
- * Find largest stripe count the caller can use.
+ * Check stripe count the caller can use.
  *
+ * For new layouts (no initialized components), check the total size of the
+ * layout against the maximum EA size from the backing file system.  This
+ * stops us from creating a layout which will be too large once initialized.
+ *
+ * For existing layouts (with initialized components):
  * Find the maximal possible stripe count not greater than \a stripe_count.
- * Sometimes suggested stripecount can't be reached for a number of reasons:
- * lack of enough active OSTs or the backend does not support EAs that large.
- * If the passed one is 0, then the filesystem's default one is used.
+ * If the provided stripe count is 0, then the filesystem's default is used.
  *
  * \param[in] lod      LOD device
  * \param[in] lo       The lod_object
@@ -1749,6 +1752,10 @@ __u16 lod_get_stripe_count(struct lod_device *lod, struct lod_object *lo,
                           __u16 stripe_count)
 {
        __u32 max_stripes = LOV_MAX_STRIPE_COUNT_OLD;
+       /* max stripe count is based on OSD ea size */
+       unsigned int easize = lod->lod_osd_max_easize;
+       int i;
+
 
        if (!stripe_count)
                stripe_count = lod->lod_desc.ld_default_stripe_count;
@@ -1757,33 +1764,38 @@ __u16 lod_get_stripe_count(struct lod_device *lod, struct lod_object *lo,
        if (!stripe_count)
                stripe_count = 1;
 
-       /* stripe count is based on whether OSD can handle larger EA sizes */
-       if (lod->lod_osd_max_easize > 0) {
-               unsigned int easize = lod->lod_osd_max_easize;
-               int i;
-
-               if (lo->ldo_is_composite) {
-                       struct lod_layout_component *lod_comp;
-                       unsigned int header_sz = sizeof(struct lov_comp_md_v1);
-
-                       header_sz += sizeof(struct lov_comp_md_entry_v1) *
-                                       lo->ldo_comp_cnt;
-                       for (i = 0; i < lo->ldo_comp_cnt; i++) {
-                               lod_comp = &lo->ldo_comp_entries[i];
-                               if (lod_comp->llc_flags & LCME_FL_INIT)
-                                       header_sz += lov_mds_md_size(
-                                               lod_comp->llc_stripe_count,
-                                               LOV_MAGIC_V3);
-                       }
-                       if (easize > header_sz)
-                               easize -= header_sz;
-                       else
-                               easize = 0;
+       if (lo->ldo_is_composite) {
+               struct lod_layout_component *lod_comp;
+               unsigned int header_sz = sizeof(struct lov_comp_md_v1);
+               unsigned int init_comp_sz = 0;
+               unsigned int total_comp_sz = 0;
+               unsigned int comp_sz;
+
+               header_sz += sizeof(struct lov_comp_md_entry_v1) *
+                               lo->ldo_comp_cnt;
+
+               for (i = 0; i < lo->ldo_comp_cnt; i++) {
+                       lod_comp = &lo->ldo_comp_entries[i];
+                       comp_sz = lov_mds_md_size(lod_comp->llc_stripe_count,
+                                                 LOV_MAGIC_V3);
+                       total_comp_sz += comp_sz;
+                       if (lod_comp->llc_flags & LCME_FL_INIT)
+                               init_comp_sz += comp_sz;
                }
 
-               max_stripes = lov_mds_md_max_stripe_count(easize, LOV_MAGIC_V3);
+               if (init_comp_sz > 0)
+                       total_comp_sz = init_comp_sz;
+
+               header_sz += total_comp_sz;
+
+               if (easize > header_sz)
+                       easize -= header_sz;
+               else
+                       easize = 0;
        }
 
+       max_stripes = lov_mds_md_max_stripe_count(easize, LOV_MAGIC_V3);
+
        return (stripe_count < max_stripes) ? stripe_count : max_stripes;
 }