Whamcloud - gitweb
LU-10808 lod: remove DoM component if DoM is disabled 82/32482/5
authorMikhail Pershin <mike.pershin@intel.com>
Mon, 21 May 2018 18:24:05 +0000 (21:24 +0300)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 7 Jun 2018 20:08:49 +0000 (20:08 +0000)
If file is created with DoM component but server disables
DoM file creation then remove DoM entry from file layout
and keep other components.
If layout has only DoM entry then just return error.

Signed-off-by: Mikhail Pershin <mike.pershin@intel.com>
Change-Id: Ibafd0269d76dc5de4599efca064930607dc556eb
Reviewed-on: https://review.whamcloud.com/32482
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/lod/lod_lov.c
lustre/tests/sanity.sh

index 092389f..cd96cff 100644 (file)
@@ -1644,30 +1644,94 @@ out:
        RETURN(rc);
 }
 
+static inline
+struct lov_comp_md_entry_v1 *comp_entry_v1(struct lov_comp_md_v1 *comp, int i)
+{
+       LASSERTF((le32_to_cpu(comp->lcm_magic) & ~LOV_MAGIC_DEFINED) ==
+                LOV_USER_MAGIC_COMP_V1, "Wrong magic %x\n",
+                le32_to_cpu(comp->lcm_magic));
+       LASSERTF(i >= 0 && i < le16_to_cpu(comp->lcm_entry_count),
+                "bad index %d, max = %d\n",
+                i, le16_to_cpu(comp->lcm_entry_count));
+
+       return &comp->lcm_entries[i];
+}
+
+#define for_each_comp_entry_v1(comp, entry) \
+       for (entry = comp_entry_v1(comp, 0); \
+            entry <= comp_entry_v1(comp, \
+                                  le16_to_cpu(comp->lcm_entry_count) - 1); \
+            entry++)
+
+int lod_erase_dom_stripe(struct lov_comp_md_v1 *comp_v1)
+{
+       struct lov_comp_md_entry_v1 *ent, *dom_ent;
+       __u16 entries;
+       __u32 dom_off, dom_size, comp_size;
+       void *blob_src, *blob_dst;
+       unsigned int blob_size, blob_shift;
+
+       entries = le16_to_cpu(comp_v1->lcm_entry_count) - 1;
+       /* if file has only DoM stripe return just error */
+       if (entries == 0)
+               return -EFBIG;
+
+       comp_size = le32_to_cpu(comp_v1->lcm_size);
+       dom_ent = &comp_v1->lcm_entries[0];
+       dom_off = le32_to_cpu(dom_ent->lcme_offset);
+       dom_size = le32_to_cpu(dom_ent->lcme_size);
+
+       /* shift entries array first */
+       comp_v1->lcm_entry_count = cpu_to_le16(entries);
+       memmove(dom_ent, dom_ent + 1,
+               entries * sizeof(struct lov_comp_md_entry_v1));
+
+       /* now move blob of layouts */
+       blob_dst = (void *)comp_v1 + dom_off - sizeof(*dom_ent);
+       blob_src = (void *)comp_v1 + dom_off + dom_size;
+       blob_size = (unsigned long)((void *)comp_v1 + comp_size - blob_src);
+       blob_shift = sizeof(*dom_ent) + dom_size;
+
+       memmove(blob_dst, blob_src, blob_size);
+
+       for_each_comp_entry_v1(comp_v1, ent) {
+               __u32 off;
+
+               off = le32_to_cpu(ent->lcme_offset);
+               ent->lcme_offset = cpu_to_le32(off - blob_shift);
+       }
+
+       comp_v1->lcm_size = cpu_to_le32(comp_size - blob_shift);
+
+       /* notify a caller to re-check entry */
+       return -ERESTART;
+}
+
 int lod_fix_dom_stripe(struct lod_device *d, struct lov_comp_md_v1 *comp_v1)
 {
-       struct lov_comp_md_entry_v1 *ent;
+       struct lov_comp_md_entry_v1 *ent, *dom_ent;
        struct lu_extent *dom_ext, *ext;
        struct lov_user_md_v1 *lum;
        __u32 stripe_size;
        __u16 mid, dom_mid;
-       int i;
+       int rc = 0;
 
-       ent = &comp_v1->lcm_entries[0];
-       dom_ext = &ent->lcme_extent;
-       dom_mid = mirror_id_of(le32_to_cpu(ent->lcme_id));
+       dom_ent = &comp_v1->lcm_entries[0];
+       dom_ext = &dom_ent->lcme_extent;
+       dom_mid = mirror_id_of(le32_to_cpu(dom_ent->lcme_id));
        stripe_size = d->lod_dom_max_stripesize;
 
-       lum = (void *)comp_v1 + le32_to_cpu(ent->lcme_offset);
+       lum = (void *)comp_v1 + le32_to_cpu(dom_ent->lcme_offset);
        CDEBUG(D_LAYOUT, "DoM component size %u was bigger than MDT limit %u, "
               "new size is %u\n", le32_to_cpu(lum->lmm_stripe_size),
               d->lod_dom_max_stripesize, stripe_size);
        lum->lmm_stripe_size = cpu_to_le32(stripe_size);
 
-       for (i = 1; i < le16_to_cpu(comp_v1->lcm_entry_count); i++) {
-               ent = &comp_v1->lcm_entries[i];
-               mid = mirror_id_of(le32_to_cpu(ent->lcme_id));
+       for_each_comp_entry_v1(comp_v1, ent) {
+               if (ent == dom_ent)
+                       continue;
 
+               mid = mirror_id_of(le32_to_cpu(ent->lcme_id));
                if (mid != dom_mid)
                        continue;
 
@@ -1685,9 +1749,17 @@ int lod_fix_dom_stripe(struct lod_device *d, struct lov_comp_md_v1 *comp_v1)
                ext->e_start = cpu_to_le64(stripe_size);
                break;
        }
-       /* Update DoM extent end finally */
-       dom_ext->e_end = cpu_to_le64(stripe_size);
-       return 0;
+
+       if (stripe_size == 0) {
+               /* DoM component size is zero due to server setting,
+                * remove it from the layout */
+               rc = lod_erase_dom_stripe(comp_v1);
+       } else {
+               /* Update DoM extent end finally */
+               dom_ext->e_end = cpu_to_le64(stripe_size);
+       }
+
+       return rc;
 }
 
 /**
@@ -1714,9 +1786,9 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo,
        __u64   prev_end = 0;
        __u32   stripe_size = 0;
        __u16   prev_mid = -1, mirror_id = -1;
-       __u32   mirror_count = 0;
+       __u32   mirror_count;
        __u32   magic;
-       int     rc = 0, i;
+       int     rc = 0;
        ENTRY;
 
        lum = buf->lb_buf;
@@ -1748,6 +1820,8 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo,
                RETURN(-EINVAL);
        }
 
+recheck:
+       mirror_count = 0;
        if (le16_to_cpu(comp_v1->lcm_entry_count) == 0) {
                CDEBUG(D_LAYOUT, "entry count is zero\n");
                RETURN(-EINVAL);
@@ -1764,8 +1838,7 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo,
                ++mirror_count;
        }
 
-       for (i = 0; i < le16_to_cpu(comp_v1->lcm_entry_count); i++) {
-               ent = &comp_v1->lcm_entries[i];
+       for_each_comp_entry_v1(comp_v1, ent) {
                ext = &ent->lcme_extent;
 
                if (le64_to_cpu(ext->e_start) >= le64_to_cpu(ext->e_end)) {
@@ -1821,10 +1894,11 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo,
                lum = tmp.lb_buf;
                if (lov_pattern(le32_to_cpu(lum->lmm_pattern)) ==
                    LOV_PATTERN_MDT) {
-                       /* DoM component can be only the first entry */
-                       if (i > 0) {
-                               CDEBUG(D_LAYOUT, "invalid DoM layout "
-                                      "entry found at %i index\n", i);
+                       /* DoM component can be only the first stripe */
+                       if (le64_to_cpu(ext->e_start) > 0) {
+                               CDEBUG(D_LAYOUT, "invalid DoM component "
+                                      "with %llu extent start\n",
+                                      le64_to_cpu(ext->e_start));
                                RETURN(-EINVAL);
                        }
                        stripe_size = le32_to_cpu(lum->lmm_stripe_size);
@@ -1843,10 +1917,14 @@ int lod_verify_striping(struct lod_device *d, struct lod_object *lo,
                                       "%u is bigger than MDT limit %u, check "
                                       "dom_max_stripesize parameter\n",
                                       stripe_size, d->lod_dom_max_stripesize);
-                               if (d->lod_dom_max_stripesize)
-                                       lod_fix_dom_stripe(d, comp_v1);
-                               else
-                                       RETURN(-EFBIG);
+                               rc = lod_fix_dom_stripe(d, comp_v1);
+                               if (rc == -ERESTART) {
+                                       /* DoM entry was removed, re-check
+                                        * new layout from start */
+                                       goto recheck;
+                               } else if (rc) {
+                                       RETURN(rc);
+                               }
                        }
                }
 
