Whamcloud - gitweb
8e5a3cda8b005a014c3b0d136a37e55629a3e1ec
[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 ###
258 # short_nodename
259 #
260 # Find remote nodename, stripped of any domain, etc.
261 # 'hostname -s' is easy, but not implemented on all systems
262 short_nodename() {
263         local rname=$(do_node $1 "uname -n" || echo -1)
264         if [[ "$rname" = "-1" ]]; then
265                 rname=$1
266         fi
267         echo $(short_hostname $rname)
268 }
269
270 print_opts () {
271     local var
272
273     echo OPTIONS:
274
275     for i in $@; do
276         var=$i
277         echo "${var}=${!var}"
278     done
279     [ -e $MACHINEFILE ] && cat $MACHINEFILE
280 }
281
282 run_compilebench() {
283         # Space estimation:
284         # compile dir kernel-0  ~1GB
285         # required space        ~1GB * cbench_IDIRS
286
287     cbench_DIR=${cbench_DIR:-""}
288     cbench_IDIRS=${cbench_IDIRS:-2}
289     cbench_RUNS=${cbench_RUNS:-2}
290
291     print_opts cbench_DIR cbench_IDIRS cbench_RUNS
292
293     [ x$cbench_DIR = x ] &&
294         { skip_env "compilebench not found" && return; }
295
296     [ -e $cbench_DIR/compilebench ] || \
297         { skip_env "No compilebench build" && return; }
298
299         local space=$(df -P $DIR | tail -n 1 | awk '{ print $4 }')
300         if [[ $space -le $((1024 * 1024 * cbench_IDIRS)) ]]; then
301                 cbench_IDIRS=$((space / 1024 / 1024))
302                 [[ $cbench_IDIRS -eq 0 ]] &&
303                         skip_env "Need free space at least 1GB, have $space" &&
304                         return
305
306                 echo "free space=$space, reducing initial dirs to $cbench_IDIRS"
307         fi
308
309     # FIXME:
310     # t-f _base needs to be modifyed to set properly tdir
311     # for new "test_foo" functions names
312     # local testdir=$DIR/$tdir
313     local testdir=$DIR/d0.compilebench
314     mkdir -p $testdir
315
316     local savePWD=$PWD
317     cd $cbench_DIR
318     local cmd="./compilebench -D $testdir -i $cbench_IDIRS \
319         -r $cbench_RUNS --makej"
320
321     log "$cmd"
322
323     local rc=0
324     eval $cmd
325     rc=$?
326
327     cd $savePWD
328     [ $rc = 0 ] || error "compilebench failed: $rc"
329     rm -rf $testdir
330 }
331
332 run_metabench() {
333
334     METABENCH=${METABENCH:-$(which metabench 2> /dev/null || true)}
335     mbench_NFILES=${mbench_NFILES:-30400}
336     # threads per client
337     mbench_THREADS=${mbench_THREADS:-4}
338         mbench_OPTIONS=${mbench_OPTIONS:-}
339
340     [ x$METABENCH = x ] &&
341         { skip_env "metabench not found" && return; }
342
343     # FIXME
344     # Need space estimation here.
345
346     print_opts METABENCH clients mbench_NFILES mbench_THREADS
347
348     local testdir=$DIR/d0.metabench
349     mkdir -p $testdir
350     # mpi_run uses mpiuser
351     chmod 0777 $testdir
352
353     # -C             Run the file creation tests.
354     # -S             Run the file stat tests.
355     # -c nfile       Number of files to be used in each test.
356     # -k             Cleanup.  Remove the test directories.
357         local cmd="$METABENCH -w $testdir -c $mbench_NFILES -C -S -k $mbench_OPTIONS"
358     echo "+ $cmd"
359
360         # find out if we need to use srun by checking $SRUN_PARTITION
361         if [ "$SRUN_PARTITION" ]; then
362                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
363                         -n $((num_clients * mbench_THREADS)) \
364                         -p $SRUN_PARTITION -- $cmd
365         else
366                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
367                         -np $((num_clients * $mbench_THREADS)) $cmd
368         fi
369
370     local rc=$?
371     if [ $rc != 0 ] ; then
372         error "metabench failed! $rc"
373     fi
374     rm -rf $testdir
375 }
376
377 run_simul() {
378
379     SIMUL=${SIMUL:=$(which simul 2> /dev/null || true)}
380     # threads per client
381     simul_THREADS=${simul_THREADS:-2}
382     simul_REP=${simul_REP:-20}
383
384     if [ "$NFSCLIENT" ]; then
385         skip "skipped for NFSCLIENT mode"
386         return
387     fi
388
389     [ x$SIMUL = x ] &&
390         { skip_env "simul not found" && return; }
391
392     # FIXME
393     # Need space estimation here.
394
395     print_opts SIMUL clients simul_REP simul_THREADS
396
397     local testdir=$DIR/d0.simul
398     mkdir -p $testdir
399     # mpi_run uses mpiuser
400     chmod 0777 $testdir
401
402     # -n # : repeat each test # times
403     # -N # : repeat the entire set of tests # times
404
405     local cmd="$SIMUL -d $testdir -n $simul_REP -N $simul_REP"
406
407         echo "+ $cmd"
408         # find out if we need to use srun by checking $SRUN_PARTITION
409         if [ "$SRUN_PARTITION" ]; then
410                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
411                         -n $((num_clients * simul_THREADS)) -p $SRUN_PARTITION \
412                         -- $cmd
413         else
414                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
415                         -np $((num_clients * simul_THREADS)) $cmd
416         fi
417
418     local rc=$?
419     if [ $rc != 0 ] ; then
420         error "simul failed! $rc"
421     fi
422     rm -rf $testdir
423 }
424
425 run_mdtest() {
426
427     MDTEST=${MDTEST:=$(which mdtest 2> /dev/null || true)}
428     # threads per client
429     mdtest_THREADS=${mdtest_THREADS:-2}
430     mdtest_nFiles=${mdtest_nFiles:-"100000"}
431     # We devide the files by number of core
432     mdtest_nFiles=$((mdtest_nFiles/mdtest_THREADS/num_clients))
433     mdtest_iteration=${mdtest_iteration:-1}
434
435     local type=${1:-"ssf"}
436
437     if [ "$NFSCLIENT" ]; then
438         skip "skipped for NFSCLIENT mode"
439         return
440     fi
441
442     [ x$MDTEST = x ] &&
443         { skip_env "mdtest not found" && return; }
444
445     # FIXME
446     # Need space estimation here.
447
448     print_opts MDTEST mdtest_iteration mdtest_THREADS mdtest_nFiles
449
450     local testdir=$DIR/d0.mdtest
451     mkdir -p $testdir
452     # mpi_run uses mpiuser
453     chmod 0777 $testdir
454
455     # -i # : repeat each test # times
456     # -d   : test dir
457     # -n # : number of file/dir to create/stat/remove
458     # -u   : each process create/stat/remove individually
459
460     local cmd="$MDTEST -d $testdir -i $mdtest_iteration -n $mdtest_nFiles"
461     [ $type = "fpp" ] && cmd="$cmd -u"
462
463         echo "+ $cmd"
464         # find out if we need to use srun by checking $SRUN_PARTITION
465         if [ "$SRUN_PARTITION" ]; then
466                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
467                         -n $((num_clients * mdtest_THREADS)) \
468                         -p $SRUN_PARTITION -- $cmd
469         else
470                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
471                         -np $((num_clients * mdtest_THREADS)) $cmd
472         fi
473
474     local rc=$?
475     if [ $rc != 0 ] ; then
476         error "mdtest failed! $rc"
477     fi
478     rm -rf $testdir
479 }
480
481 run_connectathon() {
482
483     cnt_DIR=${cnt_DIR:-""}
484     cnt_NRUN=${cnt_NRUN:-10}
485
486     print_opts cnt_DIR cnt_NRUN
487
488     [ x$cnt_DIR = x ] &&
489         { skip_env "connectathon dir not found" && return; }
490
491     [ -e $cnt_DIR/runtests ] || \
492         { skip_env "No connectathon runtests found" && return; }
493
494     local testdir=$DIR/d0.connectathon
495     mkdir -p $testdir
496
497     local savePWD=$PWD
498     cd $cnt_DIR
499
500     #
501     # cthon options (must be in this order)
502     #
503     # -N numpasses - will be passed to the runtests script.  This argument
504     #         is optional.  It specifies the number of times to run
505     #         through the tests.
506     #
507     # One of these test types
508     #    -b  basic
509     #    -g  general
510     #    -s  special
511     #    -l  lock
512     #    -a  all of the above
513     #
514     # -f      a quick functionality test
515     #
516
517     tests="-b -g -s"
518     # Include lock tests unless we're running on nfsv4
519     local fstype=$(df -TP $testdir | awk 'NR==2  {print $2}')
520     echo "$testdir: $fstype"
521     if [[ $fstype != "nfs4" ]]; then
522         tests="$tests -l"
523     fi
524     echo "tests: $tests"
525     for test in $tests; do
526         local cmd="./runtests -N $cnt_NRUN $test -f $testdir"
527         local rc=0
528
529         log "$cmd"
530         eval $cmd
531         rc=$?
532         [ $rc = 0 ] || error "connectathon failed: $rc"
533     done
534
535     cd $savePWD
536     rm -rf $testdir
537 }
538
539 run_ior() {
540     local type=${1:="ssf"}
541
542     IOR=${IOR:-$(which IOR 2> /dev/null || true)}
543     # threads per client
544     ior_THREADS=${ior_THREADS:-2}
545     ior_iteration=${ior_iteration:-1}
546     ior_blockSize=${ior_blockSize:-6}   # GB
547     ior_xferSize=${ior_xferSize:-2m}
548     ior_type=${ior_type:-POSIX}
549     ior_DURATION=${ior_DURATION:-30}    # minutes
550
551     [ x$IOR = x ] &&
552         { skip_env "IOR not found" && return; }
553
554     local space=$(df -P $DIR | tail -n 1 | awk '{ print $4 }')
555     local total_threads=$(( num_clients * ior_THREADS ))
556     echo "+ $ior_blockSize * 1024 * 1024 * $total_threads "
557     if [ $((space / 2)) -le \
558         $(( ior_blockSize * 1024 * 1024 * total_threads)) ]; then
559         echo "+ $space * 9/10 / 1024 / 1024 / $num_clients / $ior_THREADS"
560         ior_blockSize=$(( space /2 /1024 /1024 / num_clients / ior_THREADS ))
561         [ $ior_blockSize = 0 ] && \
562             skip_env "Need free space more than $((2 * total_threads))GB: \
563                 $((total_threads *1024 *1024*2)), have $space" && return
564
565         local reduced_size="$num_clients x $ior_THREADS x $ior_blockSize"
566         echo "free space=$space, Need: $reduced_size GB"
567         echo "(blockSize reduced to $ior_blockSize Gb)"
568     fi
569
570     print_opts IOR ior_THREADS ior_DURATION MACHINEFILE
571
572     local testdir=$DIR/d0.ior.$type
573     mkdir -p $testdir
574     # mpi_run uses mpiuser
575     chmod 0777 $testdir
576     if [ "$NFSCLIENT" ]; then
577         setstripe_nfsserver $testdir -c -1 ||
578             { error "setstripe on nfsserver failed" && return 1; }
579     else
580         $LFS setstripe $testdir -c -1 ||
581             { error "setstripe failed" && return 2; }
582     fi
583     #
584     # -b N  blockSize --
585     #       contiguous bytes to write per task (e.g.: 8, 4k, 2m, 1g)"
586     # -o S  testFileName
587     # -t N  transferSize -- size of transfer in bytes (e.g.: 8, 4k, 2m, 1g)"
588     # -w    writeFile -- write file"
589     # -r    readFile -- read existing file"
590     # -W    checkWrite -- check read after write"
591     # -C    reorderTasks -- changes task ordering to n+1 ordering for readback
592     # -T    maxTimeDuration -- max time in minutes to run tests"
593     # -k    keepFile -- keep testFile(s) on program exit
594
595     local cmd="$IOR -a $ior_type -b ${ior_blockSize}g -o $testdir/iorData \
596          -t $ior_xferSize -v -C -w -r -W -i $ior_iteration -T $ior_DURATION -k"
597     [ $type = "fpp" ] && cmd="$cmd -F"
598
599         echo "+ $cmd"
600         # find out if we need to use srun by checking $SRUN_PARTITION
601         if [ "$SRUN_PARTITION" ]; then
602                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
603                         -n $((num_clients * ior_THREADS)) -p $SRUN_PARTITION \
604                         -- $cmd
605         else
606                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
607                         -np $((num_clients * $ior_THREADS)) $cmd
608         fi
609
610     local rc=$?
611     if [ $rc != 0 ] ; then
612         error "ior failed! $rc"
613     fi
614     rm -rf $testdir
615 }
616
617 run_mib() {
618
619     MIB=${MIB:=$(which mib 2> /dev/null || true)}
620     # threads per client
621     mib_THREADS=${mib_THREADS:-2}
622     mib_xferSize=${mib_xferSize:-1m}
623     mib_xferLimit=${mib_xferLimit:-5000}
624     mib_timeLimit=${mib_timeLimit:-300}
625
626     if [ "$NFSCLIENT" ]; then
627         skip "skipped for NFSCLIENT mode"
628         return
629     fi
630
631     [ x$MIB = x ] &&
632         { skip_env "MIB not found" && return; }
633
634     print_opts MIB mib_THREADS mib_xferSize mib_xferLimit mib_timeLimit \
635         MACHINEFILE
636
637     local testdir=$DIR/d0.mib
638     mkdir -p $testdir
639     # mpi_run uses mpiuser
640     chmod 0777 $testdir
641     $LFS setstripe $testdir -c -1 ||
642         { error "setstripe failed" && return 2; }
643     #
644     # -I    Show intermediate values in output
645     # -H    Show headers in output
646     # -L    Do not issue new system calls after this many seconds
647     # -s    Use system calls of this size
648     # -t    test dir
649     # -l    Issue no more than this many system calls
650     local cmd="$MIB -t $testdir -s $mib_xferSize -l $mib_xferLimit \
651         -L $mib_timeLimit -HI -p mib.$(date +%Y%m%d%H%M%S)"
652
653         echo "+ $cmd"
654         # find out if we need to use srun by checking $SRUN_PARTITION
655         if [ "$SRUN_PARTITION" ]; then
656                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
657                         -n $((num_clients * mib_THREADS)) -p $SRUN_PARTITION \
658                         -- $cmd
659         else
660                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
661                         -np $((num_clients * mib_THREADS)) $cmd
662         fi
663
664     local rc=$?
665     if [ $rc != 0 ] ; then
666         error "mib failed! $rc"
667     fi
668     rm -rf $testdir
669 }
670
671 run_cascading_rw() {
672
673     CASC_RW=${CASC_RW:-$(which cascading_rw 2> /dev/null || true)}
674     # threads per client
675     casc_THREADS=${casc_THREADS:-2}
676     casc_REP=${casc_REP:-300}
677
678     if [ "$NFSCLIENT" ]; then
679         skip "skipped for NFSCLIENT mode"
680         return
681     fi
682
683     [ x$CASC_RW = x ] &&
684         { skip_env "cascading_rw not found" && return; }
685
686     # FIXME
687     # Need space estimation here.
688
689     print_opts CASC_RW clients casc_THREADS casc_REP MACHINEFILE
690
691     local testdir=$DIR/d0.cascading_rw
692     mkdir -p $testdir
693     # mpi_run uses mpiuser
694     chmod 0777 $testdir
695
696     # -g: debug mode
697     # -n: repeat test # times
698
699     local cmd="$CASC_RW -g -d $testdir -n $casc_REP"
700
701         echo "+ $cmd"
702         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
703                 -np $((num_clients * $casc_THREADS)) $cmd
704
705     local rc=$?
706     if [ $rc != 0 ] ; then
707         error "cascading_rw failed! $rc"
708     fi
709     rm -rf $testdir
710 }
711
712 run_write_append_truncate() {
713
714     # threads per client
715     write_THREADS=${write_THREADS:-8}
716     write_REP=${write_REP:-10000}
717
718     if [ "$NFSCLIENT" ]; then
719         skip "skipped for NFSCLIENT mode"
720         return
721     fi
722
723     # location is lustre/tests dir
724     if ! which write_append_truncate > /dev/null 2>&1 ; then
725         skip_env "write_append_truncate not found"
726         return
727     fi
728
729     # FIXME
730     # Need space estimation here.
731
732     local testdir=$DIR/d0.write_append_truncate
733     local file=$testdir/f0.wat
734
735     print_opts clients write_REP write_THREADS MACHINEFILE
736
737     mkdir -p $testdir
738     # mpi_run uses mpiuser
739     chmod 0777 $testdir
740
741     local cmd="write_append_truncate -n $write_REP $file"
742
743         echo "+ $cmd"
744         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
745                 -np $((num_clients * $write_THREADS)) $cmd
746
747     local rc=$?
748     if [ $rc != 0 ] ; then
749         error "write_append_truncate failed! $rc"
750         return $rc
751     fi
752     rm -rf $testdir
753 }
754
755 run_write_disjoint() {
756
757     WRITE_DISJOINT=${WRITE_DISJOINT:-$(which write_disjoint \
758         2> /dev/null || true)}
759     # threads per client
760     wdisjoint_THREADS=${wdisjoint_THREADS:-4}
761     wdisjoint_REP=${wdisjoint_REP:-10000}
762
763     if [ "$NFSCLIENT" ]; then
764         skip "skipped for NFSCLIENT mode"
765         return
766     fi
767
768     [ x$WRITE_DISJOINT = x ] &&
769         { skip_env "write_disjoint not found" && return; }
770
771     # FIXME
772     # Need space estimation here.
773
774     print_opts WRITE_DISJOINT clients wdisjoint_THREADS wdisjoint_REP \
775         MACHINEFILE
776     local testdir=$DIR/d0.write_disjoint
777     mkdir -p $testdir
778     # mpi_run uses mpiuser
779     chmod 0777 $testdir
780
781     local cmd="$WRITE_DISJOINT -f $testdir/file -n $wdisjoint_REP"
782
783         echo "+ $cmd"
784         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
785                 -np $((num_clients * $wdisjoint_THREADS)) $cmd
786
787     local rc=$?
788     if [ $rc != 0 ] ; then
789         error "write_disjoint failed! $rc"
790     fi
791     rm -rf $testdir
792 }
793
794 run_parallel_grouplock() {
795
796     PARALLEL_GROUPLOCK=${PARALLEL_GROUPLOCK:-$(which parallel_grouplock \
797         2> /dev/null || true)}
798     parallel_grouplock_MINTASKS=${parallel_grouplock_MINTASKS:-5}
799
800     if [ "$NFSCLIENT" ]; then
801         skip "skipped for NFSCLIENT mode"
802         return
803     fi
804
805     [ x$PARALLEL_GROUPLOCK = x ] &&
806         { skip "PARALLEL_GROUPLOCK not found" && return; }
807
808     print_opts clients parallel_grouplock_MINTASKS MACHINEFILE
809
810     local testdir=$DIR/d0.parallel_grouplock
811     mkdir -p $testdir
812     # mpi_run uses mpiuser
813     chmod 0777 $testdir
814
815     local cmd
816     local status=0
817     local subtest
818         for i in $(seq 12); do
819                 subtest="-t $i"
820                 local cmd="$PARALLEL_GROUPLOCK -g -v -d $testdir $subtest"
821                 echo "+ $cmd"
822
823                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
824                         -np $parallel_grouplock_MINTASKS $cmd
825                 local rc=$?
826                 if [ $rc != 0 ] ; then
827                         error_noexit "parallel_grouplock subtests $subtest " \
828                                      "failed! $rc"
829                 else
830                         echo "parallel_grouplock subtests $subtest PASS"
831                 fi
832                 let status=$((status + rc))
833                 # clear debug to collect one log per one test
834                 do_nodes $(comma_list $(nodes_list)) lctl clear
835         done
836         [ $status -eq 0 ] || error "parallel_grouplock status: $status"
837         rm -rf $testdir
838 }
839
840 cleanup_statahead () {
841     trap 0
842
843     local clients=$1
844     local mntpt_root=$2
845     local num_mntpts=$3
846
847     for i in $(seq 0 $num_mntpts);do
848         zconf_umount_clients $clients ${mntpt_root}$i ||
849             error_exit "Failed to umount lustre on ${mntpt_root}$i"
850     done
851 }
852
853 run_statahead () {
854
855     statahead_NUMMNTPTS=${statahead_NUMMNTPTS:-5}
856     statahead_NUMFILES=${statahead_NUMFILES:-500000}
857
858     if [[ -n $NFSCLIENT ]]; then
859         skip "Statahead testing is not supported on NFS clients."
860         return 0
861     fi
862
863     [ x$MDSRATE = x ] &&
864         { skip_env "mdsrate not found" && return; }
865
866     print_opts MDSRATE clients statahead_NUMMNTPTS statahead_NUMFILES
867
868     # create large dir
869
870     # do not use default "d[0-9]*" dir name
871     # to avoid of rm $statahead_NUMFILES (500k) files in t-f cleanup
872     local dir=dstatahead
873     local testdir=$DIR/$dir
874
875     # cleanup only if dir exists
876     # cleanup only $statahead_NUMFILES number of files
877     # ignore the other files created by someone else
878     [ -d $testdir ] &&
879         mdsrate_cleanup $((num_clients * 32)) $MACHINEFILE \
880             $statahead_NUMFILES $testdir 'f%%d' --ignore
881
882     mkdir -p $testdir
883     # mpi_run uses mpiuser
884     chmod 0777 $testdir
885
886     local num_files=$statahead_NUMFILES
887
888     local IFree=$(inodes_available)
889     if [ $IFree -lt $num_files ]; then
890       num_files=$IFree
891     fi
892
893     cancel_lru_locks mdc
894
895     local cmd1="${MDSRATE} ${MDSRATE_DEBUG} --mknod --dir $testdir"
896     local cmd2="--nfiles $num_files --filefmt 'f%%d'"
897     local cmd="$cmd1 $cmd2"
898     echo "+ $cmd"
899
900         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
901                 -np $((num_clients * 32)) $cmd
902
903     local rc=$?
904     if [ $rc != 0 ] ; then
905         error "mdsrate failed to create $rc"
906         return $rc
907     fi
908
909     local num_mntpts=$statahead_NUMMNTPTS
910     local mntpt_root=$TMP/mntpt/lustre
911     local mntopts=$MNTOPTSTATAHEAD
912
913     echo "Mounting $num_mntpts lustre clients starts on $clients"
914     trap "cleanup_statahead $clients $mntpt_root $num_mntpts" EXIT ERR
915     for i in $(seq 0 $num_mntpts); do
916         zconf_mount_clients $clients ${mntpt_root}$i "$mntopts" ||
917             error_exit "Failed to mount lustre on ${mntpt_root}$i on $clients"
918     done
919
920     do_rpc_nodes $clients cancel_lru_locks mdc
921
922     do_rpc_nodes $clients do_ls $mntpt_root $num_mntpts $dir
923
924     mdsrate_cleanup $((num_clients * 32)) $MACHINEFILE \
925         $num_files $testdir 'f%%d' --ignore
926
927     # use rm instead of rmdir because of
928     # testdir could contain the files created by someone else,
929     # or by previous run where is num_files prev > num_files current
930     rm -rf $testdir
931     cleanup_statahead $clients $mntpt_root $num_mntpts
932 }