1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-10 16:58:47 +03:00

lvconvert: add infrastructure for RaidLV reshaping support

In order to support striped raid5/6/10 LV reshaping (change
of LV type, stripesize or number of legs), this patch
introduces more local infrastructure to raid_manip.c
used by followup patches.

Changes:
- enhance _raid45610_to_raid0_or_striped_wrapper() to support
  raid5_n with 2 areas to raid1 conversion to allow for
  striped/raid0(_meta)/raid4/5/6 -> raid1/linear conversions;
  rename it to _takeover_downconvert_wrapper to discontinue the
  illegible function name
- enhance _striped_or_raid0_to_raid45610_wrapper()  to support
  raid1 with 2 areas to raid5* conversions to allow for
  linear/raid1 -> striped/raid0(_meta)/raid4/5/6 conversions;
  rename it to _takeover_upconvert_wrapper for the same reason

Related: rhbz834579
Related: rhbz1191935
Related: rhbz1191978
This commit is contained in:
Heinz Mauelshagen 2017-02-24 03:37:12 +01:00
parent 932db3db53
commit 34a8d3c2fd

View File

@ -4748,14 +4748,14 @@ static int _shift_parity_dev(struct lv_segment *seg)
return 1;
}
/* raid456 -> raid0* / striped */
/* raid45610 -> raid0* / stripe, raid5_n -> raid4 */
static int _raid45_to_raid54_wrapper(TAKEOVER_FN_ARGS);
static int _raid45610_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
static int _takeover_downconvert_wrapper(TAKEOVER_FN_ARGS)
{
int rename_sublvs = 0;
struct lv_segment *seg = first_seg(lv);
struct dm_list removal_lvs;
uint32_t region_size = seg->region_size;
char res_str[30];
dm_list_init(&removal_lvs);
@ -4766,10 +4766,35 @@ static int _raid45610_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
return 0;
}
if (!yes && yes_no_prompt("Are you sure you want to convert \"%s\" LV %s to \"%s\" "
"type losing %s resilience? [y/n]: ",
lvseg_name(seg), display_lvname(lv), new_segtype->name,
segtype_is_striped(new_segtype) ? "all" : "some") == 'n') {
if (seg_is_any_raid10(seg) && (seg->area_count % seg->data_copies)) {
log_error("Can't convert %s LV %s to %s with odd number of stripes.",
lvseg_name(seg), display_lvname(lv), new_segtype->name);
return 0;
}
if (seg_is_any_raid5(seg) &&
segtype_is_raid1(new_segtype)) {
if (seg->area_count != 2) {
log_error("Can't convert %s LV %s to %s with != 2 legs.",
lvseg_name(seg), display_lvname(lv), new_segtype->name);
return 0;
}
if (seg->area_count != new_image_count) {
log_error(INTERNAL_ERROR "Bogus new_image_count converting %s LV %s to %s.",
lvseg_name(seg), display_lvname(lv), new_segtype->name);
return 0;
}
}
if (seg->area_count > 2) {
if (dm_snprintf(res_str, sizeof(res_str), " losing %s resilience",
segtype_is_striped(new_segtype) ? "all" : "some") < 0)
return_0;
} else
*res_str = '\0';
if (!yes && yes_no_prompt("Are you sure you want to convert \"%s\" LV %s to \"%s\" type%s? [y/n]: ",
lvseg_name(seg), display_lvname(lv), new_segtype->name, res_str) == 'n') {
log_error("Logical volume %s NOT converted to \"%s\"",
display_lvname(lv), new_segtype->name);
return 0;
@ -4779,6 +4804,9 @@ static int _raid45610_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
if (!archive(lv->vg))
return_0;
if (!_lv_free_reshape_space(lv))
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
@ -4790,28 +4818,35 @@ static int _raid45610_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
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;
}
} else if (seg_is_raid10_near(seg)) {
log_debug_metadata("Reordering areas for raid10 -> raid0 takeover");
log_debug_metadata("Reordering areas for raid10 -> raid0 takeover.");
if (!_reorder_raid10_near_seg_areas(seg, reorder_from_raid10_near))
return 0;
}
/* Remove meta and data LVs requested */
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, &removal_lvs, 0, 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 (new_image_count != seg->area_count) {
log_debug_metadata("Removing %" PRIu32 " component LV pair(s) to %s.",
lv_raid_image_count(lv) - new_image_count,
display_lvname(lv));
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, &removal_lvs, 0, 0))
return 0;
seg->area_count = new_image_count;
}
/* FIXME Hard-coded raid4/5/6 to striped/raid0 */
if (segtype_is_striped_target(new_segtype) || segtype_is_any_raid0(new_segtype)) {
seg->area_len = seg->extents_copied = seg->area_len / seg->area_count;
seg->area_len = seg->extents_copied = seg->len / seg->area_count;
seg->region_size = 0;
if (!(seg->segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID0_META)))
return_0;
region_size = 0;
}
if (segtype_is_striped_target(new_segtype)) {
@ -4827,12 +4862,18 @@ static int _raid45610_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
} else
seg->segtype = new_segtype;
seg->region_size = new_region_size ?: region_size;
if (seg_is_raid1(seg))
seg->stripe_size = 0;
if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, 0, &removal_lvs, NULL))
return_0;
if (rename_sublvs) {
/* Got to clear the meta lvs from raid10 content to be able to convert to e.g. raid6 */
if (segtype_is_raid0_meta(new_segtype) &&
!_clear_meta_lvs(lv))
return_0;
if (!_rename_area_lvs(lv, NULL)) {
log_error("Failed to rename %s LV %s MetaLVs.", lvseg_name(seg), display_lvname(lv));
return 0;
@ -4942,8 +4983,8 @@ static int _striped_to_raid0_wrapper(struct logical_volume *lv,
return 1;
}
/* Helper: striped/raid0* -> raid4/5/6/10, raid45 -> raid6 wrapper */
static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
/* Helper: striped/raid0/raid0_meta/raid1 -> raid4/5/6/10, raid45 -> raid6 wrapper */
static int _takeover_upconvert_wrapper(TAKEOVER_FN_ARGS)
{
uint32_t extents_copied, region_size, seg_len, stripe_size;
struct lv_segment *seg = first_seg(lv);
@ -4961,10 +5002,40 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
return 0;
}
if (seg_is_any_raid5(seg) && segtype_is_any_raid6(new_segtype) && seg->area_count < 4) {
log_error("Minimum of 3 stripes needed for conversion from %s to %s.",
lvseg_name(seg), new_segtype->name);
return 0;
}
if (seg_is_raid1(seg)) {
if (seg->area_count != 2) {
log_error("Can't convert %s LV %s to %s with != 2 legs.",
lvseg_name(seg), display_lvname(lv), new_segtype->name);
return 0;
}
if (!segtype_is_any_raid5(new_segtype)) {
log_error("Can't convert %s LV %s to %s.",
lvseg_name(seg), display_lvname(lv), new_segtype->name);
return 0;
}
if (seg->area_count != new_image_count) {
log_error(INTERNAL_ERROR "Bogus new_image_count converting %s LV %s to %s.",
lvseg_name(seg), display_lvname(lv), new_segtype->name);
return 0;
}
if (!new_stripe_size)
new_stripe_size = 128;
}
/* Archive metadata */
if (!archive(lv->vg))
return_0;
if (!_lv_free_reshape_space(lv))
return_0;
/* This helper can be used to convert from striped/raid0* -> raid10 too */
if (seg_is_striped_target(seg)) {
log_debug_metadata("Converting LV %s from %s to %s.",
@ -4979,15 +5050,14 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
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 change issues in the kernel */
} else if (segtype_is_raid4(new_segtype) &&
!_clear_meta_lvs(lv))
}
if (seg_is_raid0_meta(seg) &&
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),
display_lvname(lv));
extents_copied = seg->extents_copied;
region_size = seg->region_size;
seg_len = seg->len;
@ -4998,11 +5068,21 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
return_0;
seg->area_len = seg_lv(seg, 0)->le_count;
lv->le_count = seg->len = seg->area_len * seg->area_count;
seg->area_len = seg->len;
seg->extents_copied = seg->region_size = 0;
}
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, NULL, 0, 1))
return 0;
/* Add the additional component LV pairs */
if (new_image_count != seg->area_count) {
log_debug_metadata("Adding %" PRIu32 " component LV pair(s) to %s.",
new_image_count - lv_raid_image_count(lv),
display_lvname(lv));
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, NULL, 0, 1))
return 0;
seg = first_seg(lv);
}
if (segtype_is_raid4(new_segtype) &&
(!_shift_parity_dev(seg) ||
@ -5010,25 +5090,40 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
log_error("Can't convert %s to %s.", display_lvname(lv), new_segtype->name);
return 0;
} else if (segtype_is_raid10_near(new_segtype)) {
log_debug_metadata("Reordering areas for raid0 -> raid10 takeover");
uint32_t s;
/* FIXME: raid10 ; needs to change once more than 2 data copies! */
seg->data_copies = 2;
log_debug_metadata("Reordering areas for raid0 -> raid10 takeover.");
if (!_reorder_raid10_near_seg_areas(seg, reorder_to_raid10_near))
return 0;
/* Set rebuild flags accordingly */
for (s = 0; s < seg->area_count; s++) {
seg_lv(seg, s)->status &= ~LV_REBUILD;
seg_metalv(seg, s)->status &= ~LV_REBUILD;
if (s % seg->data_copies)
seg_lv(seg, s)->status |= LV_REBUILD;
}
}
seg->segtype = new_segtype;
seg->region_size = new_region_size ?: region_size;
/* FIXME Hard-coded raid0 to raid4/5/6 */
seg->stripe_size = stripe_size;
lv->le_count = seg->len = seg->area_len = seg_len;
seg->stripe_size = new_stripe_size ?: stripe_size;
seg->extents_copied = extents_copied;
/* FIXME Hard-coded to raid4/5/6/10 */
lv->le_count = seg->len = seg->area_len = seg_len;
_check_and_adjust_region_size(lv);
log_debug_metadata("Updating VG metadata and reloading %s LV %s.",
lvseg_name(seg), display_lvname(lv));
if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, 0, NULL, NULL))
return_0;
if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, 0, &removal_lvs,
_post_raid_dummy, NULL,
_pre_raid_add_legs, NULL))
return 0;
if (segtype_is_raid4(new_segtype)) {
/* We had to rename SubLVs because of collision free shifting, rename back... */
@ -5118,23 +5213,23 @@ static int _takeover_from_raid0_to_raid1(TAKEOVER_FN_ARGS)
static int _takeover_from_raid0_to_raid10(TAKEOVER_FN_ARGS)
{
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count * 2 /* new_image_count */,
2 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count * 2 /* new_image_count */,
2 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
}
static int _takeover_from_raid0_to_raid45(TAKEOVER_FN_ARGS)
{
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 1 /* new_image_count */,
2 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 1 /* new_image_count */,
2 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
}
static int _takeover_from_raid0_to_raid6(TAKEOVER_FN_ARGS)
{
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 2 /* new_image_count */,
3 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 2 /* new_image_count */,
3 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
}
static int _takeover_from_raid0_to_striped(TAKEOVER_FN_ARGS)
@ -5170,21 +5265,21 @@ static int _takeover_from_raid0_meta_to_raid1(TAKEOVER_FN_ARGS)
static int _takeover_from_raid0_meta_to_raid10(TAKEOVER_FN_ARGS)
{
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force,
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count * 2 /* new_image_count */,
2 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
}
static int _takeover_from_raid0_meta_to_raid45(TAKEOVER_FN_ARGS)
{
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force,
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 1 /* new_image_count */,
2 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
}
static int _takeover_from_raid0_meta_to_raid6(TAKEOVER_FN_ARGS)
{
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force,
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 2 /* new_image_count */,
3 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
}
@ -5249,12 +5344,16 @@ static int _takeover_from_raid45_to_mirrored(TAKEOVER_FN_ARGS)
static int _takeover_from_raid45_to_raid0(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1, 1 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count - 1,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
}
static int _takeover_from_raid45_to_raid0_meta(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1, 1 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count - 1,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
}
static int _takeover_from_raid45_to_raid1(TAKEOVER_FN_ARGS)
@ -5278,38 +5377,44 @@ static int _takeover_from_raid45_to_raid6(TAKEOVER_FN_ARGS)
1 /* data_copies */, 0, 0, 0, allocate_pvs))
return 0;
}
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 1 /* new_image_count */,
3 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 1 /* new_image_count */,
3 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
}
static int _takeover_from_raid45_to_striped(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1, 1 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count - 1,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
}
static int _takeover_from_raid6_to_raid0(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count - 2,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count - 2,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
}
static int _takeover_from_raid6_to_raid0_meta(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count - 2,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count - 2,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
}
static int _takeover_from_raid6_to_raid45(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count - 1,
2 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count - 1,
2 /* data_copies */, 0, 0, 0, allocate_pvs);
}
static int _takeover_from_raid6_to_striped(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count - 2,
2 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count - 2,
2 /* data_copies */, 0, 0, 0, allocate_pvs);
}
static int _takeover_from_striped_to_raid0(TAKEOVER_FN_ARGS)
@ -5335,22 +5440,22 @@ static int _takeover_from_striped_to_raid0_meta(TAKEOVER_FN_ARGS)
static int _takeover_from_striped_to_raid10(TAKEOVER_FN_ARGS)
{
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count * 2 /* new_image_count */,
2 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count * 2 /* new_image_count */,
2 /* FIXME: variable data_copies */, 0, 0, new_region_size, allocate_pvs);
}
static int _takeover_from_striped_to_raid45(TAKEOVER_FN_ARGS)
{
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1,
2 /* data_copies*/, 0, 0, new_region_size, allocate_pvs);
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1,
2 /* data_copies*/, 0, 0, new_region_size, allocate_pvs);
}
static int _takeover_from_striped_to_raid6(TAKEOVER_FN_ARGS)
{
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 2 /* new_image_count */,
3 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
return _takeover_upconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count + 2 /* new_image_count */,
3 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
}
/*
@ -5384,8 +5489,9 @@ static int _takeover_from_raid10_to_mirrored(TAKEOVER_FN_ARGS)
static int _takeover_from_raid10_to_raid0(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count / 2,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count / first_seg(lv)->data_copies,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
}
/*
@ -5398,8 +5504,9 @@ static int _takeover_from_raid10_to_raid01(TAKEOVER_FN_ARGS)
static int _takeover_from_raid10_to_raid0_meta(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count / 2,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count / first_seg(lv)->data_copies,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
}
static int _takeover_from_raid10_to_raid1(TAKEOVER_FN_ARGS)
@ -5418,8 +5525,9 @@ static int _takeover_from_raid10_to_raid10(TAKEOVER_FN_ARGS)
static int _takeover_from_raid10_to_striped(TAKEOVER_FN_ARGS)
{
return _raid45610_to_raid0_or_striped_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count / 2,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
return _takeover_downconvert_wrapper(lv, new_segtype, yes, force,
first_seg(lv)->area_count / first_seg(lv)->data_copies,
1 /* data_copies */, 0, 0, 0, allocate_pvs);
}
/*