From 9399e2b75abfcedc113597c34b9f16c0d3902bdb Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Fri, 6 Nov 2015 14:19:47 +0100 Subject: [PATCH] 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 --- lib/metadata/lv_manip.c | 22 +-- lib/metadata/merge.c | 16 +- lib/metadata/metadata-exported.h | 2 +- lib/metadata/raid_manip.c | 322 ++++++++++++++++++------------- lib/metadata/segtype.h | 1 + lib/raid/raid.c | 46 ++--- tools/lvconvert.c | 16 +- 7 files changed, 239 insertions(+), 186 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)) - return 0; + 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; +} - if (data_copies && !(opts & ALLOW_DATA_COPIES)) { - if (!_log_prohibited_option(seg_from, new_segtype, "-m/--mirrors")) +/* 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 (!_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))