1#!/bin/bash
2
3# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms of version 2 of the GNU General Public License as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it would be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12#
13# Further, this software is distributed without any warranty that it is
14# free of the rightful claim of any third person regarding infringement
15# or the like.  Any license provided herein, whether implied or
16# otherwise, applies only to this software file.  Patent licenses, if
17# any, provided herein do not apply to combinations of this program with
18# other software, or any other product whatsoever.
19#
20# You should have received a copy of the GNU General Public License along
21# with this program; if not, write the Free Software Foundation, Inc.,
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23#
24# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
25# Mountain View, CA  94043, or:
26#
27# http://www.sgi.com
28#
29# For further information regarding this notice, see:
30#
31# http://oss.sgi.com/projects/GenInfo/NoticeExplan/
32
33#
34# rwtest - a shell wrapper around iogen and doio
35#
36
37trap "exit 0" INT  # Until the smarter signal handler is engaged, below.
38
39Prog=${0##*/}
40
41iOpts=""
42dOpts=""
43LockRegion=""
44Nprocs=1
45Files=""
46Remove_Test_Files=""
47Files_To_Remove=""
48MPPrun=""
49export TCID="rwtest"
50export TST_TOTAL=1
51export TST_COUNT=1
52
53usage()
54{
55	echo "$Prog: [-chq] [-N name] [ iogen options ] [ doio options ] files" >&2
56}
57
58help()
59{
60	echo "\
61    -c           Cleanup test files created by this invocation on exit.
62                 Default is to leave them.
63    -h           This help - ignore all other options/arguments
64    -F		 Only process filenames - does not run iogen & doio.
65    -P Places	 Not used
66    -S Scenario  Execute an internal scenario.
67    -N Name	 Pan-style name to be printed with error messages.
68
69    Options passed through to iogen:
70    -[afiLmOstT] arg
71    -o
72    -q		 Set rwtest to be quiet and pass the flag on to iogen.
73
74    Options passed through to doio:
75    -D[rmMVUC] arg
76    -D[aekv]
77    -n nprocs    # procs to do simultanious io to the test files.
78                 Default is 1.  If -n is non-zero, doio's -k option (use
79		 file locking) is forced.
80
81    files        Files to test on.  File names have the following format:
82		 [ size: ] path
83		 [ free% [ max size ] : ] path
84		 If no size is specified, the files must exist
85                 and the contents will be overwritten if testing write or
86                 writea system calls.  If a size is supplied, an attempt to
87                 create/grow/shrink path to the desired size will be made.
88                 size is an integer which defaults to bytes, but may be
89                 suffixed by 'b', 'k', or 'm' for blocks (4096 byte units),
90	         kilobytes (1024 byte units), or megabytes (2^20 byte units).
91
92		 If the size is a percentage, df is used to find how much
93		 free space there is (in blocks), and uses that.  The maximum
94		 size is implied to be in blocks.
95" >&2
96}
97
98killkids()
99{
100	trap "killkids" INT
101	if [[ -z $didkids ]]
102	then
103		didkids=done
104		kill -INT -$$
105	fi
106}
107
108
109cleanup_and_exit()
110{
111	if [ -n "$Remove_Test_Files" ]
112	then
113		if [ -n "$Files_To_Remove" ]
114		then
115			rm -rf $Files_To_Remove
116		fi
117	fi
118
119	if [ $1 -ne 0 ]
120	then
121	    tst_resm TFAIL "Test failed"
122	    echo "Test failed"
123	else
124	    tst_resm TPASS "Test passed"
125	    echo "Test passed"
126	fi
127
128	exit $1
129}
130
131while (( $# > 0 ))
132do	case $1 in
133	-c)	Remove_Test_Files=yes
134		;;
135
136	-d)	debug=$2
137		shift
138		;;
139
140	-h)	help
141		exit 0
142		;;
143
144	-F)
145		opt_F="-F"	# only process filenames
146		;;
147
148	-P)
149		PLACES=$2
150		shift
151		;;
152
153	-S)	Scenario=$2
154		shift
155		opt_S="-S"
156		;;
157
158	-N)	Name="($2)"
159		TCID=$2
160		iOpts="$iOpts -N $2"
161		dOpts="$dOpts -N $2"
162		shift
163		;;
164
165	# iogen Options to pass thru ... options with an argument
166	-[afiLmOstT] )
167		iOpts="$iOpts $1 $2"
168		shift
169		;;
170
171	# iogen Options to pass thru ... just the option
172	-[o] )
173		iOpts="$iOpts $1"
174		;;
175
176	# iogen options to look at
177	-q)
178		iOpts="$iOpts $1"
179		Quiet=$1
180		;;
181
182	# doio Options to pass thru ... options with an argument
183	-D[rmMVUC] )
184		o=${1#-D}
185		dOpts="$dOpts -$o $2"
186		shift
187		;;
188
189	# doio options to pass thru ... just the options
190	-D[aekv] )
191		o=${1#-D}
192		dOpts="$dOpts -$o"
193		;;
194
195	# doio options to look at
196	-n | -Dn )
197		dOpts="$dOpts $1 $2"
198		# force file locking with > 1 process
199		if [[ $2 > 1 ]]
200		then
201			dOpts="$dOpts -k"
202		fi
203		opt_n="-n"
204		shift
205		;;
206
207	\? | -*)
208		echo "$Prog:  Illegal option $1" >&2
209		tst_resm TBROK "Illegal option $1"
210		exit 1
211		;;
212
213	*)
214		break
215		;;
216	esac
217	shift
218done
219
220#
221# Hard-Coded Scenario Specifications
222#
223# FSA		RAW I/O via FSA
224# MPPnnn	Run as a <nnn> sized MPP application
225# userstripe	create files using user striping
226#
227
228if [[ -n "$opt_S" ]]
229then
230	case $Scenario in
231
232	FSA )
233		# I/O via FSA
234		Flags="parallel"
235		Nprocs=1
236		LockRegion=""
237	;;
238
239	MPP* )
240		# use mpprun...  to cooperate with a batch system, this
241		# requires scanning mppview, etc.
242
243		NPE=${Scenario#MPP}
244		MPPrun=" mpprun -n $NPE "
245	;;
246	userstripe)
247		#create files using user striping
248		Oflags=O_PLACE,0xffffffffffffffff,1000
249	;;
250
251	places*)
252		FSIZE=${Scenario#places-}
253		oi="$IFS"
254		IFS=":"
255		set -- $PLACES
256		if [ $# -eq 0 ]
257		then
258			# "this isn't supposed to happen"
259			Files="25%:rwtest.$$"
260		else
261			IFS="$oi"
262			PL=${*}
263			for p in $PL
264			do
265				f="$f "${FSIZE}":"${p}"/rwtest$$"
266			done
267			set -- $f
268		fi
269	;;
270	esac
271fi
272
273#
274# If no files are specified ...
275#	check if PLACES is set; if so, put one file in each place
276#	otherwise generate one filename in the current directory.
277#
278
279if [ $# -eq 0 ]
280then
281	# put one file in each of $PLACES
282	Files="25%:rwtest.file"
283else
284	Files=$*
285fi
286
287#
288# use 'df -PB' to see how many blocks are available, apply a hard limit of
289# 1,000,000 blocks if no limit is specified
290#
291
292case "$(uname -s)" in
293	IRIX | IRIX64 )		dfOpts="-Pb"	;;
294	Linux)			dfOpts="-P"	;;
295	*)			dfOpts="-PB"	;;
296esac
297
298for f in $Files
299do
300	file=${f##*:}
301	if [ ! -f "$file" ]
302	then
303		Files_To_Remove="$Files_To_Remove $file"
304	fi
305
306	dir=$(dirname $file)
307	# create directory for file if non-existent
308	if [ ! -d "$dir" ]
309	then
310		mkdir -p $dir
311		Files_To_Remove="$Files_To_Remove $dir"
312	fi
313	size=${f%%:*}
314	if [[ $size = *%* ]]
315	then
316
317		typeset -i n=0
318		while (( n < ${#szcache[*]} ))
319		do
320			if [[ szcache[$n] = $dir ]]; then
321				break;
322			fi
323			n=n+1
324		done
325
326		if (( n < ${#szcache[*]} ))
327		then
328			blks=${szblks[$n]}
329		else
330			# If df is a symlink (to busybox) then do not pass the $dir and $dfOpts
331			# parameters because they don't work as expected
332                        if test -h $(which df)
333                           then
334                               dir=""; dfOpts="";
335                        fi
336
337			blks=$(df $dfOpts $dir |
338			(while read fs blks used avail cap mountpoint
339			 do
340				#echo $fs $blks $used $avail >&2
341				b=$avail
342			 done
343			 echo $b) )
344
345			# check if blks is a number, else set a default value for blks
346			default_sz=1000000
347			if [ $blks -eq $blks 2> /dev/null -a $blks -gt 0 ]
348			then
349
350				case $(uname) in
351				Linux)  blks=$( expr $blks / 2 ) ;;
352				esac
353
354				szcache[${#szcache[*]}+1]=$dir
355				szblks[${#szblks[*]}+1]=$blks
356
357				max=${size##*\%}
358				[ "x$max" = "x" ] && max=$default_sz
359				size=${size%%\%*}
360
361				case $(uname) in
362				IRIX*)
363				  sz=$( perl -le 'print int( '$blks' * '$size' / 100 )' )
364				  ;;
365				*)
366				  sz=$(expr \( $blks '*' $size \) / 100)
367				  ;;
368				esac
369
370				if [ $sz -gt $max ]
371				then
372					sz=$max
373				fi
374			else
375				sz=$default_sz
376			fi
377		fi
378		f=$sz"b:"$file
379	fi
380	F[${#F[*]}+1]=$f
381done
382
383Files=${F[*]}
384
385if [[ -z ${dOpts} ]]; then
386	dOpts=-av
387fi
388
389if [[ -n "$opt_F" ]]; then
390
391	echo $Files
392
393else
394
395	cmd="${LTPROOT}/testcases/bin/iogen ${iOpts} ${Files} | $MPPrun ${LTPROOT}/testcases/bin/doio ${dOpts}"
396
397	if [[ -z "$Quiet" ]]; then
398		echo $cmd
399	fi
400
401	trap "killkids" INT
402	trap "cleanup_and_exit 2" HUP
403
404	( ${LTPROOT}/testcases/bin/iogen ${iOpts} ${Files}
405	  r=$?
406	  if [ $r -ne 0 ]
407	  then
408		echo "$Prog$Name : iogen reported errors (r=$r)" >&2
409		tst_resm TFAIL "iogen reported errors (r=$r)"
410		kill -HUP $$
411	  fi
412	) | $MPPrun ${LTPROOT}/testcases/bin/doio ${dOpts}
413	r=$?
414	if [ $r -ne 0 ]
415	then
416		echo "$Prog$Name : doio reported errors (r=$r)" >&2
417		tst_resm TFAIL "doio reported errors (r=$r)"
418	fi
419
420	cleanup_and_exit $r
421fi
422