Whamcloud - gitweb
23ff2a435a67215bde59166c0a1e2051421df340
[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=$(lfs_df $DIR | awk '/^filesystem/{ 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
339     [ x$METABENCH = x ] &&
340         { skip_env "metabench not found" && return; }
341
342     # FIXME
343     # Need space estimation here.
344
345     print_opts METABENCH clients mbench_NFILES mbench_THREADS
346
347     local testdir=$DIR/d0.metabench
348     mkdir -p $testdir
349     # mpi_run uses mpiuser
350     chmod 0777 $testdir
351
352     # -C             Run the file creation tests.
353     # -S             Run the file stat tests.
354     # -c nfile       Number of files to be used in each test.
355     # -k             Cleanup.  Remove the test directories.
356     local cmd="$METABENCH -w $testdir -c $mbench_NFILES -C -S -k"
357     echo "+ $cmd"
358
359         # find out if we need to use srun by checking $SRUN_PARTITION
360         if [ "$SRUN_PARTITION" ]; then
361                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
362                         -n $((num_clients * mbench_THREADS)) \
363                         -p $SRUN_PARTITION -- $cmd
364         else
365                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
366                         -np $((num_clients * $mbench_THREADS)) $cmd
367         fi
368
369     local rc=$?
370     if [ $rc != 0 ] ; then
371         error "metabench failed! $rc"
372     fi
373     rm -rf $testdir
374 }
375
376 run_simul() {
377
378     SIMUL=${SIMUL:=$(which simul 2> /dev/null || true)}
379     # threads per client
380     simul_THREADS=${simul_THREADS:-2}
381     simul_REP=${simul_REP:-20}
382
383     if [ "$NFSCLIENT" ]; then
384         skip "skipped for NFSCLIENT mode"
385         return
386     fi
387
388     [ x$SIMUL = x ] &&
389         { skip_env "simul not found" && return; }
390
391     # FIXME
392     # Need space estimation here.
393
394     print_opts SIMUL clients simul_REP simul_THREADS
395
396     local testdir=$DIR/d0.simul
397     mkdir -p $testdir
398     # mpi_run uses mpiuser
399     chmod 0777 $testdir
400
401     # -n # : repeat each test # times
402     # -N # : repeat the entire set of tests # times
403
404     local cmd="$SIMUL -d $testdir -n $simul_REP -N $simul_REP"
405
406         echo "+ $cmd"
407         # find out if we need to use srun by checking $SRUN_PARTITION
408         if [ "$SRUN_PARTITION" ]; then
409                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
410                         -n $((num_clients * simul_THREADS)) -p $SRUN_PARTITION \
411                         -- $cmd
412         else
413                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
414                         -np $((num_clients * simul_THREADS)) $cmd
415         fi
416
417     local rc=$?
418     if [ $rc != 0 ] ; then
419         error "simul failed! $rc"
420     fi
421     rm -rf $testdir
422 }
423
424 run_mdtest() {
425
426     MDTEST=${MDTEST:=$(which mdtest 2> /dev/null || true)}
427     # threads per client
428     mdtest_THREADS=${mdtest_THREADS:-2}
429     mdtest_nFiles=${mdtest_nFiles:-"100000"}
430     # We devide the files by number of core
431     mdtest_nFiles=$((mdtest_nFiles/mdtest_THREADS/num_clients))
432     mdtest_iteration=${mdtest_iteration:-1}
433
434     local type=${1:-"ssf"}
435
436     if [ "$NFSCLIENT" ]; then
437         skip "skipped for NFSCLIENT mode"
438         return
439     fi
440
441     [ x$MDTEST = x ] &&
442         { skip_env "mdtest not found" && return; }
443
444     # FIXME
445     # Need space estimation here.
446
447     print_opts MDTEST mdtest_iteration mdtest_THREADS mdtest_nFiles
448
449     local testdir=$DIR/d0.mdtest
450     mkdir -p $testdir
451     # mpi_run uses mpiuser
452     chmod 0777 $testdir
453
454     # -i # : repeat each test # times
455     # -d   : test dir
456     # -n # : number of file/dir to create/stat/remove
457     # -u   : each process create/stat/remove individually
458
459     local cmd="$MDTEST -d $testdir -i $mdtest_iteration -n $mdtest_nFiles"
460     [ $type = "fpp" ] && cmd="$cmd -u"
461
462         echo "+ $cmd"
463         # find out if we need to use srun by checking $SRUN_PARTITION
464         if [ "$SRUN_PARTITION" ]; then
465                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
466                         -n $((num_clients * mdtest_THREADS)) \
467                         -p $SRUN_PARTITION -- $cmd
468         else
469                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
470                         -np $((num_clients * mdtest_THREADS)) $cmd
471         fi
472
473     local rc=$?
474     if [ $rc != 0 ] ; then
475         error "mdtest failed! $rc"
476     fi
477     rm -rf $testdir
478 }
479
480 run_connectathon() {
481
482     cnt_DIR=${cnt_DIR:-""}
483     cnt_NRUN=${cnt_NRUN:-10}
484
485     print_opts cnt_DIR cnt_NRUN
486
487     [ x$cnt_DIR = x ] &&
488         { skip_env "connectathon dir not found" && return; }
489
490     [ -e $cnt_DIR/runtests ] || \
491         { skip_env "No connectathon runtests found" && return; }
492
493     local testdir=$DIR/d0.connectathon
494     mkdir -p $testdir
495
496     local savePWD=$PWD
497     cd $cnt_DIR
498
499     #
500     # cthon options (must be in this order)
501     #
502     # -N numpasses - will be passed to the runtests script.  This argument
503     #         is optional.  It specifies the number of times to run
504     #         through the tests.
505     #
506     # One of these test types
507     #    -b  basic
508     #    -g  general
509     #    -s  special
510     #    -l  lock
511     #    -a  all of the above
512     #
513     # -f      a quick functionality test
514     #
515
516     tests="-b -g -s"
517     # Include lock tests unless we're running on nfsv4
518     local fstype=$(df -TP $testdir | awk 'NR==2  {print $2}')
519     echo "$testdir: $fstype"
520     if [[ $fstype != "nfs4" ]]; then
521         tests="$tests -l"
522     fi
523     echo "tests: $tests"
524     for test in $tests; do
525         local cmd="./runtests -N $cnt_NRUN $test -f $testdir"
526         local rc=0
527
528         log "$cmd"
529         eval $cmd
530         rc=$?
531         [ $rc = 0 ] || error "connectathon failed: $rc"
532     done
533
534     cd $savePWD
535     rm -rf $testdir
536 }
537
538 run_ior() {
539     local type=${1:="ssf"}
540
541     IOR=${IOR:-$(which IOR 2> /dev/null || true)}
542     # threads per client
543     ior_THREADS=${ior_THREADS:-2}
544     ior_iteration=${ior_iteration:-1}
545     ior_blockSize=${ior_blockSize:-6}   # GB
546     ior_xferSize=${ior_xferSize:-2m}
547     ior_type=${ior_type:-POSIX}
548     ior_DURATION=${ior_DURATION:-30}    # minutes
549
550     [ x$IOR = x ] &&
551         { skip_env "IOR not found" && return; }
552
553     local space=$(df -P $DIR | tail -n 1 | awk '{ print $4 }')
554     local total_threads=$(( num_clients * ior_THREADS ))
555     echo "+ $ior_blockSize * 1024 * 1024 * $total_threads "
556     if [ $((space / 2)) -le \
557         $(( ior_blockSize * 1024 * 1024 * total_threads)) ]; then
558         echo "+ $space * 9/10 / 1024 / 1024 / $num_clients / $ior_THREADS"
559         ior_blockSize=$(( space /2 /1024 /1024 / num_clients / ior_THREADS ))
560         [ $ior_blockSize = 0 ] && \
561             skip_env "Need free space more than $((2 * total_threads))GB: \
562                 $((total_threads *1024 *1024*2)), have $space" && return
563
564         local reduced_size="$num_clients x $ior_THREADS x $ior_blockSize"
565         echo "free space=$space, Need: $reduced_size GB"
566         echo "(blockSize reduced to $ior_blockSize Gb)"
567     fi
568
569     print_opts IOR ior_THREADS ior_DURATION MACHINEFILE
570
571     local testdir=$DIR/d0.ior.$type
572     mkdir -p $testdir
573     # mpi_run uses mpiuser
574     chmod 0777 $testdir
575     if [ "$NFSCLIENT" ]; then
576         setstripe_nfsserver $testdir -c -1 ||
577             { error "setstripe on nfsserver failed" && return 1; }
578     else
579         $LFS setstripe $testdir -c -1 ||
580             { error "setstripe failed" && return 2; }
581     fi
582     #
583     # -b N  blockSize --
584     #       contiguous bytes to write per task (e.g.: 8, 4k, 2m, 1g)"
585     # -o S  testFileName
586     # -t N  transferSize -- size of transfer in bytes (e.g.: 8, 4k, 2m, 1g)"
587     # -w    writeFile -- write file"
588     # -r    readFile -- read existing file"
589     # -T    maxTimeDuration -- max time in minutes to run tests"
590     # -k    keepFile -- keep testFile(s) on program exit
591
592     local cmd="$IOR -a $ior_type -b ${ior_blockSize}g -o $testdir/iorData \
593          -t $ior_xferSize -v -w -r -i $ior_iteration -T $ior_DURATION -k"
594     [ $type = "fpp" ] && cmd="$cmd -F"
595
596         echo "+ $cmd"
597         # find out if we need to use srun by checking $SRUN_PARTITION
598         if [ "$SRUN_PARTITION" ]; then
599                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
600                         -n $((num_clients * ior_THREADS)) -p $SRUN_PARTITION \
601                         -- $cmd
602         else
603                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
604                         -np $((num_clients * $ior_THREADS)) $cmd
605         fi
606
607     local rc=$?
608     if [ $rc != 0 ] ; then
609         error "ior failed! $rc"
610     fi
611     rm -rf $testdir
612 }
613
614 run_mib() {
615
616     MIB=${MIB:=$(which mib 2> /dev/null || true)}
617     # threads per client
618     mib_THREADS=${mib_THREADS:-2}
619     mib_xferSize=${mib_xferSize:-1m}
620     mib_xferLimit=${mib_xferLimit:-5000}
621     mib_timeLimit=${mib_timeLimit:-300}
622
623     if [ "$NFSCLIENT" ]; then
624         skip "skipped for NFSCLIENT mode"
625         return
626     fi
627
628     [ x$MIB = x ] &&
629         { skip_env "MIB not found" && return; }
630
631     print_opts MIB mib_THREADS mib_xferSize mib_xferLimit mib_timeLimit \
632         MACHINEFILE
633
634     local testdir=$DIR/d0.mib
635     mkdir -p $testdir
636     # mpi_run uses mpiuser
637     chmod 0777 $testdir
638     $LFS setstripe $testdir -c -1 ||
639         { error "setstripe failed" && return 2; }
640     #
641     # -I    Show intermediate values in output
642     # -H    Show headers in output
643     # -L    Do not issue new system calls after this many seconds
644     # -s    Use system calls of this size
645     # -t    test dir
646     # -l    Issue no more than this many system calls
647     local cmd="$MIB -t $testdir -s $mib_xferSize -l $mib_xferLimit \
648         -L $mib_timeLimit -HI -p mib.$(date +%Y%m%d%H%M%S)"
649
650         echo "+ $cmd"
651         # find out if we need to use srun by checking $SRUN_PARTITION
652         if [ "$SRUN_PARTITION" ]; then
653                 $SRUN $SRUN_OPTIONS -D $testdir -w $clients -N $num_clients \
654                         -n $((num_clients * mib_THREADS)) -p $SRUN_PARTITION \
655                         -- $cmd
656         else
657                 mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
658                         -np $((num_clients * mib_THREADS)) $cmd
659         fi
660
661     local rc=$?
662     if [ $rc != 0 ] ; then
663         error "mib failed! $rc"
664     fi
665     rm -rf $testdir
666 }
667
668 run_cascading_rw() {
669
670     CASC_RW=${CASC_RW:-$(which cascading_rw 2> /dev/null || true)}
671     # threads per client
672     casc_THREADS=${casc_THREADS:-2}
673     casc_REP=${casc_REP:-300}
674
675     if [ "$NFSCLIENT" ]; then
676         skip "skipped for NFSCLIENT mode"
677         return
678     fi
679
680     [ x$CASC_RW = x ] &&
681         { skip_env "cascading_rw not found" && return; }
682
683     # FIXME
684     # Need space estimation here.
685
686     print_opts CASC_RW clients casc_THREADS casc_REP MACHINEFILE
687
688     local testdir=$DIR/d0.cascading_rw
689     mkdir -p $testdir
690     # mpi_run uses mpiuser
691     chmod 0777 $testdir
692
693     # -g: debug mode
694     # -n: repeat test # times
695
696     local cmd="$CASC_RW -g -d $testdir -n $casc_REP"
697
698         echo "+ $cmd"
699         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
700                 -np $((num_clients * $casc_THREADS)) $cmd
701
702     local rc=$?
703     if [ $rc != 0 ] ; then
704         error "cascading_rw failed! $rc"
705     fi
706     rm -rf $testdir
707 }
708
709 run_write_append_truncate() {
710
711     # threads per client
712     write_THREADS=${write_THREADS:-8}
713     write_REP=${write_REP:-10000}
714
715     if [ "$NFSCLIENT" ]; then
716         skip "skipped for NFSCLIENT mode"
717         return
718     fi
719
720     # location is lustre/tests dir
721     if ! which write_append_truncate > /dev/null 2>&1 ; then
722         skip_env "write_append_truncate not found"
723         return
724     fi
725
726     # FIXME
727     # Need space estimation here.
728
729     local testdir=$DIR/d0.write_append_truncate
730     local file=$testdir/f0.wat
731
732     print_opts clients write_REP write_THREADS MACHINEFILE
733
734     mkdir -p $testdir
735     # mpi_run uses mpiuser
736     chmod 0777 $testdir
737
738     local cmd="write_append_truncate -n $write_REP $file"
739
740         echo "+ $cmd"
741         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
742                 -np $((num_clients * $write_THREADS)) $cmd
743
744     local rc=$?
745     if [ $rc != 0 ] ; then
746         error "write_append_truncate failed! $rc"
747         return $rc
748     fi
749     rm -rf $testdir
750 }
751
752 run_write_disjoint() {
753
754     WRITE_DISJOINT=${WRITE_DISJOINT:-$(which write_disjoint \
755         2> /dev/null || true)}
756     # threads per client
757     wdisjoint_THREADS=${wdisjoint_THREADS:-4}
758     wdisjoint_REP=${wdisjoint_REP:-10000}
759
760     if [ "$NFSCLIENT" ]; then
761         skip "skipped for NFSCLIENT mode"
762         return
763     fi
764
765     [ x$WRITE_DISJOINT = x ] &&
766         { skip_env "write_disjoint not found" && return; }
767
768     # FIXME
769     # Need space estimation here.
770
771     print_opts WRITE_DISJOINT clients wdisjoint_THREADS wdisjoint_REP \
772         MACHINEFILE
773     local testdir=$DIR/d0.write_disjoint
774     mkdir -p $testdir
775     # mpi_run uses mpiuser
776     chmod 0777 $testdir
777
778     local cmd="$WRITE_DISJOINT -f $testdir/file -n $wdisjoint_REP"
779
780         echo "+ $cmd"
781         mpi_run ${MACHINEFILE_OPTION} ${MACHINEFILE} \
782                 -np $((num_clients * $wdisjoint_THREADS)) $cmd
783
784     local rc=$?
785     if [ $rc != 0 ] ; then
786         error "write_disjoint failed! $rc"
787     fi
788     rm -rf $testdir
789 }
790
791 run_parallel_grouplock() {
792
793     PARALLEL_GROUPLOCK=${PARALLEL_GROUPLOCK:-$(which parallel_grouplock \
794         2> /dev/null || true)}
795     parallel_grouplock_MINTASKS=${parallel_grouplock_MINTASKS:-5}
796
797     if [ "$NFSCLIENT" ]; then
798         skip "skipped for NFSCLIENT mode"
799         return
800     fi
801
802     [ x$PARALLEL_GROUPLOCK = x ] &&
803         { skip "PARALLEL_GROUPLOCK not found" && return; }
804
805     print_opts clients parallel_grouplock_MINTASKS MACHINEFILE
806
807     local testdir=$DIR/d0.parallel_grouplock
808     mkdir -p $testdir
809     # mpi_run uses mpiuser
810     chmod 0777 $testdir
811
812     do_nodes $clients "lctl set_param llite.*.max_rw_chunk=0" ||
813         error "set_param max_rw_chunk=0 failed "
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:-$MOUNTOPT}
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 }