]> git.ipfire.org Git - thirdparty/mdadm.git/blob - test
Assemble: Fix critical-section-recovery when assembling a growing array.
[thirdparty/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 # Check whether to run multipath tests
25 modprobe multipath 2> /dev/null
26 if grep -s 'Personalities : .*multipath' > /dev/null /proc/mdstat ; then
27 MULTIPATH="yes"
28 fi
29 INTEGRITY=yes
30
31 # assume md0, md1, md2 exist in /dev
32 md0=/dev/md0 md1=/dev/md1 md2=/dev/md2
33 mdp0=/dev/md_d0
34 mdp1=/dev/md_d1
35
36 # We test mdadm on loop-back block devices.
37 # dir for storing files should be settable by command line maybe
38 targetdir=/var/tmp
39 size=20000
40 # super0, round down to multiple of 64 and substract 64
41 mdsize0=19904
42 # super00 is nested, subtract 128
43 mdsize00=19840
44 # super1.0 round down to multiple of 2, subtract 8
45 mdsize1=19992
46 mdsize1a=19988
47 mdsize12=19988
48 # super1.2 for linear: round to multiple of 2, subtract 4
49 mdsize1_l=19996
50 mdsize2_l=19996
51 # subtract another 4 for bitmaps
52 mdsize1b=19988
53 mdsize11=19992
54 mdsize11a=19456
55 mdsize12=19988
56
57 # ddf needs bigger devices as 32Meg is reserved!
58 ddfsize=65536
59
60 config=/tmp/mdadm.conf
61
62 cleanup() {
63 udevadm settle
64 $mdadm -Ssq 2> /dev/null
65 for d in 0 1 2 3 4 5 6 7 8 9 10 11 12
66 do
67 losetup -d /dev/loop$d ; # rm -f $targetdir/mdtest$d
68 rm -f /dev/disk/by-path/loop*
69 done
70 }
71
72 ctrl-c() {
73 exitonerror=1
74 }
75
76 do_setup() {
77 trap cleanup 0 1 3 15
78 trap ctrl-c 2
79
80 devlist=
81 for d in 0 1 2 3 4 5 6 7 8 9 10 11 12
82 do
83 sz=$size
84 if [ $d -gt 7 ]; then sz=$ddfsize ; fi
85 [ -f $targetdir/mdtest$d ] || dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1
86 [ -b /dev/loop$d ] || mknod /dev/loop$d b 7 $d
87 if [ $d -eq 7 ]
88 then
89 losetup /dev/loop$d $targetdir/mdtest6 # for multipath use
90 else
91 losetup /dev/loop$d $targetdir/mdtest$d
92 fi
93 eval dev$d=/dev/loop$d
94 eval file$d=$targetdir/mdtest$d
95 eval devlist=\"\$devlist \$dev$d\"
96 #" <-- add this quote to un-confuse vim syntax highlighting
97 done
98 path0=$dev6
99 path1=$dev7
100
101 ulimit -c unlimited
102 [ -f /proc/mdstat ] || modprobe md_mod
103 echo 2000 > /proc/sys/dev/raid/speed_limit_max
104 echo 0 > /sys/module/md_mod/parameters/start_ro
105 }
106
107 # mdadm always adds --quiet, and we want to see any unexpected messages
108 mdadm() {
109 rm -f $targetdir/stderr
110 case $* in
111 *-S* ) udevadm settle;;
112 esac
113 case $* in
114 *-C* ) $mdadm 2> $targetdir/stderr --quiet "$@" --auto=yes;;
115 * ) $mdadm 2> $targetdir/stderr --quiet "$@"
116 esac
117 rv=$?
118 case $* in
119 *-S* ) udevadm settle;;
120 esac
121 cat >&2 $targetdir/stderr
122 return $rv
123 }
124
125 # check various things
126 check() {
127 case $1 in
128 spares )
129 spares=`tr '] ' '\012\012' < /proc/mdstat | grep -c '(S)' || exit 0`
130 if [ $spares -ne $2 ]
131 then
132 echo >&2 "ERROR expected $2 spares, found $spares"; exit 1;
133 fi
134 ;;
135 raid* | linear )
136 grep -s "active $1 " /proc/mdstat > /dev/null || {
137 echo >&2 "ERROR active $1 not found" ; cat /proc/mdstat ; exit 1;}
138 ;;
139 resync | recovery | reshape)
140 sleep 0.5
141 grep -s $1 /proc/mdstat > /dev/null || {
142 echo >&2 ERROR no $1 happening; cat /proc/mdstat; exit 1; }
143 ;;
144
145 nosync )
146 sleep 0.5
147 if grep -s -E '(resync|recovery|reshape) *=' > /dev/null /proc/mdstat ; then
148 echo >&2 "ERROR resync or recovery is happening!"; cat /proc/mdstat ; exit 1;
149 fi
150 ;;
151
152 wait )
153 sleep 0.1
154 while grep -E '(resync|recovery|reshape|check|repair) *=' > /dev/null /proc/mdstat
155 do sleep 2;
156 done
157 ;;
158
159 state )
160 grep -s "blocks.*\[$2\]\$" /proc/mdstat > /dev/null || {
161 echo >&2 "ERROR state $2 not found!"; cat /proc/mdstat ; exit 1; }
162 sleep 0.5
163 ;;
164
165 bitmap )
166 grep -s bitmap > /dev/null /proc/mdstat || {
167 echo >&2 ERROR no bitmap ; cat /proc/mdstat ; exit 1; }
168 ;;
169 nobitmap )
170 if grep -s "bitmap" > /dev/null /proc/mdstat
171 then
172 echo >&2 ERROR bitmap present ; cat /proc/mdstat ; exit 1;
173 fi
174 ;;
175
176 * ) echo >&2 ERROR unknown check $1 ; exit 1;
177 esac
178 }
179
180 no_errors() {
181 if [ -s $targetdir/stderr ]
182 then echo Bad errors from mdadm: ; cat $targetdir/stderr; exit 2;
183 fi
184 }
185 # basic device test
186
187 testdev() {
188 udevadm settle
189 dev=$1
190 cnt=$2
191 dvsize=$3
192 chunk=$4
193 if [ -z "$5" ]; then
194 mkfs -j $dev > /dev/null 2>&1 && fsck -fn $dev >&2
195 fi
196 dsize=$[dvsize/chunk]
197 dsize=$[dsize*chunk]
198 rasize=$[dsize*2*cnt]
199 # rasize is in sectors
200 if [ -n "$DEV_ROUND_K" ]; then
201 rasize=$[rasize/DEV_ROUND_K/2]
202 rasize=$[rasize*DEV_ROUND_K*2]
203 fi
204 if [ `/sbin/blockdev --getsize $dev` -eq 0 ]; then sleep 2 ; fi
205 _sz=`/sbin/blockdev --getsize $dev`
206 if [ $rasize -lt $_sz -o $[rasize*4/5] -gt $_sz ]
207 then
208 echo "ERROR: size is wrong for $dev: $cnt * $dvsize (chunk=$chunk) = $rasize, not $_sz"
209 exit 1
210 fi
211 }
212
213 rotest() {
214 dev=$1
215 fsck -fn $dev >&2
216 }
217
218 do_test() {
219 _script=$1
220 _basename=`basename $_script`
221 if [ -f "$_script" ]
222 then
223 rm -f $targetdir/stderr
224 # stop all arrays, just incase some script left an array active.
225 $mdadm -Ssq 2> /dev/null
226 mdadm --zero $devlist 2> /dev/null
227 mdadm --zero $devlist 2> /dev/null
228 # source script in a subshell, so it has access to our
229 # namespace, but cannot change it.
230 echo -ne "$_script... "
231 if ( set -ex ; . $_script ) &> $targetdir/log
232 then
233 echo "succeeded"
234 _fail=0
235 else
236 log=log
237 if [ $exitonerror == 0 ]; then
238 log=log-`basename $_script`
239 mv $targetdir/log $targetdir/$log
240 fi
241 echo "FAILED - see $targetdir/$log for details"
242 _fail=1
243 fi
244 if [ "$savelogs" == "1" ]; then
245 cp $targetdir/log $logdir/$_basename.log
246 fi
247 if [ "$_fail" == "1" -a "$exitonerror" == "1" ]; then
248 exit 1
249 fi
250 fi
251 }
252
253 do_help() {
254 echo "Usage: $0 [options]"
255 echo " Options:"
256 echo " --tests=<test1,test2,..> Comma separated list of tests to run"
257 echo " --disable-multipath Disable any tests involving multipath"
258 echo " --disable-integrity Disable slow tests of RAID[56] consistency"
259 echo " --logdir=<directory> Directory to save logfiles in"
260 echo " --save-logs Save all logs in <logdir>"
261 echo " --keep-going Don't stop on error, ie. run all tests"
262 echo " setup Setup test environment and exit"
263 echo " cleanup Cleanup test environment"
264 echo " <prefix> Run tests with <prefix>"
265 }
266
267 parse_args() {
268 for i in $*
269 do
270 case $i in
271 [0-9]*)
272 prefix=$i
273 ;;
274 setup)
275 echo "mdadm test environment setup"
276 do_setup
277 trap 0; exit 0
278 ;;
279 cleanup)
280 cleanup
281 exit 0
282 ;;
283 --tests=*)
284 TESTLIST=`expr "x$i" : 'x[^=]*=\(.*\)' | sed -e 's/,/ /g'`
285 ;;
286 --logdir=*)
287 logdir=`expr "x$i" : 'x[^=]*=\(.*\)'`
288 ;;
289 --save-logs)
290 savelogs=1
291 if [ ! -d $logdir ] ; then
292 mkdir $logdir
293 if [ $? -ne 0 ] ; then
294 exit 1;
295 fi
296 fi
297 ;;
298 --keep-going | --no-error)
299 exitonerror=0
300 ;;
301 --disable-multipath)
302 unset MULTIPATH
303 ;;
304 --disable-integrity)
305 unset INTEGRITY
306 ;;
307 --help)
308 do_help
309 exit 0;
310 ;;
311 -*)
312 echo " $0: Unknown argument: $i"
313 do_help
314 exit 0;
315 ;;
316 esac
317 done
318 }
319
320 parse_args $@
321
322 do_setup
323
324 if [ "$savelogs" == "1" ]; then
325 echo "Saving logs to $logdir"
326 fi
327
328 if [ "x$TESTLIST" != "x" ]; then
329 for script in $TESTLIST
330 do
331 do_test $testdir/$script
332 done
333 else
334 for script in $testdir/$prefix $testdir/$prefix*[^~]
335 do
336 do_test $script
337 done
338 fi
339 exit 0