summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2016-02-05 18:41:29 +0100
committerHeinz Mauelshagen <heinzm@redhat.com>2016-02-05 18:41:29 +0100
commit9433958318a424f0c5646c2672b0da40f7d81a10 (patch)
tree3833e45038598f5cce0957f31461a2b3ee867501
parentb4c213b77500cf6bc3191b6b9fd3e2f5859df2bb (diff)
downloadlvm2-9433958318a424f0c5646c2672b0da40f7d81a10.tar.gz
lv_manip: LV resizing fixes
-rw-r--r--lib/activate/dev_manager.c6
-rw-r--r--lib/metadata/lv_manip.c53
-rw-r--r--lib/metadata/merge.c17
-rw-r--r--lib/metadata/raid_manip.c77
4 files changed, 75 insertions, 78 deletions
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 7153db362..ab9b54bb8 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -180,11 +180,7 @@ typedef enum {
/* Return length of segment depending on type and reshape_len */
static uint32_t _seg_len(const struct lv_segment *seg)
{
- if (seg_is_raid(seg))
- return seg->len - (((seg->area_count - seg->segtype->parity_devs) * seg->reshape_len) /
- (seg_is_any_raid10(seg) ? seg->data_copies : 1));
-
- return seg->len;
+ return seg->len - (seg_is_raid(seg) ? ((seg->area_count - seg->segtype->parity_devs) * seg->reshape_len) : 0);
}
static int _info_run(info_type_t type, const char *name, const char *dlid,
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 5df10180c..8b8bc6e06 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1437,15 +1437,21 @@ PFLA("lv=%s lv->le_count=%u seg=%p extents=%u stripes=%u data_copies=%u delete=%
if (!dont_recurse) {
for (s = 0; s < seg->area_count; s++) {
if (_is_layered_lv(lv, s)) {
- uint32_t seg_lv_extents = seg_lv(seg, s)->le_count;
+ uint32_t sub_lv_extents;
+ struct logical_volume *lv1 = seg_lv(seg, s);
+ struct lv_segment *seg1 = last_seg(lv1);
- if (!delete)
- seg_lv_extents -= lv->le_count - extents;
+ if (delete)
+ sub_lv_extents = lv1->le_count;
+ else
+ sub_lv_extents = lv1->le_count - _round_to_stripe_boundary(lv1, lv1->le_count - extents,
+ seg1->area_count - seg1->segtype->parity_devs,
+ 0 /* reduce */);
-PFLA("recursive seg_lv(seg, %u)=%s", s, display_lvname(seg_lv(seg, s)));
- if (!_lv_reduce(seg_lv(seg, s), seg_lv_extents, delete))
+PFLA("recursive seg_lv(seg, %u)=%s", s, display_lvname(lv1));
+ if (!_lv_reduce(lv1, sub_lv_extents, delete))
return_0;
-PFLA("end recursive seg_lv(seg, %u)=%s", s, display_lvname(seg_lv(seg, s)));
+PFLA("end recursive seg_lv(seg, %u)=%s", s, display_lvname(lv1));
reduced++;
}
}
@@ -3442,8 +3448,8 @@ static int _allocate(struct alloc_handle *ah,
PFLA("ah->new_extents=%u extents_still_needed=%u rimage_extents=%u", ah->new_extents, ah->new_extents - alloc_state.allocated, rimage_extents);
if (extents_still_needed > rimage_extents &&
(extents_still_needed % rimage_extents)) {
- log_error("Number of extents requested (%u) needs to be divisible by %d.",
- ah->new_extents - alloc_state.allocated,
+ log_error("Number of extents requested (%u) for LV %s needs to be divisible by %d.",
+ ah->new_extents - alloc_state.allocated, display_lvname(lv),
rimage_extents);
return 0;
}
@@ -4437,7 +4443,6 @@ int lv_extend(struct logical_volume *lv,
{
int r = 1;
int log_count = 0;
- int alloc_mirrors = 1;
uint32_t area_count, s;
struct alloc_handle *ah;
uint32_t sub_lv_count;
@@ -4452,24 +4457,36 @@ int lv_extend(struct logical_volume *lv,
return 0;
}
- if (segtype_is_mirrored(segtype) || segtype_is_raid1(segtype))
+ /* Should be ensured by the caller... */
+#if 0
+ if (!segtype_is_raid01(segtype) &&
+ (segtype_is_mirrored(segtype) || segtype_is_raid1(segtype)))
stripes = 1;
+#endif
log_very_verbose("Adding segment of type %s to LV %s.", segtype->name, display_lvname(lv));
PFLA("extents=%u", extents);
-#if 1
/* Check for multi-level stack (e.g. extension of a duplicated LV stack) */
if (seg) {
int extended = 0;
for (s = 0; s < seg->area_count; s++) {
if (_is_layered_lv(lv, s)) {
+ uint32_t sub_lv_extents, stripes1;
struct logical_volume *lv1 = seg_lv(seg, s);
struct lv_segment *seg1 = last_seg(lv1);
+
+ stripes1 = seg1->area_count - seg1->segtype->parity_devs;
+ sub_lv_extents = _round_to_stripe_boundary(lv1, lv->le_count + extents, stripes1, 1 /* extend */);
+ if (sub_lv_extents < lv->le_count)
+ return_0;
+ sub_lv_extents -= lv1->le_count;
PFLA("recursive seg_lv(seg, %u)=%s extents=%u", s, display_lvname(lv1), extents);
- if (extents + lv->le_count > lv1->le_count &&
- !lv_extend(lv1, seg1->segtype, seg1->area_count, seg1->stripe_size, seg1->data_copies, seg1->region_size, extents, allocatable_pvs, alloc, approx_alloc))
+ if (sub_lv_extents + lv->le_count > lv1->le_count &&
+ !lv_extend(lv1, seg1->segtype, stripes1, seg1->stripe_size,
+ seg1->data_copies, seg1->region_size, sub_lv_extents,
+ allocatable_pvs, alloc, approx_alloc))
return_0;
extended++;
@@ -4484,9 +4501,10 @@ PFLA("recursive seg_lv(seg, %u)=%s extents=%u", s, display_lvname(lv1), extents)
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
return 1;
}
-#endif
+
/* Caller should ensure... */
if (seg_is_striped(seg) ||
+ seg_is_raid01(seg) ||
seg_is_striped_raid(seg)) {
area_count = seg->area_count;
stripes = area_count - seg->segtype->parity_devs;
@@ -4514,11 +4532,8 @@ PFLA("extents=%u stripe_size=%u", extents, stripe_size);
/* FIXME Support striped metadata pool */
log_count = 1;
- } else if (segtype_is_striped_raid(segtype)) {
- /* If only one extent is being requested on a striped raid set, it's reshape space being requested */
- alloc_mirrors = extents > 1 ? 1 : 0;
+ } else if (segtype_is_striped_raid(segtype))
extents = _round_to_stripe_boundary(lv, extents, stripes, 1 /* extend */);
- }
PFLA("extents=%u segtype=%s mirrors=%u stripes=%u log_count=%u", extents, segtype->name, mirrors, stripes, log_count);
@@ -4549,7 +4564,7 @@ PFLA("extents=%u mirrors=%u stripes=%u log_count=%u", extents, mirrors, stripes,
return 0;
}
- if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, alloc_mirrors ? mirrors : 1,
+ if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors,
log_count, region_size, extents,
allocatable_pvs, alloc, approx_alloc, NULL)))
return_0;
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 40c7c4aa0..d5f17d6d2 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -147,8 +147,8 @@ PFLA("segtype=%s", lvseg_name(first_seg(lv)));
PFLA("lv=%s segtype=%s seg->len=%u seg->area_len=%u seg->area_count=%u data_rimage_count=%u parity_devs=%u area_multiplier=%u seg->data_copies=%u rimageextents=%u seg->reshape_len=%u", lv->name, seg->segtype->name, seg->len, seg->area_len, seg->area_count, data_rimage_count, seg->segtype->parity_devs, area_multiplier, seg->data_copies, raid_rimage_extents(seg->segtype, seg->len - data_rimage_count * seg->reshape_len, data_rimage_count, seg->data_copies), seg->reshape_len);
#if 1
data_copies = seg_is_any_raid10(seg) ? seg->data_copies : 1;
- if (raid_rimage_extents(seg->segtype, seg->len - data_rimage_count * seg->reshape_len,
- data_rimage_count, seg->data_copies) != seg->area_len - data_copies * seg->reshape_len) {
+ if (!raid_rimage_extents(seg->segtype, seg->len - data_rimage_count * seg->reshape_len,
+ data_rimage_count, seg->data_copies) == seg->area_len - data_copies * seg->reshape_len) {
#else
if (seg->area_len * area_multiplier != seg->len) {
#endif
@@ -158,6 +158,19 @@ PFLA("lv=%s segtype=%s seg->len=%u seg->area_len=%u seg->area_count=%u data_rima
inc_error_count;
}
+#if 0
+ if (seg_is_any_raid10(seg) && (seg->len % seg->data_copies)) {
+ log_error("raid10 segment length %u of %s not divisible by %u data copies",
+ seg->len, lv->name, seg->data_copies);
+ inc_error_count;
+ }
+#endif
+ if (seg_is_any_raid10(seg) && (seg->data_copies < 1 || seg->data_copies > seg->area_count)) {
+ log_error("raid10 data copies %u of %s and area count %u missmatch",
+ seg->data_copies, lv->name, seg->area_count);
+ inc_error_count;
+ }
+
if (lv_is_error_when_full(lv) &&
!seg_can_error_when_full(seg)) {
log_error("LV %s: segment %u (%s) does not support flag "
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index 120bae6c1..4262204b2 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2015 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2011-2016 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -4419,12 +4419,9 @@ PFLA("seg->len=%u", first_seg(lv)->len);
* - reset rebuild flag on new image LVs
* - set delta disks plus flag on new image LVs
*/
- log_debug_metadata("Setting delta disk flag on new data LVs of %s",
- display_lvname(lv));
if (old_image_count < seg->area_count) {
- if (!_vg_write_commit_backup(vg))
- return 0;
-
+ log_debug_metadata("Setting delta disk flag on new data LVs of %s",
+ display_lvname(lv));
for (s = old_image_count; s < seg->area_count; s++) {
slv = seg_lv(seg, s);
PFLA("seg_lv(seg, %u)=%s", s, display_lvname(slv));
@@ -4710,31 +4707,18 @@ PFLA("seg->data_copies=%u new_data_copies=%u", seg->data_copies, new_data_copies
return 0;
PFL();
/* Check a request to change the number of data copies in a raid10 LV */
- if (seg->data_copies != new_data_copies) {
- if (seg_is_raid10_far(seg)) {
- /*
- * Ensure resynchronisation of new data copies
- * No reshape space needed, because raid10_far uses distinct stripe zones
- * for its data copies rather than rotating them in individual stripes.
- */
- *force_repair = new_data_copies > seg->data_copies;
- alloc_reshape_space = 0;
-
- if (!_lv_raid10_resize_data_copies(lv, new_segtype, new_data_copies, allocate_pvs))
- return 0;
+ if (seg_is_raid10_far(seg) &&
+ seg->data_copies != new_data_copies) {
+ /*
+ * Ensure resynchronisation of new data copies
+ * No reshape space needed, because raid10_far uses distinct stripe zones
+ * for its data copies rather than rotating them in individual stripes.
+ */
+ *force_repair = new_data_copies > seg->data_copies;
+ alloc_reshape_space = 0;
- } else if (seg_is_any_raid10(seg)) {
- /* Ensure resynchronisation */
- *force_repair = 1;
- if (new_data_copies > seg->data_copies) {
- where = alloc_end;
- if (!_lv_raid10_resize_data_copies(lv, new_segtype, new_data_copies, allocate_pvs))
- return 0;
- } else {
- where = alloc_begin;
- seg->data_copies = new_data_copies;
- }
- }
+ if (!_lv_raid10_resize_data_copies(lv, new_segtype, new_data_copies, allocate_pvs))
+ return 0;
}
/*
@@ -4796,11 +4780,13 @@ static int _pre_raid_reshape(struct logical_volume *lv, void *data)
struct lv_segment *seg;
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
- RETURN_IF_ZERO((old_image_count = *((uint32_t *) data)), "proper data argument");
+ RETURN_IF_ZERO(data, "proper data pointer argument");
+ RETURN_IF_ZERO((old_image_count = *((uint32_t *) data)), "proper old image count");
/* Activate any new image component pairs */
if (old_image_count < seg->area_count)
- return _activate_sub_lvs(lv, old_image_count);
+ return _vg_write_commit_backup(lv->vg) &&
+ _activate_sub_lvs(lv, old_image_count);
return 1;
}
@@ -8451,13 +8437,6 @@ TAKEOVER_HELPER_FN(_r10_r10)
if (!_reorder_raid10_near_seg_areas(seg, reorder_from_raid10_near))
return 0;
-#if 0
- if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_RAID4)))
- return_0;
-
- seg->data_copies = 1;
-#endif
-
PFLA("seg->area_count=%u, new_count=%u", seg->area_count, seg->area_count / data_copies * new_data_copies);
if (!_lv_change_image_count(lv, seg->area_count / data_copies * new_data_copies,
allocate_pvs, &removal_lvs))
@@ -9484,14 +9463,6 @@ PFL();
case 0:
break;
case 1:
-#if 0
- if ((rcp.data_copies > 1 || stripes != seg->area_count - seg->segtype->parity_devs) &&
- !is_same_level(seg->segtype, new_segtype)) {
- log_error("Can't reshape and takeover %s at the same time",
- display_lvname(lv));
- return 0;
- }
-#endif
if (!_raid_reshape(lv, new_segtype, rcp.yes, rcp.force,
data_copies, region_size,
stripes, stripe_size, rcp.allocate_pvs))
@@ -10400,7 +10371,7 @@ static int _partial_raid_lv_is_redundant(const struct logical_volume *lv)
/*
* raid10:
*
- * - if #devices is divisable by number of data copies,
+ lv->* - if #devices is divisable by number of data copies,
* the data copies form 'mirror groups' like 'AAABBB' for 3 data copies and 6 stripes ->
* check that each of the mirror groups has at least 2 data copies available
*
@@ -10526,10 +10497,12 @@ static int _raid10_seg_images_sane(struct lv_segment *seg)
slv = seg_lv(seg, s);
if (len) {
RETURN_IF_ZERO((slv->le_count == len), "consistent raid10_far image LV length");
- RETURN_IF_NONZERO((slv->le_count % seg->data_copies),
- "raid10_far image LV length divisibility by #data_copies");
- } else
+ } else {
RETURN_IF_ZERO((len = slv->le_count), "raid10_far image LV length");
+ }
+
+ RETURN_IF_NONZERO((slv->le_count % seg->data_copies),
+ "raid10_far image LV length divisibility by #data_copies");
}
return 1;
@@ -10566,7 +10539,7 @@ static int _split_lv_data_images(struct logical_volume *lv,
* Reorder segments for @extents length in @lv;
* @extend flag indicates extension/reduction request.
*
- * raid10_far arranges stripe zones with differing data block rotation
+ * raid10_far arranges stripe zones with data block rotation
* one after the other and does data_copies across them.
*
* In order to resize those, we have to split them up by # data copies