Whamcloud - gitweb
LU-13273 tests: run_ior() parameters order fix
[fs/lustre-release.git] / lustre / tests / functions.sh
1 #!/bin/bash
2
3 # Simple function used by run_*.sh scripts
4
5 assert_env() {
6     local failed=""
7     for name in $@; do
8         if [ -z "${!name}" ]; then
9             echo "$0: $name must be set"
10             failed=1
11         fi
12     done
13     [ $failed ] && exit 1 || true
14 }
15
16 # lrepl - Lustre test Read-Eval-Print Loop.
17 #
18 # This function implements a REPL for the Lustre test framework.  It
19 # doesn't exec an actual shell because the user may want to inspect
20 # variables and use functions from the test framework.
21 lrepl() {
22     local line
23     local rawline
24     local prompt
25
26     cat <<EOF
27         This is an interactive read-eval-print loop interactive shell
28         simulation that you can use to debug failing tests.  You can
29         enter most bash command lines (see notes below).
30
31         Use this REPL to inspect variables, set them, call test
32         framework shell functions, etcetera.
33
34         'exit' or EOF to exit this shell.
35
36         set \$retcode to 0 to cause the assertion failure that
37         triggered this REPL to be ignored.
38
39         Examples:
40             do_facet ost1 lctl get_param ost.*.ost.threads_*
41             do_rpc_nodes \$OSTNODES unload_modules
42
43         NOTES:
44             All but the last line of multi-line statements or blocks
45             must end in a backslash.
46
47             "Here documents" are not supported.
48
49             History is not supported, but command-line editing is.
50
51 EOF
52
53     # Prompt escapes don't work in read -p, sadly.
54     prompt=":${TESTNAME:-UNKNOWN}:$(uname -n):$(basename $PWD)% "
55
56     # We use read -r to get close to a shell experience
57     while read -e -r -p "$prompt" rawline; do
58         line=
59         case "$rawline" in
60         # Don't want to exit-exit, just exit the REPL
61         exit) break;;
62         # We need to handle continuations, and read -r doesn't do
63         # that for us.  Yet we need read -r.
64         #
65         # We also use case/esac to compare lines read to "*\\"
66         # because [ "$line" = *\\ ] and variants of that don't work.
67         *\\) line="$rawline"
68             while read -e -r -p '> ' rawline
69             do
70                 line="$line"$'\n'"$rawline"
71                 case "$rawline" in
72                 # We could check for here documents by matching
73                 # against *<<*, but who cares.
74                 *\\) continue;;
75                 *) break;;
76                 esac
77             done
78             ;;
79         *) line=$rawline
80         esac
81
82         case "$line" in
83         *\\) break;;
84         esac
85
86         # Finally!  Time to eval.
87         eval "$line"
88     done
89
90     echo $'\n\tExiting interactive shell...\n'
91     return 0
92 }
93
94 # lassert - Lustre test framework assert
95 #
96 # Arguments: failure code, failure message, expression/statement
97 #
98 # lassert evaluates the expression given, and, if false, calls
99 # error() to trigger test failure.  If REPL_ON_LASSERT is true then
100 # lassert will call lrepl() to give the user an interactive shell.
101 # If the REPL sets retcode=0 then the assertion failure will be
102 # ignored.
103 lassert() {
104     local retcode=$1
105     local msg=$2
106     shift 2
107
108     echo "checking $* ($(eval echo \""$*"\"))..."
109     eval "$@" && return 0;
110
111     if ${REPL_ON_LASSERT:-false}; then
112         echo "Assertion $retcode failed: $* (expanded: $(eval echo \""$*"\"))
113 $msg"
114         lrepl
115     fi
116
117     error "Assertion $retcode failed: $* (expanded: $(eval echo \""$*"\"))
118 $msg"
119     return $retcode
120 }
121
122 # setmodopts- set module options for subsequent calls to load_modules
123 #
124 # Usage: setmodopts module_name new_value [var_in_which_to_save_old_value]
125 #        setmodopts -a module_name new_value [var_in_which_to_save_old_value]
126 #
127 # In the second usage the new value is appended to the old.
128 setmodopts() {
129         local _append=false
130
131         if [ "$1" = -a ]; then
132             _append=true
133             shift
134         fi
135
136         local _var=MODOPTS_$1
137         local _newvalue=$2
138         local _savevar=$3
139         local _oldvalue
140
141         # Dynamic naming of variables is a pain in bash.  In ksh93 we could
142         # write "nameref opts_var=${modname}_MODOPTS" then assign directly
143         # to opts_var.  Associative arrays would also help, alternatively.
144         # Alas, we're stuck with eval until all distros move to a more recent
145         # version of bash.  Fortunately we don't need to eval unset and export.
146
147         if [ -z "$_newvalue" ]; then
148             unset $_var
149             return 0
150         fi
151
152         _oldvalue=${!var}
153         $_append && _newvalue="$_oldvalue $_newvalue"
154         export $_var="$_newvalue"
155         echo setmodopts: ${_var}=${_newvalue}
156
157         [ -n "$_savevar" ] && eval $_savevar=\""$_oldvalue"\"
158 }
159
160 echoerr () { echo "$@" 1>&2 ; }
161
162 signaled() {
163     echoerr "$(date +'%F %H:%M:%S'): client load was signaled to terminate"
164
165     local PGID=$(ps -eo "%c %p %r" | awk "/ $PPID / {print \$3}")
166     kill -TERM -$PGID
167     sleep 5
168     kill -KILL -$PGID
169 }
170
171 mpi_run () {
172     local mpirun="$MPIRUN $MPIRUN_OPTIONS --oversubscribe"
173     local command="$mpirun $@"
174     local mpilog=$TMP/mpi.log
175     local rc
176
177     if [ -n "$MPI_USER" -a "$MPI_USER" != root -a -n "$mpirun" ]; then
178         echo "+ chmod 0777 $MOUNT"
179         chmod 0777 $MOUNT
180         command="su $MPI_USER sh -c \"$command \""
181     fi
182
183     ls -ald $MOUNT
184     echo "+ $command"
185     eval $command 2>&1 | tee $mpilog || true
186
187     rc=${PIPESTATUS[0]}
188     if [ $rc -eq 0 ] && grep -q "p4_error:" $mpilog ; then
189        rc=1
190     fi
191     return $rc
192 }
193
194 nids_list () {
195         local list
196         local escape="$2"
197         for i in ${1//,/ }; do
198                 if [ "$list" = "" ]; then
199                         list="$i@$NETTYPE"
200                 else
201                         list="$list$escape $i@$NETTYPE"
202                 fi
203         done
204         echo $list
205 }
206
207 # FIXME: all setup/cleanup can be done without rpc.sh
208 lst_end_session () {
209     local verbose=false
210     [ x$1 = x--verbose ] && verbose=true
211
212     export LST_SESSION=`$LST show_session 2>/dev/null | awk -F " " '{print $5}'`
213     [ "$LST_SESSION" == "" ] && return
214
215         $LST stop b
216     if $verbose; then
217         $LST show_error c s
218     fi
219     $LST end_session
220 }
221
222 lst_session_cleanup_all () {
223     local list=$(comma_list $(nodes_list))
224     do_rpc_nodes $list lst_end_session
225 }
226
227 lst_cleanup () {
228     lsmod | grep -q lnet_selftest && \
229         rmmod lnet_selftest > /dev/null 2>&1 || true
230 }
231
232 lst_cleanup_all () {
233    local list=$(comma_list $(nodes_list))
234
235    # lst end_session needs to be executed only locally
236    # i.e. on node where lst new_session was called
237    lst_end_session --verbose
238    do_rpc_nodes $list lst_cleanup
239 }
240
241 lst_setup () {
242     load_module lnet_selftest
243 }
244
245 lst_setup_all () {
246     local list=$(comma_list $(nodes_list))
247     do_rpc_nodes $list lst_setup
248 }
249
250 ###
251 # short_hostname
252 #
253 # Passed a single argument, strips everything off following
254 # and includes the first period.
255 # client-20.lab.whamcloud.com becomes client-20
256 short_hostname() {
257   echo $(sed 's/\..*//' <<< $1)
258 }
259
260 ###
261 # short_nodename
262 #
263 # Find remote nodename, stripped of any domain, etc.
264 # 'hostname -s' is easy, but not implemented on all systems
265 short_nodename() {
266         local rname=$(do_node $1 "uname -n" || echo -1)
267         if [[ "$rname" = "-1" ]]; then
268                 rname=$1
269         fi
270         echo $(short_hostname $rname)
271 }
272
273 print_opts () {
274     local var
275
276     echo OPTIONS:
277
278     for i in $@; do
279         var=$i
280         echo "${var}=${!var}"
281     done
282     [ -e $MACHINEFILE ] && cat $MACHINEFILE
283 }
284
285 is_lustre () {
286         [ "$(stat -f -c %T $1)" = "lustre" ]
287 }
288
289 setstripe_getstripe () {
290         local file=$1
291         shift
292         local params=$@
293
294         is_lustre $file || return 0
295
296         if [ -n "$params" ]; then
297                 $LFS setstripe $params $file ||
298                         error "setstripe $params failed"
299         fi
300         $LFS getstripe $file ||
301                 error "getstripe $file failed"
302 }
303
304 run_compilebench() {
305         local dir=${1:-$DIR}
306         local cbench_DIR=${cbench_DIR:-""}
307         local cbench_IDIRS=${cbench_IDIRS:-2}
308         local cbench_RUNS=${cbench_RUNS:-2}
309
310         print_opts cbench_DIR cbench_IDIRS cbench_RUNS
311
312         [ x$cbench_DIR = x ] &&
313                 skip_env "compilebench not found"
314
315         [ -e $cbench_DIR/compilebench ] ||
316                 skip_env "No compilebench build"
317
318         # Space estimation:
319         # compile dir kernel-0  ~1GB
320         # required space        ~1GB * cbench_IDIRS
321         local space=$(df -P $dir | tail -n 1 | awk '{ print $4 }')
322         if [[ $space -le $((1024 * 1024 * cbench_IDIRS)) ]]; then
323                 cbench_IDIRS=$((space / 1024 / 1024))
324                 [[ $cbench_IDIRS -eq 0 ]] &&
325                         skip_env "Need free space at least 1GB, have $space"
326
327                 echo "reducing initial dirs to $cbench_IDIRS"
328         fi
329         echo "free space = $space KB"
330
331         # FIXME:
332         # t-f _base needs to be modifyed to set properly tdir
333         # for new "test_foo" functions names
334         # local testdir=$DIR/$tdir
335         local testdir=$dir/d0.compilebench.$$
336         mkdir -p $testdir
337         setstripe_getstripe $testdir $cbench_STRIPEPARAMS
338
339     local savePWD=$PWD
340     cd $cbench_DIR
341     local cmd="./compilebench -D $testdir -i $cbench_IDIRS \
342         -r $cbench_RUNS --makej"
343
344     log "$cmd"
345
346     local rc=0
347     eval $cmd
348     rc=$?
349
350     cd $savePWD
351     [ $rc = 0 ] || error "compilebench failed: $rc"
352     rm -rf $testdir
353 }
354
355 run_metabench() {
356         local dir=${1:-$DIR}
357         local mntpt=${2:-$MOUNT}
358         METABENCH=${METABENCH:-$(which metabench 2> /dev/null || true)}
359         mbench_NFILES=${mbench_NFILES:-30400}
360         # threads per client
361         mbench_THREADS=${mbench_THREADS:-4}
362         mbench_OPTIONS=${mbench_OPTIONS:-}
363         mbench_CLEANUP=${mbench_CLEANUP:-true}
364
365         [ x$METABENCH = x ] && skip_env "metabench not found"
366
367         print_opts METABENCH clients mbench_NFILES mbench_THREADS
368
369         local testdir=$dir/d0.metabench
370         mkdir -p $testdir
371         setstripe_getstripe $testdir $mbench_STRIPEPARAMS
372
373         # mpi_run uses mpiuser
374         chmod 0777 $testdir
375
376         # -C             Run the file creation tests. Creates zero byte files.
377         # -S             Run the file stat tests.
378         # -c nfile       Number of files to be used in each test.
379         # -k             Cleanup files when finished.
380         local cmd="$METABENCH -w $testdir -c $mbench_NFILES -C -S $mbench_OPTIONS"
381         echo "+ $cmd"
382
383         # find out if we need to use srun by checking $SRUN_PARTITION
384         if [ "$SRUN_PARTITION" ]; then
385                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
386                         -n $((num_clients * mbench_THREADS)) \
387                         -p $SRUN_PARTITION -- $cmd
388         else
389                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
390                         -np $((num_clients * $mbench_THREADS)) $cmd
391         fi
392
393         local rc=$?
394         if [ $rc != 0 ] ; then
395                 error "metabench failed! $rc"
396         fi
397
398         if $mbench_CLEANUP; then
399                 rm -rf $testdir
400         else
401                 mv $dir/d0.metabench $mntpt/_xxx.$(date +%s).d0.metabench
402         fi
403 }
404
405 run_simul() {
406         SIMUL=${SIMUL:=$(which simul 2> /dev/null || true)}
407         [ x$SIMUL = x ] && skip_env "simul not found"
408         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
409
410         # threads per client
411         simul_THREADS=${simul_THREADS:-2}
412         simul_REP=${simul_REP:-20}
413
414         # FIXME
415         # Need space estimation here.
416
417         print_opts SIMUL clients simul_REP simul_THREADS
418
419         local testdir=$DIR/d0.simul
420         mkdir -p $testdir
421         setstripe_getstripe $testdir $simul_STRIPEPARAMS
422
423         # mpi_run uses mpiuser
424         chmod 0777 $testdir
425
426         # -n # : repeat each test # times
427         # -N # : repeat the entire set of tests # times
428
429         local cmd="$SIMUL -d $testdir -n $simul_REP -N $simul_REP"
430
431         echo "+ $cmd"
432         # find out if we need to use srun by checking $SRUN_PARTITION
433         if [ "$SRUN_PARTITION" ]; then
434                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
435                         -n $((num_clients * simul_THREADS)) -p $SRUN_PARTITION \
436                         -- $cmd
437         else
438                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
439                         -np $((num_clients * simul_THREADS)) $cmd
440         fi
441
442     local rc=$?
443     if [ $rc != 0 ] ; then
444         error "simul failed! $rc"
445     fi
446     rm -rf $testdir
447 }
448
449 run_mdtest() {
450         MDTEST=${MDTEST:=$(which mdtest 2> /dev/null || true)}
451         [ x$MDTEST = x ] && skip_env "mdtest not found"
452         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
453
454         # threads per client
455         mdtest_THREADS=${mdtest_THREADS:-2}
456         mdtest_nFiles=${mdtest_nFiles:-"100000"}
457         # We devide the files by number of core
458         mdtest_nFiles=$((mdtest_nFiles/mdtest_THREADS/num_clients))
459         mdtest_iteration=${mdtest_iteration:-1}
460         local mdtest_custom_params=${mdtest_custom_params:-""}
461         local type=${1:-"ssf"}
462
463         # FIXME
464         # Need space estimation here.
465
466         print_opts MDTEST mdtest_iteration mdtest_THREADS mdtest_nFiles
467
468         local testdir=$DIR/d0.mdtest
469         mkdir -p $testdir
470         setstripe_getstripe $testdir $mdtest_STRIPEPARAMS
471
472         # mpi_run uses mpiuser
473         chmod 0777 $testdir
474
475         # -i # : repeat each test # times
476         # -d   : test dir
477         # -n # : number of file/dir to create/stat/remove
478         # -u   : each process create/stat/remove individually
479
480         local cmd="$MDTEST -d $testdir -i $mdtest_iteration \
481                 -n $mdtest_nFiles $mdtest_custom_params"
482
483         [ $type = "fpp" ] && cmd="$cmd -u"
484
485         echo "+ $cmd"
486         # find out if we need to use srun by checking $SRUN_PARTITION
487         if [ "$SRUN_PARTITION" ]; then
488                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
489                         -n $((num_clients * mdtest_THREADS)) \
490                         -p $SRUN_PARTITION -- $cmd
491         else
492                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
493                         -np $((num_clients * mdtest_THREADS)) $cmd
494         fi
495
496     local rc=$?
497     if [ $rc != 0 ] ; then
498         error "mdtest failed! $rc"
499     fi
500     rm -rf $testdir
501 }
502
503 run_connectathon() {
504         local dir=${1:-$DIR}
505         cnt_DIR=${cnt_DIR:-""}
506         cnt_NRUN=${cnt_NRUN:-10}
507
508         print_opts cnt_DIR cnt_NRUN
509
510         [ x$cnt_DIR = x ] && skip_env "connectathon dir not found"
511         [ -e $cnt_DIR/runtests ] || skip_env "No connectathon runtests found"
512
513         # Space estimation:
514         # "special" tests create a 30 MB file + misc. small files
515         # required space ~40 MB
516         local space=$(df -P $dir | tail -n 1 | awk '{ print $4 }')
517         if [[ $space -le $((1024 * 40)) ]]; then
518                 skip_env "Need free space at least 40MB, have $space KB"
519         fi
520         echo "free space = $space KB"
521
522         local testdir=$dir/d0.connectathon
523         mkdir -p $testdir
524         setstripe_getstripe $testdir $cnt_STRIPEPARAMS
525
526         local savePWD=$PWD
527         cd $cnt_DIR
528
529         #
530         # To run connectathon:
531         # runtests [-a|-b|-g|-s|-l] [-f|-n|-t] [-N numpasses] [test-directory]
532         #
533         # One of the following test types
534         #    -b  basic
535         #    -g  general
536         #    -s  special
537         #    -l  lock
538         #    -a  all of the above
539         #
540         # -f  a quick functional test
541         # -n  suppress directory operations (mkdir and rmdir)
542         # -t  run with time statistics (default for basic tests)
543         #
544         # -N numpasses - specifies the number of times to run
545         #                the tests. Optional.
546
547         tests="-b -g -s"
548         # Include lock tests unless we're running on nfsv4
549         local fstype=$(df -TP $testdir | awk 'NR==2  {print $2}')
550         echo "$testdir: $fstype"
551         if [[ $fstype != "nfs4" ]]; then
552                 tests="$tests -l"
553         fi
554         echo "tests: $tests"
555         for test in $tests; do
556                 local cmd="sh ./runtests -N $cnt_NRUN $test -f $testdir"
557                 local rc=0
558
559                 log "$cmd"
560                 eval $cmd
561                 rc=$?
562                 [ $rc = 0 ] || error "connectathon failed: $rc"
563         done
564
565         cd $savePWD
566         rm -rf $testdir
567 }
568
569 run_ior() {
570         local type=${1:="ssf"}
571         local dir=${2:-$DIR}
572         local testdir=$dir/d0.ior.$type
573         local nfs_srvmntpt=$3
574
575         if [ "$NFSCLIENT" ]; then
576                 [[ -n $nfs_srvmntpt ]] ||
577                         { error "NFSCLIENT mode, but nfs exported dir"\
578                                 "is not set!" && return 1; }
579         fi
580
581         IOR=${IOR:-$(which IOR 2> /dev/null || true)}
582         [ x$IOR = x ] && skip_env "IOR not found"
583
584         # threads per client
585         ior_THREADS=${ior_THREADS:-2}
586         ior_iteration=${ior_iteration:-1}
587         ior_blockSize=${ior_blockSize:-6}
588         ior_blockUnit=${ior_blockUnit:-M}   # K, M, G
589         ior_xferSize=${ior_xferSize:-1M}
590         ior_type=${ior_type:-POSIX}
591         ior_DURATION=${ior_DURATION:-30}        # minutes
592         local multiplier=1
593         case ${ior_blockUnit} in
594                 [G])
595                         multiplier=$((1024 * 1024 * 1024))
596                         ;;
597                 [M])
598                         multiplier=$((1024 * 1024))
599                         ;;
600                 [K])
601                         multiplier=1024
602                         ;;
603                 *)      error "Incorrect block unit should be one of [KMG]"
604                         ;;
605         esac
606
607         # calculate the space in bytes
608         local space=$(df -B 1 -P $dir | tail -n 1 | awk '{ print $4 }')
609         local total_threads=$((num_clients * ior_THREADS))
610         echo "+ $ior_blockSize * $multiplier * $total_threads "
611         if [ $((space / 2)) -le \
612              $((ior_blockSize * multiplier * total_threads)) ]; then
613                 ior_blockSize=$((space / 2 / multiplier / total_threads))
614                 [ $ior_blockSize -eq 0 ] &&
615                 skip_env "Need free space more than $((2 * total_threads)) \
616                          ${ior_blockUnit}: have $((space / multiplier))"
617
618                 echo "(reduced blockSize to $ior_blockSize \
619                      ${ior_blockUnit} bytes)"
620         fi
621
622         print_opts IOR ior_THREADS ior_DURATION MACHINEFILE
623
624         mkdir -p $testdir
625
626         # mpi_run uses mpiuser
627         chmod 0777 $testdir
628         [[ "$ior_stripe_params" && -z "$ior_STRIPEPARAMS" ]] &&
629                 ior_STRIPEPARAMS="$ior_stripe_params" &&
630                 echo "got deprecated ior_stripe_params,"\
631                         "use ior_STRIPEPARAMS instead"
632         setstripe_getstripe $testdir $ior_STRIPEPARAMS
633
634         #
635         # -b N  blockSize --
636         #       contiguous bytes to write per task (e.g.: 8, 4K, 2M, 1G)"
637         # -o S  testFileName
638         # -t N  transferSize -- size of transfer in bytes (e.g.: 8, 4K, 2M, 1G)"
639         # -w    writeFile -- write file"
640         # -r    readFile -- read existing file"
641         # -W    checkWrite -- check read after write"
642         # -C    reorderTasks -- changes task ordering to n+1 ordering for readback
643         # -T    maxTimeDuration -- max time in minutes to run tests"
644         # -k    keepFile -- keep testFile(s) on program exit
645
646         local cmd
647         if [ -n "$ior_custom_params" ]; then
648                 cmd="$IOR -o $testdir/iorData $ior_custom_params"
649         else
650                 cmd="$IOR -a $ior_type -b ${ior_blockSize}${ior_blockUnit} \
651                 -o $testdir/iorData -t $ior_xferSize -v -C -w -r -W \
652                 -i $ior_iteration -T $ior_DURATION -k"
653         fi
654
655         [ $type = "fpp" ] && cmd="$cmd -F"
656
657         echo "+ $cmd"
658         # find out if we need to use srun by checking $SRUN_PARTITION
659         if [ "$SRUN_PARTITION" ]; then
660                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
661                         -n $((num_clients * ior_THREADS)) -p $SRUN_PARTITION \
662                         -- $cmd
663         else
664                 mpi_ior_custom_threads=${mpi_ior_custom_threads:-"$((num_clients * ior_THREADS))"}
665                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
666                         -np $mpi_ior_custom_threads $cmd
667         fi
668
669     local rc=$?
670     if [ $rc != 0 ] ; then
671         error "ior failed! $rc"
672     fi
673     rm -rf $testdir
674 }
675
676 run_mib() {
677         MIB=${MIB:=$(which mib 2> /dev/null || true)}
678         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
679         [ x$MIB = x ] && skip_env "MIB not found"
680
681         # threads per client
682         mib_THREADS=${mib_THREADS:-2}
683         mib_xferSize=${mib_xferSize:-1m}
684         mib_xferLimit=${mib_xferLimit:-5000}
685         mib_timeLimit=${mib_timeLimit:-300}
686         mib_STRIPEPARAMS=${mib_STRIPEPARAMS:-"-c -1"}
687
688         print_opts MIB mib_THREADS mib_xferSize mib_xferLimit mib_timeLimit \
689                 MACHINEFILE
690
691         local testdir=$DIR/d0.mib
692         mkdir -p $testdir
693         setstripe_getstripe $testdir $mib_STRIPEPARAMS
694
695         # mpi_run uses mpiuser
696         chmod 0777 $testdir
697
698         #
699         # -I    Show intermediate values in output
700         # -H    Show headers in output
701         # -L    Do not issue new system calls after this many seconds
702         # -s    Use system calls of this size
703         # -t    test dir
704         # -l    Issue no more than this many system calls
705         local cmd="$MIB -t $testdir -s $mib_xferSize -l $mib_xferLimit \
706                 -L $mib_timeLimit -HI -p mib.$(date +%Y%m%d%H%M%S)"
707
708         echo "+ $cmd"
709         # find out if we need to use srun by checking $SRUN_PARTITION
710         if [ "$SRUN_PARTITION" ]; then
711                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
712                         -n $((num_clients * mib_THREADS)) -p $SRUN_PARTITION \
713                         -- $cmd
714         else
715                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
716                         -np $((num_clients * mib_THREADS)) $cmd
717         fi
718
719     local rc=$?
720     if [ $rc != 0 ] ; then
721         error "mib failed! $rc"
722     fi
723     rm -rf $testdir
724 }
725
726 run_cascading_rw() {
727         CASC_RW=${CASC_RW:-$(which cascading_rw 2> /dev/null || true)}
728         [ x$CASC_RW = x ] && skip_env "cascading_rw not found"
729         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
730
731         # threads per client
732         casc_THREADS=${casc_THREADS:-2}
733         casc_REP=${casc_REP:-300}
734
735         # FIXME
736         # Need space estimation here.
737
738         print_opts CASC_RW clients casc_THREADS casc_REP MACHINEFILE
739
740         local testdir=$DIR/d0.cascading_rw
741         mkdir -p $testdir
742         setstripe_getstripe $testdir $casc_STRIPEPARAMS
743
744         # mpi_run uses mpiuser
745         chmod 0777 $testdir
746
747         # -g: debug mode
748         # -n: repeat test # times
749
750         local cmd="$CASC_RW -g -d $testdir -n $casc_REP"
751
752         echo "+ $cmd"
753         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
754                 -np $((num_clients * $casc_THREADS)) $cmd
755
756     local rc=$?
757     if [ $rc != 0 ] ; then
758         error "cascading_rw failed! $rc"
759     fi
760     rm -rf $testdir
761 }
762
763 run_write_append_truncate() {
764         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
765         # location is lustre/tests dir
766         if ! which write_append_truncate > /dev/null 2>&1 ; then
767                 skip_env "write_append_truncate not found"
768         fi
769
770         # threads per client
771         write_THREADS=${write_THREADS:-8}
772         write_REP=${write_REP:-10000}
773
774         # FIXME
775         # Need space estimation here.
776
777         local testdir=$DIR/d0.write_append_truncate
778         local file=$testdir/f0.wat
779
780         print_opts clients write_REP write_THREADS MACHINEFILE
781
782         mkdir -p $testdir
783         # mpi_run uses mpiuser
784         setstripe_getstripe $testdir $write_STRIPEPARAMS
785
786         chmod 0777 $testdir
787
788         local cmd="write_append_truncate -n $write_REP $file"
789
790         echo "+ $cmd"
791         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
792                 -np $((num_clients * $write_THREADS)) $cmd
793
794     local rc=$?
795     if [ $rc != 0 ] ; then
796         error "write_append_truncate failed! $rc"
797         return $rc
798     fi
799     rm -rf $testdir
800 }
801
802 run_write_disjoint() {
803         WRITE_DISJOINT=${WRITE_DISJOINT:-$(which write_disjoint 2> /dev/null ||
804                                            true)}
805         [ x$WRITE_DISJOINT = x ] && skip_env "write_disjoint not found"
806         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
807
808         # threads per client
809         wdisjoint_THREADS=${wdisjoint_THREADS:-4}
810         wdisjoint_REP=${wdisjoint_REP:-10000}
811         chunk_size_limit=$1
812
813         # FIXME
814         # Need space estimation here.
815
816         print_opts WRITE_DISJOINT clients wdisjoint_THREADS wdisjoint_REP \
817                 MACHINEFILE
818         local testdir=$DIR/d0.write_disjoint
819         mkdir -p $testdir
820         setstripe_getstripe $testdir $wdisjoint_STRIPEPARAMS
821
822         # mpi_run uses mpiuser
823         chmod 0777 $testdir
824
825         local cmd="$WRITE_DISJOINT -f $testdir/file -n $wdisjoint_REP -m \
826                         $chunk_size_limit"
827
828         echo "+ $cmd"
829         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
830                 -np $((num_clients * $wdisjoint_THREADS)) $cmd
831
832     local rc=$?
833     if [ $rc != 0 ] ; then
834         error "write_disjoint failed! $rc"
835     fi
836     rm -rf $testdir
837 }
838
839 run_parallel_grouplock() {
840         PARALLEL_GROUPLOCK=${PARALLEL_GROUPLOCK:-$(which parallel_grouplock \
841             2> /dev/null || true)}
842
843         [ x$PARALLEL_GROUPLOCK = x ] && skip "PARALLEL_GROUPLOCK not found"
844         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
845
846         parallel_grouplock_MINTASKS=${parallel_grouplock_MINTASKS:-5}
847
848         print_opts clients parallel_grouplock_MINTASKS MACHINEFILE
849
850         local testdir=$DIR/d0.parallel_grouplock
851         mkdir -p $testdir
852         setstripe_getstripe $testdir $parallel_grouplock_STRIPEPARAMS
853
854         # mpi_run uses mpiuser
855         chmod 0777 $testdir
856
857         local cmd
858         local status=0
859         local subtest
860         for i in $(seq 12); do
861                 subtest="-t $i"
862                 local cmd="$PARALLEL_GROUPLOCK -g -v -d $testdir $subtest"
863                 echo "+ $cmd"
864
865                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
866                         -np $parallel_grouplock_MINTASKS $cmd
867                 local rc=$?
868                 if [ $rc != 0 ] ; then
869                         error_noexit "parallel_grouplock subtests $subtest " \
870                                      "failed! $rc"
871                 else
872                         echo "parallel_grouplock subtests $subtest PASS"
873                 fi
874                 let status=$((status + rc))
875                 # clear debug to collect one log per one test
876                 do_nodes $(comma_list $(nodes_list)) lctl clear
877         done
878         [ $status -eq 0 ] || error "parallel_grouplock status: $status"
879         rm -rf $testdir
880 }
881
882 cleanup_statahead () {
883     trap 0
884
885     local clients=$1
886     local mntpt_root=$2
887     local num_mntpts=$3
888
889     for i in $(seq 0 $num_mntpts);do
890         zconf_umount_clients $clients ${mntpt_root}$i ||
891             error_exit "Failed to umount lustre on ${mntpt_root}$i"
892     done
893 }
894
895 run_statahead () {
896         if [[ -n $NFSCLIENT ]]; then
897                 skip "Statahead testing is not supported on NFS clients."
898         fi
899         [ x$MDSRATE = x ] && skip_env "mdsrate not found"
900
901         statahead_NUMMNTPTS=${statahead_NUMMNTPTS:-5}
902         statahead_NUMFILES=${statahead_NUMFILES:-500000}
903
904         print_opts MDSRATE clients statahead_NUMMNTPTS statahead_NUMFILES
905
906         # create large dir
907
908         # do not use default "d[0-9]*" dir name
909         # to avoid of rm $statahead_NUMFILES (500k) files in t-f cleanup
910         local dir=dstatahead
911         local testdir=$DIR/$dir
912
913         # cleanup only if dir exists
914         # cleanup only $statahead_NUMFILES number of files
915         # ignore the other files created by someone else
916         [ -d $testdir ] &&
917         mdsrate_cleanup $((num_clients * 32)) $MACHINEFILE \
918                 $statahead_NUMFILES $testdir 'f%%d' --ignore
919
920         mkdir -p $testdir
921         setstripe_getstripe $testdir $statahead_STRIPEPARAMS
922
923     # mpi_run uses mpiuser
924     chmod 0777 $testdir
925
926     local num_files=$statahead_NUMFILES
927
928     local IFree=$(inodes_available)
929     if [ $IFree -lt $num_files ]; then
930       num_files=$IFree
931     fi
932
933     cancel_lru_locks mdc
934
935     local cmd1="${MDSRATE} ${MDSRATE_DEBUG} --mknod --dir $testdir"
936     local cmd2="--nfiles $num_files --filefmt 'f%%d'"
937     local cmd="$cmd1 $cmd2"
938     echo "+ $cmd"
939
940         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
941                 -np $((num_clients * 32)) $cmd
942
943     local rc=$?
944     if [ $rc != 0 ] ; then
945         error "mdsrate failed to create $rc"
946         return $rc
947     fi
948
949     local num_mntpts=$statahead_NUMMNTPTS
950     local mntpt_root=$TMP/mntpt/lustre
951     local mntopts=$MNTOPTSTATAHEAD
952
953     echo "Mounting $num_mntpts lustre clients starts on $clients"
954     trap "cleanup_statahead $clients $mntpt_root $num_mntpts" EXIT ERR
955     for i in $(seq 0 $num_mntpts); do
956         zconf_mount_clients $clients ${mntpt_root}$i "$mntopts" ||
957             error_exit "Failed to mount lustre on ${mntpt_root}$i on $clients"
958     done
959
960     do_rpc_nodes $clients cancel_lru_locks mdc
961
962     do_rpc_nodes $clients do_ls $mntpt_root $num_mntpts $dir
963
964     mdsrate_cleanup $((num_clients * 32)) $MACHINEFILE \
965         $num_files $testdir 'f%%d' --ignore
966
967     # use rm instead of rmdir because of
968     # testdir could contain the files created by someone else,
969     # or by previous run where is num_files prev > num_files current
970     rm -rf $testdir
971     cleanup_statahead $clients $mntpt_root $num_mntpts
972 }
973
974 cleanup_rr_alloc () {
975         trap 0
976         local clients="$1"
977         local mntpt_root="$2"
978         local rr_alloc_MNTPTS="$3"
979         local mntpt_dir=$(dirname ${mntpt_root})
980
981         for i in $(seq 0 $((rr_alloc_MNTPTS - 1))); do
982                 zconf_umount_clients $clients ${mntpt_root}$i ||
983                 error_exit "Failed to umount lustre on ${mntpt_root}$i"
984         done
985         do_nodes $clients "rm -rf $mntpt_dir"
986 }
987
988 run_rr_alloc() {
989         remote_mds_nodsh && skip "remote MDS with nodsh"
990         echo "===Test gives more reproduction percentage if number of "\
991                 "client and ost are more. Test with 44 or more clients "\
992                 "and 73 or more OSTs gives 100% reproduction rate=="
993
994         RR_ALLOC=${RR_ALLOC:-$(which rr_alloc 2> /dev/null || true)}
995         [ x$RR_ALLOC = x ] && skip_env "rr_alloc not found"
996         declare -a diff_max_min_arr
997         # foeo = file on each ost. calc = calculated.
998         local ost_idx
999         local foeo_calc
1000         local qos_prec_objs="${TMP}/qos_and_precreated_objects"
1001         local rr_alloc_NFILES=${rr_alloc_NFILES:-555}
1002         local rr_alloc_MNTPTS=${rr_alloc_MNTPTS:-11}
1003         local total_MNTPTS=$((rr_alloc_MNTPTS * num_clients))
1004         local mntpt_root="${TMP}/rr_alloc_mntpt/lustre"
1005         if [ $MDSCOUNT -lt 2 ]; then
1006                 [ -e $DIR/$tdir ] || mkdir -p $DIR/$tdir
1007         else
1008                 [ -e $DIR/$tdir ] || $LFS mkdir -i 0 $DIR/$tdir
1009         fi
1010         setstripe_getstripe $DIR/$tdir $rr_alloc_STRIPEPARAMS
1011
1012         chmod 0777 $DIR/$tdir
1013
1014         trap "cleanup_rr_alloc $clients $mntpt_root $rr_alloc_MNTPTS" EXIT ERR
1015         for i in $(seq 0 $((rr_alloc_MNTPTS - 1))); do
1016                 zconf_mount_clients $clients ${mntpt_root}$i $MOUNT_OPTS ||
1017                 error_exit "Failed to mount lustre on ${mntpt_root}$i $clients"
1018         done
1019
1020         local cmd="$RR_ALLOC $mntpt_root/$tdir/ash $rr_alloc_NFILES \
1021                 $num_clients"
1022
1023         # Save mdt values, set threshold to 100% i.e always Round Robin,
1024         # restore the saved values again after creating files...
1025         save_lustre_params mds1 \
1026                 "lov.$FSNAME-MDT0000*.qos_threshold_rr" > $qos_prec_objs
1027         save_lustre_params mds1 \
1028                 "osp.$FSNAME-OST*-osc-MDT0000.create_count" >> $qos_prec_objs
1029
1030         local old_create_count=$(grep -e "create_count" $qos_prec_objs |
1031                 cut -d'=' -f 2 | sort -nr | head -n1)
1032
1033         # Make sure that every osp has enough precreated objects for the file
1034         # creation app
1035
1036         # create_count is always set to the power of 2 only, so if the files
1037         # per OST are not multiple of that then it will be set to nearest
1038         # lower power of 2. So set 'create_count' to the upper power of 2.
1039
1040         foeo_calc=$((rr_alloc_NFILES * total_MNTPTS / OSTCOUNT))
1041         local create_count=$((2 * foeo_calc))
1042         do_facet mds1 "$LCTL set_param -n \
1043                 lov.$FSNAME-MDT0000*.qos_threshold_rr 100 \
1044                 osp.$FSNAME-OST*-osc-MDT0000.create_count $create_count" ||
1045                 error "failed while setting qos_threshold_rr & creat_count"
1046
1047         # Create few temporary files in order to increase the precreated objects
1048         # to a desired value, before starting 'rr_alloc' app. Due to default
1049         # value 32 of precreation count (OST_MIN_PRECREATE=32), precreated
1050         # objects available are 32 initially, these gets exhausted very soon,
1051         # which causes skip of some osps when very large number of files
1052         # is created per OSTs.
1053         createmany -o $DIR/$tdir/foo- $(((old_create_count + 1) * OSTCOUNT)) \
1054                 > /dev/null
1055         rm -f /$DIR/$tdir/foo*
1056
1057         # Check for enough precreated objects... We should not
1058         # fail here because code(osp_precreate.c) also takes care of it.
1059         # So we have good chances of passing test even if this check fails.
1060         local mdt_idx=0
1061         for ost_idx in $(seq 0 $((OSTCOUNT - 1))); do
1062                 [[ $(precreated_ost_obj_count $mdt_idx $ost_idx) -ge \
1063                         $foeo_calc ]] || echo "Warning: test may fail because" \
1064                         "of lack of precreated objects on OST${ost_idx}"
1065         done
1066
1067         if [[ $total_MNTPTS -ne 0 ]]; then
1068                 # Now start the actual file creation app.
1069                 mpi_run "-np $total_MNTPTS" $cmd || return
1070         else
1071                 error "No mount point"
1072         fi
1073
1074         restore_lustre_params < $qos_prec_objs
1075         rm -f $qos_prec_objs
1076
1077         diff_max_min_arr=($($LFS getstripe -r $DIR/$tdir/ |
1078                 grep "lmm_stripe_offset:" | awk '{print $2}' | sort -n |
1079                 uniq -c | awk 'NR==1 {min=max=$1} \
1080                 { $1<min ? min=$1 : min; $1>max ? max=$1 : max} \
1081                 END {print max-min, max, min}'))
1082
1083         rm -rf $DIR/$tdir
1084
1085         # In-case of fairly large number of file creation using RR (round-robin)
1086         # there can be two cases in which deviation will occur than the regular
1087         # RR algo behaviour-
1088         # 1- When rr_alloc does not start right with 'lqr_start_count' reseeded,
1089         # 2- When rr_alloc does not finish with 'lqr_start_count == 0'.
1090         # So the difference of files b/w any 2 OST should not be more than 2.
1091         [[ ${diff_max_min_arr[0]} -le 2 ]] ||
1092                 error "Uneven distribution detected: difference between" \
1093                 "maximum files per OST (${diff_max_min_arr[1]}) and" \
1094                 "minimum files per OST (${diff_max_min_arr[2]}) must not be" \
1095                 "greater than 2"
1096 }
1097
1098 run_fs_test() {
1099         # fs_test.x is the default name for exe
1100         FS_TEST=${FS_TEST:=$(which fs_test.x 2> /dev/null || true)}
1101
1102         local clients=${CLIENTS:-$(hostname)}
1103         local testdir=$DIR/d0.fs_test
1104         local file=${testdir}/fs_test
1105         fs_test_threads=${fs_test_threads:-2}
1106         fs_test_type=${fs_test_type:-1}
1107         fs_test_nobj=${fs_test_nobj:-10}
1108         fs_test_check=${fs_test_check:-3}
1109         fs_test_strided=${fs_test_strided:-1}
1110         fs_test_touch=${fs_test_touch:-3}
1111         fs_test_supersize=${fs_test_supersize:-1}
1112         fs_test_op=${fs_test_op:-write}
1113         fs_test_barriers=${fs_test_barriers:-bopen,bwrite,bclose}
1114         fs_test_io=${fs_test_io:-mpi}
1115         fs_test_objsize=${fs_test_objsize:-100}
1116         fs_test_objunit=${fs_test_objunit:-1048576} # 1 mb
1117         fs_test_ndirs=${fs_test_ndirs:-80000}
1118
1119         [ x$FS_TEST = x ] && skip "FS_TEST not found"
1120
1121         # Space estimation  in bytes
1122         local space=$(df -B 1 -P $dir | tail -n 1 | awk '{ print $4 }')
1123         local total_threads=$((num_clients * fs_test_threads))
1124         echo "+ $fs_test_objsize * $fs_test_objunit * $total_threads "
1125         if [ $((space / 2)) -le \
1126                 $((fs_test_objsize * fs_test_objunit * total_threads)) ]; then
1127                         fs_test_objsize=$((space / 2 / fs_test_objunit / \
1128                                 total_threads))
1129                         [ $fs_test_objsize -eq 0 ] &&
1130                         skip_env "Need free space more than \
1131                                 $((2 * total_threads * fs_test_objunit)) \
1132                                 : have $((space / fs_test_objunit))"
1133
1134                         echo "(reduced objsize to \
1135                                 $((fs_test_objsize * fs_test_objunit)) bytes)"
1136         fi
1137
1138         print_opts FS_TEST clients fs_test_threads fs_test_objsize MACHINEFILE
1139
1140         mkdir -p $testdir
1141         setstripe_getstripe $testdir $fs_test_STRIPEPARAMS
1142
1143         # mpi_run uses mpiuser
1144         chmod 0777 $testdir
1145
1146         # --nodb          Turn off the database code at runtime
1147         # -g --target     The path to the data file
1148         # -t --type       Whether to do N-N (1) or N-1 (2)
1149         # -n --nobj       The number of objects written/read by each proc
1150         # -z --size       The size of each object
1151         # -d ---num_nn_dirs Number of subdirectories for files
1152         # -C --check      Check every byte using argument 3.
1153         # --collective    Whether to use collective I/O (for N-1, mpi-io only)
1154         # -s --strided    Whether to use a strided pattern (for N-1 only)
1155         # -T --touch      Touch every byte using argument 3
1156         # -o --op         Whether to read only (read) or write only (write)
1157         # -b --barriers   When to barrier.
1158         # -i --io         Use POSIX, MPI, or PLFS IO routines (mpi|posix|plfs)
1159         # -S --supersize  Specify how many objects per superblock
1160
1161         local cmd="$FS_TEST -nodb -g $file -t $fs_test_type -n $fs_test_nobj \
1162                 -z $((fs_test_objsize * fs_test_objunit)) -d $fs_test_ndirs \
1163                 -C $fs_test_check -collective -s $fs_test_strided \
1164                 -T $fs_test_touch -o $fs_test_op -b $fs_test_barriers \
1165                 -i $fs_test_io -S $fs_test_supersize"
1166
1167         echo "+ $cmd"
1168         mpi_run "-np $((num_clients * fs_test_threads))" $cmd
1169
1170         local rc=$?
1171         if [ $rc != 0 ] ; then
1172                 error "fs_test failed! $rc"
1173         fi
1174
1175         rm -rf $testdir
1176 }
1177
1178 ior_mdtest_parallel() {
1179         local rc1=0
1180         local rc2=0
1181         local type=$1
1182
1183         run_ior $type &
1184         local pids=$!
1185
1186         run_mdtest $type || rc2=$?
1187         [[ $rc2 -ne 0 ]] && echo "mdtest failed with error $rc2"
1188
1189         wait $pids || rc1=$?
1190         [[ $rc1 -ne 0 ]] && echo "ior failed with error $rc1"
1191
1192         [[ $rc1 -ne 0 || $rc2 -ne 0 ]] && return 1
1193         return 0
1194 }
1195
1196 run_fio() {
1197         FIO=${FIO:=$(which fio 2> /dev/null || true)}
1198
1199         local clients=${CLIENTS:-$(hostname)}
1200         local fio_jobNum=${fio_jobNum:-4}
1201         local fio_jobFile=${fio_jobFile:-$TMP/fiojobfile.$(date +%s)}
1202         local fio_bs=${fio_bs:-1}
1203         local testdir=$DIR/d0.fio
1204         local file=${testdir}/fio
1205         local runtime=60
1206         local propagate=false
1207
1208         [ "$SLOW" = "no" ] || runtime=600
1209
1210         [ x$FIO = x ] && skip_env "FIO not found"
1211
1212         mkdir -p $testdir
1213         setstripe_getstripe $testdir $fio_STRIPEPARAMS
1214
1215         # use fio job file if exists,
1216         # create a simple one if missing
1217         if ! [ -f $fio_jobFile ]; then
1218                 cat >> $fio_jobFile <<EOF
1219 [global]
1220 rw=randwrite
1221 size=128m
1222 time_based=1
1223 runtime=$runtime
1224 filename=${file}_\$(hostname)
1225 EOF
1226                 # bs size increased by $i for each job
1227                 for ((i=1; i<=fio_jobNum; i++)); do
1228                         cat >> $fio_jobFile <<EOF
1229
1230 [job$i]
1231 bs=$(( fio_bs * i ))m
1232 EOF
1233                 done
1234                 # job file is created, should be propagated to all clients
1235                 propagate=true
1236         fi
1237
1238
1239         # propagate the job file if not all clients have it yet or
1240         # if the job file was created during the test run
1241         if ! do_nodesv $clients " [ -f $fio_jobFile ] " ||
1242            $propagate; then
1243                 local cfg=$(cat $fio_jobFile)
1244                 do_nodes $clients "echo \\\"$cfg\\\" > ${fio_jobFile}" ||
1245                         error "job file $fio_jobFile is not propagated"
1246                 do_nodesv $clients "cat ${fio_jobFile}"
1247         fi
1248
1249         cmd="$FIO $fio_jobFile"
1250         echo "+ $cmd"
1251
1252         log "clients: $clients $cmd"
1253
1254         local rc=0
1255         do_nodesv $clients "$cmd "
1256         rc=$?
1257
1258         [ $rc = 0 ] || error "fio failed: $rc"
1259         rm -rf $testdir
1260 }
1261
1262 run_xdd() {
1263         XDD=${XDD:=$(which xdd 2> /dev/null || true)}
1264
1265         local clients=${CLIENTS:-$(hostname)}
1266         local testdir=$DIR/d0.xdd
1267         xdd_queuedepth=${xdd_queuedepth:-4}
1268         xdd_blocksize=${xdd_blocksize:-512}
1269         xdd_reqsize=${xdd_reqsize:-128}
1270         xdd_mbytes=${xdd_mbytes:-100}
1271         xdd_passes=${xdd_passes:-40}
1272         xdd_rwratio=${xdd_rwratio:-0}
1273         xdd_ntargets=${xdd_ntargets:-6}
1274         local xdd_custom_params=${xdd_custom_params:-"-dio -stoponerror \
1275                 -maxpri -minall -noproclock -nomemlock"}
1276
1277         [ x$XDD = x ] && skip "XDD not found"
1278
1279         print_opts XDD clients xdd_queuedepth xdd_blocksize xdd_reqsize \
1280                 xdd_mbytes xdd_passes xdd_rwratio
1281
1282         mkdir -p $testdir
1283         setstripe_getstripe $testdir $xdd_STRIPEPARAMS
1284
1285         local files=""
1286         # Target files creates based on the given number of targets
1287         for (( i=0; i < $xdd_ntargets; i++ ))
1288         do
1289                 files+="${testdir}/xdd"$i" "
1290         done
1291
1292         # -targets      specifies the devices or files to perform operation
1293         # -reqsize      number of 'blocks' per operation
1294         # -mbytes       number of 1024*1024-byte blocks to transfer
1295         # -blocksize    size of a single 'block'
1296         # -passes       number of times to read mbytes
1297         # -queuedepth   number of commands to queue on the target
1298         # -rwratio      percentage of read to write operations
1299         # -verbose      will print out statistics on each pass
1300
1301         local cmd="$XDD -targets $xdd_ntargets $files -reqsize $xdd_reqsize \
1302                 -mbytes $xdd_mbytes -blocksize $xdd_blocksize \
1303                 -passes $xdd_passes -queuedepth $xdd_queuedepth \
1304                 -rwratio $xdd_rwratio -verbose $xdd_custom_params"
1305         echo "+ $cmd"
1306
1307         local rc=0
1308         do_nodesv $clients "$cmd "
1309         rc=$?
1310
1311         [ $rc = 0 ] || error "xdd failed: $rc"
1312
1313         rm -rf $testdir
1314 }