1# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
2# Copyright (C) 2007 NEC Corporation
3#
4# This copyrighted material is made available to anyone wishing to use,
5# modify, copy, or redistribute it subject to the terms and conditions
6# of the GNU General Public License v.2.
7#
8# You should have received a copy of the GNU General Public License
9# along with this program; if not, write to the Free Software Foundation,
10# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
11
12test_description="ensure that 'vgreduce --removemissing' works on mirrored LV"
13
14. ./test-utils.sh
15
16dmsetup_has_dm_devdir_support_ || exit 200
17
18lv_is_on_ ()
19{
20	local lv=$vg/$1
21	shift
22	local pvs=$*
23
24	echo "Check if $lv is exactly on PVs $pvs"
25	rm -f out1 out2
26	echo $pvs | sed 's/ /\n/g' | sort | uniq > out1
27
28	lvs -a -odevices --noheadings $lv | \
29	sed 's/([^)]*)//g; s/[ ,]/\n/g' | sort | uniq > out2
30
31	diff --ignore-blank-lines out1 out2
32}
33
34mimages_are_on_ ()
35{
36	local lv=$1
37	shift
38	local pvs="$*"
39	local mimages
40	local i
41
42	echo "Check if mirror images of $lv are on PVs $pvs"
43	rm -f out1 out2
44	echo $pvs | sed 's/ /\n/g' | sort | uniq > out1
45
46	mimages=$(lvs --noheadings -a -o lv_name $vg | grep "${lv}_mimage_" | \
47		sed 's/\[//g; s/\]//g')
48	for i in $mimages; do
49		echo "Checking $vg/$i"
50		lvs -a -odevices --noheadings $vg/$i | \
51			sed 's/([^)]*)//g; s/ //g; s/,/ /g' | sort | uniq >> out2
52	done
53
54	diff --ignore-blank-lines out1 out2
55}
56
57mirrorlog_is_on_()
58{
59	local lv="$1"_mlog
60	shift
61	lv_is_on_ $lv $*
62}
63
64lv_is_linear_()
65{
66	echo "Check if $1 is linear LV (i.e. not a mirror)"
67	lvs -o stripes,attr --noheadings $vg/$1 | sed 's/ //g'
68	lvs -o stripes,attr --noheadings $vg/$1 | sed 's/ //g' | grep -q '^1-'
69}
70
71rest_pvs_()
72{
73	local index=$1
74	local num=$2
75	local rem=""
76	local n
77
78	for n in $(seq 1 $(($index - 1))) $(seq $(($index + 1)) $num); do
79		eval local dev=$\dev$n
80		rem="$rem $dev"
81	done
82
83	echo "$rem"
84}
85
86# ---------------------------------------------------------------------
87# Initialize PVs and VGs
88
89prepare_vg 5
90
91# ---------------------------------------------------------------------
92# Common environment setup/cleanup for each sub testcases
93
94prepare_lvs_()
95{
96	lvremove -ff $vg;
97	if dmsetup table|grep $vg; then
98		echo "ERROR: lvremove did leave some some mappings in DM behind!"
99		return 1
100	fi
101	:
102}
103
104check_and_cleanup_lvs_()
105{
106	lvs -a -o+devices $vg
107	lvremove -ff $vg
108	if dmsetup table|grep $vg; then
109		echo "ERROR: lvremove did leave some some mappings in DM behind!"
110		return 1
111	fi
112}
113
114recover_vg_()
115{
116	enable_dev $*
117	pvcreate -ff $*
118	vgextend $vg $*
119	check_and_cleanup_lvs_
120}
121
122#COMM "check environment setup/cleanup"
123prepare_lvs_
124check_and_cleanup_lvs_
125
126# ---------------------------------------------------------------------
127# one of mirror images has failed
128
129#COMM "basic: fail the 2nd mirror image of 2-way mirrored LV"
130prepare_lvs_
131lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
132lvchange -an $vg/$lv1
133aux mimages_are_on_ $lv1 $dev1 $dev2
134mirrorlog_is_on_ $lv1 $dev3
135disable_dev $dev2
136vgreduce --removemissing --force $vg
137lv_is_linear_ $lv1
138lv_is_on_ $lv1 $dev1
139
140# "cleanup"
141recover_vg_ $dev2
142
143# ---------------------------------------------------------------------
144# LV has 3 images in flat,
145# 1 out of 3 images fails
146
147#COMM test_3way_mirror_fail_1_ <PV# to fail>
148test_3way_mirror_fail_1_()
149{
150	local index=$1
151
152	lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev4:0-1
153	lvchange -an $vg/$lv1
154	aux mimages_are_on_ $lv1 $dev1 $dev2 $dev3
155	mirrorlog_is_on_ $lv1 $dev4
156	eval disable_dev \$dev$index
157	vgreduce --removemissing --force $vg
158	lvs -a -o+devices $vg
159	mimages_are_on_ $lv1 $(rest_pvs_ $index 3)
160	mirrorlog_is_on_ $lv1 $dev4
161}
162
163for n in $(seq 1 3); do
164	#COMM fail mirror image $(($n - 1)) of 3-way mirrored LV"
165	prepare_lvs_
166	test_3way_mirror_fail_1_ $n
167	eval recover_vg_ \$dev$n
168done
169
170# ---------------------------------------------------------------------
171# LV has 3 images in flat,
172# 2 out of 3 images fail
173
174#COMM test_3way_mirror_fail_2_ <PV# NOT to fail>
175test_3way_mirror_fail_2_()
176{
177	local index=$1
178
179	lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev4:0-1
180	lvchange -an $vg/$lv1
181	mimages_are_on_ $lv1 $dev1 $dev2 $dev3
182	mirrorlog_is_on_ $lv1 $dev4
183	rest_pvs_ $index 3
184	disable_dev $(rest_pvs_ $index 3)
185	vgreduce --force --removemissing $vg
186	lvs -a -o+devices $vg
187	aux lv_is_linear_ $lv1
188	eval lv_is_on_ $lv1 \$dev$n
189}
190
191for n in $(seq 1 3); do
192	#COMM fail mirror images other than mirror image $(($n - 1)) of 3-way mirrored LV
193	prepare_lvs_
194	test_3way_mirror_fail_2_ $n
195	recover_vg_ $(rest_pvs_ $n 3)
196done
197
198# ---------------------------------------------------------------------
199# LV has 4 images, 1 of them is in the temporary mirror for syncing.
200# 1 out of 4 images fails
201
202#COMM test_3way_mirror_plus_1_fail_1_ <PV# to fail>
203test_3way_mirror_plus_1_fail_1_()
204{
205	local index=$1
206
207	lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev5:0-1
208	lvchange -an $vg/$lv1
209	lvconvert -m+1 $vg/$lv1 $dev4
210	mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4
211	mirrorlog_is_on_ $lv1 $dev5
212	eval disable_dev \$dev$n
213	vgreduce --removemissing --force $vg
214	lvs -a -o+devices $vg
215	mimages_are_on_ $lv1 $(rest_pvs_ $index 4)
216	mirrorlog_is_on_ $lv1 $dev5
217}
218
219for n in $(seq 1 4); do
220	#COMM "fail mirror image $(($n - 1)) of 4-way (1 converting) mirrored LV"
221	prepare_lvs_
222	test_3way_mirror_plus_1_fail_1_ $n
223	eval recover_vg_ \$dev$n
224done
225
226# ---------------------------------------------------------------------
227# LV has 4 images, 1 of them is in the temporary mirror for syncing.
228# 3 out of 4 images fail
229
230#COMM test_3way_mirror_plus_1_fail_3_ <PV# NOT to fail>
231test_3way_mirror_plus_1_fail_3_()
232{
233	local index=$1
234
235	lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev5:0-1
236	lvchange -an $vg/$lv1
237	lvconvert -m+1 $vg/$lv1 $dev4
238	mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4
239	mirrorlog_is_on_ $lv1 $dev5
240	disable_dev $(rest_pvs_ $index 4)
241	vgreduce --removemissing --force $vg
242	lvs -a -o+devices $vg
243	eval local dev=\$dev$n
244	mimages_are_on_ $lv1 $dev || lv_is_on_ $lv1 $dev
245	not mirrorlog_is_on_ $lv1 $dev5
246}
247
248for n in $(seq 1 4); do
249	#COMM "fail mirror images other than mirror image $(($n - 1)) of 4-way (1 converting) mirrored LV"
250	prepare_lvs_
251	test_3way_mirror_plus_1_fail_3_ $n
252	recover_vg_ $(rest_pvs_ $n 4)
253done
254
255# ---------------------------------------------------------------------
256# LV has 4 images, 2 of them are in the temporary mirror for syncing.
257# 1 out of 4 images fail
258
259# test_2way_mirror_plus_2_fail_1_ <PV# to fail>
260test_2way_mirror_plus_2_fail_1_()
261{
262	local index=$1
263
264	lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1
265	lvchange -an $vg/$lv1
266	lvconvert -m+2 $vg/$lv1 $dev3 $dev4
267	mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4
268	mirrorlog_is_on_ $lv1 $dev5
269	eval disable_dev \$dev$n
270	vgreduce --removemissing --force $vg
271	lvs -a -o+devices $vg
272	mimages_are_on_ $lv1 $(rest_pvs_ $index 4)
273	mirrorlog_is_on_ $lv1 $dev5
274}
275
276for n in $(seq 1 4); do
277	#COMM "fail mirror image $(($n - 1)) of 4-way (2 converting) mirrored LV"
278	prepare_lvs_
279	test_2way_mirror_plus_2_fail_1_ $n
280	eval recover_vg_ \$dev$n
281done
282
283# ---------------------------------------------------------------------
284# LV has 4 images, 2 of them are in the temporary mirror for syncing.
285# 3 out of 4 images fail
286
287# test_2way_mirror_plus_2_fail_3_ <PV# NOT to fail>
288test_2way_mirror_plus_2_fail_3_()
289{
290	local index=$1
291
292	lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1
293	lvchange -an $vg/$lv1
294	lvconvert -m+2 $vg/$lv1 $dev3 $dev4
295	mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4
296	mirrorlog_is_on_ $lv1 $dev5
297	disable_dev $(rest_pvs_ $index 4)
298	vgreduce --removemissing --force $vg
299	lvs -a -o+devices $vg
300	eval local dev=\$dev$n
301	mimages_are_on_ $lv1 $dev || lv_is_on_ $lv1 $dev
302	not mirrorlog_is_on_ $lv1 $dev5
303}
304
305for n in $(seq 1 4); do
306	#COMM "fail mirror images other than mirror image $(($n - 1)) of 4-way (2 converting) mirrored LV"
307	prepare_lvs_
308	test_2way_mirror_plus_2_fail_3_ $n
309	recover_vg_ $(rest_pvs_ $n 4)
310done
311
312# ---------------------------------------------------------------------
313# log device is gone (flat mirror and stacked mirror)
314
315#COMM "fail mirror log of 2-way mirrored LV"
316prepare_lvs_
317lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1
318lvchange -an $vg/$lv1
319mimages_are_on_ $lv1 $dev1 $dev2
320mirrorlog_is_on_ $lv1 $dev5
321disable_dev $dev5
322vgreduce --removemissing --force $vg
323mimages_are_on_ $lv1 $dev1 $dev2
324not mirrorlog_is_on_ $lv1 $dev5
325recover_vg_ $dev5
326
327#COMM "fail mirror log of 3-way (1 converting) mirrored LV"
328prepare_lvs_
329lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1
330lvchange -an $vg/$lv1
331lvconvert -m+1 $vg/$lv1 $dev3
332mimages_are_on_ $lv1 $dev1 $dev2 $dev3
333mirrorlog_is_on_ $lv1 $dev5
334disable_dev $dev5
335vgreduce --removemissing --force $vg
336mimages_are_on_ $lv1 $dev1 $dev2 $dev3
337not mirrorlog_is_on_ $lv1 $dev5
338recover_vg_ $dev5
339
340# ---------------------------------------------------------------------
341# all images are gone (flat mirror and stacked mirror)
342
343#COMM "fail all mirror images of 2-way mirrored LV"
344prepare_lvs_
345lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1
346lvchange -an $vg/$lv1
347mimages_are_on_ $lv1 $dev1 $dev2
348mirrorlog_is_on_ $lv1 $dev5
349disable_dev $dev1 $dev2
350vgreduce --removemissing --force $vg
351not lvs $vg/$lv1
352recover_vg_ $dev1 $dev2
353
354#COMM "fail all mirror images of 3-way (1 converting) mirrored LV"
355prepare_lvs_
356lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1
357lvchange -an $vg/$lv1
358lvconvert -m+1 $vg/$lv1 $dev3
359mimages_are_on_ $lv1 $dev1 $dev2 $dev3
360mirrorlog_is_on_ $lv1 $dev5
361disable_dev $dev1 $dev2 $dev3
362vgreduce --removemissing --force $vg
363not lvs $vg/$lv1
364recover_vg_ $dev1 $dev2 $dev3
365
366# ---------------------------------------------------------------------
367# Multiple LVs
368
369#COMM "fail a mirror image of one of mirrored LV"
370prepare_lvs_
371lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1
372lvchange -an $vg/$lv1
373lvcreate -l2 -m1 -n $lv2 $vg $dev3 $dev4 $dev5:1-1
374lvchange -an $vg/$lv2
375mimages_are_on_ $lv1 $dev1 $dev2
376mimages_are_on_ $lv2 $dev3 $dev4
377mirrorlog_is_on_ $lv1 $dev5
378mirrorlog_is_on_ $lv2 $dev5
379disable_dev $dev2
380vgreduce --removemissing --force $vg
381mimages_are_on_ $lv2 $dev3 $dev4
382mirrorlog_is_on_ $lv2 $dev5
383lv_is_linear_ $lv1
384lv_is_on_ $lv1 $dev1
385recover_vg_ $dev2
386
387#COMM "fail mirror images, one for each mirrored LV"
388prepare_lvs_
389lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1
390lvchange -an $vg/$lv1
391lvcreate -l2 -m1 -n $lv2 $vg $dev3 $dev4 $dev5:1-1
392lvchange -an $vg/$lv2
393mimages_are_on_ $lv1 $dev1 $dev2
394mimages_are_on_ $lv2 $dev3 $dev4
395mirrorlog_is_on_ $lv1 $dev5
396mirrorlog_is_on_ $lv2 $dev5
397disable_dev $dev2
398disable_dev $dev4
399vgreduce --removemissing --force $vg
400lv_is_linear_ $lv1
401lv_is_on_ $lv1 $dev1
402lv_is_linear_ $lv2
403lv_is_on_ $lv2 $dev3
404recover_vg_ $dev2 $dev4
405
406# ---------------------------------------------------------------------
407# no failure
408
409#COMM "no failures"
410prepare_lvs_
411lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0-1
412lvchange -an $vg/$lv1
413mimages_are_on_ $lv1 $dev1 $dev2
414mirrorlog_is_on_ $lv1 $dev5
415vgreduce --removemissing --force $vg
416mimages_are_on_ $lv1 $dev1 $dev2
417mirrorlog_is_on_ $lv1 $dev5
418check_and_cleanup_lvs_
419
420# ---------------------------------------------------------------------
421
422