xref: /freebsd/tests/sys/geom/class/mirror/component_selection.sh (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1
2ATF_TEST=true
3class=mirror
4. $(atf_get_srcdir)/conf.sh
5
6atf_test_case run_latest_genid cleanup
7run_latest_genid_head()
8{
9	atf_set "descr" \
10	    "Ensure that we properly select components (latest genid) during STARTING."
11	atf_set "require.user" "root"
12}
13run_latest_genid_body()
14{
15	geom_atf_test_setup
16	if ! error_message=$(geom_load_class_if_needed nop); then
17		atf_skip "$error_message"
18	fi
19
20	f1=$(mktemp ${base}.XXXXXX)
21	f2=$(mktemp ${base}.XXXXXX)
22	f3=$(mktemp ${base}.XXXXXX)
23	rnd1=$(mktemp ${base}.XXXXXX)
24	rnd2=$(mktemp ${base}.XXXXXX)
25
26	atf_check truncate -s 2M $f1
27	atf_check truncate -s 2M $f2
28	atf_check truncate -s 2M $f3
29	dd if=/dev/urandom bs=512 count=1 of="$rnd1"
30	dd if=/dev/urandom bs=512 count=1 of="$rnd2"
31
32	attach_md md1 -t vnode -f ${f1}
33	attach_md md2 -t vnode -f ${f2}
34	attach_md md3 -t vnode -f ${f3}
35
36	# Use a gnop for md1 just for consistency; it's not used for anything.
37	atf_check gnop create $md1
38	atf_check gnop create $md2
39	atf_check gnop create $md3
40	# Hardcode component names so that the non-.nop device isn't tasted
41	# instead.
42	atf_check gmirror label -h $name ${md1}.nop
43	devwait
44
45	atf_check gmirror insert -h $name ${md2}.nop
46	atf_check gmirror insert -h $name ${md3}.nop
47	syncwait
48
49	# Fail mirror 3, writing known contents to mirror 1+2 block 1
50	atf_check -s exit:0 -e empty -o empty \
51	    gnop configure -w 100 ${md3}.nop
52	atf_check -s exit:0 dd if="$rnd1" bs=512 count=1 oseek=1 conv=notrunc \
53	    of=/dev/mirror/$name status=none
54
55	disconnectwait nop "${md3}.nop"
56
57	# Should have two mirrors remaining after md3 was evicted
58	atf_check [ $(gmirror status -s $name | wc -l) -eq 2 ]
59	atf_check -s exit:0 -o match:"DEGRADED  ${md1}.nop \(ACTIVE\)" \
60		gmirror status -s $name
61	atf_check -s exit:0 -o match:"DEGRADED  ${md2}.nop \(ACTIVE\)" \
62		gmirror status -s $name
63
64	# Repeat:
65	# Fail mirror 2, writing known contents to mirror 1 block 2
66	atf_check -s exit:0 -e empty -o empty \
67	    gnop configure -w 100 ${md2}.nop
68	atf_check -s exit:0 dd if="$rnd2" bs=512 count=2 oseek=1 conv=notrunc \
69	    of=/dev/mirror/$name status=none
70
71	disconnectwait nop "${md2}.nop"
72
73	# Should have one mirror remaining after md2 was evicted
74	atf_check [ $(gmirror status -s $name | wc -l) -eq 1 ]
75	atf_check -s exit:0 -o match:"DEGRADED  ${md1}.nop \(ACTIVE\)" \
76		gmirror status -s $name
77
78	# Stop the mirror and remove the pieces so gmirror can't see them.
79	atf_check gmirror stop $name
80	atf_check gnop destroy ${md1}.nop
81	atf_check gnop destroy ${md2}.nop
82	atf_check gnop destroy ${md3}.nop
83
84	# Rebuild; spin up "disk" with lowest genid
85	atf_check gnop create $md3
86	md3gen=$(gmirror dump /dev/${md3}.nop | grep genid | cut -d: -f2)
87	# Assert gmirror is referencing this component for now:
88	atf_check [ $(consumerrefs nop ${md3}.nop) = "r1w1e1" ]
89
90	# Adding newer genid should kick out old component
91	atf_check gnop create $md2
92	md2gen=$(gmirror dump /dev/${md2}.nop | grep genid | cut -d: -f2)
93	atf_check [ $md2gen -gt $md3gen ]
94
95	disconnectwait nop "${md3}.nop"
96
97	# Can't test this because 'status' doesn't exist until RUNNING:
98	#atf_check [ $(gmirror status -s $name | wc -l) -eq 1 ]
99	# But as a substitute, assert gmirror has dropped reference to staler
100	# component in favor of newer component:
101	atf_check [ $(consumerrefs nop ${md2}.nop) = "r1w1e1" ]
102
103	# ditto
104	atf_check gnop create $md1
105	md1gen=$(gmirror dump /dev/${md1}.nop | grep genid | cut -d: -f2)
106	atf_check [ $md1gen -gt $md2gen ]
107
108	disconnectwait nop "${md2}.nop"
109
110	# Assert gmirror has dropped reference to stale component in favor of
111	# newer component:
112	atf_check [ $(consumerrefs nop ${md1}.nop) = "r1w1e1" ]
113
114	# gmirror won't start the mirror automatically with only one component
115	# ($md0) of configured three, so this waits out the
116	# kern.geom.mirror.timeout:
117	devwait
118
119	atf_check [ $(gmirror status -s $name | wc -l) -eq 1 ]
120	atf_check -s exit:0 -o match:"DEGRADED  ${md1}.nop \(ACTIVE\)" \
121		gmirror status -s $name
122}
123run_latest_genid_cleanup()
124{
125	. $(atf_get_srcdir)/conf.sh
126
127	if [ -f "$TEST_MDS_FILE" ]; then
128		while read test_md; do
129			echo "# Removing test gnop: ${test_md}.nop"
130			gnop destroy -f "${test_md}.nop" 2>/dev/null || :
131		done < "$TEST_MDS_FILE"
132	fi
133	gmirror_test_cleanup
134}
135
136atf_init_test_cases()
137{
138	atf_add_test_case run_latest_genid
139}
140