]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | #!/usr/bin/env bash |
7c673cae FG |
2 | |
3 | # Copyright (C) 2012 Dreamhost, LLC | |
4 | # | |
5 | # This is free software; see the source for copying conditions. | |
6 | # There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR | |
7 | # A PARTICULAR PURPOSE. | |
8 | # | |
9 | # This is free software; you can redistribute it and/or modify it | |
10 | # under the terms of the GNU General Public License as | |
11 | # published by the Free Software Foundation version 2. | |
12 | ||
13 | # Usage: | |
14 | # run_xfstests -t /dev/<testdev> -s /dev/<scratchdev> [-f <fstype>] -- <tests> | |
15 | # - test device and scratch device will both get trashed | |
16 | # - fstypes can be xfs, ext4, or btrfs (xfs default) | |
17 | # - tests can be listed individually: generic/001 xfs/008 xfs/009 | |
18 | # tests can also be specified by group: -g quick | |
19 | # | |
20 | # Exit status: | |
21 | # 0: success | |
22 | # 1: usage error | |
23 | # 2: other runtime error | |
24 | # 99: argument count error (programming error) | |
25 | # 100: getopt error (internal error) | |
26 | ||
27 | # Alex Elder <elder@dreamhost.com> | |
28 | # April 13, 2012 | |
29 | ||
30 | set -e | |
31 | ||
32 | PROGNAME=$(basename $0) | |
33 | ||
7c673cae FG |
34 | # Default command line option values |
35 | COUNT="1" | |
36 | EXPUNGE_FILE="" | |
37 | DO_RANDOMIZE="" # false | |
181888fb | 38 | FSTYP="xfs" |
7c673cae FG |
39 | SCRATCH_DEV="" # MUST BE SPECIFIED |
40 | TEST_DEV="" # MUST BE SPECIFIED | |
41 | TESTS="-g auto" # The "auto" group is supposed to be "known good" | |
42 | ||
7c673cae FG |
43 | # print an error message and quit with non-zero status |
44 | function err() { | |
45 | if [ $# -gt 0 ]; then | |
46 | echo "" >&2 | |
47 | echo "${PROGNAME}: ${FUNCNAME[1]}: $@" >&2 | |
48 | fi | |
49 | exit 2 | |
50 | } | |
51 | ||
52 | # routine used to validate argument counts to all shell functions | |
53 | function arg_count() { | |
54 | local func | |
55 | local want | |
56 | local got | |
57 | ||
58 | if [ $# -eq 2 ]; then | |
59 | func="${FUNCNAME[1]}" # calling function | |
60 | want=$1 | |
61 | got=$2 | |
62 | else | |
63 | func="${FUNCNAME[0]}" # i.e., arg_count | |
64 | want=2 | |
65 | got=$# | |
66 | fi | |
67 | [ "${want}" -eq "${got}" ] && return 0 | |
68 | echo "${PROGNAME}: ${func}: arg count bad (want ${want} got ${got})" >&2 | |
69 | exit 99 | |
70 | } | |
71 | ||
72 | # validation function for repeat count argument | |
73 | function count_valid() { | |
74 | arg_count 1 $# | |
75 | ||
76 | test "$1" -gt 0 # 0 is pointless; negative is wrong | |
77 | } | |
78 | ||
79 | # validation function for filesystem type argument | |
80 | function fs_type_valid() { | |
81 | arg_count 1 $# | |
82 | ||
83 | case "$1" in | |
84 | xfs|ext4|btrfs) return 0 ;; | |
85 | *) return 1 ;; | |
86 | esac | |
87 | } | |
88 | ||
89 | # validation function for device arguments | |
90 | function device_valid() { | |
91 | arg_count 1 $# | |
92 | ||
93 | # Very simple testing--really should try to be more careful... | |
94 | test -b "$1" | |
95 | } | |
96 | ||
97 | # validation function for expunge file argument | |
98 | function expunge_file_valid() { | |
99 | arg_count 1 $# | |
100 | ||
101 | test -s "$1" | |
102 | } | |
103 | ||
104 | # print a usage message and quit | |
105 | # | |
106 | # if a message is supplied, print that first, and then exit | |
107 | # with non-zero status | |
108 | function usage() { | |
109 | if [ $# -gt 0 ]; then | |
110 | echo "" >&2 | |
111 | echo "$@" >&2 | |
112 | fi | |
113 | ||
114 | echo "" >&2 | |
115 | echo "Usage: ${PROGNAME} <options> -- <tests>" >&2 | |
116 | echo "" >&2 | |
117 | echo " options:" >&2 | |
118 | echo " -h or --help" >&2 | |
119 | echo " show this message" >&2 | |
120 | echo " -c or --count" >&2 | |
121 | echo " iteration count (1 or more)" >&2 | |
122 | echo " -f or --fs-type" >&2 | |
123 | echo " one of: xfs, ext4, btrfs" >&2 | |
124 | echo " (default fs-type: xfs)" >&2 | |
125 | echo " -r or --randomize" >&2 | |
126 | echo " randomize test order" >&2 | |
127 | echo " -s or --scratch-dev (REQUIRED)" >&2 | |
128 | echo " name of device used for scratch filesystem" >&2 | |
129 | echo " -t or --test-dev (REQUIRED)" >&2 | |
130 | echo " name of device used for test filesystem" >&2 | |
131 | echo " -x or --expunge-file" >&2 | |
132 | echo " name of file with list of tests to skip" >&2 | |
133 | echo " tests:" >&2 | |
134 | echo " list of test numbers, e.g.:" >&2 | |
135 | echo " generic/001 xfs/008 shared/032 btrfs/009" >&2 | |
136 | echo " or possibly an xfstests test group, e.g.:" >&2 | |
137 | echo " -g quick" >&2 | |
138 | echo " (default tests: -g auto)" >&2 | |
139 | echo "" >&2 | |
140 | ||
141 | [ $# -gt 0 ] && exit 1 | |
142 | ||
143 | exit 0 # This is used for a --help | |
144 | } | |
145 | ||
146 | # parse command line arguments | |
147 | function parseargs() { | |
148 | # Short option flags | |
149 | SHORT_OPTS="" | |
150 | SHORT_OPTS="${SHORT_OPTS},h" | |
151 | SHORT_OPTS="${SHORT_OPTS},c:" | |
152 | SHORT_OPTS="${SHORT_OPTS},f:" | |
153 | SHORT_OPTS="${SHORT_OPTS},r" | |
154 | SHORT_OPTS="${SHORT_OPTS},s:" | |
155 | SHORT_OPTS="${SHORT_OPTS},t:" | |
156 | SHORT_OPTS="${SHORT_OPTS},x:" | |
157 | ||
158 | # Long option flags | |
159 | LONG_OPTS="" | |
160 | LONG_OPTS="${LONG_OPTS},help" | |
161 | LONG_OPTS="${LONG_OPTS},count:" | |
162 | LONG_OPTS="${LONG_OPTS},fs-type:" | |
163 | LONG_OPTS="${LONG_OPTS},randomize" | |
164 | LONG_OPTS="${LONG_OPTS},scratch-dev:" | |
165 | LONG_OPTS="${LONG_OPTS},test-dev:" | |
166 | LONG_OPTS="${LONG_OPTS},expunge-file:" | |
167 | ||
168 | TEMP=$(getopt --name "${PROGNAME}" \ | |
169 | --options "${SHORT_OPTS}" \ | |
170 | --longoptions "${LONG_OPTS}" \ | |
171 | -- "$@") | |
172 | eval set -- "$TEMP" | |
173 | ||
174 | while [ "$1" != "--" ]; do | |
175 | case "$1" in | |
176 | -h|--help) | |
177 | usage | |
178 | ;; | |
179 | -c|--count) | |
180 | count_valid "$2" || | |
181 | usage "invalid count '$2'" | |
182 | COUNT="$2" | |
183 | shift | |
184 | ;; | |
185 | -f|--fs-type) | |
186 | fs_type_valid "$2" || | |
187 | usage "invalid fs_type '$2'" | |
181888fb | 188 | FSTYP="$2" |
7c673cae FG |
189 | shift |
190 | ;; | |
191 | -r|--randomize) | |
192 | DO_RANDOMIZE="t" | |
193 | ;; | |
194 | -s|--scratch-dev) | |
195 | device_valid "$2" || | |
196 | usage "invalid scratch-dev '$2'" | |
197 | SCRATCH_DEV="$2" | |
198 | shift | |
199 | ;; | |
200 | -t|--test-dev) | |
201 | device_valid "$2" || | |
202 | usage "invalid test-dev '$2'" | |
203 | TEST_DEV="$2" | |
204 | shift | |
205 | ;; | |
206 | -x|--expunge-file) | |
207 | expunge_file_valid "$2" || | |
208 | usage "invalid expunge-file '$2'" | |
209 | EXPUNGE_FILE="$2" | |
210 | shift | |
211 | ;; | |
212 | *) | |
213 | exit 100 # Internal error | |
214 | ;; | |
215 | esac | |
216 | shift | |
217 | done | |
218 | shift | |
219 | ||
220 | [ -n "${TEST_DEV}" ] || usage "test-dev must be supplied" | |
221 | [ -n "${SCRATCH_DEV}" ] || usage "scratch-dev must be supplied" | |
222 | ||
223 | [ $# -eq 0 ] || TESTS="$@" | |
224 | } | |
225 | ||
226 | ################################################################ | |
227 | ||
7c673cae FG |
228 | # run mkfs on the given device using the specified filesystem type |
229 | function do_mkfs() { | |
230 | arg_count 1 $# | |
231 | ||
232 | local dev="${1}" | |
233 | local options | |
234 | ||
235 | case "${FSTYP}" in | |
181888fb FG |
236 | xfs) options="-f" ;; |
237 | ext4) options="-F" ;; | |
238 | btrfs) options="-f" ;; | |
7c673cae FG |
239 | esac |
240 | ||
241 | "mkfs.${FSTYP}" ${options} "${dev}" || | |
242 | err "unable to make ${FSTYP} file system on device \"${dev}\"" | |
243 | } | |
244 | ||
7c673cae FG |
245 | # top-level setup routine |
246 | function setup() { | |
247 | arg_count 0 $# | |
248 | ||
181888fb FG |
249 | wget -P "${TESTDIR}" http://download.ceph.com/qa/xfstests.tar.gz |
250 | tar zxf "${TESTDIR}/xfstests.tar.gz" -C "$(dirname "${XFSTESTS_DIR}")" | |
251 | mkdir "${TEST_DIR}" | |
252 | mkdir "${SCRATCH_MNT}" | |
253 | do_mkfs "${TEST_DEV}" | |
7c673cae FG |
254 | } |
255 | ||
256 | # top-level (final) cleanup routine | |
257 | function cleanup() { | |
258 | arg_count 0 $# | |
259 | ||
181888fb FG |
260 | # ensure teuthology can clean up the logs |
261 | chmod -R a+rw "${TESTDIR}/archive" | |
262 | ||
263 | findmnt "${TEST_DEV}" && umount "${TEST_DEV}" | |
264 | [ -d "${SCRATCH_MNT}" ] && rmdir "${SCRATCH_MNT}" | |
265 | [ -d "${TEST_DIR}" ] && rmdir "${TEST_DIR}" | |
266 | rm -rf "${XFSTESTS_DIR}" | |
267 | rm -f "${TESTDIR}/xfstests.tar.gz" | |
7c673cae | 268 | } |
7c673cae FG |
269 | |
270 | # ################################################################ | |
271 | ||
272 | start_date="$(date)" | |
7c673cae | 273 | parseargs "$@" |
181888fb FG |
274 | [ -n "${TESTDIR}" ] || usage "TESTDIR env variable must be set" |
275 | [ -d "${TESTDIR}/archive" ] || usage "\$TESTDIR/archive directory must exist" | |
276 | TESTDIR="$(readlink -e "${TESTDIR}")" | |
277 | [ -n "${EXPUNGE_FILE}" ] && EXPUNGE_FILE="$(readlink -e "${EXPUNGE_FILE}")" | |
7c673cae | 278 | |
181888fb FG |
279 | XFSTESTS_DIR="/var/lib/xfstests" # hardcoded into dbench binary |
280 | TEST_DIR="/mnt/test_dir" | |
281 | SCRATCH_MNT="/mnt/scratch_mnt" | |
282 | MKFS_OPTIONS="" | |
20effc67 | 283 | EXT_MOUNT_OPTIONS="-o block_validity,dioread_nolock" |
181888fb FG |
284 | |
285 | trap cleanup EXIT ERR HUP INT QUIT | |
7c673cae FG |
286 | setup |
287 | ||
181888fb FG |
288 | export TEST_DEV |
289 | export TEST_DIR | |
290 | export SCRATCH_DEV | |
291 | export SCRATCH_MNT | |
292 | export FSTYP | |
293 | export MKFS_OPTIONS | |
294 | export EXT_MOUNT_OPTIONS | |
295 | ||
7c673cae FG |
296 | pushd "${XFSTESTS_DIR}" |
297 | for (( i = 1 ; i <= "${COUNT}" ; i++ )); do | |
298 | [ "${COUNT}" -gt 1 ] && echo "=== Iteration "$i" starting at: $(date)" | |
299 | ||
181888fb FG |
300 | RESULT_BASE="${TESTDIR}/archive/results-${i}" |
301 | mkdir "${RESULT_BASE}" | |
302 | export RESULT_BASE | |
303 | ||
7c673cae FG |
304 | EXPUNGE="" |
305 | [ -n "${EXPUNGE_FILE}" ] && EXPUNGE="-E ${EXPUNGE_FILE}" | |
306 | ||
307 | RANDOMIZE="" | |
308 | [ -n "${DO_RANDOMIZE}" ] && RANDOMIZE="-r" | |
309 | ||
310 | # -T output timestamps | |
181888fb FG |
311 | PATH="${PWD}/bin:${PATH}" ./check -T ${RANDOMIZE} ${EXPUNGE} ${TESTS} |
312 | findmnt "${TEST_DEV}" && umount "${TEST_DEV}" | |
7c673cae FG |
313 | |
314 | [ "${COUNT}" -gt 1 ] && echo "=== Iteration "$i" complete at: $(date)" | |
315 | done | |
316 | popd | |
317 | ||
318 | # cleanup is called via the trap call, above | |
319 | ||
320 | echo "This xfstests run started at: ${start_date}" | |
321 | echo "xfstests run completed at: $(date)" | |
322 | [ "${COUNT}" -gt 1 ] && echo "xfstests run consisted of ${COUNT} iterations" | |
181888fb | 323 | echo OK |