Version 2.02.81 -
===================================
+ Add disk to mirrored log type conversion.
Version 2.02.80 - 10th January 2011
===================================
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;
}
struct logical_volume **img_lvs,
int log)
{
- uint32_t m;
+ uint32_t m, first_area;
char *img_name;
size_t len;
}
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 {
}
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;
}
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) {
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;
/* 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))
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
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
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
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
# 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
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
# 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
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
. 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
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,
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,
/* 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 */
/* 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);
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;