From 3fd758ed4f40f235d26df9fd7c6b459590fbe0cf Mon Sep 17 00:00:00 2001 From: Mikhail Pershin Date: Mon, 21 May 2018 21:24:05 +0300 Subject: [PATCH] LU-10808 lod: remove DoM component if DoM is disabled 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 Change-Id: Ibafd0269d76dc5de4599efca064930607dc556eb Reviewed-on: https://review.whamcloud.com/32482 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Fan Yong Reviewed-by: Oleg Drokin --- lustre/lod/lod_lov.c | 126 +++++++++++++++++++++++++++++++++++++++---------- lustre/tests/sanity.sh | 19 +++++++- 2 files changed, 119 insertions(+), 26 deletions(-) diff --git a/lustre/lod/lod_lov.c b/lustre/lod/lod_lov.c index 092389f..cd96cff 100644 --- a/lustre/lod/lod_lov.c +++ b/lustre/lod/lod_lov.c @@ -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); + } } } diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 906d0a7..dbe6ec3 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -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 || -- 1.8.3.1