From e37b173f13fe61efa1b9577be32d1b0fd80b3263 Mon Sep 17 00:00:00 2001 From: Jonathan Earl Brassow Date: Wed, 21 Apr 2010 13:55:08 +0000 Subject: [PATCH] Disallow the primary mirror image from being removed when the mirror is not in-sync. This restriction is not extended to repair operations (i.e. it will not limit what 'lvconvert --repair' can do). --- WHATS_NEW | 1 + lib/metadata/mirror.c | 18 ++++++++++++++---- test/t-lvconvert-mirror.sh | 14 ++++++++++++-- test/t-mirror-lvconvert.sh | 7 +++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index f1a88b719..fea72345b 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.64 - ================================= + Disallow primary mirror image removal when mirror is not in-sync. Remove obsolete --name parameter from vgcfgrestore. Add -S command to clvmd to restart the daemon preserving exclusive locks. Increment lvm2app version from 1 to 2. diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c index 1f9d38e78..3a32c4c61 100644 --- a/lib/metadata/mirror.c +++ b/lib/metadata/mirror.c @@ -751,7 +751,7 @@ static int _remove_mirror_images(struct logical_volume *lv, uint32_t *removed) { uint32_t m; - uint32_t s; + int32_t s; int removable_pvs_specified; struct logical_volume *sub_lv; struct logical_volume *detached_log_lv = NULL; @@ -781,15 +781,25 @@ static int _remove_mirror_images(struct logical_volume *lv, /* Move removable_pvs to end of array */ if (removable_pvs_specified) { - for (s = 0; s < mirrored_seg->area_count && - old_area_count - new_area_count < num_removed; s++) { + for (s = mirrored_seg->area_count - 1; + s >= 0 && old_area_count - new_area_count < num_removed; + s--) { sub_lv = seg_lv(mirrored_seg, s); if (!is_temporary_mirror_layer(sub_lv) && _is_mirror_image_removable(sub_lv, removable_pvs)) { + /* + * Check if the user is trying to pull the + * primary mirror image when the mirror is + * not in-sync. + */ + if ((s == 0) && !_mirrored_lv_in_sync(lv) && + !(lv->status & PARTIAL_LV)) { + log_error("Unable to remove primary mirror image while mirror is not in-sync"); + return_0; + } if (!shift_mirror_images(mirrored_seg, s)) return_0; - s--; /* adjust counter after shifting */ new_area_count--; } } diff --git a/test/t-lvconvert-mirror.sh b/test/t-lvconvert-mirror.sh index 419b4ede8..ed60cc2a5 100644 --- a/test/t-lvconvert-mirror.sh +++ b/test/t-lvconvert-mirror.sh @@ -61,10 +61,20 @@ lvcreate -l2 -n $lv1 $vg $dev1 not lvconvert -m+1 --mirrorlog core $vg/$lv1 $dev1 lvremove -ff $vg -lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev4 $dev3:0-1 +# Start w/ 3-way mirror +# Test pulling primary image before mirror in-sync (should fail) +# Test pulling primary image after mirror in-sync (should work) +# Test that the correct devices remain in the mirror +lvcreate -l8 -m2 -n $lv1 $vg $dev1 $dev2 $dev4 $dev3:0-1 +# FIXME: +# This is somewhat timing dependent - sync /could/ finish before +# we get a chance to have this command fail +not lvconvert -m-1 $vg/$lv1 $dev1 +while [ `lvs --noheadings -o copy_percent $vg/$lv1` != "100.00" ]; do + sleep 1 +done lvconvert -m-1 $vg/$lv1 $dev1 check mirror_images_on $lv1 $dev2 $dev4 lvconvert -m-1 $vg/$lv1 $dev2 check linear $vg $lv1 check lv_on $vg/$lv1 $dev4 - diff --git a/test/t-mirror-lvconvert.sh b/test/t-mirror-lvconvert.sh index ce36cf5ed..038c9438a 100755 --- a/test/t-mirror-lvconvert.sh +++ b/test/t-mirror-lvconvert.sh @@ -98,6 +98,12 @@ wait_conversion_() while (lvs --noheadings -oattr "$lv" | grep -q '^ *c'); do sleep 1; done } +wait_sync_() +{ + local lv=$1 + while [ `lvs --noheadings -o copy_percent $lv` != "100.00" ]; do sleep 1; done +} + check_no_tmplvs_() { local lv=$1 @@ -404,6 +410,7 @@ lvcreate -l`pvs --noheadings -ope_count $dev1` -m1 -n $lv1 $vg $dev1 $dev2 $dev3 lvs -a -o+devices $vg check_mirror_count_ $vg/$lv1 2 check_mirror_log_ $vg/$lv1 +wait_sync_ $vg/$lv1 # cannot pull primary unless mirror in-sync lvconvert -m0 $vg/$lv1 $dev1 lvs -a -o+devices $vg check_no_tmplvs_ $vg/$lv1 -- 2.43.5