3 # Copyright (C) 2012 Dreamhost, LLC
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.
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.
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
23 # 2: other runtime error
24 # 99: argument count error (programming error)
25 # 100: getopt error (internal error)
27 # Alex Elder <elder@dreamhost.com>
32 PROGNAME
=$
(basename $0)
34 # xfstests is downloaded from this git repository and then built.
35 # XFSTESTS_REPO="git://oss.sgi.com/xfs/cmds/xfstests.git"
36 XFSTESTS_REPO
="git://git.ceph.com/xfstests.git"
37 XFSTESTS_VERSION
="facff609afd6a2ca557c2b679e088982026aa188"
38 XFSPROGS_REPO
="git://oss.sgi.com/xfs/cmds/xfsprogs"
39 XFSPROGS_VERSION
="v3.2.2"
40 XFSDUMP_REPO
="git://oss.sgi.com/xfs/cmds/xfsdump"
41 XFSDUMP_VERSION
="v3.1.4"
43 # Default command line option values
46 DO_RANDOMIZE
="" # false
48 SCRATCH_DEV
="" # MUST BE SPECIFIED
49 TEST_DEV
="" # MUST BE SPECIFIED
50 TESTS
="-g auto" # The "auto" group is supposed to be "known good"
52 # We no longer need to set the stripe unit in XFS_MKFS_OPTIONS because recent
53 # versions of mkfs.xfs autodetect it.
55 # print an error message and quit with non-zero status
59 echo "${PROGNAME}: ${FUNCNAME[1]}: $@" >&2
64 # routine used to validate argument counts to all shell functions
65 function arg_count
() {
71 func
="${FUNCNAME[1]}" # calling function
75 func
="${FUNCNAME[0]}" # i.e., arg_count
79 [ "${want}" -eq "${got}" ] && return 0
80 echo "${PROGNAME}: ${func}: arg count bad (want ${want} got ${got})" >&2
84 # validation function for repeat count argument
85 function count_valid
() {
88 test "$1" -gt 0 # 0 is pointless; negative is wrong
91 # validation function for filesystem type argument
92 function fs_type_valid
() {
96 xfs|ext4|btrfs
) return 0 ;;
101 # validation function for device arguments
102 function device_valid
() {
105 # Very simple testing--really should try to be more careful...
109 # validation function for expunge file argument
110 function expunge_file_valid
() {
116 # print a usage message and quit
118 # if a message is supplied, print that first, and then exit
119 # with non-zero status
121 if [ $# -gt 0 ]; then
127 echo "Usage: ${PROGNAME} <options> -- <tests>" >&2
130 echo " -h or --help" >&2
131 echo " show this message" >&2
132 echo " -c or --count" >&2
133 echo " iteration count (1 or more)" >&2
134 echo " -f or --fs-type" >&2
135 echo " one of: xfs, ext4, btrfs" >&2
136 echo " (default fs-type: xfs)" >&2
137 echo " -r or --randomize" >&2
138 echo " randomize test order" >&2
139 echo " -s or --scratch-dev (REQUIRED)" >&2
140 echo " name of device used for scratch filesystem" >&2
141 echo " -t or --test-dev (REQUIRED)" >&2
142 echo " name of device used for test filesystem" >&2
143 echo " -x or --expunge-file" >&2
144 echo " name of file with list of tests to skip" >&2
146 echo " list of test numbers, e.g.:" >&2
147 echo " generic/001 xfs/008 shared/032 btrfs/009" >&2
148 echo " or possibly an xfstests test group, e.g.:" >&2
150 echo " (default tests: -g auto)" >&2
153 [ $# -gt 0 ] && exit 1
155 exit 0 # This is used for a --help
158 # parse command line arguments
159 function parseargs
() {
162 SHORT_OPTS
="${SHORT_OPTS},h"
163 SHORT_OPTS
="${SHORT_OPTS},c:"
164 SHORT_OPTS
="${SHORT_OPTS},f:"
165 SHORT_OPTS
="${SHORT_OPTS},r"
166 SHORT_OPTS
="${SHORT_OPTS},s:"
167 SHORT_OPTS
="${SHORT_OPTS},t:"
168 SHORT_OPTS
="${SHORT_OPTS},x:"
172 LONG_OPTS
="${LONG_OPTS},help"
173 LONG_OPTS
="${LONG_OPTS},count:"
174 LONG_OPTS
="${LONG_OPTS},fs-type:"
175 LONG_OPTS
="${LONG_OPTS},randomize"
176 LONG_OPTS
="${LONG_OPTS},scratch-dev:"
177 LONG_OPTS
="${LONG_OPTS},test-dev:"
178 LONG_OPTS
="${LONG_OPTS},expunge-file:"
180 TEMP
=$
(getopt
--name "${PROGNAME}" \
181 --options "${SHORT_OPTS}" \
182 --longoptions "${LONG_OPTS}" \
186 while [ "$1" != "--" ]; do
193 usage
"invalid count '$2'"
198 fs_type_valid
"$2" ||
199 usage
"invalid fs_type '$2'"
208 usage
"invalid scratch-dev '$2'"
214 usage
"invalid test-dev '$2'"
219 expunge_file_valid
"$2" ||
220 usage
"invalid expunge-file '$2'"
225 exit 100 # Internal error
232 [ -n "${TEST_DEV}" ] || usage
"test-dev must be supplied"
233 [ -n "${SCRATCH_DEV}" ] || usage
"scratch-dev must be supplied"
235 [ $# -eq 0 ] || TESTS
="$@"
238 ################################################################
240 [ -n "${TESTDIR}" ] || usage
"TESTDIR env variable must be set"
242 # Set up some environment for normal teuthology test setup.
243 # This really should not be necessary but I found it was.
244 export CEPH_ARGS
="--conf ${TESTDIR}/ceph.conf"
245 export CEPH_ARGS
="${CEPH_ARGS} --keyring ${TESTDIR}/data/client.0.keyring"
246 export CEPH_ARGS
="${CEPH_ARGS} --name client.0"
248 export LD_LIBRARY_PATH
="${TESTDIR}/binary/usr/local/lib:${LD_LIBRARY_PATH}"
249 export PATH
="${TESTDIR}/binary/usr/local/bin:${PATH}"
250 export PATH
="${TESTDIR}/binary/usr/local/sbin:${PATH}"
252 ################################################################
254 # Filesystem-specific mkfs options--set if not supplied
255 #export XFS_MKFS_OPTIONS="${XFS_MKFS_OPTIONS:--f -l su=65536}"
256 export EXT4_MKFS_OPTIONS
="${EXT4_MKFS_OPTIONS:--F}"
257 export BTRFS_MKFS_OPTION
# No defaults
259 XFSTESTS_DIR
="/var/lib/xfstests" # Where the tests live
260 XFSPROGS_DIR
="/tmp/cephtest/xfsprogs-install"
261 XFSDUMP_DIR
="/tmp/cephtest/xfsdump-install"
262 export PATH
="${XFSPROGS_DIR}/sbin:${XFSDUMP_DIR}/sbin:${PATH}"
264 # download, build, and install xfstests
265 function install_xfstests
() {
273 git clone
"${XFSTESTS_REPO}"
276 git checkout
"${XFSTESTS_VERSION}"
278 ncpu
=$
(getconf _NPROCESSORS_ONLN
2>&1)
279 [ -n "${ncpu}" -a "${ncpu}" -gt 1 ] && multiple="-j ${ncpu}"
288 # remove previously-installed xfstests files
289 function remove_xfstests
() {
292 rm -rf "${TESTDIR}/xfstests"
293 rm -rf "${XFSTESTS_DIR}"
296 # create a host options file that uses the specified devices
297 function setup_host_options
() {
299 export MNTDIR
="/tmp/cephtest"
301 # Create mount points for the test and scratch filesystems
303 local test_dir
="$(mktemp -d ${MNTDIR}/test_dir.XXXXXXXXXX)"
304 local scratch_dir
="$(mktemp -d ${MNTDIR}/scratch_mnt.XXXXXXXXXX)"
306 # Write a host options file that uses these devices.
307 # xfstests uses the file defined by HOST_OPTIONS as the
308 # place to get configuration variables for its run, and
309 # all (or most) of the variables set here are required.
310 export HOST_OPTIONS
="$(mktemp ${TESTDIR}/host_options.XXXXXXXXXX)"
311 cat > "${HOST_OPTIONS}" <<-!
312 # Created by ${PROGNAME} on $(date)
313 # HOST_OPTIONS="${HOST_OPTIONS}"
314 TEST_DEV="${TEST_DEV}"
315 SCRATCH_DEV="${SCRATCH_DEV}"
316 TEST_DIR="${test_dir}"
317 SCRATCH_MNT="${scratch_dir}"
319 export TEST_DEV SCRATCH_DEV TEST_DIR SCRATCH_MNT FSTYP
321 export XFS_MKFS_OPTIONS="${XFS_MKFS_OPTIONS}"
324 # Now ensure we are using the same values
328 # remove the host options file, plus the directories it refers to
329 function cleanup_host_options() {
332 rm -rf "${TEST_DIR}" "${SCRATCH_MNT}"
333 rm -f "${HOST_OPTIONS}"
336 # run mkfs on the given device using the specified filesystem type
344 xfs) options="${XFS_MKFS_OPTIONS}" ;;
345 ext4) options="${EXT4_MKFS_OPTIONS}" ;;
346 btrfs) options="${BTRFS_MKFS_OPTIONS}" ;;
349 "mkfs.${FSTYP}" ${options} "${dev}" ||
350 err "unable to make ${FSTYP} file system on device \"${dev}\""
353 # mount the given device on the given mount point
354 function do_mount() {
360 mount "${dev}" "${dir}" ||
361 err "unable to mount file system \"${dev}\" on \"${dir}\""
364 # unmount a previously-mounted device
365 function do_umount() {
370 if mount | grep "${dev}" > /dev/null; then
371 if ! umount "${dev}"; then
372 err "unable to unmount device \"${dev}\""
375 # Report it but don't error out
376 echo "device \"${dev}\" was not mounted" >&2
380 # do basic xfstests setup--make and mount the test and scratch filesystems
381 function setup_xfstests() {
384 # TEST_DEV can persist across test runs, but for now we
385 # don't bother. I believe xfstests prefers its devices to
386 # have been already been formatted for the desired
387 # filesystem type--it uses blkid to identify things or
388 # something. So we mkfs both here for a fresh start.
389 do_mkfs "${TEST_DEV}"
390 do_mkfs "${SCRATCH_DEV}"
392 # I believe the test device is expected to be mounted; the
393 # scratch doesn't need to be (but it doesn't hurt).
394 do_mount "${TEST_DEV}" "${TEST_DIR}"
395 do_mount "${SCRATCH_DEV}" "${SCRATCH_MNT}"
398 # clean up changes made by setup_xfstests
399 function cleanup_xfstests() {
402 # Unmount these in case a test left them mounted (plus
403 # the corresponding setup function mounted them...)
404 do_umount "${TEST_DEV}"
405 do_umount "${SCRATCH_DEV}"
407 rmdir "${SCRATCH_MNT}"
411 function install_xfsprogs() {
415 git clone ${XFSPROGS_REPO}
417 git checkout ${XFSPROGS_VERSION}
418 libtoolize -c `libtoolize -n -i >/dev/null 2>/dev/null && echo -i` -f
419 cp include/install-sh .
422 ./configure --prefix=${XFSPROGS_DIR}
427 function install_xfsdump() {
431 git clone ${XFSDUMP_REPO}
433 git checkout ${XFSDUMP_VERSION}
435 # somebody took #define min and #define max out, which breaks the build on
436 # ubuntu. we back out this commit here, though that may cause problems with
437 # this script down the line.
438 git revert -n 5a2985233c390d59d2a9757b119cb0e001c87a96
439 libtoolize -c `libtoolize -n -i >/dev/null 2>/dev/null && echo -i` -f
440 cp include/install-sh .
443 ./configure --prefix=${XFSDUMP_DIR}
444 (make -k install || true) # that's right, the install process is broken too
448 function remove_xfsprogs() {
451 rm -rf ${TESTDIR}/xfsprogs
452 rm -rf ${XFSPROGS_DIR}
455 function remove_xfsdump() {
458 rm -rf ${TESTDIR}/xfsdump
459 rm -rf ${XFSDUMP_DIR}
463 # top-level setup routine
474 # top-level (final) cleanup routine
485 trap cleanup EXIT ERR HUP INT QUIT
487 # ################################################################
495 pushd "${XFSTESTS_DIR}"
496 for (( i = 1 ; i <= "${COUNT}" ; i++ )); do
497 [ "${COUNT}" -gt 1 ] && echo "=== Iteration "$i" starting at: $(date)"
500 [ -n "${EXPUNGE_FILE}" ] && EXPUNGE="-E ${EXPUNGE_FILE}"
503 [ -n "${DO_RANDOMIZE}" ] && RANDOMIZE="-r"
505 # -T output timestamps
506 ./check -T ${RANDOMIZE} ${EXPUNGE} ${TESTS}
509 [ "${COUNT}" -gt 1 ] && echo "=== Iteration "$i" complete at: $(date)"
513 # cleanup is called via the trap call, above
515 echo "This xfstests run started at: ${start_date}"
516 echo "xfstests run completed at: $(date)"
517 [ "${COUNT}" -gt 1 ] && echo "xfstests run consisted of ${COUNT} iterations"