Whamcloud - gitweb
LU-13404 utils: fix lfs mirror duplicate file check
[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         local mdtest_Nmntp=${mdtest_Nmntp:-1}
464
465         if [ $type = "ssf" ] && [ $mdtest_Nmntp -ne 1 ]; then
466                 skip "shared directory mode is not compatible" \
467                         "with multiple directory paths"
468         fi
469
470         # FIXME
471         # Need space estimation here.
472
473         print_opts MDTEST mdtest_iteration mdtest_THREADS mdtest_nFiles
474
475         local testdir=$DIR/d0.mdtest
476         mkdir -p $testdir
477         setstripe_getstripe $testdir $mdtest_STRIPEPARAMS
478         chmod 0777 $testdir
479
480         for ((i=1; i<mdtest_Nmntp; i++)); do
481                 zconf_mount_clients $clients $MOUNT$i "$mntopts" ||
482                         error_exit "Failed $clients on $MOUNT$i"
483                 local dir=$DIR$i/d0.mdtest$i
484                 mkdir -p $dir
485                 setstripe_getstripe $dir $mdtest_SETSTRIPEPARAMS
486                 chmod 0777 $dir
487                 testdir="$testdir@$dir"
488         done
489         # mpi_run uses mpiuser
490
491         # -i # : repeat each test # times
492         # -d   : test dir
493         # -n # : number of file/dir to create/stat/remove
494         # -u   : each process create/stat/remove individually
495
496         local cmd="$MDTEST -d $testdir -i $mdtest_iteration \
497                 -n $mdtest_nFiles $mdtest_custom_params"
498
499         [ $type = "fpp" ] && cmd="$cmd -u"
500
501         echo "+ $cmd"
502         # find out if we need to use srun by checking $SRUN_PARTITION
503         if [ "$SRUN_PARTITION" ]; then
504                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
505                         -n $((num_clients * mdtest_THREADS)) \
506                         -p $SRUN_PARTITION -- $cmd
507         else
508                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
509                         -np $((num_clients * mdtest_THREADS)) $cmd
510         fi
511
512     local rc=$?
513     if [ $rc != 0 ] ; then
514         error "mdtest failed! $rc"
515     fi
516         rm -rf $testdir
517         for ((i=1; i<mdtest_Nmntp; i++)); do
518                 local dir=$DIR$i/d0.mdtest$i
519                 rm -rf $dir
520                 zconf_umount_clients $clients $MOUNT$i ||
521                         error_exit "Failed umount $MOUNT$i on $clients"
522         done
523 }
524
525 run_connectathon() {
526         local dir=${1:-$DIR}
527         cnt_DIR=${cnt_DIR:-""}
528         cnt_NRUN=${cnt_NRUN:-10}
529
530         print_opts cnt_DIR cnt_NRUN
531
532         [ x$cnt_DIR = x ] && skip_env "connectathon dir not found"
533         [ -e $cnt_DIR/runtests ] || skip_env "No connectathon runtests found"
534
535         # Space estimation:
536         # "special" tests create a 30 MB file + misc. small files
537         # required space ~40 MB
538         local space=$(df -P $dir | tail -n 1 | awk '{ print $4 }')
539         if [[ $space -le $((1024 * 40)) ]]; then
540                 skip_env "Need free space at least 40MB, have $space KB"
541         fi
542         echo "free space = $space KB"
543
544         local testdir=$dir/d0.connectathon
545         mkdir -p $testdir
546         setstripe_getstripe $testdir $cnt_STRIPEPARAMS
547
548         local savePWD=$PWD
549         cd $cnt_DIR
550
551         #
552         # To run connectathon:
553         # runtests [-a|-b|-g|-s|-l] [-f|-n|-t] [-N numpasses] [test-directory]
554         #
555         # One of the following test types
556         #    -b  basic
557         #    -g  general
558         #    -s  special
559         #    -l  lock
560         #    -a  all of the above
561         #
562         # -f  a quick functional test
563         # -n  suppress directory operations (mkdir and rmdir)
564         # -t  run with time statistics (default for basic tests)
565         #
566         # -N numpasses - specifies the number of times to run
567         #                the tests. Optional.
568
569         tests="-b -g -s"
570         # Include lock tests unless we're running on nfsv4
571         local fstype=$(df -TP $testdir | awk 'NR==2  {print $2}')
572         echo "$testdir: $fstype"
573         if [[ $fstype != "nfs4" ]]; then
574                 tests="$tests -l"
575         fi
576         echo "tests: $tests"
577         for test in $tests; do
578                 local cmd="sh ./runtests -N $cnt_NRUN $test -f $testdir"
579                 local rc=0
580
581                 log "$cmd"
582                 eval $cmd
583                 rc=$?
584                 [ $rc = 0 ] || error "connectathon failed: $rc"
585         done
586
587         cd $savePWD
588         rm -rf $testdir
589 }
590
591 run_ior() {
592         local type=${1:="ssf"}
593         local dir=${2:-$DIR}
594         local testdir=$dir/d0.ior.$type
595         local nfs_srvmntpt=$3
596
597         if [ "$NFSCLIENT" ]; then
598                 [[ -n $nfs_srvmntpt ]] ||
599                         { error "NFSCLIENT mode, but nfs exported dir"\
600                                 "is not set!" && return 1; }
601         fi
602
603         IOR=${IOR:-$(which IOR 2> /dev/null || true)}
604         [ x$IOR = x ] && skip_env "IOR not found"
605
606         # threads per client
607         ior_THREADS=${ior_THREADS:-2}
608         ior_iteration=${ior_iteration:-1}
609         ior_blockSize=${ior_blockSize:-6}
610         ior_blockUnit=${ior_blockUnit:-M}   # K, M, G
611         ior_xferSize=${ior_xferSize:-1M}
612         ior_type=${ior_type:-POSIX}
613         ior_DURATION=${ior_DURATION:-30}        # minutes
614         local multiplier=1
615         case ${ior_blockUnit} in
616                 [G])
617                         multiplier=$((1024 * 1024 * 1024))
618                         ;;
619                 [M])
620                         multiplier=$((1024 * 1024))
621                         ;;
622                 [K])
623                         multiplier=1024
624                         ;;
625                 *)      error "Incorrect block unit should be one of [KMG]"
626                         ;;
627         esac
628
629         # calculate the space in bytes
630         local space=$(df -B 1 -P $dir | tail -n 1 | awk '{ print $4 }')
631         local total_threads=$((num_clients * ior_THREADS))
632         echo "+ $ior_blockSize * $multiplier * $total_threads "
633         if [ $((space / 2)) -le \
634              $((ior_blockSize * multiplier * total_threads)) ]; then
635                 ior_blockSize=$((space / 2 / multiplier / total_threads))
636                 [ $ior_blockSize -eq 0 ] &&
637                 skip_env "Need free space more than $((2 * total_threads)) \
638                          ${ior_blockUnit}: have $((space / multiplier))"
639
640                 echo "(reduced blockSize to $ior_blockSize \
641                      ${ior_blockUnit} bytes)"
642         fi
643
644         print_opts IOR ior_THREADS ior_DURATION MACHINEFILE
645
646         mkdir -p $testdir
647
648         # mpi_run uses mpiuser
649         chmod 0777 $testdir
650         [[ "$ior_stripe_params" && -z "$ior_STRIPEPARAMS" ]] &&
651                 ior_STRIPEPARAMS="$ior_stripe_params" &&
652                 echo "got deprecated ior_stripe_params,"\
653                         "use ior_STRIPEPARAMS instead"
654         setstripe_getstripe $testdir $ior_STRIPEPARAMS
655
656         #
657         # -b N  blockSize --
658         #       contiguous bytes to write per task (e.g.: 8, 4K, 2M, 1G)"
659         # -o S  testFileName
660         # -t N  transferSize -- size of transfer in bytes (e.g.: 8, 4K, 2M, 1G)"
661         # -w    writeFile -- write file"
662         # -r    readFile -- read existing file"
663         # -W    checkWrite -- check read after write"
664         # -C    reorderTasks -- changes task ordering to n+1 ordering for readback
665         # -T    maxTimeDuration -- max time in minutes to run tests"
666         # -k    keepFile -- keep testFile(s) on program exit
667
668         local cmd
669         if [ -n "$ior_custom_params" ]; then
670                 cmd="$IOR -o $testdir/iorData $ior_custom_params"
671         else
672                 cmd="$IOR -a $ior_type -b ${ior_blockSize}${ior_blockUnit} \
673                 -o $testdir/iorData -t $ior_xferSize -v -C -w -r -W \
674                 -i $ior_iteration -T $ior_DURATION -k"
675         fi
676
677         [ $type = "fpp" ] && cmd="$cmd -F"
678
679         echo "+ $cmd"
680         # find out if we need to use srun by checking $SRUN_PARTITION
681         if [ "$SRUN_PARTITION" ]; then
682                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
683                         -n $((num_clients * ior_THREADS)) -p $SRUN_PARTITION \
684                         -- $cmd
685         else
686                 mpi_ior_custom_threads=${mpi_ior_custom_threads:-"$((num_clients * ior_THREADS))"}
687                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
688                         -np $mpi_ior_custom_threads $cmd
689         fi
690
691     local rc=$?
692     if [ $rc != 0 ] ; then
693         error "ior failed! $rc"
694     fi
695     rm -rf $testdir
696 }
697
698 run_mib() {
699         MIB=${MIB:=$(which mib 2> /dev/null || true)}
700         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
701         [ x$MIB = x ] && skip_env "MIB not found"
702
703         # threads per client
704         mib_THREADS=${mib_THREADS:-2}
705         mib_xferSize=${mib_xferSize:-1m}
706         mib_xferLimit=${mib_xferLimit:-5000}
707         mib_timeLimit=${mib_timeLimit:-300}
708         mib_STRIPEPARAMS=${mib_STRIPEPARAMS:-"-c -1"}
709
710         print_opts MIB mib_THREADS mib_xferSize mib_xferLimit mib_timeLimit \
711                 MACHINEFILE
712
713         local testdir=$DIR/d0.mib
714         mkdir -p $testdir
715         setstripe_getstripe $testdir $mib_STRIPEPARAMS
716
717         # mpi_run uses mpiuser
718         chmod 0777 $testdir
719
720         #
721         # -I    Show intermediate values in output
722         # -H    Show headers in output
723         # -L    Do not issue new system calls after this many seconds
724         # -s    Use system calls of this size
725         # -t    test dir
726         # -l    Issue no more than this many system calls
727         local cmd="$MIB -t $testdir -s $mib_xferSize -l $mib_xferLimit \
728                 -L $mib_timeLimit -HI -p mib.$(date +%Y%m%d%H%M%S)"
729
730         echo "+ $cmd"
731         # find out if we need to use srun by checking $SRUN_PARTITION
732         if [ "$SRUN_PARTITION" ]; then
733                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
734                         -n $((num_clients * mib_THREADS)) -p $SRUN_PARTITION \
735                         -- $cmd
736         else
737                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
738                         -np $((num_clients * mib_THREADS)) $cmd
739         fi
740
741     local rc=$?
742     if [ $rc != 0 ] ; then
743         error "mib failed! $rc"
744     fi
745     rm -rf $testdir
746 }
747
748 run_cascading_rw() {
749         CASC_RW=${CASC_RW:-$(which cascading_rw 2> /dev/null || true)}
750         [ x$CASC_RW = x ] && skip_env "cascading_rw not found"
751         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
752
753         # threads per client
754         casc_THREADS=${casc_THREADS:-2}
755         casc_REP=${casc_REP:-300}
756
757         # FIXME
758         # Need space estimation here.
759
760         print_opts CASC_RW clients casc_THREADS casc_REP MACHINEFILE
761
762         local testdir=$DIR/d0.cascading_rw
763         mkdir -p $testdir
764         setstripe_getstripe $testdir $casc_STRIPEPARAMS
765
766         # mpi_run uses mpiuser
767         chmod 0777 $testdir
768
769         # -g: debug mode
770         # -n: repeat test # times
771
772         local cmd="$CASC_RW -g -d $testdir -n $casc_REP"
773
774         echo "+ $cmd"
775         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
776                 -np $((num_clients * $casc_THREADS)) $cmd
777
778     local rc=$?
779     if [ $rc != 0 ] ; then
780         error "cascading_rw failed! $rc"
781     fi
782     rm -rf $testdir
783 }
784
785 run_write_append_truncate() {
786         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
787         # location is lustre/tests dir
788         if ! which write_append_truncate > /dev/null 2>&1 ; then
789                 skip_env "write_append_truncate not found"
790         fi
791
792         # threads per client
793         write_THREADS=${write_THREADS:-8}
794         write_REP=${write_REP:-10000}
795
796         # FIXME
797         # Need space estimation here.
798
799         local testdir=$DIR/d0.write_append_truncate
800         local file=$testdir/f0.wat
801
802         print_opts clients write_REP write_THREADS MACHINEFILE
803
804         mkdir -p $testdir
805         # mpi_run uses mpiuser
806         setstripe_getstripe $testdir $write_STRIPEPARAMS
807
808         chmod 0777 $testdir
809
810         local cmd="write_append_truncate -n $write_REP $file"
811
812         echo "+ $cmd"
813         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
814                 -np $((num_clients * $write_THREADS)) $cmd
815
816     local rc=$?
817     if [ $rc != 0 ] ; then
818         error "write_append_truncate failed! $rc"
819         return $rc
820     fi
821     rm -rf $testdir
822 }
823
824 run_write_disjoint() {
825         WRITE_DISJOINT=${WRITE_DISJOINT:-$(which write_disjoint 2> /dev/null ||
826                                            true)}
827         [ x$WRITE_DISJOINT = x ] && skip_env "write_disjoint not found"
828         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
829
830         # threads per client
831         wdisjoint_THREADS=${wdisjoint_THREADS:-4}
832         wdisjoint_REP=${wdisjoint_REP:-10000}
833         chunk_size_limit=$1
834
835         # FIXME
836         # Need space estimation here.
837
838         print_opts WRITE_DISJOINT clients wdisjoint_THREADS wdisjoint_REP \
839                 MACHINEFILE
840         local testdir=$DIR/d0.write_disjoint
841         mkdir -p $testdir
842         setstripe_getstripe $testdir $wdisjoint_STRIPEPARAMS
843
844         # mpi_run uses mpiuser
845         chmod 0777 $testdir
846
847         local cmd="$WRITE_DISJOINT -f $testdir/file -n $wdisjoint_REP -m \
848                         $chunk_size_limit"
849
850         echo "+ $cmd"
851         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
852                 -np $((num_clients * $wdisjoint_THREADS)) $cmd
853
854     local rc=$?
855     if [ $rc != 0 ] ; then
856         error "write_disjoint failed! $rc"
857     fi
858     rm -rf $testdir
859 }
860
861 run_parallel_grouplock() {
862         PARALLEL_GROUPLOCK=${PARALLEL_GROUPLOCK:-$(which parallel_grouplock \
863             2> /dev/null || true)}
864
865         [ x$PARALLEL_GROUPLOCK = x ] && skip "PARALLEL_GROUPLOCK not found"
866         [ "$NFSCLIENT" ] && skip "skipped for NFSCLIENT mode"
867
868         parallel_grouplock_MINTASKS=${parallel_grouplock_MINTASKS:-5}
869
870         print_opts clients parallel_grouplock_MINTASKS MACHINEFILE
871
872         local testdir=$DIR/d0.parallel_grouplock
873         mkdir -p $testdir
874         setstripe_getstripe $testdir $parallel_grouplock_STRIPEPARAMS
875
876         # mpi_run uses mpiuser
877         chmod 0777 $testdir
878
879         local cmd
880         local status=0
881         local subtest
882         for i in $(seq 12); do
883                 subtest="-t $i"
884                 local cmd="$PARALLEL_GROUPLOCK -g -v -d $testdir $subtest"
885                 echo "+ $cmd"
886
887                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
888                         -np $parallel_grouplock_MINTASKS $cmd
889                 local rc=$?
890                 if [ $rc != 0 ] ; then
891                         error_noexit "parallel_grouplock subtests $subtest " \
892                                      "failed! $rc"
893                 else
894                         echo "parallel_grouplock subtests $subtest PASS"
895                 fi
896                 let status=$((status + rc))
897                 # clear debug to collect one log per one test
898                 do_nodes $(comma_list $(nodes_list)) lctl clear
899         done
900         [ $status -eq 0 ] || error "parallel_grouplock status: $status"
901         rm -rf $testdir
902 }
903
904 cleanup_statahead () {
905     trap 0
906
907     local clients=$1
908     local mntpt_root=$2
909     local num_mntpts=$3
910
911     for i in $(seq 0 $num_mntpts);do
912         zconf_umount_clients $clients ${mntpt_root}$i ||
913             error_exit "Failed to umount lustre on ${mntpt_root}$i"
914     done
915 }
916
917 run_statahead () {
918         if [[ -n $NFSCLIENT ]]; then
919                 skip "Statahead testing is not supported on NFS clients."
920         fi
921         [ x$MDSRATE = x ] && skip_env "mdsrate not found"
922
923         statahead_NUMMNTPTS=${statahead_NUMMNTPTS:-5}
924         statahead_NUMFILES=${statahead_NUMFILES:-500000}
925
926         print_opts MDSRATE clients statahead_NUMMNTPTS statahead_NUMFILES
927
928         # create large dir
929
930         # do not use default "d[0-9]*" dir name
931         # to avoid of rm $statahead_NUMFILES (500k) files in t-f cleanup
932         local dir=dstatahead
933         local testdir=$DIR/$dir
934
935         # cleanup only if dir exists
936         # cleanup only $statahead_NUMFILES number of files
937         # ignore the other files created by someone else
938         [ -d $testdir ] &&
939         mdsrate_cleanup $((num_clients * 32)) $MACHINEFILE \
940                 $statahead_NUMFILES $testdir 'f%%d' --ignore
941
942         mkdir -p $testdir
943         setstripe_getstripe $testdir $statahead_STRIPEPARAMS
944
945     # mpi_run uses mpiuser
946     chmod 0777 $testdir
947
948     local num_files=$statahead_NUMFILES
949
950     local IFree=$(inodes_available)
951     if [ $IFree -lt $num_files ]; then
952       num_files=$IFree
953     fi
954
955     cancel_lru_locks mdc
956
957     local cmd1="${MDSRATE} ${MDSRATE_DEBUG} --mknod --dir $testdir"
958     local cmd2="--nfiles $num_files --filefmt 'f%%d'"
959     local cmd="$cmd1 $cmd2"
960     echo "+ $cmd"
961
962         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
963                 -np $((num_clients * 32)) $cmd
964
965     local rc=$?
966     if [ $rc != 0 ] ; then
967         error "mdsrate failed to create $rc"
968         return $rc
969     fi
970
971     local num_mntpts=$statahead_NUMMNTPTS
972     local mntpt_root=$TMP/mntpt/lustre
973     local mntopts=$MNTOPTSTATAHEAD
974
975     echo "Mounting $num_mntpts lustre clients starts on $clients"
976     trap "cleanup_statahead $clients $mntpt_root $num_mntpts" EXIT ERR
977     for i in $(seq 0 $num_mntpts); do
978         zconf_mount_clients $clients ${mntpt_root}$i "$mntopts" ||
979             error_exit "Failed to mount lustre on ${mntpt_root}$i on $clients"
980     done
981
982     do_rpc_nodes $clients cancel_lru_locks mdc
983
984     do_rpc_nodes $clients do_ls $mntpt_root $num_mntpts $dir
985
986     mdsrate_cleanup $((num_clients * 32)) $MACHINEFILE \
987         $num_files $testdir 'f%%d' --ignore
988
989     # use rm instead of rmdir because of
990     # testdir could contain the files created by someone else,
991     # or by previous run where is num_files prev > num_files current
992     rm -rf $testdir
993     cleanup_statahead $clients $mntpt_root $num_mntpts
994 }
995
996 cleanup_rr_alloc () {
997         trap 0
998         local clients="$1"
999         local mntpt_root="$2"
1000         local rr_alloc_MNTPTS="$3"
1001         local mntpt_dir=$(dirname ${mntpt_root})
1002
1003         for i in $(seq 0 $((rr_alloc_MNTPTS - 1))); do
1004                 zconf_umount_clients $clients ${mntpt_root}$i ||
1005                 error_exit "Failed to umount lustre on ${mntpt_root}$i"
1006         done
1007         do_nodes $clients "rm -rf $mntpt_dir"
1008 }
1009
1010 run_rr_alloc() {
1011         remote_mds_nodsh && skip "remote MDS with nodsh"
1012         echo "===Test gives more reproduction percentage if number of "\
1013                 "client and ost are more. Test with 44 or more clients "\
1014                 "and 73 or more OSTs gives 100% reproduction rate=="
1015
1016         RR_ALLOC=${RR_ALLOC:-$(which rr_alloc 2> /dev/null || true)}
1017         [ x$RR_ALLOC = x ] && skip_env "rr_alloc not found"
1018         declare -a diff_max_min_arr
1019         # foeo = file on each ost. calc = calculated.
1020         local ost_idx
1021         local foeo_calc
1022         local qos_prec_objs="${TMP}/qos_and_precreated_objects"
1023         local rr_alloc_NFILES=${rr_alloc_NFILES:-555}
1024         local rr_alloc_MNTPTS=${rr_alloc_MNTPTS:-11}
1025         local total_MNTPTS=$((rr_alloc_MNTPTS * num_clients))
1026         local mntpt_root="${TMP}/rr_alloc_mntpt/lustre"
1027         if [ $MDSCOUNT -lt 2 ]; then
1028                 [ -e $DIR/$tdir ] || mkdir -p $DIR/$tdir
1029         else
1030                 [ -e $DIR/$tdir ] || $LFS mkdir -i 0 $DIR/$tdir
1031         fi
1032         setstripe_getstripe $DIR/$tdir $rr_alloc_STRIPEPARAMS
1033
1034         chmod 0777 $DIR/$tdir
1035
1036         trap "cleanup_rr_alloc $clients $mntpt_root $rr_alloc_MNTPTS" EXIT ERR
1037         for i in $(seq 0 $((rr_alloc_MNTPTS - 1))); do
1038                 zconf_mount_clients $clients ${mntpt_root}$i $MOUNT_OPTS ||
1039                 error_exit "Failed to mount lustre on ${mntpt_root}$i $clients"
1040         done
1041
1042         local cmd="$RR_ALLOC $mntpt_root/$tdir/ash $rr_alloc_NFILES \
1043                 $num_clients"
1044
1045         # Save mdt values, set threshold to 100% i.e always Round Robin,
1046         # restore the saved values again after creating files...
1047         save_lustre_params mds1 \
1048                 "lov.$FSNAME-MDT0000*.qos_threshold_rr" > $qos_prec_objs
1049         save_lustre_params mds1 \
1050                 "osp.$FSNAME-OST*-osc-MDT0000.create_count" >> $qos_prec_objs
1051
1052         local old_create_count=$(grep -e "create_count" $qos_prec_objs |
1053                 cut -d'=' -f 2 | sort -nr | head -n1)
1054
1055         # Make sure that every osp has enough precreated objects for the file
1056         # creation app
1057
1058         # create_count is always set to the power of 2 only, so if the files
1059         # per OST are not multiple of that then it will be set to nearest
1060         # lower power of 2. So set 'create_count' to the upper power of 2.
1061
1062         foeo_calc=$((rr_alloc_NFILES * total_MNTPTS / OSTCOUNT))
1063         local create_count=$((2 * foeo_calc))
1064         do_facet mds1 "$LCTL set_param -n \
1065                 lov.$FSNAME-MDT0000*.qos_threshold_rr 100 \
1066                 osp.$FSNAME-OST*-osc-MDT0000.create_count $create_count" ||
1067                 error "failed while setting qos_threshold_rr & creat_count"
1068
1069         # Create few temporary files in order to increase the precreated objects
1070         # to a desired value, before starting 'rr_alloc' app. Due to default
1071         # value 32 of precreation count (OST_MIN_PRECREATE=32), precreated
1072         # objects available are 32 initially, these gets exhausted very soon,
1073         # which causes skip of some osps when very large number of files
1074         # is created per OSTs.
1075         createmany -o $DIR/$tdir/foo- $(((old_create_count + 1) * OSTCOUNT)) \
1076                 > /dev/null
1077         rm -f /$DIR/$tdir/foo*
1078
1079         # Check for enough precreated objects... We should not
1080         # fail here because code(osp_precreate.c) also takes care of it.
1081         # So we have good chances of passing test even if this check fails.
1082         local mdt_idx=0
1083         for ost_idx in $(seq 0 $((OSTCOUNT - 1))); do
1084                 [[ $(precreated_ost_obj_count $mdt_idx $ost_idx) -ge \
1085                         $foeo_calc ]] || echo "Warning: test may fail because" \
1086                         "of lack of precreated objects on OST${ost_idx}"
1087         done
1088
1089         if [[ $total_MNTPTS -ne 0 ]]; then
1090                 # Now start the actual file creation app.
1091                 mpi_run "-np $total_MNTPTS" $cmd || return
1092         else
1093                 error "No mount point"
1094         fi
1095
1096         restore_lustre_params < $qos_prec_objs
1097         rm -f $qos_prec_objs
1098
1099         diff_max_min_arr=($($LFS getstripe -r $DIR/$tdir/ |
1100                 grep "lmm_stripe_offset:" | awk '{print $2}' | sort -n |
1101                 uniq -c | awk 'NR==1 {min=max=$1} \
1102                 { $1<min ? min=$1 : min; $1>max ? max=$1 : max} \
1103                 END {print max-min, max, min}'))
1104
1105         rm -rf $DIR/$tdir
1106
1107         # In-case of fairly large number of file creation using RR (round-robin)
1108         # there can be two cases in which deviation will occur than the regular
1109         # RR algo behaviour-
1110         # 1- When rr_alloc does not start right with 'lqr_start_count' reseeded,
1111         # 2- When rr_alloc does not finish with 'lqr_start_count == 0'.
1112         # So the difference of files b/w any 2 OST should not be more than 2.
1113         [[ ${diff_max_min_arr[0]} -le 2 ]] ||
1114                 error "Uneven distribution detected: difference between" \
1115                 "maximum files per OST (${diff_max_min_arr[1]}) and" \
1116                 "minimum files per OST (${diff_max_min_arr[2]}) must not be" \
1117                 "greater than 2"
1118 }
1119
1120 run_fs_test() {
1121         # fs_test.x is the default name for exe
1122         FS_TEST=${FS_TEST:=$(which fs_test.x 2> /dev/null || true)}
1123
1124         local clients=${CLIENTS:-$(hostname)}
1125         local testdir=$DIR/d0.fs_test
1126         local file=${testdir}/fs_test
1127         fs_test_threads=${fs_test_threads:-2}
1128         fs_test_type=${fs_test_type:-1}
1129         fs_test_nobj=${fs_test_nobj:-10}
1130         fs_test_check=${fs_test_check:-3}
1131         fs_test_strided=${fs_test_strided:-1}
1132         fs_test_touch=${fs_test_touch:-3}
1133         fs_test_supersize=${fs_test_supersize:-1}
1134         fs_test_op=${fs_test_op:-write}
1135         fs_test_barriers=${fs_test_barriers:-bopen,bwrite,bclose}
1136         fs_test_io=${fs_test_io:-mpi}
1137         fs_test_objsize=${fs_test_objsize:-100}
1138         fs_test_objunit=${fs_test_objunit:-1048576} # 1 mb
1139         fs_test_ndirs=${fs_test_ndirs:-80000}
1140
1141         [ x$FS_TEST = x ] && skip "FS_TEST not found"
1142
1143         # Space estimation  in bytes
1144         local space=$(df -B 1 -P $dir | tail -n 1 | awk '{ print $4 }')
1145         local total_threads=$((num_clients * fs_test_threads))
1146         echo "+ $fs_test_objsize * $fs_test_objunit * $total_threads "
1147         if [ $((space / 2)) -le \
1148                 $((fs_test_objsize * fs_test_objunit * total_threads)) ]; then
1149                         fs_test_objsize=$((space / 2 / fs_test_objunit / \
1150                                 total_threads))
1151                         [ $fs_test_objsize -eq 0 ] &&
1152                         skip_env "Need free space more than \
1153                                 $((2 * total_threads * fs_test_objunit)) \
1154                                 : have $((space / fs_test_objunit))"
1155
1156                         echo "(reduced objsize to \
1157                                 $((fs_test_objsize * fs_test_objunit)) bytes)"
1158         fi
1159
1160         print_opts FS_TEST clients fs_test_threads fs_test_objsize MACHINEFILE
1161
1162         mkdir -p $testdir
1163         setstripe_getstripe $testdir $fs_test_STRIPEPARAMS
1164
1165         # mpi_run uses mpiuser
1166         chmod 0777 $testdir
1167
1168         # --nodb          Turn off the database code at runtime
1169         # -g --target     The path to the data file
1170         # -t --type       Whether to do N-N (1) or N-1 (2)
1171         # -n --nobj       The number of objects written/read by each proc
1172         # -z --size       The size of each object
1173         # -d ---num_nn_dirs Number of subdirectories for files
1174         # -C --check      Check every byte using argument 3.
1175         # --collective    Whether to use collective I/O (for N-1, mpi-io only)
1176         # -s --strided    Whether to use a strided pattern (for N-1 only)
1177         # -T --touch      Touch every byte using argument 3
1178         # -o --op         Whether to read only (read) or write only (write)
1179         # -b --barriers   When to barrier.
1180         # -i --io         Use POSIX, MPI, or PLFS IO routines (mpi|posix|plfs)
1181         # -S --supersize  Specify how many objects per superblock
1182
1183         local cmd="$FS_TEST -nodb -g $file -t $fs_test_type -n $fs_test_nobj \
1184                 -z $((fs_test_objsize * fs_test_objunit)) -d $fs_test_ndirs \
1185                 -C $fs_test_check -collective -s $fs_test_strided \
1186                 -T $fs_test_touch -o $fs_test_op -b $fs_test_barriers \
1187                 -i $fs_test_io -S $fs_test_supersize"
1188
1189         echo "+ $cmd"
1190         mpi_run "-np $((num_clients * fs_test_threads))" $cmd
1191
1192         local rc=$?
1193         if [ $rc != 0 ] ; then
1194                 error "fs_test failed! $rc"
1195         fi
1196
1197         rm -rf $testdir
1198 }
1199
1200 ior_mdtest_parallel() {
1201         local rc1=0
1202         local rc2=0
1203         local type=$1
1204
1205         run_ior $type &
1206         local pids=$!
1207
1208         run_mdtest $type || rc2=$?
1209         [[ $rc2 -ne 0 ]] && echo "mdtest failed with error $rc2"
1210
1211         wait $pids || rc1=$?
1212         [[ $rc1 -ne 0 ]] && echo "ior failed with error $rc1"
1213
1214         [[ $rc1 -ne 0 || $rc2 -ne 0 ]] && return 1
1215         return 0
1216 }
1217
1218 run_fio() {
1219         FIO=${FIO:=$(which fio 2> /dev/null || true)}
1220
1221         local clients=${CLIENTS:-$(hostname)}
1222         local fio_jobNum=${fio_jobNum:-4}
1223         local fio_jobFile=${fio_jobFile:-$TMP/fiojobfile.$(date +%s)}
1224         local fio_bs=${fio_bs:-1}
1225         local testdir=$DIR/d0.fio
1226         local file=${testdir}/fio
1227         local runtime=60
1228         local propagate=false
1229
1230         [ "$SLOW" = "no" ] || runtime=600
1231
1232         [ x$FIO = x ] && skip_env "FIO not found"
1233
1234         mkdir -p $testdir
1235         setstripe_getstripe $testdir $fio_STRIPEPARAMS
1236
1237         # use fio job file if exists,
1238         # create a simple one if missing
1239         if ! [ -f $fio_jobFile ]; then
1240                 cat >> $fio_jobFile <<EOF
1241 [global]
1242 rw=randwrite
1243 size=128m
1244 time_based=1
1245 runtime=$runtime
1246 filename=${file}_\$(hostname)
1247 EOF
1248                 # bs size increased by $i for each job
1249                 for ((i=1; i<=fio_jobNum; i++)); do
1250                         cat >> $fio_jobFile <<EOF
1251
1252 [job$i]
1253 bs=$(( fio_bs * i ))m
1254 EOF
1255                 done
1256                 # job file is created, should be propagated to all clients
1257                 propagate=true
1258         fi
1259
1260
1261         # propagate the job file if not all clients have it yet or
1262         # if the job file was created during the test run
1263         if ! do_nodesv $clients " [ -f $fio_jobFile ] " ||
1264            $propagate; then
1265                 local cfg=$(cat $fio_jobFile)
1266                 do_nodes $clients "echo \\\"$cfg\\\" > ${fio_jobFile}" ||
1267                         error "job file $fio_jobFile is not propagated"
1268                 do_nodesv $clients "cat ${fio_jobFile}"
1269         fi
1270
1271         cmd="$FIO $fio_jobFile"
1272         echo "+ $cmd"
1273
1274         log "clients: $clients $cmd"
1275
1276         local rc=0
1277         do_nodesv $clients "$cmd "
1278         rc=$?
1279
1280         [ $rc = 0 ] || error "fio failed: $rc"
1281         rm -rf $testdir
1282 }
1283
1284 run_xdd() {
1285         XDD=${XDD:=$(which xdd 2> /dev/null || true)}
1286
1287         local clients=${CLIENTS:-$(hostname)}
1288         local testdir=$DIR/d0.xdd
1289         xdd_queuedepth=${xdd_queuedepth:-4}
1290         xdd_blocksize=${xdd_blocksize:-512}
1291         xdd_reqsize=${xdd_reqsize:-128}
1292         xdd_mbytes=${xdd_mbytes:-100}
1293         xdd_passes=${xdd_passes:-40}
1294         xdd_rwratio=${xdd_rwratio:-0}
1295         xdd_ntargets=${xdd_ntargets:-6}
1296         local xdd_custom_params=${xdd_custom_params:-"-dio -stoponerror \
1297                 -maxpri -minall -noproclock -nomemlock"}
1298
1299         [ x$XDD = x ] && skip "XDD not found"
1300
1301         print_opts XDD clients xdd_queuedepth xdd_blocksize xdd_reqsize \
1302                 xdd_mbytes xdd_passes xdd_rwratio
1303
1304         mkdir -p $testdir
1305         setstripe_getstripe $testdir $xdd_STRIPEPARAMS
1306
1307         local files=""
1308         # Target files creates based on the given number of targets
1309         for (( i=0; i < $xdd_ntargets; i++ ))
1310         do
1311                 files+="${testdir}/xdd"$i" "
1312         done
1313
1314         # -targets      specifies the devices or files to perform operation
1315         # -reqsize      number of 'blocks' per operation
1316         # -mbytes       number of 1024*1024-byte blocks to transfer
1317         # -blocksize    size of a single 'block'
1318         # -passes       number of times to read mbytes
1319         # -queuedepth   number of commands to queue on the target
1320         # -rwratio      percentage of read to write operations
1321         # -verbose      will print out statistics on each pass
1322
1323         local cmd="$XDD -targets $xdd_ntargets $files -reqsize $xdd_reqsize \
1324                 -mbytes $xdd_mbytes -blocksize $xdd_blocksize \
1325                 -passes $xdd_passes -queuedepth $xdd_queuedepth \
1326                 -rwratio $xdd_rwratio -verbose $xdd_custom_params"
1327         echo "+ $cmd"
1328
1329         local rc=0
1330         do_nodesv $clients "$cmd "
1331         rc=$?
1332
1333         [ $rc = 0 ] || error "xdd failed: $rc"
1334
1335         rm -rf $testdir
1336 }