diff options
author | Heinz Mauelshagen <heinzm@redhat.com> | 2016-02-05 18:41:29 +0100 |
---|---|---|
committer | Heinz Mauelshagen <heinzm@redhat.com> | 2016-02-05 18:41:29 +0100 |
commit | 9433958318a424f0c5646c2672b0da40f7d81a10 (patch) | |
tree | 3833e45038598f5cce0957f31461a2b3ee867501 | |
parent | b4c213b77500cf6bc3191b6b9fd3e2f5859df2bb (diff) | |
download | lvm2-9433958318a424f0c5646c2672b0da40f7d81a10.tar.gz |
lv_manip: LV resizing fixes
-rw-r--r-- | lib/activate/dev_manager.c | 6 | ||||
-rw-r--r-- | lib/metadata/lv_manip.c | 53 | ||||
-rw-r--r-- | lib/metadata/merge.c | 17 | ||||
-rw-r--r-- | lib/metadata/raid_manip.c | 77 |
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 |