opnsense-src/tests/sys/geom/class/mirror/sync_error.sh
Gleb Smirnoff 96950419f1 tests: don't run atf_* in a subshell
Shell limitation is that a classic function call via $() is a subshell
and atf-sh(3) commands won't work as epxected there.  Subsequently,
atf_skip inside a function won't skip a test.  The test will fail later.

A working approach is to pass desired variable name as argument to
a function and don't run subshell.

Reviewed by:		ngie
Differential Revision:	https://reviews.freebsd.org/D42646
Fixes:			ea82362219
2023-11-27 13:15:59 -08:00

108 lines
2.9 KiB
Bash

ATF_TEST=true
. $(atf_get_srcdir)/conf.sh
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()
{
geom_atf_test_setup
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
attach_md md1 -t vnode -f ${f1}
attach_md md2 -t vnode -f ${f2}
atf_check gmirror label $name $md1
devwait
atf_check -s ignore -e empty -o not-empty sysctl ${REG_READ_FP}="1*return(5)[pid $(gmirror_worker_pid)]"
# 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_check -s ignore -e ignore -o ignore 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()
{
geom_atf_test_setup
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
attach_md md1 -t vnode -f ${f1}
attach_md md2 -t vnode -f ${f2}
attach_md md3 -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)[pid $(gmirror_worker_pid)]"
# 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_check -s ignore -e ignore -o ignore 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
}