]> git.neil.brown.name Git - mdadm.git/blob - test
Release mdadm-4.0
[mdadm.git] / test
1 #!/bin/bash
2 #
3 # run test suite for mdadm
4 user=`id -un`
5 if [ " $user" != " root" ]
6 then echo >&2 "test: testing can only be done as 'root'."
7      exit 1;
8 fi
9
10 prefix='[0-9][0-9]'
11
12 dir=`pwd`
13 mdadm=$dir/mdadm
14 if [ \! -x $mdadm ]
15 then
16    echo >&2 "test: $mdadm isn't usable."
17 fi
18
19 testdir="tests"
20 logdir="$testdir/logs"
21 logsave=0
22 exitonerror=1
23
24 echo "Testing on linux-$(uname -r) kernel"
25
26 # Check whether to run multipath tests
27 modprobe multipath 2> /dev/null
28 if grep -s 'Personalities : .*multipath' > /dev/null /proc/mdstat ; then
29     MULTIPATH="yes"
30 fi
31 INTEGRITY=yes
32 DEVTYPE=loop
33 LVM_VOLGROUP=mdtest
34
35 # make sure to test local mdmon, not system one
36 export MDADM_NO_SYSTEMCTL=1
37
38 # assume md0, md1, md2 exist in /dev
39 md0=/dev/md0 md1=/dev/md1 md2=/dev/md2
40 mdp0=/dev/md_d0
41 mdp1=/dev/md_d1
42
43 # We test mdadm on loop-back block devices.
44 # dir for storing files should be settable by command line maybe
45 targetdir=/var/tmp
46 size=20000
47 # super0, round down to multiple of 64 and substract 64
48 mdsize0=19904
49 # super00 is nested, subtract 128
50 mdsize00=19840
51 # super1.0 round down to multiple of 2, subtract 8
52 mdsize1=19992
53 mdsize1a=19988
54 mdsize12=19988
55 # super1.2 for linear: round to multiple of 2, subtract 4
56 mdsize1_l=19996
57 mdsize2_l=19996
58 # subtract another 4 for bitmaps
59 mdsize1b=19988
60 mdsize11=19992
61 mdsize11a=19456
62 mdsize12=19988
63
64 # ddf needs bigger devices as 32Meg is reserved!
65 ddfsize=65536
66
67 config=/tmp/mdadm.conf
68
69 cleanup() {
70         udevadm settle
71         $mdadm -Ssq 2> /dev/null
72         case $DEVTYPE in
73         loop)
74           for d in 0 1 2 3 4 5 6 7  8 9 10 11 12 13
75           do
76             losetup -d /dev/loop$d ; # rm -f $targetdir/mdtest$d
77             rm -f /dev/disk/by-path/loop*
78           done
79           ;;
80         lvm)
81           for d in 0 1 2 3 4 5 6 7  8 9 10 11 12 13
82           do
83             eval "lvremove --quiet -f \$dev$d"
84           done
85           ;;
86         esac
87 }
88
89 ctrl_c() {
90         exitonerror=1
91 }
92
93 do_setup() {
94   trap cleanup 0 1 3 15
95   trap ctrl_c 2
96
97   # make sure there are no loop devices remaining.
98   # udev started things can sometimes prevent them being stopped
99   # immediately
100   while grep loop /proc/partitions > /dev/null 2>&1
101   do
102     mdadm -Ss
103     losetup -d /dev/loop[0-9]* 2> /dev/null
104     sleep 1
105   done
106   devlist=
107   for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13
108   do
109     sz=$size
110     if [ $d -gt 7 ]; then sz=$ddfsize ; fi
111     case $DEVTYPE in
112     loop)
113       [ -f $targetdir/mdtest$d ] || dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1
114       # make sure udev doesn't touch
115       mdadm --zero $targetdir/mdtest$d 2> /dev/null
116       [ -b /dev/loop$d ] || mknod /dev/loop$d b 7 $d
117       if [ $d -eq 7 ]
118       then
119         losetup /dev/loop$d $targetdir/mdtest6 # for multipath use
120       else
121         losetup /dev/loop$d $targetdir/mdtest$d
122       fi
123       eval dev$d=/dev/loop$d
124       eval file$d=$targetdir/mdtest$d
125       ;;
126     lvm)
127       unset MULTIPATH
128       eval dev$d=/dev/mapper/${LVM_VOLGROUP}-mdtest$d
129       if ! lvcreate --quiet -L ${sz}K -n mdtest$d $LVM_VOLGROUP; then
130           trap '' 0 # make sure lvremove is not called
131           eval echo error creating \$dev$d
132           exit 129
133       fi
134       ;;
135     ram)
136       unset MULTIPATH
137       eval dev$d=/dev/ram$d
138       ;;
139     esac
140     eval devlist=\"\$devlist \$dev$d\"
141     eval devlist$d=\"\$devlist\"
142    #" <-- add this quote to un-confuse vim syntax highlighting
143   done
144   path0=$dev6
145   path1=$dev7
146
147   ulimit -c unlimited
148   [ -f /proc/mdstat ] || modprobe md_mod
149   echo 2000 > /proc/sys/dev/raid/speed_limit_max
150   echo 0 > /sys/module/md_mod/parameters/start_ro
151 }
152
153 # mdadm always adds --quiet, and we want to see any unexpected messages
154 mdadm() {
155     rm -f $targetdir/stderr
156     case $* in
157         *-S* ) udevadm settle
158                p=`cat /proc/sys/dev/raid/speed_limit_max`
159                echo 20000 > /proc/sys/dev/raid/speed_limit_max
160     esac
161     case $* in
162         *-C* ) $mdadm 2> $targetdir/stderr --quiet "$@" --auto=yes;;
163         * )    $mdadm 2> $targetdir/stderr --quiet "$@"
164     esac
165     rv=$?
166     case $* in
167         *-S* ) udevadm settle
168                echo $p > /proc/sys/dev/raid/speed_limit_max
169     esac
170     cat >&2 $targetdir/stderr
171     return $rv
172 }
173
174 # check various things
175 check() {
176    case $1 in
177     spares )
178        spares=`tr '] ' '\012\012' < /proc/mdstat | grep -c '(S)' || exit 0`
179        if [ $spares -ne $2 ]
180        then
181           echo >&2 "ERROR expected $2 spares, found $spares"; exit 1;
182        fi
183       ;;
184     raid* | linear )
185       grep -s "active $1 " /proc/mdstat > /dev/null || {
186                 echo >&2 "ERROR active $1 not found" ; cat /proc/mdstat ; exit 1;}
187      ;;
188     algorithm )
189       grep -s " algorithm $2 " /proc/mdstat > /dev/null || {
190           echo >&2 "ERROR algorithm $2 not found"; cat /proc/mdstat; exit 1;}
191      ;;
192     resync | recovery | reshape)
193         cnt=5
194         while ! grep -s $1 /proc/mdstat > /dev/null
195         do
196             if [ $cnt -gt 0 ] && grep -v idle /sys/block/md*/md/sync_action > /dev/null
197             then # Something isn't idle - wait a bit
198                 sleep 0.5
199                 cnt=$[cnt-1]
200             else
201                 echo >&2 ERROR no $1 happening; cat /proc/mdstat; exit 1
202             fi
203         done
204         ;;
205
206      nosync )
207        sleep 0.5
208        # Since 4.2 we delay the close of recovery until there has been a chance for
209        # spares to be activated.  That means that a recovery that finds nothing
210        # to do can still take a little longer than expected.
211        # add an extra check: is sync_completed shows the end is reached, assume
212        # there is no recovery.
213        if grep -s -E '(resync|recovery|reshape) *=' > /dev/null /proc/mdstat ; then
214            incomplete=`grep / /sys/block/md*/md/sync_completed 2> /dev/null | sed '/^ *\([0-9]*\) \/ \1/d'`
215            if [ -n "$incomplete" ]; then
216                 echo >&2 "ERROR resync or recovery is happening!"; cat /proc/mdstat ; exit 1;
217            fi
218        fi
219      ;;
220
221     wait )
222       p=`cat /proc/sys/dev/raid/speed_limit_max`
223       echo 2000000 > /proc/sys/dev/raid/speed_limit_max
224       sleep 0.1
225       while grep -E '(resync|recovery|reshape|check|repair) *=' > /dev/null /proc/mdstat ||
226               grep -v idle > /dev/null /sys/block/md*/md/sync_action
227       do sleep 0.5;
228       done
229       echo $p > /proc/sys/dev/raid/speed_limit_max
230       ;;
231
232     state )
233        grep -s "blocks.*\[$2\]\$" /proc/mdstat > /dev/null || {
234                 echo >&2 "ERROR state $2 not found!"; cat /proc/mdstat ; exit 1; }
235        sleep 0.5
236       ;;
237
238     bitmap )
239        grep -s bitmap > /dev/null /proc/mdstat || {
240                 echo >&2 ERROR no bitmap ; cat /proc/mdstat ; exit 1; }
241       ;;
242     nobitmap )
243        if grep -s "bitmap" > /dev/null /proc/mdstat
244        then
245                 echo >&2 ERROR bitmap present ; cat /proc/mdstat ; exit 1;
246        fi
247       ;;
248
249     readonly )
250        grep -s "read-only" > /dev/null /proc/mdstat || {
251                 echo >&2 "ERROR array is not read-only!"; cat /proc/mdstat ; exit 1; }
252       ;;
253
254     inactive )
255        grep -s "inactive" > /dev/null /proc/mdstat || {
256                 echo >&2 "ERROR array is not inactive!"; cat /proc/mdstat ; exit 1; }
257       ;;
258     * ) echo >&2 ERROR unknown check $1 ; exit 1;
259    esac
260 }
261
262 no_errors() {
263   if [ -s $targetdir/stderr ]
264   then echo Bad errors from mdadm: ; cat $targetdir/stderr; exit 2;
265   fi
266 }
267 # basic device test
268
269 testdev() {
270    udevadm settle
271    dev=$1
272    cnt=$2
273    dvsize=$3
274    chunk=$4
275    if [ -z "$5" ]; then
276       mkfs.ext3 -F -j $dev > /dev/null 2>&1 && fsck -fn $dev >&2
277    fi
278    dsize=$[dvsize/chunk]
279    dsize=$[dsize*chunk]
280    rasize=$[dsize*2*cnt]
281    # rasize is in sectors
282    if [ -n "$DEV_ROUND_K" ]; then
283       rasize=$[rasize/DEV_ROUND_K/2]
284       rasize=$[rasize*DEV_ROUND_K*2]
285    fi
286    if [ `/sbin/blockdev --getsize $dev` -eq 0 ]; then sleep 2 ; fi
287    _sz=`/sbin/blockdev --getsize $dev`
288    if [ $rasize -lt $_sz -o $[rasize*4/5] -gt $_sz ]
289    then
290      echo "ERROR: size is wrong for $dev: $cnt * $dvsize (chunk=$chunk) = $rasize, not $_sz"
291      exit 1
292    fi
293 }
294
295 fast_sync() {
296   echo 200000 > /proc/sys/dev/raid/speed_limit_max
297 }
298
299 rotest() {
300   dev=$1
301   fsck -fn $dev >&2
302 }
303
304 do_test() {
305   _script=$1
306   _basename=`basename $_script`
307   if [ -f "$_script" ]
308   then
309     rm -f $targetdir/stderr
310     # stop all arrays, just incase some script left an array active.
311     $mdadm -Ssq 2> /dev/null
312     mdadm --zero $devlist 2> /dev/null
313     mdadm --zero $devlist 2> /dev/null
314     # this might have been reset: restore the default.
315     echo 2000 > /proc/sys/dev/raid/speed_limit_max
316     # source script in a subshell, so it has access to our
317     # namespace, but cannot change it.
318     echo -ne "$_script... "
319     if ( set -ex ; . $_script ) &> $targetdir/log
320     then
321       echo "succeeded"
322       _fail=0
323     else
324       log=log
325       cat $targetdir/stderr >> $targetdir/log
326       echo "=======================dmesg=================" >> $targetdir/log
327       dmesg | tail -n 200 >> $targetdir/log
328       if [ $exitonerror == 0 ]; then
329           log=log-`basename $_script`
330           mv $targetdir/log $logdir/$log
331       fi
332       echo "FAILED - see $logdir/$log for details"
333       _fail=1
334     fi
335     if [ "$savelogs" == "1" ]; then
336       cp $targetdir/log $logdir/$_basename.log
337     fi
338     if [ "$_fail" == "1" -a "$exitonerror" == "1" ]; then
339       exit 1
340     fi
341   fi
342 }
343
344 do_help() {
345   echo "Usage: $0 [options]"
346   echo " Options:"
347   echo "    --tests=<test1,test2,..>    Comma separated list of tests to run"
348   echo "    --disable-multipath         Disable any tests involving multipath"
349   echo "    --disable-integrity         Disable slow tests of RAID[56] consistency"
350   echo "    --logdir=<directory>        Directory to save logfiles in"
351   echo "    --save-logs                 Save all logs in <logdir>"
352   echo "    --keep-going                Don't stop on error, ie. run all tests"
353   echo "    --dev=[loop|lvm|ram]        Use loop devices (default), LVM, or RAM disk"
354   echo "    --volgroup=<name>           LVM volume group for LVM test"
355   echo "    setup                       Setup test environment and exit"
356   echo "    cleanup                     Cleanup test environment"
357   echo "    <prefix>                    Run tests with <prefix>"
358 }
359
360 parse_args() {
361   for i in $*
362   do
363     case $i in
364     [0-9]*)
365       prefix=$i
366       ;;
367     setup)
368       echo "mdadm test environment setup"
369       do_setup
370       trap 0; exit 0
371       ;;
372     cleanup)
373       cleanup
374       exit 0
375       ;;
376     --tests=*)
377       TESTLIST=`expr "x$i" : 'x[^=]*=\(.*\)' | sed -e 's/,/ /g'`
378       ;;
379     --logdir=*)
380       logdir=`expr "x$i" : 'x[^=]*=\(.*\)'`
381       ;;
382     --save-logs)
383       savelogs=1
384       ;;
385     --keep-going | --no-error)
386       exitonerror=0
387       ;;
388     --disable-multipath)
389       unset MULTIPATH
390       ;;
391     --disable-integrity)
392       unset INTEGRITY
393       ;;
394     --dev=loop)
395       DEVTYPE=loop
396       ;;
397     --dev=lvm)
398       DEVTYPE=lvm
399       ;;
400     --dev=ram)
401       DEVTYPE=ram
402       ;;
403     --volgroup=*)
404       LVM_VOLGROUP=`expr "x$i" : 'x[^=]*=\(.*\)'`
405       ;;
406     --help)
407       do_help
408       exit 0;
409       ;;
410     -*)
411       echo " $0: Unknown argument: $i"
412       do_help
413       exit 0;
414       ;;
415     esac
416 done
417 }
418
419 logdir=$targetdir
420 parse_args $@
421
422 do_setup
423 mkdir -p $logdir
424
425 if [ "$savelogs" == "1" ]; then
426   echo "Saving logs to $logdir"
427 fi
428
429 if [ "x$TESTLIST" != "x" ]; then
430   for script in $TESTLIST
431   do
432     do_test $testdir/$script
433   done
434 else
435   for script in $testdir/$prefix $testdir/$prefix*[^~]
436   do
437     do_test $script
438   done
439 fi
440 exit 0