You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
532 lines
18 KiB
532 lines
18 KiB
WHATS_NEW | 2 + |
|
lib/metadata/raid_manip.c | 277 +++++++++++++++++++++++++++++++--- |
|
test/shell/lvconvert-raid-takeover.sh | 53 ++++++- |
|
tools/lvconvert.c | 24 +-- |
|
4 files changed, 314 insertions(+), 42 deletions(-) |
|
|
|
diff --git a/WHATS_NEW b/WHATS_NEW |
|
index 5cbf4ec..6a0c311 100644 |
|
--- a/WHATS_NEW |
|
+++ b/WHATS_NEW |
|
@@ -1,5 +1,7 @@ |
|
Version 2.02.167 - |
|
====================================== |
|
+ Add direct striped -> raid4 conversion |
|
+ Fix raid4 parity image pair position on conversions from striped/raid0* |
|
Disable lvconvert of thin pool to raid while active. |
|
|
|
Version 2.02.166 - 26th September 2016 |
|
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
|
index 5fc520e..e5fd195 100644 |
|
--- a/lib/metadata/raid_manip.c |
|
+++ b/lib/metadata/raid_manip.c |
|
@@ -2459,7 +2459,7 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv, |
|
0 /* chunk_size */, |
|
0 /* seg->region_size */, 0u /* extents_copied */ , |
|
NULL /* pvmove_source_seg */))) { |
|
- log_error("Failed to allocate new raid0 segement for LV %s.", display_lvname(lv)); |
|
+ log_error("Failed to allocate new raid0 segment for LV %s.", display_lvname(lv)); |
|
return NULL; |
|
} |
|
|
|
@@ -2519,42 +2519,51 @@ static struct possible_takeover_reshape_type _possible_takeover_reshape_types[] |
|
{ .current_types = SEG_STRIPED_TARGET, /* linear, i.e. seg->area_count = 1 */ |
|
.possible_types = SEG_RAID1, |
|
.current_areas = 1, |
|
- .options = ALLOW_NONE }, |
|
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
|
{ .current_types = SEG_STRIPED_TARGET, /* linear, i.e. seg->area_count = 1 */ |
|
.possible_types = SEG_RAID0|SEG_RAID0_META, |
|
.current_areas = 1, |
|
.options = ALLOW_STRIPE_SIZE }, |
|
- { .current_types = SEG_STRIPED_TARGET, /* striped, i.e. seg->area_count > 1 */ |
|
+ { .current_types = SEG_STRIPED_TARGET, /* striped -> raid0*, i.e. seg->area_count > 1 */ |
|
.possible_types = SEG_RAID0|SEG_RAID0_META, |
|
.current_areas = ~0U, |
|
.options = ALLOW_NONE }, |
|
+ { .current_types = SEG_STRIPED_TARGET, /* striped -> raid4 , i.e. seg->area_count > 1 */ |
|
+ .possible_types = SEG_RAID4, |
|
+ .current_areas = ~0U, |
|
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
|
/* raid0* -> */ |
|
{ .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count = 1 */ |
|
.possible_types = SEG_RAID1, |
|
.current_areas = 1, |
|
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
|
+ { .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0* -> striped, i.e. seg->area_count > 1 */ |
|
+ .possible_types = SEG_STRIPED_TARGET, |
|
+ .current_areas = ~0U, |
|
.options = ALLOW_NONE }, |
|
- { .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count > 1 */ |
|
- .possible_types = SEG_RAID4, |
|
+ { .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0* -> raid0*, i.e. seg->area_count > 1 */ |
|
+ .possible_types = SEG_RAID0_META|SEG_RAID0, |
|
.current_areas = ~0U, |
|
.options = ALLOW_NONE }, |
|
- { .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0 striped, i.e. seg->area_count > 0 */ |
|
+ { .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0* -> raid4, i.e. seg->area_count > 1 */ |
|
+ .possible_types = SEG_RAID4, |
|
+ .current_areas = ~0U, |
|
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
|
+ /* raid4 -> -> */ |
|
+ { .current_types = SEG_RAID4, /* raid4 ->striped/raid0*, i.e. seg->area_count > 1 */ |
|
.possible_types = SEG_STRIPED_TARGET|SEG_RAID0|SEG_RAID0_META, |
|
.current_areas = ~0U, |
|
.options = ALLOW_NONE }, |
|
- /* raid1 -> */ |
|
+ /* raid1 -> mirror */ |
|
{ .current_types = SEG_RAID1, |
|
- .possible_types = SEG_RAID1|SEG_MIRROR, |
|
+ .possible_types = SEG_MIRROR, |
|
.current_areas = ~0U, |
|
- .options = ALLOW_NONE }, |
|
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
|
/* mirror -> raid1 with arbitrary number of legs */ |
|
{ .current_types = SEG_MIRROR, |
|
- .possible_types = SEG_MIRROR|SEG_RAID1, |
|
- .current_areas = ~0U, |
|
- .options = ALLOW_NONE }, |
|
- { .current_types = SEG_RAID4, |
|
- .possible_types = SEG_STRIPED_TARGET|SEG_RAID0|SEG_RAID0_META, |
|
+ .possible_types = SEG_RAID1, |
|
.current_areas = ~0U, |
|
- .options = ALLOW_NONE }, |
|
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
|
|
|
/* END */ |
|
{ .current_types = 0 } |
|
@@ -2861,9 +2870,176 @@ static int _raid1_to_mirrored_wrapper(TAKEOVER_FN_ARGS) |
|
allocate_pvs, 1, &removal_lvs); |
|
} |
|
|
|
+/* |
|
+ * HM Helper: (raid0_meta -> raid4) |
|
+ * |
|
+ * To convert raid0_meta to raid4, which involves shifting the |
|
+ * parity device to lv segment area 0 and thus changing MD |
|
+ * array roles, detach the MetaLVs and reload as raid0 in |
|
+ * order to wipe them then reattach and set back to raid0_meta. |
|
+ */ |
|
+static int _clear_meta_lvs(struct logical_volume *lv) |
|
+{ |
|
+ uint32_t s; |
|
+ struct lv_segment *seg = first_seg(lv); |
|
+ struct lv_segment_area *tmp_areas; |
|
+ const struct segment_type *tmp_segtype; |
|
+ struct dm_list meta_lvs; |
|
+ struct lv_list *lvl_array, *lvl; |
|
+ |
|
+ /* Reject non-raid0_meta segment types cautiously */ |
|
+ if (!seg_is_raid0_meta(seg) || |
|
+ !seg->meta_areas) |
|
+ return_0; |
|
+ |
|
+ if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem, seg->area_count * sizeof(*lvl_array)))) |
|
+ return_0; |
|
+ |
|
+ dm_list_init(&meta_lvs); |
|
+ tmp_areas = seg->meta_areas; |
|
+ |
|
+ /* Extract all MetaLVs listing them on @meta_lvs */ |
|
+ log_debug_metadata("Extracting all MetaLVs of %s to activate as raid0", |
|
+ display_lvname(lv)); |
|
+ if (!_extract_image_component_sublist(seg, RAID_META, 0, seg->area_count, &meta_lvs, 0)) |
|
+ return_0; |
|
+ |
|
+ /* Memorize meta areas and segtype to set again after initializing. */ |
|
+ seg->meta_areas = NULL; |
|
+ tmp_segtype = seg->segtype; |
|
+ |
|
+ if (!(seg->segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID0)) || |
|
+ !lv_update_and_reload(lv)) |
|
+ return_0; |
|
+ |
|
+ /* |
|
+ * Now deactivate the MetaLVs before clearing, so |
|
+ * that _clear_lvs() will activate them visible. |
|
+ */ |
|
+ log_debug_metadata("Deactivating pulled out MetaLVs of %s before initializing.", |
|
+ display_lvname(lv)); |
|
+ dm_list_iterate_items(lvl, &meta_lvs) |
|
+ if (!deactivate_lv(lv->vg->cmd, lvl->lv)) |
|
+ return_0; |
|
+ |
|
+ log_debug_metadata("Clearing allocated raid0_meta metadata LVs for conversion to raid4"); |
|
+ if (!_clear_lvs(&meta_lvs)) { |
|
+ log_error("Failed to initialize metadata LVs"); |
|
+ return 0; |
|
+ } |
|
+ |
|
+ /* Set memorized meta areas and raid0_meta segtype */ |
|
+ seg->meta_areas = tmp_areas; |
|
+ seg->segtype = tmp_segtype; |
|
+ |
|
+ log_debug_metadata("Adding metadata LVs back into %s", display_lvname(lv)); |
|
+ s = 0; |
|
+ dm_list_iterate_items(lvl, &meta_lvs) { |
|
+ lv_set_hidden(lvl->lv); |
|
+ if (!set_lv_segment_area_lv(seg, s++, lvl->lv, 0, RAID_META)) |
|
+ return 0; |
|
+ } |
|
+ |
|
+ return 1; |
|
+} |
|
+ |
|
+/* |
|
+ * HM Helper: (raid0* <-> raid4) |
|
+ * |
|
+ * Rename SubLVs (pairs) allowing to shift names w/o collisions with active ones. |
|
+ */ |
|
+#define SLV_COUNT 2 |
|
+static int _rename_area_lvs(struct logical_volume *lv, const char *suffix) |
|
+{ |
|
+ uint32_t s; |
|
+ size_t sz = strlen("rimage") + (suffix ? strlen(suffix) : 0) + 1; |
|
+ char *sfx[SLV_COUNT] = { NULL, NULL }; |
|
+ struct lv_segment *seg = first_seg(lv); |
|
+ |
|
+ /* Create _generate_raid_name() suffixes w/ or w/o passed in @suffix */ |
|
+ for (s = 0; s < SLV_COUNT; s++) |
|
+ if (!(sfx[s] = dm_pool_alloc(lv->vg->cmd->mem, sz)) || |
|
+ dm_snprintf(sfx[s], sz, suffix ? "%s%s" : "%s", s ? "rmeta" : "rimage", suffix) < 0) |
|
+ return_0; |
|
+ |
|
+ /* Change names (temporarily) to be able to shift numerical name suffixes */ |
|
+ for (s = 0; s < seg->area_count; s++) { |
|
+ if (!(seg_lv(seg, s)->name = _generate_raid_name(lv, sfx[0], s))) |
|
+ return_0; |
|
+ if (seg->meta_areas && |
|
+ !(seg_metalv(seg, s)->name = _generate_raid_name(lv, sfx[1], s))) |
|
+ return_0; |
|
+ } |
|
+ |
|
+ for (s = 0; s < SLV_COUNT; s++) |
|
+ dm_pool_free(lv->vg->cmd->mem, sfx[s]); |
|
+ |
|
+ return 1; |
|
+} |
|
+ |
|
+/* |
|
+ * HM Helper: (raid0* <-> raid4) |
|
+ * |
|
+ * Switch area LVs in lv segment @seg indexed by @s1 and @s2 |
|
+ */ |
|
+static void _switch_area_lvs(struct lv_segment *seg, uint32_t s1, uint32_t s2) |
|
+{ |
|
+ struct logical_volume *lvt; |
|
+ |
|
+ lvt = seg_lv(seg, s1); |
|
+ seg_lv(seg, s1) = seg_lv(seg, s2); |
|
+ seg_lv(seg, s2) = lvt; |
|
+ |
|
+ /* Be cautious */ |
|
+ if (seg->meta_areas) { |
|
+ lvt = seg_metalv(seg, s1); |
|
+ seg_metalv(seg, s1) = seg_metalv(seg, s2); |
|
+ seg_metalv(seg, s2) = lvt; |
|
+ } |
|
+} |
|
+ |
|
+/* |
|
+ * HM Helper: |
|
+ * |
|
+ * shift range of area LVs in @seg in range [ @s1, @s2 ] up if @s1 < @s2, |
|
+ * else down bubbling the parity SubLVs up/down whilst shifting. |
|
+ */ |
|
+static void _shift_area_lvs(struct lv_segment *seg, uint32_t s1, uint32_t s2) |
|
+{ |
|
+ uint32_t s; |
|
+ |
|
+ if (s1 < s2) |
|
+ /* Forward shift n+1 -> n */ |
|
+ for (s = s1; s < s2; s++) |
|
+ _switch_area_lvs(seg, s, s + 1); |
|
+ else |
|
+ /* Reverse shift n-1 -> n */ |
|
+ for (s = s1; s > s2; s--) |
|
+ _switch_area_lvs(seg, s, s - 1); |
|
+} |
|
+ |
|
+/* |
|
+ * Switch position of first and last area lv within |
|
+ * @lv to move parity SubLVs from end to end. |
|
+ * |
|
+ * Direction depends on segment type raid4 / raid0_meta. |
|
+ */ |
|
+static int _shift_parity_dev(struct lv_segment *seg) |
|
+{ |
|
+ if (seg_is_raid0_meta(seg)) |
|
+ _shift_area_lvs(seg, seg->area_count - 1, 0); |
|
+ else if (seg_is_raid4(seg)) |
|
+ _shift_area_lvs(seg, 0, seg->area_count - 1); |
|
+ else |
|
+ return 0; |
|
+ |
|
+ return 1; |
|
+} |
|
+ |
|
/* raid45 -> raid0* / striped */ |
|
static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS) |
|
{ |
|
+ int rename_sublvs = 0; |
|
struct lv_segment *seg = first_seg(lv); |
|
struct dm_list removal_lvs; |
|
|
|
@@ -2879,10 +3055,39 @@ static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS) |
|
if (!_raid_in_sync(lv)) |
|
return 0; |
|
|
|
+ if (!yes && yes_no_prompt("Are you sure you want to convert \"%s\" LV %s to \"%s\" " |
|
+ "type using all resilience? [y/n]: ", |
|
+ lvseg_name(seg), display_lvname(lv), new_segtype->name) == 'n') { |
|
+ log_error("Logical volume %s NOT converted to \"%s\"", |
|
+ display_lvname(lv), new_segtype->name); |
|
+ return 0; |
|
+ } |
|
+ if (sigint_caught()) |
|
+ return_0; |
|
+ |
|
/* Archive metadata */ |
|
if (!archive(lv->vg)) |
|
return_0; |
|
|
|
+ /* |
|
+ * raid4 (which actually gets mapped to raid5/dedicated first parity disk) |
|
+ * needs shifting of SubLVs to move the parity SubLV pair in the first area |
|
+ * to the last one before conversion to raid0[_meta]/striped to allow for |
|
+ * SubLV removal from the end of the areas arrays. |
|
+ */ |
|
+ if (seg_is_raid4(seg)) { |
|
+ /* Shift parity SubLV pair "PDD..." -> "DD...P" to be able to remove it off the end */ |
|
+ if (!_shift_parity_dev(seg)) |
|
+ return 0; |
|
+ |
|
+ if (segtype_is_any_raid0(new_segtype) && |
|
+ !(rename_sublvs = _rename_area_lvs(lv, "_"))) { |
|
+ log_error("Failed to rename %s LV %s MetaLVs", lvseg_name(seg), display_lvname(lv)); |
|
+ return 0; |
|
+ } |
|
+ |
|
+ } |
|
+ |
|
/* Remove meta and data LVs requested */ |
|
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, &removal_lvs, 0, 0)) |
|
return 0; |
|
@@ -2902,7 +3107,19 @@ static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS) |
|
|
|
seg->region_size = 0; |
|
|
|
- return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs); |
|
+ if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs)) |
|
+ return_0; |
|
+ |
|
+ if (rename_sublvs) { |
|
+ if (!_rename_area_lvs(lv, NULL)) { |
|
+ log_error("Failed to rename %s LV %s MetaLVs", lvseg_name(seg), display_lvname(lv)); |
|
+ return 0; |
|
+ } |
|
+ if (!lv_update_and_reload(lv)) |
|
+ return_0; |
|
+ } |
|
+ |
|
+ return 1; |
|
} |
|
|
|
static int _striped_to_raid0_wrapper(struct logical_volume *lv, |
|
@@ -2930,6 +3147,9 @@ static int _striped_to_raid0_wrapper(struct logical_volume *lv, |
|
static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
|
{ |
|
struct lv_segment *seg = first_seg(lv); |
|
+ struct dm_list removal_lvs; |
|
+ |
|
+ dm_list_init(&removal_lvs); |
|
|
|
if (seg_is_raid10(seg)) |
|
return _takeover_unsupported_yet(lv, new_stripes, new_segtype); |
|
@@ -2944,6 +3164,13 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
|
return 0; |
|
} |
|
|
|
+ /* FIXME: restricted to raid4 for the time being... */ |
|
+ if (!segtype_is_raid4(new_segtype)) { |
|
+ /* Can't convert striped/raid0* to e.g. raid10_offset */ |
|
+ log_error("Can't convert %s to %s", display_lvname(lv), new_segtype->name); |
|
+ return 0; |
|
+ } |
|
+ |
|
/* Archive metadata */ |
|
if (!archive(lv->vg)) |
|
return_0; |
|
@@ -2961,7 +3188,10 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
|
log_debug_metadata("Adding metadata LVs to %s", display_lvname(lv)); |
|
if (!_raid0_add_or_remove_metadata_lvs(lv, 1 /* update_and_reload */, allocate_pvs, NULL)) |
|
return 0; |
|
- } |
|
+ /* raid0_meta -> raid4 needs clearing of MetaLVs in order to avoid raid disk role cahnge issues in the kernel */ |
|
+ } else if (segtype_is_raid4(new_segtype) && |
|
+ !_clear_meta_lvs(lv)) |
|
+ return 0; |
|
|
|
/* Add the additional component LV pairs */ |
|
log_debug_metadata("Adding %" PRIu32 " component LV pair(s) to %s", new_image_count - lv_raid_image_count(lv), |
|
@@ -2969,8 +3199,9 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
|
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, NULL, 0, 1)) |
|
return 0; |
|
|
|
- if (!segtype_is_raid4(new_segtype)) { |
|
- /* Can't convert striped/raid0* to e.g. raid10_offset */ |
|
+ if (segtype_is_raid4(new_segtype) && |
|
+ (!_shift_parity_dev(seg) || |
|
+ !_rename_area_lvs(lv, "_"))) { |
|
log_error("Can't convert %s to %s", display_lvname(lv), new_segtype->name); |
|
return 0; |
|
} |
|
@@ -2987,6 +3218,14 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
|
if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, NULL)) |
|
return_0; |
|
|
|
+ if (segtype_is_raid4(new_segtype)) { |
|
+ /* We had to rename SubLVs because of collision free sgifting, rename back... */ |
|
+ if (!_rename_area_lvs(lv, NULL)) |
|
+ return 0; |
|
+ if (!lv_update_and_reload(lv)) |
|
+ return_0; |
|
+ } |
|
+ |
|
return 1; |
|
} |
|
|
|
diff --git a/test/shell/lvconvert-raid-takeover.sh b/test/shell/lvconvert-raid-takeover.sh |
|
index 19a65d3..0140e22 100644 |
|
--- a/test/shell/lvconvert-raid-takeover.sh |
|
+++ b/test/shell/lvconvert-raid-takeover.sh |
|
@@ -78,22 +78,58 @@ aux wait_for_sync $vg $lv1 |
|
# Clean up |
|
lvremove --yes $vg/$lv1 |
|
|
|
-# Create 3-way raid0 |
|
-lvcreate -y -aey --type raid0 -i 3 -L 64M -n $lv1 $vg |
|
-check lv_field $vg/$lv1 segtype "raid0" |
|
+# Create 3-way striped |
|
+lvcreate -y -aey --type striped -i 3 -L 64M -n $lv1 $vg |
|
+check lv_field $vg/$lv1 segtype "striped" |
|
check lv_field $vg/$lv1 stripes 3 |
|
echo y | mkfs -t ext4 /dev/mapper/$vg-$lv1 |
|
fsck -fn /dev/mapper/$vg-$lv1 |
|
|
|
-# Convert raid0 -> raid4 |
|
+# Create 3-way raid0 |
|
+lvcreate -y -aey --type raid0 -i 3 -L 64M -n $lv2 $vg |
|
+check lv_field $vg/$lv2 segtype "raid0" |
|
+check lv_field $vg/$lv2 stripes 3 |
|
+echo y | mkfs -t ext4 /dev/mapper/$vg-$lv2 |
|
+fsck -fn /dev/mapper/$vg-$lv2 |
|
+ |
|
+# Create 3-way raid0_meta |
|
+lvcreate -y -aey --type raid0_meta -i 3 -L 64M -n $lv3 $vg |
|
+check lv_field $vg/$lv3 segtype "raid0_meta" |
|
+check lv_field $vg/$lv3 stripes 3 |
|
+echo y | mkfs -t ext4 /dev/mapper/$vg-$lv3 |
|
+fsck -fn /dev/mapper/$vg-$lv3 |
|
+ |
|
+# Create 3-way raid4 |
|
+lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg |
|
+check lv_field $vg/$lv4 segtype "raid4" |
|
+check lv_field $vg/$lv4 stripes 4 |
|
+echo y | mkfs -t ext4 /dev/mapper/$vg-$lv4 |
|
+fsck -fn /dev/mapper/$vg-$lv4 |
|
+aux wait_for_sync $vg $lv4 |
|
+fsck -fn /dev/mapper/$vg-$lv4 |
|
+ |
|
+# Convert raid4 -> striped (correct raid4 mapping test!) |
|
+lvconvert -y --ty striped $vg/$lv4 |
|
+check lv_field $vg/$lv4 segtype "striped" |
|
+check lv_field $vg/$lv4 stripes 3 |
|
+fsck -fn /dev/mapper/$vg-$lv4 |
|
+ |
|
+# Convert striped -> raid4 |
|
lvconvert -y --ty raid4 $vg/$lv1 |
|
-lvchange --refresh $vg/$lv1 |
|
check lv_field $vg/$lv1 segtype "raid4" |
|
check lv_field $vg/$lv1 stripes 4 |
|
fsck -fn /dev/mapper/$vg-$lv1 |
|
aux wait_for_sync $vg $lv1 |
|
fsck -fn /dev/mapper/$vg-$lv1 |
|
|
|
+# Convert raid0 -> raid4 |
|
+lvconvert -y --ty raid4 $vg/$lv2 |
|
+check lv_field $vg/$lv2 segtype "raid4" |
|
+check lv_field $vg/$lv2 stripes 4 |
|
+fsck -fn /dev/mapper/$vg-$lv2 |
|
+aux wait_for_sync $vg $lv2 |
|
+fsck -fn /dev/mapper/$vg-$lv2 |
|
+ |
|
# Convert raid4 -> raid0_meta |
|
lvconvert -y --ty raid0_meta $vg/$lv1 |
|
check lv_field $vg/$lv1 segtype "raid0_meta" |
|
@@ -116,11 +152,16 @@ fsck -fn /dev/mapper/$vg-$lv1 |
|
|
|
# Convert raid0 -> raid4 |
|
lvconvert -y --ty raid4 $vg/$lv1 |
|
-lvchange --refresh $vg/$lv1 |
|
check lv_field $vg/$lv1 segtype "raid4" |
|
check lv_field $vg/$lv1 stripes 4 |
|
fsck -fn /dev/mapper/$vg-$lv1 |
|
aux wait_for_sync $vg $lv1 |
|
fsck -fn /dev/mapper/$vg-$lv1 |
|
|
|
+# Convert raid4 -> striped |
|
+lvconvert -y --ty striped $vg/$lv1 |
|
+check lv_field $vg/$lv1 segtype "striped" |
|
+check lv_field $vg/$lv1 stripes 3 |
|
+fsck -fn /dev/mapper/$vg-$lv1 |
|
+ |
|
vgremove -ff $vg |
|
diff --git a/tools/lvconvert.c b/tools/lvconvert.c |
|
index 0d2a4d1..541df72 100644 |
|
--- a/tools/lvconvert.c |
|
+++ b/tools/lvconvert.c |
|
@@ -1931,7 +1931,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
|
return 1; |
|
} |
|
goto try_new_takeover_or_reshape; |
|
- } else if (!lp->repair && !lp->replace && (!*lp->type_str || seg->segtype == lp->segtype)) { |
|
+ } else if (!lp->repair && !lp->replace && !*lp->type_str) { |
|
log_error("Conversion operation not yet supported."); |
|
return 0; |
|
} |
|
@@ -2017,28 +2017,18 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
|
return 1; |
|
} |
|
|
|
- |
|
try_new_takeover_or_reshape: |
|
- |
|
/* FIXME This needs changing globally. */ |
|
if (!arg_is_set(cmd, stripes_long_ARG)) |
|
lp->stripes = 0; |
|
|
|
- /* Only let raid4 through for now. */ |
|
- if (lp->type_str && lp->type_str[0] && lp->segtype != seg->segtype && |
|
- ((seg_is_raid4(seg) && seg_is_striped(lp) && lp->stripes > 1) || |
|
- (seg_is_striped(seg) && seg->area_count > 1 && seg_is_raid4(lp)))) { |
|
- if (!lv_raid_convert(lv, lp->segtype, lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size, |
|
- lp->region_size, lp->pvh)) |
|
- return_0; |
|
- |
|
- log_print_unless_silent("Logical volume %s successfully converted.", |
|
- display_lvname(lv)); |
|
- return 1; |
|
- } |
|
+ if (!lv_raid_convert(lv, lp->segtype, lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size, |
|
+ lp->region_size, lp->pvh)) |
|
+ return_0; |
|
|
|
- log_error("Conversion operation not yet supported."); |
|
- return 0; |
|
+ log_print_unless_silent("Logical volume %s successfully converted.", |
|
+ display_lvname(lv)); |
|
+ return 1; |
|
} |
|
|
|
static int _lvconvert_splitsnapshot(struct cmd_context *cmd, struct logical_volume *cow,
|
|
|