aboutsummaryrefslogtreecommitdiff
path: root/tests/sys/geom/class/mirror
diff options
context:
space:
mode:
Diffstat (limited to 'tests/sys/geom/class/mirror')
-rw-r--r--tests/sys/geom/class/mirror/10_test.sh68
-rw-r--r--tests/sys/geom/class/mirror/11_test.sh83
-rw-r--r--tests/sys/geom/class/mirror/12_test.sh67
-rw-r--r--tests/sys/geom/class/mirror/13_test.sh80
-rw-r--r--tests/sys/geom/class/mirror/1_test.sh22
-rw-r--r--tests/sys/geom/class/mirror/2_test.sh51
-rw-r--r--tests/sys/geom/class/mirror/3_test.sh63
-rw-r--r--tests/sys/geom/class/mirror/4_test.sh65
-rw-r--r--tests/sys/geom/class/mirror/5_test.sh63
-rw-r--r--tests/sys/geom/class/mirror/6_test.sh44
-rw-r--r--tests/sys/geom/class/mirror/7_test.sh63
-rw-r--r--tests/sys/geom/class/mirror/8_test.sh55
-rw-r--r--tests/sys/geom/class/mirror/9_test.sh57
-rw-r--r--tests/sys/geom/class/mirror/Makefile31
-rw-r--r--tests/sys/geom/class/mirror/Makefile.depend10
-rwxr-xr-xtests/sys/geom/class/mirror/component_selection.sh139
-rw-r--r--tests/sys/geom/class/mirror/conf.sh57
-rw-r--r--tests/sys/geom/class/mirror/sync_error.sh108
18 files changed, 1126 insertions, 0 deletions
diff --git a/tests/sys/geom/class/mirror/10_test.sh b/tests/sys/geom/class/mirror/10_test.sh
new file mode 100644
index 000000000000..351689d1e185
--- /dev/null
+++ b/tests/sys/geom/class/mirror/10_test.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+# Test handling of read errors.
+
+. $(dirname $0)/conf.sh
+
+echo 1..3
+
+set -e
+
+ddbs=2048
+regreadfp="debug.fail_point.g_mirror_regular_request_read"
+m1=$(mktemp $base.XXXXXX)
+m2=$(mktemp $base.XXXXXX)
+
+dd if=/dev/random of=$m1 bs=$ddbs count=1024 >/dev/null 2>&1
+dd if=/dev/zero of=$m2 bs=$ddbs count=1024 >/dev/null 2>&1
+
+attach_md us0 -t vnode -f $m1
+attach_md us1 -t vnode -f $m2
+
+gmirror label $name /dev/$us0
+gmirror insert $name /dev/$us1
+devwait
+syncwait
+
+tmp1=$(mktemp $base.XXXXXX)
+tmp2=$(mktemp $base.XXXXXX)
+
+EIO=5
+# gmirror should retry a failed read from the other mirror.
+sysctl ${regreadfp}="1*return(${EIO})[pid $(gmirror_worker_pid)]"
+dd if=/dev/mirror/$name of=$tmp1 iseek=256 bs=$ddbs count=1 >/dev/null 2>&1
+dd if=/dev/$us1 of=$tmp2 iseek=256 bs=$ddbs count=1 >/dev/null 2>&1
+sysctl ${regreadfp}='off'
+
+if cmp -s $tmp1 $tmp2; then
+ echo "ok 1"
+else
+ echo "not ok 1"
+fi
+
+# Make sure that one of the mirrors was marked broken.
+genid1=$(gmirror dump /dev/$us0 | awk '/^[[:space:]]*genid: /{print $2}')
+genid2=$(gmirror dump /dev/$us1 | awk '/^[[:space:]]*genid: /{print $2}')
+if [ $genid1 -eq $(($genid2 + 1)) -o $genid2 -eq $(($genid1 + 1)) ]; then
+ echo "ok 2"
+else
+ echo "not ok 2"
+fi
+
+# Force a retaste of the disconnected component.
+if [ $(gmirror status -s $name | awk '{print $3}') = $us0 ]; then
+ detach_md $us1
+ attach_md us1 -t vnode -f $m2
+else
+ detach_md $us0
+ attach_md us0 -t vnode -f $m1
+fi
+
+# Make sure that the component wasn't re-added to the gmirror.
+if [ $(gmirror status -s $name | wc -l) -eq 1 ]; then
+ echo "ok 3"
+else
+ echo "not ok 3"
+fi
+
+rm -f $m1 $m2 $tmp1 $tmp2
diff --git a/tests/sys/geom/class/mirror/11_test.sh b/tests/sys/geom/class/mirror/11_test.sh
new file mode 100644
index 000000000000..0e498ae03d15
--- /dev/null
+++ b/tests/sys/geom/class/mirror/11_test.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+# Test handling of read errors.
+
+. $(dirname $0)/conf.sh
+
+echo 1..4
+
+set -e
+
+ddbs=2048
+regreadfp="debug.fail_point.g_mirror_regular_request_read"
+m1=$(mktemp $base.XXXXXX)
+m2=$(mktemp $base.XXXXXX)
+
+dd if=/dev/random of=$m1 bs=$ddbs count=1024 >/dev/null 2>&1
+dd if=/dev/zero of=$m2 bs=$ddbs count=1024 >/dev/null 2>&1
+
+attach_md us0 -t vnode -f $m1
+attach_md us1 -t vnode -f $m2
+
+gmirror label $name /dev/$us0
+gmirror insert $name /dev/$us1
+devwait
+syncwait
+
+tmp1=$(mktemp $base.XXXXXX)
+tmp2=$(mktemp $base.XXXXXX)
+
+ENXIO=6
+# gmirror has special handling for ENXIO. It does not mark the failed component
+# as broken, allowing it to rejoin the mirror automatically when it appears.
+sysctl ${regreadfp}="1*return(${ENXIO})[pid $(gmirror_worker_pid)]"
+dd if=/dev/mirror/$name of=$tmp1 iseek=512 bs=$ddbs count=1 >/dev/null 2>&1
+dd if=/dev/$us1 of=$tmp2 iseek=512 bs=$ddbs count=1 >/dev/null 2>&1
+sysctl ${regreadfp}='off'
+
+if cmp -s $tmp1 $tmp2; then
+ echo "ok 1"
+else
+ echo "not ok 1"
+fi
+
+# Verify that the genids still match after ENXIO.
+genid1=$(gmirror dump /dev/$us0 | awk '/^[[:space:]]*genid: /{print $2}')
+genid2=$(gmirror dump /dev/$us1 | awk '/^[[:space:]]*genid: /{print $2}')
+if [ $genid1 -eq $genid2 ]; then
+ echo "ok 2"
+else
+ echo "not ok 2"
+fi
+
+# Trigger a syncid bump.
+dd if=/dev/zero of=/dev/mirror/$name bs=$ddbs count=1 >/dev/null 2>&1
+
+# The ENXIO+write should have caused a syncid bump.
+syncid1=$(gmirror dump /dev/$us0 | awk '/^[[:space:]]*syncid: /{print $2}')
+syncid2=$(gmirror dump /dev/$us1 | awk '/^[[:space:]]*syncid: /{print $2}')
+if [ $syncid1 -eq $(($syncid2 + 1)) -o $syncid2 -eq $(($syncid1 + 1)) ]; then
+ echo "ok 3"
+else
+ echo "not ok 3"
+fi
+
+# Force a retaste of the disconnected component.
+if [ $(gmirror status -s $name | awk '{print $3}') = $us0 ]; then
+ detach_md $us1
+ attach_md us1 -t vnode -f $m2
+else
+ detach_md $us0
+ attach_md us0 -t vnode -f $m1
+fi
+
+# Make sure that the retaste caused the mirror to automatically be re-added.
+if [ $(gmirror status -s $name | wc -l) -eq 2 ]; then
+ echo "ok 4"
+else
+ echo "not ok 4"
+fi
+
+syncwait
+
+rm -f $m1 $m2 $tmp1 $tmp2
diff --git a/tests/sys/geom/class/mirror/12_test.sh b/tests/sys/geom/class/mirror/12_test.sh
new file mode 100644
index 000000000000..4f24dd081fef
--- /dev/null
+++ b/tests/sys/geom/class/mirror/12_test.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+# Test handling of write errors.
+
+. $(dirname $0)/conf.sh
+
+echo 1..3
+
+set -e
+
+ddbs=2048
+regwritefp="debug.fail_point.g_mirror_regular_request_write"
+m1=$(mktemp $base.XXXXXX)
+m2=$(mktemp $base.XXXXXX)
+
+dd if=/dev/zero of=$m1 bs=$ddbs count=1024 >/dev/null 2>&1
+dd if=/dev/zero of=$m2 bs=$ddbs count=1024 >/dev/null 2>&1
+
+attach_md us0 -t vnode -f $m1
+attach_md us1 -t vnode -f $m2
+
+gmirror label $name /dev/$us0 /dev/$us1
+devwait
+
+tmp1=$(mktemp $base.XXXXXX)
+tmp2=$(mktemp $base.XXXXXX)
+dd if=/dev/random of=$tmp1 bs=$ddbs count=1 >/dev/null 2>&1
+
+EIO=5
+# gmirror should kick one of the mirrors out after hitting EIO.
+sysctl ${regwritefp}="1*return(${EIO})[pid $(gmirror_worker_pid)]"
+dd if=$tmp1 of=/dev/mirror/$name bs=$ddbs count=1 >/dev/null 2>&1
+dd if=/dev/mirror/$name of=$tmp2 bs=$ddbs count=1 >/dev/null 2>&1
+sysctl ${regwritefp}='off'
+
+if cmp -s $tmp1 $tmp2; then
+ echo "ok 1"
+else
+ echo "not ok 1"
+fi
+
+# Make sure that one of the mirrors was marked broken.
+genid1=$(gmirror dump /dev/$us0 | awk '/^[[:space:]]*genid: /{print $2}')
+genid2=$(gmirror dump /dev/$us1 | awk '/^[[:space:]]*genid: /{print $2}')
+if [ $genid1 -eq $(($genid2 + 1)) -o $genid2 -eq $(($genid1 + 1)) ]; then
+ echo "ok 2"
+else
+ echo "not ok 2"
+fi
+
+# Force a retaste of the disconnected component.
+if [ $(gmirror status -s $name | awk '{print $3}') = $us0 ]; then
+ detach_md $us1
+ attach_md us1 -t vnode -f $m2
+else
+ detach_md $us0
+ attach_md us0 -t vnode -f $m1
+fi
+
+# Make sure that the component wasn't re-added to the gmirror.
+if [ $(gmirror status -s $name | wc -l) -eq 1 ]; then
+ echo "ok 3"
+else
+ echo "not ok 3"
+fi
+
+rm -f $m1 $m2 $tmp1 $tmp2
diff --git a/tests/sys/geom/class/mirror/13_test.sh b/tests/sys/geom/class/mirror/13_test.sh
new file mode 100644
index 000000000000..c312a1b7a795
--- /dev/null
+++ b/tests/sys/geom/class/mirror/13_test.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+# Test handling of write errors.
+
+. $(dirname $0)/conf.sh
+
+echo 1..4
+
+set -e
+
+ddbs=2048
+regwritefp="debug.fail_point.g_mirror_regular_request_write"
+m1=$(mktemp $base.XXXXXX)
+m2=$(mktemp $base.XXXXXX)
+
+dd if=/dev/random of=$m1 bs=$ddbs count=1024 >/dev/null 2>&1
+dd if=/dev/zero of=$m2 bs=$ddbs count=1024 >/dev/null 2>&1
+
+attach_md us0 -t vnode -f $m1
+attach_md us1 -t vnode -f $m2
+
+gmirror label $name /dev/$us0 /dev/$us1
+devwait
+
+tmp1=$(mktemp $base.XXXXXX)
+tmp2=$(mktemp $base.XXXXXX)
+
+dd if=/dev/random of=$tmp1 bs=$ddbs count=1 >/dev/null 2>&1
+
+ENXIO=6
+# gmirror has special handling for ENXIO. It does not mark the failed component
+# as broken, allowing it to rejoin the mirror automatically when it appears.
+sysctl ${regwritefp}="1*return(${ENXIO})[pid $(gmirror_worker_pid)]"
+dd if=$tmp1 of=/dev/mirror/$name bs=$ddbs count=1 >/dev/null 2>&1
+dd if=/dev/mirror/$name of=$tmp2 bs=$ddbs count=1 >/dev/null 2>&1
+sysctl ${regwritefp}='off'
+
+if cmp -s $tmp1 $tmp2; then
+ echo "ok 1"
+else
+ echo "not ok 1"
+fi
+
+# Verify that the genids still match after ENXIO.
+genid1=$(gmirror dump /dev/$us0 | awk '/^[[:space:]]*genid: /{print $2}')
+genid2=$(gmirror dump /dev/$us1 | awk '/^[[:space:]]*genid: /{print $2}')
+if [ $genid1 -eq $genid2 ]; then
+ echo "ok 2"
+else
+ echo "not ok 2"
+fi
+
+# The ENXIO should have caused a syncid bump.
+syncid1=$(gmirror dump /dev/$us0 | awk '/^[[:space:]]*syncid: /{print $2}')
+syncid2=$(gmirror dump /dev/$us1 | awk '/^[[:space:]]*syncid: /{print $2}')
+if [ $syncid1 -eq $(($syncid2 + 1)) -o $syncid2 -eq $(($syncid1 + 1)) ]; then
+ echo "ok 3"
+else
+ echo "not ok 3"
+fi
+
+# Force a retaste of the disconnected component.
+if [ $(gmirror status -s $name | awk '{print $3}') = $us0 ]; then
+ detach_md $us1
+ attach_md us1 -t vnode -f $m2
+else
+ detach_md $us0
+ attach_md us0 -t vnode -f $m1
+fi
+
+# Make sure that the retaste caused the mirror to automatically be re-added.
+if [ $(gmirror status -s $name | wc -l) -eq 2 ]; then
+ echo "ok 4"
+else
+ echo "not ok 4"
+fi
+
+syncwait
+
+rm -f $m1 $m2 $tmp1 $tmp2
diff --git a/tests/sys/geom/class/mirror/1_test.sh b/tests/sys/geom/class/mirror/1_test.sh
new file mode 100644
index 000000000000..929aa1c6ddcf
--- /dev/null
+++ b/tests/sys/geom/class/mirror/1_test.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+. `dirname $0`/conf.sh
+
+echo "1..1"
+
+attach_md us0 -t malloc -s 1M || exit 1
+attach_md us1 -t malloc -s 2M || exit 1
+attach_md us2 -t malloc -s 3M || exit 1
+
+gmirror label $name /dev/$us0 /dev/$us1 /dev/$us2 || exit 1
+devwait
+
+# Size of created device should be 1MB - 512b.
+
+size=`diskinfo /dev/mirror/${name} | awk '{print $3}'`
+
+if [ $size -eq 1048064 ]; then
+ echo "ok 1"
+else
+ echo "not ok 1"
+fi
diff --git a/tests/sys/geom/class/mirror/2_test.sh b/tests/sys/geom/class/mirror/2_test.sh
new file mode 100644
index 000000000000..31bb426d05d7
--- /dev/null
+++ b/tests/sys/geom/class/mirror/2_test.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+. `dirname $0`/conf.sh
+
+echo "1..4"
+
+balance="round-robin"
+ddbs=2048
+nblocks1=1024
+nblocks2=`expr $nblocks1 / \( $ddbs / 512 \)`
+src=`mktemp $base.XXXXXX` || exit 1
+dst=`mktemp $base.XXXXXX` || exit 1
+
+dd if=/dev/random of=${src} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+attach_md us0 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us1 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us2 -t malloc -s `expr $nblocks1 + 1` || exit 1
+
+gmirror label -b $balance $name /dev/${us0} /dev/${us1} /dev/${us2} || exit 1
+devwait
+
+dd if=${src} of=/dev/mirror/${name} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 1"
+else
+ echo "ok 1"
+fi
+dd if=/dev/${us0} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 2"
+else
+ echo "ok 2"
+fi
+dd if=/dev/${us1} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 3"
+else
+ echo "ok 3"
+fi
+
+dd if=/dev/${us2} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 4"
+else
+ echo "ok 4"
+fi
+
+rm -f ${src} ${dst}
diff --git a/tests/sys/geom/class/mirror/3_test.sh b/tests/sys/geom/class/mirror/3_test.sh
new file mode 100644
index 000000000000..dd2ca8f028fd
--- /dev/null
+++ b/tests/sys/geom/class/mirror/3_test.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+. `dirname $0`/conf.sh
+
+echo "1..5"
+
+balance="round-robin"
+ddbs=2048
+nblocks1=1024
+nblocks2=`expr $nblocks1 / \( $ddbs / 512 \)`
+src=`mktemp $base.XXXXXX` || exit 1
+dst=`mktemp $base.XXXXXX` || exit 1
+
+dd if=/dev/random of=${src} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+attach_md us0 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us1 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us2 -t malloc -s `expr $nblocks1 + 1` || exit 1
+
+gmirror label -b $balance $name /dev/${us0} /dev/${us1} /dev/${us2} || exit 1
+devwait
+
+dd if=${src} of=/dev/mirror/${name} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 1"
+else
+ echo "ok 1"
+fi
+
+gmirror remove $name ${us0}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 2"
+else
+ echo "ok 2"
+fi
+
+gmirror remove $name ${us1}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 3"
+else
+ echo "ok 3"
+fi
+
+gmirror remove $name ${us2}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 4"
+else
+ echo "ok 4"
+fi
+
+# mirror/${name} should be removed.
+if [ -c /dev/${name} ]; then
+ echo "not ok 5"
+else
+ echo "ok 5"
+fi
+
+rm -f ${src} ${dst}
diff --git a/tests/sys/geom/class/mirror/4_test.sh b/tests/sys/geom/class/mirror/4_test.sh
new file mode 100644
index 000000000000..a5f469a2d95e
--- /dev/null
+++ b/tests/sys/geom/class/mirror/4_test.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+. `dirname $0`/conf.sh
+
+echo "1..5"
+
+balance="load"
+ddbs=2048
+nblocks1=1024
+nblocks2=`expr $nblocks1 / \( $ddbs / 512 \)`
+src=`mktemp $base.XXXXXX` || exit 1
+dst=`mktemp $base.XXXXXX` || exit 1
+
+dd if=/dev/random of=${src} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+attach_md us0 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us1 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us2 -t malloc -s `expr $nblocks1 + 1` || exit 1
+
+gmirror label -b $balance $name /dev/${us0} /dev/${us1} /dev/${us2} || exit 1
+devwait
+
+dd if=${src} of=/dev/mirror/${name} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 1"
+else
+ echo "ok 1"
+fi
+
+gmirror remove $name ${us0}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 2"
+else
+ echo "ok 2"
+fi
+
+gmirror remove $name ${us1}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 3"
+else
+ echo "ok 3"
+fi
+
+gmirror remove $name ${us2}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 4"
+else
+ echo "ok 4"
+fi
+
+gmirror destroy $name
+
+# mirror/${name} should be removed.
+if [ -c /dev/${name} ]; then
+ echo "not ok 5"
+else
+ echo "ok 5"
+fi
+
+rm -f ${src} ${dst}
diff --git a/tests/sys/geom/class/mirror/5_test.sh b/tests/sys/geom/class/mirror/5_test.sh
new file mode 100644
index 000000000000..43062dc1feea
--- /dev/null
+++ b/tests/sys/geom/class/mirror/5_test.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+. `dirname $0`/conf.sh
+
+echo "1..5"
+
+balance="split"
+ddbs=8192
+nblocks1=1024
+nblocks2=`expr $nblocks1 / \( $ddbs / 512 \)`
+src=`mktemp $base.XXXXXX` || exit 1
+dst=`mktemp $base.XXXXXX` || exit 1
+
+dd if=/dev/random of=${src} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+attach_md us0 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us1 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us2 -t malloc -s `expr $nblocks1 + 1` || exit 1
+
+gmirror label -b $balance -s `expr $ddbs / 2` $name /dev/${us0} /dev/${us1} /dev/${us2} || exit 1
+devwait
+
+dd if=${src} of=/dev/mirror/${name} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 1"
+else
+ echo "ok 1"
+fi
+
+gmirror remove $name ${us0}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 2"
+else
+ echo "ok 2"
+fi
+
+gmirror remove $name ${us1}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 3"
+else
+ echo "ok 3"
+fi
+
+gmirror remove $name ${us2}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 4"
+else
+ echo "ok 4"
+fi
+
+# mirror/${name} should be removed.
+if [ -c /dev/${name} ]; then
+ echo "not ok 5"
+else
+ echo "ok 5"
+fi
+
+rm -f ${src} ${dst}
diff --git a/tests/sys/geom/class/mirror/6_test.sh b/tests/sys/geom/class/mirror/6_test.sh
new file mode 100644
index 000000000000..f37a45404642
--- /dev/null
+++ b/tests/sys/geom/class/mirror/6_test.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+. `dirname $0`/conf.sh
+
+echo "1..2"
+
+balance="split"
+ddbs=8192
+nblocks1=1024
+nblocks2=`expr $nblocks1 / \( $ddbs / 512 \)`
+src=`mktemp $base.XXXXXX` || exit 1
+dst=`mktemp $base.XXXXXX` || exit 1
+
+dd if=/dev/random of=${src} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+attach_md us0 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us1 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us2 -t malloc -s `expr $nblocks1 + 1` || exit 1
+
+gmirror label -b $balance -s `expr $ddbs / 2` $name /dev/${us0} /dev/${us1} || exit 1
+devwait
+
+dd if=${src} of=/dev/mirror/${name} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+dd if=/dev/zero of=/dev/${us2} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 1"
+else
+ echo "ok 1"
+fi
+
+# Connect disk to the mirror.
+gmirror insert ${name} ${us2}
+# Wait for synchronization.
+sleep 1
+dd if=/dev/${us2} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 2"
+else
+ echo "ok 2"
+fi
+
+rm -f ${src} ${dst}
diff --git a/tests/sys/geom/class/mirror/7_test.sh b/tests/sys/geom/class/mirror/7_test.sh
new file mode 100644
index 000000000000..5f93f2fc4943
--- /dev/null
+++ b/tests/sys/geom/class/mirror/7_test.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+. `dirname $0`/conf.sh
+
+echo "1..5"
+
+balance="prefer"
+ddbs=2048
+nblocks1=1024
+nblocks2=`expr $nblocks1 / \( $ddbs / 512 \)`
+src=`mktemp $base.XXXXXX` || exit 1
+dst=`mktemp $base.XXXXXX` || exit 1
+
+dd if=/dev/random of=${src} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+attach_md us0 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us1 -t malloc -s `expr $nblocks1 + 1` || exit 1
+attach_md us2 -t malloc -s `expr $nblocks1 + 1` || exit 1
+
+gmirror label -b $balance $name /dev/${us0} /dev/${us1} /dev/${us2} || exit 1
+devwait
+
+dd if=${src} of=/dev/mirror/${name} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 1"
+else
+ echo "ok 1"
+fi
+
+gmirror remove $name ${us0}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 2"
+else
+ echo "ok 2"
+fi
+
+gmirror remove $name ${us1}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 3"
+else
+ echo "ok 3"
+fi
+
+gmirror remove $name ${us2}
+dd if=/dev/mirror/${name} of=${dst} bs=$ddbs count=$nblocks2 >/dev/null 2>&1
+if [ `md5 -q ${src}` != `md5 -q ${dst}` ]; then
+ echo "not ok 4"
+else
+ echo "ok 4"
+fi
+
+# mirror/${name} should be removed.
+if [ -c /dev/${name} ]; then
+ echo "not ok 5"
+else
+ echo "ok 5"
+fi
+
+rm -f ${src} ${dst}
diff --git a/tests/sys/geom/class/mirror/8_test.sh b/tests/sys/geom/class/mirror/8_test.sh
new file mode 100644
index 000000000000..baea157a0ba8
--- /dev/null
+++ b/tests/sys/geom/class/mirror/8_test.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+# Regression test for r317712.
+
+. `dirname $0`/conf.sh
+
+if ! [ -c /dev/mdctl ]; then
+ echo "1..0 # SKIP no /dev/mdctl to create md devices"
+ exit 0
+fi
+
+echo 1..1
+
+ddbs=2048
+m1=`mktemp $base.XXXXXX` || exit 1
+m2=`mktemp $base.XXXXXX` || exit 1
+
+dd if=/dev/zero of=$m1 bs=$ddbs count=1024 >/dev/null 2>&1
+dd if=/dev/zero of=$m2 bs=$ddbs count=1024 >/dev/null 2>&1
+
+us0=$(mdconfig -t vnode -f $m1) || exit 1
+us1=$(mdconfig -t vnode -f $m2) || exit 1
+
+gmirror label $name /dev/$us0 /dev/$us1 || exit 1
+devwait
+
+# Ensure that the mirrors are marked dirty, and then disconnect them.
+# We need to have the gmirror provider open when destroying the MDs since
+# gmirror will automatically mark the mirrors clean when the provider is closed.
+exec 9>/dev/mirror/$name
+dd if=/dev/zero bs=$ddbs count=1 >&9 2>/dev/null
+mdconfig -d -u ${us0#md} -o force || exit 1
+mdconfig -d -u ${us1#md} -o force || exit 1
+exec 9>&-
+
+dd if=/dev/random of=$m1 bs=$ddbs count=1 conv=notrunc >/dev/null 2>&1
+attach_md us0 -t vnode -f $m1 || exit 1
+devwait # This will take kern.geom.mirror.timeout seconds.
+
+# Re-attach the second mirror and wait for it to synchronize.
+attach_md us1 -t vnode -f $m2 || exit 1
+syncwait
+
+# Verify the two mirrors are identical. Destroy the gmirror first so that
+# the mirror metadata is wiped; otherwise the metadata blocks will fail
+# the comparison. It would be nice to do this with a "gmirror verify"
+# command instead.
+gmirror destroy $name
+if cmp -s ${m1} ${m2}; then
+ echo "ok 1"
+else
+ echo "not ok 1"
+fi
+
+rm -f $m1 $m2
diff --git a/tests/sys/geom/class/mirror/9_test.sh b/tests/sys/geom/class/mirror/9_test.sh
new file mode 100644
index 000000000000..6bcb26860615
--- /dev/null
+++ b/tests/sys/geom/class/mirror/9_test.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+# Regression test for r306743.
+
+. `dirname $0`/conf.sh
+
+echo 1..1
+
+ddbs=2048
+m1=`mktemp $base.XXXXXX` || exit 1
+m2=`mktemp $base.XXXXXX` || exit 1
+m3=`mktemp $base.XXXXXX` || exit 1
+
+dd if=/dev/zero of=$m1 bs=$ddbs count=1024 >/dev/null 2>&1
+dd if=/dev/zero of=$m2 bs=$ddbs count=1024 >/dev/null 2>&1
+dd if=/dev/zero of=$m3 bs=$ddbs count=1024 >/dev/null 2>&1
+
+attach_md us0 -t vnode -f $m1 || exit 1
+attach_md us1 -t vnode -f $m2 || exit 1
+attach_md us2 -t vnode -f $m3 || exit 1
+
+gmirror label $name /dev/$us0 /dev/$us1 || exit 1
+devwait
+
+# Break one of the mirrors by forcing a single metadata write error.
+# When dd closes the mirror provider, gmirror will attempt to mark the mirrors
+# clean, and will kick one of the mirrors out upon hitting the error.
+sysctl debug.fail_point.g_mirror_metadata_write="1*return(5)[pid $(gmirror_worker_pid)]" || exit 1
+dd if=/dev/random of=/dev/mirror/$name bs=$ddbs count=1 >/dev/null 2>&1
+sysctl debug.fail_point.g_mirror_metadata_write='off' || exit 1
+
+# Replace the broken mirror, and then stop the gmirror.
+gmirror forget $name || exit 1
+gmirror insert $name /dev/$us2 || exit 1
+syncwait
+gmirror stop $name || exit 1
+
+# Restart the gmirror on the original two mirrors. One of them is broken,
+# so we should end up with a degraded gmirror.
+gmirror activate $name /dev/$us0 /dev/$us1 || exit 1
+devwait
+dd if=/dev/random of=/dev/mirror/$name bs=$ddbs count=1 >/dev/null 2>&1
+
+# Re-add the replacement mirror and verify the two mirrors are synchronized.
+# Destroy the gmirror first so that the mirror metadata is wiped; otherwise
+# the metadata blocks will fail the comparison. It would be nice to do this
+# with a "gmirror verify" command instead.
+gmirror activate $name /dev/$us2 || exit 1
+syncwait
+gmirror destroy $name || exit 1
+if cmp -s $m1 $m3; then
+ echo "ok 1"
+else
+ echo "not ok 1"
+fi
+
+rm -f $m1 $m2 $m3
diff --git a/tests/sys/geom/class/mirror/Makefile b/tests/sys/geom/class/mirror/Makefile
new file mode 100644
index 000000000000..635288cc3d53
--- /dev/null
+++ b/tests/sys/geom/class/mirror/Makefile
@@ -0,0 +1,31 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/sys/geom/class/${.CURDIR:T}
+
+TAP_TESTS_SH+= 1_test
+TAP_TESTS_SH+= 2_test
+TAP_TESTS_SH+= 3_test
+TAP_TESTS_SH+= 4_test
+TAP_TESTS_SH+= 5_test
+TAP_TESTS_SH+= 6_test
+TAP_TESTS_SH+= 7_test
+TAP_TESTS_SH+= 8_test
+TAP_TESTS_SH+= 9_test
+TAP_TESTS_SH+= 10_test
+TAP_TESTS_SH+= 11_test
+TAP_TESTS_SH+= 12_test
+TAP_TESTS_SH+= 13_test
+
+ATF_TESTS_SH+= component_selection
+ATF_TESTS_SH+= sync_error
+
+# Tests use a global gmirror fail point.
+TEST_METADATA+= is_exclusive=true
+
+${PACKAGE}FILES+= conf.sh
+
+.for t in ${TAP_TESTS_SH}
+TEST_METADATA.$t+= required_user="root"
+.endfor
+
+.include <bsd.test.mk>
diff --git a/tests/sys/geom/class/mirror/Makefile.depend b/tests/sys/geom/class/mirror/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/tests/sys/geom/class/mirror/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/tests/sys/geom/class/mirror/component_selection.sh b/tests/sys/geom/class/mirror/component_selection.sh
new file mode 100755
index 000000000000..b5c8cec78c61
--- /dev/null
+++ b/tests/sys/geom/class/mirror/component_selection.sh
@@ -0,0 +1,139 @@
+
+ATF_TEST=true
+class=mirror
+. $(atf_get_srcdir)/conf.sh
+
+atf_test_case run_latest_genid cleanup
+run_latest_genid_head()
+{
+ atf_set "descr" \
+ "Ensure that we properly select components (latest genid) during STARTING."
+ atf_set "require.user" "root"
+}
+run_latest_genid_body()
+{
+ geom_atf_test_setup
+ if ! error_message=$(geom_load_class_if_needed nop); then
+ atf_skip "$error_message"
+ fi
+
+ f1=$(mktemp ${base}.XXXXXX)
+ f2=$(mktemp ${base}.XXXXXX)
+ f3=$(mktemp ${base}.XXXXXX)
+ rnd1=$(mktemp ${base}.XXXXXX)
+ rnd2=$(mktemp ${base}.XXXXXX)
+
+ atf_check truncate -s 2M $f1
+ atf_check truncate -s 2M $f2
+ atf_check truncate -s 2M $f3
+ dd if=/dev/urandom bs=512 count=1 of="$rnd1"
+ dd if=/dev/urandom bs=512 count=1 of="$rnd2"
+
+ attach_md md1 -t vnode -f ${f1}
+ attach_md md2 -t vnode -f ${f2}
+ attach_md md3 -t vnode -f ${f3}
+
+ # Use a gnop for md1 just for consistency; it's not used for anything.
+ atf_check gnop create $md1
+ atf_check gnop create $md2
+ atf_check gnop create $md3
+ # Hardcode component names so that the non-.nop device isn't tasted
+ # instead.
+ atf_check gmirror label -h $name ${md1}.nop
+ devwait
+
+ atf_check gmirror insert -h $name ${md2}.nop
+ atf_check gmirror insert -h $name ${md3}.nop
+ syncwait
+
+ # Fail mirror 3, writing known contents to mirror 1+2 block 1
+ atf_check -s exit:0 -e empty -o empty \
+ gnop configure -w 100 ${md3}.nop
+ atf_check -s exit:0 dd if="$rnd1" bs=512 count=1 oseek=1 conv=notrunc \
+ of=/dev/mirror/$name status=none
+
+ disconnectwait nop "${md3}.nop"
+
+ # Should have two mirrors remaining after md3 was evicted
+ atf_check [ $(gmirror status -s $name | wc -l) -eq 2 ]
+ atf_check -s exit:0 -o match:"DEGRADED ${md1}.nop \(ACTIVE\)" \
+ gmirror status -s $name
+ atf_check -s exit:0 -o match:"DEGRADED ${md2}.nop \(ACTIVE\)" \
+ gmirror status -s $name
+
+ # Repeat:
+ # Fail mirror 2, writing known contents to mirror 1 block 2
+ atf_check -s exit:0 -e empty -o empty \
+ gnop configure -w 100 ${md2}.nop
+ atf_check -s exit:0 dd if="$rnd2" bs=512 count=2 oseek=1 conv=notrunc \
+ of=/dev/mirror/$name status=none
+
+ disconnectwait nop "${md2}.nop"
+
+ # Should have one mirror remaining after md2 was evicted
+ atf_check [ $(gmirror status -s $name | wc -l) -eq 1 ]
+ atf_check -s exit:0 -o match:"DEGRADED ${md1}.nop \(ACTIVE\)" \
+ gmirror status -s $name
+
+ # Stop the mirror and remove the pieces so gmirror can't see them.
+ atf_check gmirror stop $name
+ atf_check gnop destroy ${md1}.nop
+ atf_check gnop destroy ${md2}.nop
+ atf_check gnop destroy ${md3}.nop
+
+ # Rebuild; spin up "disk" with lowest genid
+ atf_check gnop create $md3
+ md3gen=$(gmirror dump /dev/${md3}.nop | grep genid | cut -d: -f2)
+ # Assert gmirror is referencing this component for now:
+ atf_check [ $(consumerrefs nop ${md3}.nop) = "r1w1e1" ]
+
+ # Adding newer genid should kick out old component
+ atf_check gnop create $md2
+ md2gen=$(gmirror dump /dev/${md2}.nop | grep genid | cut -d: -f2)
+ atf_check [ $md2gen -gt $md3gen ]
+
+ disconnectwait nop "${md3}.nop"
+
+ # Can't test this because 'status' doesn't exist until RUNNING:
+ #atf_check [ $(gmirror status -s $name | wc -l) -eq 1 ]
+ # But as a substitute, assert gmirror has dropped reference to staler
+ # component in favor of newer component:
+ atf_check [ $(consumerrefs nop ${md2}.nop) = "r1w1e1" ]
+
+ # ditto
+ atf_check gnop create $md1
+ md1gen=$(gmirror dump /dev/${md1}.nop | grep genid | cut -d: -f2)
+ atf_check [ $md1gen -gt $md2gen ]
+
+ disconnectwait nop "${md2}.nop"
+
+ # Assert gmirror has dropped reference to stale component in favor of
+ # newer component:
+ atf_check [ $(consumerrefs nop ${md1}.nop) = "r1w1e1" ]
+
+ # gmirror won't start the mirror automatically with only one component
+ # ($md0) of configured three, so this waits out the
+ # kern.geom.mirror.timeout:
+ devwait
+
+ atf_check [ $(gmirror status -s $name | wc -l) -eq 1 ]
+ atf_check -s exit:0 -o match:"DEGRADED ${md1}.nop \(ACTIVE\)" \
+ gmirror status -s $name
+}
+run_latest_genid_cleanup()
+{
+ . $(atf_get_srcdir)/conf.sh
+
+ if [ -f "$TEST_MDS_FILE" ]; then
+ while read test_md; do
+ echo "# Removing test gnop: ${test_md}.nop"
+ gnop destroy -f "${test_md}.nop" 2>/dev/null || :
+ done < "$TEST_MDS_FILE"
+ fi
+ gmirror_test_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case run_latest_genid
+}
diff --git a/tests/sys/geom/class/mirror/conf.sh b/tests/sys/geom/class/mirror/conf.sh
new file mode 100644
index 000000000000..5d3b8623dcd6
--- /dev/null
+++ b/tests/sys/geom/class/mirror/conf.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+name="$(mktemp -u mirror.XXXXXX)"
+class="mirror"
+base=`basename $0`
+
+gmirror_test_cleanup()
+{
+ [ -c /dev/$class/$name ] && gmirror destroy $name
+ geom_test_cleanup
+}
+trap gmirror_test_cleanup ABRT EXIT INT TERM
+
+gmirror_worker_pid()
+{
+ pgrep -S -n "g_mirror mirror\..*"
+}
+
+syncwait()
+{
+ while $(gmirror status -s $name | grep -q SYNCHRONIZING); do
+ sleep 0.1;
+ done
+}
+
+consumerrefs()
+{
+ gclass=$1
+ geom=$2
+
+ if [ $# -ne 2 ]; then
+ echo "Bad usage consumerrefs" >&2
+ exit 1
+ fi
+
+ geom "${gclass}" list "${geom}" | \
+ grep -A5 ^Consumers | \
+ grep Mode | \
+ cut -d: -f2
+}
+
+disconnectwait()
+{
+ gclass=$1
+ geom=$2
+
+ if [ $# -ne 2 ]; then
+ echo "Bad usage disconnectwait" >&2
+ exit 1
+ fi
+
+ while [ $(consumerrefs "$gclass" "$geom") != r0w0e0 ]; do
+ sleep 0.05
+ done
+}
+
+. `dirname $0`/../geom_subr.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 000000000000..c51418151f0a
--- /dev/null
+++ b/tests/sys/geom/class/mirror/sync_error.sh
@@ -0,0 +1,108 @@
+
+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
+}