summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2015-11-06 14:19:47 +0100
committerHeinz Mauelshagen <heinzm@redhat.com>2015-11-06 14:19:47 +0100
commit9399e2b75abfcedc113597c34b9f16c0d3902bdb (patch)
treeabacf3b46e7875d20b83c8bba360c1f8f03c9d7f
parent1dd4629cacbab9bf3ec66e1f17c117b3c0eb170c (diff)
downloadlvm2-9399e2b75abfcedc113597c34b9f16c0d3902bdb.tar.gz
raid_manip:
fix data_copies on TAKEOVER_FN calls fix _lv_free_reshape_space() reshape_len add more possible_types conversion raid: add descriptor field to segment types to display on failing conversion merge: remove now superfluous _data_rimages_count() all: comments
-rw-r--r--lib/metadata/lv_manip.c22
-rw-r--r--lib/metadata/merge.c16
-rw-r--r--lib/metadata/metadata-exported.h2
-rw-r--r--lib/metadata/raid_manip.c320
-rw-r--r--lib/metadata/segtype.h1
-rw-r--r--lib/raid/raid.c46
-rw-r--r--tools/lvconvert.c16
7 files changed, 238 insertions, 185 deletions
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 33b9e3804..00a0d550c 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1290,11 +1290,11 @@ static int _lv_segment_add_areas(struct logical_volume *lv,
/* Return area_len for @extents based on @seg's properties (e.g. striped, ...) */
static uint32_t _seg_area_len(struct lv_segment *seg, uint32_t extents)
{
- uint32_t r;
- uint32_t stripes = seg->area_count - ((seg->area_count > 2) ? seg->segtype->parity_devs : 0);
+ /* Prevent parity_devs to be subtracted in case of 2 devs raid4/5 */
+ uint32_t r, stripes = seg->area_count - (seg->area_count > 2 ? seg->segtype->parity_devs : 0);
PFLA("lv=%s extents=%u", display_lvname(seg->lv), extents);
-PFLA("segtype=%s stripes=%u data_copies=%u", lvseg_name(seg), stripes, seg->data_copies);
+PFLA("segtype=%s seg->reshape_len=%u stripes=%u data_copies=%u", lvseg_name(seg), seg->reshape_len, stripes, seg->data_copies);
r = raid_rimage_extents(seg->segtype, extents - seg->reshape_len * stripes,
stripes, seg->data_copies ?: 1);
PFLA("area_len=%u", r);
@@ -1809,13 +1809,10 @@ PFLA("extend=%u existing_extents=%u, new_extents=%u, area_count=%u mirrors=%u st
* exists and they only want replacement drives.
*/
/* HM FIXME: avoid this overload to define the parity_count to allocate! */
-#if 0
parity_count = (area_count <= segtype->parity_devs) ? 0 : segtype->parity_devs;
- parity_count = segtype->parity_devs;
-#else
- parity_count = extend ? 0 : segtype->parity_devs;
-#endif
+
alloc_count = area_count + parity_count;
+
PFLA("alloc_count=%u parity_count=%u metadata_area_count=%u", alloc_count, parity_count, metadata_area_count);
if (segtype_is_raid(segtype) && metadata_area_count) {
/* RAID has a meta area for each device */
@@ -1866,7 +1863,7 @@ PFLA("alloc_count=%u parity_count=%u metadata_area_count=%u", alloc_count, parit
ah->mirror_logs_separate = find_config_tree_bool(cmd, allocation_mirror_logs_require_separate_pvs_CFG, NULL);
total_extents = new_extents;
-PFLA("ah->area_multiple=%u area_count=%u new_extents=%u total_extents=%u", ah->area_multiple, area_count, new_extents, total_extents);
+PFLA("ah->area_multiple=%u area_count=%u new_extents=%u total_extents=%u stripes=%u mirrors=%u", ah->area_multiple, area_count, new_extents, total_extents, stripes, mirrors);
if (segtype_is_raid(segtype)) {
#if 1
total_extents = raid_total_extents(segtype, total_extents, stripes, mirrors);
@@ -4394,14 +4391,15 @@ PFLA("recursive seg_lv(seg, %u)=%s extents=%u", s, display_lvname(lv1), extents)
mirrors = seg->data_copies;
} else {
+ area_count = seg->data_copies;
stripes = 1;
- area_count = mirrors = seg->data_copies;
+ mirrors = seg->data_copies;
}
} else
area_count = max(stripes + segtype->parity_devs, mirrors);
-PFLA("mirrors=%u stripes=%u", mirrors, stripes);
+PFLA("area_count=%u mirrors=%u stripes=%u", area_count, mirrors, stripes);
if (segtype_is_virtual(segtype))
return lv_add_virtual_segment(lv, 0u, extents, segtype);
@@ -4444,7 +4442,7 @@ PFLA("extents=%u mirrors=%u stripes=%u log_count=%u", extents, mirrors, stripes,
return 0;
}
- if (!(ah = allocate_extents(lv->vg, lv, segtype, (lv->le_count && mirrors == 1) ? area_count : stripes, mirrors,
+ 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 10d063c8f..188e4e434 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -70,20 +70,6 @@ int lv_merge_segments(struct logical_volume *lv)
if (error_count++ > ERROR_MAX) \
goto out
-/* Return number of data rimages for @seg paying attention to delta disks (reshaping) */
-static uint32_t _data_rimage_count(struct lv_segment *seg)
-{
- uint32_t r = seg->area_count - seg->segtype->parity_devs, s;
-
-#if 0
- for (s = 0; s < seg->area_count; s++)
- if (seg_type(seg, s) == AREA_LV &&
- (seg_lv(seg, s)->status & LV_RESHAPE_DELTA_DISKS_MINUS))
- r--;
-#endif
-
- return r;
-}
/*
* Verify that an LV's segments are consecutive, complete and don't overlap.
*/
@@ -155,7 +141,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
}
area_multiplier = (seg_is_striped_raid(seg) || seg_is_striped(seg)) ? seg->area_count - seg->segtype->parity_devs : 1;
- data_rimage_count = _data_rimage_count(seg);
+ data_rimage_count = seg->area_count - seg->segtype->parity_devs;
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
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index d90ebb1d4..dd9b65088 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1149,7 +1149,7 @@ int lv_raid_split_and_track(struct logical_volume *lv,
struct dm_list *splittable_pvs);
int lv_raid_merge(struct logical_volume *lv);
int lv_raid_convert(struct logical_volume *lv,
- const struct segment_type *new_segtype,
+ struct segment_type *new_segtype,
int yes, int force,
int duplicate, int unduplicate,
const int data_copies,
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index 9b7719066..d835a19c7 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -236,21 +236,13 @@ uint32_t raid_rimage_extents(const struct segment_type *segtype,
segtype_is_raid1(segtype))
return extents;
- /* Caller should ensure... */
- if (!stripes)
- stripes = 1;
-
- if (!segtype_is_raid(segtype) ||
- segtype_is_raid01(segtype))
- return extents / stripes;
-
r = extents;
if (segtype_is_any_raid10(segtype))
- /* Caller should ensure... */
- r *= data_copies ?: 1;
+ r *= (data_copies ?: 1); /* Caller should ensure data_copies > 0 */
- r = dm_div_up(r, stripes);
+ r = dm_div_up(r, (stripes ?: 1)); /* Caller should ensure stripes > 0 */
+PFLA("r=%llu", (unsigned long long) r);
return r > UINT_MAX ? 0 : (uint32_t) r;
}
@@ -538,9 +530,8 @@ static int _yes_no_conversion(const struct logical_volume *lv,
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
RETURN_IF_ZERO(new_data_copies, "new data copies");
- RETURN_IF_ZERO(new_segtype, "segment type argument");
-
- new_segtype_tmp = (struct segment_type *) new_segtype; /* Drop const */
+ RETURN_IF_ZERO((new_segtype_tmp = (struct segment_type *) new_segtype), /* Drop const */
+ "segment type argument");
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) && driver_version(NULL, 0)) {
log_error("Unable to retrieve logical volume information: aborting");
@@ -2309,8 +2300,12 @@ PFL();
RETURN_IF_LV_SEG_ZERO(lv, (seg = first_seg(lv)));
if (_reshape_len_per_dev(seg)) {
+ uint32_t total_reshape_len = _reshape_len_per_dev(seg) *
+ _data_rimages_count(seg, seg->area_count);
+
/*
* Got reshape space on request to free it.
+ *
* If it happens to be at the beginning of
* the data LVs, remap it to the end in order
* to be able to free it via lv_reduce().
@@ -2318,11 +2313,11 @@ PFL();
if (!_lv_alloc_reshape_space(lv, alloc_end, NULL))
return_0;
- /* Reset reshape length upfront lv_reduce() to allow it to set area_len ... properly */
+ /* Reset reshape length upfront lv_reduce() to allow it to set sgement len+area_len properly */
if (!_lv_set_reshape_len(lv, 0))
return 0;
- if (!lv_reduce(lv, _reshape_len_per_dev(seg) * _data_rimages_count(seg, seg->area_count)))
+ if (!lv_reduce(lv, total_reshape_len))
return_0;
seg->data_offset = 0;
@@ -2379,7 +2374,9 @@ static int _reset_flags_passed_to_kernel(struct logical_volume *lv, int *flag_cl
*flag_cleared = 0;
for (s = 0; s < seg->area_count; s++) {
- RETURN_IF_ZERO(seg_type(seg, s) == AREA_LV, "sub image lv");
+ if (seg_type(seg, s) == AREA_PV)
+ continue;
+
slv = seg_lv(seg, s);
#if 1
if (slv->status & LV_RESHAPE_DELTA_DISKS_MINUS) {
@@ -3331,11 +3328,11 @@ static int _striped_to_raid0_move_segs_to_raid0_lvs(struct logical_volume *lv,
/* Allocate a segment with one area for each segment in the striped LV */
if (!(seg_new = alloc_lv_segment(segtype, dlv,
- le, seg_from->area_len - seg_from->reshape_len,
- seg_from->reshape_len, status,
- seg_from->stripe_size, NULL, 1 /* area_count */,
- seg_from->area_len, seg_from->data_copies,
- seg_from->chunk_size, 0 /* region_size */, 0, NULL)))
+ le, seg_from->area_len,
+ 0 /* reshape_len */, status,
+ 0 /* stripe_size */, NULL, 1 /* area_count */,
+ seg_from->area_len, 1 /* data_copies */,
+ 0 /* chunk_size */, 0 /* region_size */, 0, NULL)))
return_0;
seg_type(seg_new, 0) = AREA_UNASSIGNED;
@@ -3413,8 +3410,8 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
int alloc_metadata_devs,
int update_and_reload)
{
+ uint32_t area_count, area_len = 0, stripe_size;
struct lv_segment *seg, *raid0_seg;
- unsigned area_count;
struct segment_type *segtype;
struct dm_list data_lvs;
@@ -3427,6 +3424,12 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
return NULL;
}
+ dm_list_iterate_items(seg, &lv->segments)
+ area_len += seg->area_len;
+
+ seg = first_seg(lv);
+ stripe_size = seg->stripe_size;
+
/* Check for not (yet) supported varying area_count on multi-segment striped LVs */
if (!_lv_has_one_stripe_zone(lv)) {
log_error("Cannot convert striped LV %s with varying stripe count to raid0",
@@ -3467,9 +3470,9 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
if (!(raid0_seg = alloc_lv_segment(segtype, lv,
0 /* le */, lv->le_count /* len */,
0 /* reshape_len */, seg->status,
- seg->stripe_size, NULL /* log_lv */,
- area_count, seg->area_len,
- seg->data_copies, seg->chunk_size,
+ stripe_size, NULL /* log_lv */,
+ area_count, area_len,
+ 1 /* data_copies */, 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));
@@ -4291,20 +4294,20 @@ static struct possible_takeover_reshape_type _possible_takeover_reshape_types[]
.options = ALLOW_REGION_SIZE },
/* raid0* -> */
- { .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count > 0 */
+ { .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count = 1 */
.possible_types = SEG_RAID1,
- .current_areas = ~0U,
+ .current_areas = 1,
.options = ALLOW_DATA_COPIES|ALLOW_REGION_SIZE },
- { .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count > 0 */
+ { .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count > 1 */
.possible_types = SEG_RAID10_NEAR|SEG_RAID10_FAR,
.current_areas = ~0U,
.options = ALLOW_DATA_COPIES|ALLOW_REGION_SIZE },
- { .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count > 0 */
+ { .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count > 1 */
.possible_types = SEG_RAID4|SEG_RAID5_LS|SEG_RAID5_LA|SEG_RAID5_RS|SEG_RAID5_RA|SEG_RAID5_N|SEG_RAID6_N_6,
.current_areas = ~0U,
.options = ALLOW_REGION_SIZE },
{ .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0 striped, i.e. seg->area_count > 0 */
- .possible_types = SEG_AREAS_STRIPED,
+ .possible_types = SEG_AREAS_STRIPED|SEG_RAID0|SEG_RAID0_META,
.current_areas = ~0U,
.options = ALLOW_NONE },
@@ -4376,15 +4379,18 @@ static struct possible_takeover_reshape_type _possible_takeover_reshape_types[]
/* raid6 -> */
{ .current_types = SEG_RAID6_ZR,
- .possible_types = SEG_RAID6_NC|SEG_RAID6_NR|SEG_RAID6_N_6,
+ .possible_types = SEG_RAID6_LS_6|SEG_RAID6_LA_6|SEG_RAID6_RS_6|SEG_RAID6_RA_6| \
+ SEG_RAID6_NC|SEG_RAID6_NR|SEG_RAID6_N_6,
.current_areas = ~0U,
.options = ALLOW_STRIPE_SIZE },
{ .current_types = SEG_RAID6_NC,
- .possible_types = SEG_RAID6_NR|SEG_RAID6_ZR|SEG_RAID6_N_6,
+ .possible_types = SEG_RAID6_LS_6|SEG_RAID6_LA_6|SEG_RAID6_RS_6|SEG_RAID6_RA_6| \
+ SEG_RAID6_NR|SEG_RAID6_ZR|SEG_RAID6_N_6,
.current_areas = ~0U,
.options = ALLOW_STRIPE_SIZE },
{ .current_types = SEG_RAID6_NR,
- .possible_types = SEG_RAID6_NC|SEG_RAID6_ZR|SEG_RAID6_N_6,
+ .possible_types = SEG_RAID6_LS_6|SEG_RAID6_LA_6|SEG_RAID6_RS_6|SEG_RAID6_RA_6| \
+ SEG_RAID6_NC|SEG_RAID6_ZR|SEG_RAID6_N_6,
.current_areas = ~0U,
.options = ALLOW_STRIPE_SIZE },
{ .current_types = SEG_RAID6_LS_6,
@@ -4413,7 +4419,7 @@ static struct possible_takeover_reshape_type _possible_takeover_reshape_types[]
.current_areas = ~0U,
.options = ALLOW_STRIPE_SIZE },
{ .current_types = SEG_RAID6_N_6,
- .possible_types = SEG_AREAS_STRIPED|SEG_RAID0|SEG_RAID0_META|SEG_RAID4,
+ .possible_types = SEG_AREAS_STRIPED|SEG_RAID0|SEG_RAID0_META|SEG_RAID4|SEG_RAID5_N,
.current_areas = ~0U,
.options = ALLOW_NONE },
@@ -4463,10 +4469,12 @@ static struct possible_takeover_reshape_type *__get_possible_takeover_reshape_ty
RETURN_IF_ZERO(seg_from, "segment from argument");
+PFLA("seg_from=%s segtype_to=%s", lvseg_name(seg_from), segtype_to ? segtype_to->name : "NIL");
+
for ( ; pt->current_types; pt++) {
if ((seg_from->segtype->flags & pt->current_types) &&
(segtype_to ? (segtype_to->flags & pt->possible_types) : 1)) {
- found = 1;
+ // found = 1;
if (seg_from->area_count <= pt->current_areas)
return pt;
@@ -4570,7 +4578,7 @@ static int _log_possible_conversion_types(struct logical_volume *lv, const struc
t = 1ULL << i;
if ((t & pt->possible_types) &&
((segtype = get_segtype_from_flag(lv->vg->cmd, t))))
- log_warn("%s", segtype->name);
+ log_warn("%s%s%s", segtype->name, segtype->descr ? " -> " : "", segtype->descr);
}
log_warn("To convert to other arbitrary layouts by duplication, use \"lvconvert --duplicate ...\"");
@@ -4592,16 +4600,16 @@ static uint64_t _r5_to_r6[][2] = {
/* Return segment type flag for raid5 -> raid6 conversions */
-static uint64_t _get_r56_flag(const struct lv_segment *seg, unsigned idx1, unsigned idx2)
+static uint64_t _get_r56_flag(const struct lv_segment *seg, unsigned idx)
{
unsigned elems = ARRAY_SIZE(_r5_to_r6);
RETURN_IF_ZERO(seg, "lv segment argument");
- RETURN_IF_ZERO(idx1 != idx2, "suitable index arguments");
+ RETURN_IF_NONZERO(idx > 1, "proper index");
while (elems--)
- if (seg->segtype->flags & _r5_to_r6[elems][idx1])
- return _r5_to_r6[elems][idx2];
+ if (seg->segtype->flags & _r5_to_r6[elems][idx])
+ return _r5_to_r6[elems][!idx];
return 0;
}
@@ -4611,7 +4619,7 @@ static uint64_t _raid_seg_flag_5_to_6(const struct lv_segment *seg)
{
RETURN_IF_ZERO(seg, "lv segment argument");
- return _get_r56_flag(seg, 0, 1);
+ return _get_r56_flag(seg, 0);
}
/* Return segment type flag for raid6 -> raid5 conversions */
@@ -4619,7 +4627,8 @@ static uint64_t _raid_seg_flag_6_to_5(const struct lv_segment *seg)
{
RETURN_IF_ZERO(seg, "lv segment argument");
- return _get_r56_flag(seg, 1, 0);
+PFL();
+ return _get_r56_flag(seg, 1);
}
/******* END: raid <-> raid conversion *******/
@@ -5976,7 +5985,7 @@ TAKEOVER_HELPER_FN(_raid0_mirror)
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, (seg = first_seg(lv)), new_segtype);
if (seg->area_count != 1)
- return _error(lv, new_segtype, yes, force, 0, 0 /* data_copies */, 0, 0, NULL);
+ return _error(lv, new_segtype, yes, force, 0, 1 /* data_copies */, 0, 0, NULL);
new_image_count = new_image_count > 1 ? new_image_count : 2;
@@ -6078,7 +6087,7 @@ TAKEOVER_HELPER_FN(_mirror_raid0)
if (!_lv_is_synced(lv))
return 0;
- if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 0, 0, 0))
+ if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 1, 0, 0))
return 0;
/* Archive metadata */
@@ -6165,7 +6174,7 @@ TAKEOVER_HELPER_FN(_raid1_raid0)
return 0;
}
- if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 0, 0, 0))
+ if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 1, 0, 0))
return 0;
/* Archive metadata */
@@ -6206,7 +6215,7 @@ PFLA("new_stripes=%u new_image_count=%u", new_stripes, new_image_count);
if (!_raid_in_sync(lv))
return 0;
- if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 0, 0, 0))
+ if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 1, 0, 0))
return 0;
/* Archive metadata */
@@ -6262,7 +6271,7 @@ PFL();
if (!_raid_in_sync(lv))
return 0;
PFL();
- if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 0, 0, 0))
+ if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 1, 0, 0))
return 0;
/* Archive metadata */
@@ -6456,7 +6465,7 @@ TAKEOVER_HELPER_FN_REMOVAL_LVS(_raid10_striped_r0)
if (!_raid_in_sync(lv))
return 0;
- if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 0, 0, 0))
+ if (!_yes_no_conversion(lv, new_segtype, yes, force, new_image_count, 1, 0, 0))
return 0;
/* Archive metadata */
@@ -6627,7 +6636,7 @@ TAKEOVER_FN(_s_r0)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, 0, 0, 0))
+ if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, 1, 0, 0))
return 0;
/* Archive metadata */
@@ -6642,7 +6651,7 @@ TAKEOVER_FN(_s_r0m)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, 0, 0, 0))
+ if (!_yes_no_conversion(lv, new_segtype, yes, force, 0, 1, 0, 0))
return 0;
/* Archive metadata */
@@ -6680,7 +6689,7 @@ TAKEOVER_FN(_m_r0)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _mirror_raid0(lv, new_segtype, yes, force, 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _mirror_raid0(lv, new_segtype, yes, force, 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* mirror -> raid0_meta */
@@ -6688,7 +6697,7 @@ TAKEOVER_FN(_m_r0m)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _mirror_raid0(lv, new_segtype, yes, force, 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _mirror_raid0(lv, new_segtype, yes, force, 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* Mirror -> raid1 */
@@ -6716,7 +6725,7 @@ TAKEOVER_FN(_m_r45)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _mirror_r45(lv, new_segtype, yes, force, 0, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _mirror_r45(lv, new_segtype, yes, force, 0, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* Mirror with 2 images -> raid10 */
@@ -6754,7 +6763,7 @@ TAKEOVER_FN(_r0_l)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _raid0_linear(lv, new_segtype, yes, force, 0, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid0_linear(lv, new_segtype, yes, force, 0, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid0 with one image -> mirror */
@@ -6762,7 +6771,7 @@ TAKEOVER_FN(_r0_m)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _raid0_mirror(lv, new_segtype, yes, force, new_image_count, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid0_mirror(lv, new_segtype, yes, force, new_image_count, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid0 -> raid0_meta */
@@ -6798,7 +6807,7 @@ TAKEOVER_FN(_r0_r1)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _raid0_raid1(lv, new_segtype, yes, force, new_image_count, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid0_raid1(lv, new_segtype, yes, force, new_image_count, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid0 -> raid4/5_n */
@@ -6806,7 +6815,7 @@ TAKEOVER_FN(_r0_r45)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _striped_raid0_raid45610(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _striped_raid0_raid45610(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid0 -> raid6_n_6 */
@@ -6814,7 +6823,7 @@ TAKEOVER_FN(_r0_r6)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _striped_raid0_raid45610(lv, new_segtype, yes, force, first_seg(lv)->area_count + 2, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _striped_raid0_raid45610(lv, new_segtype, yes, force, first_seg(lv)->area_count + 2, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid0 with N images (N > 1) -> raid10 */
@@ -6830,7 +6839,7 @@ TAKEOVER_FN(_r0m_l)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _raid0_linear(lv, new_segtype, yes, force, 0, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid0_linear(lv, new_segtype, yes, force, 0, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid0_meta -> mirror */
@@ -6838,7 +6847,7 @@ TAKEOVER_FN(_r0m_m)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _raid0_mirror(lv, new_segtype, yes, force, new_image_count, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid0_mirror(lv, new_segtype, yes, force, new_image_count, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid0_meta -> raid0 */
@@ -6878,7 +6887,7 @@ TAKEOVER_FN(_r0m_r1)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _raid0_raid1(lv, new_segtype, yes, force, new_image_count, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid0_raid1(lv, new_segtype, yes, force, new_image_count, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid0_meta -> raid4/5_n */
@@ -6886,7 +6895,7 @@ TAKEOVER_FN(_r0m_r45)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _striped_raid0_raid45610(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _striped_raid0_raid45610(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid0_meta -> raid6_n_6 */
@@ -6894,7 +6903,7 @@ TAKEOVER_FN(_r0m_r6)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _striped_raid0_raid45610(lv, new_segtype, yes, force, first_seg(lv)->area_count + 2, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _striped_raid0_raid45610(lv, new_segtype, yes, force, first_seg(lv)->area_count + 2, 1 /* data_copies */, 0, 0, allocate_pvs);
}
@@ -6962,7 +6971,7 @@ TAKEOVER_FN(_r1_r0)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _raid1_raid0(lv, new_segtype, yes, force, 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid1_raid0(lv, new_segtype, yes, force, 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid1 -> raid0_meta */
@@ -6970,14 +6979,14 @@ TAKEOVER_FN(_r1_r0m)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _raid1_raid0(lv, new_segtype, yes, force, 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid1_raid0(lv, new_segtype, yes, force, 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
TAKEOVER_FN(_r1_r1)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _raid145_raid1_raid6(lv, new_segtype, yes, force, new_image_count, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid145_raid1_raid6(lv, new_segtype, yes, force, new_image_count, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid1 with 2 legs -> raid4/5 */
@@ -6992,7 +7001,7 @@ TAKEOVER_FN(_r1_r45)
return 0;
}
- return _raid145_raid4510(lv, new_segtype, yes, force, new_image_count, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid145_raid4510(lv, new_segtype, yes, force, new_image_count, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/****************************************************************************/
@@ -7008,7 +7017,7 @@ TAKEOVER_FN(_r1_r10)
return 1;
}
-return _raid145_raid4510(lv, new_segtype, yes, force, new_image_count, 0 /* data_copies */, 0 /* stripes */, 0, allocate_pvs);
+return _raid145_raid4510(lv, new_segtype, yes, force, new_image_count, 1 /* data_copies */, 0 /* stripes */, 0, allocate_pvs);
}
/* raid45 with 2 images -> linear */
@@ -7031,7 +7040,7 @@ TAKEOVER_FN(_r45_s)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
PFL();
- return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid4/5 with 2 images -> mirror */
@@ -7039,7 +7048,7 @@ TAKEOVER_FN(_r45_m)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _mirror_r45(lv, new_segtype, yes, force, 0, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _mirror_r45(lv, new_segtype, yes, force, 0, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid4/5 -> raid0 */
@@ -7047,7 +7056,7 @@ TAKEOVER_FN(_r45_r0)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid4/5 -> raid0_meta */
@@ -7055,7 +7064,7 @@ TAKEOVER_FN(_r45_r0m)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid4 with 2 images or raid5_n with 3 images -> raid1 */
@@ -7073,7 +7082,7 @@ TAKEOVER_FN(_r45_r1)
return 0;
}
- return _raid145_raid4510(lv, new_segtype, yes, force, 2, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid145_raid4510(lv, new_segtype, yes, force, 2, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid4 <-> raid5_n */
@@ -7141,7 +7150,7 @@ TAKEOVER_FN(_r45_r6)
return_0;
}
- return _raid145_raid1_raid6(lv, new_segtype, yes, force, seg->area_count + 1, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _raid145_raid1_raid6(lv, new_segtype, yes, force, seg->area_count + 1, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid6 -> striped */
@@ -7149,7 +7158,7 @@ TAKEOVER_FN(_r6_s)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 2, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 2, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid6 -> raid0 */
@@ -7157,7 +7166,7 @@ TAKEOVER_FN(_r6_r0)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 2, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 2, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid6 -> raid0_meta */
@@ -7165,7 +7174,7 @@ TAKEOVER_FN(_r6_r0m)
{
RETURN_IF_LV_SEG_SEGTYPE_ZERO(lv, first_seg(lv), new_segtype);
- return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 2, 0 /* data_copies */, 0, 0, allocate_pvs);
+ return _r456_r0_striped(lv, new_segtype, yes, force, first_seg(lv)->area_count - 2, 1 /* data_copies */, 0, 0, allocate_pvs);
}
/* raid6* -> raid4/5* */
@@ -7210,13 +7219,7 @@ TAKEOVER_FN(_r6_r45)
if (!_lv_change_image_count(lv, new_image_count, allocate_pvs, &removal_lvs))
return 0;
- if (segtype_is_raid4(new_segtype))
- seg->segtype = new_segtype;
-
- else if(!(seg->segtype = get_segtype_from_flag(lv->vg->cmd, _raid_seg_flag_6_to_5(seg)))) {
- log_error(INTERNAL_ERROR "Failed to get raid6 -> raid5 conversion type");
- return_0;
- }
+ seg->segtype = new_segtype;
return _lv_update_and_reload_origin_eliminate_lvs(lv, &removal_lvs);
}
@@ -7244,7 +7247,7 @@ PFL();
dm_list_init(&removal_lvs);
- return _raid10_striped_r0(lv, new_segtype, yes, 0, 0, 0 /* data_copies */, 0, 0, allocate_pvs, &removal_lvs);
+ return _raid10_striped_r0(lv, new_segtype, yes, 0, 0, 1 /* data_copies */, 0, 0, allocate_pvs, &removal_lvs);
}
/* raid10 with 2 images -> mirror */
@@ -7290,7 +7293,7 @@ TAKEOVER_FN(_r10_r0)
dm_list_init(&removal_lvs);
- return _raid10_striped_r0(lv, new_segtype, yes, 0, 0, 0 /* data_copies */, 0, 0, allocate_pvs, &removal_lvs);
+ return _raid10_striped_r0(lv, new_segtype, yes, 0, 0, 1 /* data_copies */, 0, 0, allocate_pvs, &removal_lvs);
}
/* raid10 -> raid0_meta */
@@ -7302,7 +7305,7 @@ TAKEOVER_FN(_r10_r0m)
dm_list_init(&removal_lvs);
- return _raid10_striped_r0(lv, new_segtype, yes, 0, 0, 0 /* data_copies */, 0, 0, allocate_pvs, &removal_lvs);
+ return _raid10_striped_r0(lv, new_segtype, yes, 0, 0, 1 /* data_copies */, 0, 0, allocate_pvs, &removal_lvs);
}
/* raid10 with 2 images -> raid1 */
@@ -7586,75 +7589,99 @@ static int _log_prohibited_option(const struct lv_segment *seg_from,
return 1;
}
-static int _conversion_options_allowed(const struct lv_segment *seg_from,
- const struct segment_type *segtype_to,
- uint32_t new_image_count,
- int data_copies, int region_size,
- int stripes, int stripe_size)
+/* Set segtype conveniently for raid4 <-> raid5 <-> raid6 takeover */
+static int _set_convenient_raid456_segtype_to(const struct lv_segment *seg_from,
+ struct segment_type **segtype)
{
- int r = 1;
- uint32_t opts;
- const struct segment_type *new_segtype;
+ uint64_t seg_flag;
struct cmd_context *cmd;
+ struct segment_type *requested_segtype;
RETURN_IF_ZERO(seg_from, "segment from argument");
- RETURN_IF_ZERO(segtype_to, "segment type argument");
+ RETURN_IF_ZERO(segtype || *segtype, "segment type argument");
cmd = seg_from->lv->vg->cmd;
- new_segtype = segtype_to;
-
+ requested_segtype = *segtype;
+PFL();
if (seg_is_striped(seg_from) ||
seg_is_any_raid0(seg_from) ||
seg_is_raid4(seg_from)) {
+PFL();
/* If this is any raid5 conversion request -> enforce raid5_n, because we convert from striped */
- if (segtype_is_any_raid5(new_segtype) &&
- !segtype_is_raid5_n(new_segtype) &&
- !(new_segtype = get_segtype_from_flag(cmd, SEG_RAID5_N))) {
+ if (segtype_is_any_raid5(*segtype) &&
+ !segtype_is_raid5_n(*segtype) &&
+ !(*segtype = get_segtype_from_flag(cmd, SEG_RAID5_N))) {
log_error(INTERNAL_ERROR "Failed to get raid5_n segtype!");
return 0;
- }
/* If this is any raid6 conversion request -> enforce raid6_n_6, because we convert from striped */
- if (segtype_is_any_raid6(new_segtype) &&
- !segtype_is_raid6_n_6(new_segtype) &&
- !(new_segtype = get_segtype_from_flag(cmd, SEG_RAID6_N_6))) {
+ } else if (segtype_is_any_raid6(*segtype) &&
+ !segtype_is_raid6_n_6(*segtype) &&
+ !(*segtype = get_segtype_from_flag(cmd, SEG_RAID6_N_6))) {
log_error(INTERNAL_ERROR "Failed to get raid6_n_6 segtype!");
return 0;
}
/* Got to do check for raid5 -> raid6 ... */
} else if (seg_is_any_raid5(seg_from) &&
- segtype_is_any_raid6(new_segtype) &&
- !(new_segtype = get_segtype_from_flag(cmd, _raid_seg_flag_5_to_6(seg_from)))) {
+ segtype_is_any_raid6(*segtype) &&
+ (!(seg_flag = _raid_seg_flag_5_to_6(seg_from)) ||
+ !(*segtype = get_segtype_from_flag(cmd, seg_flag)))) {
log_error(INTERNAL_ERROR "Failed to get raid5 -> raid6 conversion type");
return_0;
/* ... and raid6 -> raid5 */
} else if (seg_is_any_raid6(seg_from) &&
- segtype_is_any_raid5(new_segtype) &&
- !(new_segtype = get_segtype_from_flag(cmd, _raid_seg_flag_6_to_5(seg_from)))) {
+ segtype_is_any_raid5(*segtype) &&
+ (!(seg_flag = _raid_seg_flag_6_to_5(seg_from)) ||
+ !(*segtype = get_segtype_from_flag(cmd, seg_flag)))) {
log_error(INTERNAL_ERROR "Failed to get raid6 -> raid5 conversion type");
return_0;
}
- if (!_get_allowed_conversion_options(seg_from, new_segtype, new_image_count, &opts))
+ if (requested_segtype != *segtype)
+ log_warn("Replaced requested segment type %s with %s for LV %s to allow for takeover",
+ requested_segtype->name, (*segtype)->name, display_lvname(seg_from->lv));
+
+ return 1;
+}
+
+/* Check allowed conversion from @seg_from to @segtype_to */
+static int _conversion_options_allowed(const struct lv_segment *seg_from,
+ struct segment_type **segtype_to,
+ uint32_t new_image_count,
+ int data_copies, int region_size,
+ int stripes, int stripe_size)
+{
+ int r = 1;
+ uint32_t opts;
+
+ RETURN_IF_ZERO(seg_from, "segment from argument");
+ RETURN_IF_ZERO(segtype_to || *segtype_to, "segment type to argument");
+PFL();
+ if (!_set_convenient_raid456_segtype_to(seg_from, segtype_to))
return 0;
+PFLA("seg_from->segtype=%s segtype_to=%s", lvseg_name(seg_from), (*segtype_to)->name);
- if (data_copies && !(opts & ALLOW_DATA_COPIES)) {
- if (!_log_prohibited_option(seg_from, new_segtype, "-m/--mirrors"))
+ if (!_get_allowed_conversion_options(seg_from, *segtype_to, new_image_count, &opts))
+ return 0;
+PFLA("segtype_to=%s", (*segtype_to)->name);
+
+ if (data_copies > 1 && !(opts & ALLOW_DATA_COPIES)) {
+ if (!_log_prohibited_option(seg_from, *segtype_to, "-m/--mirrors"))
return 0;
r = 0;
}
if (stripes && !(opts & ALLOW_STRIPES)) {
- if (!_log_prohibited_option(seg_from, new_segtype, "--stripes"))
+ if (!_log_prohibited_option(seg_from, *segtype_to, "--stripes"))
return 0;
r = 0;
}
if (stripe_size && !(opts & ALLOW_STRIPE_SIZE)) {
- if (!_log_prohibited_option(seg_from, new_segtype, "-I/--stripesize"))
+ if (!_log_prohibited_option(seg_from, *segtype_to, "-I/--stripesize"))
return 0;
r = 0;
}
@@ -7716,10 +7743,10 @@ static int _conversion_options_allowed(const struct lv_segment *seg_from,
* in order to avoid bio_endio in the targets map method?
*/
int lv_raid_convert(struct logical_volume *lv,
- const struct segment_type *new_segtype,
+ struct segment_type *new_segtype,
int yes, int force,
int duplicate, int unduplicate,
- const int new_data_copies,
+ const int new_data_copies, /* to be able to detect -m0; -1 if not set */
const unsigned new_region_size,
const unsigned new_stripes,
const unsigned new_stripe_size,
@@ -7728,16 +7755,15 @@ int lv_raid_convert(struct logical_volume *lv,
{
uint32_t image_count, data_copies, region_size, stripes, stripe_size;
struct lv_segment *seg;
- struct segment_type *new_segtype_tmp = (struct segment_type *) new_segtype;;
struct segment_type *striped_segtype;
struct dm_list removal_lvs;
takeover_fn_t tfn;
RETURN_IF_ZERO(lv, "lv argument");
- /* new_segtype may be NULL */
+ /* new_segtype may be NAUGHT */
+ RETURN_IF_ZERO((seg = first_seg(lv)), "lv segment");
dm_list_init(&removal_lvs);
- seg = first_seg(lv);
if (duplicate && unduplicate) {
log_error("--duplicate and --unduplicate are mutually exclusive!");
@@ -7750,7 +7776,28 @@ int lv_raid_convert(struct logical_volume *lv,
}
if (!unduplicate) {
- new_segtype = new_segtype ?: seg->segtype;
+PFL();
+ /* If we don't unduplicate, define new_segtype if not passed in */
+ if (!new_segtype) {
+ struct lv_segment *seg1;
+
+ if (_lv_is_duplicating(lv)) {
+ RETURN_IF_ZERO(seg_type(seg, 0) == AREA_LV &&
+ seg_lv(seg, 0) &&
+ first_seg(seg_lv(seg, 0)),
+ "sub lv #0");
+PFL();
+ seg1 = first_seg(seg_lv(seg, 0));
+ } else
+ seg1 = seg;
+
+ new_segtype = (struct segment_type *) seg1->segtype;
+#if 0
+ stripes = new_stripes ?: _data_rimages_count(seg1, seg1->area_count);
+ stripe_size = new_stripe_size ?: seg1->stripe_size;
+ data_copies = new_data_copies > -1 ? new_data_copies : seg1->data_copies;
+#endif
+ }
if (!(striped_segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
@@ -7774,9 +7821,10 @@ PFLA("new_segtype=%s segtype=%s, seg->area_count=%u", new_segtype ? new_segtype-
/* Define if not passed in */
region_size = new_region_size ?: seg->region_size;
- data_copies = new_data_copies > -1 ? new_data_copies + 1 : seg->data_copies;
+ data_copies = new_data_copies > -1 ? new_data_copies : seg->data_copies;
- if (!seg_is_linear(seg) &&
+ if (new_segtype &&
+ !seg_is_linear(seg) &&
(segtype_is_striped(new_segtype) ||
segtype_is_striped_raid(new_segtype))) {
stripes = new_stripes ?: _data_rimages_count(seg, seg->area_count);
@@ -7828,8 +7876,22 @@ PFLA("new_segtype=%s image_count=%u data_copies=%u stripes=%u", new_segtype ? ne
*/
if (unduplicate) {
if (_lv_is_duplicating(lv)) {
+ if (new_segtype) {
+ stripes = new_stripes;
+ stripe_size = new_stripe_size;
+ data_copies = new_data_copies > -1 ? new_data_copies : 1;
+
+ } else {
+ struct lv_segment *sseg = first_seg(seg_lv(seg, 0));
+
+ new_segtype = (struct segment_type *) sseg->segtype;
+ stripes = new_stripes ?: _data_rimages_count(sseg, sseg->area_count);
+ stripe_size = new_stripe_size ?: sseg->stripe_size;
+ data_copies = new_data_copies > -1 ? new_data_copies : sseg->data_copies;
+ }
+
if (!_raid_conv_unduplicate(lv, new_segtype,
- new_stripes, new_stripe_size, data_copies, yes)) {
+ stripes, stripe_size, data_copies, yes)) {
if (!_lv_is_duplicating(lv))
_log_possible_conversion_types(lv, new_segtype);
@@ -7848,9 +7910,9 @@ PFLA("new_segtype=%s image_count=%u data_copies=%u stripes=%u", new_segtype ? ne
*
* reshape of capable raid type requested
*/
- new_segtype = new_segtype ?: seg->segtype;
+ new_segtype = new_segtype ?: (struct segment_type *) seg->segtype;
- switch (_reshape_requested(lv, new_segtype_tmp ?: seg->segtype, new_stripes, new_stripe_size)) {
+ switch (_reshape_requested(lv, new_segtype, new_stripes, new_stripe_size)) {
case 0:
break;
case 1:
@@ -7885,7 +7947,7 @@ PFLA("yes=%d new_segtype=%s data_copies=%u stripes=%u stripe_size=%u", yes, new_
*/
if (duplicate) {
/* Check valid options mirrors, stripes and/or stripe_size have been provided suitable to the conversion */
- if (!_conversion_options_allowed(seg, new_segtype, image_count /* duplicate check for image_count > 0 */,
+ if (!_conversion_options_allowed(seg, &new_segtype, image_count /* duplicate check for image_count > 0 */,
new_data_copies, new_region_size,
new_stripes, new_stripe_size))
return _log_possible_conversion_types(lv, new_segtype);
@@ -7909,7 +7971,7 @@ PFLA("yes=%d new_segtype=%s data_copies=%u stripes=%u stripe_size=%u", yes, new_
* Check acceptible options mirrors, region_size,
* stripes and/or stripe_size have been provided.
*/
- if (!_conversion_options_allowed(seg, new_segtype, 0 /* Takeover */,
+ if (!_conversion_options_allowed(seg, &new_segtype, 0 /* Takeover */,
data_copies, new_region_size,
new_stripes, new_stripe_size))
return _log_possible_conversion_types(lv, new_segtype);
@@ -7929,7 +7991,7 @@ err:
/* FIXME: enhance message */
log_error("Converting the segment type for %s (directly) from %s to %s"
" is not supported.", display_lvname(lv),
- lvseg_name(seg), new_segtype_tmp->name);
+ lvseg_name(seg), new_segtype->name);
return 0;
}
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index c76a411df..5875fd723 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -119,6 +119,7 @@ struct segment_type {
struct segtype_handler *ops;
const char *name;
+ const char *descr;
void *library; /* lvm_register_segtype() sets this. */
void *private; /* For the segtype handler to use. */
diff --git a/lib/raid/raid.c b/lib/raid/raid.c
index e75d1e55e..7939b5e02 100644
--- a/lib/raid/raid.c
+++ b/lib/raid/raid.c
@@ -494,31 +494,32 @@ static const struct raid_type {
const char name[19];
unsigned parity;
uint64_t extra_flags;
+ const char *descr; /* HM FIXME: use segtype flags instead and display based on them */
} _raid_types[] = {
- { SEG_TYPE_NAME_RAID0, 0, SEG_RAID0 },
- { SEG_TYPE_NAME_RAID0_META, 0, SEG_RAID0_META },
- { SEG_TYPE_NAME_RAID1, 0, SEG_RAID1 | SEG_AREAS_MIRRORED },
+ { SEG_TYPE_NAME_RAID0, 0, SEG_RAID0, "striped/raid4/raid5/raid6" },
+ { SEG_TYPE_NAME_RAID0_META, 0, SEG_RAID0_META, "striped/raid4/raid5/raid6" },
+ { SEG_TYPE_NAME_RAID1, 0, SEG_RAID1 | SEG_AREAS_MIRRORED, "linear/raid4(2)/raid5(2)/raid10" },
{ SEG_TYPE_NAME_RAID01, 0, SEG_RAID01 | SEG_AREAS_MIRRORED },
- { SEG_TYPE_NAME_RAID10_NEAR, 0, SEG_RAID10_NEAR | SEG_AREAS_MIRRORED },
- { SEG_TYPE_NAME_RAID10_FAR, 0, SEG_RAID10_FAR | SEG_AREAS_MIRRORED | SEG_CAN_SPLIT },
+ { SEG_TYPE_NAME_RAID10_NEAR, 0, SEG_RAID10_NEAR | SEG_AREAS_MIRRORED, "raid1?" },
+ { SEG_TYPE_NAME_RAID10_FAR, 0, SEG_RAID10_FAR | SEG_AREAS_MIRRORED | SEG_CAN_SPLIT, "striped/raid0" },
{ SEG_TYPE_NAME_RAID10_OFFSET, 0, SEG_RAID10_OFFSET | SEG_AREAS_MIRRORED },
- { SEG_TYPE_NAME_RAID10, 0, SEG_RAID10 | SEG_AREAS_MIRRORED }, /* is raid10_near" */
- { SEG_TYPE_NAME_RAID4, 1, SEG_RAID4 },
- { SEG_TYPE_NAME_RAID5_N, 1, SEG_RAID5_N },
- { SEG_TYPE_NAME_RAID5_LA, 1, SEG_RAID5_LA },
- { SEG_TYPE_NAME_RAID5_LS, 1, SEG_RAID5_LS },
- { SEG_TYPE_NAME_RAID5_RA, 1, SEG_RAID5_RA },
- { SEG_TYPE_NAME_RAID5_RS, 1, SEG_RAID5_RS },
- { SEG_TYPE_NAME_RAID5, 1, SEG_RAID5 }, /* is raid5_ls */
- { SEG_TYPE_NAME_RAID6_NC, 2, SEG_RAID6_NC },
- { SEG_TYPE_NAME_RAID6_NR, 2, SEG_RAID6_NR },
- { SEG_TYPE_NAME_RAID6_ZR, 2, SEG_RAID6_ZR },
- { SEG_TYPE_NAME_RAID6_LA_6, 2, SEG_RAID6_LA_6 },
- { SEG_TYPE_NAME_RAID6_LS_6, 2, SEG_RAID6_LS_6 },
- { SEG_TYPE_NAME_RAID6_RA_6, 2, SEG_RAID6_RA_6 },
- { SEG_TYPE_NAME_RAID6_RS_6, 2, SEG_RAID6_RS_6 },
- { SEG_TYPE_NAME_RAID6_N_6, 2, SEG_RAID6_N_6 },
- { SEG_TYPE_NAME_RAID6, 2, SEG_RAID6 }, /* is raid6_zr */
+ { SEG_TYPE_NAME_RAID10, 0, SEG_RAID10 | SEG_AREAS_MIRRORED /* is raid10_near */, "raid1(!(stripes%mirrors)" },
+ { SEG_TYPE_NAME_RAID4, 1, SEG_RAID4, "striped/raid0*/raid5/raid6" },
+ { SEG_TYPE_NAME_RAID5_N, 1, SEG_RAID5_N, "raid0/striped/raid4/raid6" },
+ { SEG_TYPE_NAME_RAID5_LA, 1, SEG_RAID5_LA, "raid5*/raid6" },
+ { SEG_TYPE_NAME_RAID5_LS, 1, SEG_RAID5_LS, "raid5*/raid6" },
+ { SEG_TYPE_NAME_RAID5_RA, 1, SEG_RAID5_RA, "raid5*/raid6" },
+ { SEG_TYPE_NAME_RAID5_RS, 1, SEG_RAID5_RS, "raid5*/raid6" },
+ { SEG_TYPE_NAME_RAID5, 1, SEG_RAID5 /* is raid5_ls */, "raid5*/raid6" },
+ { SEG_TYPE_NAME_RAID6_NC, 2, SEG_RAID6_NC, "raid6*" },
+ { SEG_TYPE_NAME_RAID6_NR, 2, SEG_RAID6_NR, "raid6*" },
+ { SEG_TYPE_NAME_RAID6_ZR, 2, SEG_RAID6_ZR, "raid6*" },
+ { SEG_TYPE_NAME_RAID6_LA_6, 2, SEG_RAID6_LA_6, "raid5/raid6*" },
+ { SEG_TYPE_NAME_RAID6_LS_6, 2, SEG_RAID6_LS_6, "raid5/raid6*" },
+ { SEG_TYPE_NAME_RAID6_RA_6, 2, SEG_RAID6_RA_6, "raid5/raid6*" },
+ { SEG_TYPE_NAME_RAID6_RS_6, 2, SEG_RAID6_RS_6, "raid5/raid6*" },
+ { SEG_TYPE_NAME_RAID6_N_6, 2, SEG_RAID6_N_6, "striped/raid0*/raid5/raid6*" },
+ { SEG_TYPE_NAME_RAID6, 2, SEG_RAID6 /* is raid6_zr */, "raid6*" },
};
static struct segment_type *_init_raid_segtype(struct cmd_context *cmd,
@@ -535,6 +536,7 @@ static struct segment_type *_init_raid_segtype(struct cmd_context *cmd,
segtype->ops = &_raid_ops;
segtype->name = rt->name;
+ segtype->descr = rt->descr ?: "";
segtype->flags = SEG_RAID | SEG_ONLY_EXCLUSIVE | rt->extra_flags | monitored;
segtype->parity_devs = rt->parity;
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 236ac7b8e..9878a0a20 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -1703,8 +1703,7 @@ static void _lvconvert_raid_repair_ask(struct cmd_context *cmd,
static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *lp)
{
- int replace = 0, image_count = 0;
- uint32_t data_copies;
+ int data_copies, image_count = 0, replace = 0;
struct dm_list *failed_pvs;
struct cmd_context *cmd = lv->vg->cmd;
struct lv_segment *seg = first_seg(lv);
@@ -1761,6 +1760,7 @@ PFLA("image_count=%u\n", image_count);
arg_is_set(cmd, mirrors_ARG) ||
arg_is_set(cmd, stripes_long_ARG) ||
arg_is_set(cmd, stripesize_ARG) ||
+ arg_is_set(cmd, duplicate_ARG) ||
arg_is_set(cmd, unduplicate_ARG))) {
unsigned stripes = 0;
unsigned stripe_size = arg_count(cmd, stripesize_ARG) ? lp->stripe_size : 0;
@@ -1813,12 +1813,16 @@ PFLA("image_count=%u\n", image_count);
}
data_copies = stripes = 1;
stripe_size = 0;
- }
- return lv_raid_convert(lv, arg_count(cmd, type_ARG) ? lp->segtype : NULL, lp->yes, lp->force,
+ } else
+ data_copies = arg_is_set(cmd, mirrors_ARG) ? lp->mirrors : -1;
+
+ return lv_raid_convert(lv, arg_count(cmd, type_ARG) ? (struct segment_type *) lp->segtype : NULL,
+ lp->yes, lp->force,
arg_is_set(cmd, duplicate_ARG), arg_is_set(cmd, unduplicate_ARG),
- arg_is_set(cmd, mirrors_ARG) ? lp->mirrors : -1, lp->region_size,
- stripes, stripe_size, lp->pool_data_name, lp->pvh);
+ data_copies, lp->region_size,
+ stripes, stripe_size,
+ lp->pool_data_name, lp->pvh);
}
if (arg_count(cmd, replace_ARG))