mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +03:00
ddb14b6b05
This patch ensures that under normal conditions (i.e. not during repair operations) that users are prevented from removing devices that would cause data loss. When a RAID1 is undergoing its initial sync, it is ok to remove all but one of the images because they have all existed since creation and contain all the data written since the array was created. OTOH, if the RAID1 was created as a result of an up-convert from linear, it is very important not to let the user remove the primary image (the source of all the data). They should be allowed to remove any devices they want and as many as they want as long as one original (primary) device is left during a "recover" (aka up-convert). This fixes bug 1461187 and includes the necessary regression tests.
319 lines
9.3 KiB
Bash
319 lines
9.3 KiB
Bash
#!/bin/sh
|
|
# Copyright (C) 2011-2017 Red Hat, Inc. All rights reserved.
|
|
#
|
|
# This copyrighted material is made available to anyone wishing to use,
|
|
# modify, copy, or redistribute it subject to the terms and conditions
|
|
# of the GNU General Public License v.2.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software Foundation,
|
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
# disable lvmetad logging as it bogs down test systems
|
|
|
|
SKIP_WITH_LVMLOCKD=1
|
|
SKIP_WITH_LVMPOLLD=1
|
|
|
|
export LVM_TEST_LVMETAD_DEBUG_OPTS=${LVM_TEST_LVMETAD_DEBUG_OPTS-}
|
|
|
|
. lib/inittest
|
|
|
|
get_image_pvs() {
|
|
local d
|
|
local images
|
|
|
|
images=`dmsetup ls | grep ${1}-${2}_.image_.* | cut -f1 | sed -e s:-:/:`
|
|
lvs --noheadings -a -o devices $images | sed s/\(.\)//
|
|
}
|
|
|
|
########################################################
|
|
# MAIN
|
|
########################################################
|
|
aux have_raid 1 3 0 || skip
|
|
|
|
aux prepare_pvs 9
|
|
# vgcreate -s 256k $vg $(cat DEVICES)
|
|
vgcreate -s 2m $vg $(cat DEVICES)
|
|
|
|
###########################################
|
|
# RAID1 convert tests
|
|
###########################################
|
|
for under_snap in false true; do
|
|
for i in 1 2 3; do
|
|
for j in 1 2 3; do
|
|
if [ $i -eq 1 ]; then
|
|
from="linear"
|
|
else
|
|
from="$i-way"
|
|
fi
|
|
if [ $j -eq 1 ]; then
|
|
to="linear"
|
|
else
|
|
to="$j-way"
|
|
fi
|
|
|
|
echo -n "Converting from $from to $to"
|
|
if $under_snap; then
|
|
echo -n " (while under a snapshot)"
|
|
fi
|
|
echo
|
|
|
|
if [ $i -eq 1 ]; then
|
|
# Shouldn't be able to create with just 1 image
|
|
not lvcreate --type raid1 -m 0 -l 2 -n $lv1 $vg
|
|
|
|
lvcreate -aey -l 2 -n $lv1 $vg
|
|
else
|
|
lvcreate --type raid1 -m $(($i - 1)) -l 2 -n $lv1 $vg
|
|
aux wait_for_sync $vg $lv1
|
|
fi
|
|
|
|
if $under_snap; then
|
|
lvcreate -aey -s $vg/$lv1 -n snap -l 2
|
|
fi
|
|
|
|
mirrors=$((j - 1))
|
|
if [ $i -eq 1 ]
|
|
then
|
|
[ $mirrors -eq 0 ] && lvconvert -y -m $mirrors $vg/$lv1
|
|
else
|
|
if [ $mirrors -eq 0 ]
|
|
then
|
|
not lvconvert -m $mirrors $vg/$lv1
|
|
lvconvert -y -m $mirrors $vg/$lv1
|
|
else
|
|
lvconvert -y -m $mirrors $vg/$lv1
|
|
fi
|
|
fi
|
|
|
|
# FIXME: ensure no residual devices
|
|
|
|
if [ $j -eq 1 ]; then
|
|
check linear $vg $lv1
|
|
fi
|
|
lvremove -ff $vg
|
|
done
|
|
done
|
|
done
|
|
|
|
##############################################
|
|
# RAID1 - shouldn't be able to add image
|
|
# if created '--nosync', but should
|
|
# be able to after 'lvchange --resync'
|
|
##############################################
|
|
lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg --nosync
|
|
not lvconvert -m +1 $vg/$lv1
|
|
lvchange --resync -y $vg/$lv1
|
|
aux wait_for_sync $vg $lv1
|
|
lvconvert -y -m +1 $vg/$lv1
|
|
lvremove -ff $vg
|
|
|
|
# 3-way to 2-way convert while specifying devices
|
|
lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg "$dev1" "$dev2" "$dev3"
|
|
aux wait_for_sync $vg $lv1
|
|
lvconvert -y -m 1 $vg/$lv1 "$dev2"
|
|
lvremove -ff $vg
|
|
|
|
#
|
|
# FIXME: Add tests that specify particular devices to be removed
|
|
#
|
|
|
|
###########################################
|
|
# RAID1 split tests
|
|
###########################################
|
|
# 3-way to 2-way/linear
|
|
lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg
|
|
aux wait_for_sync $vg $lv1
|
|
lvconvert --splitmirrors 1 -n $lv2 $vg/$lv1
|
|
check lv_exists $vg $lv1
|
|
check linear $vg $lv2
|
|
check active $vg $lv2
|
|
# FIXME: ensure no residual devices
|
|
lvremove -ff $vg
|
|
|
|
# 2-way to linear/linear
|
|
lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg
|
|
aux wait_for_sync $vg $lv1
|
|
not lvconvert --splitmirrors 1 -n $lv2 $vg/$lv1
|
|
lvconvert --yes --splitmirrors 1 -n $lv2 $vg/$lv1
|
|
check linear $vg $lv1
|
|
check linear $vg $lv2
|
|
check active $vg $lv2
|
|
# FIXME: ensure no residual devices
|
|
lvremove -ff $vg
|
|
|
|
# 4-way
|
|
lvcreate --type raid1 -m 4 -l 2 -n $lv1 $vg
|
|
aux wait_for_sync $vg $lv1
|
|
lvconvert --splitmirrors 1 --name $lv2 $vg/$lv1 "$dev2"
|
|
lvremove -ff $vg
|
|
|
|
###########################################
|
|
# RAID1 split + trackchanges / merge with content check
|
|
###########################################
|
|
# 3-way to 2-way/linear
|
|
lvcreate --type raid1 -m 2 -l 1 -n $lv1 $vg
|
|
mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1"
|
|
fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1"
|
|
aux wait_for_sync $vg $lv1
|
|
fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1"
|
|
lvconvert --splitmirrors 1 --trackchanges $vg/$lv1
|
|
check lv_exists $vg $lv1
|
|
check linear $vg ${lv1}_rimage_2
|
|
fsck.ext4 -fn "$DM_DEV_DIR/mapper/$vg-${lv1}_rimage_2"
|
|
dd of="$DM_DEV_DIR/$vg/$lv1" if=/dev/zero bs=512 oflag=direct count=`blockdev --getsz "$DM_DEV_DIR/$vg/$lv1"`
|
|
not fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1"
|
|
fsck.ext4 -fn "$DM_DEV_DIR/mapper/$vg-${lv1}_rimage_2"
|
|
# FIXME: needed on tiny loop but not on real block backend ?
|
|
lvchange --refresh $vg/$lv1
|
|
lvconvert --merge $vg/${lv1}_rimage_2
|
|
aux wait_for_sync $vg $lv1
|
|
lvconvert --splitmirrors 1 --trackchanges $vg/$lv1
|
|
not fsck.ext4 -fn "$DM_DEV_DIR/mapper/$vg-${lv1}_rimage_2"
|
|
# FIXME: ensure no residual devices
|
|
lvremove -ff $vg
|
|
|
|
# Check split track changes gets rejected w/o -y on 2-legged raid1
|
|
lvcreate --type raid1 -m 1 -l 1 -n $lv1 $vg
|
|
mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1"
|
|
fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1"
|
|
aux wait_for_sync $vg $lv1
|
|
fsck.ext4 -fn "$DM_DEV_DIR/$vg/$lv1"
|
|
not lvconvert --splitmirrors 1 --trackchanges $vg/$lv1
|
|
lvconvert --yes --splitmirrors 1 --trackchanges $vg/$lv1
|
|
# FIXME: ensure no residual devices
|
|
lvremove -ff $vg
|
|
|
|
###########################################
|
|
# Linear to RAID1 conversion ("raid1" default segtype)
|
|
###########################################
|
|
lvcreate -aey -l 2 -n $lv1 $vg
|
|
lvconvert -y -m 1 $vg/$lv1 \
|
|
--config 'global { mirror_segtype_default = "raid1" }'
|
|
lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*r'
|
|
lvremove -ff $vg
|
|
|
|
###########################################
|
|
# Linear to RAID1 conversion (override "mirror" default segtype)
|
|
###########################################
|
|
lvcreate -aey -l 2 -n $lv1 $vg
|
|
lvconvert --yes --type raid1 -m 1 $vg/$lv1 \
|
|
--config 'global { mirror_segtype_default = "mirror" }'
|
|
lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*r'
|
|
lvremove -ff $vg
|
|
|
|
###########################################
|
|
# Must not be able to convert non-EX LVs in a cluster
|
|
###########################################
|
|
if [ -e LOCAL_CLVMD ]; then
|
|
lvcreate -l 2 -n $lv1 $vg
|
|
not lvconvert -y --type raid1 -m 1 $vg/$lv1 \
|
|
--config 'global { mirror_segtype_default = "mirror" }'
|
|
lvremove -ff $vg
|
|
fi
|
|
|
|
###########################################
|
|
# Mirror to RAID1 conversion
|
|
###########################################
|
|
for i in 1 2 3 ; do
|
|
lvcreate -aey --type mirror -m $i -l 2 -n $lv1 $vg
|
|
aux wait_for_sync $vg $lv1
|
|
lvconvert -y --type raid1 $vg/$lv1
|
|
lvremove -ff $vg
|
|
done
|
|
|
|
###########################################
|
|
# Upconverted RAID1 should not allow loss of primary
|
|
# - don't allow removal of primary while syncing
|
|
# - DO allow removal of secondaries while syncing
|
|
###########################################
|
|
aux delay_dev $dev2 0 100
|
|
lvcreate -aey -l 2 -n $lv1 $vg $dev1 $dev2
|
|
lvconvert -y -m 1 $vg/$lv1 \
|
|
--config 'global { mirror_segtype_default = "raid1" }'
|
|
lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*r'
|
|
not lvconvert --yes -m 0 $vg/$lv1 $dev1
|
|
lvconvert --yes -m 0 $vg/$lv1 $dev2
|
|
aux enable_dev $dev2
|
|
lvremove -ff $vg
|
|
|
|
###########################################
|
|
# lvcreated RAID1 should allow all down-conversion
|
|
# - DO allow removal of primary while syncing
|
|
# - DO allow removal of secondaries while syncing
|
|
###########################################
|
|
aux delay_dev $dev2 0 100
|
|
lvcreate --type raid1 -m 2 -aey -l 2 -n $lv1 $vg $dev1 $dev2 $dev3
|
|
lvconvert --yes -m 1 $vg/$lv1 $dev3
|
|
lvconvert --yes -m 0 $vg/$lv1 $dev1
|
|
aux enable_dev $dev2
|
|
lvremove -ff $vg
|
|
|
|
###########################################
|
|
# Converting from 2-way RAID1 to 3-way
|
|
# - DO allow removal of one of primary sources
|
|
# - Do not allow removal of all primary sources
|
|
###########################################
|
|
lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg $dev1 $dev2
|
|
aux wait_for_sync $vg $lv1
|
|
aux delay_dev $dev3 0 100
|
|
lvconvert --yes -m +1 $vg/$lv1 $dev3
|
|
# should allow 1st primary to be removed
|
|
lvconvert --yes -m -1 $vg/$lv1 $dev1
|
|
# should NOT allow last primary to be removed
|
|
not lvconvert --yes -m -1 $vg/$lv1 $dev2
|
|
# should allow non-primary to be removed
|
|
lvconvert --yes -m 0 $vg/$lv1 $dev3
|
|
aux enable_dev $dev3
|
|
lvremove -ff $vg
|
|
|
|
###########################################
|
|
# Converting from 2-way RAID1 to 3-way
|
|
# - Should allow removal of two devices,
|
|
# as long as they aren't both primary
|
|
###########################################
|
|
lvcreate --type raid1 -m 1 -aey -l 2 -n $lv1 $vg $dev1 $dev2
|
|
aux wait_for_sync $vg $lv1
|
|
aux delay_dev $dev3 0 100
|
|
lvconvert --yes -m +1 $vg/$lv1 $dev3
|
|
# should NOT allow both primaries to be removed
|
|
not lvconvert -m 0 $vg/$lv1 $dev1 $dev2
|
|
# should allow primary + non-primary
|
|
lvconvert --yes -m 0 $vg/$lv1 $dev1 $dev3
|
|
aux enable_dev $dev3
|
|
lvremove -ff $vg
|
|
|
|
###########################################
|
|
# Device Replacement Testing
|
|
###########################################
|
|
# RAID1: Replace up to n-1 devices - trying different combinations
|
|
# Test for 2-way to 4-way RAID1 LVs
|
|
for i in {1..3}; do
|
|
lvcreate --type raid1 -m $i -l 2 -n $lv1 $vg
|
|
|
|
for j in $(seq $(($i + 1))); do # The number of devs to replace at once
|
|
for o in $(seq 0 $i); do # The offset into the device list
|
|
replace=""
|
|
|
|
devices=( $(get_image_pvs $vg $lv1) )
|
|
|
|
for k in $(seq $j); do
|
|
index=$((($k + $o) % ($i + 1)))
|
|
replace="$replace --replace ${devices[$index]}"
|
|
done
|
|
aux wait_for_sync $vg $lv1
|
|
|
|
if [ $j -ge $((i + 1)) ]; then
|
|
# Can't replace all at once.
|
|
not lvconvert $replace $vg/$lv1
|
|
else
|
|
lvconvert $replace $vg/$lv1
|
|
fi
|
|
done
|
|
done
|
|
|
|
lvremove -ff $vg
|
|
done
|
|
|
|
vgremove -ff $vg
|