1# $FreeBSD$
2
3ATF_TEST=true
4. $(atf_get_srcdir)/conf.sh
5
6REG_READ_FP=debug.fail_point.g_mirror_regular_request_read
7
8atf_test_case sync_read_error_2_disks cleanup
9sync_read_error_2_disks_head()
10{
11	atf_set "descr" \
12		"Ensure that we properly handle read errors during synchronization."
13	atf_set "require.user" "root"
14}
15sync_read_error_2_disks_body()
16{
17	geom_atf_test_setup
18
19	f1=$(mktemp ${base}.XXXXXX)
20	f2=$(mktemp ${base}.XXXXXX)
21
22	atf_check dd if=/dev/zero bs=1M count=32 of=$f1 status=none
23	atf_check truncate -s 32M $f2
24
25	md1=$(attach_md -t vnode -f ${f1})
26	md2=$(attach_md -t vnode -f ${f2})
27
28	atf_check gmirror label $name $md1
29	devwait
30
31	atf_check -s ignore -e empty -o not-empty sysctl ${REG_READ_FP}="1*return(5)[pid $(gmirror_worker_pid)]"
32
33	# If a read error occurs while synchronizing and the mirror contains
34	# a single active disk, gmirror has no choice but to fail the
35	# synchronization and kick the new disk out of the mirror.
36	atf_check gmirror insert $name $md2
37	sleep 0.1
38	syncwait
39	atf_check [ $(gmirror status -s $name | wc -l) -eq 1 ]
40	atf_check -s exit:0 -o match:"DEGRADED  $md1 \(ACTIVE\)" \
41		gmirror status -s $name
42}
43sync_read_error_2_disks_cleanup()
44{
45	atf_check -s ignore -e ignore -o ignore sysctl ${REG_READ_FP}='off'
46	gmirror_test_cleanup
47}
48
49atf_test_case sync_read_error_3_disks cleanup
50sync_read_error_3_disks_head()
51{
52	atf_set "descr" \
53		"Ensure that we properly handle read errors during synchronization."
54	atf_set "require.user" "root"
55}
56sync_read_error_3_disks_body()
57{
58	geom_atf_test_setup
59
60	f1=$(mktemp ${base}.XXXXXX)
61	f2=$(mktemp ${base}.XXXXXX)
62	f3=$(mktemp ${base}.XXXXXX)
63
64	atf_check dd if=/dev/random bs=1M count=32 of=$f1 status=none
65	atf_check truncate -s 32M $f2
66	atf_check truncate -s 32M $f3
67
68	md1=$(attach_md -t vnode -f ${f1})
69	md2=$(attach_md -t vnode -f ${f2})
70	md3=$(attach_md -t vnode -f ${f3})
71
72	atf_check gmirror label $name $md1
73	devwait
74
75	atf_check gmirror insert $name $md2
76	syncwait
77
78	atf_check -s exit:0 -e empty -o not-empty sysctl ${REG_READ_FP}="1*return(5)[pid $(gmirror_worker_pid)]"
79
80	# If a read error occurs while synchronizing a new disk, and we have
81	# multiple active disks, we retry the read after an error. The disk
82	# which returned the read error is kicked out of the mirror.
83	atf_check gmirror insert $name $md3
84	syncwait
85	atf_check [ $(gmirror status -s $name | wc -l) -eq 2 ]
86	atf_check -s exit:0 -o match:"DEGRADED  $md3 \(ACTIVE\)" \
87		gmirror status -s $name
88
89	# Make sure that the two active disks are identical. Destroy the
90	# mirror first so that the metadata sectors are wiped.
91	if $(gmirror status -s $name | grep -q $md1); then
92		active=$md1
93	else
94		active=$md2
95	fi
96	atf_check gmirror destroy $name
97	atf_check cmp /dev/$active /dev/$md3
98}
99sync_read_error_3_disks_cleanup()
100{
101	atf_check -s ignore -e ignore -o ignore sysctl ${REG_READ_FP}='off'
102	gmirror_test_cleanup
103}
104
105atf_init_test_cases()
106{
107	atf_add_test_case sync_read_error_2_disks
108	atf_add_test_case sync_read_error_3_disks
109}
110