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