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