common: use mount/umount helpers everywhere
[xfstests-dev.git] / common / dump
1 ##/bin/bash
2 #
3 # Copyright (c) 2000-2002,2005 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 # Functions useful for xfsdump/xfsrestore tests
20 #
21
22 # --- initializations ---
23 rm -f $seqres.full
24
25 if [ -n "$DEBUGDUMP" ]; then
26         _dump_debug=-v4
27         _restore_debug=-v4
28         _invutil_debug=-d
29
30         # Use dump/restore in qa directory (copy them here) for debugging
31         export PATH="$here:$PATH"
32         export __XFSDUMP_PROG="`set_prog_path xfsdump`"
33         export XFSDUMP_PROG="$__XFSDUMP_PROG -e"
34         export XFSRESTORE_PROG="`set_prog_path xfsrestore`"
35         export XFSINVUTIL_PROG="`set_prog_path xfsinvutil`"
36         [ -x $here/xfsdump ]    && echo "Using xfstests' xfsdump for debug"
37         [ -x $here/xfsrestore ] && echo "Using xfstests' xfsrestore for debug"
38         [ -x $here/xfsinvutil ] && echo "Using xfstests' xfsinvutil for debug"
39 fi
40
41 [ "$XFSDUMP_PROG" = "" ]    && _notrun "xfsdump not found"
42 [ "$XFSRESTORE_PROG" = "" ] && _notrun "xfsrestore not found"
43 [ "$XFSINVUTIL_PROG" = "" ] && _notrun "xfsinvutil not found"
44
45 # status returned for not run tests
46 NOTRUNSTS=2
47
48 # name those directories
49 dump_file=$tmp.dumpfile
50 # dump_file=$here/dumpfile #TEMP OVERRIDE DUMP FILE
51 dump_sdir=dumpdir
52 dump_dir=$SCRATCH_MNT/$dump_sdir
53 restore_sdir=restoredir
54 restore_dir=$SCRATCH_MNT/$restore_sdir
55 multi=3
56 dumptape=$TAPE_DEV
57 media_label="stress_tape_media"
58 session_label="stress_$seq"
59
60 nobody=4 # define this uid/gid as a number
61 do_quota_check=true # do quota check if quotas enabled
62
63 _need_to_be_root
64
65 # install our cleaner
66 trap "_cleanup; exit \$status" 0 1 2 3 15
67
68 # start inventory from a known base - move it aside for test
69 for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
70     if [ -d $dir ]; then
71         [ -d $dir.$seq ] && rm -rf $dir.$seq
72         mv $dir $dir.$seq
73     fi
74 done
75
76 have_mtvariable=false
77 [ `uname` = "Linux" ] && have_mtvariable=true
78
79
80 _require_multi_stream()
81 {
82     $XFSDUMP_PROG -JF -f /dev/null -f /dev/null 2> /dev/null |
83     grep -q "too many -f arguments" &&
84     _notrun "xfsdump multi-stream support required"
85 }
86
87 _require_legacy_v2_format()
88 {
89     $XFSDUMP_PROG 2>&1 |
90     grep -q "generate format 2 dump" ||
91     _notrun "xfsdump -K option required"
92
93     $XFSRESTORE_PROG 2>&1 |
94     grep -q "force use of format 2 generation" ||
95     _notrun "xfsrestore -K option required"
96 }
97
98 #
99 # do a remote/local mt
100 #
101 _mt()
102 {
103     op=$1
104     if _isrmt; then
105         # REMOTE
106         _rmtdev=`echo $dumptape | $AWK_PROG -F: '{print $2}'`
107
108         if echo $dumptape | grep '@' >/dev/null; then
109             _spec=`echo $dumptape | $AWK_PROG -F: '{print $1}'`
110             _rmtuser=`echo $_spec | $AWK_PROG -F@ '{print $1}'`
111             _rmthost=`echo $_spec | $AWK_PROG -F@ '{print $2}'`
112             rsh -n -l $_rmtuser $_rmthost "mt -t $_rmtdev $op"
113         else
114             _rmthost=`echo $dumptape | $AWK_PROG -F: '{print $1}'`
115             rsh -n $_rmthost "mt -t $_rmtdev $op"
116         fi
117     else
118         #LOCAL
119         mt -t $dumptape $op
120     fi
121 }
122
123 _check_onl()
124 {
125     _limit=10
126     i=0
127     while [ $i -lt $_limit ]; do
128         echo "Checking online..." >>$seqres.full
129         if _mt status >$tmp.status 2>&1; then
130             break;
131         else
132             sleep 1
133         fi
134         let i=$i+1
135     done
136
137
138     if [ $i -eq $_limit ]; then
139         echo "ERROR: mt -f $dumptape failed"
140         cat $tmp.status
141
142         _notrun "mt -f $dumptape failed"
143     fi
144
145
146     if egrep -i 'onl|ready' $tmp.status | grep -iv 'not ready' >/dev/null; then
147         :
148     else
149         echo "ERROR: $dumptape is not online"
150         cat $tmp.status
151
152         _notrun "dumptape, $dumptape, is not online"
153     fi
154 }
155
156 _wait_tape()
157 {
158     echo "Wait for tape, $dumptape, ..." >>$seqres.full
159
160     i=0
161     while [ $i -lt 20 ]; do
162         echo "Checking status..." >>$seqres.full
163         if _mt status 2>&1 | tee -a $seqres.full | egrep -i "onl|ready" >/dev/null; then
164             break;
165         else
166             sleep 1
167         fi
168         let i=$i+1
169     done
170 }
171
172 #
173 # Keep trying so we know we really have rewound
174 #
175 _rewind()
176 {
177     echo "Initiate rewind..." >>$seqres.full
178     _wait_tape
179     _mt rewind >/dev/null
180     _wait_tape
181 }
182
183 #
184 # Do a custom erase because:
185 # (i) some machines don't support it
186 # (ii) some machines take forever to do it
187 #
188 _erase_soft()
189 {
190     echo "Erasing tape" | tee -a $seqres.full
191     _rewind
192     _mt weof 3
193     _rewind
194 }
195
196 _erase_hard()
197 {
198     echo "Erasing tape" | tee -a $seqres.full
199     _mt erase
200 }
201
202 _isrmt()
203 {
204     echo $dumptape | grep ':' >/dev/null
205 }
206
207 #
208 # Get tape ready
209 #
210 _set_variable()
211 {
212     $have_mtvariable || return
213
214     if _isrmt; then
215         :
216     else
217         # LOCAL
218         echo "Put scsi tape driver into variable block size mode"
219         mt -f $dumptape setblk 0
220     fi
221 }
222
223 _require_tape()
224 {
225     dumptape=$1
226
227     if [ -z "$dumptape" -o "@" == "$dumptape" ]; then
228         _notrun "No dump tape specified"
229     fi
230
231     _check_onl
232     _set_variable
233 }
234
235 _wipe_fs()
236 {
237     _require_scratch
238
239     _scratch_mkfs_xfs >>$seqres.full || _fail "mkfs failed"
240     _scratch_mount >>$seqres.full || _fail "mount failed"
241 }
242
243 #
244 # Cleanup created dirs and files
245 # Called by trap
246 #
247 _cleanup()
248 {
249     # Some tests include this before checking _supported_fs xfs
250     # and the sleeps & checks here get annoying
251     if [ "$FSTYP" != "xfs" ]; then
252        return
253     fi
254
255     cd $here
256     rm -f $tmp.*
257
258     if [ -n "$DEBUGDUMP" ]; then
259         # save it for inspection
260         for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
261             [ -d $dir ] || continue
262             tar -cvf $seqres.inventory.tar $dir
263             ls -nR $dir >$seqres.inventory.ls
264         done
265     fi
266
267     # put inventory dir back
268     for dir in /var/xfsdump/inventory /var/lib/xfsdump/inventory; do
269         [ -d $dir.$seq ] || continue
270         rm -rf $dir             # get rid of new one
271         mv $dir.$seq $dir
272     done
273
274     if [ $status -ne $NOTRUNSTS ]; then
275         # Sleep added to stop _check_scratch_fs from complaining that the
276         # scratch_dev is still busy
277         sleep 10
278
279         _check_scratch_fs
280     fi
281 }
282
283 #
284 # ensure that bulkstat data will
285 # match with incore data
286 # by forcing disk data to be written out
287 #
288 _stable_fs()
289 {
290     _saveddir=`pwd`; cd /
291     _scratch_unmount >>$seqres.full || _fail "unmount failed"
292     _scratch_mount >>$seqres.full || _fail "mount failed"
293     cd $_saveddir
294 }
295
296 #
297 # Run fsstress to create a mixture of
298 # files,dirs,links,symlinks
299 #
300 # Pinched from test 013.
301 # Takes one argument, the number of ops to perform
302 #
303 _create_dumpdir_stress_num()
304 {
305     echo "Creating directory system to dump using fsstress."
306
307     _count=$1
308     _wipe_fs
309
310     _param="-f link=10 -f creat=10 -f mkdir=10 -f truncate=5 -f symlink=10"
311     rm -rf $dump_dir
312     if ! mkdir $dump_dir; then
313         echo "    failed to mkdir $dump_dir"
314         status=1
315         exit
316     fi
317     echo ""
318     echo "-----------------------------------------------"
319     echo "fsstress : $_param"
320     echo "-----------------------------------------------"
321     if ! $here/ltp/fsstress $_param -s 1 $FSSTRESS_AVOID -n $_count -d $dump_dir >$tmp.out 2>&1
322     then
323         echo "    fsstress (count=$_count) returned $? - see $seqres.full"
324
325         echo "--------------------------------------"       >>$seqres.full
326         echo "output from fsstress:"                        >>$seqres.full
327         echo "--------------------------------------"       >>$seqres.full
328         cat $tmp.out                                        >>$seqres.full
329         status=1
330     fi
331
332     _stable_fs
333 }
334
335 _create_dumpdir_stress() {
336         _create_dumpdir_stress_num 240
337 }
338
339 _mk_fillconfig1()
340 {
341     cat <<End-of-File >$tmp.config
342 # pathname      size in bytes   owner   group
343 #
344 small           10      $nobody $nobody
345 big             102400  daemon  sys
346 sub/small       10      bin     bin
347 sub/big         102400  $nobody sys
348 #
349 sub/a           1       $nobody $nobody
350 sub/b           2       $nobody $nobody
351 sub/c           4       $nobody $nobody
352 sub/d           8       $nobody $nobody
353 sub/e           16      $nobody $nobody
354 sub/f           32      $nobody $nobody
355 sub/g           64      $nobody $nobody
356 sub/h           128     $nobody $nobody
357 sub/i           256     $nobody $nobody
358 sub/j           512     $nobody $nobody
359 sub/k           1024    $nobody $nobody
360 sub/l           2048    $nobody $nobody
361 sub/m           4096    $nobody $nobody
362 sub/n           8192    $nobody $nobody
363 #
364 sub/a00         100     $nobody $nobody
365 sub/b00         200     $nobody $nobody
366 sub/c00         400     $nobody $nobody
367 sub/d00         800     $nobody $nobody
368 sub/e00         1600    $nobody $nobody
369 sub/f00         3200    $nobody $nobody
370 sub/g00         6400    $nobody $nobody
371 sub/h00         12800   $nobody $nobody
372 sub/i00         25600   $nobody $nobody
373 sub/j00         51200   $nobody $nobody
374 sub/k00         102400  $nobody $nobody
375 sub/l00         204800  $nobody $nobody
376 sub/m00         409600  $nobody $nobody
377 sub/n00         819200  $nobody $nobody
378 #
379 sub/a000        1000    $nobody $nobody
380 sub/e000        16000   $nobody $nobody
381 sub/h000        128000  $nobody $nobody
382 sub/k000        1024000 $nobody $nobody
383 End-of-File
384 }
385
386 _mk_fillconfig2()
387 {
388     cat <<End-of-File >$tmp.config
389 # pathname      size in bytes
390 #
391 smalll          10      $nobody $nobody
392 biggg           102400  $nobody $nobody
393 sub/smalll      10      $nobody $nobody
394 sub/biggg       102400  $nobody $nobody
395 End-of-File
396 }
397
398 _mk_fillconfig_perm()
399 {
400     # dir_guid: ugo=rwx,g+s on dir is for IRIX chmod(1)
401
402     cat <<End-of-File >$tmp.config
403 # pathname      size/dir  user group mode
404 #
405 file_suid       10      $nobody $nobody 04777
406 file_guid       10      $nobody $nobody 02777
407 file_sticky     10      $nobody $nobody 01777
408 file_mix1       10      $nobody $nobody 761
409 file_mix2       10      $nobody $nobody 642
410 dir_suid        d       $nobody $nobody 04777
411 dir_guid        d       $nobody $nobody ugo=rwx,g+s
412 dir_sticky      d       $nobody $nobody 01777
413 dir_mix1        d       $nobody $nobody 761
414 dir_mix2        d       $nobody $nobody 642
415 End-of-File
416 }
417
418 _mk_fillconfig_ea()
419 {
420     cat <<End-of-File >$tmp.config
421 # pathname      size    user    group    perm   name value namespace
422 #
423 smalll          10      $nobody $nobody  777    attr1 some_text   user
424 biggg           102400  $nobody $nobody  777    attr2 some_text2  root
425 sub/smalll      10      $nobody $nobody  777    attr3 some_text3  user
426 sub/biggg       102400  $nobody $nobody  777    attr4 some_text4  root
427 dir             d       $nobody $nobody  777    attr5 dir_text    user
428 #
429 # Add more files so that there are more than the number
430 # of streams.
431 # There are bugs in dump/restore for # non-dir files < # streams
432 # It can be tested in another configuration.
433 # It is a pathalogical case.
434 #
435 sub/a           1       $nobody $nobody
436 sub/b           2       $nobody $nobody
437 sub/c           4       $nobody $nobody
438 sub/d           8       $nobody $nobody
439 sub/e           16      $nobody $nobody
440 sub/f           32      $nobody $nobody
441 sub/g           64      $nobody $nobody
442 sub/h           128     $nobody $nobody
443 sub/i           256     $nobody $nobody
444 sub/j           512     $nobody $nobody
445 sub/k           1024    $nobody $nobody
446 sub/l           2048    $nobody $nobody
447 sub/m           4096    $nobody $nobody
448 sub/n           8192    $nobody $nobody
449 End-of-File
450 }
451
452 #
453 # extended file attribute flags
454 #
455 _mk_fillconfig_xattr()
456 {
457     cat <<End-of-File >$tmp.config
458 # pathname      size    user    group    perm   name
459 #
460 xflag_realtime  10      $nobody $nobody  777    XFS_XFLAG_REALTIME
461 xflag_prealloc  10      $nobody $nobody  777    XFS_XFLAG_PREALLOC
462 xflag_immutable 10      $nobody $nobody  777    XFS_XFLAG_IMMUTABLE
463 xflag_append    10      $nobody $nobody  777    XFS_XFLAG_APPEND
464 xflag_sync      10      $nobody $nobody  777    XFS_XFLAG_SYNC
465 xflag_noatime   10      $nobody $nobody  777    XFS_XFLAG_NOATIME
466 xflag_nodump    10      $nobody $nobody  777    XFS_XFLAG_NODUMP
467 xflag_hasattr   10      $nobody $nobody  777    XFS_XFLAG_HASATTR
468 End-of-File
469 }
470
471 #
472 # Create a bunch of directories/files of different sizes
473 # filled with data.
474 #
475 # Pinched from test 001.
476 #
477 _do_create_dumpdir_fill()
478 {
479     echo "Creating directory system to dump using src/fill."
480
481     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
482     cd $dump_dir
483
484     $verbose && echo -n "Setup "
485     sed -e '/^#/d' $tmp.config \
486     | while read file nbytes owner group perms ea_name ea_value namespace
487     do
488         if [ $nbytes = "d" ]; then
489             # create a directory
490             dir=$file
491             if [ ! -d $dir ]
492             then
493                 if mkdir $dir
494                 then
495                     :
496                 else
497                     $verbose && echo
498                     echo "Error: cannot mkdir \"$dir\""
499                     exit 1
500                 fi
501             fi
502         else
503             # create a directory/file
504             dir=`dirname $file`
505             if [ "$dir" != "." ]
506             then
507                 if [ ! -d $dir ]
508                 then
509                     if mkdir $dir
510                     then
511                         :
512                     else
513                         $verbose && echo
514                         echo "Error: cannot mkdir \"$dir\""
515                         exit 1
516                     fi
517                 fi
518             fi
519             rm -f $file
520             if $here/src/fill $file $file $nbytes
521             then
522                 :
523             else
524                 $verbose && echo
525                 echo "Error: cannot create \"$file\""
526                 exit 1
527             fi
528         fi
529         if [ -n "$owner" -a -n "$group" ]; then
530             chown $owner.$group $file
531         fi
532         if [ -n "$perms" ]; then
533             chmod $perms $file
534         fi
535
536         # extended attributes (EA)
537         if [ -n "$ea_name" -a -n "$ea_value" ]; then
538             if [ "X$namespace" = "Xroot" ]; then
539                 attr -R -s $ea_name -V $ea_value $file
540             else
541                 attr -s $ea_name -V $ea_value $file
542             fi
543         # extended file attribute flags - no value - NOT EAs
544         elif [ -n "$ea_name" -a -z "$ea_value" ]; then
545             # set the flag
546             # TODO XXX
547             # use xfs_io to send the ioctl
548             :
549         fi
550         $verbose && echo -n "."
551     done
552     $verbose && echo
553
554     cd $here
555 }
556
557 _mk_fillconfig_multi()
558 {
559     _mk_fillconfig1
560     cat <<End-of-File >>$tmp.config
561 # pathname      size in bytes
562 #
563 large000        8874368 $nobody $nobody
564 large111        2582912 $nobody $nobody
565 large222        7825792 $nobody $nobody
566 End-of-File
567 }
568
569 _create_dumpdir_largefile()
570 {
571     _wipe_fs
572     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
573     _largesize=4294967297
574     _largefile=$dump_dir/largefile
575     echo "dd a largefile at offset $_largesize"
576     POSIXLY_CORRECT=yes \
577     dd if=/dev/zero of=$_largefile bs=1 seek=$_largesize count=10 2>&1
578     _stable_fs
579 }
580
581 _create_dumpdir_fill()
582 {
583     _wipe_fs
584     _mk_fillconfig1
585     _do_create_dumpdir_fill
586     _stable_fs
587 }
588
589 _create_dumpdir_fill2()
590 {
591     _wipe_fs
592     _mk_fillconfig2
593     _do_create_dumpdir_fill
594     _stable_fs
595 }
596
597 _create_dumpdir_fill_perm()
598 {
599     _wipe_fs
600     _mk_fillconfig_perm
601     _do_create_dumpdir_fill
602     _stable_fs
603 }
604
605 _create_dumpdir_fill_ea()
606 {
607     _wipe_fs
608     _mk_fillconfig_ea
609     _do_create_dumpdir_fill
610     _stable_fs
611 }
612
613 #
614 # Create enough files, and a few large enough files, so that
615 # some files are likely to be split across streams.
616 #
617 _create_dumpdir_fill_multi()
618 {
619     _wipe_fs
620     _mk_fillconfig_multi
621     _do_create_dumpdir_fill
622     _stable_fs
623 }
624
625 #
626 # Append a subset of the fill'ed files
627 # So we can see if just these get dumped on an incremental
628 #
629 _append_dumpdir_fill()
630 {
631     cd $dump_dir
632     cat <<End-of-File >$tmp.config
633 # pathname
634 #
635 small
636 sub/big
637 #
638 sub/a
639 sub/c
640 sub/e
641 End-of-File
642     sed -e '/^#/d' $tmp.config \
643     | while read file
644     do
645         echo 'Extra text' >>$file
646     done
647
648     cd $here
649     _stable_fs
650 }
651
652 _do_create_dump_symlinks()
653 {
654     echo "Creating directory system of symlinks to dump."
655
656     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
657     cd $dump_dir
658
659     $verbose && echo -n "Setup "
660     sed -e '/^#/d' $tmp.config \
661     | while read file nbytes owner group owner2 group2 perms perms2
662     do
663         dir=`dirname $file`
664         if [ "$dir" != "." ]
665         then
666             if [ ! -d $dir ]
667             then
668                 if mkdir $dir
669                 then
670                     :
671                 else
672                     $verbose && echo
673                     echo "Error: cannot mkdir \"$dir\""
674                     exit 1
675                 fi
676             fi
677         fi
678         rm -f $file
679         touch $file
680
681         # Do chmod on symlink using umask.
682         # This won't do the right thing as it subtracts permissions.
683         # However, I don't care, as long as I get some different perms
684         # for testing.
685         if [ -n "$perms2" ]; then
686             omask=`umask`
687             umask $perms2
688         fi
689         ln -s $file $file-link
690         if [ -n "$perms2" ]; then
691             umask $omask
692         fi
693
694         if [ -n "$owner" -a -n "$group" ]; then
695             chown $owner.$group $file
696         fi
697         if [ -n "$owner" -a -n "$group" ]; then
698             chown -h $owner.$group $file-link
699         fi
700         if [ -n "$perms" ]; then
701             chmod $perms $file
702         fi
703         $verbose && echo -n "."
704     done
705     $verbose && echo
706
707     cd $here
708 }
709
710 _mk_symlink_config()
711 {
712     cat <<End-of-File >$tmp.config
713 # path  size    owner1  group1  owner2  group2  perm1   perm2
714 #
715 a       0       $nobody $nobody daemon  sys     124     421
716 b       0       daemon  sys     bin     bin     347     743
717 sub/a   0       bin     bin     $nobody sys     777     777
718 sub/b   0       $nobody sys     $nobody $nobody 367     763
719 End-of-File
720 }
721
722 _create_dumpdir_symlinks()
723 {
724     _wipe_fs
725     _mk_symlink_config
726     _do_create_dump_symlinks
727     _stable_fs
728 }
729
730 #
731 # create hardlinks of form $_fname, $_fname_h1 $_fname_h2 ...
732 #
733 _create_hardlinks()
734 {
735     _fname=$1
736     _numlinks=$2
737
738     touch $_fname
739     _j=1
740     while [ $_j -le $_numlinks ]; do
741         _suffix=_h$_j
742         _hardlink=$_fname$_suffix
743         echo "creating hardlink $_hardlink to $_fname"
744         ln $_fname $_hardlink
745         let _j=$_j+1
746     done
747 }
748
749 #
750 # create a set of hardlinks
751 # create hardlinks of form file1, file1_h1 file1_h2 ...
752 # create hardlinks of form file2, file2_h1 file2_h2 ...
753 # create hardlinks of form file3, file3_h1 file3_h2 ...
754 #
755 _create_hardset()
756 {
757     _numsets=$1
758     _i=1
759     while [ $_i -le $_numsets ]; do
760         _create_hardlinks file$_i 5
761         let _i=$_i+1
762     done
763 }
764
765
766 _modify_level()
767 {
768     _level=$1
769     echo "mod level $_level" >$dump_dir/file$_level
770 }
771
772 _create_dumpdir_hardlinks()
773 {
774     _numsets=$1
775     _wipe_fs
776     echo "Creating directory system of hardlinks to incrementally dump."
777
778     mkdir -p $dump_dir || _fail "cannot mkdir \"$dump_dir\""
779     cd $dump_dir
780
781     _create_hardset $_numsets
782
783     cd $here
784     _stable_fs
785 }
786
787 #
788 # Filter for ls
789 # Filter out times and dates on symlinks and char devices.
790 # Filter out size on directories because this can differ
791 # when transitioning to long inode numbers (ie. 64 bits).
792 #
793 _ls_filter()
794 {
795   $AWK_PROG '
796         /^l/ { date = $8; time = $7; sub(date,"DATE"); sub(time,"TIME"); print}
797         /^c/ { date = $9; time = $7; sub(date,"DATE"); sub(time,"TIME"); print}
798         /^d/ { size = $5; sub(size,"SIZE"); print}
799         {print}' \
800   | sed -e 's/total [0-9][0-9]*/total TOTAL/'
801 }
802
803 #
804 # Filtering of Irix character hwgraph device names
805 # e.g.
806 # chardev: /hw/node/xtalk/15/pci/0/scsi_ctlr/0/target/1/lun/0/disk/partition/4/char
807 # blkdev:  /dev/dsk/dks0d1s4
808 #
809 _filter_devchar()
810 {
811     $AWK_PROG '
812         /\/hw\/node/ {
813             sub(/\/hw.*scsi_ctlr\//,"/dev/dsk/dks")  # blah blah /dev/dsk/dks0/target/1/....
814             sub(/\/target\//,"d")                    # blah blah /dev/dsk/dks0d1/lun/0/disk.....
815             sub(/\/lun.*partition\//,"s")            # blah blah /dev/dsk/dks0d1s4/char
816             sub(/\/char/,"")                         # blah blah /dev/dsk/dks0d1s4
817         }
818         { print }
819     '
820 }
821
822
823 #
824 # Filter out the non-deterministic dump msgs from
825 # xfsdump and xfsrestore
826 #
827 _dump_filter_main()
828 {
829   _filter_devchar |\
830   sed \
831       -e "s#$__XFSDUMP_PROG#xfsdump#"                   \
832       -e "s#$XFSRESTORE_PROG#xfsrestore#"               \
833       -e "s#$XFSINVUTIL_PROG#xfsinvutil#"               \
834       -e "s/`hostname`/HOSTNAME/"                       \
835       -e "s#$SCRATCH_DEV#SCRATCH_DEV#"                  \
836       -e "s#$SCRATCH_RAWDEV#SCRATCH_DEV#"               \
837       -e "s#$dumptape#TAPE_DEV#"                        \
838       -e "s#$SCRATCH_MNT#SCRATCH_MNT#"                  \
839       -e "s#$dump_file#DUMP_FILE#"                      \
840       -e 's#/var/lib/xfsdump#/var/xfsdump#'             \
841       -e 's/session id:[        ]*[0-9a-f-]*/session id: ID/'  \
842       -e '/filesystem id:[      ]*[0-9a-f-]*/d'         \
843       -e 's/time:[      ].*/time: TIME/'                \
844       -e 's/date:[      ].*/date: DATE/'                \
845       -e 's/dump begun .*/dump begun DATE/'             \
846       -e 's/previously begun .*/previously begun DATE/' \
847       -e 's/[0-9][0-9]* seconds/SECS seconds/'          \
848       -e 's/restore.[0-9][0-9]*/restore.PID/'           \
849       -e 's/ino [0-9][0-9]*/ino INO/g'                  \
850       -e '/stream [0-9]:/s/offset [0-9][0-9]*/offset NUM/g'     \
851       -e '/: dump size/s/[0-9][0-9]*/NUM/'              \
852       -e '/dump size:/s/[0-9][0-9]*/NUM/'               \
853       -e '/dump size per stream:/s/[0-9][0-9]*/NUM/'    \
854       -e 's/\(media file size[   ]*\)[0-9][0-9]*/\1NUM/' \
855       -e 's/\(mfile size:[       ]*\)[0-9][0-9]*/\1NUM/' \
856       -e '/drive[        ]*[0-9][0-9]*:/d'              \
857       -e '/\/dev\/tty/d'                                \
858       -e '/inventory session uuid/d'                    \
859       -e '/ - Running single-threaded/d'                \
860       -e '/Mount point match/d'                         \
861       -e '/^.*I\/O metrics: .*$/d'                      \
862       -e 's/1048576/BLOCKSZ/'                           \
863       -e 's/2097152/BLOCKSZ/'                           \
864       -e 's/(pid[        ]*[1-9][0-9]*)/\(pid PID\)/'   \
865       -e '/version [3-9]\.[0-9]/d'                      \
866       -e 's/\/hw\/module.*$/SCRATCH_DEV/'               \
867       -e 's/xfsdump: ino map phase 1: .*/xfsdump: ino map <PHASES>/' \
868       -e '/xfsdump: ino map phase [2]/,1d'              \
869       -e '/xfsdump: ino map phase [3]/,1d'              \
870       -e '/xfsdump: ino map phase [4]/,1d'              \
871       -e '/xfsdump: ino map phase [5]/,1d'              \
872       -e 's/id:[[:space:]]*[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}/ID: ID/'                                              \
873       -e 's/\[y\/n\][- ]----------------------*/\[y\/n\]/'              \
874       -e '/skip attribute set/d'                                \
875   | perl -ne '
876         # filter out all the output between the lines "Dump Summary:"
877         # and "Dump Status:"
878         if ($_ =~ /(?:Dump|Restore) Summary/) {
879                 $skip = 1;
880         } elsif ($_ =~ /(?:Dump|Restore) Status/) {
881                 $skip = 0;
882         }
883         print if (! $skip);' \
884   | perl -ne '
885         # correct the file count if large scratch devices are being used
886         $skip = 0;
887         if ($_ =~ /(\S+) directories and (\S+) entries/) {
888                 $foo = $2;
889                 if ($ENV{'LARGE_SCRATCH_DEV'} && $foo > 0) {
890                         $foo -= 1;
891                 }
892                 printf("xfsrestore: %u directories and %u entries processed\n",
893                                                 $1, $foo);
894                 $skip = 1;
895         }
896         print if (! $skip);'
897 }
898
899 _dump_filter()
900 {
901    if $do_quota_check
902    then
903        _dump_filter_main | _check_quota_dumprestore | _check_quota_entries
904    else
905        _dump_filter_main
906    fi
907 }
908
909 _invutil_filter()
910 {
911   _dump_filter_main \
912   | sed \
913         -e 's/UUID[     ]*:[    ][0-9a-f-]*/UUID                :       ID/' \
914         -e 's/TIME OF DUMP[     ]*:.*/TIME OF DUMP      :       TIME/' \
915         -e 's/HOSTNAME:SCRATCH_MNT.*/HOSTNAME:SCRATCH_MNT/' \
916         -e 's#inventory/[0-9a-f-]*#inventory/UUID#' \
917
918 }
919
920
921 _dir_filter()
922 {
923   sed \
924     -e "s#$dump_file#DUMP_FILE#g"      \
925     -e "s#$SCRATCH_DEV#SCRATCH_DEV#"        \
926     -e "s#$SCRATCH_RAWDEV#SCRATCH_DEV#"    \
927     -e "s#$dumptape#TAPE_DEV#"         \
928     -e "s#$dump_dir#DUMP_DIR#g"       \
929     -e "s#$restore_dir#RESTORE_DIR#g" \
930     -e "s#$SCRATCH_MNT#SCRATCH_MNT#g"       \
931     -e "s#$dump_sdir#DUMP_SUBDIR#g"   \
932     -e "s#$restore_sdir#RESTORE_SUBDIR#g" \
933     -e "s#$$#PID#g" \
934     -e "/Only in SCRATCH_MNT: .use_space/d" \
935     -e "s#$RESULT_DIR/##g" \
936
937 }
938
939 #
940 # Parse xfsdump arguments.
941 # Note: requires a space between option letter and argument
942 #
943 _parse_dump_args()
944 {
945     OPTIND=0
946     dump_args=""
947     while [ $# -gt 0 ]
948     do
949         case $1
950         in
951         -f)
952             [ -z "$2" ] && _fail "missing argument for -f"
953             dumptape=$2
954             dump_file=$2
955             shift
956             ;;
957         -L)
958             [ -z "$2" ] && _fail "missing argument for -L"
959             session_label=$2
960             shift
961             ;;
962         --multi)
963             [ -z "$2" ] && _fail "missing argument for --multi"
964             multi=$2
965             shift
966             ;;
967         --check-quota)
968             do_quota_check=true
969             ;;
970         --no-check-quota)
971             do_quota_check=false
972             ;;
973         -o|-D|-F|-K)
974             dump_args="$dump_args $1"
975             ;;
976         -l|-d)
977             [ -z "$2" ] && _fail "missing argument for $1"
978             dump_args="$dump_args $1$2"
979             shift
980             ;;
981         *)
982             _fail "invalid argument to common/dump function: $1"
983             ;;
984         esac
985         shift
986     done
987 }
988
989 #
990 # Parse xfsrestore arguments.
991 # Note: requires a space between option letter and argument
992 #
993 _parse_restore_args()
994 {
995     OPTIND=0
996     restore_args=""
997     while [ $# -gt 0 ]
998     do
999         case $1
1000         in
1001         -f)
1002             [ -z "$2" ] && _fail "missing argument for -f"
1003             dumptape=$2
1004             dump_file=$2
1005             shift
1006             ;;
1007         -L)
1008             [ -z "$2" ] && _fail "missing argument for -L"
1009             session_label=$2
1010             shift
1011             ;;
1012         --multi)
1013             [ -z "$2" ] && _fail "missing argument for --multi"
1014             multi=$2
1015             shift
1016             ;;
1017         --check-quota)
1018             do_quota_check=true
1019             ;;
1020         --no-check-quota)
1021             do_quota_check=false
1022             ;;
1023         -K|-R)
1024             restore_args="$restore_args $1"
1025             ;;
1026         *)
1027             _fail "invalid argument to common/dump function: $1"
1028             ;;
1029         esac
1030         shift
1031     done
1032 }
1033
1034
1035 #
1036 # Dump a subdir
1037 #
1038 _do_dump_sub()
1039 {
1040     _parse_dump_args $*
1041
1042     echo "Dumping to tape..."
1043     opts="$_dump_debug$dump_args -s $dump_sdir -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
1044     echo "xfsdump $opts" | _dir_filter
1045     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1046 }
1047
1048 #
1049 # Do dump to tape
1050 #
1051 _do_dump()
1052 {
1053     _parse_dump_args $*
1054
1055     echo "Dumping to tape..."
1056     opts="$_dump_debug$dump_args -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
1057     echo "xfsdump $opts" | _dir_filter
1058     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1059 }
1060
1061
1062 #
1063 # Do full dump with -m
1064 #
1065 _do_dump_min()
1066 {
1067     _parse_dump_args $*
1068
1069     echo "Dumping to tape..."
1070     onemeg=1048576
1071     opts="$_dump_debug$dump_args -m -b $onemeg -l0 -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
1072     echo "xfsdump $opts" | _dir_filter
1073     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1074 }
1075
1076
1077 #
1078 # Do full dump to file
1079 #
1080 _do_dump_file()
1081 {
1082     _parse_dump_args $*
1083
1084     echo "Dumping to file..."
1085     opts="$_dump_debug$dump_args -f $dump_file -M $media_label -L $session_label $SCRATCH_MNT"
1086     echo "xfsdump $opts" | _dir_filter
1087     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1088 }
1089
1090 #
1091 # Do full dump to multiple files
1092 #
1093 _do_dump_multi_file()
1094 {
1095     _parse_dump_args $*
1096
1097     multi_args=""
1098
1099     i=0
1100     while [ $i -lt $multi ]
1101     do
1102         multi_args="$multi_args -f $dump_file.$i -M $media_label.$i"
1103         let i=$i+1
1104     done
1105
1106     echo "Dumping to files..."
1107     opts="$_dump_debug$dump_args $multi_args -L $session_label $SCRATCH_MNT"
1108     echo "xfsdump $opts" | _dir_filter
1109     $XFSDUMP_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1110 }
1111
1112
1113 _prepare_restore_dir()
1114 {
1115     rm -rf $restore_dir
1116     mkdir $restore_dir || _fail "failed to mkdir $restore_dir"
1117 }
1118
1119
1120 #
1121 # Get tape ready and restore dir
1122 #
1123 _prepare_restore()
1124 {
1125     _prepare_restore_dir
1126
1127     echo "Rewinding tape"
1128     _rewind
1129 }
1130
1131 #
1132 # Restore the tape into $restore_dir
1133 #
1134 _do_restore()
1135 {
1136     _parse_restore_args $*
1137     _prepare_restore
1138
1139     echo "Restoring from tape..."
1140     opts="$_restore_debug$restore_args -f $dumptape  -L $session_label $restore_dir"
1141     echo "xfsrestore $opts" | _dir_filter
1142     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1143 }
1144
1145 #
1146 # Restore the tape into $restore_dir using -m
1147 #
1148 _do_restore_min()
1149 {
1150     _parse_restore_args $*
1151     _prepare_restore
1152
1153     echo "Restoring from tape..."
1154     onemeg=1048576
1155     opts="$_restore_debug$restore_args -m -b $onemeg -f $dumptape  -L $session_label $restore_dir"
1156     echo "xfsrestore $opts" | _dir_filter
1157     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1158 }
1159
1160 #
1161 # Restore the tape from a dump file
1162 #
1163 _do_restore_file()
1164 {
1165     _parse_restore_args $*
1166     _prepare_restore_dir
1167
1168     echo "Restoring from file..."
1169     opts="$_restore_debug$restore_args -f $dump_file  -L $session_label $restore_dir"
1170     echo "xfsrestore $opts" | _dir_filter
1171     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1172 }
1173
1174 #
1175 # Cumulative restore from a file
1176 # Must call _prepare_restore_dir before the first
1177 # (and only the first) call to this function.
1178 #
1179 _do_restore_file_cum()
1180 {
1181     _parse_restore_args $*
1182
1183     echo "Restoring cumumlative from file..."
1184     opts="$_restore_debug$restore_args -f $dump_file -r $restore_dir"
1185     echo "xfsrestore $opts" | _dir_filter
1186     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1187 }
1188
1189 _do_restore_toc()
1190 {
1191     _parse_restore_args $*
1192
1193     echo "Contents of dump ..."
1194     opts="$_restore_debug$restore_args -f $dump_file -t"
1195     echo "xfsrestore $opts" | _dir_filter
1196     cd $SCRATCH_MNT # for IRIX which needs xfs cwd
1197     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter_main |\
1198     _check_quota_file |\
1199     _check_quota_entries |\
1200     $AWK_PROG 'NF != 1 { print; next }
1201                {files = sprintf("%s\n%s", files, $1)}
1202                 END { print files | "sort" } '
1203     # the above awk code is to alpha sort only the output
1204     # of files (and not the verbose restore msgs)
1205     cd $here # put back
1206 }
1207
1208 #
1209 # Restore the tape from multiple dump files
1210 #
1211 _do_restore_multi_file()
1212 {
1213     _parse_restore_args $*
1214     _prepare_restore_dir
1215
1216     multi_args=""
1217
1218     i=0
1219     while [ $i -lt $multi ]
1220     do
1221         multi_args="$multi_args -f $dump_file.$i"
1222         let i=$i+1
1223     done
1224
1225     echo "Restoring from file..."
1226     opts="$_restore_debug$restore_args $multi_args -L $session_label $restore_dir"
1227     echo "xfsrestore $opts" | _dir_filter
1228     $XFSRESTORE_PROG $opts 2>&1 | tee -a $seqres.full | _dump_filter
1229 }
1230
1231 #
1232 # Do xfsdump piped into xfsrestore - xfsdump | xfsrestore
1233 # Pass dump options in $1 and restore options in $2, if required. e.g.:
1234 #     _do_dump_restore "-o -F" "-R"
1235 #     _do_dump_restore "" "-R"
1236 #
1237 # Use -s as we want to dump and restore to the same xfs partition
1238 #
1239 _do_dump_restore()
1240 {
1241     _parse_dump_args $1
1242     _parse_restore_args $2
1243     _prepare_restore_dir
1244     echo "xfsdump|xfsrestore ..."
1245     restore_opts="$_restore_debug$restore_args - $restore_dir"
1246     dump_opts="$_dump_debug$dump_args -s $dump_sdir - $SCRATCH_MNT"
1247     echo "xfsdump $dump_opts | xfsrestore $restore_opts" | _dir_filter
1248     $XFSDUMP_PROG $dump_opts 2>$tmp.dump.mlog | $XFSRESTORE_PROG $restore_opts 2>&1 | tee -a $seqres.full | _dump_filter
1249     _dump_filter <$tmp.dump.mlog
1250 }
1251
1252 #
1253 # Compare dumped subdirectory with restored dir
1254 # using ls -nR.
1255 # Thus no contents are compared but permissions, sizes,
1256 # owners, etc... are.
1257 #
1258 _ls_compare_sub()
1259 {
1260     #
1261     # verify we got back what we dumped
1262     #
1263     echo "Comparing listing of dump directory with restore directory"
1264     ls -nR $dump_dir | tee -a $seqres.full | _ls_filter >$tmp.dump_dir
1265     ls -nR $restore_dir/$dump_sdir | tee -a $seqres.full | _ls_filter \
1266     | sed -e "s#$restore_sdir\/##" >$tmp.restore_dir
1267
1268     diff -bcs $tmp.dump_dir $tmp.restore_dir | sed -e "s#$tmp#TMP#g"
1269 }
1270
1271 #
1272 # filter out the date fields
1273 #
1274 _ls_nodate_filter()
1275 {
1276     $AWK_PROG 'NF == 9 { print $1, $2, $3, $4, $9 }'
1277 }
1278
1279 #
1280 # _ls_compare_sub but don't compare dates
1281 _ls_nodate_compare_sub()
1282 {
1283     #
1284     # verify we got back what we dumped
1285     #
1286     echo "Comparing listing of dump directory with restore directory"
1287     ls -nR $dump_dir | tee -a $seqres.full | _ls_filter | _ls_nodate_filter >$tmp.dump_dir
1288     ls -nR $restore_dir/$dump_sdir | tee -a $seqres.full | _ls_filter \
1289     | _ls_nodate_filter | sed -e "s#$restore_sdir\/##" >$tmp.restore_dir
1290
1291     diff -bcs $tmp.dump_dir $tmp.restore_dir | sed -e "s#$tmp#TMP#g"
1292 }
1293
1294 #
1295 # Compare using recursive diff the files of the dumped
1296 # subdirectory.
1297 # This one will compare the contents.
1298 #
1299 _diff_compare_sub()
1300 {
1301     echo "Comparing dump directory with restore directory"
1302     diff -rs $dump_dir $restore_dir/$dump_sdir | _dir_filter
1303 }
1304
1305 _get_eas_on_path()
1306 {
1307     _path=$1
1308
1309 # Tim - this is the IRIX way...
1310     # find $_path -exec attr -l {} \; |\
1311     # awk '{print $9, $2}' |\
1312     # sed 's/["]//g' |\
1313     # sort |\
1314 # and this is now the Linux way...
1315     echo "User names"
1316     getfattr --absolute-names -Rh -m user $_path |\
1317     perl -wn -e '
1318         if (m/^# file: (\S+)/) { $file = $1 }
1319         elsif (m/^user\.(\w+)/) { print $file, " ",$1,"\n" }' |\
1320     sort |\
1321     while read file ea_name; do
1322         attr -g $ea_name $file
1323     done
1324
1325     if [ "$USE_ATTR_SECURE" = yes ]; then
1326         echo "Security names"
1327         getfattr --absolute-names -Rh -m security $_path |\
1328         perl -wn -e '
1329             if (m/^# file: (\S+)/) { $file = $1 }
1330             elsif (m/^security\.(\w+)/) { print $file, " ",$1,"\n" }' |\
1331         sort |\
1332         while read file ea_name; do
1333             attr -g $ea_name $file
1334         done
1335     fi
1336
1337     echo "Root names"
1338     getfattr --absolute-names -Rh -m trusted $_path |\
1339     perl -wn -e '
1340         if (m/^# file: (\S+)/) { $file = $1 }
1341         elsif (m/^trusted\.(\w+)/) { print $file, " ",$1,"\n" }' |\
1342     sort |\
1343     while read file ea_name; do
1344         attr -R -g $ea_name $file
1345     done
1346 }
1347
1348 #
1349 # Compare the extended attributes of the files/dirs
1350 # b/w the dumped and restore dirs.
1351 #
1352 #
1353 # Attribute "attr5" had a 8 byte value for /spare1/dump.5460/dir:
1354 # Attribute "attr5" had a 8 byte value for /spare1/restore.5460/dump.5460/dir:
1355 #
1356 _diff_compare_eas()
1357 {
1358     echo "Comparing dump directory with restore directory"
1359     echo "Looking at the extended attributes (EAs)"
1360     echo "EAs on dump"
1361     _get_eas_on_path $dump_dir | tee $seqres.ea1 | _dir_filter
1362     echo "EAs on restore"
1363     _get_eas_on_path $restore_dir/$dump_sdir \
1364     | sed -e "s#$restore_sdir\/##" \
1365     | tee $seqres.ea2 \
1366     | _dir_filter
1367     diff -s $seqres.ea1 $seqres.ea2 | _dir_filter
1368 }
1369
1370
1371 #
1372 # Compare using recursive diff the files of the dumped
1373 # filesystem
1374 #
1375 _diff_compare()
1376 {
1377     echo "Comparing dump directory with restore directory"
1378     diff -rs $SCRATCH_MNT $restore_dir | _dir_filter | _check_quota_diff
1379 }
1380
1381 #
1382 # Check out the dump inventory
1383 #
1384 _dump_inventory()
1385 {
1386     $XFSDUMP_PROG $_dump_debug -I | tee -a $seqres.full | _dump_filter_main
1387 }
1388
1389 #
1390 # Do the xfsinvutil cmd with debug and filters
1391 # Need to set variable: "$middate" to the invutil date
1392 #
1393 _do_invutil()
1394 {
1395     host=`hostname`
1396     echo "xfsinvutil $_invutil_debug -M $host:$SCRATCH_MNT \"$middate\" $*" >$seqres.full
1397     $XFSINVUTIL_PROG $_invutil_debug $* -M $host:$SCRATCH_MNT "$middate" \
1398     | tee -a $seqres.full | _invutil_filter
1399 }
1400
1401 #
1402 # ensure we can find the user quota msg if user quotas are on
1403 # ensure we can find the group quota msg if group quotas are on
1404 #
1405 _check_quota()
1406 {
1407     usermsg=$1
1408     groupmsg=$2
1409     projectmsg=$3
1410     uquota=0
1411     gquota=0
1412     pquota=0
1413     $here/src/feature -U $SCRATCH_DEV && uquota=1
1414     $here/src/feature -G $SCRATCH_DEV && gquota=1
1415     $here/src/feature -P $SCRATCH_DEV && pquota=1
1416
1417     $AWK_PROG -v uquota=$uquota -v gquota=$gquota -v pquota=$pquota \
1418               -v full=$seqres.full -v usermsg="$usermsg" \
1419               -v groupmsg="$groupmsg" -v projectmsg="$projectmsg" '
1420         $0 ~ projectmsg {
1421                         print "Found project quota:", $0 >>full
1422                         found_pquota = 1
1423                         if (!pquota) {
1424                             print "Found extra:", $0
1425                         }
1426                         next
1427         }
1428         $0 ~ groupmsg {
1429                         print "Found group quota:", $0 >>full
1430                         found_gquota = 1
1431                         if (!gquota) {
1432                             print "Found extra:", $0
1433                         }
1434                         next
1435         }
1436         $0 ~ usermsg {
1437                         print "Found user quota:", $0 >>full
1438                         found_uquota = 1
1439                         if (!uquota) {
1440                             print "Found extra:", $0
1441                         }
1442                         next
1443         }
1444                         { print }
1445         END {
1446                 if (uquota && !found_uquota) {
1447                     print "Missing user quota msg:", usermsg
1448                 }
1449                 if (gquota && !found_gquota) {
1450                     print "Missing group quota msg:", groupmsg
1451                 }
1452                 if (pquota && !found_pquota) {
1453                     print "Missing project quota msg:", projectmsg
1454                 }
1455         }
1456     '
1457 }
1458
1459 #
1460 # xfsrestore: 3 directories and 40 entries processed
1461 #   $5 = 40
1462 #   num entries needs to be reduced by num quota file(s)
1463 #
1464 _check_quota_entries()
1465 {
1466     uquota=0
1467     gquota=0
1468     pquota=0
1469     $here/src/feature -U $SCRATCH_DEV && uquota=1
1470     $here/src/feature -G $SCRATCH_DEV && gquota=1
1471     $here/src/feature -P $SCRATCH_DEV && pquota=1
1472     $AWK_PROG -v uquota=$uquota -v gquota=$gquota -v pquota=$pquota '
1473         /entries processed/ {
1474                 if (uquota) $5--
1475                 if (gquota) $5--
1476                 if (pquota) $5--
1477         }
1478         {print}'
1479 }
1480
1481 #
1482 # Look for:
1483 # xfsdump: saving user quota information for: SCRATCH_MNT
1484 # xfsdump: saving group quota information for: SCRATCH_MNT
1485 # xfsdump: saving project quota information for: SCRATCH_MNT
1486 # xfsrestore: user quota information written to ...'
1487 # xfsrestore: group quota information written to ...'
1488 # xfsrestore: project quota information written to ...'
1489 #
1490 # If on IRIX then look for:
1491 # xfsrestore: use 'edquota' to restore quotas
1492 # Else look for:
1493 # xfsrestore: use 'xfs_quota' to restore quotas
1494 #
1495 _check_quota_dumprestore()
1496 {
1497     if [ "$HOSTOS" == "IRIX" ]; then
1498         _check_quota 'user quota information' \
1499                      'group quota information' \
1500                      'project quota information' | \
1501         sed "/xfsrestore:.*use 'edquota' to restore quotas/d"
1502     else
1503         _check_quota 'user quota information' \
1504                      'group quota information' \
1505                      'project quota information' | \
1506         sed "/xfsrestore:.*use 'xfs_quota' to restore quotas/d"
1507     fi
1508 }
1509
1510 #
1511 # Look for:
1512 # Only in RESTORE_DIR: xfsdump_quotas
1513 # Only in RESTORE_DIR: xfsdump_quotas_group
1514 # Only in RESTORE_DIR: xfsdump_quotas_project
1515 #
1516 _check_quota_diff()
1517 {
1518    _check_quota 'Only in RESTORE_DIR: xfsdump_quotas' \
1519         'Only in RESTORE_DIR: xfsdump_quotas_group' \
1520         'Only in RESTORE_DIR: xfsdump_quotas_proj'
1521 }
1522
1523 #
1524 # Look for the quota file in the output
1525 # Ensure that it is there if it should be
1526 # Filter it out so that the output is always the same
1527 # even with no quotas
1528 #
1529 _check_quota_file()
1530 {
1531    _check_quota 'xfsdump_quotas' 'xfsdump_quotas_group' 'xfsdump_quotas_proj'
1532 }
1533
1534
1535 # make sure this script returns success
1536 /bin/true