Whamcloud - gitweb
LU-14521 flr: delete mirror without volatile file
[fs/lustre-release.git] / lustre / lod / lod_lov.c
index d0a711e..4376eaa 100644 (file)
@@ -415,7 +415,7 @@ int lod_del_device(const struct lu_env *env, struct lod_device *lod,
        mutex_lock(&ltd->ltd_mutex);
        tgt = LTD_TGT(ltd, idx);
        /* check that the index is allocated in the bitmap */
-       if (!cfs_bitmap_check(ltd->ltd_tgt_bitmap, idx) || !tgt) {
+       if (!test_bit(idx, ltd->ltd_tgt_bitmap) || !tgt) {
                CERROR("%s: device %d is not set up\n", obd->obd_name, idx);
                GOTO(out, rc = -EINVAL);
        }
@@ -549,8 +549,7 @@ int lod_def_striping_comp_resize(struct lod_default_striping *lds, __u16 count)
 void lod_free_comp_entries(struct lod_object *lo)
 {
        if (lo->ldo_mirrors) {
-               OBD_FREE(lo->ldo_mirrors,
-                        sizeof(*lo->ldo_mirrors) * lo->ldo_mirror_count);
+               OBD_FREE_PTR_ARRAY(lo->ldo_mirrors, lo->ldo_mirror_count);
                lo->ldo_mirrors = NULL;
                lo->ldo_mirror_count = 0;
        }
@@ -569,8 +568,7 @@ int lod_alloc_comp_entries(struct lod_object *lo,
        LASSERT(lo->ldo_comp_cnt == 0 && lo->ldo_comp_entries == NULL);
 
        if (mirror_count > 0) {
-               OBD_ALLOC(lo->ldo_mirrors,
-                         sizeof(*lo->ldo_mirrors) * mirror_count);
+               OBD_ALLOC_PTR_ARRAY(lo->ldo_mirrors, mirror_count);
                if (!lo->ldo_mirrors)
                        return -ENOMEM;
 
@@ -580,8 +578,7 @@ int lod_alloc_comp_entries(struct lod_object *lo,
        OBD_ALLOC_LARGE(lo->ldo_comp_entries,
                        sizeof(*lo->ldo_comp_entries) * comp_count);
        if (lo->ldo_comp_entries == NULL) {
-               OBD_FREE(lo->ldo_mirrors,
-                        sizeof(*lo->ldo_mirrors) * mirror_count);
+               OBD_FREE_PTR_ARRAY(lo->ldo_mirrors, mirror_count);
                lo->ldo_mirror_count = 0;
                return -ENOMEM;
        }
@@ -707,7 +704,7 @@ static int lod_gen_component_ea(const struct lu_env *env,
                        RETURN(-E2BIG);
                objs = &v3->lmm_objects[0];
        }
-       stripe_count = lod_comp_entry_stripe_count(lo, lod_comp, is_dir);
+       stripe_count = lod_comp_entry_stripe_count(lo, comp_idx, is_dir);
        if (stripe_count == 0 && !is_dir &&
            !(lod_comp->llc_pattern & LOV_PATTERN_F_RELEASED) &&
            !(lod_comp->llc_pattern & LOV_PATTERN_MDT))
@@ -961,10 +958,10 @@ repeat:
  * \retval                     0 if the index is present
  * \retval                     -EINVAL if not
  */
-static int validate_lod_and_idx(struct lod_device *md, __u32 idx)
+int validate_lod_and_idx(struct lod_device *md, __u32 idx)
 {
        if (unlikely(idx >= md->lod_ost_descs.ltd_tgts_size ||
-                    !cfs_bitmap_check(md->lod_ost_bitmap, idx))) {
+                    !test_bit(idx, md->lod_ost_bitmap))) {
                CERROR("%s: bad idx: %d of %d\n", lod2obd(md)->obd_name, idx,
                       md->lod_ost_descs.ltd_tgts_size);
                return -EINVAL;
@@ -1028,10 +1025,10 @@ int lod_initialize_objects(const struct lu_env *env, struct lod_object *lo,
        LASSERT(lod_comp->llc_stripe_size > 0);
 
        stripe_len = lod_comp->llc_stripe_count;
-       OBD_ALLOC(stripe, sizeof(stripe[0]) * stripe_len);
+       OBD_ALLOC_PTR_ARRAY(stripe, stripe_len);
        if (stripe == NULL)
                RETURN(-ENOMEM);
-       OBD_ALLOC(ost_indices, sizeof(*ost_indices) * stripe_len);
+       OBD_ALLOC_PTR_ARRAY(ost_indices, stripe_len);
        if (!ost_indices)
                GOTO(out, rc = -ENOMEM);
 
@@ -1077,11 +1074,10 @@ out:
                        if (stripe[i] != NULL)
                                dt_object_put(env, stripe[i]);
 
-               OBD_FREE(stripe, sizeof(stripe[0]) * stripe_len);
+               OBD_FREE_PTR_ARRAY(stripe, stripe_len);
                lod_comp->llc_stripe_count = 0;
                if (ost_indices)
-                       OBD_FREE(ost_indices,
-                                sizeof(*ost_indices) * stripe_len);
+                       OBD_FREE_PTR_ARRAY(ost_indices, stripe_len);
        } else {
                lod_comp->llc_stripe = stripe;
                lod_comp->llc_ost_indices = ost_indices;
@@ -1142,9 +1138,12 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo,
                        GOTO(out, rc = -EINVAL);
                lo->ldo_layout_gen = le32_to_cpu(comp_v1->lcm_layout_gen);
                lo->ldo_is_composite = 1;
-               lo->ldo_flr_state = le16_to_cpu(comp_v1->lcm_flags) &
-                                       LCM_FL_FLR_MASK;
                mirror_cnt = le16_to_cpu(comp_v1->lcm_mirror_count) + 1;
+               if (mirror_cnt > 1)
+                       lo->ldo_flr_state = le16_to_cpu(comp_v1->lcm_flags) &
+                                                       LCM_FL_FLR_MASK;
+               else
+                       lo->ldo_flr_state = LCM_FL_NONE;
        } else if (magic == LOV_MAGIC_FOREIGN) {
                size_t length;
 
@@ -1187,7 +1186,26 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo,
                        ext = &comp_v1->lcm_entries[i].lcme_extent;
                        lod_comp->llc_extent.e_start =
                                le64_to_cpu(ext->e_start);
+                       if (lod_comp->llc_extent.e_start &
+                           (LOV_MIN_STRIPE_SIZE - 1)) {
+                               CDEBUG(D_LAYOUT,
+                                      "extent start %llu is not a multiple of min size %u\n",
+                                      lod_comp->llc_extent.e_start,
+                                      LOV_MIN_STRIPE_SIZE);
+                               GOTO(out, rc = -EINVAL);
+                       }
+
                        lod_comp->llc_extent.e_end = le64_to_cpu(ext->e_end);
+                       if (lod_comp->llc_extent.e_end != LUSTRE_EOF &&
+                           lod_comp->llc_extent.e_end &
+                           (LOV_MIN_STRIPE_SIZE - 1)) {
+                               CDEBUG(D_LAYOUT,
+                                      "extent end %llu is not a multiple of min size %u\n",
+                                      lod_comp->llc_extent.e_end,
+                                      LOV_MIN_STRIPE_SIZE);
+                               GOTO(out, rc = -EINVAL);
+                       }
+
                        lod_comp->llc_flags =
                                le32_to_cpu(comp_v1->lcm_entries[i].lcme_flags);
                        if (lod_comp->llc_flags & LCME_FL_NOSYNC)
@@ -1243,7 +1261,7 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo,
                                int j;
 
                                stripe_count = lod_comp_entry_stripe_count(
-                                                       lo, lod_comp, false);
+                                                       lo, i, false);
                                if (stripe_count == 0 &&
                                    !(lod_comp->llc_pattern & LOV_PATTERN_F_RELEASED) &&
                                    !(lod_comp->llc_pattern & LOV_PATTERN_MDT))
@@ -1534,7 +1552,7 @@ static int lod_verify_v1v3(struct lod_device *d, const struct lu_buf *buf,
                }
 
                /* if lmm_stripe_offset is *not* in bitmap */
-               if (!cfs_bitmap_check(d->lod_ost_bitmap, stripe_offset)) {
+               if (!test_bit(stripe_offset, d->lod_ost_bitmap)) {
                        CDEBUG(D_LAYOUT, "stripe offset %u not in bitmap\n",
                               stripe_offset);
                        GOTO(out, rc = -EINVAL);
@@ -1612,40 +1630,51 @@ int lod_erase_dom_stripe(struct lov_comp_md_v1 *comp_v1,
 {
        struct lov_comp_md_entry_v1 *ent;
        __u16 entries;
-       __u32 dom_off, dom_size, comp_size;
-       void *blob_src, *blob_dst;
-       unsigned int blob_size, blob_shift;
+       __u32 dom_off, dom_size, comp_size, off;
+       void *src, *dst;
+       unsigned int size, 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;
+       LASSERT(entries > 0);
+       comp_v1->lcm_entry_count = cpu_to_le16(entries);
 
        comp_size = le32_to_cpu(comp_v1->lcm_size);
        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);
-
+       /* all entries offsets are shifted by entry size at least */
+       shift = sizeof(*dom_ent);
        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);
+               if (off == dom_off) {
+                       /* Entry deletion creates two holes in layout data:
+                        * - hole in entries array
+                        * - hole in layout data at dom_off with dom_size
+                        *
+                        * First memmove is one entry shift from next entry
+                        * start with size up to dom_off in blob
+                        */
+                       dst = (void *)ent;
+                       src = (void *)(ent + 1);
+                       size = (unsigned long)((void *)comp_v1 + dom_off - src);
+                       memmove(dst, src, size);
+                       /* take 'off' from just moved entry */
+                       off = le32_to_cpu(ent->lcme_offset);
+                       /* second memmove is blob tail after 'off' up to
+                        * component end
+                        */
+                       dst = (void *)comp_v1 + dom_off - sizeof(*ent);
+                       src = (void *)comp_v1 + off;
+                       size = (unsigned long)(comp_size - off);
+                       memmove(dst, src, size);
+                       /* all entries offsets after DoM entry are shifted by
+                        * dom_size additionally
+                        */
+                       shift += dom_size;
+               }
+               ent->lcme_offset = cpu_to_le32(off - shift);
        }
-
-       comp_v1->lcm_size = cpu_to_le32(comp_size - blob_shift);
+       comp_v1->lcm_size = cpu_to_le32(comp_size - shift);
 
        /* notify a caller to re-check entry */
        return -ERESTART;
@@ -1732,6 +1761,7 @@ int lod_dom_stripesize_choose(const struct lu_env *env, struct lod_device *d,
        __u32 max_stripe_size;
        __u16 mid, dom_mid;
        int rc = 0;
+       bool dom_next_entry = false;
 
        dom_ext = &dom_ent->lcme_extent;
        dom_mid = mirror_id_of(le32_to_cpu(dom_ent->lcme_id));
@@ -1746,6 +1776,10 @@ int lod_dom_stripesize_choose(const struct lu_env *env, struct lod_device *d,
               stripe_size, max_stripe_size);
        lum->lmm_stripe_size = cpu_to_le32(max_stripe_size);
 
+       /* In common case the DoM stripe is first entry in a mirror and
+        * can be deleted only if it is not single entry in layout or
+        * mirror, otherwise error should be returned.
+        */
        for_each_comp_entry_v1(comp_v1, ent) {
                if (ent == dom_ent)
                        continue;
@@ -1766,12 +1800,19 @@ int lod_dom_stripesize_choose(const struct lu_env *env, struct lod_device *d,
                 * always and don't need adjustment since use own layouts.
                 */
                ext->e_start = cpu_to_le64(max_stripe_size);
+               dom_next_entry = true;
                break;
        }
 
        if (max_stripe_size == 0) {
-               /* DoM component size is zero due to server setting,
-                * remove it from the layout */
+               /* DoM component size is zero due to server setting, remove
+                * it from the layout but only if next component exists in
+                * the same mirror. That must be checked prior calling the
+                * lod_erase_dom_stripe().
+                */
+               if (!dom_next_entry)
+                       return -EFBIG;
+
                rc = lod_erase_dom_stripe(comp_v1, dom_ent);
        } else {
                /* Update DoM extent end finally */
@@ -1892,7 +1933,10 @@ recheck:
        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)) {
+               if (le64_to_cpu(ext->e_start) > le64_to_cpu(ext->e_end) ||
+                   le64_to_cpu(ext->e_start) & (LOV_MIN_STRIPE_SIZE - 1) ||
+                   (le64_to_cpu(ext->e_end) != LUSTRE_EOF &&
+                   le64_to_cpu(ext->e_end) & (LOV_MIN_STRIPE_SIZE - 1))) {
                        CDEBUG(D_LAYOUT, "invalid extent "DEXT"\n",
                               le64_to_cpu(ext->e_start),
                               le64_to_cpu(ext->e_end));