]>
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" | |
126 | } | |
127 | ||
128 | do_setup() { | |
129 | trap cleanup 0 1 3 15 | |
130 | trap ctrl_c 2 | |
131 | ||
132 | check_env | |
133 | [ -d $logdir ] || mkdir -p $logdir | |
cbb8d34a ZL |
134 | |
135 | devlist= | |
136 | if [ "$DEVTYPE" == "loop" ] | |
137 | then | |
138 | # make sure there are no loop devices remaining. | |
139 | # udev started things can sometimes prevent them being stopped | |
140 | # immediately | |
141 | while grep loop /proc/partitions > /dev/null 2>&1 | |
142 | do | |
143 | $mdadm -Ssq | |
144 | losetup -d /dev/loop[0-9]* 2> /dev/null | |
145 | sleep 0.2 | |
146 | done | |
147 | elif [ "$DEVTYPE" == "disk" ] | |
148 | then | |
149 | if [ ! -z "$disks" ] | |
150 | then | |
151 | for d in $(seq 0 ${#disks[@]}) | |
152 | do | |
153 | eval "dev$d=${disks[$d]}" | |
154 | eval devlist=\"\$devlist \$dev$d\" | |
155 | eval devlist$d=\"\$devlist\" | |
156 | done | |
157 | $mdadm --zero ${disks[@]} &> /dev/null | |
158 | else | |
159 | echo "Forget to provide physical devices for disk mode." | |
160 | exit 1 | |
161 | fi | |
162 | fi | |
163 | for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |
164 | do | |
165 | sz=$size | |
166 | [ $d -gt 7 ] && sz=$ddfsize | |
167 | case $DEVTYPE in | |
168 | loop) | |
169 | [ -f $targetdir/mdtest$d ] || | |
170 | dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1 | |
171 | # make sure udev doesn't touch | |
172 | mdadm --zero $targetdir/mdtest$d 2> /dev/null | |
173 | [ -b /dev/loop$d ] || mknod /dev/loop$d b 7 $d | |
174 | if [ $d -eq 7 ] | |
175 | then | |
176 | losetup /dev/loop$d $targetdir/mdtest6 # for multipath use | |
177 | else | |
178 | losetup /dev/loop$d $targetdir/mdtest$d | |
179 | fi | |
180 | eval dev$d=/dev/loop$d | |
181 | eval file$d=$targetdir/mdtest$d | |
182 | ;; | |
183 | lvm) | |
184 | unset MULTIPATH | |
185 | eval dev$d=/dev/mapper/${LVM_VOLGROUP}-mdtest$d | |
186 | if ! lvcreate --quiet -L ${sz}K -n mdtest$d $LVM_VOLGROUP | |
187 | then | |
188 | trap '' 0 # make sure lvremove is not called | |
189 | eval echo error creating \$dev$d | |
190 | exit 129 | |
191 | fi | |
192 | ;; | |
193 | ram) | |
194 | unset MULTIPATH | |
195 | eval dev$d=/dev/ram$d | |
196 | ;; | |
197 | esac | |
198 | eval devlist=\"\$devlist \$dev$d\" | |
199 | eval devlist$d=\"\$devlist\" | |
200 | #" <-- add this quote to un-confuse vim syntax highlighting | |
201 | done | |
202 | path0=$dev6 | |
203 | path1=$dev7 | |
204 | ulimit -c unlimited | |
205 | [ -f /proc/mdstat ] || modprobe md_mod | |
206 | echo 2000 > /proc/sys/dev/raid/speed_limit_max | |
207 | echo 0 > /sys/module/md_mod/parameters/start_ro | |
208 | } | |
209 | ||
210 | # check various things | |
211 | check() { | |
212 | case $1 in | |
9c816fe2 XN |
213 | opposite_result ) |
214 | if [ $? -eq 0 ]; then | |
215 | die "This command shouldn't run successfully" | |
216 | fi | |
59416da7 | 217 | ;; |
cbb8d34a ZL |
218 | spares ) |
219 | spares=$(tr '] ' '\012\012' < /proc/mdstat | grep -c '(S)' || exit 0) | |
220 | [ $spares -ne $2 ] && | |
221 | die "expected $2 spares, found $spares" | |
222 | ;; | |
223 | raid* | linear ) | |
224 | grep -sq "active $1 " /proc/mdstat || | |
225 | die "active $1 not found" | |
226 | ;; | |
227 | algorithm ) | |
228 | grep -sq " algorithm $2 " /proc/mdstat || | |
229 | die "algorithm $2 not found" | |
230 | ;; | |
231 | resync | recovery | reshape ) | |
232 | cnt=5 | |
233 | while ! grep -sq $1 /proc/mdstat | |
234 | do | |
235 | if [ $cnt -gt 0 ] && grep -v idle /sys/block/md*/md/sync_action > /dev/null | |
236 | then # Something isn't idle - wait a bit | |
237 | sleep 0.5 | |
238 | cnt=$[cnt-1] | |
239 | else | |
240 | die "no $1 happening" | |
241 | fi | |
242 | done | |
243 | ;; | |
244 | nosync ) | |
245 | sleep 0.5 | |
246 | # Since 4.2 we delay the close of recovery until there has been a chance for | |
247 | # spares to be activated. That means that a recovery that finds nothing | |
248 | # to do can still take a little longer than expected. | |
249 | # add an extra check: is sync_completed shows the end is reached, assume | |
250 | # there is no recovery. | |
251 | if grep -sq -E '(resync|recovery|reshape) *=' /proc/mdstat | |
252 | then | |
253 | incomplete=`grep / /sys/block/md*/md/sync_completed 2> /dev/null | sed '/^ *\([0-9]*\) \/ \1/d'` | |
254 | [ -n "$incomplete" ] && | |
255 | die "resync or recovery is happening!" | |
256 | fi | |
257 | ;; | |
258 | wait ) | |
259 | p=`cat /proc/sys/dev/raid/speed_limit_max` | |
260 | echo 2000000 > /proc/sys/dev/raid/speed_limit_max | |
261 | sleep 0.1 | |
262 | while grep -Eq '(resync|recovery|reshape|check|repair) *=' /proc/mdstat || | |
263 | grep -v idle > /dev/null /sys/block/md*/md/sync_action | |
264 | do | |
265 | sleep 0.5 | |
266 | done | |
267 | echo $p > /proc/sys/dev/raid/speed_limit_max | |
268 | ;; | |
269 | state ) | |
270 | grep -sq "blocks.*\[$2\]\$" /proc/mdstat || | |
271 | die "state $2 not found!" | |
272 | sleep 0.5 | |
273 | ;; | |
274 | bitmap ) | |
275 | grep -sq bitmap /proc/mdstat || | |
276 | die "no bitmap" | |
277 | ;; | |
278 | nobitmap ) | |
279 | grep -sq "bitmap" /proc/mdstat && | |
280 | die "bitmap present" | |
281 | ;; | |
282 | readonly ) | |
283 | grep -sq "read-only" /proc/mdstat || | |
284 | die "array is not read-only!" | |
285 | ;; | |
286 | inactive ) | |
287 | grep -sq "inactive" /proc/mdstat || | |
288 | die "array is not inactive!" | |
289 | ;; | |
290 | # It only can be used when there is only one raid | |
291 | chunk ) | |
292 | chunk_size=`awk -F',' '/chunk/{print $2}' /proc/mdstat | awk -F'[a-z]' '{print $1}'` | |
293 | if [ "$chunk_size" -ne "$2" ] ; then | |
294 | die "chunksize should be $2, but it's $chunk_size" | |
295 | fi | |
296 | ;; | |
297 | * ) | |
298 | die "unknown check $1" | |
299 | ;; | |
300 | esac | |
301 | } | |
302 | ||
303 | no_errors() { | |
304 | if [ -s $targetdir/stderr ] | |
305 | then | |
306 | echo Bad errors from mdadm: | |
307 | cat $targetdir/stderr | |
308 | exit 2 | |
309 | fi | |
310 | } | |
311 | ||
312 | # basic device test | |
313 | testdev() { | |
314 | [ -b $1 ] || die "$1 isn't a block device." | |
315 | [ "$DEVTYPE" == "disk" ] && return 0 | |
316 | udevadm settle | |
317 | dev=$1 | |
318 | cnt=$2 | |
319 | dvsize=$3 | |
320 | chunk=$4 | |
321 | if [ -z "$5" ] | |
322 | then | |
323 | mkfs.ext3 -F -j $dev > /dev/null 2>&1 && fsck -fn $dev >&2 | |
324 | fi | |
325 | dsize=$[dvsize/chunk] | |
326 | dsize=$[dsize*chunk] | |
327 | rasize=$[dsize*2*cnt] | |
328 | # rasize is in sectors | |
329 | if [ -n "$DEV_ROUND_K" ] | |
330 | then | |
331 | rasize=$[rasize/DEV_ROUND_K/2] | |
332 | rasize=$[rasize*DEV_ROUND_K*2] | |
333 | fi | |
334 | [ `/sbin/blockdev --getsize $dev` -eq 0 ] && sleep 2 | |
335 | _sz=`/sbin/blockdev --getsize $dev` | |
336 | [ $rasize -lt $_sz -o $[rasize*4/5] -gt $_sz ] && | |
337 | die "size is wrong for $dev: $cnt * $dvsize (chunk=$chunk) = $rasize, not $_sz" | |
338 | return 0 | |
339 | } | |
340 | ||
341 | rotest() { | |
342 | dev=$1 | |
343 | fsck -fn $dev >&2 | |
344 | } |