]>
Commit | Line | Data |
---|---|---|
cbb8d34a ZL |
1 | #!/bin/bash |
2 | ||
3 | # We test mdadm on loop-back block devices. | |
4 | # dir for storing files should be settable by command line maybe | |
5 | size=20000 | |
6 | # super0, round down to multiple of 64 and substract 64 | |
7 | mdsize0=19904 | |
8 | # super00 is nested, subtract 128 | |
9 | mdsize00=19840 | |
10 | # super1.0 round down to multiple of 2, subtract 8 | |
11 | mdsize1=19992 | |
12 | mdsize1a=19988 | |
13 | mdsize12=19988 | |
14 | # super1.2 for linear: round to multiple of 2, subtract 4 | |
15 | mdsize1_l=19996 | |
16 | mdsize2_l=19996 | |
17 | # subtract another 4 for bitmaps | |
18 | mdsize1b=19988 | |
19 | mdsize11=19992 | |
20 | mdsize11a=19456 | |
21 | mdsize12=19988 | |
22 | ||
23 | # ddf needs bigger devices as 32Meg is reserved! | |
24 | ddfsize=65536 | |
25 | ||
26 | # $1 is optional parameter, it shows why to save log | |
27 | save_log() { | |
28 | status=$1 | |
29 | logfile="$status""$_basename".log | |
30 | ||
31 | cat $targetdir/stderr >> $targetdir/log | |
32 | cp $targetdir/log $logdir/$_basename.log | |
33 | echo "## $HOSTNAME: saving dmesg." >> $logdir/$logfile | |
34 | dmesg -c >> $logdir/$logfile | |
35 | echo "## $HOSTNAME: saving proc mdstat." >> $logdir/$logfile | |
36 | cat /proc/mdstat >> $logdir/$logfile | |
37 | array=($(mdadm -Ds | cut -d' ' -f2)) | |
38 | [ "$1" == "fail" ] && | |
39 | echo "FAILED - see $logdir/$_basename.log and $logdir/$logfile for details" | |
40 | if [ $DEVTYPE == 'lvm' ] | |
41 | then | |
42 | # not supported lvm type yet | |
43 | echo | |
44 | elif [ "$DEVTYPE" == 'loop' -o "$DEVTYPE" == 'disk' ] | |
45 | then | |
46 | if [ ! -z "$array" -a ${#array[@]} -ge 1 ] | |
47 | then | |
48 | echo "## $HOSTNAME: mdadm -D ${array[@]}" >> $logdir/$logfile | |
49 | $mdadm -D ${array[@]} >> $logdir/$logfile | |
50 | # ignore saving external(external file, imsm...) bitmap | |
51 | cat /proc/mdstat | grep -q "linear\|external" && return 0 | |
52 | md_disks=($($mdadm -D -Y ${array[@]} | grep "/dev/" | cut -d'=' -f2)) | |
53 | cat /proc/mdstat | grep -q "bitmap" | |
54 | if [ $? -eq 0 ] | |
55 | then | |
56 | echo "## $HOSTNAME: mdadm -X ${md_disks[@]}" >> $logdir/$logfile | |
57 | $mdadm -X ${md_disks[@]} >> $logdir/$logfile | |
58 | fi | |
59 | else | |
60 | echo "## $HOSTNAME: no array assembled!" >> $logdir/$logfile | |
61 | fi | |
62 | fi | |
63 | } | |
64 | ||
65 | cleanup() { | |
66 | udevadm settle | |
67 | $mdadm -Ssq 2> /dev/null | |
68 | case $DEVTYPE in | |
69 | loop ) | |
70 | for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |
71 | do | |
72 | losetup -d /dev/loop$d &> /dev/null | |
73 | rm -f /dev/disk/by-path/loop* | |
74 | rm -f /var/tmp/mdtest$d | |
75 | done | |
76 | ;; | |
77 | lvm ) | |
78 | for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |
79 | do | |
80 | eval "lvremove --quiet -f \$dev$d" | |
81 | done | |
82 | ;; | |
83 | disk ) | |
84 | $mdadm --zero ${disks[@]} &> /dev/null | |
85 | ;; | |
86 | esac | |
87 | } | |
88 | ||
89 | check_env() { | |
90 | user=$(id -un) | |
91 | [ "X$user" != "Xroot" ] && { | |
92 | echo "test: testing can only be done as 'root'." | |
93 | exit 1 | |
94 | } | |
95 | [ -x "raid6check" -a -x $mdadm ] || { | |
96 | echo "test: please run 'make everything' before perform testing." | |
97 | exit 1 | |
98 | } | |
99 | cmds=(mdadm lsblk df udevadm losetup mkfs.ext3 fsck seq) | |
100 | for cmd in ${cmds[@]} | |
101 | do | |
102 | which $cmd > /dev/null || { | |
103 | echo "$cmd command not found!" | |
104 | exit 1 | |
105 | } | |
106 | done | |
107 | mdadm_src_ver="$($mdadm -V 2>&1)" | |
108 | mdadm_sbin_ver="$($(which mdadm) -V 2>&1)" | |
109 | if [ "$mdadm_src_ver" != "$mdadm_sbin_ver" ] | |
110 | then | |
111 | # it's nessesary to 'make install' mdadm to /SBIN/DIR, | |
112 | # such as systemd/mdadm-grow-continue@.service, would | |
113 | # run as an instance by systemd when reshape happens, | |
114 | # thus ensure that the correct mdadm is in testing. | |
115 | echo "test: please run 'make install' before testing." | |
116 | exit 1 | |
117 | fi | |
118 | if ! $(df -T . | grep -iq ext) | |
119 | then | |
120 | # 'external file' bitmap only supports with ext[2-4] file system | |
121 | echo "test: please run test suite with ext[2-4] file system." | |
122 | exit 1 | |
123 | fi | |
124 | if $(lsblk -a | grep -iq raid) | |
125 | then | |
126 | # donot run mdadm -Ss directly if there are RAIDs working. | |
127 | echo "test: please run test suite without running RAIDs environment." | |
128 | exit 1 | |
129 | fi | |
130 | # Check whether to run multipath tests | |
131 | modprobe multipath 2> /dev/null | |
132 | grep -sq 'Personalities : .*multipath' /proc/mdstat && | |
133 | MULTIPATH="yes" | |
134 | } | |
135 | ||
136 | do_setup() { | |
137 | trap cleanup 0 1 3 15 | |
138 | trap ctrl_c 2 | |
139 | ||
140 | check_env | |
141 | [ -d $logdir ] || mkdir -p $logdir | |
142 | dmesg -c > /dev/null | |
143 | ||
144 | devlist= | |
145 | if [ "$DEVTYPE" == "loop" ] | |
146 | then | |
147 | # make sure there are no loop devices remaining. | |
148 | # udev started things can sometimes prevent them being stopped | |
149 | # immediately | |
150 | while grep loop /proc/partitions > /dev/null 2>&1 | |
151 | do | |
152 | $mdadm -Ssq | |
153 | losetup -d /dev/loop[0-9]* 2> /dev/null | |
154 | sleep 0.2 | |
155 | done | |
156 | elif [ "$DEVTYPE" == "disk" ] | |
157 | then | |
158 | if [ ! -z "$disks" ] | |
159 | then | |
160 | for d in $(seq 0 ${#disks[@]}) | |
161 | do | |
162 | eval "dev$d=${disks[$d]}" | |
163 | eval devlist=\"\$devlist \$dev$d\" | |
164 | eval devlist$d=\"\$devlist\" | |
165 | done | |
166 | $mdadm --zero ${disks[@]} &> /dev/null | |
167 | else | |
168 | echo "Forget to provide physical devices for disk mode." | |
169 | exit 1 | |
170 | fi | |
171 | fi | |
172 | for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |
173 | do | |
174 | sz=$size | |
175 | [ $d -gt 7 ] && sz=$ddfsize | |
176 | case $DEVTYPE in | |
177 | loop) | |
178 | [ -f $targetdir/mdtest$d ] || | |
179 | dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1 | |
180 | # make sure udev doesn't touch | |
181 | mdadm --zero $targetdir/mdtest$d 2> /dev/null | |
182 | [ -b /dev/loop$d ] || mknod /dev/loop$d b 7 $d | |
183 | if [ $d -eq 7 ] | |
184 | then | |
185 | losetup /dev/loop$d $targetdir/mdtest6 # for multipath use | |
186 | else | |
187 | losetup /dev/loop$d $targetdir/mdtest$d | |
188 | fi | |
189 | eval dev$d=/dev/loop$d | |
190 | eval file$d=$targetdir/mdtest$d | |
191 | ;; | |
192 | lvm) | |
193 | unset MULTIPATH | |
194 | eval dev$d=/dev/mapper/${LVM_VOLGROUP}-mdtest$d | |
195 | if ! lvcreate --quiet -L ${sz}K -n mdtest$d $LVM_VOLGROUP | |
196 | then | |
197 | trap '' 0 # make sure lvremove is not called | |
198 | eval echo error creating \$dev$d | |
199 | exit 129 | |
200 | fi | |
201 | ;; | |
202 | ram) | |
203 | unset MULTIPATH | |
204 | eval dev$d=/dev/ram$d | |
205 | ;; | |
206 | esac | |
207 | eval devlist=\"\$devlist \$dev$d\" | |
208 | eval devlist$d=\"\$devlist\" | |
209 | #" <-- add this quote to un-confuse vim syntax highlighting | |
210 | done | |
211 | path0=$dev6 | |
212 | path1=$dev7 | |
213 | ulimit -c unlimited | |
214 | [ -f /proc/mdstat ] || modprobe md_mod | |
215 | echo 2000 > /proc/sys/dev/raid/speed_limit_max | |
216 | echo 0 > /sys/module/md_mod/parameters/start_ro | |
217 | } | |
218 | ||
219 | # check various things | |
220 | check() { | |
221 | case $1 in | |
9c816fe2 XN |
222 | opposite_result ) |
223 | if [ $? -eq 0 ]; then | |
224 | die "This command shouldn't run successfully" | |
225 | fi | |
cbb8d34a ZL |
226 | spares ) |
227 | spares=$(tr '] ' '\012\012' < /proc/mdstat | grep -c '(S)' || exit 0) | |
228 | [ $spares -ne $2 ] && | |
229 | die "expected $2 spares, found $spares" | |
230 | ;; | |
231 | raid* | linear ) | |
232 | grep -sq "active $1 " /proc/mdstat || | |
233 | die "active $1 not found" | |
234 | ;; | |
235 | algorithm ) | |
236 | grep -sq " algorithm $2 " /proc/mdstat || | |
237 | die "algorithm $2 not found" | |
238 | ;; | |
239 | resync | recovery | reshape ) | |
240 | cnt=5 | |
241 | while ! grep -sq $1 /proc/mdstat | |
242 | do | |
243 | if [ $cnt -gt 0 ] && grep -v idle /sys/block/md*/md/sync_action > /dev/null | |
244 | then # Something isn't idle - wait a bit | |
245 | sleep 0.5 | |
246 | cnt=$[cnt-1] | |
247 | else | |
248 | die "no $1 happening" | |
249 | fi | |
250 | done | |
251 | ;; | |
252 | nosync ) | |
253 | sleep 0.5 | |
254 | # Since 4.2 we delay the close of recovery until there has been a chance for | |
255 | # spares to be activated. That means that a recovery that finds nothing | |
256 | # to do can still take a little longer than expected. | |
257 | # add an extra check: is sync_completed shows the end is reached, assume | |
258 | # there is no recovery. | |
259 | if grep -sq -E '(resync|recovery|reshape) *=' /proc/mdstat | |
260 | then | |
261 | incomplete=`grep / /sys/block/md*/md/sync_completed 2> /dev/null | sed '/^ *\([0-9]*\) \/ \1/d'` | |
262 | [ -n "$incomplete" ] && | |
263 | die "resync or recovery is happening!" | |
264 | fi | |
265 | ;; | |
266 | wait ) | |
267 | p=`cat /proc/sys/dev/raid/speed_limit_max` | |
268 | echo 2000000 > /proc/sys/dev/raid/speed_limit_max | |
269 | sleep 0.1 | |
270 | while grep -Eq '(resync|recovery|reshape|check|repair) *=' /proc/mdstat || | |
271 | grep -v idle > /dev/null /sys/block/md*/md/sync_action | |
272 | do | |
273 | sleep 0.5 | |
274 | done | |
275 | echo $p > /proc/sys/dev/raid/speed_limit_max | |
276 | ;; | |
277 | state ) | |
278 | grep -sq "blocks.*\[$2\]\$" /proc/mdstat || | |
279 | die "state $2 not found!" | |
280 | sleep 0.5 | |
281 | ;; | |
282 | bitmap ) | |
283 | grep -sq bitmap /proc/mdstat || | |
284 | die "no bitmap" | |
285 | ;; | |
286 | nobitmap ) | |
287 | grep -sq "bitmap" /proc/mdstat && | |
288 | die "bitmap present" | |
289 | ;; | |
290 | readonly ) | |
291 | grep -sq "read-only" /proc/mdstat || | |
292 | die "array is not read-only!" | |
293 | ;; | |
294 | inactive ) | |
295 | grep -sq "inactive" /proc/mdstat || | |
296 | die "array is not inactive!" | |
297 | ;; | |
298 | # It only can be used when there is only one raid | |
299 | chunk ) | |
300 | chunk_size=`awk -F',' '/chunk/{print $2}' /proc/mdstat | awk -F'[a-z]' '{print $1}'` | |
301 | if [ "$chunk_size" -ne "$2" ] ; then | |
302 | die "chunksize should be $2, but it's $chunk_size" | |
303 | fi | |
304 | ;; | |
305 | * ) | |
306 | die "unknown check $1" | |
307 | ;; | |
308 | esac | |
309 | } | |
310 | ||
311 | no_errors() { | |
312 | if [ -s $targetdir/stderr ] | |
313 | then | |
314 | echo Bad errors from mdadm: | |
315 | cat $targetdir/stderr | |
316 | exit 2 | |
317 | fi | |
318 | } | |
319 | ||
320 | # basic device test | |
321 | testdev() { | |
322 | [ -b $1 ] || die "$1 isn't a block device." | |
323 | [ "$DEVTYPE" == "disk" ] && return 0 | |
324 | udevadm settle | |
325 | dev=$1 | |
326 | cnt=$2 | |
327 | dvsize=$3 | |
328 | chunk=$4 | |
329 | if [ -z "$5" ] | |
330 | then | |
331 | mkfs.ext3 -F -j $dev > /dev/null 2>&1 && fsck -fn $dev >&2 | |
332 | fi | |
333 | dsize=$[dvsize/chunk] | |
334 | dsize=$[dsize*chunk] | |
335 | rasize=$[dsize*2*cnt] | |
336 | # rasize is in sectors | |
337 | if [ -n "$DEV_ROUND_K" ] | |
338 | then | |
339 | rasize=$[rasize/DEV_ROUND_K/2] | |
340 | rasize=$[rasize*DEV_ROUND_K*2] | |
341 | fi | |
342 | [ `/sbin/blockdev --getsize $dev` -eq 0 ] && sleep 2 | |
343 | _sz=`/sbin/blockdev --getsize $dev` | |
344 | [ $rasize -lt $_sz -o $[rasize*4/5] -gt $_sz ] && | |
345 | die "size is wrong for $dev: $cnt * $dvsize (chunk=$chunk) = $rasize, not $_sz" | |
346 | return 0 | |
347 | } | |
348 | ||
349 | rotest() { | |
350 | dev=$1 | |
351 | fsck -fn $dev >&2 | |
352 | } |