]>
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 | |
7d81135e ZL |
58 | echo "## $HOSTNAME: mdadm -E ${md_disks[@]}" >> $logdir/$logfile |
59 | $mdadm -E ${md_disks[@]} >> $logdir/$logfile | |
cbb8d34a ZL |
60 | fi |
61 | else | |
62 | echo "## $HOSTNAME: no array assembled!" >> $logdir/$logfile | |
63 | fi | |
64 | fi | |
65 | } | |
66 | ||
67 | cleanup() { | |
68 | udevadm settle | |
69 | $mdadm -Ssq 2> /dev/null | |
70 | case $DEVTYPE in | |
71 | loop ) | |
72 | for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |
73 | do | |
74 | losetup -d /dev/loop$d &> /dev/null | |
75 | rm -f /dev/disk/by-path/loop* | |
76 | rm -f /var/tmp/mdtest$d | |
77 | done | |
78 | ;; | |
79 | lvm ) | |
80 | for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |
81 | do | |
82 | eval "lvremove --quiet -f \$dev$d" | |
83 | done | |
84 | ;; | |
85 | disk ) | |
86 | $mdadm --zero ${disks[@]} &> /dev/null | |
87 | ;; | |
88 | esac | |
89 | } | |
90 | ||
064bd3f5 ZL |
91 | do_clean() |
92 | { | |
93 | mdadm -Ss > /dev/null | |
94 | mdadm --zero $devlist 2> /dev/null | |
95 | dmesg -c > /dev/null | |
96 | } | |
97 | ||
cbb8d34a ZL |
98 | check_env() { |
99 | user=$(id -un) | |
100 | [ "X$user" != "Xroot" ] && { | |
101 | echo "test: testing can only be done as 'root'." | |
102 | exit 1 | |
103 | } | |
59416da7 JS |
104 | [ \! -x $mdadm ] && { |
105 | echo "test: please run make everything before perform testing." | |
cbb8d34a ZL |
106 | exit 1 |
107 | } | |
108 | cmds=(mdadm lsblk df udevadm losetup mkfs.ext3 fsck seq) | |
109 | for cmd in ${cmds[@]} | |
110 | do | |
111 | which $cmd > /dev/null || { | |
112 | echo "$cmd command not found!" | |
113 | exit 1 | |
114 | } | |
115 | done | |
cbb8d34a ZL |
116 | if $(lsblk -a | grep -iq raid) |
117 | then | |
118 | # donot run mdadm -Ss directly if there are RAIDs working. | |
119 | echo "test: please run test suite without running RAIDs environment." | |
120 | exit 1 | |
121 | fi | |
122 | # Check whether to run multipath tests | |
123 | modprobe multipath 2> /dev/null | |
124 | grep -sq 'Personalities : .*multipath' /proc/mdstat && | |
125 | MULTIPATH="yes" | |
64a4fcb4 SL |
126 | if [ "$MULTIPATH" != "yes" ]; then |
127 | echo "test: skipping tests for multipath, which is removed in upstream 6.8+ kernels" | |
128 | fi | |
129 | ||
130 | # Check whether to run linear tests | |
131 | modprobe linear 2> /dev/null | |
132 | grep -sq 'Personalities : .*linear' /proc/mdstat && | |
133 | LINEAR="yes" | |
134 | if [ "$LINEAR" != "yes" ]; then | |
135 | echo "test: skipping tests for linear, which is removed in upstream 6.8+ kernels" | |
136 | fi | |
cbb8d34a ZL |
137 | } |
138 | ||
139 | do_setup() { | |
140 | trap cleanup 0 1 3 15 | |
141 | trap ctrl_c 2 | |
142 | ||
143 | check_env | |
144 | [ -d $logdir ] || mkdir -p $logdir | |
cbb8d34a ZL |
145 | |
146 | devlist= | |
147 | if [ "$DEVTYPE" == "loop" ] | |
148 | then | |
149 | # make sure there are no loop devices remaining. | |
150 | # udev started things can sometimes prevent them being stopped | |
151 | # immediately | |
152 | while grep loop /proc/partitions > /dev/null 2>&1 | |
153 | do | |
154 | $mdadm -Ssq | |
155 | losetup -d /dev/loop[0-9]* 2> /dev/null | |
156 | sleep 0.2 | |
157 | done | |
158 | elif [ "$DEVTYPE" == "disk" ] | |
159 | then | |
160 | if [ ! -z "$disks" ] | |
161 | then | |
162 | for d in $(seq 0 ${#disks[@]}) | |
163 | do | |
164 | eval "dev$d=${disks[$d]}" | |
165 | eval devlist=\"\$devlist \$dev$d\" | |
166 | eval devlist$d=\"\$devlist\" | |
167 | done | |
168 | $mdadm --zero ${disks[@]} &> /dev/null | |
169 | else | |
170 | echo "Forget to provide physical devices for disk mode." | |
171 | exit 1 | |
172 | fi | |
173 | fi | |
174 | for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |
175 | do | |
176 | sz=$size | |
177 | [ $d -gt 7 ] && sz=$ddfsize | |
178 | case $DEVTYPE in | |
179 | loop) | |
180 | [ -f $targetdir/mdtest$d ] || | |
181 | dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1 | |
182 | # make sure udev doesn't touch | |
183 | mdadm --zero $targetdir/mdtest$d 2> /dev/null | |
cbb8d34a ZL |
184 | if [ $d -eq 7 ] |
185 | then | |
186 | losetup /dev/loop$d $targetdir/mdtest6 # for multipath use | |
187 | else | |
188 | losetup /dev/loop$d $targetdir/mdtest$d | |
189 | fi | |
190 | eval dev$d=/dev/loop$d | |
191 | eval file$d=$targetdir/mdtest$d | |
192 | ;; | |
193 | lvm) | |
194 | unset MULTIPATH | |
195 | eval dev$d=/dev/mapper/${LVM_VOLGROUP}-mdtest$d | |
196 | if ! lvcreate --quiet -L ${sz}K -n mdtest$d $LVM_VOLGROUP | |
197 | then | |
198 | trap '' 0 # make sure lvremove is not called | |
199 | eval echo error creating \$dev$d | |
200 | exit 129 | |
201 | fi | |
202 | ;; | |
203 | ram) | |
204 | unset MULTIPATH | |
205 | eval dev$d=/dev/ram$d | |
206 | ;; | |
207 | esac | |
208 | eval devlist=\"\$devlist \$dev$d\" | |
209 | eval devlist$d=\"\$devlist\" | |
210 | #" <-- add this quote to un-confuse vim syntax highlighting | |
211 | done | |
212 | path0=$dev6 | |
213 | path1=$dev7 | |
214 | ulimit -c unlimited | |
215 | [ -f /proc/mdstat ] || modprobe md_mod | |
216 | echo 2000 > /proc/sys/dev/raid/speed_limit_max | |
217 | echo 0 > /sys/module/md_mod/parameters/start_ro | |
218 | } | |
219 | ||
220 | # check various things | |
221 | check() { | |
222 | case $1 in | |
9c816fe2 XN |
223 | opposite_result ) |
224 | if [ $? -eq 0 ]; then | |
225 | die "This command shouldn't run successfully" | |
226 | fi | |
59416da7 | 227 | ;; |
cbb8d34a ZL |
228 | spares ) |
229 | spares=$(tr '] ' '\012\012' < /proc/mdstat | grep -c '(S)' || exit 0) | |
230 | [ $spares -ne $2 ] && | |
231 | die "expected $2 spares, found $spares" | |
232 | ;; | |
233 | raid* | linear ) | |
234 | grep -sq "active $1 " /proc/mdstat || | |
235 | die "active $1 not found" | |
236 | ;; | |
237 | algorithm ) | |
238 | grep -sq " algorithm $2 " /proc/mdstat || | |
239 | die "algorithm $2 not found" | |
240 | ;; | |
241 | resync | recovery | reshape ) | |
242 | cnt=5 | |
243 | while ! grep -sq $1 /proc/mdstat | |
244 | do | |
245 | if [ $cnt -gt 0 ] && grep -v idle /sys/block/md*/md/sync_action > /dev/null | |
246 | then # Something isn't idle - wait a bit | |
247 | sleep 0.5 | |
248 | cnt=$[cnt-1] | |
249 | else | |
250 | die "no $1 happening" | |
251 | fi | |
252 | done | |
253 | ;; | |
254 | nosync ) | |
255 | sleep 0.5 | |
256 | # Since 4.2 we delay the close of recovery until there has been a chance for | |
257 | # spares to be activated. That means that a recovery that finds nothing | |
258 | # to do can still take a little longer than expected. | |
259 | # add an extra check: is sync_completed shows the end is reached, assume | |
260 | # there is no recovery. | |
261 | if grep -sq -E '(resync|recovery|reshape) *=' /proc/mdstat | |
262 | then | |
263 | incomplete=`grep / /sys/block/md*/md/sync_completed 2> /dev/null | sed '/^ *\([0-9]*\) \/ \1/d'` | |
264 | [ -n "$incomplete" ] && | |
265 | die "resync or recovery is happening!" | |
266 | fi | |
267 | ;; | |
268 | wait ) | |
269 | p=`cat /proc/sys/dev/raid/speed_limit_max` | |
270 | echo 2000000 > /proc/sys/dev/raid/speed_limit_max | |
271 | sleep 0.1 | |
272 | while grep -Eq '(resync|recovery|reshape|check|repair) *=' /proc/mdstat || | |
273 | grep -v idle > /dev/null /sys/block/md*/md/sync_action | |
274 | do | |
275 | sleep 0.5 | |
276 | done | |
277 | echo $p > /proc/sys/dev/raid/speed_limit_max | |
278 | ;; | |
279 | state ) | |
280 | grep -sq "blocks.*\[$2\]\$" /proc/mdstat || | |
281 | die "state $2 not found!" | |
282 | sleep 0.5 | |
283 | ;; | |
284 | bitmap ) | |
285 | grep -sq bitmap /proc/mdstat || | |
286 | die "no bitmap" | |
287 | ;; | |
288 | nobitmap ) | |
289 | grep -sq "bitmap" /proc/mdstat && | |
290 | die "bitmap present" | |
291 | ;; | |
292 | readonly ) | |
293 | grep -sq "read-only" /proc/mdstat || | |
294 | die "array is not read-only!" | |
295 | ;; | |
296 | inactive ) | |
297 | grep -sq "inactive" /proc/mdstat || | |
298 | die "array is not inactive!" | |
299 | ;; | |
300 | # It only can be used when there is only one raid | |
301 | chunk ) | |
302 | chunk_size=`awk -F',' '/chunk/{print $2}' /proc/mdstat | awk -F'[a-z]' '{print $1}'` | |
303 | if [ "$chunk_size" -ne "$2" ] ; then | |
304 | die "chunksize should be $2, but it's $chunk_size" | |
305 | fi | |
306 | ;; | |
307 | * ) | |
308 | die "unknown check $1" | |
309 | ;; | |
310 | esac | |
311 | } | |
312 | ||
313 | no_errors() { | |
314 | if [ -s $targetdir/stderr ] | |
315 | then | |
316 | echo Bad errors from mdadm: | |
317 | cat $targetdir/stderr | |
318 | exit 2 | |
319 | fi | |
320 | } | |
321 | ||
322 | # basic device test | |
323 | testdev() { | |
324 | [ -b $1 ] || die "$1 isn't a block device." | |
325 | [ "$DEVTYPE" == "disk" ] && return 0 | |
326 | udevadm settle | |
327 | dev=$1 | |
328 | cnt=$2 | |
329 | dvsize=$3 | |
330 | chunk=$4 | |
331 | if [ -z "$5" ] | |
332 | then | |
333 | mkfs.ext3 -F -j $dev > /dev/null 2>&1 && fsck -fn $dev >&2 | |
334 | fi | |
335 | dsize=$[dvsize/chunk] | |
336 | dsize=$[dsize*chunk] | |
337 | rasize=$[dsize*2*cnt] | |
338 | # rasize is in sectors | |
339 | if [ -n "$DEV_ROUND_K" ] | |
340 | then | |
341 | rasize=$[rasize/DEV_ROUND_K/2] | |
342 | rasize=$[rasize*DEV_ROUND_K*2] | |
343 | fi | |
344 | [ `/sbin/blockdev --getsize $dev` -eq 0 ] && sleep 2 | |
345 | _sz=`/sbin/blockdev --getsize $dev` | |
346 | [ $rasize -lt $_sz -o $[rasize*4/5] -gt $_sz ] && | |
347 | die "size is wrong for $dev: $cnt * $dvsize (chunk=$chunk) = $rasize, not $_sz" | |
348 | return 0 | |
349 | } | |
350 | ||
351 | rotest() { | |
352 | dev=$1 | |
353 | fsck -fn $dev >&2 | |
354 | } |