Add rwtest case that Steve found an unwritten extent/direct IO bug with.
[xfstests-dev.git] / ltp / rwtest.sh
1 #!/bin/sh
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., 59
22 # Temple Place - Suite 330, Boston MA 02111-1307, 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
37 trap "exit 0" INT  # Until the smarter signal handler is engaged, below.
38
39 Prog=$(basename $0)
40
41 iOpts=""
42 dOpts=""
43 LockRegion=""
44 Nprocs=1
45 Files=""
46 Remove_Test_Files=""
47 Files_To_Remove=""
48 MPPrun=""
49
50 usage()
51 {
52         echo "$Prog: [-chq] [-N name] [ iogen options ] [ doio options ] files" >&2
53 }
54
55 help()
56 {
57         echo "\
58     -c           Cleanup test files created by this invocation on exit.
59                  Default is to leave them.  
60     -h           This help - ignore all other options/arguments
61     -F           Only process filenames - does not run iogen & doio.
62     -P Places    Not used
63     -S Scenario  Execute an internal scenario.
64     -N Name      Pan-style name to be printed with error messages.
65
66     Options passed through to iogen:
67     -[afiLmOstT] arg
68     -o
69     -q           Set rwtest to be quiet and pass the flag on to iogen.
70
71     Options passed through to doio:
72     -D[rmMVUC] arg
73     -D[aekv]
74     -n nprocs    # procs to do simultanious io to the test files.
75                  Default is 1.  If -n is non-zero, doio's -k option (use
76                  file locking) is forced.
77
78     files        Files to test on.  File names have the following fomat:
79                  [ size: ] path
80                  [ free% [ max size ] : ] path
81                  If no size is specified, the files must exist
82                  and the contents will be overwritten if testing write or
83                  writea system calls.  If a size is supplied, an attempt to
84                  create/grow/shrink path to the desired size will be made.
85                  size is an integer which defaults to bytes, but may be
86                  suffixed by 'b', 'k', or 'm' for blocks (4096 byte units), 
87                  kilobytes (1024 byte units), or megabytes (2^20 byte units).
88
89                  If the size is a percentage, df is used to find how much
90                  free space there is (in blocks), and uses that.  The maximum
91                  size is implied to be in blocks.
92 " >&2
93 }
94
95 killkids()
96 {
97         trap "killkids" INT
98         if [[ -z $didkids ]]
99         then
100                 didkids=done
101                 kill -INT -$$
102         fi
103 }
104
105
106 cleanup_and_exit()
107 {
108         if [ -n "$Remove_Test_Files" ]
109         then
110                 if [ -n "$Files_To_Remove" ]
111                 then
112                         rm -f $Files_To_Remove
113                 fi
114         fi
115
116         exit $1
117 }
118
119 while (( $# > 0 ))
120 do      case $1 in
121         -c)     Remove_Test_Files=yes
122                 ;;
123
124         -d)     debug=$2
125                 shift
126                 ;;
127
128         -h)     help
129                 exit 0
130                 ;;
131
132         -F)
133                 opt_F="-F"      # only process filenames
134                 ;;
135
136         -P)
137                 PLACES=$2
138                 shift
139                 ;;
140
141         -S)     Scenario=$2
142                 shift
143                 opt_S="-S"
144                 ;;
145
146         -N)     Name="($2)"
147                 iOpts="$iOpts -N $2"
148                 dOpts="$dOpts -N $2"
149                 shift
150                 ;;
151
152         # iogen Options to pass thru ... options with an argument
153         -[afiLmOstT] )
154                 iOpts="$iOpts $1 $2"
155                 shift
156                 ;;
157
158         # iogen Options to pass thru ... just the option
159         -[o] )
160                 iOpts="$iOpts $1"
161                 ;;
162
163         # iogen options to look at
164         -q)
165                 iOpts="$iOpts $1"
166                 Quiet=$1
167                 ;;
168
169         # doio Options to pass thru ... options with an argument
170         -D[rmMVUC] )
171                 o=${1#-D}
172                 dOpts="$dOpts -$o $2"
173                 shift
174                 ;;
175
176         # doio options to pass thru ... just the options
177         -D[aekv] )
178                 o=${1#-D}
179                 dOpts="$dOpts -$o"
180                 ;;
181
182         # doio options to look at
183         -n | -Dn )
184                 dOpts="$dOpts $1 $2"
185                 # force file locking with > 1 process
186                 if [[ $2 > 1 ]]
187                 then
188                         dOpts="$dOpts -k"
189                 fi
190                 opt_n="-n"
191                 shift
192                 ;;
193
194         \? | -*)
195                 echo "$Prog:  Illegal option $1" >&2
196                 exit 1
197                 ;;
198
199         *)
200                 break
201                 ;;
202         esac
203         shift
204 done
205
206 if [[ $TOUTPUT = "NOPASS" ]]; then
207         iOpts="$iOpts -q"
208         Quiet="-q"
209 fi
210
211 #
212 # Hard-Coded Scenario Specifications
213 #
214 # FSA           RAW I/O via FSA
215 # MPPnnn        Run as a <nnn> sized MPP application
216 # userstripe    create files using user striping
217 #
218
219 if [[ -n "$opt_S" ]]
220 then
221         case $Scenario in
222
223         FSA )
224                 # I/O via FSA
225                 Flags="parallel"
226                 Nprocs=1
227                 LockRegion=""
228         ;;
229
230         MPP* )
231                 # use mpprun...  to cooperate with a batch system, this
232                 # requires scanning mppview, etc.
233
234                 NPE=${Scenario#MPP}
235                 MPPrun=" mpprun -n $NPE "
236         ;;
237         userstripe)
238                 #create files using user striping
239                 Oflags=O_PLACE,0xffffffffffffffff,1000
240         ;;
241
242         places*)
243                 FSIZE=${Scenario#places-}
244                 oi="$IFS"
245                 IFS=":"
246                 set -- $PLACES
247                 if [ $# -eq 0 ]
248                 then
249                         # "this isn't supposed to happen"
250                         Files="25%:rwtest.$$"
251                 else
252                         IFS="$oi"
253                         PL=${*}
254                         for p in $PL
255                         do
256                                 f="$f "${FSIZE}":"${p}"/rwtest$$"
257                         done
258                         set -- $f
259                 fi
260         ;;
261         esac
262 fi
263
264 #
265 # If no files are specified ...
266 #       check if PLACES is set; if so, put one file in each place
267 #       otherwise generate one filename in the current directory.
268 #
269
270 if [ $# -eq 0 ]
271 then
272         # put one file in each of $PLACES
273         Files="25%:rwtest.file"
274 else
275         Files=$*
276 fi
277
278 #
279 # use 'df -PB' to see how many blocks are available, apply a hard limit of
280 # 1,000,000 blocks if no limit is specified
281 #
282
283 case $(uname -s) in
284         IRIX | IRIX64 )         dfOpts="-Pb"    ;;
285         Linux)                  dfOpts="-P"     ;;
286         *)                      dfOpts="-PB"    ;;
287 esac
288
289 for f in $Files
290 do
291         file=${f##*:}
292         if [ ! -f "$file" ]
293         then
294                 Files_To_Remove="$Files_To_Remove $file"
295         fi
296
297         dir=$(dirname $file)
298         size=${f%%:*}
299         if [[ $size = *%* ]]
300         then
301
302                 typeset -i n=0
303                 while (( n < ${#szcache[*]} ))
304                 do
305                         if [[ szcache[$n] = $dir ]]; then
306                                 break;
307                         fi
308                         n=n+1
309                 done
310
311                 if (( n < ${#szcache[*]} ))
312                 then
313                         blks=${szblks[$n]}
314                 else
315                         blks=$(df $dfOpts $dir |
316                         (while read fs blks used avail cap mountpoint
317                          do
318                                 #echo $fs $blks $used $avail >&2
319                                 b=$avail
320                          done
321                          echo $b) )
322
323                         case $(uname) in
324                         Linux)  blks=$( expr $blks / 2 ) ;;
325                         esac
326
327                         szcache[${#szcache[*]}+1]=$dir
328                         szblks[${#szblks[*]}+1]=$blks
329                 fi
330
331                 max=${size##*\%}
332                 if [[ "$max" = "" ]]
333                 then
334                         max=1000000
335                 fi
336                 size=${size%%\%*}
337
338                 case $(uname) in
339                 IRIX*)
340                   sz=$( perl -le 'print int( '$blks' * '$size' / 100 )' )
341                   ;;
342                 *)
343                   sz=$(expr \( $blks '*' $size \) / 100)
344                   ;;
345                 esac
346
347                 if [[ $sz -gt $max ]]
348                 then
349                         sz=$max
350                 fi
351                 f=$sz"b:"$file
352         fi
353         F[${#F[*]}+1]=$f
354 done
355
356 Files=${F[*]}
357
358 if [[ -z ${dOpts} ]]; then
359         dOpts=-av
360 fi
361
362 if [[ -n "$opt_F" ]]; then
363
364         echo $Files
365
366 else
367
368         [[ -n "$here" ]] || here=`pwd`
369         if [[ -x ${LTPROOT}/testcases/bin/iogen ]]; then
370                 IOgen=${LTPROOT}/testcases/bin/iogen
371         elif [[ -x ${here}/ltp/iogen ]]; then
372                 IOgen=$here/ltp/iogen
373         elif [[ -x ./iogen ]]; then
374                 IOgen=./iogen
375         else
376                 echo Cannot find iogen command
377                 exit 1
378         fi
379         if [[ -x ${LTPROOT}/testcases/bin/doio ]]; then
380                 doIO=${LTPROOT}/testcases/bin/doio
381         elif [[ -x ${here}/ltp/doio ]]; then
382                 doIO=$here/ltp/doio
383         elif [[ -x ./doio ]]; then
384                 doIO=./doio
385         else
386                 echo Cannot find doio command
387                 exit 1
388         fi
389
390         cmd="$IOgen ${iOpts} ${Files} | $MPPrun $doIO ${dOpts}"
391
392         if [[ -z "$Quiet" ]]; then
393                 echo $cmd
394         fi
395
396         trap "killkids" INT
397         trap "cleanup_and_exit 2" HUP
398
399         ( $IOgen ${iOpts} ${Files}
400           r=$?
401           if [ $r -ne 0 ]
402           then
403                 echo "$Prog$Name : iogen reported errors (r=$r)" >&2
404                 kill -HUP $$
405           fi
406         ) | $MPPrun $doIO ${dOpts}
407         r=$?
408         if [ $r -ne 0 ]
409         then
410                 echo "$Prog$Name : doio reported errors (r=$r)" >&2
411         fi
412
413         cleanup_and_exit $r
414 fi