]> git.ipfire.org Git - thirdparty/mdadm.git/blame - test
mdadm/test: correct the logic operation in save_log
[thirdparty/mdadm.git] / test
CommitLineData
23b7d3b9 1#!/bin/bash
5e7519fa
NB
2#
3# run test suite for mdadm
20d10b4b 4dir=$(pwd)
5e7519fa 5mdadm=$dir/mdadm
60381555 6testdir="tests"
20d10b4b
ZL
7targetdir="/var/tmp"
8logdir="$targetdir"
9config=/tmp/mdadm.conf
60381555 10
20d10b4b
ZL
11savelogs=0
12exitonerror=1
13prefix='[0-9][0-9]'
98a92cff 14
20d10b4b 15# use loop devices by default if doesn't specify --dev
7d8a70bf 16DEVTYPE=loop
20d10b4b 17INTEGRITY=yes
7d8a70bf 18LVM_VOLGROUP=mdtest
04c1ca5f 19
9540cc24
N
20# make sure to test local mdmon, not system one
21export MDADM_NO_SYSTEMCTL=1
22
5e7519fa 23# assume md0, md1, md2 exist in /dev
662c349a
ZL
24md0=/dev/md0
25md1=/dev/md1
26md2=/dev/md2
1f48664b
NB
27mdp0=/dev/md_d0
28mdp1=/dev/md_d1
5e7519fa
NB
29
30# We test mdadm on loop-back block devices.
31# dir for storing files should be settable by command line maybe
5e7519fa 32size=20000
69646c14 33# super0, round down to multiple of 64 and substract 64
5e7519fa 34mdsize0=19904
1c203a4b
NB
35# super00 is nested, subtract 128
36mdsize00=19840
69646c14 37# super1.0 round down to multiple of 2, subtract 8
1bf4e2d9 38mdsize1=19992
ebe6ea0c
N
39mdsize1a=19988
40mdsize12=19988
41# super1.2 for linear: round to multiple of 2, subtract 4
3c8b2739
N
42mdsize1_l=19996
43mdsize2_l=19996
69646c14
NB
44# subtract another 4 for bitmaps
45mdsize1b=19988
46mdsize11=19992
3c8b2739 47mdsize11a=19456
69646c14 48mdsize12=19988
5e7519fa 49
d50683f9
N
50# ddf needs bigger devices as 32Meg is reserved!
51ddfsize=65536
52
20d10b4b
ZL
53# $1 is optional parameter, it shows why to save log
54save_log() {
55 status=$1
56 logfile="$status""$_basename".log
57
58 cat $targetdir/stderr >> $targetdir/log
59 cp $targetdir/log $logdir/$_basename.log
60 echo "## $HOSTNAME: saving dmesg." >> $logdir/$logfile
61 dmesg -c >> $logdir/$logfile
20d10b4b
ZL
62 echo "## $HOSTNAME: saving proc mdstat." >> $logdir/$logfile
63 cat /proc/mdstat >> $logdir/$logfile
64 array=($(mdadm -Ds | cut -d' ' -f2))
20d10b4b
ZL
65 [ "$1" == "fail" ] &&
66 echo "FAILED - see $logdir/$_basename.log and $logdir/$logfile for details"
20d10b4b
ZL
67 if [ $DEVTYPE == 'lvm' ]
68 then
69 # not supported lvm type yet
70 echo
25357919 71 elif [ "$DEVTYPE" == 'loop' -o "$DEVTYPE" == 'disk' ]
20d10b4b 72 then
3af7f2ad 73 if [ ! -z "$array" -a ${#array[@]} -ge 1 ]
20d10b4b 74 then
ed5e31aa
ZL
75 echo "## $HOSTNAME: mdadm -D ${array[@]}" >> $logdir/$logfile
76 $mdadm -D ${array[@]} >> $logdir/$logfile
77 # ignore saving external(external file, imsm...) bitmap
78 cat /proc/mdstat | grep -q "linear\|external" && return 0
25357919 79 md_disks=($($mdadm -D -Y ${array[@]} | grep "/dev/" | cut -d'=' -f2))
20d10b4b
ZL
80 cat /proc/mdstat | grep -q "bitmap"
81 if [ $? -eq 0 ]
82 then
83 echo "## $HOSTNAME: mdadm -X ${md_disks[@]}" >> $logdir/$logfile
84 $mdadm -X ${md_disks[@]} >> $logdir/$logfile
85 fi
86 else
87 echo "## $HOSTNAME: no array assembled!" >> $logdir/$logfile
88 fi
89 fi
90}
91
92die() {
93 echo -e "\n\tERROR: $* \n"
94 save_log fail
95 exit 2
96}
ed02d9cc 97
5e7519fa 98cleanup() {
2952742d 99 udevadm settle
4f8a3e5b 100 $mdadm -Ssq 2> /dev/null
662c349a 101 case $DEVTYPE in
20d10b4b 102 loop )
662c349a
ZL
103 for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13
104 do
20d10b4b 105 losetup -d /dev/loop$d
662c349a 106 rm -f /dev/disk/by-path/loop*
20d10b4b 107 rm -f /var/tmp/mdtest$d
662c349a
ZL
108 done
109 ;;
20d10b4b 110 lvm )
662c349a
ZL
111 for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13
112 do
113 eval "lvremove --quiet -f \$dev$d"
114 done
115 ;;
25357919
ZL
116 disk )
117 $mdadm --zero ${disks[@]} &> /dev/null
118 ;;
662c349a 119 esac
5e7519fa
NB
120}
121
d5a221a5 122ctrl_c() {
4d5995c4
GE
123 exitonerror=1
124}
125
572d7091 126do_setup() {
662c349a
ZL
127 trap cleanup 0 1 3 15
128 trap ctrl_c 2
5e7519fa 129
20d10b4b
ZL
130 [ -d $logdir ] || mkdir -p $logdir
131 dmesg -c > /dev/null
132
25357919 133 devlist=
20d10b4b
ZL
134 if [ "$DEVTYPE" == "loop" ]
135 then
136 # make sure there are no loop devices remaining.
137 # udev started things can sometimes prevent them being stopped
138 # immediately
139 while grep loop /proc/partitions > /dev/null 2>&1
140 do
141 $mdadm -Ssq
142 losetup -d /dev/loop[0-9]* 2> /dev/null
143 sleep 0.2
144 done
25357919
ZL
145 elif [ "$DEVTYPE" == "disk" ]
146 then
147 if [ ! -z "$disks" ]
148 then
149 for d in $(seq 0 ${#disks[@]})
150 do
151 eval "dev$d=${disks[$d]}"
152 eval devlist=\"\$devlist \$dev$d\"
153 eval devlist$d=\"\$devlist\"
154 done
155 $mdadm --zero ${disks[@]} &> /dev/null
156 else
157 echo "Forget to provide physical devices for disk mode."
158 exit 1
159 fi
20d10b4b 160 fi
662c349a
ZL
161 for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13
162 do
163 sz=$size
20d10b4b 164 [ $d -gt 7 ] && sz=$ddfsize
662c349a
ZL
165 case $DEVTYPE in
166 loop)
167 [ -f $targetdir/mdtest$d ] ||
168 dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1
169 # make sure udev doesn't touch
170 mdadm --zero $targetdir/mdtest$d 2> /dev/null
171 [ -b /dev/loop$d ] || mknod /dev/loop$d b 7 $d
172 if [ $d -eq 7 ]
173 then
174 losetup /dev/loop$d $targetdir/mdtest6 # for multipath use
175 else
176 losetup /dev/loop$d $targetdir/mdtest$d
177 fi
178 eval dev$d=/dev/loop$d
179 eval file$d=$targetdir/mdtest$d
180 ;;
181 lvm)
182 unset MULTIPATH
183 eval dev$d=/dev/mapper/${LVM_VOLGROUP}-mdtest$d
184 if ! lvcreate --quiet -L ${sz}K -n mdtest$d $LVM_VOLGROUP
185 then
186 trap '' 0 # make sure lvremove is not called
187 eval echo error creating \$dev$d
188 exit 129
189 fi
190 ;;
191 ram)
192 unset MULTIPATH
193 eval dev$d=/dev/ram$d
194 ;;
195 esac
196 eval devlist=\"\$devlist \$dev$d\"
197 eval devlist$d=\"\$devlist\"
198 #" <-- add this quote to un-confuse vim syntax highlighting
199 done
200 path0=$dev6
201 path1=$dev7
202 ulimit -c unlimited
203 [ -f /proc/mdstat ] || modprobe md_mod
204 echo 2000 > /proc/sys/dev/raid/speed_limit_max
205 echo 0 > /sys/module/md_mod/parameters/start_ro
572d7091 206}
0aa389dc 207
dab6685f
NB
208# mdadm always adds --quiet, and we want to see any unexpected messages
209mdadm() {
662c349a
ZL
210 rm -f $targetdir/stderr
211 case $* in
212 *-S* )
213 udevadm settle
214 p=`cat /proc/sys/dev/raid/speed_limit_max`
215 echo 20000 > /proc/sys/dev/raid/speed_limit_max
216 ;;
217 esac
218 case $* in
20d10b4b
ZL
219 *-C* | *--create* | *-B* | *--build* )
220 # clear superblock every time once creating or
221 # building arrays, because it's always creating
222 # and building array many times in a test case.
223 for args in $*
224 do
225 [[ $args =~ "/dev/" ]] && {
226 [[ $args =~ "md" ]] ||
227 $mdadm --zero $args > /dev/null
228 }
229 done
662c349a
ZL
230 $mdadm 2> $targetdir/stderr --quiet "$@" --auto=yes
231 ;;
232 * )
233 $mdadm 2> $targetdir/stderr --quiet "$@"
234 ;;
235 esac
236 rv=$?
237 case $* in
238 *-S* )
239 udevadm settle
240 echo $p > /proc/sys/dev/raid/speed_limit_max
241 ;;
242 esac
243 cat >&2 $targetdir/stderr
244 return $rv
dab6685f
NB
245}
246
247# check various things
248check() {
662c349a
ZL
249 case $1 in
250 spares )
20d10b4b
ZL
251 spares=$(tr '] ' '\012\012' < /proc/mdstat | grep -c '(S)' || exit 0)
252 [ $spares -ne $2 ] &&
253 die "expected $2 spares, found $spares"
662c349a
ZL
254 ;;
255 raid* | linear )
20d10b4b
ZL
256 grep -sq "active $1 " /proc/mdstat ||
257 die "active $1 not found"
662c349a
ZL
258 ;;
259 algorithm )
20d10b4b
ZL
260 grep -sq " algorithm $2 " /proc/mdstat ||
261 die "algorithm $2 not found"
662c349a
ZL
262 ;;
263 resync | recovery | reshape )
264 cnt=5
20d10b4b 265 while ! grep -sq $1 /proc/mdstat
662c349a
ZL
266 do
267 if [ $cnt -gt 0 ] && grep -v idle /sys/block/md*/md/sync_action > /dev/null
268 then # Something isn't idle - wait a bit
269 sleep 0.5
270 cnt=$[cnt-1]
271 else
20d10b4b 272 die "no $1 happening"
662c349a
ZL
273 fi
274 done
275 ;;
276 nosync )
a76b3a34 277 sleep 0.5
662c349a
ZL
278 # Since 4.2 we delay the close of recovery until there has been a chance for
279 # spares to be activated. That means that a recovery that finds nothing
280 # to do can still take a little longer than expected.
281 # add an extra check: is sync_completed shows the end is reached, assume
282 # there is no recovery.
20d10b4b 283 if grep -sq -E '(resync|recovery|reshape) *=' /proc/mdstat
662c349a
ZL
284 then
285 incomplete=`grep / /sys/block/md*/md/sync_completed 2> /dev/null | sed '/^ *\([0-9]*\) \/ \1/d'`
20d10b4b
ZL
286 [ -n "$incomplete" ] &&
287 die "resync or recovery is happening!"
662c349a
ZL
288 fi
289 ;;
290 wait )
291 p=`cat /proc/sys/dev/raid/speed_limit_max`
292 echo 2000000 > /proc/sys/dev/raid/speed_limit_max
293 sleep 0.1
20d10b4b 294 while grep -Eq '(resync|recovery|reshape|check|repair) *=' /proc/mdstat ||
662c349a
ZL
295 grep -v idle > /dev/null /sys/block/md*/md/sync_action
296 do
297 sleep 0.5
298 done
299 echo $p > /proc/sys/dev/raid/speed_limit_max
300 ;;
301 state )
20d10b4b
ZL
302 grep -sq "blocks.*\[$2\]\$" /proc/mdstat ||
303 die "state $2 not found!"
662c349a
ZL
304 sleep 0.5
305 ;;
306 bitmap )
20d10b4b
ZL
307 grep -sq bitmap /proc/mdstat ||
308 die "no bitmap"
662c349a
ZL
309 ;;
310 nobitmap )
20d10b4b
ZL
311 grep -sq "bitmap" /proc/mdstat &&
312 die "bitmap present"
662c349a
ZL
313 ;;
314 readonly )
20d10b4b
ZL
315 grep -sq "read-only" /proc/mdstat ||
316 die "array is not read-only!"
662c349a
ZL
317 ;;
318 inactive )
20d10b4b
ZL
319 grep -sq "inactive" /proc/mdstat ||
320 die "array is not inactive!"
662c349a 321 ;;
62e2991f
XN
322 # It only can be used when there is only one raid
323 chunk )
324 chunk_size=`awk -F',' '/chunk/{print $2}' /proc/mdstat | awk -F'[a-z]' '{print $1}'`
325 if [ "$chunk_size" -ne "$2" ] ; then
326 die "chunksize should be $2, but it's $chunk_size"
327 fi
328 ;;
662c349a 329 * )
20d10b4b 330 die "unknown check $1"
662c349a
ZL
331 ;;
332 esac
dab6685f
NB
333}
334
bf4fb153 335no_errors() {
662c349a
ZL
336 if [ -s $targetdir/stderr ]
337 then
338 echo Bad errors from mdadm:
339 cat $targetdir/stderr
340 exit 2
341 fi
bf4fb153 342}
dab6685f 343
662c349a 344# basic device test
dab6685f 345testdev() {
20d10b4b 346 [ -b $1 ] || die "$1 isn't a block device."
25357919 347 [ "$DEVTYPE" == "disk" ] && return 0
662c349a
ZL
348 udevadm settle
349 dev=$1
350 cnt=$2
351 dvsize=$3
352 chunk=$4
353 if [ -z "$5" ]
354 then
355 mkfs.ext3 -F -j $dev > /dev/null 2>&1 && fsck -fn $dev >&2
356 fi
357 dsize=$[dvsize/chunk]
358 dsize=$[dsize*chunk]
359 rasize=$[dsize*2*cnt]
360 # rasize is in sectors
361 if [ -n "$DEV_ROUND_K" ]
362 then
363 rasize=$[rasize/DEV_ROUND_K/2]
364 rasize=$[rasize*DEV_ROUND_K*2]
365 fi
20d10b4b 366 [ `/sbin/blockdev --getsize $dev` -eq 0 ] && sleep 2
662c349a 367 _sz=`/sbin/blockdev --getsize $dev`
20d10b4b
ZL
368 [ $rasize -lt $_sz -o $[rasize*4/5] -gt $_sz ] &&
369 die "size is wrong for $dev: $cnt * $dvsize (chunk=$chunk) = $rasize, not $_sz"
370 return 0
6fd2a36f
N
371}
372
c13c45e9 373rotest() {
662c349a
ZL
374 dev=$1
375 fsck -fn $dev >&2
c13c45e9
NB
376}
377
4e5ce543 378do_test() {
662c349a
ZL
379 _script=$1
380 _basename=`basename $_script`
381 if [ -f "$_script" ]
382 then
383 rm -f $targetdir/stderr
384 # stop all arrays, just incase some script left an array active.
385 $mdadm -Ssq 2> /dev/null
386 mdadm --zero $devlist 2> /dev/null
662c349a
ZL
387 # this might have been reset: restore the default.
388 echo 2000 > /proc/sys/dev/raid/speed_limit_max
389 # source script in a subshell, so it has access to our
390 # namespace, but cannot change it.
391 echo -ne "$_script... "
392 if ( set -ex ; . $_script ) &> $targetdir/log
393 then
20d10b4b
ZL
394 dmesg | grep -iq "error\|call trace\|segfault" &&
395 die "dmesg prints errors when testing $_basename!"
662c349a
ZL
396 echo "succeeded"
397 _fail=0
398 else
20d10b4b 399 save_log fail
662c349a
ZL
400 _fail=1
401 fi
20d10b4b
ZL
402 [ "$savelogs" == "1" ] &&
403 mv -f $targetdir/log $logdir/$_basename.log
404 [ "$_fail" == "1" -a "$exitonerror" == "1" ] && exit 1
662c349a 405 fi
4e5ce543
JS
406}
407
408do_help() {
20d10b4b
ZL
409 cat <<-EOF
410 Usage: $0 [options]
25357919 411 Example for disk mode: ./test --dev=disk --disks=/dev/sda{2..15}
20d10b4b
ZL
412 Options:
413 --tests=test1,test2,... Comma separated list of tests to run
8403b202 414 --raidtype= raid0|linear|raid1|raid456|raid10|ddf|imsm
20d10b4b
ZL
415 --disable-multipath Disable any tests involving multipath
416 --disable-integrity Disable slow tests of RAID[56] consistency
417 --logdir=directory Directory to save all logfiles in
418 --save-logs Usually use with --logdir together
419 --keep-going | --no-error Don't stop on error, ie. run all tests
25357919
ZL
420 --dev=loop|lvm|ram|disk Use loop devices (default), LVM, RAM or disk
421 --disks= Provide a bunch of physical devices for test
20d10b4b
ZL
422 --volgroup=name LVM volume group for LVM test
423 setup Setup test environment and exit
424 cleanup Cleanup test environment
425 prefix Run tests with <prefix>
426 --help | -h Print this usage
427 EOF
4e5ce543
JS
428}
429
430parse_args() {
662c349a
ZL
431 for i in $*
432 do
433 case $i in
20d10b4b 434 [0-9][0-9] )
662c349a
ZL
435 prefix=$i
436 ;;
437 setup )
438 echo "mdadm test environment setup"
439 do_setup
440 trap 0
441 exit 0
442 ;;
443 cleanup )
444 cleanup
445 exit 0
446 ;;
447 --tests=* )
20d10b4b 448 TESTLIST=($(echo ${i##*=} | sed -e 's/,/ /g'))
662c349a 449 ;;
8403b202
ZL
450 --raidtype=* )
451 case ${i##*=} in
452 raid0 )
453 TESTLIST=($(ls $testdir | grep "[0-9][0-9]r0\|raid0"))
454 ;;
455 linear )
456 TESTLIST=($(ls $testdir | grep "linear"))
457 ;;
458 raid1 )
459 TESTLIST=($(ls $testdir | grep "[0-9][0-9]r1\|raid1" | grep -vi raid10))
460 ;;
461 raid456 )
462 TESTLIST=($(ls $testdir | grep "[0-9][0-9]r[4-6]\|raid[4-6]"))
463 ;;
464 raid10 )
465 TESTLIST=($(ls $testdir | grep "[0-9][0-9]r10\|raid10"))
466 ;;
467 ddf )
468 TESTLIST=($(ls $testdir | grep "[0-9][0-9]ddf"))
469 ;;
470 imsm )
471 TESTLIST=($(ls $testdir | grep "[0-9][0-9]imsm"))
472 ;;
473 * )
474 echo "Unknown argument: $i"
475 do_help
476 exit 1
477 ;;
478 esac
479 ;;
662c349a 480 --logdir=* )
20d10b4b 481 logdir="${i##*=}"
662c349a
ZL
482 ;;
483 --save-logs )
484 savelogs=1
485 ;;
486 --keep-going | --no-error )
487 exitonerror=0
488 ;;
489 --disable-multipath )
490 unset MULTIPATH
491 ;;
492 --disable-integrity )
493 unset INTEGRITY
494 ;;
20d10b4b
ZL
495 --dev=* )
496 case ${i##*=} in
497 loop )
498 DEVTYPE=loop
499 ;;
500 lvm )
501 DEVTYPE=lvm
502 ;;
503 ram )
504 DEVTYPE=ram
505 ;;
25357919
ZL
506 disk )
507 DEVTYPE=disk
508 ;;
20d10b4b
ZL
509 * )
510 echo "Unknown argument: $i"
511 do_help
512 exit 1
513 ;;
514 esac
662c349a 515 ;;
25357919
ZL
516 --disks=* )
517 disks=(${disks[*]} ${i##*=})
518 ;;
662c349a
ZL
519 --volgroup=* )
520 LVM_VOLGROUP=`expr "x$i" : 'x[^=]*=\(.*\)'`
521 ;;
20d10b4b 522 --help | -h )
662c349a
ZL
523 do_help
524 exit 0
525 ;;
20d10b4b 526 * )
662c349a
ZL
527 echo " $0: Unknown argument: $i"
528 do_help
20d10b4b 529 exit 1
662c349a
ZL
530 ;;
531 esac
532 done
4e5ce543
JS
533}
534
20d10b4b
ZL
535check_env() {
536 user=$(id -un)
537 [ "X$user" != "Xroot" ] && {
538 echo "test: testing can only be done as 'root'."
539 exit 1
540 }
541 [ -x "raid6check" -a -x $mdadm ] || {
542 echo "test: please run 'make everything' before perform testing."
543 exit 1
544 }
25357919 545 cmds=(mdadm lsblk df udevadm losetup mkfs.ext3 fsck seq)
20d10b4b
ZL
546 for cmd in ${cmds[@]}
547 do
548 which $cmd > /dev/null || {
549 echo "$cmd command not found!"
550 exit 1
551 }
552 done
553 mdadm_src_ver="$($mdadm -V 2>&1)"
554 mdadm_sbin_ver="$($(which mdadm) -V 2>&1)"
555 if [ "$mdadm_src_ver" != "$mdadm_sbin_ver" ]
556 then
557 # it's nessesary to 'make install' mdadm to /SBIN/DIR,
558 # such as systemd/mdadm-grow-continue@.service, would
559 # run as an instance by systemd when reshape happens,
560 # thus ensure that the correct mdadm is in testing.
561 echo "test: please run 'make install' before testing."
562 exit 1
563 fi
564 if ! $(df -T . | grep -iq ext)
565 then
566 # 'external file' bitmap only supports with ext[2-4] file system
567 echo "test: please run test suite with ext[2-4] file system."
568 exit 1
569 fi
570 if $(lsblk -a | grep -iq raid)
571 then
572 # donot run mdadm -Ss directly if there are RAIDs working.
573 echo "test: please run test suite without running RAIDs environment."
574 exit 1
575 fi
576 # Check whether to run multipath tests
577 modprobe multipath 2> /dev/null
578 grep -sq 'Personalities : .*multipath' /proc/mdstat &&
579 MULTIPATH="yes"
580}
4e5ce543 581
20d10b4b
ZL
582main() {
583 check_env
584 do_setup
572d7091 585
20d10b4b
ZL
586 echo "Testing on linux-$(uname -r) kernel"
587 [ "$savelogs" == "1" ] &&
588 echo "Saving logs to $logdir"
589 if [ "x$TESTLIST" != "x" ]
590 then
591 for script in ${TESTLIST[@]}
592 do
593 do_test $testdir/$script
594 done
595 else
596 for script in $testdir/$prefix $testdir/$prefix*[^~]
597 do
598 do_test $script
599 done
600 fi
60381555 601
20d10b4b
ZL
602 exit 0
603}
604
605parse_args $@
606main