xfstests: support post-udev device mapper nodes
[xfstests-dev.git] / 001
1 #! /bin/bash
2 # FS QA Test No. 001
3 #
4 # Random file copier to produce chains of identical files so the head
5 # and the tail can be diff'd at the end of each iteration.
6 #
7 # Exercises creat, write and unlink for a variety of directory sizes, and
8 # checks for data corruption.
9 #
10 # run [config]
11 #
12 # config has one line per file with filename and byte size, else use
13 # the default one below.
14 #
15 #-----------------------------------------------------------------------
16 # Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved.
17 #
18 # This program is free software; you can redistribute it and/or
19 # modify it under the terms of the GNU General Public License as
20 # published by the Free Software Foundation.
21 #
22 # This program is distributed in the hope that it would be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 # GNU General Public License for more details.
26 #
27 # You should have received a copy of the GNU General Public License
28 # along with this program; if not, write the Free Software Foundation,
29 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
30 #
31 #-----------------------------------------------------------------------
32 #
33 # creator
34 owner=kenmcd@sgi.com
35
36 seq=`basename $0`
37 echo "QA output created by $seq"
38
39 # get standard environment, filters and checks
40 . ./common.rc
41 . ./common.filter
42
43 tmp=/tmp/$$
44 here=`pwd`
45 status=1
46 done_cleanup=false
47 trap "_cleanup; rm -f $tmp.*; exit \$status" 0 1 2 3 15
48
49 # real QA test starts here
50 _supported_fs generic
51 _supported_os IRIX Linux
52
53 verbose=true
54 verify=$here/verify_fill
55
56 if [ $# -eq 0 ]
57 then
58     # use the default config
59     #
60     cat <<End-of-File >$tmp.config
61 # pathname      size in bytes
62 #
63 small           10
64 big             102400
65 sub/small       10
66 sub/big         102400
67 #
68 sub/a           1
69 sub/b           2
70 sub/c           4
71 sub/d           8
72 sub/e           16
73 sub/f           32
74 sub/g           64
75 sub/h           128
76 sub/i           256
77 sub/j           512
78 sub/k           1024
79 sub/l           2048
80 sub/m           4096
81 sub/n           8192
82 #
83 sub/a00         100
84 sub/b00         200
85 sub/c00         400
86 sub/d00         800
87 sub/e00         1600
88 sub/f00         3200
89 sub/g00         6400
90 sub/h00         12800
91 sub/i00         25600
92 sub/j00         51200
93 sub/k00         102400
94 sub/l00         204800
95 sub/m00         409600
96 sub/n00         819200
97 #
98 sub/a000        1000
99 sub/e000        16000
100 sub/h000        128000
101 sub/k000        1024000
102 End-of-File
103 elif [ $# -eq 1 ]
104 then
105     if [ -f $1 ]
106     then
107         cp $1 $tmp.config
108     else
109         echo "Error: cannot open config \"$1\""
110         exit 1
111     fi
112 else
113     echo "Usage: run [config]"
114     exit 1
115 fi
116
117 ncopy=200               # number of file copies in the chain step
118 udf_fsize=20240         # number of sectors for UDF
119
120 _setup()
121 {
122     if mkdir -p $testdir/$$
123     then
124         :
125     else
126         echo "Error: cannot mkdir \"$testdir/$$\""
127         exit 1
128     fi
129     cd $testdir/$$
130
131     $verbose && echo -n "setup "
132     sed -e '/^#/d' $tmp.config \
133     | while read file nbytes
134     do
135         dir=`dirname $file`
136         if [ "$dir" != "." ]
137         then
138             if [ ! -d $dir ]
139             then
140                 if mkdir $dir
141                 then
142                     :
143                 else
144                     $verbose && echo
145                     echo "Error: cannot mkdir \"$dir\""
146                     exit 1
147                 fi
148             fi
149         fi
150         rm -f $file
151         if $here/src/fill $file $file $nbytes
152         then
153             :
154         else
155             $verbose && echo
156             echo "Error: cannot create \"$file\""
157             exit 1
158         fi
159         $verbose && echo -n "."
160     done
161     $verbose && echo
162 }
163
164 _mark_iteration()
165 {
166     $verbose && echo -n "mark_iteration "
167     sed -e '/^#/d' $tmp.config \
168     | while read file nbytes
169     do
170         if [ ! -f $file ]
171         then
172             $verbose && echo
173             echo "Error: $file vanished!"
174             touch $tmp.bad
175             continue
176         fi
177         sed -e "s/ [0-9][0-9]* / $1 /" <$file >$file.tmp
178         mv $file.tmp $file
179         $verbose && echo -n "."
180     done
181     $verbose && echo
182 }
183
184 # for each file, make a number of copies forming a chain like foo.0,
185 # foo.1, foo.2, ... foo.N
186 #
187 # files are chosen at random, so the lengths of the chains are different
188 #
189 # then rename foo.N to foo.last and remove all of the other files in
190 # the chain
191 #
192 _chain()
193 {
194     $AWK_PROG -v full_file=$here/$seq.full -v verify=$verify <$tmp.config '
195 BEGIN   { nfile = 0 }
196 /^\#/   { next }
197         { file[nfile] = $1
198           size[nfile] = $2
199           link[nfile] = 0
200           nfile++
201           total_size += $2
202         }
203 END     { srand('$iter')
204           for (i=0; i < '$ncopy'; i++) {
205             # choose a file at random, and add one copy to that chain
206             j = -1
207             while (j < 0 || j >= nfile)
208                 j = int(rand() * nfile)
209             if (link[j] == 0) {
210                 # previous should already exist and next one should not exist
211                 printf "if [ ! -f %s ]; then echo \"%s missing!\"; exit; fi\n",file[j],file[j]
212                 printf "if [ -f %s.0 ]; then echo \"%s.0 already present!\"; exit; fi\n",file[j],file[j]
213                 printf "cp %s %s.0 || exit 1\n",file[j],file[j]
214                 printf "ls -i %s.0\n", file[j] >full_file;
215                 total_size += size[j]
216                 printf "# total size = %d\n", total_size 
217             }
218             else {
219                 # previous should already exist and next one should not exist
220                 printf "if [ ! -f %s.%d ]; then echo \"%s.%d missing!\"; exit; fi\n",file[j],link[j]-1,file[j],link[j]-1
221                 printf "if [ -f %s.%d ]; then echo \"%s.%d already present!\"; exit; fi\n",file[j],link[j],file[j],link[j]
222                 printf "cp %s.%d %s.%d || exit 1\n",file[j],link[j]-1,file[j],link[j]
223                 printf "ls -i %s.%d\n", file[j], link[j] >full_file;
224                 total_size += size[j]
225                 printf "# total size = %d\n", total_size 
226             }
227             link[j]++
228           }
229           # close all the chains, 
230           # if have at least one copy then move the last copy to "file[j].last"
231           # and remove all of the other files except the head of the chain
232           for (j=0; j<nfile; j++) {
233             if (link[j] > 0) {
234                 printf "mv %s.%d %s.last\n",file[j],link[j]-1,file[j]
235                 printf "ls -i %s.last\n", file[j] >full_file;
236             }
237             for (i=0; i<link[j]-1; i++) {
238                 printf "rm -f %s.%d\n",file[j],i
239             }
240           }
241         }' \
242         | tee -a $here/$seq.full | sh
243 }
244
245 _check()
246 {
247     rm -f $tmp.bad
248     $verbose && echo -n "check "
249     sed -e '/^#/d' $tmp.config \
250     | while read file nbytes
251     do
252         # the file is never removed so it should exist
253         if [ ! -f $file ]
254         then
255             $verbose && echo
256             echo "Error: $file vanished!"
257             touch $tmp.bad
258             continue
259         fi
260         # checks that the file and its last copy are the same
261         if [ -f $file.last ]
262         then
263             if cmp $file $file.last >/dev/null 2>&1
264             then
265                 $verbose && echo -n "."
266             else
267                 $verbose && echo
268                 echo "Error: corruption for $file ..."
269                 diff -c $file $file.last
270                 touch $tmp.bad
271             fi
272         else
273             $verbose && echo -n "."
274         fi
275     done
276     $verbose && echo
277 }
278
279 _cleanup()
280 {
281     # cleanup
282     #
283     if $done_cleanup
284     then
285         :
286     elif [ $status -eq 0 ]
287     then
288         $verbose && echo "cleanup"
289         cd /
290         rm -rf $testdir/$$
291         _cleanup_testdir
292         done_cleanup=true
293     fi
294 }
295
296 rm -f $here/$seq.full
297 status=0
298 _cleanup
299 status=1
300 done_cleanup=false
301
302 _setup_testdir
303 _setup
304
305 # do the test
306 #
307 for iter in 1 2 3 4 5
308 do
309     echo -n "iter $iter chain ... "
310     echo "iter $iter" >> $here/$seq.full
311     _chain
312     _check
313     if [ -f $tmp.bad ]
314     then
315         echo "Fatal error: test abandoned without changes"
316         exit 1
317     fi
318 done
319
320 status=0
321 exit