diff options
author | markj <markj@FreeBSD.org> | 2018-01-24 15:16:17 +0000 |
---|---|---|
committer | markj <markj@FreeBSD.org> | 2018-01-24 15:16:17 +0000 |
commit | 3d8890c2b7f6938fe084da4969bfd8c6117574ce (patch) | |
tree | c207d2090379cecd6f665c29bf500a317a54cab2 /tests | |
parent | b70682f89cf71a733251c8ec71971664407c2a46 (diff) | |
download | FreeBSD-src-3d8890c2b7f6938fe084da4969bfd8c6117574ce.zip FreeBSD-src-3d8890c2b7f6938fe084da4969bfd8c6117574ce.tar.gz |
MFC r327779, r327780:
Fix handling of read errors during synchronization.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/sys/geom/class/mirror/Makefile | 2 | ||||
-rw-r--r-- | tests/sys/geom/class/mirror/sync_error.sh | 110 |
2 files changed, 112 insertions, 0 deletions
diff --git a/tests/sys/geom/class/mirror/Makefile b/tests/sys/geom/class/mirror/Makefile index 095fb90..817d5d6 100644 --- a/tests/sys/geom/class/mirror/Makefile +++ b/tests/sys/geom/class/mirror/Makefile @@ -18,6 +18,8 @@ TAP_TESTS_SH+= 11_test TAP_TESTS_SH+= 12_test TAP_TESTS_SH+= 13_test +ATF_TESTS_SH+= sync_error + ${PACKAGE}FILES+= conf.sh .for t in ${TAP_TESTS_SH} diff --git a/tests/sys/geom/class/mirror/sync_error.sh b/tests/sys/geom/class/mirror/sync_error.sh new file mode 100644 index 0000000..89fd31e --- /dev/null +++ b/tests/sys/geom/class/mirror/sync_error.sh @@ -0,0 +1,110 @@ +# $FreeBSD$ + +REG_READ_FP=debug.fail_point.g_mirror_regular_request_read + +atf_test_case sync_read_error_2_disks cleanup +sync_read_error_2_disks_head() +{ + atf_set "descr" \ + "Ensure that we properly handle read errors during synchronization." + atf_set "require.user" "root" +} +sync_read_error_2_disks_body() +{ + . $(atf_get_srcdir)/conf.sh + + f1=$(mktemp ${base}.XXXXXX) + f2=$(mktemp ${base}.XXXXXX) + + atf_check dd if=/dev/zero bs=1M count=32 of=$f1 status=none + atf_check truncate -s 32M $f2 + + md1=$(attach_md -t vnode -f ${f1}) + md2=$(attach_md -t vnode -f ${f2}) + + atf_check gmirror label $name $md1 + devwait + + atf_check -s exit:0 -e empty -o not-empty sysctl ${REG_READ_FP}='1*return(5)' + + # If a read error occurs while synchronizing and the mirror contains + # a single active disk, gmirror has no choice but to fail the + # synchronization and kick the new disk out of the mirror. + atf_check gmirror insert $name $md2 + sleep 0.1 + syncwait + atf_check [ $(gmirror status -s $name | wc -l) -eq 1 ] + atf_check -s exit:0 -o match:"DEGRADED $md1 \(ACTIVE\)" \ + gmirror status -s $name +} +sync_read_error_2_disks_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + + atf_check -s exit:0 -e empty -o not-empty sysctl ${REG_READ_FP}='off' + gmirror_test_cleanup +} + +atf_test_case sync_read_error_3_disks cleanup +sync_read_error_3_disks_head() +{ + atf_set "descr" \ + "Ensure that we properly handle read errors during synchronization." + atf_set "require.user" "root" +} +sync_read_error_3_disks_body() +{ + . $(atf_get_srcdir)/conf.sh + + f1=$(mktemp ${base}.XXXXXX) + f2=$(mktemp ${base}.XXXXXX) + f3=$(mktemp ${base}.XXXXXX) + + atf_check dd if=/dev/random bs=1M count=32 of=$f1 status=none + atf_check truncate -s 32M $f2 + atf_check truncate -s 32M $f3 + + md1=$(attach_md -t vnode -f ${f1}) + md2=$(attach_md -t vnode -f ${f2}) + md3=$(attach_md -t vnode -f ${f3}) + + atf_check gmirror label $name $md1 + devwait + + atf_check gmirror insert $name $md2 + syncwait + + atf_check -s exit:0 -e empty -o not-empty sysctl ${REG_READ_FP}='1*return(5)' + + # If a read error occurs while synchronizing a new disk, and we have + # multiple active disks, we retry the read after an error. The disk + # which returned the read error is kicked out of the mirror. + atf_check gmirror insert $name $md3 + syncwait + atf_check [ $(gmirror status -s $name | wc -l) -eq 2 ] + atf_check -s exit:0 -o match:"DEGRADED $md3 \(ACTIVE\)" \ + gmirror status -s $name + + # Make sure that the two active disks are identical. Destroy the + # mirror first so that the metadata sectors are wiped. + if $(gmirror status -s $name | grep -q $md1); then + active=$md1 + else + active=$md2 + fi + atf_check gmirror destroy $name + atf_check cmp /dev/$active /dev/$md3 +} +sync_read_error_3_disks_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + + atf_check -s exit:0 -e empty -o not-empty sysctl ${REG_READ_FP}='off' + gmirror_test_cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case sync_read_error_2_disks + atf_add_test_case sync_read_error_3_disks +} |