From d67ac7ed5cf1c91944f7223269958bc7d7b54b5e Mon Sep 17 00:00:00 2001 From: Jonathan Earl Brassow Date: Tue, 11 Jan 2011 17:05:08 +0000 Subject: [PATCH] Add disk to mirrored log type conversion. --- WHATS_NEW | 1 + lib/metadata/lv_manip.c | 3 +-- lib/metadata/mirror.c | 38 ++++++++++++++++++++++++------ test/t-lvconvert-mirror-basic.sh | 6 ----- test/t-lvconvert-repair-policy.sh | 3 ++- test/t-lvconvert-repair-replace.sh | 30 +++++++++++++++++++++++ test/t-lvconvert-repair.sh | 17 +++++++++++++ test/t-lvconvert-twostep.sh | 5 ++++ tools/lvconvert.c | 26 ++++++++++---------- tools/lvcreate.c | 2 -- 10 files changed, 101 insertions(+), 30 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 696d05e05..c5dfcc7de 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.81 - =================================== + Add disk to mirrored log type conversion. Version 2.02.80 - 10th January 2011 =================================== diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index e19d59df3..5f79994b0 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -1557,8 +1557,7 @@ struct alloc_handle *allocate_extents(struct volume_group *vg, parallel_areas))) return_NULL; - if (!segtype_is_virtual(segtype) && - !_allocate(ah, vg, lv, 1, allocatable_pvs)) { + if (!_allocate(ah, vg, lv, 1, allocatable_pvs)) { alloc_destroy(ah); return_NULL; } diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c index 1be07cfd1..a45bfe6cb 100644 --- a/lib/metadata/mirror.c +++ b/lib/metadata/mirror.c @@ -1295,7 +1295,7 @@ static int _create_mimage_lvs(struct alloc_handle *ah, struct logical_volume **img_lvs, int log) { - uint32_t m; + uint32_t m, first_area; char *img_name; size_t len; @@ -1322,10 +1322,13 @@ static int _create_mimage_lvs(struct alloc_handle *ah, } if (log) { - if (!lv_add_log_segment(ah, m * stripes + 1, img_lvs[m], 0)) { - log_error("Aborting. Failed to add mirror image segment " - "to %s. Remove new LV and retry.", - img_lvs[m]->name); + first_area = m * stripes + (log - 1); + + if (!lv_add_log_segment(ah, first_area, img_lvs[m], 0)) { + /* error msg already from lv_add_log_segment */ + log_verbose("Failed to add mirror image segment" + " to %s. Remove new LV and retry.", + img_lvs[m]->name); return 0; } } else { @@ -1760,7 +1763,7 @@ static struct logical_volume *_set_up_mirror_log(struct cmd_context *cmd, } if ((log_count > 1) && - !_form_mirror(cmd, ah, log_lv, log_count-1, 1, 0, region_size, 1)) { + !_form_mirror(cmd, ah, log_lv, log_count-1, 1, 0, region_size, 2)) { log_error("Failed to form mirrored log."); return NULL; } @@ -1792,6 +1795,7 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv, int in_sync; struct logical_volume *log_lv; struct lvinfo info; + int old_log_count; int r = 0; if (dm_list_size(&lv->segments) != 1) { @@ -1811,6 +1815,15 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv, return 0; } + log_lv = first_seg(lv)->log_lv; + old_log_count = (log_lv) ? lv_mirror_count(log_lv) : 0; + if (old_log_count == log_count) { + log_verbose("Mirror already has a %s log", + !log_count ? "core" : + (log_count == 1) ? "disk" : "mirrored"); + return 1; + } + if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv, 0))) return_0; @@ -1826,13 +1839,24 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv, /* allocate destination extents */ ah = allocate_extents(lv->vg, NULL, segtype, - 0, 0, log_count, region_size, 0, + 0, 0, log_count - old_log_count, region_size, 0, allocatable_pvs, alloc, parallel_areas); if (!ah) { log_error("Unable to allocate extents for mirror log."); return 0; } + if (old_log_count) { + /* Converting from disk to mirrored log */ + if (!_form_mirror(cmd, ah, log_lv, log_count - 1, 1, 0, + region_size, 1)) { + log_error("Failed to convert mirror log"); + return 0; + } + r = 1; + goto out; + } + /* check sync status */ if (lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL) && (sync_percent == PERCENT_100)) diff --git a/test/t-lvconvert-mirror-basic.sh b/test/t-lvconvert-mirror-basic.sh index 7a939f1ec..d2d43e599 100644 --- a/test/t-lvconvert-mirror-basic.sh +++ b/test/t-lvconvert-mirror-basic.sh @@ -54,12 +54,6 @@ test_lvconvert() local active=true local i - if [ "$start_log_type" = "disk" ] && - [ "$finish_log_type" = "mirrored" ]; then - echo "FIXME: disk -> mirrored log conversion not yet supported by LVM" - return 0 - fi - test "$5" = "active" && active=false #test $finish_count -gt $start_count && up=true diff --git a/test/t-lvconvert-repair-policy.sh b/test/t-lvconvert-repair-policy.sh index 947c63eaa..9ae25a48a 100644 --- a/test/t-lvconvert-repair-policy.sh +++ b/test/t-lvconvert-repair-policy.sh @@ -55,7 +55,8 @@ lvs | grep mirror_mlog cleanup $dev1 # Fail a leg of a mirror w/ no available spare -# Expected result: 2-way with corelog +# Expected result: linear +# (or 2-way with leg/log overlap if alloc anywhere) aux disable_dev $dev2 $dev4 repair 'activation { mirror_image_fault_policy = "replace" }' check mirror $vg mirror diff --git a/test/t-lvconvert-repair-replace.sh b/test/t-lvconvert-repair-replace.sh index 9b23a8284..1a0bdebdc 100644 --- a/test/t-lvconvert-repair-replace.sh +++ b/test/t-lvconvert-repair-replace.sh @@ -13,6 +13,7 @@ aux prepare_vg 6 +# 3-way, disk log # multiple failures, full replace lvcreate --mirrorlog disk -m 2 --ig -L 1 -n 3way $vg $dev1 $dev2 $dev3 $dev4:0-1 aux disable_dev $dev1 $dev2 @@ -23,8 +24,37 @@ vgreduce --removemissing $vg check mirror $vg 3way aux enable_dev $dev1 $dev2 +vgremove -ff $vg; vgcreate -c n $vg $dev1 $dev2 $dev3 $dev4 $dev5 $dev6 + +# 2-way, mirrored log +# Double log failure, full replace +lvcreate --mirrorlog mirrored -m 1 --ig -L 1 -n 2way $vg \ + $dev1 $dev2 $dev3:0 $dev4:0 +aux disable_dev $dev3 $dev4 +echo y | lvconvert --repair $vg/2way 2>&1 | tee 2way.out +lvs -a -o +devices | not grep unknown +not grep "WARNING: Failed" 2way.out +vgreduce --removemissing $vg +check mirror $vg 2way +aux enable_dev $dev3 $dev4 + +vgremove -ff $vg; vgcreate -c n $vg $dev1 $dev2 $dev3 $dev4 $dev5 $dev6 + +# 3-way, mirrored log +# Single log failure, replace +lvcreate --mirrorlog mirrored -m 2 --ig -L 1 -n 3way $vg \ + $dev1 $dev2 $dev3 $dev4:0 $dev5:0 +aux disable_dev $dev4 +echo y | lvconvert --repair $vg/3way 2>&1 | tee 3way.out +lvs -a -o +devices | not grep unknown +not grep "WARNING: Failed" 3way.out +vgreduce --removemissing $vg +check mirror $vg 3way +aux enable_dev $dev4 + vgremove -ff $vg; vgcreate -c n $vg $dev1 $dev2 $dev3 $dev4 $dev5 +# 3-way, disk log # multiple failures, partial replace lvcreate --mirrorlog disk -m 2 --ig -L 1 -n 3way $vg $dev1 $dev2 $dev3 $dev4 aux disable_dev $dev1 $dev2 diff --git a/test/t-lvconvert-repair.sh b/test/t-lvconvert-repair.sh index c27a9a027..635e4c8ba 100644 --- a/test/t-lvconvert-repair.sh +++ b/test/t-lvconvert-repair.sh @@ -14,6 +14,7 @@ # fail multiple devices +# 4-way, disk log => 2-way, disk log aux prepare_vg 5 lvcreate -m 3 --ig -L 1 -n 4way $vg $dev1 $dev2 $dev3 $dev4 $dev5:0 aux disable_dev $dev2 $dev4 @@ -23,6 +24,7 @@ vgreduce --removemissing $vg aux enable_dev $dev2 $dev4 check mirror $vg 4way $dev5 +# 3-way, disk log => linear aux prepare_vg 5 lvcreate -m 2 --ig -L 1 -n 3way $vg aux disable_dev $dev1 $dev2 @@ -37,6 +39,7 @@ check linear $vg 3way # fail just log and get it removed +# 3-way, disk log => 3-way, core log aux prepare_vg 5 lvcreate -m 2 --ig -L 1 -n 3way $vg $dev1 $dev2 $dev3 $dev4:0 aux disable_dev $dev4 @@ -48,6 +51,20 @@ dmsetup ls | grep $PREFIX | not grep mlog vgreduce --removemissing $vg aux enable_dev $dev4 +# 3-way, mirrored log => 3-way, core log +aux prepare_vg 5 +lvcreate -m 2 --mirrorlog mirrored --ig -L 1 -n 3way $vg \ + $dev1 $dev2 $dev3 $dev4:0 $dev5:0 +aux disable_dev $dev4 $dev5 +echo n | lvconvert --repair $vg/3way +check mirror $vg 3way core +lvs -a -o +devices | not grep unknown +lvs -a -o +devices | not grep mlog +dmsetup ls | grep $PREFIX | not grep mlog +vgreduce --removemissing $vg +aux enable_dev $dev4 $dev5 + +# 2-way, disk log => 2-way, core log aux prepare_vg 5 lvcreate -m 1 --ig -L 1 -n 2way $vg $dev1 $dev2 $dev3:0 aux disable_dev $dev3 diff --git a/test/t-lvconvert-twostep.sh b/test/t-lvconvert-twostep.sh index f9425cc4b..7e65ff9f9 100644 --- a/test/t-lvconvert-twostep.sh +++ b/test/t-lvconvert-twostep.sh @@ -12,10 +12,15 @@ . lib/test aux prepare_vg 4 + lvcreate -m 1 --mirrorlog disk --ig -L 1 -n mirror $vg not lvconvert -m 2 --mirrorlog core $vg/mirror $dev3 2>&1 | tee errs grep "two steps" errs + lvconvert -m 2 $vg/mirror $dev3 lvconvert --mirrorlog core $vg/mirror not lvconvert -m 1 --mirrorlog disk $vg/mirror $dev3 2>&1 | tee errs grep "two steps" errs + +not lvconvert -m 1 --mirrorlog mirrored $vg/mirror $dev3 $dev4 2>&1 | tee errs +grep "two steps" errs diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 9ae5f7a2a..40558e989 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -718,6 +718,7 @@ static int _lv_update_mirrored_log(struct logical_volume *lv, operable_pvs, 0U); } +static int _reload_lv(struct cmd_context *cmd, struct logical_volume *lv); static int _lv_update_log_type(struct cmd_context *cmd, struct lvconvert_params *lp, struct logical_volume *lv, @@ -738,14 +739,6 @@ static int _lv_update_log_type(struct cmd_context *cmd, lv->le_count, lp->region_size); - /* Add a log where there is none */ - if (!old_log_count) { - if (!add_mirror_log(cmd, original_lv, log_count, - region_size, operable_pvs, lp->alloc)) - return_0; - return 1; - } - /* Remove an existing log completely */ if (!log_count) { if (!remove_mirror_log(cmd, original_lv, operable_pvs, @@ -759,9 +752,17 @@ static int _lv_update_log_type(struct cmd_context *cmd, /* Adding redundancy to the log */ if (old_log_count < log_count) { - log_error("Adding log redundancy not supported yet."); - log_error("Try converting the log to 'core' first."); - return_0; + if (!add_mirror_log(cmd, original_lv, log_count, + region_size, operable_pvs, lp->alloc)) + return_0; + /* + * FIXME: This simple approach won't work in cluster mirrors, + * but it doesn't matter because we don't support + * mirrored logs in cluster mirrors. + */ + if (old_log_count) + return _reload_lv(cmd, log_lv); + return 1; } /* Reducing redundancy of the log */ @@ -1109,7 +1110,8 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd, /* FIXME: can't have multiple mlogs. force corelog. */ if (!lv_add_mirrors(cmd, lv, - new_mimage_count - old_mimage_count, lp->stripes, lp->stripe_size, + new_mimage_count - old_mimage_count, + lp->stripes, lp->stripe_size, region_size, 0U, operable_pvs, lp->alloc, MIRROR_BY_LV)) { layer_lv = seg_lv(first_seg(lv), 0); diff --git a/tools/lvcreate.c b/tools/lvcreate.c index 13b592659..701641715 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -538,8 +538,6 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv) struct lvcreate_cmdline_params lcp; struct volume_group *vg; - memset(&lp, 0, sizeof(lp)); - if (!_lvcreate_params(&lp, &lcp, cmd, argc, argv)) return EINVALID_CMD_LINE; -- 2.43.5