Add GPL license plate to SGI's files.
[xfstests-dev.git] / common.log
1 ##/bin/sh
2 #
3 # Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms 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,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write the Free Software Foundation,
16 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 #
18 #
19 # common routines for log testing
20 # Created by dxm@sgi.com & tes@sgi.com
21 #
22
23 fulldir=$seq.fulldir
24 rm -rf $fulldir
25
26 _cleanup_logfiles()
27 {
28     if [ $status -eq 0 ]; then
29         # don't keep these files around unless something went wrong
30         rm -rf $fulldir
31     fi
32 }
33
34 _full()
35 {
36     echo ""            >>$seq.full      
37     echo "*** $* ***"  >>$seq.full
38     echo ""            >>$seq.full
39 }
40
41 _echofull()
42 {
43     echo ""            | tee -a $seq.full      
44     echo "*** $* ***"  | tee -a $seq.full
45     echo ""            | tee -a $seq.full
46 }
47
48 # Handle the operations which get split over Log Record
49 # boundaries.
50 # Oper (379)..... flags: CONTINUE
51 # ...
52 # Oper (0)....... flags: WAS_CONT END
53 #
54 # or
55 #
56 # Oper (379)..... flags: none 
57 # ...
58 # Oper (0)....... flags: none 
59 #
60 _filter_opnum()
61 {
62     $AWK_PROG '
63 BEGIN { 
64         debug = 0 
65         }
66 /^Oper/ && debug {
67             printf "line = %s\n", $0
68         }
69 /^Oper/ {
70             was_cont = 0
71         }
72 /^Oper/ && /flags: CONTINUE/ { 
73             # this will be the first op of split region
74             $9 = "none" # overwrite CONTINUE flags
75             print
76             print "Not printing rest"
77             was_cont = 1
78             next        
79         }
80 /^Oper/ && /flags: WAS_CONT END/ {
81             # this will be the last op of split region
82             # skip over was-continued op
83             # we assume there can be only 1
84             was_cont = 1
85             next        
86         }
87 (was_cont == 1) { 
88             # skip over any continued op stuff
89             next
90         }
91         {print}
92     '
93 }
94
95 #
96 # Filter out things that can change
97 # We have complexities which change when log is sync'ed at different
98 # times.
99 # Example1: DATA FORK EXTENTS
100 # These will not show up if inode is sync'ed sooner
101 #       /DATA FORK EXTENTS/d;
102 #       /INODE:/s/flags:0x5/flags:0x1/g;
103 # define XFS_ILOG_CORE   0x001   /* log standard inode fields */
104 # define XFS_ILOG_DEXT   0x004   /* log i_df.if_extents */
105 #
106 #
107
108 _filter_logprint()
109 {
110     _fix_malloc |\
111     sed '
112         s/ver:[0-9]/ver:<VERS>/;
113         s/version [0-9] format [0-9]/version <VERS> format <FORMAT>/;
114         s/data device: 0x[0-9a-f][0-9a-f]*/data device: <DEVICE>/;
115         s/log device: 0x[0-9a-f][0-9a-f]*/log device: <DEVICE>/;
116         s/log file: \".*\"/log device: <DEVICE>/;
117         s/daddr: [0-9][0-9]*/daddr: <DADDR>/;
118         s/length: [0-9][0-9]*/length: <LENGTH>/;
119         s/length: [0-9][0-9]*/length: <LENGTH>/;
120         s/^cycle num overwrites: .*$/cycle num overwrites: <TIDS>/;
121         s/tid: [0-9a-f][0-9a-f]*/tid: <TID>/;
122         s/tid:0x[0-9a-f][0-9a-f]*/tid:<TID>/;
123         s/q:0x[0-9a-f][0-9a-f]*/q:<Q>/;
124         s/a:0x[0-9a-f][0-9a-f]*/a:<A>/g;
125         s/blkno:0x[0-9a-f][0-9a-f]*/blkno:<BLKNO>/g;
126         s/blkno: *[0-9][0-9]* (0x[0-9a-f]*)/blkno: <BLKNO> (<BLKNO>)/g;
127         s/blkno: *[0-9][0-9]*/blkno: <BLKNO>/g;
128         s/boff: [0-9][0-9]*/boff: <BOFF>/g;
129         s/len: *[0-9][0-9]*/len:<LEN>/g;
130         /BUF:/s/[       ]*flags:.*$//;
131         /zeroed blocks/s/[0-9][0-9]*/<COUNT>/g;
132         /cleared blocks/d;
133         /log tail/s/[0-9][0-9]*/<COUNT>/g;
134         s/atime:[0-9a-fx]*  *mtime:[0-9a-fx]*  *ctime:[0-9a-fx]*/atime:<TIME>  mtime:<TIME>  ctime:<TIME>/;
135         s/atime 0x[0-9a-f]* mtime 0x[0-9a-f]* ctime 0x[0-9a-f]*/atime <TIME>  mtime <TIME>  ctime <TIME>/;
136         s/block [0-9][0-9]*/block <BLOCK>/;
137         s/icount: *[0-9][0-9]*  *ifree: *[0-9][0-9]*  *fdblks: *[0-9][0-9]*  *frext: *[0-9][0-9]*/icount:<COUNT> ifree:<FREE> fdblks:<BLOCKS> frext:<COUNT>/;
138         s/sunit: *[0-9][0-9]*  *swidth: *[0-9][0-9]*/sunit:<SUNIT> swidth:<SWIDTH>/;
139         s/1st: *[0-9][0-9]*  *last: *[0-9][0-9]*  *cnt: *[0-9][0-9]*  *freeblks: *[0-9][0-9]*  *longest: *[0-9][0-9]*/1st:<NUM> last:<NUM> cnt:<COUNT> freeblks:<COUNT> longest:<NUM>/;
140         s/^uuid: *[0-9a-f-][0-9a-f-]* *format: *.*$/uuid: <UUID> format: <FORMAT>/;
141         /flushiter:/d;
142         /version:/,/h_size:/d;
143         /override tail/s/[0-9][0-9]*/<TAIL_BLK>/;
144         /^---*/d;
145         /^===*/d;
146         /^~~~*/d;
147         /extended-header/d;
148         /LOG REC AT LSN/d;
149         /DATA FORK EXTENTS/d;
150         s/BUF: cnt:[1-9][0-9]* total:[1-9][0-9]*.*/BUF: cnt:C total:T/;
151         s/INO: cnt:[1-9][0-9]* total:[1-9][0-9]*.*/INO: cnt:C total:T/;
152         s/#regs: *[1-9][0-9]*/#regs:R/;
153         /INODE:/s/flags:0x5/flags:0x1/g;
154         s/Oper ([0-9][0-9]*)/Oper (OPNUM)/;
155         /^[     ]*$/d;
156         s/  */ /g;
157         s/ $//;
158         s/newino: 0x[0-9a-f]*$/newino: <INO>/g
159         s/newino:0x[0-9a-f]*$/newino:<INO>/g
160         s/ino: 0x[0-9a-f]* flags:/ino: <INO> flags:/g
161         s/ino:0x[0-9a-f]* flags:/ino:<INO> flags:/g
162         s/onlink:[0-9][0-9]*/onlink:<ONLINK>/;
163         s/gen:-*[0-9][0-9]*/gen:<GEN>/;
164         s/gen 0x[0-9a-f][0-9a-f]*/gen <GEN>/;
165     '|\
166     awk '
167         # collapse BUF DATA group into 1 line
168         # for Oper data this can be over separate operations...ughh
169         /BUF DATA/ { 
170                 if (!buf_data) { # 1st one
171                     if (oper) { 
172                         print oper
173                         oper = 0
174                     }           
175                     print
176                 }
177                 buf_data = 1
178                 oper = 0 # wont need it now
179                 next
180         }
181         /^Oper/ { 
182                 # store it as we dont know if 2nd BUF DATA is to follow
183                 if (oper) {
184                     print oper
185                 }
186                 oper = $0
187                 next
188         }
189         /^TRANS/ && dummy_rec == 1 {
190                 # start printing again - dummy transaction over
191                 dummy_rec = 0
192         }
193         /DUMMY1/ {
194                 # filter out dummy transactions
195                 dummy_rec = 1
196                 next
197         }
198         {
199                 if (dummy_rec) {
200                     next
201                 }
202                 buf_data = 0
203                 if (oper) { # now we can print out oper
204                     print oper
205                     oper = 0    
206                 }
207                 print
208         }
209     '
210 }
211
212 _check_log()
213 {
214     _full "clean_log : xfs_logprint"
215     _scratch_xfs_logprint -t | tee -a $seq.full \
216         | head | grep -q "<CLEAN>" || _fail "DIRTY LOG"
217 }
218
219 _print_logstate()
220 {
221     _scratch_xfs_logprint -t | tee -a $seq.full >$tmp.logprint
222     if grep -q "<DIRTY>" $tmp.logprint; then
223         echo "dirty log"
224     fi
225     if grep -q "<CLEAN>" $tmp.logprint; then
226         echo "clean log"
227     fi
228 }
229
230 _print_operation()
231 {
232     mkdir $fulldir >/dev/null 2>&1
233     mntopt=`echo $MOUNT_OPTIONS | sed 's/ //g'`
234     mkfsopt=`echo $MKFS_OPTIONS | sed 's/ //g'`
235     raw=$fulldir/op.mnt$mntopt.mkfs$mkfsopt$sync_suffix.raw
236     filtered=$fulldir/op.mnt$mntopt.mkfs$mkfsopt$sync_suffix.filtered
237
238     echo "### xfs_logprint output ###" | tee $raw >$filtered
239     _scratch_xfs_logprint -c  2>&1 \
240     | tee -a $raw      \
241     | _filter_logprint \
242     | _filter_opnum    \
243     >>$filtered
244 }
245
246 # start at rec#2 "-s 2" so we skip over UMOUNT record which will always
247 # be a 512b single header at mkfs time
248 # and may not match with the FS mounted at a different LR size 
249 # => xlog_do_recovery_pass() can not handle the different hdr sizes
250 #    it assumes them all to be the same between the start..finish
251 # NB: On IRIX there is no UMOUNT record and so we could start from -s 0.
252
253 _print_transaction_inode()
254 {
255     _start=$1
256     mkdir $fulldir >/dev/null 2>&1
257     mntopt=`echo $MOUNT_OPTIONS | sed 's/ //g'`
258     mkfsopt=`echo $MKFS_OPTIONS | sed 's/ //g'`
259     raw=$fulldir/trans_inode.mnt$mntopt.mkfs$mkfsopt$sync_suffix.raw
260     filtered=$fulldir/trans_inode.mnt$mntopt.mkfs$mkfsopt$sync_suffix.filtered
261
262     echo "### xfs_logprint -t -i -s START output ###" | tee $raw >$filtered
263     _scratch_xfs_logprint -t -i -s $_start 2>&1 \
264     | tee -a $raw      \
265     | _filter_logprint \
266     >>$filtered
267 }
268
269 _print_transaction_buf()
270 {
271     _start=$1
272     mkdir $fulldir >/dev/null 2>&1
273     mntopt=`echo $MOUNT_OPTIONS | sed 's/ //g'`
274     mkfsopt=`echo $MKFS_OPTIONS | sed 's/ //g'`
275     raw=$fulldir/trans_buf.mnt$mntopt.mkfs$mkfsopt$sync_suffix.raw
276     filtered=$fulldir/trans_buf.mnt$mntopt.mkfs$mkfsopt$sync_suffix.filtered
277
278     echo "### xfs_logprint -t -b -s START output ###" | tee $raw >$filtered
279     _scratch_xfs_logprint -t -b -s $_start 2>&1 \
280     | tee -a $raw      \
281     | _filter_logprint \
282     >>$filtered
283 }
284
285 _mkfs_log()
286 {
287     # create the FS
288     # mkfs options to append to log size otion can be specified ($*)
289     export MKFS_OPTIONS="-l size=2000b $*"
290     _full "mkfs"
291     _scratch_mkfs_xfs >>$seq.full 2>&1
292     if [ $? -ne 0 ] ; then 
293         _echofull "Cannot mkfs for this test using option specified: $MKFS_OPTIONS"
294         return 1
295     fi  
296
297     return 0
298 }
299
300
301 #
302 # mount fs and create some log traffic
303 #
304 _create_log()
305 {
306     # mount the FS
307     _full "mount"
308     _scratch_mount >>$seq.full 2>&1
309     if [ $? -ne 0 ] ; then 
310         _echofull "mount failed: $MOUNT_OPTIONS"
311         return 1
312     fi
313
314     # generate some log traffic - but not too much - life gets a little
315     # more complicated if the log wraps around. This traffic is
316     # pretty much arbitary, but could probably be made better than this.
317     touch $SCRATCH_MNT/{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}
318         
319     # unmount the FS
320     _full "umount"
321     umount $SCRATCH_DEV >>$seq.full 2>&1
322     if [ $? -ne 0 ] ; then 
323         _echofull "umount failed"
324         return 1
325     fi
326
327     return 0
328 }
329
330 #
331 # mount fs and create some log traffic with sync'ing
332 #
333 _create_log_sync()
334 {
335     # mount the FS
336     _full " mount"
337     _scratch_mount >>$seq.full 2>&1
338     if [ $? -ne 0 ] ; then 
339         _echofull "mount failed: $MOUNT_OPTIONS"
340         return 1
341     fi
342
343     # generate some log traffic - but not too much
344     # add some syncs to get the log flushed to disk 
345     for file in $SCRATCH_MNT/{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}; do
346         touch $file
347         sync
348     done
349
350     # unmount the FS
351     _full "umount"
352     umount $SCRATCH_DEV >>$seq.full 2>&1
353     if [ $? -ne 0 ] ; then 
354         _echofull "umount failed"
355         return 1
356     fi
357 }
358
359 _cmp_output()
360 {
361     echo "*** compare logprint: $1 with $2"
362     if ! diff $1 $2 >/dev/null; then
363         _fail "logprint output $1 differs to $2"
364     fi
365 }
366
367 #
368 # Op data of different Log Record sizes will mean that data is
369 # split at different points and in op printing it will not
370 # try and decode the data which has been split up.
371 # So we do a special diff processing to complain of differences
372 # if no split is involved.
373 #
374 # Example diff with forms of:
375 # "Left over region from split log item"
376 # "Not printing rest of data"
377 #
378 #   2149c2149
379 #   < Left over region from split log item
380 #   ---
381 #   > BUF DATA
382 #   2888c2888,2889
383 #   < INODE: #regs: 3 Not printing rest of data
384 #   ---
385 #   > INODE: #regs: 3 ino: 0x80 flags: 0x5 dsize: 16
386 #   >  blkno: <BLKNO> len:<LEN> boff: <BOFF>
387 #
388 _process_op_diff()
389 {
390     $AWK_PROG <$1 '
391         BEGIN { num_splits = 1; max_splits = 50 }
392         /^[0-9]/ {
393
394                 # ensure a split happened in previous difference
395                 if (num_splits < 1 || num_splits > max_splits) {
396                         print num_splits, " split(s) found prior to diff cmd: ", $0
397                         num_splits = 1 # shut-up end condition
398                         exit 1
399                 }
400                 num_splits = 0
401
402                 next
403         }
404         /Left over region/ || /Not printing rest/ { 
405                 num_splits++
406                 next
407         }
408         { next }
409         END { 
410                 if (num_splits < 1 || num_splits > max_splits) {
411                         print num_splits, " split(s) found prior to diff end"
412                         exit 1
413                 }
414         }
415     '
416     return $?
417 }
418
419 _cmp_op_output()
420 {
421     echo "*** compare logprint: $1 with $2"
422
423     diff $1 $2 >$filtered.diff
424     if ! _process_op_diff $filtered.diff
425     then
426         _fail "logprint output $1 differs to $2 considering splits"
427     fi
428 }
429
430 # return xfs log version of device
431 # e.g.
432 #   _log_version /dev/dsk/dks0d1s4
433 #
434 _log_version()
435 {
436     _dev=$1 
437     vers=`xfs_db -c 'sb 0' -c 'p versionnum' -r $_dev | $AWK_PROG '{print $3}'`
438     logver=`echo $vers | sed -e 's/0x[0-9a-f]\([0-9a-f]\)[0-9a-f][0-9a-f]/\1/'` 
439     if [ $logver = 4 -o $logver = 5 -o $logver = 6 -o $logver = 7 -o \
440          $logver = c -o $logver = d -o $logver = e -o $logver = f ]; then
441         echo 2
442     else
443         echo 1
444     fi
445 }
446
447 _require_v2log()
448 {
449     # test out mkfs to see if it supports "-l version=2"
450     export MKFS_OPTIONS="-l version=2"
451     if ! _scratch_mkfs_xfs >>$seq.full 2>&1; then
452         _notrun "mkfs does not support v2 logs"
453     fi
454
455     # test out mount to see if it mounts a v2 log fs
456     export MOUNT_OPTIONS="-o logbsize=32k"
457     if ! _scratch_mount >>$seq.full 2>&1; then
458         _notrun "mount/kernel does not support v2 logs"
459     fi
460
461     # check after unmount to see if it is clean
462     # i.e. it is not a 6.5.25 buggy version checking kernel
463     touch $SCRATCH_MNT/file
464     umount $SCRATCH_DEV >>$seq.full 2>&1
465     if _scratch_xfs_logprint -t | tee -a $seq.full \
466         | head | grep -q "<DIRTY>"; then
467         _notrun "kernel does not support v2 logs"
468     fi
469  
470     # otherwise presume it does support v2 logs...:)
471 }
472
473
474 # make sure this script returns success
475 /bin/true