diff options
Diffstat (limited to 'tests/sys/geom/class/mirror')
| -rw-r--r-- | tests/sys/geom/class/mirror/10_test.sh | 68 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/11_test.sh | 83 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/12_test.sh | 67 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/13_test.sh | 80 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/1_test.sh | 22 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/2_test.sh | 51 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/3_test.sh | 63 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/4_test.sh | 65 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/5_test.sh | 63 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/6_test.sh | 44 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/7_test.sh | 63 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/8_test.sh | 55 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/9_test.sh | 57 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/Makefile | 31 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/Makefile.depend | 10 | ||||
| -rwxr-xr-x | tests/sys/geom/class/mirror/component_selection.sh | 139 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/conf.sh | 57 | ||||
| -rw-r--r-- | tests/sys/geom/class/mirror/sync_error.sh | 108 |
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 +} |
