Extra filtering as part of IRIX/Linux xfstests reconciliation for dump.
[xfstests-dev.git] / common.dump
1 #/bin/sh
2
3 #
4 # Functions useful for xfsdump/xfsrestore tests
5 #
6 # Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
7
8 # This program is free software; you can redistribute it and/or modify it
9 # under the terms of version 2 of the GNU General Public License as
10 # published by the Free Software Foundation.
11
12 # This program is distributed in the hope that it would be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16 # Further, this software is distributed without any warranty that it is
17 # free of the rightful claim of any third person regarding infringement
18 # or the like.  Any license provided herein, whether implied or
19 # otherwise, applies only to this software file.  Patent licenses, if
20 # any, provided herein do not apply to combinations of this program with
21 # other software, or any other product whatsoever.
22
23 # You should have received a copy of the GNU General Public License along
24 # with this program; if not, write the Free Software Foundation, Inc., 59
25 # Temple Place - Suite 330, Boston MA 02111-1307, USA.
26
27 # Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
28 # Mountain View, CA  94043, or:
29
30 # http://www.sgi.com 
31
32 # For further information regarding this notice, see: 
33
34 # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
35 #
36
37 # --- initializations ---
38 rm -f $seq.full
39
40 if [ -n "$DEBUGDUMP" ]; then
41   _dump_debug=-v5
42   _restore_debug=-v5
43   _invutil_debug=-d
44 fi
45  
46 # Use dump/restore in qa directory for debugging
47 PATH=".:$PATH"
48 export PATH
49 #which xfsdump
50 #which xfsrestore
51 #which xfsinvutil
52
53 # status returned for not run tests
54 NOTRUNSTS=2
55
56 # name those directories
57 dump_file=$tmp.dumpfile
58 # dump_file=$here/dumpfile #TEMP OVERRIDE DUMP FILE
59 dump_sdir=dumpdir
60 dump_dir=$SCRATCH_MNT/$dump_sdir
61 restore_sdir=restoredir
62 restore_dir=$SCRATCH_MNT/$restore_sdir
63 multi=3
64 dumptape=$TAPE_DEV
65 media_label="stress_tape_media"
66 session_label="stress_$seq"
67
68 nobody=4 # define this uid/gid as a number
69 do_quota_check=true # do quota check if quotas enabled
70
71 _need_to_be_root
72
73 # install our cleaner
74 trap "_cleanup; exit \$status" 0 1 2 3 15
75
76 # start inventory from a known base - move it aside for test
77 for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
78     if [ -d $dir ]; then
79         [ -d $dir.$seq ] && rm -rf $dir.$seq
80         mv $dir $dir.$seq
81     fi
82 done
83
84 # remove this when xfstests irix/linux port done
85 if [ "X$XFS_HOST_OS" = "Xirix" ]
86 then # IRIX
87     have_mtvariable=false
88     MKFS_OPTS=""
89 else # Linux
90     have_mtvariable=true
91     MKFS_OPTS="-f"
92 fi
93
94
95 #
96 # do a remote/local mt
97 #
98 _mt()
99 {
100     op=$1
101     if _isrmt; then  
102         # REMOTE
103         _rmtdev=`echo $dumptape | $AWK_PROG -F: '{print $2}'`
104
105         if echo $dumptape | grep '@' >/dev/null; then
106             _spec=`echo $dumptape | $AWK_PROG -F: '{print $1}'`
107             _rmtuser=`echo $_spec | $AWK_PROG -F@ '{print $1}'`
108             _rmthost=`echo $_spec | $AWK_PROG -F@ '{print $2}'`
109             rsh -n -l $_rmtuser $_rmthost "mt -t $_rmtdev $op"
110         else
111             _rmthost=`echo $dumptape | $AWK_PROG -F: '{print $1}'`
112             rsh -n $_rmthost "mt -t $_rmtdev $op"
113         fi
114     else
115         #LOCAL
116         mt -t $dumptape $op
117     fi
118 }
119
120 _check_onl()
121 {
122     _limit=10
123     i=0
124     while [ $i -lt $_limit ]; do  
125         echo "Checking online..." >>$seq.full
126         if _mt status >$tmp.status 2>&1; then
127             break; 
128         else
129             sleep 2 
130         fi
131         i=`expr $i + 1`
132     done
133
134
135     if [ $i -eq $_limit ]; then
136         echo "ERROR: mt -f $dumptape failed"
137         cat $tmp.status
138
139         echo "mt -f $dumptape failed" >$seq.notrun 
140         status=$NOTRUNSTS
141         exit
142     fi 
143
144
145     if egrep -i 'onl|ready' $tmp.status | grep -iv 'not ready' >/dev/null; then
146         :
147     else
148         echo "ERROR: $dumptape is not online"
149         cat $tmp.status
150
151         echo "dumptape, $dumptape, is not online" >$seq.notrun 
152         status=$NOTRUNSTS
153         exit
154     fi
155 }
156
157 _wait_tape()
158 {
159     echo "Wait for tape, $dumptape, ..." >>$seq.full
160
161     i=0
162     while [ $i -lt 20 ]; do  
163         echo "Checking status..." >>$seq.full
164         if _mt status 2>&1 | tee -a $seq.full | egrep -i "onl|ready" >/dev/null; then
165             break; 
166         else
167             sleep 2 
168         fi
169         i=`expr $i + 1`
170     done
171 }
172
173 #
174 # Keep trying so we know we really have rewound
175 #
176 _rewind()
177 {
178     echo "Initiate rewind..." >>$seq.full
179     _wait_tape
180     _mt rewind >/dev/null
181     _wait_tape
182 }
183
184 #
185 # Do a custom erase because: 
186 # (i) some machines don't support it
187 # (ii) some machines take forever to do it
188 #
189 _erase_soft()
190 {
191     echo "Erasing tape" | tee -a $seq.full
192     _rewind
193     _mt weof 3
194     _rewind
195 }
196
197 _erase_hard()
198 {
199     echo "Erasing tape" | tee -a $seq.full
200     _mt erase
201 }
202
203 _isrmt()
204 {
205     echo $dumptape | grep ':' >/dev/null
206 }
207
208 #
209 # Get tape ready
210 #
211 _set_variable()
212 {
213     $have_mtvariable || return
214
215     if _isrmt; then
216         :
217     else
218         # LOCAL
219         echo "Put scsi tape driver into variable block size mode"
220         mt -f $dumptape setblk 0
221     fi  
222 }
223
224 _require_tape()
225 {
226     dumptape=$1
227
228     if [ -z "$dumptape" ]; then
229         echo "This test requires a dump tape - none was specified"
230         echo "No dump tape specified" >$seq.notrun 
231         status=$NOTRUNSTS
232         exit
233     fi
234
235     _check_onl
236     _set_variable
237 }
238
239 _error()
240 {
241     echo "Error: $*" | tee -a $seq.full
242     echo "(see $seq.full for details)"
243     status=1
244     exit
245 }
246
247 _wipe_fs()
248 {
249     _require_scratch
250
251     mkfs -t xfs $MKFS_OPTS $SCRATCH_DEV>>$seq.full  ||\
252         _error "mkfs failed"
253       
254     mount -t xfs $SCRATCH_DEV $SCRATCH_MNT >>$seq.full ||\
255         _error "mount failed"
256 }
257
258
259 # Cleanup created dirs and files
260 # Called by trap
261 #
262 _cleanup()
263 {
264     cd $here
265     rm -f $tmp.*
266
267     if [ -n "$DEBUGDUMP" ]; then
268         # save it for inspection
269         for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
270             [ -d $dir ] || continue
271             tar -cvf $seq.inventory.tar $dir
272             ls -lR $dir >$seq.inventory.ls
273         done
274     fi
275
276     # put inventory dir back
277     for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
278         [ -d $dir.$seq ] || continue
279         rm -rf $dir             # get rid of new one
280         mv $dir.$seq $dir
281     done
282
283     if [ $status -ne $NOTRUNSTS ]; then
284         # Sleep added to stop _check_fs from complaining that the
285         # scratch_dev is still busy
286         sleep 10
287
288         _check_fs $SCRATCH_DEV
289     fi
290 }
291
292 #
293 # ensure that bulkstat data will
294 # match with incore data
295 # by forcing disk data to be written out
296 #
297 _stable_fs()
298 {
299     umount $SCRATCH_MNT >>$seq.full ||\
300         _error "unmount failed"
301     mount -t xfs $SCRATCH_DEV $SCRATCH_MNT >>$seq.full ||\
302         _error "mount failed"
303 }
304
305 #
306 # Run src/fsstress to create a mixture of 
307 # files,dirs,links,symlinks
308 #
309 # Pinched from test 013.
310 #
311 _create_dumpdir_stress()
312 {
313     echo "Creating directory system to dump using src/fsstress."
314
315     _wipe_fs
316
317     _param="-f link=10 -f creat=10 -f mkdir=10 -f truncate=5 -f symlink=10"
318     _count=200
319     rm -rf $dump_dir
320     if ! mkdir $dump_dir; then
321         echo "    failed to mkdir $dump_dir"
322         status=1
323         exit
324     fi
325     echo ""
326     echo "-----------------------------------------------"
327     echo "fsstress : $_param"
328     echo "-----------------------------------------------"
329     if ! $here/src/fsstress $_param -s 1 $FSSTRESS_AVOID -n $_count -d $dump_dir >$tmp.out 2>&1
330     then
331         echo "    fsstress (count=$_count) returned $? - see $seq.full"
332         
333         echo "--------------------------------------"       >>$here/$seq.full
334         echo "output from fsstress:"                        >>$here/$seq.full
335         echo "--------------------------------------"       >>$here/$seq.full
336         cat $tmp.out                                        >>$here/$seq.full
337         status=1
338     fi
339
340     _stable_fs
341 }
342
343 _mk_fillconfig1()
344 {
345     cat <<End-of-File >$tmp.config
346 # pathname      size in bytes   owner   group
347 #
348 small           10      $nobody $nobody
349 big             102400  daemon  sys
350 sub/small       10      bin     bin
351 sub/big         102400  $nobody sys
352 #
353 sub/a           1       $nobody $nobody
354 sub/b           2       $nobody $nobody
355 sub/c           4       $nobody $nobody
356 sub/d           8       $nobody $nobody
357 sub/e           16      $nobody $nobody
358 sub/f           32      $nobody $nobody
359 sub/g           64      $nobody $nobody
360 sub/h           128     $nobody $nobody
361 sub/i           256     $nobody $nobody
362 sub/j           512     $nobody $nobody
363 sub/k           1024    $nobody $nobody
364 sub/l           2048    $nobody $nobody
365 sub/m           4096    $nobody $nobody
366 sub/n           8192    $nobody $nobody
367 #
368 sub/a00         100     $nobody $nobody
369 sub/b00         200     $nobody $nobody
370 sub/c00         400     $nobody $nobody
371 sub/d00         800     $nobody $nobody
372 sub/e00         1600    $nobody $nobody
373 sub/f00         3200    $nobody $nobody
374 sub/g00         6400    $nobody $nobody
375 sub/h00         12800   $nobody $nobody
376 sub/i00         25600   $nobody $nobody
377 sub/j00         51200   $nobody $nobody
378 sub/k00         102400  $nobody $nobody
379 sub/l00         204800  $nobody $nobody
380 sub/m00         409600  $nobody $nobody
381 sub/n00         819200  $nobody $nobody
382 #
383 sub/a000        1000    $nobody $nobody
384 sub/e000        16000   $nobody $nobody
385 sub/h000        128000  $nobody $nobody
386 sub/k000        1024000 $nobody $nobody
387 End-of-File
388 }
389
390 _mk_fillconfig2()
391 {
392     cat <<End-of-File >$tmp.config
393 # pathname      size in bytes
394 #
395 smalll          10      $nobody $nobody
396 biggg           102400  $nobody $nobody
397 sub/smalll      10      $nobody $nobody
398 sub/biggg       102400  $nobody $nobody
399 End-of-File
400 }
401
402 _mk_fillconfig_perm()
403 {
404     # dir_guid: ugo=rwx,g+s on dir is for IRIX chmod(1)
405
406     cat <<End-of-File >$tmp.config
407 # pathname      size/dir  user group mode
408 #
409 file_suid       10      $nobody $nobody 04777
410 file_guid       10      $nobody $nobody 02777
411 file_sticky     10      $nobody $nobody 01777
412 file_mix1       10      $nobody $nobody 761
413 file_mix2       10      $nobody $nobody 642
414 dir_suid        d       $nobody $nobody 04777
415 dir_guid        d       $nobody $nobody ugo=rwx,g+s
416 dir_sticky      d       $nobody $nobody 01777
417 dir_mix1        d       $nobody $nobody 761
418 dir_mix2        d       $nobody $nobody 642
419 End-of-File
420 }
421
422 _mk_fillconfig_ea()
423 {
424     cat <<End-of-File >$tmp.config
425 # pathname      size    user    group    perm   name value
426 #
427 smalll          10      $nobody $nobody  777    attr1 some_text    
428 biggg           102400  $nobody $nobody  777    attr2 some_text2
429 sub/smalll      10      $nobody $nobody  777    attr3 some_text3
430 sub/biggg       102400  $nobody $nobody  777    attr4 some_text4
431 dir             d       $nobody $nobody  777    attr5 dir_text
432 #
433 # Add more files so that there are more than the number
434 # of streams.
435 # There are bugs in dump/restore for # non-dir files < # streams
436 # It can be tested in another configuration.
437 # It is a pathalogical case.
438 #
439 sub/a           1       $nobody $nobody
440 sub/b           2       $nobody $nobody
441 sub/c           4       $nobody $nobody
442 sub/d           8       $nobody $nobody
443 sub/e           16      $nobody $nobody
444 sub/f           32      $nobody $nobody
445 sub/g           64      $nobody $nobody
446 sub/h           128     $nobody $nobody
447 sub/i           256     $nobody $nobody
448 sub/j           512     $nobody $nobody
449 sub/k           1024    $nobody $nobody
450 sub/l           2048    $nobody $nobody
451 sub/m           4096    $nobody $nobody
452 sub/n           8192    $nobody $nobody
453 End-of-File
454 }
455
456 #
457 # Create a bunch of directories/files of different sizes
458 # filled with data.
459 #
460 # Pinched from test 001.
461 #
462 _do_create_dumpdir_fill()
463 {
464     echo "Creating directory system to dump using src/fill."
465
466     if mkdir -p $dump_dir
467     then
468         :
469     else
470         echo "Error: cannot mkdir \"$dump_dir\""
471         exit 1
472     fi
473     cd $dump_dir
474
475     $verbose && echo -n "Setup "
476     sed -e '/^#/d' $tmp.config \
477     | while read file nbytes owner group perms ea_name ea_value
478     do
479         if [ $nbytes = "d" ]; then
480             # create a directory
481             dir=$file   
482             if [ ! -d $dir ]
483             then
484                 if mkdir $dir
485                 then
486                     :
487                 else
488                     $verbose && echo
489                     echo "Error: cannot mkdir \"$dir\""
490                     exit 1
491                 fi
492             fi
493         else
494             # create a directory/file
495             dir=`dirname $file`
496             if [ "$dir" != "." ]
497             then
498                 if [ ! -d $dir ]
499                 then
500                     if mkdir $dir
501                     then
502                         :
503                     else
504                         $verbose && echo
505                         echo "Error: cannot mkdir \"$dir\""
506                         exit 1
507                     fi
508                 fi
509             fi
510             rm -f $file
511             if $here/src/fill $file $file $nbytes
512             then
513                 :
514             else
515                 $verbose && echo
516                 echo "Error: cannot create \"$file\""
517                 exit 1
518             fi
519         fi
520         if [ -n "$owner" -a -n "$group" ]; then
521             chown $owner.$group $file
522         fi
523         if [ -n "$perms" ]; then
524             chmod $perms $file
525         fi
526         if [ -n "$ea_name" -a -n "$ea_value" ]; then
527             attr -s $ea_name -V $ea_value $file
528         fi
529         $verbose && echo -n "."
530     done
531     $verbose && echo
532
533     cd $here
534 }
535
536
537 _create_dumpdir_fill()
538 {
539     _wipe_fs
540     _mk_fillconfig1
541     _do_create_dumpdir_fill
542     _stable_fs
543 }       
544
545 _create_dumpdir_fill2()
546 {
547     _wipe_fs
548     _mk_fillconfig2
549     _do_create_dumpdir_fill
550     _stable_fs
551 }       
552
553 _create_dumpdir_fill_perm()
554 {
555     _wipe_fs
556     _mk_fillconfig_perm
557     _do_create_dumpdir_fill
558     _stable_fs
559 }       
560
561 _create_dumpdir_fill_ea()
562 {
563     _wipe_fs
564     _mk_fillconfig_ea
565     _do_create_dumpdir_fill
566     _stable_fs
567 }       
568
569
570 #
571 # Append a subset of the fill'ed files
572 # So we can see if just these get dumped on an incremental
573 #
574 _append_dumpdir_fill()
575 {
576     cd $dump_dir
577     cat <<End-of-File >$tmp.config
578 # pathname
579 #
580 small   
581 sub/big 
582 #
583 sub/a
584 sub/c
585 sub/e
586 End-of-File
587     sed -e '/^#/d' $tmp.config \
588     | while read file
589     do
590         echo 'Extra text' >>$file
591     done
592
593     cd $here
594     _stable_fs
595 }
596
597 _do_create_dump_symlinks()
598 {
599     echo "Creating directory system of symlinks to dump."
600
601     if mkdir -p $dump_dir
602     then
603         :
604     else
605         echo "Error: cannot mkdir \"$dump_dir\""
606         exit 1
607     fi
608     cd $dump_dir
609
610     $verbose && echo -n "Setup "
611     sed -e '/^#/d' $tmp.config \
612     | while read file nbytes owner group owner2 group2 perms perms2
613     do
614         dir=`dirname $file`
615         if [ "$dir" != "." ]
616         then
617             if [ ! -d $dir ]
618             then
619                 if mkdir $dir
620                 then
621                     :
622                 else
623                     $verbose && echo
624                     echo "Error: cannot mkdir \"$dir\""
625                     exit 1
626                 fi
627             fi
628         fi
629         rm -f $file
630         touch $file
631
632         # Do chmod on symlink using umask.
633         # This won't do the right thing as it subtracts permissions.
634         # However, I don't care, as long as I get some different perms
635         # for testing.
636         if [ -n "$perms2" ]; then
637             omask=`umask`
638             umask $perms2
639         fi
640         ln -s $file $file-link
641         if [ -n "$perms2" ]; then
642             umask $omask        
643         fi
644
645         if [ -n "$owner" -a -n "$group" ]; then
646             chown $owner.$group $file
647         fi
648         if [ -n "$owner" -a -n "$group" ]; then
649             chown -h $owner.$group $file-link
650         fi
651         if [ -n "$perms" ]; then
652             chmod $perms $file
653         fi
654         $verbose && echo -n "."
655     done
656     $verbose && echo
657
658     cd $here
659 }
660
661 _mk_symlink_config()
662 {
663     cat <<End-of-File >$tmp.config
664 # path  size    owner1  group1  owner2  group2  perm1   perm2 
665 #
666 a       0       $nobody $nobody daemon  sys     124     421
667 b       0       daemon  sys     bin     bin     347     743
668 sub/a   0       bin     bin     $nobody sys     777     777
669 sub/b   0       $nobody sys     $nobody $nobody 367     763
670 End-of-File
671 }
672
673 _create_dumpdir_symlinks()
674 {
675     _wipe_fs
676     _mk_symlink_config
677     _do_create_dump_symlinks
678     _stable_fs
679 }       
680
681 #
682 # Filter for ls
683 # Filter out dates on symlinks and char devices
684 #
685 _ls_filter()
686 {
687   $AWK_PROG '
688         /^l/ { date = $8; sub(date,"DATE"); print}
689         /^c/ { date = $9; sub(date,"DATE"); print}
690         {print}' \
691   | sed -e 's/total [0-9][0-9]*/total TOTAL/'
692 }
693
694
695
696 # Filter out the non-deterministic dump msgs from
697 # xfsdump and xfsrestore
698 #
699 _dump_filter_main()
700 {
701   sed \
702       -e "s/`hostname`/HOSTNAME/"   \
703       -e "s#$SCRATCH_DEV#SCRATCH_DEV#"    \
704       -e "s#$SCRATCH_RAWDEV#SCRATCH_DEV#"    \
705       -e "s#$dumptape#TAPE_DEV#"    \
706       -e "s#$SCRATCH_MNT#SCRATCH_MNT#"    \
707       -e "s#$dump_file#DUMP_FILE#"  \
708       -e 's/id:[        ]*[0-9a-f-]*/id: ID/'  \
709       -e 's/time:[      ].*/time: TIME/'       \
710       -e 's/date:[      ].*/date: DATE/'       \
711       -e 's/dump begun .*/dump begun DATE/'    \
712       -e 's/[0-9][0-9]* seconds/SECS seconds/' \
713       -e 's/restore.[0-9][0-9]*/restore.PID/' \
714       -e 's/ino [0-9][0-9]*/ino INO/' \
715       -e '/: dump size/s/[0-9][0-9]*/NUM/'     \
716       -e '/dump size:/s/[0-9][0-9]*/NUM/'      \
717       -e '/dump size per stream:/s/[0-9][0-9]*/NUM/' \
718       -e 's/\(media file size[   ]*\)[0-9][0-9]*/\1NUM/' \
719       -e 's/\(mfile size:[       ]*\)[0-9][0-9]*/\1NUM/' \
720       -e '/drive[        ]*[0-9][0-9]*:/d' \
721       -e '/\/dev\/tty/d' \
722       -e '/inventory session uuid/d' \
723       -e '/ - Running single-threaded/d' \
724       -e '/^.*I\/O metrics: .*$/d' \
725       -e 's/1048576/BLOCKSZ/' \
726       -e 's/2097152/BLOCKSZ/' \
727       -e 's/(pid[        ]*[1-9][0-9]*)/\(pid PID\)/' \
728   | perl -ne '
729       if ($_ =~ /(?:Dump|Restore) Summary/) {
730         $skip = 1;
731       } elsif ($_ =~ /(?:Dump|Restore) Status/) {
732         $skip = 0;
733       }
734       print if (! $skip);'
735 }
736
737 _dump_filter()
738 {
739    if $do_quota_check
740    then
741        _dump_filter_main | _check_quota_dumprestore
742    else
743        _dump_filter_main
744    fi
745 }
746
747 _invutil_filter()
748 {
749   _dump_filter_main \
750   | sed \
751         -e 's/UUID[     ]*:[    ][0-9a-f-]*/UUID                :       ID/' \
752         -e 's/TIME OF DUMP[     ]*:.*/TIME OF DUMP      :       TIME/' \
753         -e 's/HOSTNAME:SCRATCH_MNT.*/HOSTNAME:SCRATCH_MNT/' \
754         -e 's#inventory/[0-9a-f-]*#inventory/UUID#' \
755
756 }
757
758
759 _dir_filter()
760 {
761   sed \
762     -e "s#$dump_file#DUMP_FILE#"      \
763     -e "s#$SCRATCH_DEV#SCRATCH_DEV#"        \
764     -e "s#$SCRATCH_RAWDEV#SCRATCH_DEV#"    \
765     -e "s#$dumptape#TAPE_DEV#"         \
766     -e "s#$dump_dir#DUMP_DIR#g"       \
767     -e "s#$restore_dir#RESTORE_DIR#g" \
768     -e "s#$SCRATCH_MNT#SCRATCH_MNT#g"       \
769     -e "s#$dump_sdir#DUMP_SUBDIR#g"   \
770     -e "s#$restore_sdir#RESTORE_SUBDIR#g" \
771     -e "s#$$#PID#g" \
772
773 }
774
775 _parse_args()
776 {
777     OPTIND=0
778     dump_args=""
779     while [ $# -gt 0 ]
780     do
781         case $1
782         in
783         -f)
784             [ -z "$2" ] && _error "missing argument for -f"
785             dumptape=$2 
786             shift
787             ;;
788         -L)
789             [ -z "$2" ] && _error "missing argument for -L"
790             session_label=$2
791             shift
792             ;;
793         -o)
794             dump_args="$dump_args -o"
795             ;;
796         -F)
797             dump_args="$dump_args -F"
798             ;;
799         --multi)
800             multi=$2
801             shift
802             ;;
803         -q)
804             do_quota_check=true
805             ;;
806         -Q)
807             do_quota_check=false
808             ;;
809         *)
810             _error "invalid argument"
811             ;;
812         esac
813         shift
814     done
815 }
816
817
818 #
819 # Dump a subdir
820 #
821 _do_dump_sub()
822 {
823     _parse_args $*
824
825     echo "Dumping to tape..."
826     opts="$_dump_debug$dump_args -s $dump_sdir -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
827     echo "xfsdump $opts" | _dir_filter  
828     xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
829 }
830
831 #
832 # Do full level 0 dump
833 #
834 _do_dump()
835 {
836     _parse_args $*
837
838     echo "Dumping to tape..."
839     opts="$_dump_debug$dump_args -l0 -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
840     echo "xfsdump $opts" | _dir_filter  
841     xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
842 }
843
844
845 #
846 # Do full dump with -m
847 #
848 _do_dump_min()
849 {
850     _parse_args $*
851
852     echo "Dumping to tape..."
853     onemeg=1048576
854     opts="$_dump_debug$dump_args -m -b $onemeg -l0 -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
855     echo "xfsdump $opts" | _dir_filter  
856     xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
857 }
858
859 #
860 # Do level 1 incremental dump
861 #
862 _do_dump_incremental()
863 {
864     _parse_args $*
865
866     echo "Dumping incrementally to tape..."
867     opts="$_dump_debug$dump_args -l1 -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
868     echo "xfsdump $opts" | _dir_filter  
869     xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
870 }
871
872 #
873 # Do full dump to file
874 #
875 _do_dump_file()
876 {
877     _parse_args $*
878
879     echo "Dumping to file..."
880     opts="$_dump_debug$dump_args -f $dump_file -M $media_label -L $session_label $SCRATCH_MNT"
881     echo "xfsdump $opts" | _dir_filter  
882     xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
883 }
884
885 #
886 # Do full dump to multiple files
887 #
888 _do_dump_multi_file()
889 {
890     _parse_args "$@"
891
892     multi_args=""
893
894     i=0
895     while [ $i -lt $multi ]
896     do
897         multi_args="$multi_args -f $dump_file.$i -M $media_label.$i"
898         i=`expr $i + 1`
899     done
900
901     echo "Dumping to files..."
902     opts="$_dump_debug$dump_args $multi_args -L $session_label $SCRATCH_MNT"
903     echo "xfsdump $opts" | _dir_filter  
904     xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
905 }
906
907
908 _prepare_restore_dir()
909 {
910     rm -rf $restore_dir
911     if ! mkdir $restore_dir; then
912         echo "    failed to mkdir $restore_dir"
913         status=1
914         exit
915     fi
916 }
917
918
919 #
920 # Get tape ready and restore dir
921 #
922 _prepare_restore()
923 {
924     _prepare_restore_dir
925
926     echo "Rewinding tape"
927     _rewind
928 }
929
930 #
931 # Restore the tape into $restore_dir
932 #
933 _do_restore()
934 {
935     _parse_args $*
936     _prepare_restore
937
938
939     echo "Restoring from tape..."
940     opts="$_restore_debug$dump_args -f $dumptape  -L $session_label $restore_dir"
941     echo "xfsrestore $opts" | _dir_filter  
942     xfsrestore $opts 2>&1 | tee -a $seq.full | _dump_filter
943 }
944
945 #
946 # Restore the tape into $restore_dir using -m
947 #
948 _do_restore_min()
949 {
950     _parse_args $*
951     _prepare_restore
952
953     echo "Restoring from tape..."
954     onemeg=1048576
955     opts="$_restore_debug$dump_args -m -b $onemeg -f $dumptape  -L $session_label $restore_dir"
956     echo "xfsrestore $opts" | _dir_filter  
957     xfsrestore $opts 2>&1 | tee -a $seq.full | _dump_filter
958 }
959
960 #
961 # Restore the tape from a dump file
962 #
963 _do_restore_file()
964 {
965     _parse_args $*
966     _prepare_restore_dir
967
968     echo "Restoring from file..."
969     opts="$_restore_debug$dump_args -f $dump_file  -L $session_label $restore_dir"
970     echo "xfsrestore $opts" | _dir_filter  
971     xfsrestore $opts 2>&1 | tee -a $seq.full | _dump_filter
972 }
973
974 #
975 # Restore the tape from multiple dump files
976 #
977 _do_restore_multi_file()
978 {
979     _parse_args "$@"
980     _prepare_restore_dir
981
982     multi_args=""
983
984     i=0
985     while [ $i -lt $multi ]
986     do
987         multi_args="$multi_args -f $dump_file.$i"
988         i=`expr $i + 1`
989     done
990
991     echo "Restoring from file..."
992     opts="$_restore_debug$dump_args $multi_args -L $session_label $restore_dir"
993     echo "xfsrestore $opts" | _dir_filter  
994     xfsrestore $opts 2>&1 | tee -a $seq.full | _dump_filter
995 }
996
997 #
998 # Do xfsdump piped into xfsrestore - xfsdump | xfsrestore
999 #
1000 # Use -s as we want to dump and restore to the same xfs partition
1001 #
1002 _do_dump_restore()
1003 {
1004     _parse_args $*
1005     _prepare_restore_dir
1006     echo "xfsdump|xfsrestore ..."
1007     restore_opts="$_restore_debug - $restore_dir"
1008     dump_opts="$_dump_debug$dump_args -s $dump_sdir - $SCRATCH_MNT"
1009     echo "xfsdump $dump_opts | xfsrestore $restore_opts" | _dir_filter  
1010     xfsdump $dump_opts 2>$tmp.dump.mlog | xfsrestore $restore_opts 2>&1 | tee -a $seq.full | _dump_filter
1011     _dump_filter <$tmp.dump.mlog
1012 }
1013
1014 #
1015 # Compare dumped subdirectory with restored dir
1016 # using ls -lR.
1017 # Thus no contents are compared but permissions, sizes,
1018 # owners, etc... are.
1019 #
1020 _ls_compare_sub()
1021 {
1022     #
1023     # verify we got back what we dumped
1024     #
1025     echo "Comparing listing of dump directory with restore directory"
1026     ls -lR $dump_dir | tee -a $seq.full | _ls_filter >$tmp.dump_dir
1027     ls -lR $restore_dir/$dump_sdir | tee -a $seq.full | _ls_filter \
1028     | sed -e "s#$restore_sdir\/##" >$tmp.restore_dir
1029
1030     diff -cs $tmp.dump_dir $tmp.restore_dir | sed -e "s#$tmp#TMP#g"
1031 }
1032
1033 #
1034 # filter out the date fields
1035 #
1036 _ls_nodate_filter()
1037 {
1038     $AWK_PROG 'NF == 9 { print $1, $2, $3, $4, $9 }'
1039 }
1040
1041 #
1042 # _ls_compare_sub but don't compare dates
1043 _ls_nodate_compare_sub()
1044 {
1045     #
1046     # verify we got back what we dumped
1047     #
1048     echo "Comparing listing of dump directory with restore directory"
1049     ls -lR $dump_dir | tee -a $seq.full | _ls_filter | _ls_nodate_filter >$tmp.dump_dir
1050     ls -lR $restore_dir/$dump_sdir | tee -a $seq.full | _ls_filter \
1051     | _ls_nodate_filter | sed -e "s#$restore_sdir\/##" >$tmp.restore_dir
1052
1053     diff -cs $tmp.dump_dir $tmp.restore_dir | sed -e "s#$tmp#TMP#g"
1054 }
1055
1056 #
1057 # Compare using recursive diff the files of the dumped
1058 # subdirectory.
1059 # This one will compare the contents.
1060 #
1061 _diff_compare_sub()
1062 {
1063     echo "Comparing dump directory with restore directory"
1064     diff -rs $dump_dir $restore_dir/$dump_sdir | _dir_filter | _check_quota_diff
1065 }
1066
1067 _get_eas_on_path()
1068 {
1069     _path=$1
1070
1071     find $_path -exec attr -l {} \; |\
1072     awk '{print $9, $2}' |\
1073     sed 's/["]//g' |\
1074     while read file ea_name; do
1075         attr -g $ea_name $file
1076     done
1077 }
1078
1079 #
1080 # Compare the extended attributes of the files/dirs
1081 # b/w the dumped and restore dirs.
1082 #
1083 #
1084 # Attribute "attr5" had a 8 byte value for /spare1/dump.5460/dir:
1085 # Attribute "attr5" had a 8 byte value for /spare1/restore.5460/dump.5460/dir:
1086 #
1087 _diff_compare_eas()
1088 {
1089     echo "Comparing dump directory with restore directory"
1090     echo "Looking at the extended attributes (EAs)"
1091     echo "EAs on dump"
1092     _get_eas_on_path $dump_dir | tee $seq.ea1 | _dir_filter
1093     echo "EAs on restore"
1094     _get_eas_on_path $restore_dir/$dump_sdir \
1095     | sed -e "s#$restore_sdir\/##" \
1096     | tee $seq.ea2 \
1097     | _dir_filter
1098     diff -s $seq.ea1 $seq.ea2
1099 }
1100
1101
1102 #
1103 # Compare using recursive diff the files of the dumped
1104 # filesystem
1105 #
1106 _diff_compare()
1107 {
1108     echo "Comparing dump directory with restore directory"
1109     diff -rs $SCRATCH_MNT $restore_dir | _dir_filter | _check_quota_diff
1110 }
1111
1112 #
1113 # Check out the dump inventory
1114 #
1115 _dump_inventory()
1116 {
1117     xfsdump $_dump_debug -I | tee -a $seq.full | _dump_filter_main
1118 }
1119
1120 #
1121 # Do the xfsinvutil cmd with debug and filters
1122 # Need to set variable: "$middate" to the invutil date 
1123 #
1124 _do_invutil()
1125 {
1126     host=`hostname`
1127     echo "xfsinvutil $_invutil_debug -M $host:$SCRATCH_MNT \"$middate\" $*" >$seq.full
1128     xfsinvutil $_invutil_debug $* -M $host:$SCRATCH_MNT "$middate" \
1129     | tee -a $seq.full | _invutil_filter
1130 }
1131
1132 #
1133 # Look for:
1134 # xfsdump: saving user quota information for: SCRATCH_MNT
1135 # xfsdump: saving group quota information for: SCRATCH_MNT
1136 # xfsrestore: user quota information written to ...'
1137 # xfsrestore: group quota information written to ...'
1138 #
1139 _check_quota_dumprestore()
1140 {
1141     uquota=0
1142     gquota=0 
1143     src/feature -U $SCRATCH_DEV && uquota=1
1144     src/feature -G $SCRATCH_DEV && gquota=1
1145
1146     $AWK_PROG -v uquota=$uquota -v gquota=$gquota -v full=$seq.full '
1147         /user quota information/ {
1148                         print "Found user quota:", $0 >>full
1149                         found_uquota = 1
1150                         if (!uquota) {
1151                             print "Found extra:", $0
1152                         }
1153                         next
1154         }
1155         /group quota information/ {
1156                         print "Found group quota:", $0 >>full
1157                         found_gquota = 1
1158                         if (!gquota) {
1159                             print "Found extra:", $0
1160                         }
1161                         next
1162         }
1163                         { print }
1164         END {
1165                 if (uquota && !found_uquota) {
1166                     print "Missing saving/restoring uquota msg"
1167                 }
1168                 if (gquota && !found_gquota) {
1169                     print "Missing saving/restoring gquota msg"
1170                 }
1171         }
1172     '
1173 }
1174
1175 #
1176 # Look for:
1177 # Only in RESTORE_DIR: xfsdump_quotas
1178 # Only in RESTORE_DIR: xfsdump_quotas_group
1179 #
1180
1181 _check_quota_diff()
1182 {
1183     uquota=0
1184     gquota=0 
1185     src/feature -U $SCRATCH_DEV && uquota=1
1186     src/feature -G $SCRATCH_DEV && gquota=1
1187
1188     $AWK_PROG -v uquota=$uquota -v gquota=$gquota '
1189         /Only in RESTORE_DIR: xfsdump_quotas_group/ {
1190                         found_gquota = 1
1191                         if (!gquota) {
1192                             print "Found extra:", $0
1193                         }
1194                         next
1195         }
1196         /Only in RESTORE_DIR: xfsdump_quotas/ {
1197                         found_uquota = 1
1198                         if (!uquota) {
1199                             print "Found extra:", $0
1200                         }
1201                         next
1202         }
1203                         { print }
1204         END {
1205                 if (uquota && !found_uquota) {
1206                     print "Missing xfsdump_quotas msg"
1207                 }
1208                 if (gquota && !found_gquota) {
1209                     print "Missing xfsdump_quotas_group msg"
1210                 }
1211         }
1212     '
1213 }
1214
1215 # make sure this script returns success
1216 /bin/true