index 906d0a7..dbe6ec3 100755 (executable)
@@ -16491,7 +16491,8 @@ test_270f() {
                error "Can't set directory default striping"
 
        # exceed maximum stripe size
-       $LFS setstripe -E $((dom_limit * 2)) -L mdt $dom
+       $LFS setstripe -E $((dom_limit * 2)) -L mdt $dom ||
+               error "Can't create file with $((dom_limit * 2)) DoM stripe"
        [ $($LFS getstripe -S $dom) -eq $((dom_limit * 2)) ] &&
                error "Able to create DoM component size more than LOD limit"
 
@@ -16500,6 +16501,19 @@ test_270f() {
                                                lod.$mdtname.dom_stripesize)
        [ 0 -eq ${dom_current} ] ||
                error "Can't set zero DoM stripe limit"
+       rm $dom
+
+       # attempt to create DoM file on server with disabled DoM should
+       # remove DoM entry from layout and be succeed
+       $LFS setstripe -E $dom_limit -L mdt -E -1 $dom ||
+               error "Can't create DoM file (DoM is disabled)"
+       [ $($LFS getstripe -L $dom) == "mdt" ] &&
+               error "File has DoM component while DoM is disabled"
+       rm $dom
+
+       # attempt to create DoM file with only DoM stripe should return error
+       $LFS setstripe -E $dom_limit -L mdt $dom &&
+               error "Able to create DoM-only file while DoM is disabled"
 
        # too low values to be aligned with smallest stripe size 64K
        do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=30000
@@ -16525,7 +16539,8 @@ test_270f() {
                error "Can't create DoM component size after limit change"
        do_facet mds1 $LCTL set_param -n \
                                lod.$mdtname.dom_stripesize=$((dom_limit / 2))
-       $LFS setstripe -E $dom_limit -L mdt ${dom}_big
+       $LFS setstripe -E $dom_limit -L mdt ${dom}_big ||
+               error "Can't create DoM file after limit decrease"
        [ $($LFS getstripe -S ${dom}_big) -eq $((dom_limit / 2)) ] ||
                error "Can create big DoM component after limit decrease"
        touch ${dom}_def ||