Whamcloud - gitweb
LU-1187 tests: Add DNE test cases in sanity.
[fs/lustre-release.git] / lustre / tests / functions.sh
1 #!/bin/bash
2 # -*- mode: Bash; tab-width: 4; indent-tabs-mode: t; -*-
3 # vim:shiftwidth=4:softtabstop=4:tabstop=4:
4
5 # Simple function used by run_*.sh scripts
6
7 assert_env() {
8     local failed=""
9     for name in $@; do
10         if [ -z "${!name}" ]; then
11             echo "$0: $name must be set"
12             failed=1
13         fi
14     done
15     [ $failed ] && exit 1 || true
16 }
17
18 # lrepl - Lustre test Read-Eval-Print Loop.
19 #
20 # This function implements a REPL for the Lustre test framework.  It
21 # doesn't exec an actual shell because the user may want to inspect
22 # variables and use functions from the test framework.
23 lrepl() {
24     local line
25     local rawline
26     local prompt
27
28     cat <<EOF
29         This is an interactive read-eval-print loop interactive shell
30         simulation that you can use to debug failing tests.  You can
31         enter most bash command lines (see notes below).
32
33         Use this REPL to inspect variables, set them, call test
34         framework shell functions, etcetera.
35
36         'exit' or EOF to exit this shell.
37
38         set \$retcode to 0 to cause the assertion failure that
39         triggered this REPL to be ignored.
40
41         Examples:
42             do_facet ost1 lctl get_param ost.*.ost.threads_*
43             do_rpc_nodes \$OSTNODES unload_modules
44
45         NOTES:
46             All but the last line of multi-line statements or blocks
47             must end in a backslash.
48
49             "Here documents" are not supported.
50
51             History is not supported, but command-line editing is.
52
53 EOF
54
55     # Prompt escapes don't work in read -p, sadly.
56     prompt=":test_${testnum:-UNKNOWN}:$(uname -n):$(basename $PWD)% "
57
58     # We use read -r to get close to a shell experience
59     while read -e -r -p "$prompt" rawline; do
60         line=
61         case "$rawline" in
62         # Don't want to exit-exit, just exit the REPL
63         exit) break;;
64         # We need to handle continuations, and read -r doesn't do
65         # that for us.  Yet we need read -r.
66         #
67         # We also use case/esac to compare lines read to "*\\"
68         # because [ "$line" = *\\ ] and variants of that don't work.
69         *\\) line="$rawline"
70             while read -e -r -p '> ' rawline
71             do
72                 line="$line"$'\n'"$rawline"
73                 case "$rawline" in
74                 # We could check for here documents by matching
75                 # against *<<*, but who cares.
76                 *\\) continue;;
77                 *) break;;
78                 esac
79             done
80             ;;
81         *) line=$rawline
82         esac
83
84         case "$line" in
85         *\\) break;;
86         esac
87
88         # Finally!  Time to eval.
89         eval "$line"
90     done
91
92     echo $'\n\tExiting interactive shell...\n'
93     return 0
94 }
95
96 # lassert - Lustre test framework assert
97 #
98 # Arguments: failure code, failure message, expression/statement
99 #
100 # lassert evaluates the expression given, and, if false, calls
101 # error() to trigger test failure.  If REPL_ON_LASSERT is true then
102 # lassert will call lrepl() to give the user an interactive shell.
103 # If the REPL sets retcode=0 then the assertion failure will be
104 # ignored.
105 lassert() {
106     local retcode=$1
107     local msg=$2
108     shift 2
109
110     echo "checking $* ($(eval echo \""$*"\"))..."
111     eval "$@" && return 0;
112
113     if ${REPL_ON_LASSERT:-false}; then
114         echo "Assertion $retcode failed: $* (expanded: $(eval echo \""$*"\"))
115 $msg"
116         lrepl
117     fi
118
119     error "Assertion $retcode failed: $* (expanded: $(eval echo \""$*"\"))
120 $msg"
121     return $retcode
122 }
123
124 # setmodopts- set module options for subsequent calls to load_modules
125 #
126 # Usage: setmodopts module_name new_value [var_in_which_to_save_old_value]
127 #        setmodopts -a module_name new_value [var_in_which_to_save_old_value]
128 #
129 # In the second usage the new value is appended to the old.
130 setmodopts() {
131         local _append=false
132
133         if [ "$1" = -a ]; then
134             _append=true
135             shift
136         fi
137
138         local _var=MODOPTS_$1
139         local _newvalue=$2
140         local _savevar=$3
141         local _oldvalue
142
143         # Dynamic naming of variables is a pain in bash.  In ksh93 we could
144         # write "nameref opts_var=${modname}_MODOPTS" then assign directly
145         # to opts_var.  Associative arrays would also help, alternatively.
146         # Alas, we're stuck with eval until all distros move to a more recent
147         # version of bash.  Fortunately we don't need to eval unset and export.
148
149         if [ -z "$_newvalue" ]; then
150             unset $_var
151             return 0
152         fi
153
154         _oldvalue=${!var}
155         $_append && _newvalue="$_oldvalue $_newvalue"
156         export $_var="$_newvalue"
157         echo setmodopts: ${_var}=${_newvalue}
158
159         [ -n "$_savevar" ] && eval $_savevar=\""$_oldvalue"\"
160 }
161
162 echoerr () { echo "$@" 1>&2 ; }
163
164 signaled() {
165     echoerr "$(date +'%F %H:%M:%S'): client load was signaled to terminate"
166
167     local PGID=$(ps -eo "%c %p %r" | awk "/ $PPID / {print \$3}")
168     kill -TERM -$PGID
169     sleep 5
170     kill -KILL -$PGID
171 }
172
173 mpi_run () {
174     local mpirun="$MPIRUN $MPIRUN_OPTIONS"
175     local command="$mpirun $@"
176     local mpilog=$TMP/mpi.log
177     local rc
178
179     if [ -n "$MPI_USER" -a "$MPI_USER" != root -a -n "$mpirun" ]; then
180         echo "+ chmod 0777 $MOUNT"
181         chmod 0777 $MOUNT
182         command="su $MPI_USER sh -c \"$command \""
183     fi
184
185     ls -ald $MOUNT
186     echo "+ $command"
187     eval $command 2>&1 | tee $mpilog || true
188
189     rc=${PIPESTATUS[0]}
190     if [ $rc -eq 0 ] && grep -q "p4_error:" $mpilog ; then
191        rc=1
192     fi
193     return $rc
194 }
195
196 nids_list () {
197    local list
198    for i in ${1//,/ }; do
199        list="$list $i@$NETTYPE"
200    done
201    echo $list
202 }
203
204 # FIXME: all setup/cleanup can be done without rpc.sh
205 lst_end_session () {
206     local verbose=false
207     [ x$1 = x--verbose ] && verbose=true
208
209     export LST_SESSION=`$LST show_session 2>/dev/null | awk -F " " '{print $5}'`
210     [ "$LST_SESSION" == "" ] && return
211
212     if $verbose; then
213         $LST show_error c s
214     fi
215     $LST stop b
216     $LST end_session
217 }
218
219 lst_session_cleanup_all () {
220     local list=$(comma_list $(nodes_list))
221     do_rpc_nodes $list lst_end_session
222 }
223
224 lst_cleanup () {
225     lsmod | grep -q lnet_selftest && \
226         rmmod lnet_selftest > /dev/null 2>&1 || true
227 }
228
229 lst_cleanup_all () {
230    local list=$(comma_list $(nodes_list))
231
232    # lst end_session needs to be executed only locally
233    # i.e. on node where lst new_session was called
234    lst_end_session --verbose
235    do_rpc_nodes $list lst_cleanup
236 }
237
238 lst_setup () {
239     load_module lnet_selftest
240 }
241
242 lst_setup_all () {
243     local list=$(comma_list $(nodes_list))
244     do_rpc_nodes $list lst_setup
245 }
246
247 ###
248 # short_hostname
249 #
250 # Passed a single argument, strips everything off following
251 # and includes the first period.
252 # client-20.lab.whamcloud.com becomes client-20
253 short_hostname() {
254   echo $(sed 's/\..*//' <<< $1)
255 }
256
257 print_opts () {
258     local var
259
260     echo OPTIONS:
261
262     for i in $@; do
263         var=$i
264         echo "${var}=${!var}"
265     done
266     [ -e $MACHINEFILE ] && cat $MACHINEFILE
267 }
268
269 run_compilebench() {
270
271 # Takes:
272 # 5 min * cbench_RUNS
273 #        SLOW=no     10 mins
274 #        SLOW=yes    50 mins
275 # Space estimation:
276 #        compile dir kernel-1 680MB
277 #        required space       680MB * cbench_IDIRS = ~7 Gb
278
279     cbench_DIR=${cbench_DIR:-""}
280     cbench_IDIRS=${cbench_IDIRS:-4}
281     cbench_RUNS=${cbench_RUNS:-4}
282
283     print_opts cbench_DIR cbench_IDIRS cbench_RUNS
284
285     [ x$cbench_DIR = x ] &&
286         { skip_env "compilebench not found" && return; }
287
288     [ -e $cbench_DIR/compilebench ] || \
289         { skip_env "No compilebench build" && return; }
290
291     local space=$(df -P $DIR | tail -n 1 | awk '{ print $4 }')
292     if [ $space -le $((680 * 1024 * cbench_IDIRS)) ]; then
293         cbench_IDIRS=$(( space / 680 / 1024))
294         [ $cbench_IDIRS = 0 ] && \
295             skip_env "Need free space atleast 680 Mb, have $space" && return
296
297         log free space=$space, reducing initial dirs to $cbench_IDIRS
298     fi
299     # FIXME:
300     # t-f _base needs to be modifyed to set properly tdir
301     # for new "test_foo" functions names
302     # local testdir=$DIR/$tdir
303     local testdir=$DIR/d0.compilebench
304     mkdir -p $testdir
305
306     local savePWD=$PWD
307     cd $cbench_DIR
308     local cmd="./compilebench -D $testdir -i $cbench_IDIRS \
309         -r $cbench_RUNS --makej"
310
311     log "$cmd"
312
313     local rc=0
314     eval $cmd
315     rc=$?
316
317     cd $savePWD
318     [ $rc = 0 ] || error "compilebench failed: $rc"
319     rm -rf $testdir
320 }
321
322 run_metabench() {
323
324     METABENCH=${METABENCH:-$(which metabench 2> /dev/null || true)}
325     mbench_NFILES=${mbench_NFILES:-30400}
326     # threads per client
327     mbench_THREADS=${mbench_THREADS:-4}
328
329     [ x$METABENCH = x ] &&
330         { skip_env "metabench not found" && return; }
331
332     # FIXME
333     # Need space estimation here.
334
335     print_opts METABENCH clients mbench_NFILES mbench_THREADS
336
337     local testdir=$DIR/d0.metabench
338     mkdir -p $testdir
339     # mpi_run uses mpiuser
340     chmod 0777 $testdir
341
342     # -C             Run the file creation tests.
343     # -S             Run the file stat tests.
344     # -c nfile       Number of files to be used in each test.
345     # -k             Cleanup.  Remove the test directories.
346     local cmd="$METABENCH -w $testdir -c $mbench_NFILES -C -S -k"
347     echo "+ $cmd"
348
349     # find out if we need to use srun by checking $SRUN_PARTITION
350     if [ "$SRUN_PARTITION" ]; then
351         $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
352             -n $((num_clients * mbench_THREADS)) -p $SRUN_PARTITION -- $cmd
353     else
354         mpi_run -np $((num_clients * $mbench_THREADS)) \
355             -machinefile ${MACHINEFILE} $cmd
356     fi
357
358     local rc=$?
359     if [ $rc != 0 ] ; then
360         error "metabench failed! $rc"
361     fi
362     rm -rf $testdir
363 }
364
365 run_simul() {
366
367     SIMUL=${SIMUL:=$(which simul 2> /dev/null || true)}
368     # threads per client
369     simul_THREADS=${simul_THREADS:-2}
370     simul_REP=${simul_REP:-20}
371
372     if [ "$NFSCLIENT" ]; then
373         skip "skipped for NFSCLIENT mode"
374         return
375     fi
376
377     [ x$SIMUL = x ] &&
378         { skip_env "simul not found" && return; }
379
380     # FIXME
381     # Need space estimation here.
382
383     print_opts SIMUL clients simul_REP simul_THREADS
384
385     local testdir=$DIR/d0.simul
386     mkdir -p $testdir
387     # mpi_run uses mpiuser
388     chmod 0777 $testdir
389
390     # -n # : repeat each test # times
391     # -N # : repeat the entire set of tests # times
392
393     local cmd="$SIMUL -d $testdir -n $simul_REP -N $simul_REP"
394
395     echo "+ $cmd"
396     # find out if we need to use srun by checking $SRUN_PARTITION
397     if [ "$SRUN_PARTITION" ]; then
398         $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
399             -n $((num_clients * simul_THREADS)) -p $SRUN_PARTITION -- $cmd
400     else
401         mpi_run -np $((num_clients * simul_THREADS)) \
402             -machinefile ${MACHINEFILE} $cmd
403     fi
404
405     local rc=$?
406     if [ $rc != 0 ] ; then
407         error "simul failed! $rc"
408     fi
409     rm -rf $testdir
410 }
411
412 run_mdtest() {
413
414     MDTEST=${MDTEST:=$(which mdtest 2> /dev/null || true)}
415     # threads per client
416     mdtest_THREADS=${mdtest_THREADS:-2}
417     mdtest_nFiles=${mdtest_nFiles:-"100000"}
418     # We devide the files by number of core
419     mdtest_nFiles=$((mdtest_nFiles/mdtest_THREADS/num_clients))
420     mdtest_iteration=${mdtest_iteration:-1}
421
422     local type=${1:-"ssf"}
423
424     if [ "$NFSCLIENT" ]; then
425         skip "skipped for NFSCLIENT mode"
426         return
427     fi
428
429     [ x$MDTEST = x ] &&
430         { skip_env "mdtest not found" && return; }
431
432     # FIXME
433     # Need space estimation here.
434
435     print_opts MDTEST mdtest_iteration mdtest_THREADS mdtest_nFiles
436
437     local testdir=$DIR/d0.mdtest
438     mkdir -p $testdir
439     # mpi_run uses mpiuser
440     chmod 0777 $testdir
441
442     # -i # : repeat each test # times
443     # -d   : test dir
444     # -n # : number of file/dir to create/stat/remove
445     # -u   : each process create/stat/remove individually
446
447     local cmd="$MDTEST -d $testdir -i $mdtest_iteration -n $mdtest_nFiles"
448     [ $type = "fpp" ] && cmd="$cmd -u"
449
450     echo "+ $cmd"
451     # find out if we need to use srun by checking $SRUN_PARTITION
452     if [ "$SRUN_PARTITION" ]; then
453         $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
454             -n $((num_clients * mdtest_THREADS)) -p $SRUN_PARTITION -- $cmd
455     else
456         mpi_run -np $((num_clients * mdtest_THREADS)) \
457             -machinefile ${MACHINEFILE} $cmd
458     fi
459
460     local rc=$?
461     if [ $rc != 0 ] ; then
462         error "mdtest failed! $rc"
463     fi
464     rm -rf $testdir
465 }
466
467 run_connectathon() {
468
469     cnt_DIR=${cnt_DIR:-""}
470     cnt_NRUN=${cnt_NRUN:-10}
471
472     print_opts cnt_DIR cnt_NRUN
473
474     [ x$cnt_DIR = x ] &&
475         { skip_env "connectathon dir not found" && return; }
476
477     [ -e $cnt_DIR/runtests ] || \
478         { skip_env "No connectathon runtests found" && return; }
479
480     local testdir=$DIR/d0.connectathon
481     mkdir -p $testdir
482
483     local savePWD=$PWD
484     cd $cnt_DIR
485
486     #
487     # cthon options (must be in this order)
488     #
489     # -N numpasses - will be passed to the runtests script.  This argument
490     #         is optional.  It specifies the number of times to run
491     #         through the tests.
492     #
493     # One of these test types
494     #    -b  basic
495     #    -g  general
496     #    -s  special
497     #    -l  lock
498     #    -a  all of the above
499     #
500     # -f      a quick functionality test
501     #
502
503     tests="-b -g -s"
504     # Include lock tests unless we're running on nfsv4
505     local fstype=$(df -TP $testdir | awk 'NR==2  {print $2}')
506     echo "$testdir: $fstype"
507     if [[ $fstype != "nfs4" ]]; then
508         tests="$tests -l"
509     fi
510     echo "tests: $tests"
511     for test in $tests; do
512         local cmd="./runtests -N $cnt_NRUN $test -f $testdir"
513         local rc=0
514
515         log "$cmd"
516         eval $cmd
517         rc=$?
518         [ $rc = 0 ] || error "connectathon failed: $rc"
519     done
520
521     cd $savePWD
522     rm -rf $testdir
523 }
524
525 run_ior() {
526     local type=${1:="ssf"}
527
528     IOR=${IOR:-$(which IOR 2> /dev/null || true)}
529     # threads per client
530     ior_THREADS=${ior_THREADS:-2}
531     ior_iteration=${ior_iteration:-1}
532     ior_blockSize=${ior_blockSize:-6}   # GB
533     ior_xferSize=${ior_xferSize:-2m}
534     ior_type=${ior_type:-POSIX}
535     ior_DURATION=${ior_DURATION:-30}    # minutes
536
537     [ x$IOR = x ] &&
538         { skip_env "IOR not found" && return; }
539
540     local space=$(df -P $DIR | tail -n 1 | awk '{ print $4 }')
541     local total_threads=$(( num_clients * ior_THREADS ))
542     echo "+ $ior_blockSize * 1024 * 1024 * $total_threads "
543     if [ $((space / 2)) -le \
544         $(( ior_blockSize * 1024 * 1024 * total_threads)) ]; then
545         echo "+ $space * 9/10 / 1024 / 1024 / $num_clients / $ior_THREADS"
546         ior_blockSize=$(( space /2 /1024 /1024 / num_clients / ior_THREADS ))
547         [ $ior_blockSize = 0 ] && \
548             skip_env "Need free space more than $((2 * total_threads))GB: \
549                 $((total_threads *1024 *1024*2)), have $space" && return
550
551         local reduced_size="$num_clients x $ior_THREADS x $ior_blockSize"
552         echo "free space=$space, Need: $reduced_size GB"
553         echo "(blockSize reduced to $ior_blockSize Gb)"
554     fi
555
556     print_opts IOR ior_THREADS ior_DURATION MACHINEFILE
557
558     local testdir=$DIR/d0.ior.$type
559     mkdir -p $testdir
560     # mpi_run uses mpiuser
561     chmod 0777 $testdir
562     if [ "$NFSCLIENT" ]; then
563         setstripe_nfsserver $testdir -c -1 ||
564             { error "setstripe on nfsserver failed" && return 1; }
565     else
566         $LFS setstripe $testdir -c -1 ||
567             { error "setstripe failed" && return 2; }
568     fi
569     #
570     # -b N  blockSize --
571     #       contiguous bytes to write per task (e.g.: 8, 4k, 2m, 1g)"
572     # -o S  testFileName
573     # -t N  transferSize -- size of transfer in bytes (e.g.: 8, 4k, 2m, 1g)"
574     # -w    writeFile -- write file"
575     # -r    readFile -- read existing file"
576     # -T    maxTimeDuration -- max time in minutes to run tests"
577     # -k    keepFile -- keep testFile(s) on program exit
578
579     local cmd="$IOR -a $ior_type -b ${ior_blockSize}g -o $testdir/iorData \
580          -t $ior_xferSize -v -w -r -i $ior_iteration -T $ior_DURATION -k"
581     [ $type = "fpp" ] && cmd="$cmd -F"
582
583     echo "+ $cmd"
584     # find out if we need to use srun by checking $SRUN_PARTITION
585     if [ "$SRUN_PARTITION" ]; then
586         $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
587             -n $((num_clients * ior_THREADS)) -p $SRUN_PARTITION -- $cmd
588     else
589         mpi_run -np $((num_clients * $ior_THREADS)) \
590             -machinefile ${MACHINEFILE} $cmd
591     fi
592
593     local rc=$?
594     if [ $rc != 0 ] ; then
595         error "ior failed! $rc"
596     fi
597     rm -rf $testdir
598 }
599
600 run_mib() {
601
602     MIB=${MIB:=$(which mib 2> /dev/null || true)}
603     # threads per client
604     mib_THREADS=${mib_THREADS:-2}
605     mib_xferSize=${mib_xferSize:-1m}
606     mib_xferLimit=${mib_xferLimit:-5000}
607     mib_timeLimit=${mib_timeLimit:-300}
608
609     if [ "$NFSCLIENT" ]; then
610         skip "skipped for NFSCLIENT mode"
611         return
612     fi
613
614     [ x$MIB = x ] &&
615         { skip_env "MIB not found" && return; }
616
617     print_opts MIB mib_THREADS mib_xferSize mib_xferLimit mib_timeLimit \
618         MACHINEFILE
619
620     local testdir=$DIR/d0.mib
621     mkdir -p $testdir
622     # mpi_run uses mpiuser
623     chmod 0777 $testdir
624     $LFS setstripe $testdir -c -1 ||
625         { error "setstripe failed" && return 2; }
626     #
627     # -I    Show intermediate values in output
628     # -H    Show headers in output
629     # -L    Do not issue new system calls after this many seconds
630     # -s    Use system calls of this size
631     # -t    test dir
632     # -l    Issue no more than this many system calls
633     local cmd="$MIB -t $testdir -s $mib_xferSize -l $mib_xferLimit \
634         -L $mib_timeLimit -HI -p mib.$(date +%Y%m%d%H%M%S)"
635
636     echo "+ $cmd"
637     # find out if we need to use srun by checking $SRUN_PARTITION
638     if [ "$SRUN_PARTITION" ]; then
639         $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
640             -n $((num_clients * mib_THREADS)) -p $SRUN_PARTITION -- $cmd
641     else
642         mpi_run -np $((num_clients * mib_THREADS)) \
643             -machinefile ${MACHINEFILE} $cmd
644     fi
645
646     local rc=$?
647     if [ $rc != 0 ] ; then
648         error "mib failed! $rc"
649     fi
650     rm -rf $testdir
651 }
652
653 run_cascading_rw() {
654
655     CASC_RW=${CASC_RW:-$(which cascading_rw 2> /dev/null || true)}
656     # threads per client
657     casc_THREADS=${casc_THREADS:-2}
658     casc_REP=${casc_REP:-300}
659
660     if [ "$NFSCLIENT" ]; then
661         skip "skipped for NFSCLIENT mode"
662         return
663     fi
664
665     [ x$CASC_RW = x ] &&
666         { skip_env "cascading_rw not found" && return; }
667
668     # FIXME
669     # Need space estimation here.
670
671     print_opts CASC_RW clients casc_THREADS casc_REP MACHINEFILE
672
673     local testdir=$DIR/d0.cascading_rw
674     mkdir -p $testdir
675     # mpi_run uses mpiuser
676     chmod 0777 $testdir
677
678     # -g: debug mode
679     # -n: repeat test # times
680
681     local cmd="$CASC_RW -g -d $testdir -n $casc_REP"
682
683     echo "+ $cmd"
684     mpi_run -np $((num_clients * $casc_THREADS)) \
685         -machinefile ${MACHINEFILE} $cmd
686
687     local rc=$?
688     if [ $rc != 0 ] ; then
689         error "cascading_rw failed! $rc"
690     fi
691     rm -rf $testdir
692 }
693
694 run_write_append_truncate() {
695
696     # threads per client
697     write_THREADS=${write_THREADS:-8}
698     write_REP=${write_REP:-10000}
699
700     if [ "$NFSCLIENT" ]; then
701         skip "skipped for NFSCLIENT mode"
702         return
703     fi
704
705     # location is lustre/tests dir
706     if ! which write_append_truncate > /dev/null 2>&1 ; then
707         skip_env "write_append_truncate not found"
708         return
709     fi
710
711     # FIXME
712     # Need space estimation here.
713
714     local testdir=$DIR/d0.write_append_truncate
715     local file=$testdir/f0.wat
716
717     print_opts clients write_REP write_THREADS MACHINEFILE
718
719     mkdir -p $testdir
720     # mpi_run uses mpiuser
721     chmod 0777 $testdir
722
723     local cmd="write_append_truncate -n $write_REP $file"
724
725     echo "+ $cmd"
726     mpi_run -np $((num_clients * $write_THREADS)) \
727         -machinefile ${MACHINEFILE} $cmd
728
729     local rc=$?
730     if [ $rc != 0 ] ; then
731         error "write_append_truncate failed! $rc"
732         return $rc
733     fi
734     rm -rf $testdir
735 }
736
737 run_write_disjoint() {
738
739     WRITE_DISJOINT=${WRITE_DISJOINT:-$(which write_disjoint \
740         2> /dev/null || true)}
741     # threads per client
742     wdisjoint_THREADS=${wdisjoint_THREADS:-4}
743     wdisjoint_REP=${wdisjoint_REP:-10000}
744
745     if [ "$NFSCLIENT" ]; then
746         skip "skipped for NFSCLIENT mode"
747         return
748     fi
749
750     [ x$WRITE_DISJOINT = x ] &&
751         { skip_env "write_disjoint not found" && return; }
752
753     # FIXME
754     # Need space estimation here.
755
756     print_opts WRITE_DISJOINT clients wdisjoint_THREADS wdisjoint_REP \
757         MACHINEFILE
758     local testdir=$DIR/d0.write_disjoint
759     mkdir -p $testdir
760     # mpi_run uses mpiuser
761     chmod 0777 $testdir
762
763     local cmd="$WRITE_DISJOINT -f $testdir/file -n $wdisjoint_REP"
764
765     echo "+ $cmd"
766     mpi_run -np $((num_clients * $wdisjoint_THREADS)) \
767         -machinefile ${MACHINEFILE} $cmd
768
769     local rc=$?
770     if [ $rc != 0 ] ; then
771         error "write_disjoint failed! $rc"
772     fi
773     rm -rf $testdir
774 }
775
776 run_parallel_grouplock() {
777
778     PARALLEL_GROUPLOCK=${PARALLEL_GROUPLOCK:-$(which parallel_grouplock \
779         2> /dev/null || true)}
780     parallel_grouplock_MINTASKS=${parallel_grouplock_MINTASKS:-5}
781
782     if [ "$NFSCLIENT" ]; then
783         skip "skipped for NFSCLIENT mode"
784         return
785     fi
786
787     [ x$PARALLEL_GROUPLOCK = x ] &&
788         { skip "PARALLEL_GROUPLOCK not found" && return; }
789
790     print_opts clients parallel_grouplock_MINTASKS MACHINEFILE
791
792     local testdir=$DIR/d0.parallel_grouplock
793     mkdir -p $testdir
794     # mpi_run uses mpiuser
795     chmod 0777 $testdir
796
797     do_nodes $clients "lctl set_param llite.*.max_rw_chunk=0" ||
798         error "set_param max_rw_chunk=0 failed "
799
800     local cmd
801     local status=0
802     local subtest
803     for i in $(seq 12); do
804         subtest="-t $i"
805         local cmd="$PARALLEL_GROUPLOCK -g -v -d $testdir $subtest"
806         echo "+ $cmd"
807
808         mpi_run -np $parallel_grouplock_MINTASKS \
809             -machinefile ${MACHINEFILE} $cmd
810         local rc=$?
811         if [ $rc != 0 ] ; then
812             error_noexit "parallel_grouplock subtests $subtest failed! $rc"
813         else
814             echo "parallel_grouplock subtests $subtest PASS"
815         fi
816         let status=$((status + rc))
817         # clear debug to collect one log per one test
818         do_nodes $(comma_list $(nodes_list)) lctl clear
819      done
820     [ $status -eq 0 ] || error "parallel_grouplock status: $status"
821     rm -rf $testdir
822 }
823
824 cleanup_statahead () {
825     trap 0
826
827     local clients=$1
828     local mntpt_root=$2
829     local num_mntpts=$3
830
831     for i in $(seq 0 $num_mntpts);do
832         zconf_umount_clients $clients ${mntpt_root}$i ||
833             error_exit "Failed to umount lustre on ${mntpt_root}$i"
834     done
835 }
836
837 run_statahead () {
838
839     statahead_NUMMNTPTS=${statahead_NUMMNTPTS:-5}
840     statahead_NUMFILES=${statahead_NUMFILES:-500000}
841
842     if [[ -n $NFSCLIENT ]]; then
843         skip "Statahead testing is not supported on NFS clients."
844         return 0
845     fi
846
847     [ x$MDSRATE = x ] &&
848         { skip_env "mdsrate not found" && return; }
849
850     print_opts MDSRATE clients statahead_NUMMNTPTS statahead_NUMFILES
851
852     # create large dir
853
854     # do not use default "d[0-9]*" dir name
855     # to avoid of rm $statahead_NUMFILES (500k) files in t-f cleanup
856     local dir=dstatahead
857     local testdir=$DIR/$dir
858
859     # cleanup only if dir exists
860     # cleanup only $statahead_NUMFILES number of files
861     # ignore the other files created by someone else
862     [ -d $testdir ] &&
863         mdsrate_cleanup $((num_clients * 32)) $MACHINEFILE \
864             $statahead_NUMFILES $testdir 'f%%d' --ignore
865
866     mkdir -p $testdir
867     # mpi_run uses mpiuser
868     chmod 0777 $testdir
869
870     local num_files=$statahead_NUMFILES
871
872     local IFree=$(inodes_available)
873     if [ $IFree -lt $num_files ]; then
874       num_files=$IFree
875     fi
876
877     cancel_lru_locks mdc
878
879     local cmd1="${MDSRATE} ${MDSRATE_DEBUG} --mknod --dir $testdir"
880     local cmd2="--nfiles $num_files --filefmt 'f%%d'"
881     local cmd="$cmd1 $cmd2"
882     echo "+ $cmd"
883
884     mpi_run -np $((num_clients * 32)) -machinefile ${MACHINEFILE} $cmd
885
886     local rc=$?
887     if [ $rc != 0 ] ; then
888         error "mdsrate failed to create $rc"
889         return $rc
890     fi
891
892     local num_mntpts=$statahead_NUMMNTPTS
893     local mntpt_root=$TMP/mntpt/lustre
894     local mntopts=${MNTOPTSTATAHEAD:-$MOUNTOPT}
895
896     echo "Mounting $num_mntpts lustre clients starts on $clients"
897     trap "cleanup_statahead $clients $mntpt_root $num_mntpts" EXIT ERR
898     for i in $(seq 0 $num_mntpts); do
899         zconf_mount_clients $clients ${mntpt_root}$i "$mntopts" ||
900             error_exit "Failed to mount lustre on ${mntpt_root}$i on $clients"
901     done
902
903     do_rpc_nodes $clients cancel_lru_locks mdc
904
905     do_rpc_nodes $clients do_ls $mntpt_root $num_mntpts $dir
906
907     mdsrate_cleanup $((num_clients * 32)) $MACHINEFILE \
908         $num_files $testdir 'f%%d' --ignore
909
910     # use rm instead of rmdir because of
911     # testdir could contain the files created by someone else,
912     # or by previous run where is num_files prev > num_files current
913     rm -rf $testdir
914     cleanup_statahead $clients $mntpt_root $num_mntpts
915 }