mutex_lock(<d->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);
}
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;
}
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;
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;
}
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))
* \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;
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);
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;
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;
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)
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))
}
/* 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);
{
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;
__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));
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;
* 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 */
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));