]> git.apps.os.sepia.ceph.com Git - xfstests-dev.git/commitdiff
cmd/xfs/stress/001 1.6 Renamed to cmd/xfstests/001
authorNathan Scott <nathans@sgi.com>
Mon, 15 Jan 2001 05:01:19 +0000 (05:01 +0000)
committerNathan Scott <nathans@sgi.com>
Mon, 15 Jan 2001 05:01:19 +0000 (05:01 +0000)
144 files changed:
001 [new file with mode: 0755]
001.out [new file with mode: 0644]
002 [new file with mode: 0755]
002.out [new file with mode: 0644]
003 [new file with mode: 0755]
003.out [new file with mode: 0644]
004 [new file with mode: 0755]
004.out [new file with mode: 0644]
005 [new file with mode: 0755]
005.out [new file with mode: 0644]
006 [new file with mode: 0755]
006.out [new file with mode: 0644]
007 [new file with mode: 0755]
007.out [new file with mode: 0644]
008 [new file with mode: 0755]
008.out [new file with mode: 0644]
009 [new file with mode: 0755]
009.out [new file with mode: 0644]
010 [new file with mode: 0755]
010.out [new file with mode: 0644]
011 [new file with mode: 0755]
011.out [new file with mode: 0644]
012 [new file with mode: 0755]
012.out [new file with mode: 0644]
013 [new file with mode: 0755]
013.out [new file with mode: 0644]
014 [new file with mode: 0755]
014.out [new file with mode: 0644]
015 [new file with mode: 0755]
015.out [new file with mode: 0644]
016 [new file with mode: 0755]
016.out [new file with mode: 0644]
017 [new file with mode: 0755]
017.out [new file with mode: 0644]
018 [new file with mode: 0755]
019 [new file with mode: 0755]
019.out [new file with mode: 0644]
020 [new file with mode: 0755]
020.out [new file with mode: 0644]
021 [new file with mode: 0755]
021.out [new file with mode: 0644]
022 [new file with mode: 0755]
022.out [new file with mode: 0644]
023 [new file with mode: 0755]
023.out [new file with mode: 0644]
024 [new file with mode: 0755]
024.out [new file with mode: 0644]
025 [new file with mode: 0755]
025.out [new file with mode: 0644]
026 [new file with mode: 0755]
026.out [new file with mode: 0644]
027 [new file with mode: 0755]
027.out [new file with mode: 0644]
028 [new file with mode: 0755]
028.out [new file with mode: 0644]
029 [new file with mode: 0755]
029.out [new file with mode: 0644]
030 [new file with mode: 0755]
030.out [new file with mode: 0644]
031 [new file with mode: 0755]
031.out [new file with mode: 0644]
032 [new file with mode: 0755]
032.out [new file with mode: 0644]
033 [new file with mode: 0755]
033.out [new file with mode: 0644]
034 [new file with mode: 0755]
034.out [new file with mode: 0644]
035 [new file with mode: 0755]
035.out [new file with mode: 0644]
036 [new file with mode: 0755]
036.out [new file with mode: 0644]
037 [new file with mode: 0755]
037.out [new file with mode: 0644]
038 [new file with mode: 0755]
038.out [new file with mode: 0644]
039 [new file with mode: 0755]
039.out [new file with mode: 0644]
040 [new file with mode: 0755]
040.out [new file with mode: 0644]
041 [new file with mode: 0755]
041.out [new file with mode: 0644]
042 [new file with mode: 0755]
042.out [new file with mode: 0644]
043 [new file with mode: 0755]
043.out [new file with mode: 0644]
044 [new file with mode: 0755]
044.out [new file with mode: 0644]
045 [new file with mode: 0755]
045.out [new file with mode: 0644]
046 [new file with mode: 0755]
046.out [new file with mode: 0644]
047 [new file with mode: 0755]
047.out [new file with mode: 0644]
048 [new file with mode: 0755]
048.out [new file with mode: 0644]
049 [new file with mode: 0755]
049.out [new file with mode: 0644]
050 [new file with mode: 0755]
050.uqnoenforce [new file with mode: 0644]
050.usrquota [new file with mode: 0644]
051 [new file with mode: 0755]
051.out [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
check [new file with mode: 0755]
common [new file with mode: 0644]
common.config [new file with mode: 0644]
common.dump [new file with mode: 0644]
common.filter [new file with mode: 0644]
common.quota [new file with mode: 0644]
common.rc [new file with mode: 0644]
common.repair [new file with mode: 0644]
crash/README [new file with mode: 0644]
crash/rc.sysinit [new file with mode: 0644]
crash/xfscrash [new file with mode: 0755]
group [new file with mode: 0644]
new [new file with mode: 0755]
remake [new file with mode: 0755]
soak [new file with mode: 0755]
src/Makefile [new file with mode: 0644]
src/alloc.c [new file with mode: 0644]
src/bstat.c [new file with mode: 0644]
src/dbtest.c [new file with mode: 0644]
src/devzero.c [new file with mode: 0644]
src/dirstress.c [new file with mode: 0644]
src/fault.c [new file with mode: 0644]
src/feature.c [new file with mode: 0644]
src/fill.c [new file with mode: 0644]
src/fill2.c [new file with mode: 0644]
src/fill2fs [new file with mode: 0755]
src/fill2fs_check [new file with mode: 0755]
src/fsstress.c [new file with mode: 0644]
src/global.h [new file with mode: 0644]
src/holes.c [new file with mode: 0644]
src/ioctl.c [new file with mode: 0644]
src/loggen.c [new file with mode: 0644]
src/lstat64.c [new file with mode: 0644]
src/nametest.c [new file with mode: 0644]
src/permname.c [new file with mode: 0644]
src/randholes.c [new file with mode: 0644]
src/random.c [new file with mode: 0644]
src/runas.c [new file with mode: 0644]
src/truncfile.c [new file with mode: 0644]
src/usemem.c [new file with mode: 0644]

diff --git a/001 b/001
new file mode 100755 (executable)
index 0000000..b917210
--- /dev/null
+++ b/001
@@ -0,0 +1,314 @@
+#! /bin/sh
+#
+# XFS QA Test No. 001
+# $Id: 1.1 $
+#
+# Random file copier to produce chains of identical files so the head
+# and the tail cna be diff'd at then end of each iteration.
+#
+# Exercises creat, write and unlink for a variety of directory sizes, and
+# checks for data corruption.
+#
+# run [config]
+#
+# config has one line per file with filename and byte size, else use
+# the default one below.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=kenmcd@bruce.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+tmp=/tmp/$$
+here=`pwd`
+status=1
+done_cleanup=false
+trap "_cleanup; rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# real QA test starts here
+
+verbose=true
+
+if [ $# -eq 0 ]
+then
+    # use the default config
+    #
+    cat <<End-of-File >$tmp.config
+# pathname     size in bytes
+#
+small          10
+big            102400
+sub/small      10
+sub/big                102400
+#
+sub/a          1
+sub/b          2
+sub/c          4
+sub/d          8
+sub/e          16
+sub/f          32
+sub/g          64
+sub/h          128
+sub/i          256
+sub/j          512
+sub/k          1024
+sub/l          2048
+sub/m          4096
+sub/n          8192
+#
+sub/a00                100
+sub/b00                200
+sub/c00                400
+sub/d00                800
+sub/e00                1600
+sub/f00                3200
+sub/g00                6400
+sub/h00                12800
+sub/i00                25600
+sub/j00                51200
+sub/k00                102400
+sub/l00                204800
+sub/m00                409600
+sub/n00                819200
+#
+sub/a000       1000
+sub/e000       16000
+sub/h000       128000
+sub/k000       1024000
+End-of-File
+elif [ $# -eq 1 ]
+then
+    if [ -f $1 ]
+    then
+       cp $1 $tmp.config
+    else
+       echo "Error: cannot open config \"$1\""
+       exit 1
+    fi
+else
+    echo "Usage: run [config]"
+    exit 1
+fi
+
+ncopy=200              # number of file copies in the chain step
+
+_setup()
+{
+    if mkdir -p $TEST_DIR/$$
+    then
+       :
+    else
+       echo "Error: cannot mkdir \"$TEST_DIR/$$\""
+       exit 1
+    fi
+    cd $TEST_DIR/$$
+
+    $verbose && echo -n "setup "
+    sed -e '/^#/d' $tmp.config \
+    | while read file nbytes
+    do
+       dir=`dirname $file`
+       if [ "$dir" != "." ]
+       then
+           if [ ! -d $dir ]
+           then
+               if mkdir $dir
+               then
+                   :
+               else
+                   $verbose && echo
+                   echo "Error: cannot mkdir \"$dir\""
+                   exit 1
+               fi
+           fi
+       fi
+       rm -f $file
+       if $here/src/fill $file $file $nbytes
+       then
+           :
+       else
+           $verbose && echo
+           echo "Error: cannot create \"$file\""
+           exit 1
+       fi
+       $verbose && echo -n "."
+    done
+    $verbose && echo
+}
+
+_mark_iteration()
+{
+    $verbose && echo -n "mark_iteration "
+    sed -e '/^#/d' $tmp.config \
+    | while read file nbytes
+    do
+       if [ ! -f $file ]
+       then
+           $verbose && echo
+           echo "Error: $file vanished!"
+           touch $tmp.bad
+           continue
+       fi
+       sed -e "s/ [0-9][0-9]* / $1 /" <$file >$file.tmp
+       mv $file.tmp $file
+       $verbose && echo -n "."
+    done
+    $verbose && echo
+}
+
+# for each file, make a number of copies forming a chain like foo.0,
+# foo.1, foo.2, ... foo.N
+#
+# files are chosen at random, so the lengths of the chains are different
+#
+# then rename foo.N to foo.last and remove all of the other files in
+# the chain
+#
+_chain()
+{
+    $AWK_PROG <$tmp.config '
+BEGIN  { nfile = 0 }
+/^\#/  { next }
+       { file[nfile] = $1
+         link[nfile] = 0
+         nfile++
+       }
+END    { srand('$iter')
+         for (i=0; i < '$ncopy'; i++) {
+           # choose a file at random, and add one copy to that chain
+           j = -1
+           while (j < 0 || j >= nfile)
+               j = int(rand() * nfile)
+           if (link[j] == 0) {
+               printf "if [ ! -f %s ]; then echo \"%s missing!\"; exit; fi\n",file[j],file[j]
+               printf "if [ -f %s.0 ]; then echo \"%s.0 already present!\"; exit; fi\n",file[j],file[j]
+               printf "cp %s %s.0\n",file[j],file[j]
+           }
+           else {
+               printf "if [ ! -f %s.%d ]; then echo \"%s.%d missing!\"; exit; fi\n",file[j],link[j]-1,file[j],link[j]-1
+               printf "if [ -f %s.%d ]; then echo \"%s.%d already present!\"; exit; fi\n",file[j],link[j],file[j],link[j]
+               printf "cp %s.%d %s.%d\n",file[j],link[j]-1,file[j],link[j]
+           }
+           link[j]++
+         }
+         # close all the chains, and remove all of the files except
+         # the head of the chain
+         for (j=0; j<nfile; j++) {
+           if (link[j] > 0)
+               printf "mv %s.%d %s.last\n",file[j],link[j]-1,file[j]
+           for (i=0; i<link[j]-1; i++) {
+               printf "rm -f %s.%d\n",file[j],i
+           }
+         }
+       }' \
+       | sh
+}
+
+_check()
+{
+    rm -f $tmp.bad
+    $verbose && echo -n "check "
+    sed -e '/^#/d' $tmp.config \
+    | while read file nbytes
+    do
+       if [ ! -f $file ]
+       then
+           $verbose && echo
+           echo "Error: $file vanished!"
+           touch $tmp.bad
+           continue
+       fi
+       if [ -f $file.last ]
+       then
+           if cmp $file $file.last >/dev/null 2>&1
+           then
+               $verbose && echo -n "."
+           else
+               $verbose && echo
+               echo "Error: corruption for $file ..."
+               diff -c $file $file.last
+               touch $tmp.bad
+           fi
+       else
+           $verbose && echo -n "."
+       fi
+    done
+    $verbose && echo
+}
+
+_cleanup()
+{
+    # cleanup
+    #
+    if $done_cleanup
+    then
+       :
+    elif [ $status -eq 0 ]
+    then
+       $verbose && echo "cleanup"
+       cd /
+       rm -rf $TEST_DIR/$$
+       done_cleanup=true
+    fi
+}
+
+status=0
+_cleanup
+status=1
+done_cleanup=false
+
+_setup
+
+# do the test
+#
+for iter in 1 2 3 4 5
+do
+    echo -n "iter $iter chain ... "
+    _chain
+    _check
+    if [ -f $tmp.bad ]
+    then
+       echo "Fatal error: test abandoned without changes"
+       exit 1
+    fi
+done
+
+status=0
+exit
diff --git a/001.out b/001.out
new file mode 100644 (file)
index 0000000..e843a58
--- /dev/null
+++ b/001.out
@@ -0,0 +1,9 @@
+QA output created by 001
+cleanup
+setup ....................................
+iter 1 chain ... check ....................................
+iter 2 chain ... check ....................................
+iter 3 chain ... check ....................................
+iter 4 chain ... check ....................................
+iter 5 chain ... check ....................................
+cleanup
diff --git a/002 b/002
new file mode 100755 (executable)
index 0000000..d9dfe48
--- /dev/null
+++ b/002
@@ -0,0 +1,88 @@
+#! /bin/sh
+#
+# XFS QA Test No. 002
+# $Id: 1.1 $
+#
+# simple inode link count test for a regular file
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=kenmcd@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+tmp=/tmp/$$
+here=`pwd`
+status=0       # success is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# real QA test starts here
+
+echo "Silence is goodness ..."
+
+# ensure target directory exists
+mkdir `dirname $TEST_DIR/$tmp` 2>/dev/null
+
+touch $TEST_DIR/$tmp.1
+for l in 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+    ln $TEST_DIR/$tmp.1 $TEST_DIR/$tmp.$l
+    x=`src/lstat64 $TEST_DIR/$tmp.1 | sed -n -e '/ Links: /s/.*Links: *//p'`
+    if [ "$l" -ne $x ]
+    then
+       echo "Arrgh, created link #$l and lstat64 looks like ..."
+       src/lstat64 $TEST_DIR/$tmp.1
+       status=1
+    fi
+done
+
+for l in 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
+do
+    x=`src/lstat64 $TEST_DIR/$tmp.1 | sed -n -e '/ Links: /s/.*Links: *//p'`
+    if [ "$l" -ne $x ]
+    then
+       echo "Arrgh, about to remove link #$l and lstat64 looks like ..."
+       src/lstat64 $TEST_DIR/$tmp.1
+       status=1
+    fi
+    rm -f $TEST_DIR/$tmp.$l
+done
+
+# success, all done
+exit
diff --git a/002.out b/002.out
new file mode 100644 (file)
index 0000000..11426b5
--- /dev/null
+++ b/002.out
@@ -0,0 +1,2 @@
+QA output created by 002
+Silence is goodness ...
diff --git a/003 b/003
new file mode 100755 (executable)
index 0000000..c3147c1
--- /dev/null
+++ b/003
@@ -0,0 +1,104 @@
+#! /bin/sh
+#
+# XFS QA Test No. 003
+# $Id: 1.1 $
+#
+# exercise xfs_db bug #784078
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=nathans@melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+tmp=/tmp/$$
+here=`pwd`
+status=0       # success is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+_need_to_be_root
+
+# real QA test starts here
+
+PATH=".:$PATH"
+
+[ -f core ] && rm -f core
+[ -f core ] && echo "Warning: can't nuke existing core file!"
+
+test_done()
+{
+        sts=$?
+        [ -f core ] && echo "FAILED - core file"
+        [ ! -f core -a $sts != 0 ] && echo "FAILED - non-zero exit status"
+        rm -f core
+}
+
+# real QA test starts here
+
+echo "=== TEST 1 ==="
+xfs_db -r -c 'pop' -c 'type sb' $TEST_DEV
+test_done
+
+echo "=== TEST 2 ==="
+xfs_db -r -c 'push sb' $TEST_DEV
+test_done
+
+echo "=== TEST 3 ==="
+xfs_db -r -c 'pop' -c 'push sb' $TEST_DEV
+test_done
+
+echo "=== TEST 4 ==="
+xfs_db -r -c 'type sb' -c 'print' $TEST_DEV
+test_done
+
+echo "=== TEST 5 ==="
+xfs_db -r -c 'inode 128' -c 'push' -c 'type' $TEST_DEV >$tmp.out 2>&1
+test_done
+if ! grep -q "current type is \"inode\"" $tmp.out
+then
+       cat $tmp.out
+fi
+
+echo "=== TEST 6 ==="
+xfs_db -r -c 'sb' -c 'a' $TEST_DEV >$tmp.out 2>&1 # don't care about output
+test_done
+
+echo "=== TEST 7 ==="
+xfs_db -r -c 'ring' $TEST_DEV
+test_done
diff --git a/003.out b/003.out
new file mode 100644 (file)
index 0000000..e55df2e
--- /dev/null
+++ b/003.out
@@ -0,0 +1,12 @@
+QA output created by 003
+=== TEST 1 ===
+no current object
+=== TEST 2 ===
+=== TEST 3 ===
+=== TEST 4 ===
+no current object
+no current type
+=== TEST 5 ===
+=== TEST 6 ===
+=== TEST 7 ===
+no entries in location ring.
diff --git a/004 b/004
new file mode 100755 (executable)
index 0000000..54df4f9
--- /dev/null
+++ b/004
@@ -0,0 +1,139 @@
+#! /bin/sh
+# XFS QA Test No. 004
+# $Id: 1.1 $
+#
+# exercise xfs_db bug #789674 and other freesp functionality
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=nathans@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0
+
+_cleanup()
+{
+       umount $SCRATCH_MNT
+       rm -f $tmp.*
+       exit $status
+}
+trap "_cleanup" 0 1 2 3 15
+
+_populate_scratch()
+{
+       mkfs -t xfs -f $SCRATCH_DEV >/dev/null 2>&1
+       mount -t xfs $SCRATCH_DEV $SCRATCH_MNT
+       dd if=/dev/zero of=$SCRATCH_MNT/foo count=200 bs=4096 >/dev/null 2>&1 &
+       dd if=/dev/zero of=$SCRATCH_MNT/goo count=400 bs=4096 >/dev/null 2>&1 &
+       dd if=/dev/zero of=$SCRATCH_MNT/moo count=800 bs=4096 >/dev/null 2>&1 &
+       wait
+       umount $SCRATCH_MNT                     # flush everything
+       mount -t xfs $SCRATCH_DEV $SCRATCH_MNT  # and then remount
+}
+
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_need_to_be_root
+_require_scratch
+
+# real QA test starts here
+rm -f $seq.full
+
+_populate_scratch
+
+eval `df -P -T --block-size=512 $SCRATCH_MNT 2>&1 \
+       | $AWK_PROG 'END { printf "blocks=%u used=%u avail=%u\n", $3, $4, $5 }'`
+echo "df gave: blocks=$blocks used=$used avail=$avail" >>$seq.full
+
+blksize=`xfs_db -r -c sb -c p $SCRATCH_DEV |grep blocksize |sed -e 's/.*= *//'`
+if [ -z "$blksize" ]
+then
+       echo "Arrgh ... cannot determine blocksize for $fs, xfs_db reports"
+       xfs_db -r -c sb -c p $SCRATCH_DEV
+       status=1
+       continue
+fi
+echo "blocksize from xfs_db is '$blksize'" >>$seq.full
+
+xfs_db -r -c "freesp -s" $SCRATCH_DEV >$tmp.xfs_db
+echo "xfs_db for $SCRATCH_DEV" >>$seq.full
+cat $tmp.xfs_db >>$seq.full
+
+# check the 'blocks' field from freesp command is OK
+perl -ne '
+           BEGIN       { $avail ='$avail' * 512;
+                         $answer="(no xfs_db free blocks line?)" }
+           /free blocks (\d+)$/        || next;
+           $freesp = $1 * '$blksize';
+           if ($freesp == $avail)      { $answer = "yes"; }
+           else                        { $answer = "no ($freesp != $avail)"; }
+           END { print "$answer\n" }
+       ' <$tmp.xfs_db >$tmp.ans
+ans="`cat $tmp.ans`"
+echo "Checking blocks column same as df: $ans"
+if [ "$ans" != yes ]
+then
+       echo "Error: $SCRATCH_DEV: freesp mismatch: $ans"
+       echo "xfs_db output ..."
+       cat $tmp.xfs_db
+       status=1
+fi
+
+# check the 'pct' field from freesp command is good
+perl -ne '
+           BEGIN       { $percent = 0; }
+           /free/      && next;        # skip over free extent size number
+           if (/\s+(\d+\.\d+)$/) {
+               $percent += $1;
+           }
+           END { $percent += 0.5; print int($percent), "\n" }  # round up
+' <$tmp.xfs_db >$tmp.ans
+ans="`cat $tmp.ans`"
+echo "Checking percent column yields 100: $ans"
+if [ "$ans" != 100 ]
+then
+       echo "Error: $SCRATCH_DEV: pct mismatch: $ans (expected 100)"
+       echo "xfs_db output ..."
+       cat $tmp.xfs_db
+       status=1
+fi
+
+exit
diff --git a/004.out b/004.out
new file mode 100644 (file)
index 0000000..b598b90
--- /dev/null
+++ b/004.out
@@ -0,0 +1,3 @@
+QA output created by 004
+Checking blocks column same as df: yes
+Checking percent column yields 100: 100
diff --git a/005 b/005
new file mode 100755 (executable)
index 0000000..692035d
--- /dev/null
+++ b/005
@@ -0,0 +1,87 @@
+#! /bin/sh
+# XFS QA Test No. 005
+# $Id: 1.1 $
+#
+# Test symlinks & ELOOP
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+#
+# note ELOOP limit used to be 32 but changed to 8. Who know what
+# it might be next.
+#
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    cd $TEST_DIR
+    rm -f symlink_{0,1,2,3}{0,1,2,3,4,5,6,7,8,9} symlink_self empty_file
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+cd $TEST_DIR
+
+o=empty_file
+touch $o
+for f in symlink_{0,1,2,3}{0,1,2,3,4,5,6,7,8,9}
+do
+    ln -s $o $f
+    o=$f
+done
+
+ln -s symlink_self symlink_self
+
+echo "*** touch deep symlinks"
+echo ""
+touch symlink_{0,1,2,3}{0,1,2,3,4,5,6,7,8,9}
+echo ""
+echo "*** touch recusive symlinks"
+echo ""
+touch symlink_self
+
+exit
diff --git a/005.out b/005.out
new file mode 100644 (file)
index 0000000..890720f
--- /dev/null
+++ b/005.out
@@ -0,0 +1,39 @@
+QA output created by 005
+*** touch deep symlinks
+
+touch: symlink_08: Too many levels of symbolic links
+touch: symlink_09: Too many levels of symbolic links
+touch: symlink_10: Too many levels of symbolic links
+touch: symlink_11: Too many levels of symbolic links
+touch: symlink_12: Too many levels of symbolic links
+touch: symlink_13: Too many levels of symbolic links
+touch: symlink_14: Too many levels of symbolic links
+touch: symlink_15: Too many levels of symbolic links
+touch: symlink_16: Too many levels of symbolic links
+touch: symlink_17: Too many levels of symbolic links
+touch: symlink_18: Too many levels of symbolic links
+touch: symlink_19: Too many levels of symbolic links
+touch: symlink_20: Too many levels of symbolic links
+touch: symlink_21: Too many levels of symbolic links
+touch: symlink_22: Too many levels of symbolic links
+touch: symlink_23: Too many levels of symbolic links
+touch: symlink_24: Too many levels of symbolic links
+touch: symlink_25: Too many levels of symbolic links
+touch: symlink_26: Too many levels of symbolic links
+touch: symlink_27: Too many levels of symbolic links
+touch: symlink_28: Too many levels of symbolic links
+touch: symlink_29: Too many levels of symbolic links
+touch: symlink_30: Too many levels of symbolic links
+touch: symlink_31: Too many levels of symbolic links
+touch: symlink_32: Too many levels of symbolic links
+touch: symlink_33: Too many levels of symbolic links
+touch: symlink_34: Too many levels of symbolic links
+touch: symlink_35: Too many levels of symbolic links
+touch: symlink_36: Too many levels of symbolic links
+touch: symlink_37: Too many levels of symbolic links
+touch: symlink_38: Too many levels of symbolic links
+touch: symlink_39: Too many levels of symbolic links
+
+*** touch recusive symlinks
+
+touch: symlink_self: Too many levels of symbolic links
diff --git a/006 b/006
new file mode 100755 (executable)
index 0000000..d185a0c
--- /dev/null
+++ b/006
@@ -0,0 +1,89 @@
+#! /bin/sh
+# XFS QA Test No. 006
+# $Id: 1.1 $
+#
+# permname
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    rm -rf $TEST_DIR/permname.$$
+}
+
+_count()
+{
+    $AWK_PROG '
+        BEGIN   { count = 0 }
+                { count ++ }
+        END     { print count " files created" }
+    '
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+
+mkdir $TEST_DIR/permname.$$
+
+echo ""
+echo "single thread permname"
+echo "----------------------"
+mkdir $TEST_DIR/permname.$$/a
+cd $TEST_DIR/permname.$$/a
+$here/src/permname -c 4 -l 6 -p 1 || echo "permname returned $?"
+find . | _count
+
+echo ""
+echo "multi thread permname"
+echo "----------------------"
+mkdir $TEST_DIR/permname.$$/b
+cd $TEST_DIR/permname.$$/b
+$here/src/permname -c 4 -l 6 -p 4 || echo "permname returned $?"
+find . | _count
+
+exit
diff --git a/006.out b/006.out
new file mode 100644 (file)
index 0000000..ce17a49
--- /dev/null
+++ b/006.out
@@ -0,0 +1,11 @@
+QA output created by 006
+
+single thread permname
+----------------------
+alpha size = 4, name length = 6, total files = 4096, nproc=1
+4097 files created
+
+multi thread permname
+----------------------
+alpha size = 4, name length = 6, total files = 4096, nproc=4
+4097 files created
diff --git a/007 b/007
new file mode 100755 (executable)
index 0000000..84b78d6
--- /dev/null
+++ b/007
@@ -0,0 +1,90 @@
+#! /bin/sh
+# XFS QA Test No. 007
+# $Id: 1.1 $
+#
+# drive the src/nametest program
+# which does a heap of open(create)/unlink/stat
+# and checks that error codes make sense with its
+# memory of the files created.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    rm -f $tmp.*
+    rm -rf $TEST_DIR/$seq
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+status=1 # default failure 
+sourcefile=$tmp.nametest
+seed=1
+iterations=100000
+num_filenames=100
+
+# need to create an input file with a list of
+# filenames on each line 
+i=1
+while [ $i -le $num_filenames ]; do
+  echo "nametest.$i" >>$sourcefile
+  i=`expr $i + 1`
+done
+
+mkdir $TEST_DIR/$seq
+cd $TEST_DIR/$seq
+$here/src/nametest -l $sourcefile -s $seed -i $iterations -z
+
+
+#optional stuff if your test has verbose output to help resolve problems
+#echo
+#echo "If failure, check $seq.full (this) and $seq.full.ok (reference)"
+
+
+# success, all done
+status=0
+exit
diff --git a/007.out b/007.out
new file mode 100644 (file)
index 0000000..514b44a
--- /dev/null
+++ b/007.out
@@ -0,0 +1,22 @@
+QA output created by 007
+.Seed = 1 (use "-s 1" to re-execute this test)
+.......................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+.........................................................................
+....................................................
+creates:  18736 OK,  18802 EEXIST  ( 37538 total, 50% EEXIST)
+removes:  18675 OK,  19927 ENOENT  ( 38602 total, 51% ENOENT)
+lookups:  12000 OK,  11860 ENOENT  ( 23860 total, 49% ENOENT)
+total  :  49411 OK,  50589 w/error (100000 total, 50% w/error)
+
+cleanup:     61 removes
diff --git a/008 b/008
new file mode 100755 (executable)
index 0000000..86ecf4f
--- /dev/null
+++ b/008
@@ -0,0 +1,98 @@
+#! /bin/sh
+# XFS QA Test No. 008
+# $Id: 1.1 $
+#
+# randholes test
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -f $tmp.*; _cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    rm -rf $TEST_DIR/randholes.$$.*
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_do_test()
+{
+    _n="$1"
+    _holes="$2"
+    _param="$3"
+    
+    out=$TEST_DIR/randholes.$$.$_n
+    echo ""
+    echo "randholes.$_n : $_param"
+    echo "------------------------------------------"
+    if $here/src/randholes $_param $out >$tmp.out
+    then
+        # quick check - how many holes did we get?
+        count=`xfs_bmap $out | egrep -c ': hole'`
+        # blocks can end up adjacent, therefore number of holes varies
+        _within_tolerance "holes" $count $_holes 10% -v
+    else
+        echo "    randholes returned $? - see $seq.out.full"
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        echo "$_n - output from randholes:"                 >>$here/$seq.out.full
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        cat $tmp.out                                        >>$here/$seq.out.full
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        echo "$_n - output from bmap:"                      >>$here/$seq.out.full
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        xfs_bmap -vvv $out                                  >>$here/$seq.out.full
+        status=1
+    fi
+}
+
+# real QA test starts here
+
+rm -f $here/$seq.out.full
+
+_do_test 1 50 "-l 5000000 -c 50 -b 4096"
+_do_test 2 100 "-l 10000000 -c 100 -b 4096"
+_do_test 3 100 "-l 10000000 -c 100 -b 512"   # test partial pages
+
+# success, all done
+exit
diff --git a/008.out b/008.out
new file mode 100644 (file)
index 0000000..7bac019
--- /dev/null
+++ b/008.out
@@ -0,0 +1,13 @@
+QA output created by 008
+
+randholes.1 : -l 5000000 -c 50 -b 4096
+------------------------------------------
+holes is in range
+
+randholes.2 : -l 10000000 -c 100 -b 4096
+------------------------------------------
+holes is in range
+
+randholes.3 : -l 10000000 -c 100 -b 512
+------------------------------------------
+holes is in range
diff --git a/009 b/009
new file mode 100755 (executable)
index 0000000..6758c99
--- /dev/null
+++ b/009
@@ -0,0 +1,197 @@
+#! /bin/sh
+# XFS QA Test No. 009
+# $Id: 1.1 $
+#
+# alloc test
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    echo "*** unmount"
+    umount $SCRATCH_MNT
+}
+
+_block_filter()
+{
+   sed -e 's/[0-9][0-9]*\.\.[0-9][0-9]*/BLOCKRANGE/g'
+}
+
+_init()
+{
+    echo "*** mkfs"
+    if ! mkfs -t xfs -f $SCRATCH_DEV >$tmp.out 2>&1
+    then
+       cat $tmp.out
+        echo "failed to mkfs $SCRATCH_DEV"
+        exit 1
+    fi
+
+    echo "*** mount"
+    if ! mount $SCRATCH_DEV $SCRATCH_MNT -t xfs
+    then
+        echo "failed to mount $SCRATCH_DEV"
+        exit 1
+    fi
+}
+
+_filesize()
+{
+    ls -l $1 | $AWK_PROG '{print "filesize = " $5}'
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+_require_scratch
+
+_init
+out=$SCRATCH_MNT/$$.tmp
+
+# since we're using a clean FS here, we make some assumptions
+# about availability of contiguous blocks
+
+# also interesting to note is that ALLOC == FREE. seriously.
+# the _length is ignored_ in irix. the file is allocated up
+# to the specified offset, and zero filled if previously
+# unallocated. the file is truncated at the specified point.
+
+echo "*** test 1 - reservations cleared on O_TRUNC"
+rm -f $out
+cat <<EOF | src/alloc -n -b 4096 -f $out | _block_filter
+r 0 1000b
+m
+EOF
+_filesize $out
+
+cat <<EOF | src/alloc -n -b 4096 -f $out -t | _block_filter
+m
+EOF
+_filesize $out
+
+echo "*** test 2 - reserve & filesize"
+rm -f $out
+cat <<EOF | src/alloc -n -b 4096 -f $out | _block_filter
+r 0 1000b
+EOF
+
+_filesize $out
+
+echo "*** test 3 - alloc & filesize"
+rm -f $out
+cat <<EOF | src/alloc -n -b 4096 -f $out | _block_filter
+a 1000b
+EOF
+
+_filesize $out
+
+echo "*** test 4 - allocations cleared on O_TRUNC"
+rm -f $out
+cat <<EOF | src/alloc -n -b 4096 -f $out | _block_filter
+a 1000b
+EOF
+_filesize $out
+
+cat <<EOF | src/alloc -n -b 4096 -f $out -t | _block_filter
+m
+EOF
+_filesize $out
+
+echo "*** test 5 - reserve / unreserve"
+rm -f $out
+cat <<EOF | src/alloc -n -b 4096 -f $out | _block_filter
+r 0 100b
+u 100b 500b
+m
+u 900b 200b
+m
+EOF
+
+echo "*** test 6 - reserve adjacent"
+rm -f $out
+cat <<EOF | src/alloc -t -n -b 4096 -f $out | _block_filter
+r 0 100b
+r 100b 100b
+m
+EOF
+
+echo "*** test 7 - alloc"
+rm -f $out
+cat <<EOF | src/alloc -n -b 4096 -f $out | _block_filter
+a 1000b
+m
+a 2000b
+m
+EOF
+
+_filesize $out
+
+echo "*** test 8 - alloc & truncate"
+rm -f $out
+cat <<EOF | src/alloc -n -b 4096 -f $out | _block_filter
+a 1000b
+m
+t 500b
+m
+EOF
+
+_filesize $out
+
+echo "*** test 9 - reserve & truncate"
+rm -f $out
+cat <<EOF | src/alloc -n -b 4096 -f $out | _block_filter
+r 0 1000b
+m
+t 500b
+m
+EOF
+
+_filesize $out
+
+
+status=0
+exit
diff --git a/009.out b/009.out
new file mode 100644 (file)
index 0000000..9a706ec
--- /dev/null
+++ b/009.out
@@ -0,0 +1,114 @@
+QA output created by 009
+*** mkfs
+*** mount
+*** test 1 - reservations cleared on O_TRUNC
+    blocksize 4096
+    CMD resvsp, off=0, len=4096000
+    MAP off=0, len=4096000 [0,1000]
+        [ofs,count]: start..end
+        [0,1000]: BLOCKRANGE
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,1000]: BLOCKRANGE
+filesize = 0
+    blocksize 4096
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+filesize = 0
+*** test 2 - reserve & filesize
+    blocksize 4096
+    CMD resvsp, off=0, len=4096000
+    MAP off=0, len=4096000 [0,1000]
+        [ofs,count]: start..end
+        [0,1000]: BLOCKRANGE
+filesize = 0
+*** test 3 - alloc & filesize
+    blocksize 4096
+    CMD allocsp, off=4096000, len=-1
+    MAP off=4096000, len=-1 [1000-]
+        [ofs,count]: start..end
+filesize = 4096000
+*** test 4 - allocations cleared on O_TRUNC
+    blocksize 4096
+    CMD allocsp, off=4096000, len=-1
+    MAP off=4096000, len=-1 [1000-]
+        [ofs,count]: start..end
+filesize = 4096000
+    blocksize 4096
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+filesize = 0
+*** test 5 - reserve / unreserve
+    blocksize 4096
+    CMD resvsp, off=0, len=409600
+    MAP off=0, len=409600 [0,100]
+        [ofs,count]: start..end
+        [0,100]: BLOCKRANGE
+    CMD unresvsp, off=409600, len=2048000
+    MAP off=409600, len=2048000 [100,500]
+        [ofs,count]: start..end
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,100]: BLOCKRANGE
+    CMD unresvsp, off=3686400, len=819200
+    MAP off=3686400, len=819200 [900,200]
+        [ofs,count]: start..end
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,100]: BLOCKRANGE
+*** test 6 - reserve adjacent
+    blocksize 4096
+    CMD resvsp, off=0, len=409600
+    MAP off=0, len=409600 [0,100]
+        [ofs,count]: start..end
+        [0,100]: BLOCKRANGE
+    CMD resvsp, off=409600, len=409600
+    MAP off=409600, len=409600 [100,100]
+        [ofs,count]: start..end
+        [100,100]: BLOCKRANGE
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,200]: BLOCKRANGE
+*** test 7 - alloc
+    blocksize 4096
+    CMD allocsp, off=4096000, len=-1
+    MAP off=4096000, len=-1 [1000-]
+        [ofs,count]: start..end
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,1000]: BLOCKRANGE
+    CMD allocsp, off=8192000, len=-1
+    MAP off=8192000, len=-1 [2000-]
+        [ofs,count]: start..end
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,2000]: BLOCKRANGE
+filesize = 8192000
+*** test 8 - alloc & truncate
+    blocksize 4096
+    CMD allocsp, off=4096000, len=-1
+    MAP off=4096000, len=-1 [1000-]
+        [ofs,count]: start..end
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,1000]: BLOCKRANGE
+    TRUNCATE off=2048000
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,500]: BLOCKRANGE
+filesize = 2048000
+*** test 9 - reserve & truncate
+    blocksize 4096
+    CMD resvsp, off=0, len=4096000
+    MAP off=0, len=4096000 [0,1000]
+        [ofs,count]: start..end
+        [0,1000]: BLOCKRANGE
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,1000]: BLOCKRANGE
+    TRUNCATE off=2048000
+    MAP off=0, len=-1 [0-]
+        [ofs,count]: start..end
+        [0,1000]: BLOCKRANGE
+filesize = 2048000
+*** unmount
diff --git a/010 b/010
new file mode 100755 (executable)
index 0000000..d9e1d14
--- /dev/null
+++ b/010
@@ -0,0 +1,73 @@
+#! /bin/sh
+# XFS QA Test No. 010
+# $Id: 1.1 $
+#
+# dbtest
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=ivanr@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+
+_cleanup()
+{
+    rm -f $TEST_DIR/DBtest*.{pag,dir}
+}
+trap "_cleanup; rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# filter random number output from dbtest
+#
+_filter_dbtest()
+{
+    sed \
+        -e '/were [0-9][0-9]* duplicate/s//were BLEEP duplicate/' \
+        -e '/using [0-9][0-9]* as seed/s//using BLEEP as seed/'
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+cd $TEST_DIR
+$here/src/dbtest -l 5 -n 3000 | _filter_dbtest
+
+# success, all done
+exit
diff --git a/010.out b/010.out
new file mode 100644 (file)
index 0000000..6472a5d
--- /dev/null
+++ b/010.out
@@ -0,0 +1,58 @@
+QA output created by 010
+dbtest v1.0
+
+Creating database containing 3000 records...
+       performing lookups for 5 iterations...
+       using BLEEP as seed for srandom()...
+
+       
+There were BLEEP duplicate checksums generated
+
+Performing lookups on database...
+
+       Sequential lookups...
+
+
+       Random lookups...
+
+Lookups succeeded...
+
+Performing lookups on database...
+
+       Sequential lookups...
+
+
+       Random lookups...
+
+Lookups succeeded...
+
+Performing lookups on database...
+
+       Sequential lookups...
+
+
+       Random lookups...
+
+Lookups succeeded...
+
+Performing lookups on database...
+
+       Sequential lookups...
+
+
+       Random lookups...
+
+Lookups succeeded...
+
+Performing lookups on database...
+
+       Sequential lookups...
+
+
+       Random lookups...
+
+Lookups succeeded...
+
+Cleaning up database...
+       
+There were BLEEP duplicate checksums generated
diff --git a/011 b/011
new file mode 100755 (executable)
index 0000000..10792ed
--- /dev/null
+++ b/011
@@ -0,0 +1,98 @@
+#! /bin/sh
+# XFS QA Test No. 011
+# $Id: 1.1 $
+#
+# dirstress
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+out=$TEST_DIR/dirstress.$$
+trap "rm -f $tmp.*; _cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    rm -rf $out
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+count=1000
+if ! mkdir $out
+then
+    echo "!! couldn't mkdir $out"
+    status=1
+    exit
+fi
+
+rm -f $seq.out.full
+
+_test()
+{
+    test="$1"
+    args="$2"
+    count="$3"
+    
+    echo "*** TEST $test $args -f <count>"
+    if ! $here/src/dirstress -d $out -f $count $args >$tmp.out 2>&1
+    then
+        echo "    dirstress failed"
+        echo "*** TEST $test -d $out -f $count $args" >>$seq.out.full
+        cat $tmp.out >>$seq.out.full
+        status=1
+    fi
+}
+
+# dirstress doesn't check returns - this is a crash & burn test.
+
+count=1000
+_test 1 "-p 1 -n 1" $count
+_test 2 "-p 5 -n 1" $count
+_test 3 "-p 5 -n 5" $count
+
+# if error
+exit
diff --git a/011.out b/011.out
new file mode 100644 (file)
index 0000000..546a4db
--- /dev/null
+++ b/011.out
@@ -0,0 +1,4 @@
+QA output created by 011
+*** TEST 1 -p 1 -n 1 -f <count>
+*** TEST 2 -p 5 -n 1 -f <count>
+*** TEST 3 -p 5 -n 5 -f <count>
diff --git a/012 b/012
new file mode 100755 (executable)
index 0000000..83d997a
--- /dev/null
+++ b/012
@@ -0,0 +1,131 @@
+#! /bin/sh
+# XFS QA Test No. 012
+# $Id: 1.1 $
+#
+# holes
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -f $tmp.*; _cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    rm -rf $TEST_DIR/holes.$$.*
+}
+
+_filesize()
+{
+    ls -l $1 | $AWK_PROG '{print "    filesize = " $5}'
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_do_test()
+{
+    _n="$1"
+    _param="$2"
+    _count="$3"
+    
+    failed=0
+    
+    out=$TEST_DIR/holes.$$.$_n
+    echo ""
+    echo "holes.$_n : $_param"
+    echo "-----------------------------------------------"
+    if  ! $here/src/holes $_param $out >$tmp.out
+    then
+        echo "    holes returned $? - see $seq.out.full"
+        failed=1
+        status=1
+    fi
+        
+
+    if [ $failed -eq 0 ]
+    then        
+        # quick check - how many holes did we get?
+        count=`xfs_bmap $out | egrep -c ': hole'`
+        echo "    $count hole(s) detected"
+        # and how big was the file?
+        _filesize $out
+        
+        if [ $count -ne $_count ]
+        then
+            echo "    unexpected number of holes - see $seq.out.full"
+            status=1
+            failed=1
+        fi
+    fi
+        
+    if [ $failed -eq 1 ]
+    then
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        echo "$_n - output from holes:"                     >>$here/$seq.out.full
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        cat $tmp.out                                        >>$here/$seq.out.full
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        echo "$_n - output from bmap:"                      >>$here/$seq.out.full
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        xfs_bmap -vvv $out                                  >>$here/$seq.out.full
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        echo "$_n - output from ls -li:"                    >>$here/$seq.out.full
+        echo "--------------------------------------"       >>$here/$seq.out.full
+        ls -li $out                                         >>$here/$seq.out.full
+        status=1
+    fi
+}
+
+# real QA test starts here
+
+rm -f $here/$seq.out.full
+
+# small & fairly dense
+_do_test 1 "-l 40960000 -b 40960 -i 10 -c 1" 100
+
+# big & sparse
+_do_test 2 "-l 409600000 -b 40960 -i 1000 -c 1" 10
+
+# no holes, but a very nasty way to write a file (lots of extents)
+_do_test 3 "-l 40960000 -b 40960 -i 10 -c 10" 0
+
+exit
diff --git a/012.out b/012.out
new file mode 100644 (file)
index 0000000..6dc7ce8
--- /dev/null
+++ b/012.out
@@ -0,0 +1,16 @@
+QA output created by 012
+
+holes.1 : -l 40960000 -b 40960 -i 10 -c 1
+-----------------------------------------------
+    100 hole(s) detected
+    filesize = 40960000
+
+holes.2 : -l 409600000 -b 40960 -i 1000 -c 1
+-----------------------------------------------
+    10 hole(s) detected
+    filesize = 409600000
+
+holes.3 : -l 40960000 -b 40960 -i 10 -c 10
+-----------------------------------------------
+    0 hole(s) detected
+    filesize = 40960000
diff --git a/013 b/013
new file mode 100755 (executable)
index 0000000..9de5028
--- /dev/null
+++ b/013
@@ -0,0 +1,141 @@
+#! /bin/sh
+# XFS QA Test No. 013
+# $Id: 1.1 $
+#
+# fsstress
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    # we might get here with a RO FS
+    mount -o remount,rw $TEST_DEV >/dev/null 2>&1
+    # now kill!
+    rm -rf $TEST_DIR/fsstress.$$.*
+}
+
+_filesize()
+{
+    ls -l $1 | $AWK_PROG '{print "    filesize = " $5}'
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_do_test()
+{
+    _n="$1"
+    _param="$2"
+    _count="$3"
+    
+    failed=0
+    
+    out=$TEST_DIR/fsstress.$$.$_n
+    rm -rf $out
+    if ! mkdir $out
+    then
+        echo "    failed to mkdir $out"
+        status=1
+        exit
+    fi
+    
+    echo ""
+    echo "-----------------------------------------------"
+    echo "fsstress.$_n : $_param"
+    echo "-----------------------------------------------"
+    # -v >$tmp.out
+    if ! $here/src/fsstress $_param $FSSTRESS_AVOID -n $_count -d $out >/dev/null 2>&1
+    then
+        echo "    fsstress (count=$_count) returned $? - see $seq.full"
+        
+        echo "--------------------------------------"       >>$here/$seq.full
+        echo "$_n - output from fsstress:"                  >>$here/$seq.full
+        echo "--------------------------------------"       >>$here/$seq.full
+        echo "<NOT LOGGED>"                                 >>$here/$seq.full
+        #cat $tmp.out                                       >>$here/$seq.full
+        status=1
+    fi
+    
+    _check_fs $TEST_DEV
+}
+
+
+# real QA test starts here
+
+rm -f $here/$seq.full
+echo "berevity is wit..."
+
+count=1000
+
+_check_fs $TEST_DEV
+
+# the default
+
+_do_test 1 "-r" $count
+
+# and the default with multiprocess
+
+_do_test 2 "-p 5 -r" $count
+
+# from Glen's notes
+
+_do_test 3 "-p 4 -z -f rmdir=10 -f link=10 -f creat=10 -f mkdir=10 -f rename=30 -f stat=30 -f unlink=30 -f truncate=20" $count
+
+exit
+
+# Test with error injection:
+# 
+# (error injection)
+# fsstress -n 1000 -d $scratch -p 4 -z -f rmdir=10 -f link=10 -f creat=10 \
+#          -f mkdir=10 -f rename=30 -f stat=30 -f unlink=30 -f truncate=20 \
+#          -e 1
+# 
+# Error values 1 - 6 test IFLUSH
+#         1 - corrupt buffer being flushed to di_core.di_magic
+#         2 - corrupt inode being flushed i_d.di_magic
+#         3 - corrupt IFREG format check
+#         4 - corrupt IFDIR format check
+#         5 - corrupt i_d.di_nextents
+#         6 - corrupt i_d.di_forkoff > sb_inodesize
diff --git a/013.out b/013.out
new file mode 100644 (file)
index 0000000..547369e
--- /dev/null
+++ b/013.out
@@ -0,0 +1,14 @@
+QA output created by 013
+berevity is wit...
+
+-----------------------------------------------
+fsstress.1 : -r
+-----------------------------------------------
+
+-----------------------------------------------
+fsstress.2 : -p 5 -r
+-----------------------------------------------
+
+-----------------------------------------------
+fsstress.3 : -p 4 -z -f rmdir=10 -f link=10 -f creat=10 -f mkdir=10 -f rename=30 -f stat=30 -f unlink=30 -f truncate=20
+-----------------------------------------------
diff --git a/014 b/014
new file mode 100755 (executable)
index 0000000..2c8949e
--- /dev/null
+++ b/014
@@ -0,0 +1,73 @@
+#! /bin/sh
+# XFS QA Test No. 014
+# $Id: 1.1 $
+#
+# truncfile
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -f $tmp.*; _cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    rm -rf $TEST_DIR/truncfile.$$.*
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+
+echo "berevity is wit..."
+
+echo "------"
+echo "test 1"
+echo "------"
+if ! src/truncfile -c 10000 $TEST_DIR/truncfile.$$.0 >$tmp.out 2>&1
+then
+    out=`cat $tmp.out`
+    echo "truncfile returned $? : \"$out\""
+else
+    echo "OK"
+fi
+
+exit
diff --git a/014.out b/014.out
new file mode 100644 (file)
index 0000000..960fcb0
--- /dev/null
+++ b/014.out
@@ -0,0 +1,6 @@
+QA output created by 014
+berevity is wit...
+------
+test 1
+------
+OK
diff --git a/015 b/015
new file mode 100755 (executable)
index 0000000..cec1380
--- /dev/null
+++ b/015
@@ -0,0 +1,135 @@
+#! /bin/sh
+# XFS QA Test No. 015
+# $Id: 1.1 $
+#
+# check out-of-space behaviour
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # success is the default!
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_cleanup()
+{
+       umount $SCRATCH_MNT
+}
+
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_free()
+{
+    _df_dir $TEST_DIR | $AWK_PROG '{ print $5 }'
+}
+
+_filter_dd()
+{
+    $AWK_PROG '
+        /records in/                { next }
+        /records out/               { next }
+        /No space left on device/   { print "   !!! disk full (expected)" 
+                                      next }
+                                    { print "   *** " $0 }
+    '
+}
+
+# real QA test starts here
+_require_scratch
+
+mkfs -t xfs -f -d size=50m $SCRATCH_DEV >/dev/null
+mount -t xfs $SCRATCH_DEV $SCRATCH_MNT
+out=$SCRATCH_MNT/fillup.$$
+
+free0=`_free`
+if [ -z "$free0" ]
+then
+    echo "   *** failed to get free space (0)"
+    exit 1
+fi
+
+echo "fill disk:"      # well, filesystem really - not disk
+
+dd if=/dev/zero of=$out bs=1024k 2>&1 | _filter_dd
+
+if [ ! -e $out ]
+then
+    echo "   *** file not created"
+    exit 1
+fi
+
+if [ ! -s $out ]
+then
+    echo "   *** file created with zero length"
+    ls -l $out
+    exit 1
+fi
+
+echo "delete fill:"
+
+if ! rm $out
+then
+    echo "   *** file not deleted"
+    exit 1
+fi
+
+if [ -e $out ]
+then
+    echo "   *** file still exists"
+    ls -l $out
+    exit 1
+fi
+
+echo "check free space:"
+
+free1=`_free`
+if [ -z "$free1" ]
+then
+    echo "   *** failed to get free space (1)"
+    exit 1
+fi
+
+echo -n "   !!! "
+_within_tolerance "free space" $free1 $free0 1% -v
+
+status=0
+exit
diff --git a/015.out b/015.out
new file mode 100644 (file)
index 0000000..d2c5ae6
--- /dev/null
+++ b/015.out
@@ -0,0 +1,6 @@
+QA output created by 015
+fill disk:
+   !!! disk full (expected)
+delete fill:
+check free space:
+   !!! free space is in range
diff --git a/016 b/016
new file mode 100755 (executable)
index 0000000..9043483
--- /dev/null
+++ b/016
@@ -0,0 +1,206 @@
+#! /bin/sh
+# XFS QA Test No. 016
+# $Id: 1.1 $
+#
+# test end of log overwrite bug #796141
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+#
+# pv 796141
+#
+# create a new FS, mostly fill the log. Then wrap the log back to the
+# start bit by bit to force wiping of stale blocks near the end of the
+# log. Check the block after the log ends to check for corruption
+#
+# assumptions : 
+#    - given we're only touching a single inode, the block after the
+#      log which is in the middle ag should never be touched.
+#      if it changes, we assume the log is writing over it
+#
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1
+
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    echo "*** unmount"
+    umount $SCRATCH_MNT 2>/dev/null
+}
+
+_block_filter()
+{
+    sed -e 's/[0-9][0-9]*\.\.[0-9][0-9]*/BLOCKRANGE/g'
+}
+
+_init()
+{
+    echo "*** reset partition"
+    $here/src/devzero -b 2048 -n 50 -v 198 $SCRATCH_DEV
+    echo "*** mkfs"
+    if ! mkfs -t xfs -f -d size=50m -l size=512b $SCRATCH_DEV >$tmp.out 2>&1
+    then
+       cat $tmp.out
+        echo "failed to mkfs $SCRATCH_DEV"
+        exit 1
+    fi
+}
+
+_log_traffic()
+{
+    count=$1
+    echo "*** generate log traffic"
+    
+    out=$SCRATCH_MNT/$$.tmp
+    
+    echo "   *** mount"
+    if ! mount $SCRATCH_DEV $SCRATCH_MNT -t xfs
+    then
+        echo "failed to mount $SCRATCH_DEV"
+        exit 1
+    fi
+
+    # having quota enabled means extra log traffic - evil!
+    $here/src/feature -u $SCRATCH_DEV && _notrun "User quota are enabled"
+    $here/src/feature -g $SCRATCH_DEV && _notrun "Group quota are enabled"
+    echo "   *** fiddle"
+    while [ $count -ge 0 ]
+    do
+        touch $out 
+        rm $out
+        let "count = count - 1"
+    done
+    
+    echo "   *** unmount"
+    if ! umount $SCRATCH_DEV
+    then
+        echo "failed to unmount $SCRATCH_DEV"
+        exit 1
+    fi
+}
+
+_log_size()
+{
+    xfs_logprint -tb $SCRATCH_DEV | $AWK_PROG '
+        /log device/ {  print $7}
+    '
+}
+
+_log_head()
+{
+    xfs_logprint -tb $SCRATCH_DEV | $AWK_PROG '
+        /head:/ { print $5 }
+    '
+}
+
+_after_log()
+{
+    xfs_db -r $1 -c "sb" -c "print" | $AWK_PROG '
+        /logstart/  { logstart = $3 }
+        /logblocks/ { logblocks = $3 }
+        END {
+            print logstart + logblocks
+        }
+    '
+}
+
+_check_corrupt()
+{
+    f="c6c6c6c6"
+    echo "*** check for corruption"
+    echo "expect $f..." >>$seq.full
+    xfs_db -r $1 -c "fsblock $2" -c "print" | head | tee -a $seq.full | \
+        grep -q -v "$f $f $f $f $f $f $f $f" && \
+            _fail "!!! block $2 corrupted!"
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+rm -f $seq.full
+
+_require_scratch
+_init
+
+block=`_after_log $SCRATCH_DEV`
+echo "fsblock after log = $block"               >>$seq.full
+_check_corrupt $SCRATCH_DEV $block
+
+size=`_log_size`
+echo "log size = $size BB"                      >>$seq.full
+head=`_log_head`
+echo "log position = $head"                     >>$seq.full
+
+[ $size -eq 4096 ] || \
+    _fail "!!! unexpected log size $size"
+[ $head -eq 2 ] || \
+    _fail "!!! unexpected initial log position $head"
+
+echo "    lots of traffic"                      >>$seq.full
+_log_traffic 850
+head=`_log_head`
+echo "log position = $head"                     >>$seq.full
+
+[ $head -gt 3850 -a $head -lt 4050 ] || \
+    _fail "!!! unexpected log position $head"
+
+for c in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+    echo "   little traffic"            >>$seq.full
+    _log_traffic 2
+    head=`_log_head`
+    echo "log position = $head"         >>$seq.full
+    _check_corrupt $SCRATCH_DEV $block
+done
+
+[ $head -lt 1000 ] || \
+    _fail "!!! unexpected log position $head"
+
+
+# happy exit
+rm $seq.full
+status=0
+exit 0
diff --git a/016.out b/016.out
new file mode 100644 (file)
index 0000000..f4f9a67
--- /dev/null
+++ b/016.out
@@ -0,0 +1,115 @@
+QA output created by 016
+*** reset partition
+Wrote 51200.00Kb (value 0xc6)
+*** mkfs
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** generate log traffic
+   *** mount
+   *** fiddle
+   *** unmount
+*** check for corruption
+*** unmount
diff --git a/017 b/017
new file mode 100755 (executable)
index 0000000..0ae5353
--- /dev/null
+++ b/017
@@ -0,0 +1,109 @@
+#! /bin/sh
+# XFS QA Test No. 017
+# $Id: 1.1 $
+#
+# test remount ro - pv 795642 
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1
+
+_cleanup()
+{
+    echo "*** unmount"
+    umount $SCRATCH_MNT 2>/dev/null
+}
+trap "_cleanup; rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+_clean_log()
+{
+    echo ""                                 >>$seq.full
+    echo "*** xfs_logprint ***"             >>$seq.full
+    echo ""                                 >>$seq.full
+    xfs_logprint -tb $1                     | tee -a $seq.full \
+        | head | grep -q "<CLEAN>" || _fail "DIRTY LOG"
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+_require_scratch
+
+echo "*** init FS"
+
+rm -f $seq.full
+umount $SCRATCH_DEV >/dev/null 2>&1
+echo "*** MKFS ***"                         >>$seq.full
+echo ""                                     >>$seq.full
+mkfs -t xfs -f $SCRATCH_DEV                 >>$seq.full 2>&1 \
+    || _fail "mkfs failed"
+mount -t xfs $SCRATCH_DEV $SCRATCH_MNT      >>$seq.full 2>&1 \
+    || _fail "mount failed"
+
+echo "*** test"
+
+for l in 0 1 2 3 4
+do
+        echo "    *** test $l"
+        src/fsstress -d $SCRATCH_MNT -n 1000 $FSSTRESS_AVOID >>$seq.full
+        
+        mount -o remount,ro $SCRATCH_DEV \
+            || _fail "remount ro failed"
+            
+        _clean_log $SCRATCH_DEV 
+        
+        echo ""                             >>$seq.full
+        echo "*** XFS_CHECK ***"            >>$seq.full
+        echo ""                             >>$seq.full
+        xfs_check $SCRATCH_DEV              >>$seq.full 2>&1 \
+            || _fail "xfs_check failed"
+        mount -o remount,rw $SCRATCH_DEV \
+            || _fail "remount rw failed"
+done
+
+echo "*** done"
+# happy exit
+rm -f $seq.full
+status=0
+exit 0
diff --git a/017.out b/017.out
new file mode 100644 (file)
index 0000000..2d11c94
--- /dev/null
+++ b/017.out
@@ -0,0 +1,10 @@
+QA output created by 017
+*** init FS
+*** test
+    *** test 0
+    *** test 1
+    *** test 2
+    *** test 3
+    *** test 4
+*** done
+*** unmount
diff --git a/018 b/018
new file mode 100755 (executable)
index 0000000..fd02e4d
--- /dev/null
+++ b/018
@@ -0,0 +1,143 @@
+#! /bin/sh
+# XFS QA Test No. 018
+# $Id: 1.1 $
+#
+# xfs_logprint test
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_cleanup()
+{
+    echo "*** unmount"
+    umount $SCRATCH_MNT 2>/dev/null
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_full()
+{
+    echo ""            >>$seq.full      
+    echo "*** $* ***"  >>$seq.full
+    echo ""            >>$seq.full
+}
+
+_clean_log()
+{
+    _full "clean_log : xfs_logprint"
+    xfs_logprint -t $1                     | tee -a $seq.full \
+        | head | grep -q "<CLEAN>" || _fail "DIRTY LOG"
+}
+
+_filter_logprint()
+{
+    sed '
+        s/data device: 0x[0-9a-f][0-9a-f]*/data device: <DEVICE>/;
+        s/log device: 0x[0-9a-f][0-9a-f]*/log device: <DEVICE>/;
+        s/daddr: [0-9][0-9]*/daddr: <DADDR>/;
+        s/length: [0-9][0-9]*/length: <LENGTH>/;
+        s/length: [0-9][0-9]*/length: <LENGTH>/;
+        s/^cycle num overwrites: .*$/cycle num overwrites: <TIDS>/;
+        s/tid: [0-9a-f][0-9a-f]*/tid: <TID>/;
+        s/tid:0x[0-9a-f][0-9a-f]*/tid:<TID>/;
+        s/q:0x[0-9a-f][0-9a-f]*/q:<Q>/;
+        s/a:0x[0-9a-f][0-9a-f]*/a:<A>/g;
+        s/blkno:0x[0-9a-f][0-9a-f]*/blkno:<BLKNO>/g;
+        s/blkno: [0-9][0-9]* (0x[0-9a-f]*)/blkno: <BLKNO> (<BLKNO>)/g;
+        s/blkno: [0-9][0-9]*/blkno: <BLKNO>/g;
+        s/boff: [0-9][0-9]*/boff: <BOFF>/g;
+        s/len: *[0-9][0-9]*/len:<LEN>/g;
+        s/skipped [0-9][0-9]* zeroed blocks/skipped <COUNT> zeroed blocks/;
+        s/atime:[0-9a-fx]*  *mtime:[0-9a-fx]*  *ctime:[0-9a-fx]*/atime:<TIME>  mtime:<TIME>  ctime:<TIME>/;
+        s/atime 0x[0-9a-f]* mtime 0x[0-9a-f]* ctime 0x[0-9a-f]*/atime <TIME>  mtime <TIME>  ctime <TIME>/;
+        s/block [0-9][0-9]*/block <BLOCK>/;
+        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>/;
+        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>/;
+        s/^uuid: *[0-9a-f-][0-9a-f-]* *format: *.*$/uuid: <UUID> format: <FORMAT>/;
+    '
+
+}
+
+_check_log()
+{
+    _clean_log $SCRATCH_DEV
+    echo "### xfs_logprint output ###"
+    xfs_logprint $SCRATCH_DEV 2>&1 | _filter_logprint
+    echo "### xfs_logprint -t -i -s 0 output ###"
+    xfs_logprint -t -i -s 0 $SCRATCH_DEV 2>&1 | _filter_logprint
+    echo "### xfs_logprint -t -b -s 0 output ###"
+    xfs_logprint -t -b -s 0 $SCRATCH_DEV 2>&1 | _filter_logprint
+}
+
+# real QA test starts here
+
+_require_scratch
+
+echo "*** init FS"
+
+rm -f $seq.full
+umount $SCRATCH_DEV >/dev/null 2>&1
+
+_full "mkfs"
+mkfs -t xfs -f $SCRATCH_DEV                 >>$seq.full 2>&1 \
+    || _fail "mkfs failed"
+_full " mount"
+mount -t xfs $SCRATCH_DEV $SCRATCH_MNT      >>$seq.full 2>&1 \
+    || _fail "mount failed"
+    
+# generate some log traffic - but not too much - life gets a little
+# more complicated if the log wraps around. This traffic is
+# pretty much arbitary, but could probably be made better than this.
+
+touch $SCRATCH_MNT/{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}
+    
+_full "umount"
+umount $SCRATCH_DEV >>$seq.full 2>&1 \
+    || _fail "umount failed"
+
+_check_log
+
+rm $seq.full
+exit
diff --git a/019 b/019
new file mode 100755 (executable)
index 0000000..bef42b0
--- /dev/null
+++ b/019
@@ -0,0 +1,162 @@
+#! /bin/sh
+# XFS QA Test No. 019
+# $Id: 1.1 $
+#
+# mkfs protofile test
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+seqfull="$seq.full"
+status=1       # failure is the default!
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_cleanup()
+{
+    echo "*** unmount"
+    umount $SCRATCH_MNT 2>/dev/null
+    rm -f $tmp.*
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_full()
+{
+    echo ""            >>$seqfull      
+    echo "*** $* ***"  >>$seqfull
+    echo ""            >>$seqfull
+}
+
+_filter_stat()
+{
+    sed '
+        /^Access:/d;
+        /^Modify:/d;
+        /^Change:/d;
+        s/Device: *[0-9][0-9]*,[0-9][0-9]*/Device: <DEVICE>/;
+        s/Inode: *[0-9][0-9]*/Inode: <INODE>/;
+    ' | tr -s ' '
+}
+
+# real QA test starts here
+
+_require_scratch
+
+protofile=$tmp.proto
+tempfile=$tmp.file
+
+echo fish >$tempfile
+$here/src/devzero -b 2048 -n 2 $tempfile.2 -c -v 44
+
+cat >$protofile <<EOF
+DUMMY1
+0 0
+: root directory
+d--777 3 1
+: a directory
+directory d--755 3 1 
+file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_0 ---755 3 1 $tempfile
+file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_1 ---755 3 1 $tempfile
+file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_2 ---755 3 1 $tempfile
+file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_3 ---755 3 1 $tempfile
+file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_4 ---755 3 1 $tempfile
+$
+: back in the root
+setuid -u-666 0 0 $tempfile
+setgid --g666 0 0 $tempfile
+setugid -ug666 0 0 $tempfile
+block_device b--012 3 1 161 162 
+char_device c--345 3 1 177 178
+pipe p--670 0 0
+symlink l--123 0 0 bigfile
+: a file we actually read
+bigfile ---666 3 0 $tempfile.2
+: done
+$
+EOF
+
+if [ $? -ne 0 ]
+then
+    _fail "failed to create test protofile"
+fi
+
+_verify_fs()
+{
+       echo "*** create FS version $1"
+       VERSION="-n version=$1"
+
+       rm -f $seqfull
+       umount $SCRATCH_DEV >/dev/null 2>&1
+
+       _full "mkfs"
+       mkfs -t xfs -f $VERSION -p $protofile $SCRATCH_DEV >>$seqfull 2>&1 \
+               || _fail "mkfs failed"
+           
+       echo "*** check FS"
+       _check_fs $SCRATCH_DEV
+
+       echo "*** mount FS"
+       _full " mount"
+       mount -t xfs $SCRATCH_DEV $SCRATCH_MNT >>$seqfull 2>&1 \
+               || _fail "mount failed"
+           
+       echo "*** verify FS"
+       (cd $SCRATCH_MNT ; find . | sort \
+               | xargs $here/src/lstat64 | _filter_stat)
+       diff -q $SCRATCH_MNT/bigfile $tempfile.2 \
+               || _fail "bigfile corrupted"
+    
+       echo "*** unmount FS"
+       _full "umount"
+       umount $SCRATCH_DEV >>$seqfull 2>&1 \
+               || _fail "umount failed"
+           
+       echo "*** check FS"
+       _check_fs $SCRATCH_DEV
+}
+
+_verify_fs 1
+_verify_fs 2
+
+echo "*** done"
+rm $seqfull
+status=0
+exit
diff --git a/019.out b/019.out
new file mode 100644 (file)
index 0000000..d6397e1
--- /dev/null
+++ b/019.out
@@ -0,0 +1,164 @@
+QA output created by 019
+Wrote 2048.00Kb (value 0x2c)
+*** create FS version 1
+*** check FS
+*** mount FS
+*** verify FS
+ File: "."
+ Size: 4096 Filetype: Directory
+ Mode: (0777/drwxrwxrwx) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 3 
+
+ File: "./bigfile"
+ Size: 2097152 Filetype: Regular File
+ Mode: (0666/-rw-rw-rw-) Uid: (3) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./block_device"
+ Size: 0 Filetype: Block Device
+ Mode: (0012/b-----x-w-) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 Device type: 161,162
+
+ File: "./char_device"
+ Size: 0 Filetype: Character Device
+ Mode: (0345/c-wxr--r-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 Device type: 177,178
+
+ File: "./directory"
+ Size: 4096 Filetype: Directory
+ Mode: (0755/drwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 2 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_0"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_1"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_2"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_3"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_4"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./pipe"
+ Size: 0 Filetype: Fifo File
+ Mode: (0670/frw-rwx---) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./setgid"
+ Size: 5 Filetype: Regular File
+ Mode: (2666/-rw-rwsrw-) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./setugid"
+ Size: 5 Filetype: Regular File
+ Mode: (6666/-rwsrwsrw-) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./setuid"
+ Size: 5 Filetype: Regular File
+ Mode: (4666/-rwsrw-rw-) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./symlink"
+ Size: 7 Filetype: Symbolic Link
+ Mode: (0123/l--x-w--wx) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+*** unmount FS
+*** check FS
+*** create FS version 2
+*** check FS
+*** mount FS
+*** verify FS
+ File: "."
+ Size: 138 Filetype: Directory
+ Mode: (0777/drwxrwxrwx) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 3 
+
+ File: "./bigfile"
+ Size: 2097152 Filetype: Regular File
+ Mode: (0666/-rw-rw-rw-) Uid: (3) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./block_device"
+ Size: 0 Filetype: Block Device
+ Mode: (0012/b-----x-w-) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 Device type: 161,162
+
+ File: "./char_device"
+ Size: 0 Filetype: Character Device
+ Mode: (0345/c-wxr--r-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 Device type: 177,178
+
+ File: "./directory"
+ Size: 4096 Filetype: Directory
+ Mode: (0755/drwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 2 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_0"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_1"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_2"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_3"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./directory/file_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_4"
+ Size: 5 Filetype: Regular File
+ Mode: (0755/-rwxr-xr-x) Uid: (3) Gid: (1)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./pipe"
+ Size: 0 Filetype: Fifo File
+ Mode: (0670/frw-rwx---) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./setgid"
+ Size: 5 Filetype: Regular File
+ Mode: (2666/-rw-rwsrw-) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./setugid"
+ Size: 5 Filetype: Regular File
+ Mode: (6666/-rwsrwsrw-) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./setuid"
+ Size: 5 Filetype: Regular File
+ Mode: (4666/-rwsrw-rw-) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+
+ File: "./symlink"
+ Size: 7 Filetype: Symbolic Link
+ Mode: (0123/l--x-w--wx) Uid: (0) Gid: (0)
+Device: <DEVICE> Inode: <INODE> Links: 1 
+*** unmount FS
+*** check FS
+*** done
+*** unmount
diff --git a/020 b/020
new file mode 100755 (executable)
index 0000000..d9faaab
--- /dev/null
+++ b/020
@@ -0,0 +1,206 @@
+#! /bin/sh
+# XFS QA Test No. 020
+# $Id: 1.1 $
+#
+# extended attributes
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -f $tmp.* $testfile; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_filter()
+{
+    sed "s#$TEST_DIR[^ :]*#<TESTFILE>#g; 
+            s#$tmp[^ :]*#<TMPFILE>#g;
+            s#/proc[^ :]*#<PROCFILE>#g" $1
+}
+
+_attr()
+{
+    xfs_attr $* 2>$tmp.err >$tmp.out
+    exit=$?
+    _filter $tmp.out
+    _filter $tmp.err 1>&2
+    return $exit
+}
+
+_attr_list()
+{
+    file=$1
+    
+    echo "   *** print attributes"
+    if ! _attr -l $file >$tmp.raw
+    then
+        echo "      !!! error return"
+        return 1
+    fi
+    
+    $AWK_PROG -v file=$file '
+        {
+            print substr($2,2,length($2)-2)
+            count++
+        }
+        END { 
+            exit count 
+        }
+        ' <$tmp.raw >$tmp.list
+        
+    echo "      *** $? attribute(s)"
+    for l in `cat $tmp.list`
+    do
+        if ! _attr -g $l $file >$tmp.raw
+        then
+            echo "         *** $l"
+            echo "         !!! error return"
+            return 1
+        fi
+        $AWK_PROG '
+            NR==1 {
+                print "         *** field: " substr($2,2,length($2)-2) \
+                      " length: " $5
+                next
+            }
+            {
+                print "            ::: " $0
+            }
+        ' <$tmp.raw
+        
+    done
+}
+
+
+# real QA test starts here
+
+testfile=$TEST_DIR/attribute_$$
+
+echo "*** list non-existant file"
+_attr_list $testfile
+
+echo "*** list non-xfs file (in /proc)"
+_attr_list /proc/devices
+
+echo "*** list empty file"
+touch $testfile
+_attr_list $testfile
+
+echo "*** query non-existant attribute"
+_attr -g "nonexistant" $testfile 2>&1
+
+echo "*** one attribute"
+echo "fish" | _attr -s fish $testfile
+_attr_list $testfile
+
+echo "*** replace attribute"
+echo "fish3" | _attr -s fish $testfile
+_attr_list $testfile
+
+echo "*** add attribute"
+echo "fish2" | _attr -s snrub $testfile
+_attr_list $testfile
+
+echo "*** remove attribute"
+_attr -r fish $testfile
+_attr_list $testfile
+
+echo "*** add lots of attributes"
+v=0
+while [ $v -lt 1000 ]
+do
+    echo "value_$v" | xfs_attr -s "attribute_$v" $testfile >/dev/null
+    if [ $? -ne 0 ]
+    then
+        echo "!!! failed to add \"attribute_$v\""
+        exit 1
+    fi
+    
+    let "v = v + 1"
+done
+
+echo "*** check"
+# don't print it all out...
+xfs_attr -l $testfile \
+    | $AWK_PROG '{ l++ } END {print "   *** " l " attribute(s)" }'
+
+echo "*** remove lots of attributes"
+v=0
+while [ $v -lt 1000 ]
+do
+    if ! xfs_attr -r "attribute_$v" $testfile >/dev/null
+    then
+        echo "!!! failed to add \"attribute_$v\""
+        exit 1
+    fi
+    
+    let "v = v + 1"
+done
+
+_attr_list $testfile
+
+echo "*** really long value"
+dd if=/dev/zero bs=1024 count=100 2>/dev/null \
+    | _attr -s "long_attr" $testfile >/dev/null
+    
+_attr -g "long_attr" $testfile | tail -n +2 | od -t x1
+_attr -r "long_attr" $testfile >/dev/null
+
+
+echo "*** set/get/remove really long names (expect failure)"
+short="XXXXXXXXXX"
+long="$short$short$short$short$short$short$short$short$short$short"
+vlong="$long$long$long"
+
+_attr -s $vlong -V fish $testfile 2>&1 >/dev/null
+_attr -g $vlong $testfile 2>&1 >/dev/null
+_attr -r $vlong $testfile 2>&1 >/dev/null
+
+echo "*** check final"
+
+_attr_list $testfile
+
+echo "*** delete"
+rm -f $testfile
+
+exit
diff --git a/020.out b/020.out
new file mode 100644 (file)
index 0000000..82b5ddc
--- /dev/null
+++ b/020.out
@@ -0,0 +1,81 @@
+QA output created by 020
+*** list non-existant file
+   *** print attributes
+attr_list: No such file or directory
+Could not list attributes for <TESTFILE>
+      !!! error return
+*** list non-xfs file (in /proc)
+   *** print attributes
+attr_list: Invalid argument
+Could not list attributes for <PROCFILE>
+      !!! error return
+*** list empty file
+   *** print attributes
+      *** 0 attribute(s)
+*** query non-existant attribute
+attr_get: No data available
+Could not get "nonexistant" for <TESTFILE>
+*** one attribute
+Attribute "fish" set to a 5 byte value for <TESTFILE>:
+fish
+
+   *** print attributes
+      *** 1 attribute(s)
+         *** field: fish length: 5
+            ::: fish
+            ::: 
+*** replace attribute
+Attribute "fish" set to a 6 byte value for <TESTFILE>:
+fish3
+
+   *** print attributes
+      *** 1 attribute(s)
+         *** field: fish length: 6
+            ::: fish3
+            ::: 
+*** add attribute
+Attribute "snrub" set to a 6 byte value for <TESTFILE>:
+fish2
+
+   *** print attributes
+      *** 2 attribute(s)
+         *** field: fish length: 6
+            ::: fish3
+            ::: 
+         *** field: snrub length: 6
+            ::: fish2
+            ::: 
+*** remove attribute
+   *** print attributes
+      *** 1 attribute(s)
+         *** field: snrub length: 6
+            ::: fish2
+            ::: 
+*** add lots of attributes
+*** check
+   *** 1001 attribute(s)
+*** remove lots of attributes
+   *** print attributes
+      *** 1 attribute(s)
+         *** field: snrub length: 6
+            ::: fish2
+            ::: 
+*** really long value
+0000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+*
+0200000 0a
+0200001
+*** set/get/remove really long names (expect failure)
+attr_set: Bad address
+Could not set "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" for <TESTFILE>
+attr_get: Bad address
+Could not get "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" for <TESTFILE>
+attr_remove: Bad address
+Could not remove "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" for <TESTFILE>
+*** check final
+   *** print attributes
+      *** 1 attribute(s)
+         *** field: snrub length: 6
+            ::: fish2
+            ::: 
+*** delete
diff --git a/021 b/021
new file mode 100755 (executable)
index 0000000..ac711b4
--- /dev/null
+++ b/021
@@ -0,0 +1,126 @@
+#! /bin/sh
+# XFS QA Test No. 021
+# $Id: 1.1 $
+#
+# xfs_db type attr test (pv 797508 linux-xfs & IRIX)
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_cleanup()
+{
+    echo "*** unmount"
+    umount $SCRATCH_MNT 2>/dev/null
+    rm -f $tmp.*
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_s()
+{
+    echo $2 | xfs_attr -s $1 $testfile >/dev/null
+}
+
+_attr()
+{
+    xfs_attr $* 2>$tmp.err >$tmp.out
+    exit=$?
+    sed "s#$SCRATCH_MNT[^ .:]*#<TESTFILE>#g; s#$tmp[^ :]*#<TMPFILE>#g;" $tmp.out
+    sed "s#$SCRATCH_MNT[^ .:]*#<TESTFILE>#g; s#$tmp[^ :]*#<TMPFILE>#g;" $tmp.err 1>&2
+    return $exit
+}
+
+# real QA test starts here
+
+_require_scratch
+
+
+echo "*** mkfs"
+
+rm -f $seq.full
+umount $SCRATCH_DEV >/dev/null 2>&1
+
+mkfs -t xfs -f $SCRATCH_DEV >/dev/null \
+    || _fail "mkfs failed"
+  
+echo "*** mount FS"
+mount -t xfs $SCRATCH_DEV $SCRATCH_MNT >/dev/null \
+    || _fail "mount failed"
+    
+testfile=$SCRATCH_MNT/testfile
+echo "*** make test file 1"
+
+touch $testfile.1
+echo "v1" | _attr -s "a1" $testfile.1 >/dev/null
+echo "v2--" | _attr -s "a2--" $testfile.1 >/dev/null
+_attr -l $testfile.1
+inum_1=`ls -li $testfile.1 | $AWK_PROG '{ print $1 }'`
+
+echo "*** make test file 2"
+
+touch $testfile.2
+echo "value_1" | _attr -s "a1" $testfile.2 >/dev/null
+echo "value_2" | _attr -s "a2-----" $testfile.2 >/dev/null
+
+(echo start ; dd if=/dev/zero bs=65525 count=1 ; echo end ) \
+    | _attr -s "a3" $testfile.2 >/dev/null
+    
+_attr -l $testfile.2
+inum_2=`ls -li $testfile.2 | $AWK_PROG '{ print $1 }'`
+    
+echo "*** unmount FS"
+umount $SCRATCH_DEV >>$seq.full 2>&1 \
+    || _fail "umount failed"
+    
+echo "*** dump attributes (1)"
+
+xfs_db -r -c "inode $inum_1" -c "print a.sfattr" $SCRATCH_DEV
+
+echo "*** dump attributes (2)"
+
+xfs_db -r -c "inode $inum_2" -c "a a.bmx[0].startblock" -c "print" $SCRATCH_DEV
+    
+echo "*** done"
+rm $seq.full
+exit
diff --git a/021.out b/021.out
new file mode 100644 (file)
index 0000000..34864b4
--- /dev/null
+++ b/021.out
@@ -0,0 +1,50 @@
+QA output created by 021
+*** mkfs
+*** mount FS
+*** make test file 1
+Attribute "a1" has a 3 byte value for <TESTFILE>.1
+Attribute "a2--" has a 5 byte value for <TESTFILE>.1
+*** make test file 2
+1+0 records in
+1+0 records out
+Attribute "a1" has a 8 byte value for <TESTFILE>.2
+Attribute "a3" has a 65535 byte value for <TESTFILE>.2
+Attribute "a2-----" has a 8 byte value for <TESTFILE>.2
+*** unmount FS
+*** dump attributes (1)
+a.sfattr.hdr.totsize = 24
+a.sfattr.hdr.count = 2
+a.sfattr.list[0].namelen = 2
+a.sfattr.list[0].valuelen = 3
+a.sfattr.list[0].root = 0
+a.sfattr.list[0].name = "a1"
+a.sfattr.list[0].value = "v1\d"
+a.sfattr.list[1].namelen = 4
+a.sfattr.list[1].valuelen = 5
+a.sfattr.list[1].root = 0
+a.sfattr.list[1].name = "a2--"
+a.sfattr.list[1].value = "v2--\d"
+*** dump attributes (2)
+hdr.info.forw = 0
+hdr.info.back = 0
+hdr.info.magic = 0xfbee
+hdr.count = 3
+hdr.usedbytes = 52
+hdr.firstused = 4044
+hdr.holes = 0
+hdr.freemap[0-2] = [base,size] 0:[56,3988] 1:[0,0] 2:[0,0]
+entries[0-2] = [hashval,nameidx,incomplete,root,local] 0:[0x30b1,4080,0,0,1] 1:[0x30b3,4044,0,0,0] 2:[0xd5aad33f,4060,0,0,1]
+nvlist[0].valuelen = 8
+nvlist[0].namelen = 2
+nvlist[0].name = "a1"
+nvlist[0].value = "value_1\d"
+nvlist[1].valueblk = 0x1
+nvlist[1].valuelen = 65535
+nvlist[1].namelen = 2
+nvlist[1].name = "a3"
+nvlist[2].valuelen = 8
+nvlist[2].namelen = 7
+nvlist[2].name = "a2-----"
+nvlist[2].value = "value_2\d"
+*** done
+*** unmount
diff --git a/022 b/022
new file mode 100755 (executable)
index 0000000..6d2bd16
--- /dev/null
+++ b/022
@@ -0,0 +1,66 @@
+#! /bin/sh
+# XFS QA Test No. 022
+# $Id: 1.1 $
+#
+# Test out a level 0 dump/restore to a tape of a subdir
+# i.e. it is testing out drive_scsitape.c
+#
+# Use src/fsstress to create a directory structure with a mix of files
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -rf $tmp.*; exit \$status" 0 1 2 3 15
+
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape
+_create_dumpdir_stress
+_erase_hard
+_do_dump_sub
+_do_restore
+_ls_compare_sub
+
+# success, all done
+exit
diff --git a/022.out b/022.out
new file mode 100644 (file)
index 0000000..fd4d03b
--- /dev/null
+++ b/022.out
@@ -0,0 +1,56 @@
+QA output created by 022
+Put scsi tape driver into variable block size mode
+Creating directory system to dump using src/fsstress.
+
+-----------------------------------------------
+fsstress : -f link=10 -f creat=10 -f mkdir=10 -f truncate=5 -f symlink=10
+-----------------------------------------------
+Erasing tape
+Dumping to tape...
+xfsdump  -s DUMP_SUBDIR -f TAPE_DEV -M stress_tape_media -L stress_022 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_022"
+xfsdump: ino map phase 1: parsing subtree selections
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: pruning unneeded subtrees
+xfsdump: ino map phase 4: estimating dump size
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: writing stream terminator
+xfsdump: beginning media stream terminator
+xfsdump: media file 2 (media 0, file 2)
+xfsdump: ending media stream terminator
+xfsdump: media stream terminator size 1048576 bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -f TAPE_DEV  -L stress_022 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing listing of dump directory with restore directory
+Files TMP.dump_dir and TMP.restore_dir are identical
diff --git a/023 b/023
new file mode 100755 (executable)
index 0000000..b75cd27
--- /dev/null
+++ b/023
@@ -0,0 +1,66 @@
+#! /bin/sh
+# XFS QA Test No. 023
+# $Id: 1.1 $
+#
+# To test xfsdump/restore to tape using a directory with
+# files with data created by src/fill.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@bruce.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -rf $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape
+_create_dumpdir_fill
+_erase_hard
+_do_dump_sub
+_do_restore
+_diff_compare_sub
+_ls_compare_sub
+
+# success, all done
+exit
diff --git a/023.out b/023.out
new file mode 100644 (file)
index 0000000..823c80f
--- /dev/null
+++ b/023.out
@@ -0,0 +1,90 @@
+QA output created by 023
+Put scsi tape driver into variable block size mode
+Creating directory system to dump using src/fill.
+Setup ....................................
+Erasing tape
+Dumping to tape...
+xfsdump  -s DUMP_SUBDIR -f TAPE_DEV -M stress_tape_media -L stress_023 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_023"
+xfsdump: ino map phase 1: parsing subtree selections
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: pruning unneeded subtrees
+xfsdump: ino map phase 4: estimating dump size
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: writing stream terminator
+xfsdump: beginning media stream terminator
+xfsdump: media file 2 (media 0, file 2)
+xfsdump: ending media stream terminator
+xfsdump: media stream terminator size 1048576 bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -f TAPE_DEV  -L stress_023 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/big and RESTORE_DIR/DUMP_SUBDIR/big are identical
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Files DUMP_DIR/sub/a00 and RESTORE_DIR/DUMP_SUBDIR/sub/a00 are identical
+Files DUMP_DIR/sub/a000 and RESTORE_DIR/DUMP_SUBDIR/sub/a000 are identical
+Files DUMP_DIR/sub/b and RESTORE_DIR/DUMP_SUBDIR/sub/b are identical
+Files DUMP_DIR/sub/b00 and RESTORE_DIR/DUMP_SUBDIR/sub/b00 are identical
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Files DUMP_DIR/sub/c00 and RESTORE_DIR/DUMP_SUBDIR/sub/c00 are identical
+Files DUMP_DIR/sub/d and RESTORE_DIR/DUMP_SUBDIR/sub/d are identical
+Files DUMP_DIR/sub/d00 and RESTORE_DIR/DUMP_SUBDIR/sub/d00 are identical
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Files DUMP_DIR/sub/e00 and RESTORE_DIR/DUMP_SUBDIR/sub/e00 are identical
+Files DUMP_DIR/sub/e000 and RESTORE_DIR/DUMP_SUBDIR/sub/e000 are identical
+Files DUMP_DIR/sub/f and RESTORE_DIR/DUMP_SUBDIR/sub/f are identical
+Files DUMP_DIR/sub/f00 and RESTORE_DIR/DUMP_SUBDIR/sub/f00 are identical
+Files DUMP_DIR/sub/g and RESTORE_DIR/DUMP_SUBDIR/sub/g are identical
+Files DUMP_DIR/sub/g00 and RESTORE_DIR/DUMP_SUBDIR/sub/g00 are identical
+Files DUMP_DIR/sub/h and RESTORE_DIR/DUMP_SUBDIR/sub/h are identical
+Files DUMP_DIR/sub/h00 and RESTORE_DIR/DUMP_SUBDIR/sub/h00 are identical
+Files DUMP_DIR/sub/h000 and RESTORE_DIR/DUMP_SUBDIR/sub/h000 are identical
+Files DUMP_DIR/sub/i and RESTORE_DIR/DUMP_SUBDIR/sub/i are identical
+Files DUMP_DIR/sub/i00 and RESTORE_DIR/DUMP_SUBDIR/sub/i00 are identical
+Files DUMP_DIR/sub/j and RESTORE_DIR/DUMP_SUBDIR/sub/j are identical
+Files DUMP_DIR/sub/j00 and RESTORE_DIR/DUMP_SUBDIR/sub/j00 are identical
+Files DUMP_DIR/sub/k and RESTORE_DIR/DUMP_SUBDIR/sub/k are identical
+Files DUMP_DIR/sub/k00 and RESTORE_DIR/DUMP_SUBDIR/sub/k00 are identical
+Files DUMP_DIR/sub/k000 and RESTORE_DIR/DUMP_SUBDIR/sub/k000 are identical
+Files DUMP_DIR/sub/l and RESTORE_DIR/DUMP_SUBDIR/sub/l are identical
+Files DUMP_DIR/sub/l00 and RESTORE_DIR/DUMP_SUBDIR/sub/l00 are identical
+Files DUMP_DIR/sub/m and RESTORE_DIR/DUMP_SUBDIR/sub/m are identical
+Files DUMP_DIR/sub/m00 and RESTORE_DIR/DUMP_SUBDIR/sub/m00 are identical
+Files DUMP_DIR/sub/n and RESTORE_DIR/DUMP_SUBDIR/sub/n are identical
+Files DUMP_DIR/sub/n00 and RESTORE_DIR/DUMP_SUBDIR/sub/n00 are identical
+Files DUMP_DIR/sub/small and RESTORE_DIR/DUMP_SUBDIR/sub/small are identical
+Comparing listing of dump directory with restore directory
+Files TMP.dump_dir and TMP.restore_dir are identical
diff --git a/024 b/024
new file mode 100755 (executable)
index 0000000..826b014
--- /dev/null
+++ b/024
@@ -0,0 +1,67 @@
+#! /bin/sh
+# XFS QA Test No. 024
+# $Id: 1.1 $
+#
+# Test out incremental dumps
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@bruce.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape
+_create_dumpdir_fill
+_erase_hard
+_do_dump
+_append_dumpdir_fill
+_erase_hard
+_do_dump_incremental
+_do_restore
+_diff_compare
+
+# success, all done
+exit
diff --git a/024.out b/024.out
new file mode 100644 (file)
index 0000000..83ea8bf
--- /dev/null
+++ b/024.out
@@ -0,0 +1,123 @@
+QA output created by 024
+Put scsi tape driver into variable block size mode
+Creating directory system to dump using src/fill.
+Setup ....................................
+Erasing tape
+Dumping to tape...
+xfsdump  -l0 -f TAPE_DEV -M stress_tape_media -L stress_024 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_024"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: writing stream terminator
+xfsdump: beginning media stream terminator
+xfsdump: media file 2 (media 0, file 2)
+xfsdump: ending media stream terminator
+xfsdump: media stream terminator size 1048576 bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Erasing tape
+Dumping incrementally to tape...
+xfsdump  -l1 -f TAPE_DEV -M stress_tape_media -L stress_024 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 1 incremental dump of HOSTNAME:SCRATCH_MNT based on level 0 dump begun DATE
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_024"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: pruning unneeded subtrees
+xfsdump: ino map phase 4: estimating dump size
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: preparing drive
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: writing stream terminator
+xfsdump: beginning media stream terminator
+xfsdump: media file 2 (media 0, file 2)
+xfsdump: ending media stream terminator
+xfsdump: media stream terminator size 1048576 bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -f TAPE_DEV  -L stress_024 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Only in DUMP_DIR: big
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Only in DUMP_DIR/sub: a00
+Only in DUMP_DIR/sub: a000
+Only in DUMP_DIR/sub: b
+Only in DUMP_DIR/sub: b00
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Only in DUMP_DIR/sub: c00
+Only in DUMP_DIR/sub: d
+Only in DUMP_DIR/sub: d00
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Only in DUMP_DIR/sub: e00
+Only in DUMP_DIR/sub: e000
+Only in DUMP_DIR/sub: f
+Only in DUMP_DIR/sub: f00
+Only in DUMP_DIR/sub: g
+Only in DUMP_DIR/sub: g00
+Only in DUMP_DIR/sub: h
+Only in DUMP_DIR/sub: h00
+Only in DUMP_DIR/sub: h000
+Only in DUMP_DIR/sub: i
+Only in DUMP_DIR/sub: i00
+Only in DUMP_DIR/sub: j
+Only in DUMP_DIR/sub: j00
+Only in DUMP_DIR/sub: k
+Only in DUMP_DIR/sub: k00
+Only in DUMP_DIR/sub: k000
+Only in DUMP_DIR/sub: l
+Only in DUMP_DIR/sub: l00
+Only in DUMP_DIR/sub: m
+Only in DUMP_DIR/sub: m00
+Only in DUMP_DIR/sub: n
+Only in DUMP_DIR/sub: n00
+Only in DUMP_DIR/sub: small
+Only in SCRATCH_MNT: RESTORE_SUBDIR
diff --git a/025 b/025
new file mode 100755 (executable)
index 0000000..4ad29fc
--- /dev/null
+++ b/025
@@ -0,0 +1,64 @@
+#! /bin/sh
+# XFS QA Test No. 025
+# $Id: 1.1 $
+#
+# Test dump/restore using -m option (min strategy) 
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@bruce.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape
+_create_dumpdir_fill
+_erase_hard
+_do_dump_min
+_do_restore_min
+_diff_compare
+
+# success, all done
+exit
diff --git a/025.out b/025.out
new file mode 100644 (file)
index 0000000..36e850d
--- /dev/null
+++ b/025.out
@@ -0,0 +1,84 @@
+QA output created by 025
+Put scsi tape driver into variable block size mode
+Creating directory system to dump using src/fill.
+Setup ....................................
+Erasing tape
+Dumping to tape...
+xfsdump  -m -b 1048576 -l0 -f TAPE_DEV -M stress_tape_media -L stress_025 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_025"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -m -b 1048576 -f TAPE_DEV  -L stress_025 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/big and RESTORE_DIR/DUMP_SUBDIR/big are identical
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Files DUMP_DIR/sub/a00 and RESTORE_DIR/DUMP_SUBDIR/sub/a00 are identical
+Files DUMP_DIR/sub/a000 and RESTORE_DIR/DUMP_SUBDIR/sub/a000 are identical
+Files DUMP_DIR/sub/b and RESTORE_DIR/DUMP_SUBDIR/sub/b are identical
+Files DUMP_DIR/sub/b00 and RESTORE_DIR/DUMP_SUBDIR/sub/b00 are identical
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Files DUMP_DIR/sub/c00 and RESTORE_DIR/DUMP_SUBDIR/sub/c00 are identical
+Files DUMP_DIR/sub/d and RESTORE_DIR/DUMP_SUBDIR/sub/d are identical
+Files DUMP_DIR/sub/d00 and RESTORE_DIR/DUMP_SUBDIR/sub/d00 are identical
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Files DUMP_DIR/sub/e00 and RESTORE_DIR/DUMP_SUBDIR/sub/e00 are identical
+Files DUMP_DIR/sub/e000 and RESTORE_DIR/DUMP_SUBDIR/sub/e000 are identical
+Files DUMP_DIR/sub/f and RESTORE_DIR/DUMP_SUBDIR/sub/f are identical
+Files DUMP_DIR/sub/f00 and RESTORE_DIR/DUMP_SUBDIR/sub/f00 are identical
+Files DUMP_DIR/sub/g and RESTORE_DIR/DUMP_SUBDIR/sub/g are identical
+Files DUMP_DIR/sub/g00 and RESTORE_DIR/DUMP_SUBDIR/sub/g00 are identical
+Files DUMP_DIR/sub/h and RESTORE_DIR/DUMP_SUBDIR/sub/h are identical
+Files DUMP_DIR/sub/h00 and RESTORE_DIR/DUMP_SUBDIR/sub/h00 are identical
+Files DUMP_DIR/sub/h000 and RESTORE_DIR/DUMP_SUBDIR/sub/h000 are identical
+Files DUMP_DIR/sub/i and RESTORE_DIR/DUMP_SUBDIR/sub/i are identical
+Files DUMP_DIR/sub/i00 and RESTORE_DIR/DUMP_SUBDIR/sub/i00 are identical
+Files DUMP_DIR/sub/j and RESTORE_DIR/DUMP_SUBDIR/sub/j are identical
+Files DUMP_DIR/sub/j00 and RESTORE_DIR/DUMP_SUBDIR/sub/j00 are identical
+Files DUMP_DIR/sub/k and RESTORE_DIR/DUMP_SUBDIR/sub/k are identical
+Files DUMP_DIR/sub/k00 and RESTORE_DIR/DUMP_SUBDIR/sub/k00 are identical
+Files DUMP_DIR/sub/k000 and RESTORE_DIR/DUMP_SUBDIR/sub/k000 are identical
+Files DUMP_DIR/sub/l and RESTORE_DIR/DUMP_SUBDIR/sub/l are identical
+Files DUMP_DIR/sub/l00 and RESTORE_DIR/DUMP_SUBDIR/sub/l00 are identical
+Files DUMP_DIR/sub/m and RESTORE_DIR/DUMP_SUBDIR/sub/m are identical
+Files DUMP_DIR/sub/m00 and RESTORE_DIR/DUMP_SUBDIR/sub/m00 are identical
+Files DUMP_DIR/sub/n and RESTORE_DIR/DUMP_SUBDIR/sub/n are identical
+Files DUMP_DIR/sub/n00 and RESTORE_DIR/DUMP_SUBDIR/sub/n00 are identical
+Files DUMP_DIR/sub/small and RESTORE_DIR/DUMP_SUBDIR/sub/small are identical
+Only in SCRATCH_MNT: RESTORE_SUBDIR
diff --git a/026 b/026
new file mode 100755 (executable)
index 0000000..8f45c5b
--- /dev/null
+++ b/026
@@ -0,0 +1,62 @@
+#! /bin/sh
+# XFS QA Test No. 026
+# $Id: 1.1 $
+#
+# Test xfsdump/xfsrestore to a dump file (as opposed to a tape)
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@bruce.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_create_dumpdir_fill
+_do_dump_file
+_do_restore_file
+_diff_compare
+
+# success, all done
+exit
diff --git a/026.out b/026.out
new file mode 100644 (file)
index 0000000..25466e5
--- /dev/null
+++ b/026.out
@@ -0,0 +1,74 @@
+QA output created by 026
+Creating directory system to dump using src/fill.
+Setup ....................................
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L stress_026 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_026"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Restoring from file...
+xfsrestore  -f DUMP_FILE  -L stress_026 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/big and RESTORE_DIR/DUMP_SUBDIR/big are identical
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Files DUMP_DIR/sub/a00 and RESTORE_DIR/DUMP_SUBDIR/sub/a00 are identical
+Files DUMP_DIR/sub/a000 and RESTORE_DIR/DUMP_SUBDIR/sub/a000 are identical
+Files DUMP_DIR/sub/b and RESTORE_DIR/DUMP_SUBDIR/sub/b are identical
+Files DUMP_DIR/sub/b00 and RESTORE_DIR/DUMP_SUBDIR/sub/b00 are identical
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Files DUMP_DIR/sub/c00 and RESTORE_DIR/DUMP_SUBDIR/sub/c00 are identical
+Files DUMP_DIR/sub/d and RESTORE_DIR/DUMP_SUBDIR/sub/d are identical
+Files DUMP_DIR/sub/d00 and RESTORE_DIR/DUMP_SUBDIR/sub/d00 are identical
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Files DUMP_DIR/sub/e00 and RESTORE_DIR/DUMP_SUBDIR/sub/e00 are identical
+Files DUMP_DIR/sub/e000 and RESTORE_DIR/DUMP_SUBDIR/sub/e000 are identical
+Files DUMP_DIR/sub/f and RESTORE_DIR/DUMP_SUBDIR/sub/f are identical
+Files DUMP_DIR/sub/f00 and RESTORE_DIR/DUMP_SUBDIR/sub/f00 are identical
+Files DUMP_DIR/sub/g and RESTORE_DIR/DUMP_SUBDIR/sub/g are identical
+Files DUMP_DIR/sub/g00 and RESTORE_DIR/DUMP_SUBDIR/sub/g00 are identical
+Files DUMP_DIR/sub/h and RESTORE_DIR/DUMP_SUBDIR/sub/h are identical
+Files DUMP_DIR/sub/h00 and RESTORE_DIR/DUMP_SUBDIR/sub/h00 are identical
+Files DUMP_DIR/sub/h000 and RESTORE_DIR/DUMP_SUBDIR/sub/h000 are identical
+Files DUMP_DIR/sub/i and RESTORE_DIR/DUMP_SUBDIR/sub/i are identical
+Files DUMP_DIR/sub/i00 and RESTORE_DIR/DUMP_SUBDIR/sub/i00 are identical
+Files DUMP_DIR/sub/j and RESTORE_DIR/DUMP_SUBDIR/sub/j are identical
+Files DUMP_DIR/sub/j00 and RESTORE_DIR/DUMP_SUBDIR/sub/j00 are identical
+Files DUMP_DIR/sub/k and RESTORE_DIR/DUMP_SUBDIR/sub/k are identical
+Files DUMP_DIR/sub/k00 and RESTORE_DIR/DUMP_SUBDIR/sub/k00 are identical
+Files DUMP_DIR/sub/k000 and RESTORE_DIR/DUMP_SUBDIR/sub/k000 are identical
+Files DUMP_DIR/sub/l and RESTORE_DIR/DUMP_SUBDIR/sub/l are identical
+Files DUMP_DIR/sub/l00 and RESTORE_DIR/DUMP_SUBDIR/sub/l00 are identical
+Files DUMP_DIR/sub/m and RESTORE_DIR/DUMP_SUBDIR/sub/m are identical
+Files DUMP_DIR/sub/m00 and RESTORE_DIR/DUMP_SUBDIR/sub/m00 are identical
+Files DUMP_DIR/sub/n and RESTORE_DIR/DUMP_SUBDIR/sub/n are identical
+Files DUMP_DIR/sub/n00 and RESTORE_DIR/DUMP_SUBDIR/sub/n00 are identical
+Files DUMP_DIR/sub/small and RESTORE_DIR/DUMP_SUBDIR/sub/small are identical
+Only in SCRATCH_MNT: RESTORE_SUBDIR
diff --git a/027 b/027
new file mode 100755 (executable)
index 0000000..59b98b0
--- /dev/null
+++ b/027
@@ -0,0 +1,61 @@
+#! /bin/sh
+# XFS QA Test No. 027
+# $Id: 1.1 $
+#
+# Test out "xfsdump | xfsrestore"
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_create_dumpdir_fill
+_do_dump_restore
+_diff_compare_sub
+
+# success, all done
+exit
diff --git a/027.out b/027.out
new file mode 100644 (file)
index 0000000..3e3f27d
--- /dev/null
+++ b/027.out
@@ -0,0 +1,82 @@
+QA output created by 027
+Creating directory system to dump using src/fill.
+Setup ....................................
+xfsdump|xfsrestore ...
+xfsdump  -s DUMP_SUBDIR - SCRATCH_MNT | xfsrestore  - RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: searching media for dump
+xfsrestore: examining media file 0
+xfsrestore: dump description: 
+xfsrestore: hostname: HOSTNAME
+xfsrestore: mount point: SCRATCH_MNT
+xfsrestore: volume: SCRATCH_DEV
+xfsrestore: session time: TIME
+xfsrestore: level: 0
+xfsrestore: session label: ""
+xfsrestore: media label: ""
+xfsrestore: file system id: ID
+xfsrestore: session id: ID
+xfsrestore: media id: ID
+xfsrestore: searching media for directory dump
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: ""
+xfsdump: ino map phase 1: parsing subtree selections
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: pruning unneeded subtrees
+xfsdump: ino map phase 4: estimating dump size
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/big and RESTORE_DIR/DUMP_SUBDIR/big are identical
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Files DUMP_DIR/sub/a00 and RESTORE_DIR/DUMP_SUBDIR/sub/a00 are identical
+Files DUMP_DIR/sub/a000 and RESTORE_DIR/DUMP_SUBDIR/sub/a000 are identical
+Files DUMP_DIR/sub/b and RESTORE_DIR/DUMP_SUBDIR/sub/b are identical
+Files DUMP_DIR/sub/b00 and RESTORE_DIR/DUMP_SUBDIR/sub/b00 are identical
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Files DUMP_DIR/sub/c00 and RESTORE_DIR/DUMP_SUBDIR/sub/c00 are identical
+Files DUMP_DIR/sub/d and RESTORE_DIR/DUMP_SUBDIR/sub/d are identical
+Files DUMP_DIR/sub/d00 and RESTORE_DIR/DUMP_SUBDIR/sub/d00 are identical
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Files DUMP_DIR/sub/e00 and RESTORE_DIR/DUMP_SUBDIR/sub/e00 are identical
+Files DUMP_DIR/sub/e000 and RESTORE_DIR/DUMP_SUBDIR/sub/e000 are identical
+Files DUMP_DIR/sub/f and RESTORE_DIR/DUMP_SUBDIR/sub/f are identical
+Files DUMP_DIR/sub/f00 and RESTORE_DIR/DUMP_SUBDIR/sub/f00 are identical
+Files DUMP_DIR/sub/g and RESTORE_DIR/DUMP_SUBDIR/sub/g are identical
+Files DUMP_DIR/sub/g00 and RESTORE_DIR/DUMP_SUBDIR/sub/g00 are identical
+Files DUMP_DIR/sub/h and RESTORE_DIR/DUMP_SUBDIR/sub/h are identical
+Files DUMP_DIR/sub/h00 and RESTORE_DIR/DUMP_SUBDIR/sub/h00 are identical
+Files DUMP_DIR/sub/h000 and RESTORE_DIR/DUMP_SUBDIR/sub/h000 are identical
+Files DUMP_DIR/sub/i and RESTORE_DIR/DUMP_SUBDIR/sub/i are identical
+Files DUMP_DIR/sub/i00 and RESTORE_DIR/DUMP_SUBDIR/sub/i00 are identical
+Files DUMP_DIR/sub/j and RESTORE_DIR/DUMP_SUBDIR/sub/j are identical
+Files DUMP_DIR/sub/j00 and RESTORE_DIR/DUMP_SUBDIR/sub/j00 are identical
+Files DUMP_DIR/sub/k and RESTORE_DIR/DUMP_SUBDIR/sub/k are identical
+Files DUMP_DIR/sub/k00 and RESTORE_DIR/DUMP_SUBDIR/sub/k00 are identical
+Files DUMP_DIR/sub/k000 and RESTORE_DIR/DUMP_SUBDIR/sub/k000 are identical
+Files DUMP_DIR/sub/l and RESTORE_DIR/DUMP_SUBDIR/sub/l are identical
+Files DUMP_DIR/sub/l00 and RESTORE_DIR/DUMP_SUBDIR/sub/l00 are identical
+Files DUMP_DIR/sub/m and RESTORE_DIR/DUMP_SUBDIR/sub/m are identical
+Files DUMP_DIR/sub/m00 and RESTORE_DIR/DUMP_SUBDIR/sub/m00 are identical
+Files DUMP_DIR/sub/n and RESTORE_DIR/DUMP_SUBDIR/sub/n are identical
+Files DUMP_DIR/sub/n00 and RESTORE_DIR/DUMP_SUBDIR/sub/n00 are identical
+Files DUMP_DIR/sub/small and RESTORE_DIR/DUMP_SUBDIR/sub/small are identical
diff --git a/028 b/028
new file mode 100755 (executable)
index 0000000..e8bf4d2
--- /dev/null
+++ b/028
@@ -0,0 +1,90 @@
+#! /bin/sh
+# XFS QA Test No. 028
+# $Id: 1.1 $
+#
+# To test out xfsinvutil
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=0       # success is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+# wipe test dir clean first
+# so dump can be real quick
+_wipe_fs
+
+#
+# Create 5 dumps
+# and on the 3rd dump note the date
+# which we'll use to prune against using xfsinvutil
+#
+i=0
+while [ $i -lt 5 ]; do
+    _do_dump_file -L "session.$i"
+    if [ $i -eq 2 ]; then
+       sleep 1
+       middate=`date '+%m/%d/%Y %T'`
+    fi
+    rm $dump_file
+    sleep 2
+    i=`expr $i + 1`
+done
+
+echo "middate = $middate" >>$seq.full
+
+#
+# Now do the xfsinvutil and
+# look and the inventory before and after
+# to see if it did the job
+#
+_dump_inventory
+_do_invutil -n
+_dump_inventory
+
+
+# success, all done
+exit
diff --git a/028.out b/028.out
new file mode 100644 (file)
index 0000000..f3e8c12
--- /dev/null
+++ b/028.out
@@ -0,0 +1,323 @@
+QA output created by 028
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.0 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.0"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.1 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.1"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.2 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.2"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.3 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.3"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.4 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.4"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+file system 0:
+       fs id: ID
+       session 0:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.0"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 1:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.1"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 2:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.2"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 3:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.3"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 4:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.4"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+Processing file /var/xfsdump/inventory/UUIDstab
+   Found entry for HOSTNAME:SCRATCH_MNT
+      processing index file 
+       /var/xfsdump/inventory/UUID.InvIndex
+         Checking access for
+          /var/xfsdump/inventory/UUID.StObj
+          Mount point match
+            Session 0: HOSTNAME:SCRATCH_MNT
+-------------------------------------------------
+Pruning this matching entry:
+UUID           :       ID
+MOUNT POINT    :       HOSTNAME:SCRATCH_MNT
+DEV PATH       :       HOSTNAME:SCRATCH_DEV
+LABEL          :       session.0
+TIME OF DUMP   :       TIME
+-------------------------------------------------
+
+            Session 1: HOSTNAME:SCRATCH_MNT
+-------------------------------------------------
+Pruning this matching entry:
+UUID           :       ID
+MOUNT POINT    :       HOSTNAME:SCRATCH_MNT
+DEV PATH       :       HOSTNAME:SCRATCH_DEV
+LABEL          :       session.1
+TIME OF DUMP   :       TIME
+-------------------------------------------------
+
+            Session 2: HOSTNAME:SCRATCH_MNT
+-------------------------------------------------
+Pruning this matching entry:
+UUID           :       ID
+MOUNT POINT    :       HOSTNAME:SCRATCH_MNT
+DEV PATH       :       HOSTNAME:SCRATCH_DEV
+LABEL          :       session.2
+TIME OF DUMP   :       TIME
+-------------------------------------------------
+
+            Session 3: HOSTNAME:SCRATCH_MNT
+            Session 4: HOSTNAME:SCRATCH_MNT
+file system 0:
+       fs id: ID
+       session 0:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.3"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 1:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.4"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
diff --git a/029 b/029
new file mode 100755 (executable)
index 0000000..c6491ff
--- /dev/null
+++ b/029
@@ -0,0 +1,85 @@
+#! /bin/sh
+# XFS QA Test No. 029
+# $Id: 1.1 $
+#
+# exercise mkfs log (internal/external) zeroing
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=nathans@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+mkfs_args=""
+logp_args=""
+if [ ! -z "$SCRATCH_LOGDEV" ]  # test external log if possible
+then
+       mkfs_args="-l logdev=$SCRATCH_LOGDEV,size=1200b"
+       logp_args="-l $SCRATCH_LOGDEV"
+fi
+
+_filter_logprint()
+{
+       perl -ne '
+           s/data device: ([\w|\/]+)/data device: DDEV/;
+           s/log device: ([\w|\/]+) daddr: (\d+) length: (\d+)/log device: LDEV daddr: XXX length: XXX/;
+           s/log file: "([\w|\/]+)" daddr: (\d+) length: (\d+)/log device: LDEV daddr: XXX length: XXX/;
+           s/skipped (\w+) zeroed blocks/skipped XXX zeroed blocks/;
+            s/^uuid: *[0-9a-f-][0-9a-f-]* *format: *.*$/uuid: <UUID> format: <FORMAT>/;
+           print;
+       '
+}
+
+# real QA test starts here
+# 
+_require_scratch
+
+echo
+mkfs -t xfs -f $mkfs_args $SCRATCH_DEV | _filter_mkfs 2>/dev/null
+
+echo
+xfs_logprint $logp_args $SCRATCH_DEV | _filter_logprint
+
+status=0
+exit
diff --git a/029.out b/029.out
new file mode 100644 (file)
index 0000000..591798e
--- /dev/null
+++ b/029.out
@@ -0,0 +1,26 @@
+QA output created by 029
+
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+
+xfs_logprint:
+    data device: DDEV
+    log device: LDEV daddr: XXX length: XXX
+
+cycle: 1       version: 1              lsn: 1,0        tail_lsn: 1,0
+length of Log Record: 20       prev offset: -1         num ops: 1
+uuid: <UUID> format: <FORMAT>
+----------------------------------------------------------------------------
+Oper (0): tid: b0c0d0d0  len: 8  clientid: LOG  flags: UNMOUNT 
+Unmount filesystem
+
+============================================================================
+xfs_logprint: skipped XXX zeroed blocks
+xfs_logprint: physical end of log
+============================================================================
+xfs_logprint: logical end of log
+============================================================================
diff --git a/030 b/030
new file mode 100755 (executable)
index 0000000..f5166a2
--- /dev/null
+++ b/030
@@ -0,0 +1,99 @@
+#! /bin/sh
+# XFS QA Test No. 030
+# $Id: 1.3 $
+#
+# exercise xfs_repair repairing broken filesystems
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=nathans@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.repair
+
+# nuke the superblock, AGI, AGF, AGFL; then try repair the damage
+# 
+_check_ag()
+{
+       for structure in 'sb 0' 'agf 0' 'agi 0' 'agfl 0'
+       do
+               echo "Corrupting $structure - setting bits to $1"
+               _check_repair $1 "$structure"
+       done
+}
+
+# real QA test starts here
+_require_scratch
+
+# first we need to ensure there are no bogus secondary
+# superblocks between the primary and first secondary
+# superblock (hanging around from earlier tests)...
+# 
+size="-d size=100m"
+mkfs -t xfs -f $size $SCRATCH_DEV >/dev/null 2>&1
+if [ $? -ne 0 ]                # probably don't have a big enough scratch
+then
+       size=""
+       src/devzero -v -1 $SCRATCH_DEV >/dev/null
+else
+       clear=""
+       eval `xfs_db -r -c "sb 1" -c stack $SCRATCH_DEV | perl -ne '
+               if (/byte offset (\d+), length (\d+)/) {
+                       print "clear=", $1 / 512, "\n"; exit
+               }'`
+       [ -z "$clear" ] && echo "Cannot calculate length to clear"
+       src/devzero -v -1 -n "$clear" $SCRATCH_DEV >/dev/null
+fi
+
+# now kick off the real repair test...
+# 
+mkfs -t xfs -f $size $SCRATCH_DEV | _filter_mkfs 2>$tmp.mkfs
+source $tmp.mkfs
+_check_ag 0
+_check_ag -1
+
+
+# success, all done
+status=0
+exit
diff --git a/030.out b/030.out
new file mode 100644 (file)
index 0000000..54275d1
--- /dev/null
+++ b/030.out
@@ -0,0 +1,295 @@
+QA output created by 030
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+Corrupting sb 0 - setting bits to 0
+Wrote 0.50Kb (value 0x0)
+Phase 1 - find and verify superblock...
+bad primary superblock - bad magic number !!!
+
+attempting to find secondary superblock...
+found candidate secondary superblock...
+verified secondary superblock...
+writing modified primary superblock
+sb root inode value INO inconsistent with calculated value INO
+resetting superblock root inode pointer to INO
+sb realtime bitmap inode INO inconsistent with calculated value INO
+resetting superblock realtime bitmap ino pointer to INO
+sb realtime summary inode INO inconsistent with calculated value INO
+resetting superblock realtime summary ino pointer to INO
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+Note - stripe unit (0) and width (0) fields have been reset.
+Please set with mount -o sunit=<value>,swidth=<value>
+done
+Corrupting agf 0 - setting bits to 0
+Wrote 0.50Kb (value 0x0)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+bad magic # 0x0 for agf 0
+bad version # 0 for agf 0
+bad length 0 for agf 0, should be LENGTH
+reset bad agf for ag 0
+bad agbno AGBNO for btbno root, agno 0
+bad agbno AGBNO for btbcnt root, agno 0
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+done
+Corrupting agi 0 - setting bits to 0
+Wrote 0.50Kb (value 0x0)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+bad magic # 0x0 for agi 0
+bad version # 0 for agi 0
+bad length # 0 for agi 0, should be LENGTH
+reset bad agi for ag 0
+bad agbno AGBNO for inobt root, agno 0
+root inode chunk not found
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+error following ag 0 unlinked list
+        - process known inodes and perform inode discovery...
+imap claims in-use inode 131 is free, correcting imap
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+done
+Corrupting agfl 0 - setting bits to 0
+Wrote 0.50Kb (value 0x0)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+done
+Corrupting sb 0 - setting bits to -1
+Wrote 0.50Kb (value 0xffffffff)
+Phase 1 - find and verify superblock...
+bad primary superblock - bad magic number !!!
+
+attempting to find secondary superblock...
+found candidate secondary superblock...
+verified secondary superblock...
+writing modified primary superblock
+sb root inode value INO inconsistent with calculated value INO
+resetting superblock root inode pointer to INO
+sb realtime bitmap inode INO inconsistent with calculated value INO
+resetting superblock realtime bitmap ino pointer to INO
+sb realtime summary inode INO inconsistent with calculated value INO
+resetting superblock realtime summary ino pointer to INO
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+Note - stripe unit (0) and width (0) fields have been reset.
+Please set with mount -o sunit=<value>,swidth=<value>
+done
+Corrupting agf 0 - setting bits to -1
+Wrote 0.50Kb (value 0xffffffff)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+bad magic # 0xffffffff for agf 0
+bad version # -1 for agf 0
+bad sequence # -1 for agf 0
+bad length -1 for agf 0, should be LENGTH
+flfirst -1 in agf 0 too large (max = MAX)
+fllast -1 in agf 0 too large (max = MAX)
+reset bad agf for ag 0
+freeblk count 1 != flcount -1 in ag 0
+bad agbno AGBNO for btbno root, agno 0
+bad agbno AGBNO for btbcnt root, agno 0
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+done
+Corrupting agi 0 - setting bits to -1
+Wrote 0.50Kb (value 0xffffffff)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+bad magic # 0xffffffff for agi 0
+bad version # -1 for agi 0
+bad sequence # -1 for agi 0
+bad length # -1 for agi 0, should be LENGTH
+reset bad agi for ag 0
+bad agbno AGBNO for inobt root, agno 0
+root inode chunk not found
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+imap claims in-use inode 131 is free, correcting imap
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+done
+Corrupting agfl 0 - setting bits to -1
+Wrote 0.50Kb (value 0xffffffff)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+done
diff --git a/031 b/031
new file mode 100755 (executable)
index 0000000..3a62956
--- /dev/null
+++ b/031
@@ -0,0 +1,133 @@
+#! /bin/sh
+# XFS QA Test No. 031
+# $Id: 1.1 $
+#
+# exercise xfs_repair - ensure repeated use doesn't corrupt
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=nathans@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+rm -f $seq.full
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_check_repair()
+{
+       xfs_repair $SCRATCH_DEV >$tmp.0 2>&1
+       for i in 1 2 3 4
+       do
+               echo "Repairing, iteration $i" | tee -a $seq.full
+               xfs_repair $SCRATCH_DEV 2>&1 | tee -a $seq.full >$tmp.$i
+               diff $tmp.0 $tmp.$i
+               # echo all interesting stuff...
+               perl -ne '
+                       s/(rebuilding directory inode) (\d+)/\1 INO/g;
+                       /^\S+/ && print;
+               ' $tmp.$i
+       done
+       echo
+}
+
+# prototype file to create various directory forms
+_create_proto()
+{
+       total=$1
+       count=0
+
+       cat >$tmp.proto <<EOF
+DUMMY1
+0 0
+: root directory
+d--777 3 1
+lost+found d--755 3 1
+$
+EOF
+
+       while [ $count -lt $total ]
+       do
+               count=`expr $count + 1`
+               cat >>$tmp.proto <<EOF
+${count}_of_${total}_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ---755 3 1 /bin/true
+EOF
+       done
+       echo '$' >>$tmp.proto
+}
+
+# real QA test starts here
+# 
+_require_scratch
+
+MKFSV1="-t xfs -f -p $tmp.proto -n version=1 $SCRATCH_DEV"
+MKFSV2="-t xfs -f -p $tmp.proto -n version=2 $SCRATCH_DEV"
+
+# sanity test - default + one root directory entry
+_create_proto 0
+echo "=== version 1, one entry"
+mkfs $MKFSV1 | _filter_mkfs >/dev/null 2>&1
+_check_repair
+echo "=== version 2, one entry (shortform)"
+mkfs $MKFSV2 | _filter_mkfs >/dev/null 2>&1
+_check_repair
+
+# block-form root directory & repeat
+_create_proto 20
+echo "=== version 1, twenty entries"
+mkfs $MKFSV1 | _filter_mkfs >/dev/null 2>&1
+_check_repair
+echo "=== version 2, twenty entries (block form)"
+mkfs $MKFSV2 | _filter_mkfs >/dev/null 2>&1
+_check_repair
+
+# leaf-form root directory & repeat
+_create_proto 1000
+echo "=== version 1, thousand entries"
+mkfs $MKFSV1 | _filter_mkfs >/dev/null 2>&1
+_check_repair
+echo "=== version 2, thousand entries (leaf form)"
+mkfs $MKFSV2 | _filter_mkfs >/dev/null 2>&1
+_check_repair
+
+# success, all done
+status=0
+exit
diff --git a/031.out b/031.out
new file mode 100644 (file)
index 0000000..949df35
--- /dev/null
+++ b/031.out
@@ -0,0 +1,237 @@
+QA output created by 031
+=== version 1, one entry
+Repairing, iteration 1
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 2
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 3
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 4
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+
+=== version 2, one entry (shortform)
+Repairing, iteration 1
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 2
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 3
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 4
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+
+=== version 1, twenty entries
+Repairing, iteration 1
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 2
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 3
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 4
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+
+=== version 2, twenty entries (block form)
+Repairing, iteration 1
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+rebuilding directory inode INO
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 2
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+rebuilding directory inode INO
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 3
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+rebuilding directory inode INO
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 4
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+rebuilding directory inode INO
+Phase 7 - verify and correct link counts...
+done
+
+=== version 1, thousand entries
+Repairing, iteration 1
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 2
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 3
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 4
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+Phase 7 - verify and correct link counts...
+done
+
+=== version 2, thousand entries (leaf form)
+Repairing, iteration 1
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+rebuilding directory inode INO
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 2
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+rebuilding directory inode INO
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 3
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+rebuilding directory inode INO
+Phase 7 - verify and correct link counts...
+done
+Repairing, iteration 4
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+Phase 3 - for each AG...
+Phase 4 - check for duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+Phase 6 - check inode connectivity...
+rebuilding directory inode INO
+Phase 7 - verify and correct link counts...
+done
+
diff --git a/032 b/032
new file mode 100755 (executable)
index 0000000..f3f8bb4
--- /dev/null
+++ b/032
@@ -0,0 +1,89 @@
+#! /bin/sh
+# XFS QA Test No. 032
+# $Id: 1.1 $
+#
+# cross check mkfs detection of foreign filesystems
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=nathans@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+rm -f $seq.full
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+# 
+_require_scratch
+
+echo "Silence is golden."
+for fs in `echo /sbin/mkfs.* | sed -e 's/.sbin.mkfs.//g'`
+do
+       preop=""        # for special input needs
+       preargs=""      # for any special pre-device options
+       postargs=""     # for any special post-device options
+
+       # minix mkfs fails for large devices, restrict to 2000 blocks
+       [ $fs = "minix" ] && postargs=2000
+       # these folk prompt before writing
+       [ $fs = "jfs" ] && preop="echo Y |"
+       [ $fs = "reiserfs" ] && preop="echo y |"
+
+       # overwite the first few Kb - should blow away superblocks
+       src/devzero -n 20 $SCRATCH_DEV >/dev/null
+
+       # create a filesystem of this type
+       echo "=== Creating $fs filesystem..." >>$seq.full
+       echo "    ( mkfs -t $fs $SCRATCH_DEV )" >>$seq.full
+       eval $preop mkfs -t $fs $preargs $SCRATCH_DEV $postargs >>$seq.full 2>&1
+
+       # next, ensure we don't overwrite it
+       echo "=== Attempting XFS overwrite of $fs..." >>$seq.full
+       mkfs -t xfs $SCRATCH_DEV >>$seq.full 2>&1
+
+       [ $? -eq 0 ] && echo "Failed - overwrote fs type ${fs}!"
+done
+
+# success, all done
+status=0
+exit
diff --git a/032.out b/032.out
new file mode 100644 (file)
index 0000000..9265732
--- /dev/null
+++ b/032.out
@@ -0,0 +1,2 @@
+QA output created by 032
+Silence is golden.
diff --git a/033 b/033
new file mode 100755 (executable)
index 0000000..78a7965
--- /dev/null
+++ b/033
@@ -0,0 +1,81 @@
+#! /bin/sh
+# XFS QA Test No. 033
+# $Id: 1.1 $
+#
+# exercise xfs_repair repairing broken filesystems (root inodes)
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=nathans@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.repair
+
+# nuke the root, rt bitmap, and rt summary inodes
+# 
+_check_root_inos()
+{
+       echo "Corrupting root inode - setting bits to $1"
+       _check_repair $1 "inode $rootino"
+       echo "Corrupting rt bitmap inode - setting bits to $1"
+       _check_repair $1 "inode $rbmino"
+       echo "Corrupting rt summary inode - setting bits to $1"
+       _check_repair $1 "inode $rsumino"
+}
+
+# real QA test starts here
+_require_scratch
+
+# devzero blows away 512byte blocks, so make 512byte inodes
+mkfs -t xfs -f -i size=512 $SCRATCH_DEV | _filter_mkfs 2>/dev/null
+`xfs_db -r -c sb -c p $SCRATCH_DEV | grep 'ino = ' | \
+       sed -e 's/ //g' -e 's/^/export /'`
+# rootino, rbmino, and rsumino are now set (lets blow em away!)
+_check_root_inos 0
+_check_root_inos -1
+
+
+# success, all done
+status=0
+exit
diff --git a/033.out b/033.out
new file mode 100644 (file)
index 0000000..00244ee
--- /dev/null
+++ b/033.out
@@ -0,0 +1,229 @@
+QA output created by 033
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+Corrupting root inode - setting bits to 0
+Wrote 0.50Kb (value 0x0)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+bad magic number 0x0 on inode INO
+bad version number 0x0 on inode INO
+bad magic number 0x0 on inode INO, resetting magic number
+bad version number 0x0 on inode INO, resetting version number
+imap claims a free inode INO is in use, correcting imap and clearing inode
+cleared root inode INO
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+root inode lost
+        - clear lost+found (if it exists) ...
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+reinitializing root directory
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+resetting inode INO nlinks from 2 to 3
+done
+Corrupting rt bitmap inode - setting bits to 0
+Wrote 0.50Kb (value 0x0)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+bad magic number 0x0 on inode INO
+bad version number 0x0 on inode INO
+bad magic number 0x0 on inode INO, resetting magic number
+bad version number 0x0 on inode INO, resetting version number
+imap claims a free inode INO is in use, correcting imap and clearing inode
+cleared realtime bitmap inode INO
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+reinitializing realtime bitmap inode
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+done
+Corrupting rt summary inode - setting bits to 0
+Wrote 0.50Kb (value 0x0)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+bad magic number 0x0 on inode INO
+bad version number 0x0 on inode INO
+bad magic number 0x0 on inode INO, resetting magic number
+bad version number 0x0 on inode INO, resetting version number
+imap claims a free inode INO is in use, correcting imap and clearing inode
+cleared realtime summary inode INO
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+reinitializing realtime summary inode
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+Phase 7 - verify and correct link counts...
+done
+Corrupting root inode - setting bits to -1
+Wrote 0.50Kb (value 0xffffffff)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+bad magic number 0xffff on inode INO
+bad version number 0xffffffff on inode INO
+bad (negative) size -1 on inode INO
+bad magic number 0xffff on inode INO, resetting magic number
+bad version number 0xffffffff on inode INO, resetting version number
+bad (negative) size -1 on inode INO
+cleared root inode INO
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+root inode lost
+        - clear lost+found (if it exists) ...
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+reinitializing root directory
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+disconnected dir inode INO, moving to lost+found
+Phase 7 - verify and correct link counts...
+resetting inode INO nlinks from 2 to 3
+done
+Corrupting rt bitmap inode - setting bits to -1
+Wrote 0.50Kb (value 0xffffffff)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+bad magic number 0xffff on inode INO
+bad version number 0xffffffff on inode INO
+bad (negative) size -1 on inode INO
+bad magic number 0xffff on inode INO, resetting magic number
+bad version number 0xffffffff on inode INO, resetting version number
+bad (negative) size -1 on inode INO
+cleared realtime bitmap inode INO
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+reinitializing realtime bitmap inode
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+disconnected dir inode INO, moving to lost+found
+Phase 7 - verify and correct link counts...
+done
+Corrupting rt summary inode - setting bits to -1
+Wrote 0.50Kb (value 0xffffffff)
+Phase 1 - find and verify superblock...
+Phase 2 - using internal log
+        - zero log...
+        - scan filesystem freespace and inode maps...
+        - found root inode chunk
+Phase 3 - for each AG...
+        - scan and clear agi unlinked lists...
+        - process known inodes and perform inode discovery...
+bad magic number 0xffff on inode INO
+bad version number 0xffffffff on inode INO
+bad (negative) size -1 on inode INO
+bad magic number 0xffff on inode INO, resetting magic number
+bad version number 0xffffffff on inode INO, resetting version number
+bad (negative) size -1 on inode INO
+cleared realtime summary inode INO
+        - process newly discovered inodes...
+Phase 4 - check for duplicate blocks...
+        - setting up duplicate extent list...
+        - clear lost+found (if it exists) ...
+        - clearing existing "lost+found" inode
+        - deleting existing "lost+found" entry
+        - check for inodes claiming duplicate blocks...
+Phase 5 - rebuild AG headers and trees...
+        - reset superblock...
+Phase 6 - check inode connectivity...
+reinitializing realtime summary inode
+        - resetting contents of realtime bitmap and summary inodes
+        - ensuring existence of lost+found directory
+        - traversing filesystem starting at / ... 
+        - traversal finished ... 
+        - traversing all unattached subtrees ... 
+        - traversals finished ... 
+        - moving disconnected inodes to lost+found ... 
+disconnected dir inode INO, moving to lost+found
+Phase 7 - verify and correct link counts...
+done
diff --git a/034 b/034
new file mode 100755 (executable)
index 0000000..100304a
--- /dev/null
+++ b/034
@@ -0,0 +1,104 @@
+#! /bin/sh
+# XFS QA Test No. 034
+# $Id: 1.1 $
+#
+# pv 801241 - check for reference leaks from the *handle ioctls
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=root@leesa.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+
+_cleanup()
+{
+    echo "*** unmount"
+    umount $SCRATCH_MNT 2>/dev/null
+}
+trap "_cleanup; rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+_require_scratch
+
+echo "*** init FS"
+
+rm -f $seq.full
+umount $SCRATCH_DEV >/dev/null 2>&1
+echo "*** MKFS ***"                         >>$seq.full
+echo ""                                     >>$seq.full
+mkfs -t xfs -f $SCRATCH_DEV                 >>$seq.full 2>&1 \
+    || _fail "mkfs failed"
+mount -t xfs $SCRATCH_DEV $SCRATCH_MNT      >>$seq.full 2>&1 \
+    || _fail "mount failed"
+
+echo "*** test"
+
+_check_fs $SCRATCH_DEV
+
+if ! touch $SCRATCH_MNT/fish
+then
+    echo "!!! failed to touch fish"
+    exit
+fi
+
+if ! src/ioctl $SCRATCH_MNT $SCRATCH_MNT/fish >/dev/null 2>&1
+then
+    echo "!!! failed to run ioctl test program"
+    exit
+fi
+
+if ! rm $SCRATCH_MNT/fish
+then
+    echo "!!! failed to remove fish"
+    exit
+fi
+
+# pv 801241 causes corruption here (inode left in agi_unlinked list)
+_check_fs $SCRATCH_DEV
+
+echo "*** done"
+# happy exit
+rm -f $seq.full
+status=0
+exit 0
diff --git a/034.out b/034.out
new file mode 100644 (file)
index 0000000..b307447
--- /dev/null
+++ b/034.out
@@ -0,0 +1,5 @@
+QA output created by 034
+*** init FS
+*** test
+*** done
+*** unmount
diff --git a/035 b/035
new file mode 100755 (executable)
index 0000000..909e2ff
--- /dev/null
+++ b/035
@@ -0,0 +1,68 @@
+#! /bin/sh
+# XFS QA Test No. 035
+# $Id: 1.1 $
+#
+# Test doing multiple dumps to tape and restoring the 2nd one
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sagan.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape
+_create_dumpdir_fill
+_erase_hard
+_do_dump -L $seq.1
+_rewind
+_create_dumpdir_fill2
+_do_dump -L $seq.2
+_do_restore -L $seq.2
+_diff_compare
+
+# success, all done
+status=0
+exit
diff --git a/035.out b/035.out
new file mode 100644 (file)
index 0000000..b2fa3d5
--- /dev/null
+++ b/035.out
@@ -0,0 +1,98 @@
+QA output created by 035
+Put scsi tape driver into variable block size mode
+Creating directory system to dump using src/fill.
+Setup ....................................
+Erasing tape
+Dumping to tape...
+xfsdump  -l0 -f TAPE_DEV -M stress_tape_media -L 035.1 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "035.1"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: writing stream terminator
+xfsdump: beginning media stream terminator
+xfsdump: media file 2 (media 0, file 2)
+xfsdump: ending media stream terminator
+xfsdump: media stream terminator size 1048576 bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Creating directory system to dump using src/fill.
+Setup ....
+Dumping to tape...
+xfsdump  -l0 -f TAPE_DEV -M stress_tape_media -L 035.2 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "035.2"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: preparing drive
+xfsdump: positioned at media file 0: dump 0, stream 0
+xfsdump: positioned at media file 1: dump 0, stream 0
+xfsdump: positioned at media file 2: dump 0, stream 0
+xfsdump: stream terminator found
+xfsdump: creating dump session media file 0 (media 0, file 2)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 3)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: writing stream terminator
+xfsdump: beginning media stream terminator
+xfsdump: media file 2 (media 0, file 4)
+xfsdump: ending media stream terminator
+xfsdump: media stream terminator size 1048576 bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -f TAPE_DEV  -L 035.2 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: examining media file 1
+xfsrestore: examining media file 2
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/biggg and RESTORE_DIR/DUMP_SUBDIR/biggg are identical
+Files DUMP_DIR/smalll and RESTORE_DIR/DUMP_SUBDIR/smalll are identical
+Files DUMP_DIR/sub/biggg and RESTORE_DIR/DUMP_SUBDIR/sub/biggg are identical
+Files DUMP_DIR/sub/smalll and RESTORE_DIR/DUMP_SUBDIR/sub/smalll are identical
+Only in SCRATCH_MNT: RESTORE_SUBDIR
diff --git a/036 b/036
new file mode 100755 (executable)
index 0000000..132a5eb
--- /dev/null
+++ b/036
@@ -0,0 +1,65 @@
+#! /bin/sh
+# XFS QA Test No. 036
+# $Id: 1.1 $
+#
+# Test xfsdump/restore minrmt to a remote IRIX tape 
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape $RMT_IRIXTAPE_DEV
+_create_dumpdir_fill
+_erase_soft
+_do_dump_min -o -F
+_do_restore_min
+_diff_compare
+
+# success, all done
+status=0
+exit
diff --git a/036.out b/036.out
new file mode 100644 (file)
index 0000000..dd8a67a
--- /dev/null
+++ b/036.out
@@ -0,0 +1,84 @@
+QA output created by 036
+Creating directory system to dump using src/fill.
+Setup ....................................
+Erasing tape
+Dumping to tape...
+xfsdump  -o -F -m -b 1048576 -l0 -f TAPE_DEV -M stress_tape_media -L stress_036 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_036"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: WARNING: media may contain data. Overwrite option specified
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -m -b 1048576 -f TAPE_DEV  -L stress_036 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/big and RESTORE_DIR/DUMP_SUBDIR/big are identical
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Files DUMP_DIR/sub/a00 and RESTORE_DIR/DUMP_SUBDIR/sub/a00 are identical
+Files DUMP_DIR/sub/a000 and RESTORE_DIR/DUMP_SUBDIR/sub/a000 are identical
+Files DUMP_DIR/sub/b and RESTORE_DIR/DUMP_SUBDIR/sub/b are identical
+Files DUMP_DIR/sub/b00 and RESTORE_DIR/DUMP_SUBDIR/sub/b00 are identical
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Files DUMP_DIR/sub/c00 and RESTORE_DIR/DUMP_SUBDIR/sub/c00 are identical
+Files DUMP_DIR/sub/d and RESTORE_DIR/DUMP_SUBDIR/sub/d are identical
+Files DUMP_DIR/sub/d00 and RESTORE_DIR/DUMP_SUBDIR/sub/d00 are identical
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Files DUMP_DIR/sub/e00 and RESTORE_DIR/DUMP_SUBDIR/sub/e00 are identical
+Files DUMP_DIR/sub/e000 and RESTORE_DIR/DUMP_SUBDIR/sub/e000 are identical
+Files DUMP_DIR/sub/f and RESTORE_DIR/DUMP_SUBDIR/sub/f are identical
+Files DUMP_DIR/sub/f00 and RESTORE_DIR/DUMP_SUBDIR/sub/f00 are identical
+Files DUMP_DIR/sub/g and RESTORE_DIR/DUMP_SUBDIR/sub/g are identical
+Files DUMP_DIR/sub/g00 and RESTORE_DIR/DUMP_SUBDIR/sub/g00 are identical
+Files DUMP_DIR/sub/h and RESTORE_DIR/DUMP_SUBDIR/sub/h are identical
+Files DUMP_DIR/sub/h00 and RESTORE_DIR/DUMP_SUBDIR/sub/h00 are identical
+Files DUMP_DIR/sub/h000 and RESTORE_DIR/DUMP_SUBDIR/sub/h000 are identical
+Files DUMP_DIR/sub/i and RESTORE_DIR/DUMP_SUBDIR/sub/i are identical
+Files DUMP_DIR/sub/i00 and RESTORE_DIR/DUMP_SUBDIR/sub/i00 are identical
+Files DUMP_DIR/sub/j and RESTORE_DIR/DUMP_SUBDIR/sub/j are identical
+Files DUMP_DIR/sub/j00 and RESTORE_DIR/DUMP_SUBDIR/sub/j00 are identical
+Files DUMP_DIR/sub/k and RESTORE_DIR/DUMP_SUBDIR/sub/k are identical
+Files DUMP_DIR/sub/k00 and RESTORE_DIR/DUMP_SUBDIR/sub/k00 are identical
+Files DUMP_DIR/sub/k000 and RESTORE_DIR/DUMP_SUBDIR/sub/k000 are identical
+Files DUMP_DIR/sub/l and RESTORE_DIR/DUMP_SUBDIR/sub/l are identical
+Files DUMP_DIR/sub/l00 and RESTORE_DIR/DUMP_SUBDIR/sub/l00 are identical
+Files DUMP_DIR/sub/m and RESTORE_DIR/DUMP_SUBDIR/sub/m are identical
+Files DUMP_DIR/sub/m00 and RESTORE_DIR/DUMP_SUBDIR/sub/m00 are identical
+Files DUMP_DIR/sub/n and RESTORE_DIR/DUMP_SUBDIR/sub/n are identical
+Files DUMP_DIR/sub/n00 and RESTORE_DIR/DUMP_SUBDIR/sub/n00 are identical
+Files DUMP_DIR/sub/small and RESTORE_DIR/DUMP_SUBDIR/sub/small are identical
+Only in SCRATCH_MNT: RESTORE_SUBDIR
diff --git a/037 b/037
new file mode 100755 (executable)
index 0000000..29e680e
--- /dev/null
+++ b/037
@@ -0,0 +1,65 @@
+#! /bin/sh
+# XFS QA Test No. 037
+# $Id: 1.1 $
+#
+# Test xfsdump/restore minrmt to a remote linux tape 
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape $RMT_TAPE_DEV
+_create_dumpdir_fill
+_erase_soft
+_do_dump_min -o -F
+_do_restore_min
+_diff_compare
+
+# success, all done
+status=0
+exit
diff --git a/037.out b/037.out
new file mode 100644 (file)
index 0000000..de82872
--- /dev/null
+++ b/037.out
@@ -0,0 +1,84 @@
+QA output created by 037
+Creating directory system to dump using src/fill.
+Setup ....................................
+Erasing tape
+Dumping to tape...
+xfsdump  -o -F -m -b 1048576 -l0 -f TAPE_DEV -M stress_tape_media -L stress_037 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_037"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: WARNING: media may contain data. Overwrite option specified
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -m -b 1048576 -f TAPE_DEV  -L stress_037 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/big and RESTORE_DIR/DUMP_SUBDIR/big are identical
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Files DUMP_DIR/sub/a00 and RESTORE_DIR/DUMP_SUBDIR/sub/a00 are identical
+Files DUMP_DIR/sub/a000 and RESTORE_DIR/DUMP_SUBDIR/sub/a000 are identical
+Files DUMP_DIR/sub/b and RESTORE_DIR/DUMP_SUBDIR/sub/b are identical
+Files DUMP_DIR/sub/b00 and RESTORE_DIR/DUMP_SUBDIR/sub/b00 are identical
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Files DUMP_DIR/sub/c00 and RESTORE_DIR/DUMP_SUBDIR/sub/c00 are identical
+Files DUMP_DIR/sub/d and RESTORE_DIR/DUMP_SUBDIR/sub/d are identical
+Files DUMP_DIR/sub/d00 and RESTORE_DIR/DUMP_SUBDIR/sub/d00 are identical
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Files DUMP_DIR/sub/e00 and RESTORE_DIR/DUMP_SUBDIR/sub/e00 are identical
+Files DUMP_DIR/sub/e000 and RESTORE_DIR/DUMP_SUBDIR/sub/e000 are identical
+Files DUMP_DIR/sub/f and RESTORE_DIR/DUMP_SUBDIR/sub/f are identical
+Files DUMP_DIR/sub/f00 and RESTORE_DIR/DUMP_SUBDIR/sub/f00 are identical
+Files DUMP_DIR/sub/g and RESTORE_DIR/DUMP_SUBDIR/sub/g are identical
+Files DUMP_DIR/sub/g00 and RESTORE_DIR/DUMP_SUBDIR/sub/g00 are identical
+Files DUMP_DIR/sub/h and RESTORE_DIR/DUMP_SUBDIR/sub/h are identical
+Files DUMP_DIR/sub/h00 and RESTORE_DIR/DUMP_SUBDIR/sub/h00 are identical
+Files DUMP_DIR/sub/h000 and RESTORE_DIR/DUMP_SUBDIR/sub/h000 are identical
+Files DUMP_DIR/sub/i and RESTORE_DIR/DUMP_SUBDIR/sub/i are identical
+Files DUMP_DIR/sub/i00 and RESTORE_DIR/DUMP_SUBDIR/sub/i00 are identical
+Files DUMP_DIR/sub/j and RESTORE_DIR/DUMP_SUBDIR/sub/j are identical
+Files DUMP_DIR/sub/j00 and RESTORE_DIR/DUMP_SUBDIR/sub/j00 are identical
+Files DUMP_DIR/sub/k and RESTORE_DIR/DUMP_SUBDIR/sub/k are identical
+Files DUMP_DIR/sub/k00 and RESTORE_DIR/DUMP_SUBDIR/sub/k00 are identical
+Files DUMP_DIR/sub/k000 and RESTORE_DIR/DUMP_SUBDIR/sub/k000 are identical
+Files DUMP_DIR/sub/l and RESTORE_DIR/DUMP_SUBDIR/sub/l are identical
+Files DUMP_DIR/sub/l00 and RESTORE_DIR/DUMP_SUBDIR/sub/l00 are identical
+Files DUMP_DIR/sub/m and RESTORE_DIR/DUMP_SUBDIR/sub/m are identical
+Files DUMP_DIR/sub/m00 and RESTORE_DIR/DUMP_SUBDIR/sub/m00 are identical
+Files DUMP_DIR/sub/n and RESTORE_DIR/DUMP_SUBDIR/sub/n are identical
+Files DUMP_DIR/sub/n00 and RESTORE_DIR/DUMP_SUBDIR/sub/n00 are identical
+Files DUMP_DIR/sub/small and RESTORE_DIR/DUMP_SUBDIR/sub/small are identical
+Only in SCRATCH_MNT: RESTORE_SUBDIR
diff --git a/038 b/038
new file mode 100755 (executable)
index 0000000..65defac
--- /dev/null
+++ b/038
@@ -0,0 +1,65 @@
+#! /bin/sh
+# XFS QA Test No. 038
+# $Id: 1.1 $
+#
+# Test xfsdump/restore to a remote linux tape 
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape $RMT_TAPE_DEV
+_create_dumpdir_fill
+_erase_hard
+_do_dump
+_do_restore
+_diff_compare
+
+# success, all done
+status=0
+exit
diff --git a/038.out b/038.out
new file mode 100644 (file)
index 0000000..c16806e
--- /dev/null
+++ b/038.out
@@ -0,0 +1,88 @@
+QA output created by 038
+Creating directory system to dump using src/fill.
+Setup ....................................
+Erasing tape
+Dumping to tape...
+xfsdump  -l0 -f TAPE_DEV -M stress_tape_media -L stress_038 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_038"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: writing stream terminator
+xfsdump: beginning media stream terminator
+xfsdump: media file 2 (media 0, file 2)
+xfsdump: ending media stream terminator
+xfsdump: media stream terminator size 245760 bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -f TAPE_DEV  -L stress_038 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/big and RESTORE_DIR/DUMP_SUBDIR/big are identical
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Files DUMP_DIR/sub/a00 and RESTORE_DIR/DUMP_SUBDIR/sub/a00 are identical
+Files DUMP_DIR/sub/a000 and RESTORE_DIR/DUMP_SUBDIR/sub/a000 are identical
+Files DUMP_DIR/sub/b and RESTORE_DIR/DUMP_SUBDIR/sub/b are identical
+Files DUMP_DIR/sub/b00 and RESTORE_DIR/DUMP_SUBDIR/sub/b00 are identical
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Files DUMP_DIR/sub/c00 and RESTORE_DIR/DUMP_SUBDIR/sub/c00 are identical
+Files DUMP_DIR/sub/d and RESTORE_DIR/DUMP_SUBDIR/sub/d are identical
+Files DUMP_DIR/sub/d00 and RESTORE_DIR/DUMP_SUBDIR/sub/d00 are identical
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Files DUMP_DIR/sub/e00 and RESTORE_DIR/DUMP_SUBDIR/sub/e00 are identical
+Files DUMP_DIR/sub/e000 and RESTORE_DIR/DUMP_SUBDIR/sub/e000 are identical
+Files DUMP_DIR/sub/f and RESTORE_DIR/DUMP_SUBDIR/sub/f are identical
+Files DUMP_DIR/sub/f00 and RESTORE_DIR/DUMP_SUBDIR/sub/f00 are identical
+Files DUMP_DIR/sub/g and RESTORE_DIR/DUMP_SUBDIR/sub/g are identical
+Files DUMP_DIR/sub/g00 and RESTORE_DIR/DUMP_SUBDIR/sub/g00 are identical
+Files DUMP_DIR/sub/h and RESTORE_DIR/DUMP_SUBDIR/sub/h are identical
+Files DUMP_DIR/sub/h00 and RESTORE_DIR/DUMP_SUBDIR/sub/h00 are identical
+Files DUMP_DIR/sub/h000 and RESTORE_DIR/DUMP_SUBDIR/sub/h000 are identical
+Files DUMP_DIR/sub/i and RESTORE_DIR/DUMP_SUBDIR/sub/i are identical
+Files DUMP_DIR/sub/i00 and RESTORE_DIR/DUMP_SUBDIR/sub/i00 are identical
+Files DUMP_DIR/sub/j and RESTORE_DIR/DUMP_SUBDIR/sub/j are identical
+Files DUMP_DIR/sub/j00 and RESTORE_DIR/DUMP_SUBDIR/sub/j00 are identical
+Files DUMP_DIR/sub/k and RESTORE_DIR/DUMP_SUBDIR/sub/k are identical
+Files DUMP_DIR/sub/k00 and RESTORE_DIR/DUMP_SUBDIR/sub/k00 are identical
+Files DUMP_DIR/sub/k000 and RESTORE_DIR/DUMP_SUBDIR/sub/k000 are identical
+Files DUMP_DIR/sub/l and RESTORE_DIR/DUMP_SUBDIR/sub/l are identical
+Files DUMP_DIR/sub/l00 and RESTORE_DIR/DUMP_SUBDIR/sub/l00 are identical
+Files DUMP_DIR/sub/m and RESTORE_DIR/DUMP_SUBDIR/sub/m are identical
+Files DUMP_DIR/sub/m00 and RESTORE_DIR/DUMP_SUBDIR/sub/m00 are identical
+Files DUMP_DIR/sub/n and RESTORE_DIR/DUMP_SUBDIR/sub/n are identical
+Files DUMP_DIR/sub/n00 and RESTORE_DIR/DUMP_SUBDIR/sub/n00 are identical
+Files DUMP_DIR/sub/small and RESTORE_DIR/DUMP_SUBDIR/sub/small are identical
+Only in SCRATCH_MNT: RESTORE_SUBDIR
diff --git a/039 b/039
new file mode 100755 (executable)
index 0000000..efbb393
--- /dev/null
+++ b/039
@@ -0,0 +1,65 @@
+#! /bin/sh
+# XFS QA Test No. 039
+# $Id: 1.1 $
+#
+# Test xfsdump/restore to a remote IRIX tape 
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape $RMT_IRIXTAPE_DEV
+_create_dumpdir_fill
+_erase_soft
+_do_dump -o -F
+_do_restore
+_diff_compare
+
+# success, all done
+status=0
+exit
diff --git a/039.out b/039.out
new file mode 100644 (file)
index 0000000..68780f6
--- /dev/null
+++ b/039.out
@@ -0,0 +1,89 @@
+QA output created by 039
+Creating directory system to dump using src/fill.
+Setup ....................................
+Erasing tape
+Dumping to tape...
+xfsdump  -o -F -l0 -f TAPE_DEV -M stress_tape_media -L stress_039 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_039"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: WARNING: media may contain data. Overwrite option specified
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: writing stream terminator
+xfsdump: beginning media stream terminator
+xfsdump: media file 2 (media 0, file 2)
+xfsdump: ending media stream terminator
+xfsdump: media stream terminator size 245760 bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -f TAPE_DEV  -L stress_039 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/big and RESTORE_DIR/DUMP_SUBDIR/big are identical
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Files DUMP_DIR/sub/a00 and RESTORE_DIR/DUMP_SUBDIR/sub/a00 are identical
+Files DUMP_DIR/sub/a000 and RESTORE_DIR/DUMP_SUBDIR/sub/a000 are identical
+Files DUMP_DIR/sub/b and RESTORE_DIR/DUMP_SUBDIR/sub/b are identical
+Files DUMP_DIR/sub/b00 and RESTORE_DIR/DUMP_SUBDIR/sub/b00 are identical
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Files DUMP_DIR/sub/c00 and RESTORE_DIR/DUMP_SUBDIR/sub/c00 are identical
+Files DUMP_DIR/sub/d and RESTORE_DIR/DUMP_SUBDIR/sub/d are identical
+Files DUMP_DIR/sub/d00 and RESTORE_DIR/DUMP_SUBDIR/sub/d00 are identical
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Files DUMP_DIR/sub/e00 and RESTORE_DIR/DUMP_SUBDIR/sub/e00 are identical
+Files DUMP_DIR/sub/e000 and RESTORE_DIR/DUMP_SUBDIR/sub/e000 are identical
+Files DUMP_DIR/sub/f and RESTORE_DIR/DUMP_SUBDIR/sub/f are identical
+Files DUMP_DIR/sub/f00 and RESTORE_DIR/DUMP_SUBDIR/sub/f00 are identical
+Files DUMP_DIR/sub/g and RESTORE_DIR/DUMP_SUBDIR/sub/g are identical
+Files DUMP_DIR/sub/g00 and RESTORE_DIR/DUMP_SUBDIR/sub/g00 are identical
+Files DUMP_DIR/sub/h and RESTORE_DIR/DUMP_SUBDIR/sub/h are identical
+Files DUMP_DIR/sub/h00 and RESTORE_DIR/DUMP_SUBDIR/sub/h00 are identical
+Files DUMP_DIR/sub/h000 and RESTORE_DIR/DUMP_SUBDIR/sub/h000 are identical
+Files DUMP_DIR/sub/i and RESTORE_DIR/DUMP_SUBDIR/sub/i are identical
+Files DUMP_DIR/sub/i00 and RESTORE_DIR/DUMP_SUBDIR/sub/i00 are identical
+Files DUMP_DIR/sub/j and RESTORE_DIR/DUMP_SUBDIR/sub/j are identical
+Files DUMP_DIR/sub/j00 and RESTORE_DIR/DUMP_SUBDIR/sub/j00 are identical
+Files DUMP_DIR/sub/k and RESTORE_DIR/DUMP_SUBDIR/sub/k are identical
+Files DUMP_DIR/sub/k00 and RESTORE_DIR/DUMP_SUBDIR/sub/k00 are identical
+Files DUMP_DIR/sub/k000 and RESTORE_DIR/DUMP_SUBDIR/sub/k000 are identical
+Files DUMP_DIR/sub/l and RESTORE_DIR/DUMP_SUBDIR/sub/l are identical
+Files DUMP_DIR/sub/l00 and RESTORE_DIR/DUMP_SUBDIR/sub/l00 are identical
+Files DUMP_DIR/sub/m and RESTORE_DIR/DUMP_SUBDIR/sub/m are identical
+Files DUMP_DIR/sub/m00 and RESTORE_DIR/DUMP_SUBDIR/sub/m00 are identical
+Files DUMP_DIR/sub/n and RESTORE_DIR/DUMP_SUBDIR/sub/n are identical
+Files DUMP_DIR/sub/n00 and RESTORE_DIR/DUMP_SUBDIR/sub/n00 are identical
+Files DUMP_DIR/sub/small and RESTORE_DIR/DUMP_SUBDIR/sub/small are identical
+Only in SCRATCH_MNT: RESTORE_SUBDIR
diff --git a/040 b/040
new file mode 100755 (executable)
index 0000000..8d8a3ea
--- /dev/null
+++ b/040
@@ -0,0 +1,83 @@
+#! /bin/sh
+# XFS QA Test No. 040
+# $Id: 1.1 $
+#
+# srcdiff test
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+cd `pwd`
+
+if [ -z "$WORKAREA" ]
+then
+    export WORKAREA=../../..
+fi
+
+if [ ! -f $WORKAREA/cmd/xfs/tools/srcdiff ]
+then
+    _notrun "Can't find srcdiff tool under \"$WORKAREA\""
+fi
+
+if [ ! -d $WORKAREA/linux/fs/xfs ]
+then
+    _notrun "Can't find XFS source under \"$WORKAREA\""
+fi
+
+if [ ! -d $WORKAREA/cmd/xfs/include ]
+then
+    _notrun "Can't find XFS command headers under \"$WORKAREA\""
+fi
+
+cd $WORKAREA/cmd/xfs/tools
+perl ./srcdiff -q
+
+# success, all done
+status=0
+exit
diff --git a/040.out b/040.out
new file mode 100644 (file)
index 0000000..c240969
--- /dev/null
+++ b/040.out
@@ -0,0 +1,7 @@
+QA output created by 040
+
+=== Checking headers ===
+
+=== Checking libxfs code ===
+
+=== Checking logprint code ===
diff --git a/041 b/041
new file mode 100755 (executable)
index 0000000..5b921b2
--- /dev/null
+++ b/041
@@ -0,0 +1,118 @@
+#! /bin/sh
+# XFS QA Test No. 041
+# $Id: 041,v 1.3 2000/09/27 00:24:17 ajag Exp ajag $
+#
+# growfs QA tests - repeatedly fill/grow the filesystem
+# check the filesystem contents after each operation
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+set +x
+# creator
+owner=ajag@melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+
+_cleanup()
+{
+    umount $SCRATCH_MNT
+    rm -f $tmp.*
+}
+trap "_cleanup ; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+_require_scratch
+
+_do()
+{
+    if [ $# -ne 1 ]; then echo "Usage: _do \"cmd\"" 1>&2 ; exit 1; fi
+    echo "*** $1" >>$seq.full
+    eval "$1 >>$seq.full 2>&1"
+}
+
+_fill()
+{
+    if [ $# -ne 1 ]; then echo "Usage: _fill \"path\"" 1>&2 ; exit 1; fi
+    echo -n "Fill filesystem... "
+    _do "(src/fill2fs --verbose --dir=$1 --seed=0 --filesize=65536 --stddev=32768 --list=- >>$tmp.manifest)"
+    echo "done"
+}
+
+rm -f $seq.full
+#agsize=16
+agsize=32
+echo -n "Make $agsize megabyte filesystem on SCRATCH_DEV and mount... "
+_do "mkfs -t xfs -d size=${agsize}m,agcount=1 -l internal -f $SCRATCH_DEV"
+_do "mount -t xfs $SCRATCH_DEV $SCRATCH_MNT"
+echo "done"
+
+# full allocation group -> partial; partial -> expand partial + new partial;
+# partial -> expand partial; partial -> full
+# 17 -> 33 -> 35 -> 48 megabytes, converted to fs blocks below
+#for size in 4352 8448 8960 12288
+# 33 -> 67 -> 75 -> 96 converted to fs blocks:
+for size in 8448 17512 19200 24576
+do
+    _fill $SCRATCH_MNT/fill_$size
+    echo -n "Grow filesystem to $size blocks... "
+    _do "xfs_growfs -D ${size} $SCRATCH_MNT"
+    echo "done"
+    echo -n "Flush filesystem... "
+    _do "umount $SCRATCH_MNT"
+    _do "mount -t xfs $SCRATCH_DEV $SCRATCH_MNT"
+    echo "done"
+    echo -n "Check files... "
+    if ! _do "src/fill2fs_check $tmp.manifest"; then
+       echo "fail"
+       echo "Files corrupt/missing after growfs. Test failed see $seq.full"
+       status=1; exit
+    fi
+    echo "done"
+#    echo -n "Checking filesystem... "
+#    _check_fs $SCRATCH_DEV
+#    echo "done"
+done
+
+# success, all done
+echo "Growfs tests passed."
+status=0 ; exit
diff --git a/041.out b/041.out
new file mode 100644 (file)
index 0000000..5266aeb
--- /dev/null
+++ b/041.out
@@ -0,0 +1,19 @@
+QA output created by 041
+Make 32 megabyte filesystem on SCRATCH_DEV and mount... done
+Fill filesystem... done
+Grow filesystem to 8448 blocks... done
+Flush filesystem... done
+Check files... done
+Fill filesystem... done
+Grow filesystem to 17512 blocks... done
+Flush filesystem... done
+Check files... done
+Fill filesystem... done
+Grow filesystem to 19200 blocks... done
+Flush filesystem... done
+Check files... done
+Fill filesystem... done
+Grow filesystem to 24576 blocks... done
+Flush filesystem... done
+Check files... done
+Growfs tests passed.
diff --git a/042 b/042
new file mode 100755 (executable)
index 0000000..9dc96f4
--- /dev/null
+++ b/042
@@ -0,0 +1,174 @@
+#! /bin/sh
+# XFS QA Test No. 042
+# $Id: 042,v 1.2 2000/09/27 00:24:22 ajag Exp ajag $
+#
+# fsr.xfs QA tests
+# create a large fragmented file and check that fsr.xfs doesn't corrupt
+# it or the other contents of the filesystem
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+set +x
+# creator
+owner=ajag@melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+
+_cleanup()
+{
+    umount $SCRATCH_MNT
+    rm -f $tmp.*
+}
+trap "_cleanup ; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+_require_scratch
+
+_cull_files()
+{
+    perl -e "\$manifest=\"$tmp.manifest\";" -e '
+       open MANIFEST, $manifest;
+       @in = <MANIFEST>;
+       close MANIFEST;
+       open MANIFEST, ">$manifest";
+       for ($i = 0; $i < @in; $i++) {
+           if (($i+1) % 2 == 0) {
+               # remove every second file
+               chomp($s = $in[$i]);
+               if (unlink($s) != 1) {
+                   print "_cull_files: could not delete \"$s\"\n";
+                   exit(1);
+               }
+           }
+           else {
+               print MANIFEST $in[$i];
+           }
+       }
+       close MANIFEST;'
+}
+
+_do()
+{
+    if [ $# -ne 1 ]; then echo "Usage: _do \"cmd\"" 1>&2 ; exit 1; fi
+    echo "*** $1" >>$seq.full
+    eval "$1 >>$seq.full 2>&1"
+}
+
+
+# create a large contiguous file using dd
+# use fill2fs to fill the filesystem up with 4k sized files
+# fill any remaining space using dd
+# delete every second 4k file - remaining free space should be fragmented
+# use fill2 to generate a very large file - run it until it fails producing a truncated file
+# delete the dd-generated file
+# run fsr.xfs on the filesystem
+# check checksums for remaining files
+
+# create 3 minimum sized (16Mb) allocation groups
+# xfs_repair is going to need three to verify the superblock
+rm -f $seq.full
+echo -n "Make a 48 megabyte filesystem on SCRATCH_DEV and mount... "
+_do "mkfs -t xfs -d size=48m,agcount=3 -l internal -f $SCRATCH_DEV"
+_do "mount -t xfs $SCRATCH_DEV $SCRATCH_MNT"
+echo "done"
+echo -n "Reserve 16 1Mb unfragmented regions... "
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+do
+    _do "dd if=/dev/zero of=$SCRATCH_MNT/hole$i bs=4096 count=256"
+    _do "dd if=/dev/zero of=$SCRATCH_MNT/space$i bs=4096 count=1"
+    _do "xfs_bmap $SCRATCH_MNT/hole$i"
+done
+echo "done" 
+echo -n "Fill filesystem with 4k files, generate manifest... "
+_do "(src/fill2fs --verbose --dir=$SCRATCH_MNT/fill --seed=0 --filesize=4096 --stddev=0 --list=$tmp.manifest)"
+echo "done"
+echo -n "Use up any further available space using dd... "
+_do "dd if=/dev/zero of=$SCRATCH_MNT/pad bs=4096"
+echo "done"
+echo -n "Delete every second file... "
+if ! _do "_cull_files"; then
+    echo "fail"
+    echo "Could not cull files. Test failed see $seq.full"
+    status=1; exit
+fi
+echo "done"
+echo -n "Create one very large file... "
+_do "src/fill2 -d nbytes=16000000,file=$SCRATCH_MNT/fragmented"
+echo "done"
+_do "xfs_bmap $SCRATCH_MNT/fragmented"
+_do "(sum $SCRATCH_MNT/fragmented >$tmp.sum1)"
+echo -n "Remove other files... "
+_do "rm -rf $SCRATCH_MNT/{pad,hole*}"
+echo "done"
+
+# flush everything
+_do "umount $SCRATCH_MNT"
+_do "mount -t xfs $SCRATCH_DEV $SCRATCH_MNT"
+
+echo -n "Run fsr.xfs on filesystem... "
+_do "fsr.xfs -v $SCRATCH_DEV"
+echo "done"
+_do "xfs_bmap $SCRATCH_MNT/fragmented"
+
+echo -n "Check 4k files... "
+if ! _do "src/fill2fs_check $tmp.manifest"; then
+    echo "fail"
+    echo "4k file is corrupt/missing after fsr. Test failed see $seq.full"
+    status=1; exit
+fi
+echo "done"
+echo -n "Check large file... "
+_do "(sum $SCRATCH_MNT/fragmented >$tmp.sum2)"
+if ! diff $tmp.sum1 $tmp.sum2; then
+    echo "fail"
+    echo "File is corrupt/missing after fsr. Test failed see $seq.full"
+    status=1; exit
+fi
+echo "done"
+
+echo -n "Checking filesystem... "
+_check_fs $SCRATCH_DEV
+echo "done"
+# success, all done
+echo "fsr.xfs tests passed."
+status=0 ; exit
diff --git a/042.out b/042.out
new file mode 100644 (file)
index 0000000..785d245
--- /dev/null
+++ b/042.out
@@ -0,0 +1,13 @@
+QA output created by 042
+Make a 48 megabyte filesystem on SCRATCH_DEV and mount... done
+Reserve 16 1Mb unfragmented regions... done
+Fill filesystem with 4k files, generate manifest... done
+Use up any further available space using dd... done
+Delete every second file... done
+Create one very large file... done
+Remove other files... done
+Run fsr.xfs on filesystem... done
+Check 4k files... done
+Check large file... done
+Checking filesystem... done
+fsr.xfs tests passed.
diff --git a/043 b/043
new file mode 100755 (executable)
index 0000000..db8aae5
--- /dev/null
+++ b/043
@@ -0,0 +1,69 @@
+#! /bin/sh
+# XFS QA Test No. 043
+# $Id: 1.1 $
+#
+# Test out xfsdump/restore but rmv inventory prior to restore.
+# This checks that the on-disk inventory can be successfully
+# rebuilt from the on-tape inventory.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_require_tape
+_create_dumpdir_fill
+_erase_hard
+_do_dump_sub
+rm -rf /var/xfsdump/inventory # delete it - let cleanup fix it
+_do_restore
+_diff_compare_sub
+_ls_compare_sub
+
+# success, all done
+status=0
+exit
diff --git a/043.out b/043.out
new file mode 100644 (file)
index 0000000..035aa35
--- /dev/null
+++ b/043.out
@@ -0,0 +1,105 @@
+QA output created by 043
+Put scsi tape driver into variable block size mode
+Creating directory system to dump using src/fill.
+Setup ....................................
+Erasing tape
+Dumping to tape...
+xfsdump  -s DUMP_SUBDIR -f TAPE_DEV -M stress_tape_media -L stress_043 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_043"
+xfsdump: ino map phase 1: parsing subtree selections
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: pruning unneeded subtrees
+xfsdump: ino map phase 4: estimating dump size
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: preparing drive
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dumping session inventory
+xfsdump: beginning inventory media file
+xfsdump: media file 1 (media 0, file 1)
+xfsdump: ending inventory media file
+xfsdump: inventory media file size NUM bytes
+xfsdump: writing stream terminator
+xfsdump: beginning media stream terminator
+xfsdump: media file 2 (media 0, file 2)
+xfsdump: ending media stream terminator
+xfsdump: media stream terminator size 1048576 bytes
+xfsdump: dump size (non-dir files) : NUM bytes
+xfsdump: dump complete: SECS seconds elapsed
+Rewinding tape
+Restoring from tape...
+xfsrestore  -f TAPE_DEV  -L stress_043 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: searching media for dump
+xfsrestore: preparing drive
+xfsrestore: examining media file 0
+xfsrestore: found dump matching specified label:
+xfsrestore: hostname: HOSTNAME
+xfsrestore: mount point: SCRATCH_MNT
+xfsrestore: volume: SCRATCH_DEV
+xfsrestore: session time: TIME
+xfsrestore: level: 0
+xfsrestore: session label: "stress_043"
+xfsrestore: media label: "stress_tape_media"
+xfsrestore: file system id: ID
+xfsrestore: session id: ID
+xfsrestore: media id: ID
+xfsrestore: searching media for directory dump
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: examining media file 1
+xfsrestore: incorporating on-media session inventory into online inventory
+xfsrestore: /var/xfsdump/inventory created
+xfsrestore: using on-media session inventory
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing dump directory with restore directory
+Files DUMP_DIR/big and RESTORE_DIR/DUMP_SUBDIR/big are identical
+Files DUMP_DIR/small and RESTORE_DIR/DUMP_SUBDIR/small are identical
+Files DUMP_DIR/sub/a and RESTORE_DIR/DUMP_SUBDIR/sub/a are identical
+Files DUMP_DIR/sub/a00 and RESTORE_DIR/DUMP_SUBDIR/sub/a00 are identical
+Files DUMP_DIR/sub/a000 and RESTORE_DIR/DUMP_SUBDIR/sub/a000 are identical
+Files DUMP_DIR/sub/b and RESTORE_DIR/DUMP_SUBDIR/sub/b are identical
+Files DUMP_DIR/sub/b00 and RESTORE_DIR/DUMP_SUBDIR/sub/b00 are identical
+Files DUMP_DIR/sub/big and RESTORE_DIR/DUMP_SUBDIR/sub/big are identical
+Files DUMP_DIR/sub/c and RESTORE_DIR/DUMP_SUBDIR/sub/c are identical
+Files DUMP_DIR/sub/c00 and RESTORE_DIR/DUMP_SUBDIR/sub/c00 are identical
+Files DUMP_DIR/sub/d and RESTORE_DIR/DUMP_SUBDIR/sub/d are identical
+Files DUMP_DIR/sub/d00 and RESTORE_DIR/DUMP_SUBDIR/sub/d00 are identical
+Files DUMP_DIR/sub/e and RESTORE_DIR/DUMP_SUBDIR/sub/e are identical
+Files DUMP_DIR/sub/e00 and RESTORE_DIR/DUMP_SUBDIR/sub/e00 are identical
+Files DUMP_DIR/sub/e000 and RESTORE_DIR/DUMP_SUBDIR/sub/e000 are identical
+Files DUMP_DIR/sub/f and RESTORE_DIR/DUMP_SUBDIR/sub/f are identical
+Files DUMP_DIR/sub/f00 and RESTORE_DIR/DUMP_SUBDIR/sub/f00 are identical
+Files DUMP_DIR/sub/g and RESTORE_DIR/DUMP_SUBDIR/sub/g are identical
+Files DUMP_DIR/sub/g00 and RESTORE_DIR/DUMP_SUBDIR/sub/g00 are identical
+Files DUMP_DIR/sub/h and RESTORE_DIR/DUMP_SUBDIR/sub/h are identical
+Files DUMP_DIR/sub/h00 and RESTORE_DIR/DUMP_SUBDIR/sub/h00 are identical
+Files DUMP_DIR/sub/h000 and RESTORE_DIR/DUMP_SUBDIR/sub/h000 are identical
+Files DUMP_DIR/sub/i and RESTORE_DIR/DUMP_SUBDIR/sub/i are identical
+Files DUMP_DIR/sub/i00 and RESTORE_DIR/DUMP_SUBDIR/sub/i00 are identical
+Files DUMP_DIR/sub/j and RESTORE_DIR/DUMP_SUBDIR/sub/j are identical
+Files DUMP_DIR/sub/j00 and RESTORE_DIR/DUMP_SUBDIR/sub/j00 are identical
+Files DUMP_DIR/sub/k and RESTORE_DIR/DUMP_SUBDIR/sub/k are identical
+Files DUMP_DIR/sub/k00 and RESTORE_DIR/DUMP_SUBDIR/sub/k00 are identical
+Files DUMP_DIR/sub/k000 and RESTORE_DIR/DUMP_SUBDIR/sub/k000 are identical
+Files DUMP_DIR/sub/l and RESTORE_DIR/DUMP_SUBDIR/sub/l are identical
+Files DUMP_DIR/sub/l00 and RESTORE_DIR/DUMP_SUBDIR/sub/l00 are identical
+Files DUMP_DIR/sub/m and RESTORE_DIR/DUMP_SUBDIR/sub/m are identical
+Files DUMP_DIR/sub/m00 and RESTORE_DIR/DUMP_SUBDIR/sub/m00 are identical
+Files DUMP_DIR/sub/n and RESTORE_DIR/DUMP_SUBDIR/sub/n are identical
+Files DUMP_DIR/sub/n00 and RESTORE_DIR/DUMP_SUBDIR/sub/n00 are identical
+Files DUMP_DIR/sub/small and RESTORE_DIR/DUMP_SUBDIR/sub/small are identical
+Comparing listing of dump directory with restore directory
+Files TMP.dump_dir and TMP.restore_dir are identical
diff --git a/044 b/044
new file mode 100755 (executable)
index 0000000..014e545
--- /dev/null
+++ b/044
@@ -0,0 +1,171 @@
+#! /bin/sh
+# XFS QA Test No. 041
+# $Id: 1.1 $
+#
+# external log uuid/format tests
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+_require_logdev
+
+_filter_logprint()
+{
+       perl -ne '
+           s/data device: ([\w|\/]+)/data device: DDEV/;
+           s/log device: ([\w|\/]+) daddr: (\d+) length: (\d+)/log device: LDEV daddr: XXX length: XXX/;
+           s/log file: "([\w|\/]+)" daddr: (\d+) length: (\d+)/log device: LDEV daddr: XXX length: XXX/;
+           s/uuid: ([abcdef\d-]+)\s+format: (.+)/uuid: UUID format: FORMAT/;
+           s/skipped (\w+) zeroed blocks/skipped XXX zeroed blocks/;
+           print;
+       '
+}
+
+_check_mount()
+{
+    echo "    *** mount (expect success)"
+    if ! mount -t xfs -o logdev=$SCRATCH_LOGDEV $SCRATCH_DEV $SCRATCH_MNT
+    then
+        echo "        !!! mount failed (expecting success)"
+        status=1
+        exit
+    fi
+
+    echo "    *** umount"
+    if ! umount $SCRATCH_DEV
+    then
+        echo "        !!! umount failed (expecting success)"
+        status=1
+        exit
+    fi
+}
+
+_check_no_mount()
+{
+    echo "    *** mount (expect failure)"
+    if mount -t xfs -o logdev=$SCRATCH_LOGDEV $SCRATCH_DEV $SCRATCH_MNT >$tmp.err 2>&1
+    then
+        cat $tmp.err
+        echo "        !!! mount succeeded (expecting failure)"
+        status=1
+        exit
+    fi
+}
+
+_check_require_logdev()
+{
+    echo "    *** mount without logdev (expect failure)"
+    if mount -t xfs $SCRATCH_DEV $SCRATCH_MNT >$tmp.err 2>&1
+    then
+        cat $tmp.err
+        echo "        !!! mount succeeded (expecting failure)"
+        status=1
+        exit
+    fi
+}
+
+
+
+# real QA test starts here
+# 
+_require_scratch
+
+echo -e -n "\n\r*** XFS QA 044 - expect mount failure messages\n\r\n\r" >/dev/console
+
+echo "*** mkfs"
+mkfs -t xfs -f -l logdev=$SCRATCH_LOGDEV,size=4096b $SCRATCH_DEV | _filter_mkfs 2>/dev/null
+_check_mount
+_check_require_logdev
+
+echo "*** set uuid"
+xfs_db -x $SCRATCH_DEV -l $SCRATCH_LOGDEV -c "uuid 02020202-0202-0202-0202-020202020202" \
+    || _unexpected
+_check_mount
+
+echo "*** zero log"
+$here/src/loggen -z 100 >$SCRATCH_LOGDEV
+_check_mount
+
+echo "*** write clean log"
+$here/src/loggen -u 2 -f 1 -m 1 -z 100 >$SCRATCH_LOGDEV
+_check_mount
+
+echo "*** write clean log (different format)"
+$here/src/loggen -u 2 -f 99 -m 1 -z 100 >$SCRATCH_LOGDEV
+_check_mount
+
+echo "*** write clean log (different uuid)"
+$here/src/loggen -u 7 -m 1 -z 100 >$SCRATCH_LOGDEV
+_check_no_mount
+
+echo "*** write clean log (different uuid & format)"
+$here/src/loggen -u 7 -f 99 -m 1 -z 100 >$SCRATCH_LOGDEV
+_check_no_mount
+
+echo "*** write dirty log"
+$here/src/loggen -u 2 -e 1 -z 100 >$SCRATCH_LOGDEV
+_check_mount
+
+echo "*** write dirty log (different format)"
+$here/src/loggen -u 2 -f 99 -e 1 -z 100 >$SCRATCH_LOGDEV
+_check_no_mount
+
+echo "*** write dirty log (irix style)"
+$here/src/loggen -u 0 -f 0 -e 1 -z 100 >$SCRATCH_LOGDEV
+_check_no_mount
+
+echo "*** write large dirty log"
+$here/src/loggen -u 2 -e 16000 -z 100 >$SCRATCH_LOGDEV
+_check_mount
+
+echo -e -n "\n\r*** XFS QA 044 - done\n\r\n\r" >/dev/console
+
+status=0
+# if error
+exit
diff --git a/044.out b/044.out
new file mode 100644 (file)
index 0000000..6a9db57
--- /dev/null
+++ b/044.out
@@ -0,0 +1,66 @@
+QA output created by 044
+*** mkfs
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+    *** mount (expect success)
+    *** umount
+    *** mount without logdev (expect failure)
+*** set uuid
+clearing log and setting uuid
+writing all SBs
+new uuid = 02020202-0202-0202-0202-020202020202
+    *** mount (expect success)
+    *** umount
+*** zero log
+*** loggen
+   *** zero block (1BB) x 100
+    *** mount (expect success)
+    *** umount
+*** write clean log
+*** loggen
+   *** unmount record (2BB) x 1
+   *** zero block (1BB) x 100
+    *** mount (expect success)
+    *** umount
+*** write clean log (different format)
+*** loggen
+   *** unmount record (2BB) x 1
+   *** zero block (1BB) x 100
+    *** mount (expect success)
+    *** umount
+*** write clean log (different uuid)
+*** loggen
+   *** unmount record (2BB) x 1
+   *** zero block (1BB) x 100
+    *** mount (expect failure)
+*** write clean log (different uuid & format)
+*** loggen
+   *** unmount record (2BB) x 1
+   *** zero block (1BB) x 100
+    *** mount (expect failure)
+*** write dirty log
+*** loggen
+   *** empty record (2BB) x 1
+   *** zero block (1BB) x 100
+    *** mount (expect success)
+    *** umount
+*** write dirty log (different format)
+*** loggen
+   *** empty record (2BB) x 1
+   *** zero block (1BB) x 100
+    *** mount (expect failure)
+*** write dirty log (irix style)
+*** loggen
+   *** empty record (2BB) x 1
+   *** zero block (1BB) x 100
+    *** mount (expect failure)
+*** write large dirty log
+*** loggen
+   *** empty record (2BB) x 16000
+   *** zero block (1BB) x 100
+    *** mount (expect success)
+    *** umount
diff --git a/045 b/045
new file mode 100755 (executable)
index 0000000..94334bd
--- /dev/null
+++ b/045
@@ -0,0 +1,97 @@
+#! /bin/sh
+# XFS QA Test No. 045
+# $Id: 1.1 $
+#
+# test mount of two FSes with identical UUID and mount with unknown option
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_get_uuid()
+{
+        xfs_db -r $1 -c "uuid" | $AWK_PROG '
+                /^uuid/ { print $3 }
+        '
+}
+
+# real QA test starts here
+
+_require_scratch
+
+echo "*** get uuid"
+uuid=`_get_uuid $TEST_DEV`
+echo "*** mkfs"
+if ! mkfs -t xfs -f $SCRATCH_DEV >$tmp.out 2>&1
+then
+    cat $tmp.out
+    echo "!!! failed to mkfs on $SCRATCH_DEV"
+    exit
+fi
+
+echo "*** mount fs with bad mount option (expect failure)"
+if mount -t xfs $SCRATCH_DEV $SCRATCH_MNT -o foobar >$tmp.out 2>&1
+then
+    cat $tmp.out
+    echo "!!! mount succeeded (expecting failure)"
+    exit
+fi
+
+echo "*** duplicate uuid"
+xfs_db -x $SCRATCH_DEV -c "uuid $uuid" >/dev/null
+
+echo "*** mount fs with duplicate uuid (expect failure)"
+if mount -t xfs $SCRATCH_DEV $SCRATCH_MNT >$tmp.out 2>&1
+then
+    cat $tmp.out
+    echo "!!! mount succeeded (expecting failure)"
+    exit
+fi
+
+echo "*** ok!"
+# success, all done
+status=0
+exit
diff --git a/045.out b/045.out
new file mode 100644 (file)
index 0000000..708b709
--- /dev/null
+++ b/045.out
@@ -0,0 +1,7 @@
+QA output created by 045
+*** get uuid
+*** mkfs
+*** mount fs with bad mount option (expect failure)
+*** duplicate uuid
+*** mount fs with duplicate uuid (expect failure)
+*** ok!
diff --git a/046 b/046
new file mode 100755 (executable)
index 0000000..3bae089
--- /dev/null
+++ b/046
@@ -0,0 +1,63 @@
+#! /bin/sh
+# XFS QA Test No. 046
+# $Id: 1.1 $
+#
+# check on symlinks permissions
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+_create_dumpdir_symlinks
+_do_dump_file
+_do_restore_file
+_ls_compare_sub
+
+# success, all done
+status=0
+exit
diff --git a/046.out b/046.out
new file mode 100644 (file)
index 0000000..3013664
--- /dev/null
+++ b/046.out
@@ -0,0 +1,38 @@
+QA output created by 046
+Creating directory system of symlinks to dump.
+Setup ....
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L stress_046 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "stress_046"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+Restoring from file...
+xfsrestore  -f DUMP_FILE  -L stress_046 RESTORE_DIR
+xfsrestore: version 3.0 - Running single-threaded
+xfsrestore: using online session inventory
+xfsrestore: searching media for directory dump
+xfsrestore: examining media file 0
+xfsrestore: reading directories
+xfsrestore: directory post-processing
+xfsrestore: restoring non-directory files
+xfsrestore: restore complete: SECS seconds elapsed
+Comparing listing of dump directory with restore directory
+Files TMP.dump_dir and TMP.restore_dir are identical
diff --git a/047 b/047
new file mode 100755 (executable)
index 0000000..2d0adcc
--- /dev/null
+++ b/047
@@ -0,0 +1,98 @@
+#! /bin/sh
+# XFS QA Test No. 047
+# $Id: 1.1 $
+#
+# invutil with interactive responses
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sherman.melbourne.sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.dump
+
+# real QA test starts here
+
+# wipe test dir clean first
+# so dump can be real quick
+_wipe_fs
+
+#
+# Create 5 dumps
+# and on the 3rd dump note the date
+# which we'll use to prune against using xfsinvutil
+#
+i=0
+while [ $i -lt 5 ]; do
+    _do_dump_file -L "session.$i"
+    if [ $i -eq 2 ]; then
+       sleep 1
+       middate=`date '+%m/%d/%Y %T'`
+    fi
+    rm $dump_file
+    sleep 2
+    i=`expr $i + 1`
+done
+
+echo "middate = $middate" >>$seq.full
+
+# Only say No to 1st question to prune
+cat >$tmp.input <<EOF
+N
+Y
+Y
+Y
+Y
+EOF
+
+#
+# Now do the xfsinvutil and
+# look and the inventory before and after
+# to see if it did the job
+#
+_dump_inventory
+_do_invutil <$tmp.input
+_dump_inventory
+
+status=0
+exit
diff --git a/047.out b/047.out
new file mode 100644 (file)
index 0000000..7dd34d5
--- /dev/null
+++ b/047.out
@@ -0,0 +1,347 @@
+QA output created by 047
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.0 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.0"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: /var/xfsdump/inventory created
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.1 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.1"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.2 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.2"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.3 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.3"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+Dumping to file...
+xfsdump  -f DUMP_FILE -M stress_tape_media -L session.4 SCRATCH_MNT
+xfsdump: version 3.0 - Running single-threaded
+xfsdump: level 0 dump of HOSTNAME:SCRATCH_MNT
+xfsdump: dump date: DATE
+xfsdump: session id: ID
+xfsdump: session label: "session.4"
+xfsdump: ino map phase 1: skipping (no subtrees specified)
+xfsdump: ino map phase 2: constructing initial dump list
+xfsdump: ino map phase 3: skipping (no pruning necessary)
+xfsdump: ino map phase 4: skipping (size estimated in phase 2)
+xfsdump: ino map phase 5: skipping (only one dump stream)
+xfsdump: ino map construction complete
+xfsdump: estimated dump size: NUM bytes
+xfsdump: creating dump session media file 0 (media 0, file 0)
+xfsdump: dumping ino map
+xfsdump: dumping directories
+xfsdump: dumping non-directory files
+xfsdump: ending media file
+xfsdump: media file size NUM bytes
+xfsdump: dump size (non-dir files) : 0 bytes
+xfsdump: dump complete: SECS seconds elapsed
+file system 0:
+       fs id: ID
+       session 0:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.0"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 1:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.1"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 2:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.2"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 3:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.3"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 4:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.4"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+Processing file /var/xfsdump/inventory/UUIDstab
+   Found entry for HOSTNAME:SCRATCH_MNT
+      processing index file 
+       /var/xfsdump/inventory/UUID.InvIndex
+         Checking access for
+          /var/xfsdump/inventory/UUID.StObj
+          Mount point match
+            Session 0: HOSTNAME:SCRATCH_MNT
+-------------------------------------------------
+An entry matching the mount point/time is :
+UUID           :       ID
+MOUNT POINT    :       HOSTNAME:SCRATCH_MNT
+DEV PATH       :       HOSTNAME:SCRATCH_DEV
+TIME OF DUMP   :       TIME
+
+Do you want to prune this entry: [y/n] -------------------------------------------------
+
+            Session 1: HOSTNAME:SCRATCH_MNT
+-------------------------------------------------
+An entry matching the mount point/time is :
+UUID           :       ID
+MOUNT POINT    :       HOSTNAME:SCRATCH_MNT
+DEV PATH       :       HOSTNAME:SCRATCH_DEV
+TIME OF DUMP   :       TIME
+
+Do you want to prune this entry: [y/n] -------------------------------------------------
+
+            Session 2: HOSTNAME:SCRATCH_MNT
+-------------------------------------------------
+An entry matching the mount point/time is :
+UUID           :       ID
+MOUNT POINT    :       HOSTNAME:SCRATCH_MNT
+DEV PATH       :       HOSTNAME:SCRATCH_DEV
+TIME OF DUMP   :       TIME
+
+Do you want to prune this entry: [y/n] -------------------------------------------------
+
+            Session 3: HOSTNAME:SCRATCH_MNT
+            Session 4: HOSTNAME:SCRATCH_MNT
+file system 0:
+       fs id: ID
+       session 0:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.0"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 1:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.3"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
+       session 2:
+               mount point:    HOSTNAME:SCRATCH_MNT
+               device:         HOSTNAME:SCRATCH_DEV
+               time: TIME
+               session label:  "session.4"
+               session id: ID
+               level:          0
+               resumed:        NO
+               subtree:        NO
+               streams:        1
+               stream 0:
+                       pathname:       DUMP_FILE
+                       start:          ino 0 offset 0
+                       end:            ino 1 offset 0
+                       interrupted:    NO
+                       media files:    1
+                       media file 0:
+                               mfile index:    0
+                               mfile type:     data
+                               mfile size:     21016
+                               mfile start:    ino 0 offset 0
+                               mfile end:      ino 1 offset 0
+                               media label:    "stress_tape_media"
+                               media id: ID
diff --git a/048 b/048
new file mode 100755 (executable)
index 0000000..eb4c77a
--- /dev/null
+++ b/048
@@ -0,0 +1,60 @@
+#! /bin/sh
+# XFS QA Test No. 048
+# $Id: 1.1 $
+#
+# test return codes from ioctl on bad userspace address
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+src/fault $TEST_DIR || exit
+
+# success, all done
+status=0
+exit
diff --git a/048.out b/048.out
new file mode 100644 (file)
index 0000000..e6feb5f
--- /dev/null
+++ b/048.out
@@ -0,0 +1,5 @@
+QA output created by 048
+--- ioctl with bad output address
+   --- got error 14 as expected
+--- ioctl with bad input address
+   --- got error 14 as expected
diff --git a/049 b/049
new file mode 100755 (executable)
index 0000000..40cf8c1
--- /dev/null
+++ b/049
@@ -0,0 +1,148 @@
+#! /bin/sh
+# XFS QA Test No. 049
+# $Id: 1.1 $
+#
+# XFS on loop test
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightfullclaim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+_cleanup()
+{
+    umount $SCRATCH_MNT/test2 > /dev/null 2>&1
+    umount $SCRATCH_MNT/test > /dev/null 2>&1
+    rm -f $tmp.*
+    
+    if [ -w $seq.full ]
+    then
+        echo "--- mounts at end (after cleanup)" >> $seq.full
+        mount >> $seq.full
+    fi
+}
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "_cleanup ; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_log()
+{
+    echo "--- $*"
+    echo "--- $*" >> $seq.full
+}
+
+# real QA test starts here
+
+_require_scratch
+_require_loop
+
+rm -f $seq.full
+
+echo "(dev=$SCRATCH_DEV, mount=$SCRATCH_MNT)" >> $seq.full
+echo "" >> $seq.full
+
+echo "--- mounts" >> $seq.full
+mount >> $seq.full
+
+_log "Create ext2 fs on scratch"
+mkfs -t ext2 $SCRATCH_DEV >> $seq.full 2>&1 \
+    || _fail "!!! failed to mkfs ext2"
+
+_log "Mount ext2 fs on scratch"
+mount -t ext2 $SCRATCH_DEV $SCRATCH_MNT >> $seq.full 2>&1 \
+    || _fail "!!! failed to mount"
+
+_log "Create xfs fs in file on scratch"
+mkfs -t xfs -d file,name=$SCRATCH_MNT/test.xfs,size=20m >> $seq.full 2>&1 \
+    || _fail "!!! failed to mkfs xfs"
+
+_log "Make mount points"
+mkdir $SCRATCH_MNT/test $SCRATCH_MNT/test2 >> $seq.full 2>&1 \
+    || _fail "!!! failed to make mount points"
+
+_log "Mount xfs via loop"
+mount -t xfs -o loop $SCRATCH_MNT/test.xfs $SCRATCH_MNT/test >> $seq.full 2>&1 \
+    || _fail "!!! failed to loop mount xfs"
+
+_log "stress"
+src/fsstress -d $SCRATCH_MNT/test -n 1000 $FSSTRESS_AVOID >> $seq.full 2>&1 \
+    || _fail "!!! stress failed"
+    
+_log "clean"
+rm -rf $SCRATCH_MNT/test/* >> $seq.full 2>&1 \
+    || _fail "!!! clean failed"
+
+_log "create file for ext2 fs"
+dd if=/dev/zero of=$SCRATCH_MNT/test/test.ext2 bs=1024 count=10240 >> $seq.full 2>&1 \
+    || _fail "!!! create file failed"
+    
+_log "Create ext2 fs in file on looped xfs"
+echo y | mkfs -t ext2 $SCRATCH_MNT/test/test.ext2 >> $seq.full 2>&1 \
+    || _fail "!!! failed to mkfs ext2 on xfs"
+
+_log "Mount ext2 on xfs via loop"
+mount -t ext2 -o loop $SCRATCH_MNT/test/test.ext2 $SCRATCH_MNT/test2 >> $seq.full 2>&1 \
+    || _fail "!!! failed to loop mount xfs"
+
+_log "stress ext2 on xfs via loop"
+src/fsstress -d $SCRATCH_MNT/test2 -n 1000 $FSSTRESS_AVOID >> $seq.full 2>&1 \
+    || _fail "!!! stress ext2 failed"   
+
+_log "clean"
+rm -rf $SCRATCH_MNT/test/* >> $seq.full 2>&1 \
+    || _fail "!!! clean failed"
+   
+_log "umount ext2 on xfs"
+umount $SCRATCH_MNT/test2 >> $seq.full 2>&1 \
+    || _fail "!!! umount ext2 failed"
+    
+_log "umount xfs"
+umount $SCRATCH_MNT/test >> $seq.full 2>&1 \
+    || _fail "!!! umount xfs failed"
+    
+echo "--- mounts at end (before cleanup)" >> $seq.full
+mount >> $seq.full
+
+rm -f $seq.full
+# success, all done
+status=0
+exit
diff --git a/049.out b/049.out
new file mode 100644 (file)
index 0000000..cdd4d0a
--- /dev/null
+++ b/049.out
@@ -0,0 +1,15 @@
+QA output created by 049
+--- Create ext2 fs on scratch
+--- Mount ext2 fs on scratch
+--- Create xfs fs in file on scratch
+--- Make mount points
+--- Mount xfs via loop
+--- stress
+--- clean
+--- create file for ext2 fs
+--- Create ext2 fs in file on looped xfs
+--- Mount ext2 on xfs via loop
+--- stress ext2 on xfs via loop
+--- clean
+--- umount ext2 on xfs
+--- umount xfs
diff --git a/050 b/050
new file mode 100755 (executable)
index 0000000..7c7bd33
--- /dev/null
+++ b/050
@@ -0,0 +1,149 @@
+#! /bin/sh
+# XFS QA Test No. 050
+# $Id: 1.1 $
+#
+# Exercises basic XFS quota functionality
+#      MOUNT_OPTIONS env var switches the test type (uid/gid/acct/enfd)
+#      options are:  (-o) usrquota, grpquota, uqnoenforce, gqnoenforce
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=nathans@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.quota
+. ./common.filter
+
+_cleanup()
+{
+    echo; echo "*** unmount"
+    umount $SCRATCH_MNT 2>/dev/null
+    rm -f $tmp.*
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+rm -f $seq.full $seq.out
+
+_require_quota
+_require_scratch
+
+_mymount()
+{
+    umount $SCRATCH_DEV >/dev/null 2>&1
+    mount -t xfs $SCRATCH_DEV $SCRATCH_MNT || _fail "mount failed"
+    chmod ugo+rwx $SCRATCH_MNT
+    quot.xfs $SCRATCH_DEV >>$seq.full 2>&1
+}
+
+# real QA test starts here
+mkfs -t xfs -f $SCRATCH_DEV | _filter_mkfs 2>$tmp.mkfs
+cat $tmp.mkfs >>$seq.full
+chmod a+w $seq.full    # arbitrary users will write here
+
+# keep the blocksize and data size for dd later
+. $tmp.mkfs
+
+_mymount
+
+# setup exactly what it is we'll be testing
+if ! src/feature -q $SCRATCH_DEV
+then
+       _notrun "XFS quota not enabled"
+elif src/feature -u $SCRATCH_DEV
+then
+       type=u ; id=`_choose_uid`; ln -s $seq.usrquota $seq.out
+elif src/feature -g $SCRATCH_DEV
+then
+       type=g ; id=`_choose_gid`; ln -s $seq.grpquota $seq.out
+elif src/feature -U $SCRATCH_DEV
+then
+       type=u ; id=`_choose_uid`; ln -s $seq.uqnoenforce $seq.out
+elif src/feature -G $SCRATCH_DEV
+then
+       type=g ; id=`_choose_gid`; ln -s $seq.gqnoenforce $seq.out
+else
+       _notrun "No quota support at mount time"
+fi
+
+echo "Using output from '" `ls -l $seq.out` "'" >>$seq.full
+echo "and using type=$type id=$id" >>$seq.full
+
+echo
+echo "*** report no quota settings" | tee -a $seq.full
+repquota -m -$type $SCRATCH_DEV | _filter_repquota
+
+echo
+echo "*** report initial settings" | tee -a $seq.full
+setquota -n -$type $id $SCRATCH_DEV 100 500 4 10
+_file_as_id $SCRATCH_MNT/initme $id $type $dbsize 0
+repquota -m -$type $SCRATCH_DEV | _filter_repquota
+
+echo
+echo "*** push past the soft inode limit" | tee -a $seq.full
+_file_as_id $SCRATCH_MNT/softie1 $id $type $dbsize 0
+_file_as_id $SCRATCH_MNT/softie2 $id $type $dbsize 0
+_mymount
+repquota -m -$type $SCRATCH_DEV | _filter_repquota
+
+echo
+echo "*** push past the soft block limit" | tee -a $seq.full
+_file_as_id $SCRATCH_MNT/softie $id $type $dbsize 140
+_mymount
+repquota -m -$type $SCRATCH_DEV | _filter_repquota
+
+echo
+echo "*** push past the hard inode limit (expect EDQUOT)" | tee -a $seq.full
+for i in 1 2 3 4 5 6 7 8 9 10 11 12
+do
+       _file_as_id $SCRATCH_MNT/hard$i $id $type $dbsize 0
+done
+_mymount
+repquota -m -$type $SCRATCH_DEV | _filter_repquota
+
+echo
+echo "*** push past the hard block limit (expect EDQUOT)" | tee -a $seq.full
+_file_as_id $SCRATCH_MNT/softie $id $type $dbsize 540
+_mymount
+repquota -m -$type $SCRATCH_DEV | _filter_repquota
+
+# success, all done
+status=0
+exit
diff --git a/050.uqnoenforce b/050.uqnoenforce
new file mode 100644 (file)
index 0000000..cb211ac
--- /dev/null
@@ -0,0 +1,44 @@
+QA output created by 050
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+
+*** report no quota settings
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+
+*** report initial settings
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+[NAME]    --       0     100     500              1     4    10       
+
+*** push past the soft inode limit
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+[NAME]    --       0     100     500              3     4    10       
+
+*** push past the soft block limit
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+[NAME]    ++     140     100     500   none       4     4    10   none
+
+*** push past the hard inode limit (expect EDQUOT)
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       1       0       0              3     0     0       
+[NAME]    ++     140     100     500   none      16     4    10   none
+
+*** push past the hard block limit (expect EDQUOT)
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       1       0       0              3     0     0       
+[NAME]    ++     540     100     500   none      16     4    10   none
+
+*** unmount
diff --git a/050.usrquota b/050.usrquota
new file mode 100644 (file)
index 0000000..fcfd68a
--- /dev/null
@@ -0,0 +1,44 @@
+QA output created by 050
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+
+*** report no quota settings
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+
+*** report initial settings
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+[NAME]    --       0     100     500              1     4    10       
+
+*** push past the soft inode limit
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+[NAME]    --       0     100     500              3     4    10       
+
+*** push past the soft block limit
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+[NAME]    ++     140     100     500 7 days       4     4    10 7 days
+
+*** push past the hard inode limit (expect EDQUOT)
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+[NAME]    ++     140     100     500 7 days      10     4    10 7 days
+
+*** push past the hard block limit (expect EDQUOT)
+                        Block limits               File limits
+user            used    soft    hard  grace    used  soft  hard  grace
+[NAME]    --       0       0       0              3     0     0       
+[NAME]    ++     496     100     500 7 days      10     4    10 7 days
+
+*** unmount
diff --git a/051 b/051
new file mode 100755 (executable)
index 0000000..8b2796f
--- /dev/null
+++ b/051
@@ -0,0 +1,262 @@
+#! /bin/sh
+# XFS QA Test No. 051
+# $Id: 1.1 $
+#
+# Test out ACLs.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=tes@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+runas=$here/src/runas
+status=1       # FAILure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_cleanup()
+{
+    rm -f $tmp.*
+    rm -rf $TEST_DIR/$seq.dir1
+}
+
+_ls()
+{
+    ls -ln $* | awk '{ print $1, $3, $4, $NF }'
+} 
+
+# -----
+# minimal access ACL has ACEs: USER_OBJ, GROUP_OBJ, OTHER_OBJ
+# This is set with chacl(1) and can be changed by chmod(1).
+#
+# Test that this is being set for ACL and for std unix permissions
+# Test that we can get back the same ACL.
+# Test std permissions for rwx.
+# -----
+#
+# Test out default ACLs and that the ACL is being PASSed
+# onto the children of the dir.
+#
+# -----
+# Test out access check for extended ACLs.
+# -> 3 extra ACEs: MASK, GROUP, USER
+# -> the GROUP compares with egid of process _and_ the supplementary
+#    groups (as found in /etc/group)
+#
+# Test that mask works for USER, GROUP, GROUP_OBJ
+# Test that the ACE type priority is working
+#   -> this would be done by simultaneously matching on ACEs
+#   -> interesting if it allows user to specify ACEs in any order
+#
+
+acl1=1001;acl2=1002;acl3=1003
+
+[ -x /bin/chacl ] || _notrun "chacl command not found"
+[ -x $runas ] || _notrun "$runas executable not found"
+
+# get dir
+cd $TEST_DIR
+rm -rf $seq.dir1
+mkdir $seq.dir1
+cd $seq.dir1
+
+#-------------------------------------------------------
+# real QA test starts here
+
+echo ""
+echo "=== Test minimal ACE ==="
+
+echo "Setup file"
+touch file1
+cat <<EOF >file1
+#!/bin/sh
+echo "Test was executed"
+EOF
+chmod u=rwx file1
+chmod g=rw- file1
+chmod o=r-- file1
+chown $acl1.$acl2 file1
+_ls file1
+
+echo ""
+echo "--- Test get and set of ACL ---"
+chacl -l file1
+echo "Expect to FAIL" 
+chacl u::r--,g::rwx,o:rw- file1 2>&1
+echo "Expect to PASS" 
+chacl u::r--,g::rwx,o::rw- file1 2>&1
+chacl -l file1
+
+echo ""
+echo "--- Test sync of ACL with std permissions ---"
+_ls file1
+chmod u+w file1
+_ls file1
+chacl -l file1
+
+echo ""
+echo "--- Test owner permissions ---"
+chacl u::r-x,g::---,o::--- file1 2>&1
+chacl -l file1
+# change to owner
+echo "Expect to PASS" 
+$runas -u $acl1 -g $acl1 ./file1 2>&1
+echo "Expect to FAIL" 
+$runas -u $acl2 -g $acl2 ./file1 2>&1
+
+echo ""
+echo "--- Test group permissions ---"
+chacl u::---,g::r-x,o::--- file1 2>&1
+chacl -l file1
+echo "Expect to FAIL - acl1 is owner" 
+$runas -u $acl1 -g $acl1 ./file1 2>&1
+echo "Expect to PASS - acl2 matches group" 
+$runas -u $acl2 -g $acl2 ./file1 2>&1
+echo "Expect to PASS - acl2 matches sup group" 
+$runas -u $acl2 -g $acl3 -s $acl2 ./file1 2>&1
+echo "Expect to FAIL - acl3 is not in group" 
+$runas -u $acl3 -g $acl3 ./file1 2>&1
+
+echo ""
+echo "--- Test other permissions ---"
+chacl u::---,g::---,o::r-x file1 2>&1
+chacl -l file1
+echo "Expect to FAIL - acl1 is owner" 
+$runas -u $acl1 -g $acl1 ./file1 2>&1
+echo "Expect to FAIL - acl2 is in group" 
+$runas -u $acl2 -g $acl2 ./file1 2>&1
+echo "Expect to FAIL - acl2 is in sup. group" 
+$runas -u $acl2 -g $acl3 -s $acl2 ./file1 2>&1
+echo "Expect to PASS - acl3 is not owner or in group" 
+$runas -u $acl3 -g $acl3 ./file1 2>&1
+
+#-------------------------------------------------------
+
+echo ""
+echo "=== Test Extended ACLs ==="
+
+echo ""
+echo "--- Test adding a USER ACE ---"
+echo "Expect to FAIL as no MASK provided"
+chacl u::---,g::---,o::---,u:$acl2:r-x file1 2>&1
+echo "Ensure that ACL has not been changed"
+chacl -l file1
+echo "Expect to PASS - USER ACE matches user"
+chacl u::---,g::---,o::---,u:$acl2:r-x,m::rwx file1 2>&1
+chacl -l file1
+$runas -u $acl2 -g $acl2 ./file1 2>&1
+echo "Expect to FAIL - USER ACE does not match user"
+$runas -u $acl3 -g $acl3 ./file1 2>&1
+
+echo ""
+echo "--- Test adding a GROUP ACE ---"
+echo "Expect to FAIL as no MASK provided"
+chacl u::---,g::---,o::---,g:$acl2:r-x file1 2>&1
+echo "Ensure that ACL has not been changed"
+chacl -l file1
+chacl u::---,g::---,o::---,g:$acl2:r-x,m::rwx file1 2>&1
+chacl -l file1
+echo "Expect to PASS - GROUP ACE matches group"
+$runas -u $acl2 -g $acl2 ./file1 2>&1
+echo "Expect to PASS - GROUP ACE matches sup group"
+$runas -u $acl2 -g $acl1 -s $acl2 ./file1 2>&1
+echo "Expect to FAIL - GROUP ACE does not match group"
+$runas -u $acl3 -g $acl3 ./file1 2>&1
+
+#-------------------------------------------------------
+
+echo ""
+echo "--- Test MASK ---"
+chacl u::---,g::---,o::---,g:$acl2:r-x,m::-wx file1 2>&1
+chacl -l file1
+echo "Expect to FAIL as MASK prohibits execution"
+$runas -u $acl2 -g $acl2 ./file1 2>&1
+chacl u::---,g::---,o::---,u:$acl2:r-x,m::-wx file1 2>&1
+echo "Expect to FAIL as MASK prohibits execution"
+$runas -u $acl2 -g $acl2 ./file1 2>&1
+
+chacl u::---,g::---,o::---,u:$acl2:r-x,m::r-x file1 2>&1
+echo "Expect to PASS as MASK allows execution"
+$runas -u $acl2 -g $acl2 ./file1 2>&1
+
+#-------------------------------------------------------
+
+echo ""
+echo "--- Test ACE priority ---"
+
+chacl o::rwx,g::rwx,u:$acl1:rwx,u::---,m::rwx file1 2>&1
+echo "Expect to FAIL as should match on owner"
+$runas -u $acl1 -g $acl2 ./file1 2>&1
+
+chacl o::---,g::---,u:$acl2:rwx,u::---,m::rwx file1 2>&1
+echo "Expect to PASS as should match on user"
+$runas -u $acl2 -g $acl2 ./file1 2>&1
+
+
+#-------------------------------------------------------
+
+echo ""
+echo "=== Test can read ACLs without access permissions ==="
+# This was a bug in kernel code where syscred wasn't being used
+# to override the capabilities
+chacl o::---,g::---,u::--- file1 2>&1
+chacl -l ./file1
+
+
+#-------------------------------------------------------
+
+echo ""
+echo "=== Test Default ACLs ==="
+mkdir acldir
+chacl -b "u::rwx,g::rwx,o::rwx" "u::r-x,g::r--,o::---" ./acldir 2>&1
+chacl -l ./acldir
+
+cd acldir
+touch file2
+_ls file2
+chacl -l ./file2
+cd ..
+
+#-------------------------------------------------------
+
+# success, all done
+status=0
+exit
diff --git a/051.out b/051.out
new file mode 100644 (file)
index 0000000..3b3672f
--- /dev/null
+++ b/051.out
@@ -0,0 +1,95 @@
+QA output created by 051
+
+=== Test minimal ACE ===
+Setup file
+-rwxrw-r-- 1001 1002 file1
+
+--- Test get and set of ACL ---
+file1 []
+Expect to FAIL
+chacl: "u::r--,g::rwx,o:rw-" is an invalid ACL specification.
+Expect to PASS
+file1 [u::r--,g::rwx,o::rw-]
+
+--- Test sync of ACL with std permissions ---
+-r--rwxrw- 1001 1002 file1
+-rw-rwxrw- 1001 1002 file1
+file1 [u::rw-,g::rwx,o::rw-]
+
+--- Test owner permissions ---
+file1 [u::r-x,g::---,o::---]
+Expect to PASS
+Test was executed
+Expect to FAIL
+sh: ./file1: Permission denied
+
+--- Test group permissions ---
+file1 [u::---,g::r-x,o::---]
+Expect to FAIL - acl1 is owner
+sh: ./file1: Permission denied
+Expect to PASS - acl2 matches group
+Test was executed
+Expect to PASS - acl2 matches sup group
+Test was executed
+Expect to FAIL - acl3 is not in group
+sh: ./file1: Permission denied
+
+--- Test other permissions ---
+file1 [u::---,g::---,o::r-x]
+Expect to FAIL - acl1 is owner
+sh: ./file1: Permission denied
+Expect to FAIL - acl2 is in group
+sh: ./file1: Permission denied
+Expect to FAIL - acl2 is in sup. group
+sh: ./file1: Permission denied
+Expect to PASS - acl3 is not owner or in group
+Test was executed
+
+=== Test Extended ACLs ===
+
+--- Test adding a USER ACE ---
+Expect to FAIL as no MASK provided
+chacl: error setting access acl on "file1": Invalid argument
+Ensure that ACL has not been changed
+file1 [u::---,g::---,o::r-x]
+Expect to PASS - USER ACE matches user
+file1 [u::---,g::---,o::---,u:1002:r-x,m::rwx]
+Test was executed
+Expect to FAIL - USER ACE does not match user
+sh: ./file1: Permission denied
+
+--- Test adding a GROUP ACE ---
+Expect to FAIL as no MASK provided
+chacl: error setting access acl on "file1": Invalid argument
+Ensure that ACL has not been changed
+file1 [u::---,g::---,o::---,u:1002:r-x,m::rwx]
+file1 [u::---,g::---,o::---,g:1002:r-x,m::rwx]
+Expect to PASS - GROUP ACE matches group
+Test was executed
+Expect to PASS - GROUP ACE matches sup group
+Test was executed
+Expect to FAIL - GROUP ACE does not match group
+sh: ./file1: Permission denied
+
+--- Test MASK ---
+file1 [u::---,g::---,o::---,g:1002:r-x,m::-wx]
+Expect to FAIL as MASK prohibits execution
+./file1: ./file1: Permission denied
+Expect to FAIL as MASK prohibits execution
+./file1: ./file1: Permission denied
+Expect to PASS as MASK allows execution
+Test was executed
+
+--- Test ACE priority ---
+Expect to FAIL as should match on owner
+sh: ./file1: Permission denied
+Expect to PASS as should match on user
+Test was executed
+
+=== Test can read ACLs without access permissions ===
+./file1 [o::---,g::---,u::---]
+
+=== Test Default ACLs ===
+./acldir [u::rwx,g::rwx,o::rwx/u::r-x,g::r--,o::---]
+-r--r----- 0 0 file2
+./file2 [u::r--,g::r--,o::---]
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..ef6e323
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+#
+# $Id: Makefile,v 2.195 1999/10/19 02:07:28 kenmcd Exp $
+#
+
+TOPDIR = ..
+include $(TOPDIR)/include/builddefs
+
+TESTS = $(shell sed -n -e '/^[0-9][0-9][0-9]*/s/ .*//p' group)
+LDIRT = *.bad *.new *.core *.full *.raw core a.out *.bak check.log check.time
+SUBDIRS = src
+
+default: new remake check $(TESTS) $(SUBDIRS)
+       $(SUBDIRS_MAKERULE)
+
+install:
+
+include $(BUILDRULES)
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..27fefc8
--- /dev/null
+++ b/README
@@ -0,0 +1,174 @@
+______________________
+USING THE XFS QA SUITE
+______________________
+
+Preparing system for tests:
+
+    - compile XFS into your kernel or load XFS modules
+    - install user tools including mkfs.xfs, xfs_db & xfs_bmap
+    
+    - create two partitions to use for testing
+        - one TEST partition
+            - format as XFS, mount & optionally populate with 
+              NON-IMPORTANT stuff
+        - one SCRATCH partition
+            - leave empty and expect this partition to be clobbered
+              by some tests.
+              
+        (these must be two DIFFERENT partitions)
+              
+    - setup your environment
+        - setenv TEST_DEV "device containing TEST PARTITION"
+        - setenv TEST_DIR "mount point of TEST PARTITION"   
+        - setenv SCRATCH_DEV "device containing SCRATCH PARTITION"
+        - setenv SCRATCH_MNT "mount point for SCRATCH PARTITION"
+        - setenv TAPE_DEV "tape device for testing xfsdump"
+        - setenv RMT_TAPE_DEV "remote tape device for testing xfsdump"
+        - setenv RMT_IRIXTAPE_DEV "remote IRIX tape device for testing xfsdump"
+       - optionally:
+            - setenv SCRATCH_LOGDEV "device for external log"
+             - setenv SCRATCH_RTDEV "device for realtime data"
+        - or add a case to the switch in common.config assigning
+          these variables based on the hostname of your test
+          machine
+
+    - if testing xfsdump, make sure the tape devices have a
+      tape which can be overwritten.
+          
+    - make sure $TEST_DEV is a mounted XFS partition
+    - make sure that $SCRATCH_DEV contains nothing useful
+    
+Running tests:
+
+    - cd cmd/xfs/stress
+    - ./check 001 002 003 ... 
+    
+    The check script tests the return value of each script, and
+    compares the output against the expected output. If the output
+    is not as expected, a diff will be output and an .out.bad file
+    will be produced for the failing test.
+    
+    Unexpected console messages, crashes and hangs may be considered
+    to be failures but are not necesarily detected by the QA system.
+
+__________________________ 
+ADDING TO THE XFS QA SUITE
+__________________________
+
+
+Creating new tests scripts:
+
+    Use the "new" script.
+
+Test script environment:
+
+    When developing a new test script keep the following things in
+    mind.  All of the environment variables and shell procedures are
+    available to the script once the "common.rc" file has been
+    sourced.
+
+     1. The tests are run from an arbitrary directory.  If you want to
+       do operations on an XFS filesystem (good idea, eh?), then do
+       one of the following:
+
+       (a) Create directories and files at will in the directory
+           $TEST_DIR ... this is within an XFS filesystem and world
+           writeable.  You should cleanup when your test is done,
+           e.g. use a _cleanup shell procedure in the trap ... see
+           001 for an example.  If you need to know, the $TEST_DIR
+           direcotry is within the filesystem on the block device
+           $TEST_DEV.
+
+       (b) mkfs a new XFS filesystem on $SCRATCH_DEV, and mount this
+           on $SCRATCH_MNT. Call the the _require_scratch function 
+            on startup if you require use of the scratch partition.
+            _require_scratch does some checks on $SCRATCH_DEV & 
+            $SCRATCH_MNT and makes sure they're unmounted. You should 
+            cleanup when your test is done, and in particular unmount 
+            $SCRATCH_MNT.
+           Tests can make use of $SCRATCH_LOGDEV and $SCRATCH_RTDEV
+           for testing external log and realtime volumes - however,
+           these tests need to simply "pass" (e.g. cat $seq.out; exit
+           - or default to an internal log) in the common case where
+           these variables are not set.
+
+     2. You can safely create temporary files that are not part of the
+       filesystem tests (e.g. to catch output, prepare lists of things
+       to do, etc.) in files named $tmp.<anything>.  The standard test
+       script framework created by "new" will initialize $tmp and
+       cleanup on exit.
+
+     3. By default, tests are run as the same uid as the person
+       executing the control script "check" that runs the test scripts.
+
+       If you need to be root, add a call to the shell procedure
+       _need_to_be_root ... this will do nothing or exit with an
+       error message depending on your current uid.
+
+     4. Some other useful shell procedures:
+
+       _get_fqdn               - echo the host's fully qualified
+                                 domain name
+
+       _get_pids_by_name       - one argument is a process name, and
+                                 return all of the matching pids on
+                                 standard output
+
+       _within_tolerance       - fancy numerical "close enough is good
+                                 enough" filter for deterministic
+                                 output ... see comments in
+                                 common.filter for an explanation
+
+       _filter_date            - turn ctime(3) format dates into the
+                                 string DATE for deterministic
+                                 output
+
+Verified output:
+
+    Each test script has a numerical name, e.g. 007, and an associated
+    verified output, e.g. 007.out.
+
+    It is important that the verified output is deterministic, and
+    part of the job of the test script is to filter the output to
+    make this so.  Examples of the sort of things that need filtering:
+
+    - dates
+    - pids
+    - hostnames
+    - filesystem names
+    - timezones
+    - variable directory contents
+    - imprecise numbers, especially sizes and times
+
+    Use the "remake" script to recreate the verified output for one
+    or more tests.
+
+Pass/failure:
+
+    The script "check" may be used to run one or more tests.
+
+    Test number $seq is deemed to "pass" when:
+    (a) no "core" file is created,
+    (b) the file $seq.notrun is not created,
+    (c) the exit status is 0, and
+    (d) the output matches the verified output.
+
+    In the "not run" case (b), the $seq.notrun file should contain a
+    short one-line summary of why the test was not run.  The standard
+    output is not checked, so this can be used for a more verbose
+    explanation and to provide feedback when the QA test is run
+    interactively.
+
+
+    To force a non-zero exit status use:
+       status=1
+       exit
+
+    Note that:
+       exit 1
+    won't have the desired effect becuase of the way the exit trap
+    works.
+
+    The recent pass/fail history is maintained in the file "check.log".
+    The elapsed time for the most recent pass for each test is kept
+    in "check.time".
diff --git a/check b/check
new file mode 100755 (executable)
index 0000000..033128c
--- /dev/null
+++ b/check
@@ -0,0 +1,279 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+#
+# Control script for QA
+#
+# $Header: /build2/depot/linux/pcp/dev/qa/RCS/check,v 2.32 1999/10/18 06:58:20 kenmcd Exp $
+#
+
+tmp=/tmp/$$
+status=0
+needwrap=true
+try=0
+n_bad=0
+bad=""
+notrun=""
+interrupt=true
+
+# generic initialization
+iam=check
+if ! . ./common.rc
+then
+    echo "check: failed to source common.rc"
+    exit 1
+fi
+
+if [ $UID -ne 0 ]
+then
+    echo "check: QA must be run as root"
+    exit 1
+fi
+
+_wallclock()
+{
+    date "+%H %M %S" | $AWK_PROG '{ print $1*3600 + $2*60 + $3 }'
+}
+
+_timestamp()
+{
+    now=`date "+%D-%T"` 
+    echo -n " [$now]"
+}
+
+_wrapup()
+{
+    # for hangcheck ...
+    # remove files that were used by hangcheck
+    #
+    [ -f /tmp/check.pid ] && rm -rf /tmp/check.pid
+    [ -f /tmp/check.sts ] && rm -rf /tmp/check.sts
+
+    if $showme
+    then
+       :
+    elif $needwrap
+    then
+       if [ -f check.time -a -f $tmp.time ]
+       then
+           cat check.time $tmp.time \
+           | $AWK_PROG '
+       { t[$1] = $2 }
+END    { if (NR > 0) {
+           for (i in t) print i " " t[i]
+         }
+       }' \
+           | sort -n >$tmp.out
+           mv $tmp.out check.time
+       fi
+
+       if [ -f $tmp.expunged ]
+       then
+           notrun=`wc -l <$tmp.expunged | sed -e 's/  *//g'`
+           try=`expr $try - $notrun`
+           list=`echo "$list" | sed -f $tmp.expunged`
+       fi
+
+       echo "" >>check.log
+       date >>check.log
+       echo $list | fmt | sed -e 's/^/    /' >>check.log
+       $interrupt && echo "Interrupted!" >>check.log
+        
+       if [ ! -z "$notrun" ]
+       then
+           echo "Not run:$notrun"
+           echo "Not run:$notrun" >>check.log
+       fi
+        if [ ! -z "$n_bad" -a $n_bad != 0 ]
+       then
+           echo "Failures:$bad"
+           echo "Failed $n_bad of $try tests"
+           echo "Failures:$bad" | fmt >>check.log
+           echo "Failed $n_bad of $try tests" >>check.log
+       else
+           echo "Passed all $try tests"
+           echo "Passed all $try tests" >>check.log
+       fi
+       needwrap=false
+    fi
+
+    rm -f $tmp.*
+}
+
+trap "_wrapup; exit \$status" 0 1 2 3 15
+
+# for hangcheck ...
+# Save pid of check in a well known place, so that hangcheck can be sure it
+# has the right pid (getting the pid from ps output is not reliable enough).
+#
+rm -rf /tmp/check.pid
+echo $$ >/tmp/check.pid
+
+# for hangcheck ...
+# Save the status of check in a well known place, so that hangcheck can be
+# sure to know where check is up to (getting test number from ps output is
+# not reliable enough since the trace stuff has been introduced).
+#
+rm -rf /tmp/check.sts
+echo "preamble" >/tmp/check.sts
+
+# don't leave old full output behind on a clean run
+rm -f check.full
+
+# by default don't output timestamps
+timestamp=false
+
+. ./common
+
+[ -f check.time ] || touch check.time
+
+if [ ! -z "$MOUNT_OPTIONS" ]
+then
+    echo "check: \$MOUNT_OPTIONS specifed - \"$MOUNT_OPTIONS\""
+    umount $TEST_DEV
+    # call the overridden mount - make sure the FS starts as
+    # the same as we'll set it later.
+    if ! mount -t xfs $TEST_DEV $TEST_DIR >$tmp.err 2>&1
+    then
+       echo "our mount ..."
+       cat $tmp.err
+        # call the normal mount
+       echo "normal mount ..."
+        /bin/mount -t xfs $TEST_DEV $TEST_DIR
+        echo "check: failed to mount \$TEST_DEV using specified mount options"
+        exit 1
+    fi
+fi
+
+seq="check"
+_check_fs $TEST_DEV
+
+for seq in $list
+do
+    err=false
+    echo -n "$seq"
+    if $showme
+    then
+       echo
+       continue
+    elif [ -f expunged ] && $expunge && egrep "^$seq([         ]|\$)" expunged >/dev/null
+    then
+       echo " - expunged"
+       rm -f $seq.out.bad
+       echo "/^$seq\$/d" >>$tmp.expunged
+    elif [ ! -f $seq ]
+    then
+       echo " - no such test?"
+       echo "/^$seq\$/d" >>$tmp.expunged
+    else
+       # really going to try and run this one
+       #
+       rm -f $seq.out.bad
+       lasttime=`sed -n -e "/^$seq /s/.* //p" <check.time`
+       [ "X$lasttime" != X ] && echo -n " ${lasttime}s ..."
+       rm -f core $seq.notrun
+
+       # for hangcheck ...
+       echo "$seq" >/tmp/check.sts
+
+       start=`_wallclock`
+       $timestamp && _timestamp
+       sh $seq >$tmp.rawout 2>&1
+       sts=$?
+       $timestamp && _timestamp
+       stop=`_wallclock`
+
+       _fix_malloc <$tmp.rawout >$tmp.out
+       rm -f $tmp.rawout
+
+       if [ -f core ]
+       then
+           echo -n " [dumped core]"
+           mv core $seq.core
+           err=true
+       fi
+
+       if [ -f $seq.notrun ]
+       then
+           echo -n " [not run] "
+           cat $seq.notrun
+           notrun="$notrun $seq"
+       else
+           if [ $sts -ne 0 ]
+           then
+               echo -n " [failed, exit status $sts]"
+               err=true
+           fi
+           if [ ! -f $seq.out ]
+           then
+               echo " - no qualified output"
+               err=true
+           else
+               if diff $seq.out $tmp.out >/dev/null 2>&1
+               then
+                   echo ""
+                   if $err
+                   then
+                       :
+                   else
+                       echo "$seq `expr $stop - $start`" >>$tmp.time
+                   fi
+               else
+                   echo " - output mismatch (see $seq.out.bad)"
+                   mv $tmp.out $seq.out.bad
+                   $diff $seq.out $seq.out.bad
+                   err=true
+               fi
+           fi
+       fi
+
+    fi
+
+    # come here for each test, except when $showme is true
+    #
+    if $err
+    then
+       bad="$bad $seq"
+       n_bad=`expr $n_bad + 1`
+       quick=false
+    fi
+    [ -f $seq.notrun ] || try=`expr $try + 1`
+    
+    seq="after_$seq"
+    _check_fs $TEST_DEV
+    
+done
+
+interrupt=false
+status=`expr $n_bad`
+exit
diff --git a/common b/common
new file mode 100644 (file)
index 0000000..febd52e
--- /dev/null
+++ b/common
@@ -0,0 +1,287 @@
+##/bin/sh
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+# common procedures for QA scripts
+#
+# $Header: /disk7/depot/linux/pcp/dev/qa/RCS/common,v 2.52 2000/04/05 18:24:51 kenmcd Exp $
+#
+
+_setenvironment()
+{
+    MSGVERB="text:action"
+    export MSGVERB
+}
+
+here=`pwd`
+rm -f $here/$iam.out
+_setenvironment
+
+check=${check-true}
+
+if $check
+then
+    if make >/tmp/$$.make 2>&1
+    then
+       :
+    else
+       cat /tmp/$$.make
+       echo "Warning: make failed -- some tests may be missing"
+       warn=1
+    fi
+    rm -f /tmp/$$.make
+fi
+
+diff=diff
+if [ ! -z "$DISPLAY" ]
+then
+    which xdiff >/dev/null 2>&1 && diff=xdiff
+    which gdiff >/dev/null 2>&1 && diff=gdiff
+    which tkdiff >/dev/null 2>&1 && diff=tkdiff
+fi
+verbose=false
+quick=${quick-false}
+group=false
+xgroup=false
+showme=false
+sortme=false
+expunge=true
+have_test_arg=false
+rm -f $tmp.list $tmp.tmp $tmp.sed
+
+for r
+do
+
+    if $group
+    then
+       # arg after -g
+       group_list=`sed -n <group -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
+s/ .*//p
+}'`
+       if [ -z "$group_list" ]
+       then
+           echo "Group \"$r\" is empty or not defined?"
+           exit 1
+       fi
+       [ ! -s $tmp.list ] && touch $tmp.list
+       for t in $group_list
+       do
+           if grep -s "^$t\$" $tmp.list >/dev/null
+           then
+               :
+           else
+               echo "$t" >>$tmp.list
+           fi
+       done
+       group=false
+       continue
+
+    elif $xgroup
+    then
+       # arg after -x
+       [ ! -s $tmp.list ] && ls [0-9][0-9][0-9] [0-9][0-9][0-9][0-9] >$tmp.list 2>/dev/null
+       group_list=`sed -n <group -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
+s/ .*//p
+}'`
+       if [ -z "$group_list" ]
+       then
+           echo "Group \"$r\" is empty or not defined?"
+           exit 1
+       fi
+       numsed=0
+       rm -f $tmp.sed
+       for t in $group_list
+       do
+           if [ $numsed -gt 100 ]
+           then
+               sed -f $tmp.sed <$tmp.list >$tmp.tmp
+               mv $tmp.tmp $tmp.list
+               numsed=0
+               rm -f $tmp.sed
+           fi
+           echo "/^$t\$/d" >>$tmp.sed
+           numsed=`expr $numsed + 1`
+       done
+       sed -f $tmp.sed <$tmp.list >$tmp.tmp
+       mv $tmp.tmp $tmp.list
+       xgroup=false
+       continue
+    fi
+
+    xpand=true
+    case "$r"
+    in
+
+       -\?)    # usage
+           echo "Usage: $0 [options] [testlist]"'
+
+common options
+    -v                 verbose
+
+check options
+    -g group[,group...]        include tests from these groups
+    -l                 line mode diff [xdiff]
+    -n                 show me, do not run tests
+    -q                 quick, no checks (you are on your own)
+    -T                 output timestamps
+    -x group[,group...]        exclude tests from these groups
+'
+           exit 0
+           ;;
+
+       -g)     # -g group ... pick from group file
+           group=true
+           xpand=false
+           ;;
+
+       -l)     # line mode for diff, not gdiff over modems
+           diff=diff
+           xpand=false
+           ;;
+
+       -q)     # "quick", no checks (you are on your own)
+           quick=true
+           xpand=false
+           ;;
+
+       -n)     # show me, don't do it
+           showme=true
+           xpand=false
+           ;;
+
+       -T)     # turn on timestamp output
+           timestamp=true
+           xpand=false
+           ;;
+
+       -v)
+           verbose=true
+           xpand=false
+           ;;
+
+       -x)     # -x group ... exclude from group file
+           xgroup=true
+           xpand=false
+           ;;
+
+       '[0-9][0-9][0-9] [0-9][0-9][0-9][0-9]')
+           echo "No tests?"
+           status=1
+           exit $status
+           ;;
+
+       [0-9]*-[0-9]*)
+           eval `echo $r | sed -e 's/^/start=/' -e 's/-/ end=/'`
+           ;;
+
+       [0-9]*-)
+           eval `echo $r | sed -e 's/^/start=/' -e 's/-//'`
+           end=`echo [0-9][0-9][0-9] [0-9][0-9][0-9][0-9] | sed -e 's/\[0-9]//g' -e 's/  *$//' -e 's/.* //'`
+           if [ -z "$end" ]
+           then
+               echo "No tests in range \"$r\"?"
+               status=1
+               exit $status
+           fi
+           ;;
+
+       *)
+           start=$r
+           end=$r
+           ;;
+
+    esac
+
+    if $xpand
+    then
+       have_test_arg=true
+       $AWK_PROG </dev/null '
+BEGIN  { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \
+       | while read id
+       do
+           if grep -s "^$id " group >/dev/null
+           then
+               # in group file ... OK
+               echo $id >>$tmp.list
+           else
+               if [ -f expunged ] && $expunge && egrep "^$id([         ]|\$)" expunged >/dev/null
+               then
+                   # expunged ... will be reported, but not run, later
+                   echo $id >>$tmp.list
+               else
+                   # oops
+                   echo "$id - unknown test, ignored"
+               fi
+           fi
+       done
+    fi
+
+done
+
+if [ -s $tmp.list ]
+then
+    # found some valid test numbers ... this is good
+    :
+else
+    if $have_test_arg
+    then
+       # had test numbers, but none in group file ... do nothing
+       touch $tmp.list
+    else
+       # no test numbers, do everything from group file
+       sed -n -e '/^[0-9][0-9][0-9]*/s/[       ].*//p' <group >$tmp.list
+    fi
+fi
+
+# should be sort -n, but this did not work for Linux when this
+# was ported from IRIX
+#
+list=`sort $tmp.list`
+rm -f $tmp.list $tmp.tmp $tmp.sed
+
+if $quick
+then
+    :
+else
+
+    if ( cd src; make -i )
+    then
+       :
+    else
+       echo
+       echo ":----------------------------------------------"
+       echo ": Warning: make failed in src -- some tests may fail as a result"
+       echo ":----------------------------------------------"
+       echo
+       warn=1
+    fi
+
+fi
diff --git a/common.config b/common.config
new file mode 100644 (file)
index 0000000..547da68
--- /dev/null
@@ -0,0 +1,189 @@
+##/bin/sh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+#
+# setup and check for config parameters, and in particular
+#
+# TEST_DIR             - scratch test directory that is in an already
+#                        mounted XFS file system, needs to be be world
+#                        writeable
+# TEST_DEV             - device for file system containing TEST_DIR
+# SCRATCH_DEV          - device you can make a scratch file system on
+# SCRATCH_MNT          - mount point for scratch file system
+# 
+# and optionally:
+# SCRATCH_LOGDEV       - scratch log device for external log testing
+# SCRATCH_RTDEV                - scratch rt dev (only for testing cmds currently)
+# TAPE_DEV             - the tape device for the xfsdump tests
+# RMT_TAPE_DEV         - the remote tape device for the xfsdump tests
+# RMT_IRIXTAPE_DEV     - the IRIX remote tape device for the xfsdump tests
+#
+
+#
+# - This script is shared by the stress test system and the auto-qa
+#   system
+# - TEST_DEV & TEST_DIR must be assigned.
+# - this script shouldn't make any assertions about filesystem
+#   validity or mountedness.
+#
+
+_readlink()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _readlink filename" 1>&2
+       exit 1
+    fi
+
+    perl -e "\$in=\"$1\";" -e '
+       $lnk = readlink($in);
+       if ($lnk =~ m!^/.*!) {
+         print "$lnk\n";
+       }
+       else {
+         chomp($dir = `dirname $in`);
+         print "$dir/$lnk\n";
+       }'
+}
+
+
+case `hostname -s`
+in
+    fuzzy)
+        TEST_DEV=/dev/sda6
+       TEST_DIR=/mnt/xfs1
+       SCRATCH_DEV=/dev/sda5
+       SCRATCH_MNT=/mnt/xfs0
+       SCRATCH_LOGDEV=/dev/sda7
+       ;;
+    bruce)
+        TEST_DEV=/dev/sda10
+       TEST_DIR=/mnt/xfs1
+       SCRATCH_DEV=/dev/sda9
+       SCRATCH_MNT=/mnt/xfs0
+       SCRATCH_LOGDEV=/dev/sda11
+       TAPE_DEV=/dev/st0
+       RMT_TAPE_DEV=bruce:/dev/st0
+       RMT_IRIXTAPE_DEV=snort:/dev/tape
+       ;;
+    sherman)
+       TEST_DEV=/dev/sda10
+       TEST_DIR=/mnt/xfs1
+       SCRATCH_DEV=/dev/sda9
+       SCRATCH_MNT=/mnt/xfs0
+        ;;
+    sagan)
+        TEST_DEV=/dev/sda6
+       TEST_DIR=/mnt/xfs0
+       SCRATCH_DEV=/dev/sda7
+       SCRATCH_MNT=/mnt/xfs1
+       TAPE_DEV=/dev/st0
+       RMT_TAPE_DEV=sagan:/dev/st0
+       RMT_IRIXTAPE_DEV=snort:/dev/tape
+       ;;
+    leesa)
+        TEST_DEV=/dev/xfs_test
+       TEST_DIR=/mnt/xfs_test
+        SCRATCH_DEV=/dev/xfs_scratch
+       SCRATCH_MNT=/mnt/xfs_scratch
+       SCRATCH_LOGDEV=/dev/xfs_log
+       ;;
+    troppo)
+       TEST_DEV=/dev/hdb6
+       TEST_DIR=/mnt/test
+       SCRATCH_DEV=/dev/hdb7
+       SCRATCH_MNT=/mnt/scratch
+       SCRATCH_LOGDEV=/dev/hdb9
+       SCRATCH_RTDEV=/dev/hdb10
+       ;;
+    lord)
+       TEST_DIR=/xfs
+       TEST_DEV=/dev/sda4
+       SCRATCH_DEV=/dev/hda2
+       SCRATCH_MNT=/xfs1
+       ;;
+    lumpy)
+       TEST_DEV=/dev/sdc5
+       TEST_DIR=/mnt/scratch_0
+       SCRATCH_DEV=/dev/sdc7
+       SCRATCH_MNT=/mnt/scratch_2
+       ;;
+    bongo)
+       TEST_DEV=/dev/hda8
+       TEST_DIR=/xfs1
+       SCRATCH_DEV=/dev/hda9
+       SCRATCH_MNT=/xfs2
+       SCRATCH_LOGDEV=/dev/hda10
+       SCRATCH_RTDEV=/dev/hda11
+       ;;
+
+    *)
+       echo "common.config: Error: need to define parameters for host `hostname -s`"
+       exit 1
+       ;;
+esac
+
+if [ ! -b "$TEST_DEV" ]
+then
+    echo "common.config: Error: \$TEST_DEV ($TEST_DEV) is not a block device"
+    exit 1
+fi
+
+if [ ! -d "$TEST_DIR" ]
+then
+    echo "common.config: Error: \$TEST_DIR ($TEST_DIR) is not a directory"
+    exit 1
+fi
+
+if [ ! -z "$SCRATCH_DEV" -a ! -b "$SCRATCH_DEV" ]
+then
+    echo "common.config: Error: \$SCRATCH_DEV ($SCRATCH_DEV) is not a block device"
+    exit 1
+fi
+
+if [ ! -z "$SCRATCH_DEV" -a ! -d "$SCRATCH_MNT" ]
+then
+    echo "common.config: Error: \$SCRATCH_MNT ($SCRATCH_MNT) is not a directory"
+    exit 1
+fi
+
+# if devfs is running expand the full /dev/.. pathname - this is what will be
+# returned by utilities such as mount
+[ -L "$TEST_DEV" ] && TEST_DEV=`_readlink $TEST_DEV`
+[ -L "$SCRATCH_DEV" ] && SCRATCH_DEV=`_readlink $SCRATCH_DEV`
+[ -L "$SCRATCH_LOGDEV" ] && SCRATCH_LOGDEV=`_readlink $SCRATCH_LOGDEV`
+[ -L "$SCRATCH_RTDEV" ] && SCRATCH_RTDEV=`_readlink $SCRATCH_LOGDEV`
+
+# make sure this script returns success
+/bin/true
diff --git a/common.dump b/common.dump
new file mode 100644 (file)
index 0000000..05a7ca7
--- /dev/null
@@ -0,0 +1,868 @@
+##/bin/sh
+
+#
+# Functions useful for xfsdump/xfsrestore tests
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+# --- initializations ---
+rm -f $seq.full
+
+if [ -n "$DEBUGDUMP" ]; then
+  _dump_debug=-v5
+  _restore_debug=-v5
+  _invutil_debug=-d
+fi
+# Use dump/restore out of workareas
+PATH="../dump/dump:../dump/restore:../dump/invutil:$PATH"
+export PATH
+
+# status returned for not run tests
+NOTRUNSTS=2
+
+# name those directories
+dump_dir=$SCRATCH_MNT/dump.$$
+dump_file=$tmp.dumpfile
+dump_sdir=dump.$$
+restore_dir=$SCRATCH_MNT/restore.$$
+restore_sdir=restore.$$
+
+dumptape=$TAPE_DEV
+media_label="stress_tape_media"
+session_label="stress_$seq"
+
+nobody=4 # define this uid/gid as a number
+
+_need_to_be_root
+
+# install our cleaner
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# start inventory from a known base - move it aside for test
+if [ -d /var/xfsdump/inventory ]; then
+    if [ -d /var/xfsdump/inventory.$seq ]; then    
+       rm -rf /var/xfsdump/inventory.$seq
+    fi
+    mv /var/xfsdump/inventory /var/xfsdump/inventory.$seq
+fi
+
+
+#
+# do a remote/local mt
+#
+_mt()
+{
+    op=$1
+    if _isrmt; then  
+       # REMOTE
+       _rmthost=`echo $dumptape | awk -F: '{print $1}'`
+       _rmtdev=`echo $dumptape | awk -F: '{print $2}'`
+       rsh -n $_rmthost "mt -t $_rmtdev $op"
+       # Would have used src/testrmt but get
+        # permission denied from linux to linux for erase !?! 
+    else
+       #LOCAL
+       mt -t $dumptape $op
+    fi
+}
+
+_check_onl()
+{
+    _limit=10
+    i=0
+    while [ $i -lt $_limit ]; do  
+        echo "Checking online..." >>$seq.full
+       if _mt status >$tmp.status 2>&1; then
+           break; 
+       else
+           sleep 2 
+       fi
+       i=`expr $i + 1`
+    done
+
+
+    if [ $i -eq $_limit ]; then
+       echo "ERROR: mt -f $dumptape failed"
+       cat $tmp.status
+
+       echo "mt -f $dumptape failed" >$seq.notrun 
+       status=$NOTRUNSTS
+       exit
+    fi 
+
+
+    if egrep -i 'onl|ready' $tmp.status | grep -iv 'not ready' >/dev/null; then
+       :
+    else
+       echo "ERROR: $dumptape is not online"
+       cat $tmp.status
+
+       echo "dumptape, $dumptape, is not online" >$seq.notrun 
+       status=$NOTRUNSTS
+       exit
+    fi
+}
+
+_wait_tape()
+{
+    echo "Wait for tape, $dumptape, ..." >>$seq.full
+
+    i=0
+    while [ $i -lt 20 ]; do  
+        echo "Checking status..." >>$seq.full
+       if _mt status 2>&1 | tee -a $seq.full | egrep -i "onl|ready" >/dev/null; then
+           break; 
+       else
+           sleep 2 
+       fi
+       i=`expr $i + 1`
+    done
+}
+
+#
+# Keep trying so we know we really have rewound
+#
+_rewind()
+{
+    echo "Initiate rewind..." >>$seq.full
+    _wait_tape
+    _mt rewind >/dev/null
+    _wait_tape
+}
+
+#
+# Do a custom erase because: 
+# (i) some machines don't support it
+# (ii) some machines take forever to do it
+#
+_erase_soft()
+{
+    echo "Erasing tape" | tee -a $seq.full
+    _rewind
+    _mt weof 3
+#   src/testrmt -f $dumptape write
+    _rewind
+}
+
+_erase_hard()
+{
+    echo "Erasing tape" | tee -a $seq.full
+    _mt erase
+}
+
+_isrmt()
+{
+    echo $dumptape | grep ':' >/dev/null
+}
+
+#
+# Get tape ready
+#
+_set_variable()
+{
+    if _isrmt; then
+       :
+    else
+       # LOCAL
+       echo "Put scsi tape driver into variable block size mode"
+       mt -f $dumptape setblk 0
+    fi 
+}
+
+_require_tape()
+{
+    if [ $# -eq 0 ]; then
+       dumptape=$TAPE_DEV
+    else
+       dumptape=$1
+    fi
+
+    if [ -z "$dumptape" ]; then
+        echo "This test requires a dump tape - none was specified"
+       echo "No dump tape specified" >$seq.notrun 
+       status=$NOTRUNSTS
+       exit
+    fi
+
+    _check_onl
+    _set_variable
+}
+
+_error()
+{
+    echo "Error: $*" | tee -a $seq.full
+    echo "(see $seq.full for details)"
+    status=1
+    exit
+}
+
+_wipe_fs()
+{
+    _require_scratch
+
+    mkfs -t xfs -f $SCRATCH_DEV >>$seq.full  ||\
+       _error "mkfs failed"
+      
+    mount -t xfs $SCRATCH_DEV $SCRATCH_MNT >>$seq.full ||\
+       _error "mount failed"
+}
+
+# 
+# Cleanup created dirs and files
+# Called by trap
+#
+_cleanup()
+{
+    cd $here
+    rm -f $tmp.*
+
+    if [ -n "$DEBUGDUMP" ]; then
+        # save it for inspection
+       tar -zcvf $seq.inventory.tgz /var/xfsdump/inventory
+       ls -lR /var/xfsdump/inventory >$seq.inventory.ls
+    fi
+
+    # put inventory dir back
+    if [ -d /var/xfsdump/inventory.$seq ]; then
+        rm -rf /var/xfsdump/inventory # get rid of new one
+       mv /var/xfsdump/inventory.$seq /var/xfsdump/inventory
+    fi
+
+    if [ $status -ne $NOTRUNSTS ]; then
+       # Sleep added to stop _check_fs from complaining that the
+       # scratch_dev is still busy
+       sleep 10
+
+       _check_fs $SCRATCH_DEV
+    fi
+}
+
+_stable_fs()
+{
+#    umount $SCRATCH_MNT >/dev/null 
+#    mount $SCRATCH_MNT >/dev/null
+    sync; sync; sleep 15
+}
+
+#
+# Run stress/src/fsstress to create a mixture of 
+# files,dirs,links,symlinks
+#
+# Pinched from stress/013.
+#
+_create_dumpdir_stress()
+{
+    echo "Creating directory system to dump using src/fsstress."
+
+    _wipe_fs
+
+    _param="-f link=10 -f creat=10 -f mkdir=10 -f truncate=5 -f symlink=10"
+    _count=200
+    rm -rf $dump_dir
+    if ! mkdir $dump_dir; then
+        echo "    failed to mkdir $dump_dir"
+        status=1
+        exit
+    fi
+    echo ""
+    echo "-----------------------------------------------"
+    echo "fsstress : $_param"
+    echo "-----------------------------------------------"
+    if ! $here/src/fsstress $_param $FSSTRESS_AVOID -n $_count -d $dump_dir >$tmp.out 2>&1
+    then
+        echo "    fsstress (count=$_count) returned $? - see $seq.full"
+        
+        echo "--------------------------------------"       >>$here/$seq.full
+        echo "output from fsstress:"                        >>$here/$seq.full
+        echo "--------------------------------------"       >>$here/$seq.full
+        cat $tmp.out                                        >>$here/$seq.full
+        status=1
+    fi
+
+    _stable_fs
+}
+
+_mk_fillconfig1()
+{
+    cat <<End-of-File >$tmp.config
+# pathname     size in bytes   owner   group
+#
+small          10      $nobody $nobody
+big            102400  daemon  sys
+sub/small      10      bin     bin
+sub/big                102400  $nobody sys
+#
+sub/a          1       $nobody $nobody
+sub/b          2       $nobody $nobody
+sub/c          4       $nobody $nobody
+sub/d          8       $nobody $nobody
+sub/e          16      $nobody $nobody
+sub/f          32      $nobody $nobody
+sub/g          64      $nobody $nobody
+sub/h          128     $nobody $nobody
+sub/i          256     $nobody $nobody
+sub/j          512     $nobody $nobody
+sub/k          1024    $nobody $nobody
+sub/l          2048    $nobody $nobody
+sub/m          4096    $nobody $nobody
+sub/n          8192    $nobody $nobody
+#
+sub/a00                100     $nobody $nobody
+sub/b00                200     $nobody $nobody
+sub/c00                400     $nobody $nobody
+sub/d00                800     $nobody $nobody
+sub/e00                1600    $nobody $nobody
+sub/f00                3200    $nobody $nobody
+sub/g00                6400    $nobody $nobody
+sub/h00                12800   $nobody $nobody
+sub/i00                25600   $nobody $nobody
+sub/j00                51200   $nobody $nobody
+sub/k00                102400  $nobody $nobody
+sub/l00                204800  $nobody $nobody
+sub/m00                409600  $nobody $nobody
+sub/n00                819200  $nobody $nobody
+#
+sub/a000       1000    $nobody $nobody
+sub/e000       16000   $nobody $nobody
+sub/h000       128000  $nobody $nobody
+sub/k000       1024000 $nobody $nobody
+End-of-File
+}
+
+_mk_fillconfig2()
+{
+    cat <<End-of-File >$tmp.config
+# pathname     size in bytes
+#
+smalll         10      $nobody $nobody
+biggg          102400  $nobody $nobody
+sub/smalll     10      $nobody $nobody
+sub/biggg      102400  $nobody $nobody
+End-of-File
+}
+
+#
+# Create a bunch of directories/files of different sizes
+# filled with data.
+#
+# Pinched from stress/001.
+#
+_do_create_dumpdir_fill()
+{
+    echo "Creating directory system to dump using src/fill."
+
+    if mkdir -p $dump_dir
+    then
+       :
+    else
+       echo "Error: cannot mkdir \"$dump_dir\""
+       exit 1
+    fi
+    cd $dump_dir
+
+    $verbose && echo -n "Setup "
+    sed -e '/^#/d' $tmp.config \
+    | while read file nbytes owner group perms
+    do
+       dir=`dirname $file`
+       if [ "$dir" != "." ]
+       then
+           if [ ! -d $dir ]
+           then
+               if mkdir $dir
+               then
+                   :
+               else
+                   $verbose && echo
+                   echo "Error: cannot mkdir \"$dir\""
+                   exit 1
+               fi
+           fi
+       fi
+       rm -f $file
+       if $here/src/fill $file $file $nbytes
+       then
+           :
+       else
+           $verbose && echo
+           echo "Error: cannot create \"$file\""
+           exit 1
+       fi
+       if [ -n "$owner" -a -n "$group" ]; then
+           chown $owner.$group $file
+       fi
+       if [ -n "$perms" ]; then
+           chmod $perms $file
+       fi
+       $verbose && echo -n "."
+    done
+    $verbose && echo
+
+    cd $here
+}
+
+
+_create_dumpdir_fill()
+{
+    _wipe_fs
+    _mk_fillconfig1
+    _do_create_dumpdir_fill
+    _stable_fs
+}      
+
+_create_dumpdir_fill2()
+{
+    _wipe_fs
+    _mk_fillconfig2
+    _do_create_dumpdir_fill
+    _stable_fs
+}      
+
+
+
+#
+# Append a subset of the fill'ed files
+# So we can see if just these get dumped on an incremental
+#
+_append_dumpdir_fill()
+{
+    cd $dump_dir
+    cat <<End-of-File >$tmp.config
+# pathname
+#
+small  
+sub/big        
+#
+sub/a
+sub/c
+sub/e
+End-of-File
+    sed -e '/^#/d' $tmp.config \
+    | while read file
+    do
+        echo 'Extra text' >>$file
+    done
+
+    cd $here
+}
+
+_do_create_dump_symlinks()
+{
+    echo "Creating directory system of symlinks to dump."
+
+    if mkdir -p $dump_dir
+    then
+       :
+    else
+       echo "Error: cannot mkdir \"$dump_dir\""
+       exit 1
+    fi
+    cd $dump_dir
+
+    $verbose && echo -n "Setup "
+    sed -e '/^#/d' $tmp.config \
+    | while read file nbytes owner group owner2 group2 perms perms2
+    do
+       dir=`dirname $file`
+       if [ "$dir" != "." ]
+       then
+           if [ ! -d $dir ]
+           then
+               if mkdir $dir
+               then
+                   :
+               else
+                   $verbose && echo
+                   echo "Error: cannot mkdir \"$dir\""
+                   exit 1
+               fi
+           fi
+       fi
+       rm -f $file
+       touch $file
+
+       # Do chmod on symlink using umask.
+       # This won't do the right thing as it subtracts permissions.
+       # However, I don't care, as long as I get some different perms
+       # for testing.
+       if [ -n "$perms2" ]; then
+           omask=`umask`
+           umask $perms2
+       fi
+       ln -s $file $file-link
+       if [ -n "$perms2" ]; then
+           umask $omask        
+       fi
+
+       if [ -n "$owner" -a -n "$group" ]; then
+           chown $owner.$group $file
+       fi
+       if [ -n "$owner" -a -n "$group" ]; then
+           chown -h $owner.$group $file-link
+       fi
+       if [ -n "$perms" ]; then
+           chmod $perms $file
+       fi
+       $verbose && echo -n "."
+    done
+    $verbose && echo
+
+    cd $here
+}
+
+_mk_symlink_config()
+{
+    cat <<End-of-File >$tmp.config
+# path size    owner1  group1  owner2  group2  perm1   perm2 
+#
+a      0       $nobody $nobody daemon  sys     124     421
+b      0       daemon  sys     bin     bin     347     743
+sub/a  0       bin     bin     $nobody sys     777     777
+sub/b  0       $nobody sys     $nobody $nobody 367     763
+End-of-File
+}
+
+_create_dumpdir_symlinks()
+{
+    _wipe_fs
+    _mk_symlink_config
+    _do_create_dump_symlinks
+    _stable_fs
+}      
+
+#
+# Filter for ls
+# Filter out dates on symlinks
+#
+_ls_filter()
+{
+  $AWK_PROG '/^l/ { date = $8; sub(date,"DATE"); print}
+        {print}' \
+  | sed -e 's/total [0-9][0-9]*/total TOTAL/'
+}
+
+
+# 
+# Filter out the non-deterministic dump msgs from
+# xfsdump and xfsrestore
+#
+_dump_filter()
+{
+  sed \
+      -e "s/`hostname`/HOSTNAME/"   \
+      -e "s#$SCRATCH_DEV#SCRATCH_DEV#"    \
+      -e "s#$dumptape#TAPE_DEV#"    \
+      -e "s#$SCRATCH_MNT#SCRATCH_MNT#"    \
+      -e "s#$dump_file#DUMP_FILE#"  \
+      -e 's/id:[       ]*[0-9a-f-]*/id: ID/'  \
+      -e 's/time:[     ].*/time: TIME/'       \
+      -e 's/date:[     ].*/date: DATE/'       \
+      -e 's/dump begun .*/dump begun DATE/'    \
+      -e 's/[0-9][0-9]* seconds/SECS seconds/' \
+      -e '/: dump size/s/[1-9][0-9]*/NUM/'     \
+      -e '/dump size:/s/[1-9][0-9]*/NUM/'      \
+      -e '/media file size/s/[1-9][0-9]*/NUM/' \
+      -e '/\/dev\/tty/d' \
+      -e '/inventory session uuid/d' \
+
+}
+
+_invutil_filter()
+{
+  _dump_filter \
+  | sed \
+       -e 's/UUID[     ]*:[    ][0-9a-f-]*/UUID                :       ID/' \
+       -e 's/TIME OF DUMP[     ]*:.*/TIME OF DUMP      :       TIME/' \
+        -e 's/HOSTNAME:SCRATCH_MNT.*/HOSTNAME:SCRATCH_MNT/' \
+        -e 's#inventory/[0-9a-f-]*#inventory/UUID#' \
+
+}
+
+_dir_filter()
+{
+  sed \
+    -e "s#$dump_file#DUMP_FILE#"      \
+    -e "s#$SCRATCH_DEV#SCRATCH_DEV#"        \
+    -e "s#$dumptape#TAPE_DEV#"         \
+    -e "s#$dump_dir#DUMP_DIR#g"       \
+    -e "s#$restore_dir#RESTORE_DIR#g" \
+    -e "s#$SCRATCH_MNT#SCRATCH_MNT#g"       \
+    -e "s#$dump_sdir#DUMP_SUBDIR#g"   \
+    -e "s#$restore_sdir#RESTORE_SUBDIR#g" \
+
+}
+
+_parse_args()
+{
+    OPTIND=0
+    dump_args=""
+    while getopts "f:FL:o" c $*
+    do
+        case $c
+        in
+        f)
+            [ -z "$OPTARG" ] && _error "missing argument for -f"
+           dumptape=$OPTARG    
+            ;;
+        L)
+            [ -z "$OPTARG" ] && _error "missing argument for -L"
+           session_label=$OPTARG       
+            ;;
+       o)
+           dump_args="$dump_args -o"
+            ;;
+       F)
+           dump_args="$dump_args -F"
+            ;;
+       \?)
+            _error "invalid argument"
+            ;;
+        esac
+    done
+}
+
+
+#
+# Dump a subdir
+#
+_do_dump_sub()
+{
+    _parse_args $*
+
+    echo "Dumping to tape..."
+    opts="$_dump_debug$dump_args -s $dump_sdir -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
+    echo "xfsdump $opts" | _dir_filter  
+    xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
+}
+
+#
+# Do full level 0 dump
+#
+_do_dump()
+{
+    _parse_args $*
+
+    echo "Dumping to tape..."
+    opts="$_dump_debug$dump_args -l0 -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
+    echo "xfsdump $opts" | _dir_filter  
+    xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
+}
+
+
+#
+# Do full dump with -m
+#
+_do_dump_min()
+{
+    _parse_args $*
+
+    echo "Dumping to tape..."
+    onemeg=1048576
+    opts="$_dump_debug$dump_args -m -b $onemeg -l0 -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
+    echo "xfsdump $opts" | _dir_filter  
+    xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
+}
+
+#
+# Do level 1 incremental dump
+#
+_do_dump_incremental()
+{
+    _parse_args $*
+
+    echo "Dumping incrementally to tape..."
+    opts="$_dump_debug$dump_args -l1 -f $dumptape -M $media_label -L $session_label $SCRATCH_MNT"
+    echo "xfsdump $opts" | _dir_filter  
+    xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
+}
+
+#
+# Do full dump to file
+#
+_do_dump_file()
+{
+    _parse_args $*
+
+    echo "Dumping to file..."
+    opts="$_dump_debug$dump_args -f $dump_file -M $media_label -L $session_label $SCRATCH_MNT"
+    echo "xfsdump $opts" | _dir_filter  
+    xfsdump $opts 2>&1 | tee -a $seq.full | _dump_filter
+}
+
+
+_prepare_restore_dir()
+{
+    rm -rf $restore_dir
+    if ! mkdir $restore_dir; then
+       echo "    failed to mkdir $restore_dir"
+       status=1
+       exit
+    fi
+}
+
+
+#
+# Get tape ready and restore dir
+#
+_prepare_restore()
+{
+    _prepare_restore_dir
+
+    echo "Rewinding tape"
+    _rewind
+}
+
+#
+# Restore the tape into $restore_dir
+#
+_do_restore()
+{
+    _parse_args $*
+    _prepare_restore
+
+
+    echo "Restoring from tape..."
+    opts="$_restore_debug$dump_args -f $dumptape  -L $session_label $restore_dir"
+    echo "xfsrestore $opts" | _dir_filter  
+    xfsrestore $opts 2>&1 | tee -a $seq.full | _dump_filter
+}
+
+#
+# Restore the tape into $restore_dir using -m
+#
+_do_restore_min()
+{
+    _parse_args $*
+    _prepare_restore
+
+    echo "Restoring from tape..."
+    onemeg=1048576
+    opts="$_restore_debug$dump_args -m -b $onemeg -f $dumptape  -L $session_label $restore_dir"
+    echo "xfsrestore $opts" | _dir_filter  
+    xfsrestore $opts 2>&1 | tee -a $seq.full | _dump_filter
+}
+
+#
+# Restore the tape from a dump file
+#
+_do_restore_file()
+{
+    _parse_args $*
+    _prepare_restore_dir
+
+    echo "Restoring from file..."
+    opts="$_restore_debug$dumpargs -f $dump_file  -L $session_label $restore_dir"
+    echo "xfsrestore $opts" | _dir_filter  
+    xfsrestore $opts 2>&1 | tee -a $seq.full | _dump_filter
+}
+
+#
+# Do xfsdump piped into xfsrestore - xfsdump | xfsrestore
+#
+# Use -s as we want to dump and restore to the same xfs partition
+#
+_do_dump_restore()
+{
+    _parse_args $*
+    _prepare_restore_dir
+    echo "xfsdump|xfsrestore ..."
+    restore_opts="$_restore_debug - $restore_dir"
+    dump_opts="$_dump_debug$dump_args -s $dump_sdir - $SCRATCH_MNT"
+    echo "xfsdump $dump_opts | xfsrestore $restore_opts" | _dir_filter  
+    xfsdump $dump_opts 2>$tmp.dump.mlog | xfsrestore $restore_opts 2>&1 | tee -a $seq.full | _dump_filter
+    _dump_filter <$tmp.dump.mlog
+}
+
+#
+# Compare dumped subdirectory with restored dir
+# using ls -lR.
+# Thus no contents are compared but permissions, sizes,
+# owners, etc... are.
+#
+_ls_compare_sub()
+{
+    #
+    # verify we got back what we dumped
+    #
+    echo "Comparing listing of dump directory with restore directory"
+    ls -lR $dump_dir | tee -a $seq.full | _ls_filter >$tmp.dump_dir
+    ls -lR $restore_dir/$dump_sdir | tee -a $seq.full | _ls_filter \
+    | sed -e "s#$restore_sdir\/##" >$tmp.restore_dir
+
+    diff -cs $tmp.dump_dir $tmp.restore_dir | sed -e "s#$tmp#TMP#g"
+}
+
+
+#
+# Compare using recursive diff the files of the dumped
+# subdirectory.
+# This one will compare the contents.
+#
+_diff_compare_sub()
+{
+    echo "Comparing dump directory with restore directory"
+    diff -rs $dump_dir $restore_dir/$dump_sdir | _dir_filter
+}
+
+#
+# Compare using recursive diff the files of the dumped
+# filesystem
+#
+_diff_compare()
+{
+    echo "Comparing dump directory with restore directory"
+    diff -rs $SCRATCH_MNT $restore_dir | _dir_filter
+}
+
+#
+# Check out the dump inventory
+#
+_dump_inventory()
+{
+    xfsdump $_dump_debug -I | tee -a $seq.full | _dump_filter 
+}
+
+#
+# Do the xfsinvutil cmd with debug and filters
+# Need to set variable: "$middate" to the invutil date 
+#
+_do_invutil()
+{
+    host=`hostname`
+    echo "xfsinvutil $_invutil_debug -M $host:$SCRATCH_MNT \"$middate\" $*" >$seq.full
+    xfsinvutil $_invutil_debug -M $host:$SCRATCH_MNT "$middate" $* \
+    | tee -a $seq.full | _invutil_filter
+}
+
+# make sure this script returns success
+/bin/true
diff --git a/common.filter b/common.filter
new file mode 100644 (file)
index 0000000..122cb0e
--- /dev/null
@@ -0,0 +1,180 @@
+##/bin/sh
+
+#
+# standard filters
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+#
+
+# Checks that given_value is in range of correct_value +/- tolerance.
+# Tolerance can be an absolute value or a percentage of the correct value
+# (see examples with tolerances below).
+# Outputs suitable message to stdout if it's not in range.
+#
+# A verbose option, -v, may be used as the LAST argument
+# 
+# e.g. 
+# foo: 0.0298 = 0.03 +/- 5%
+# _within_tolerance "foo" 0.0298 0.03 5%  
+# 
+# foo: 0.0298 = 0.03 +/- 0.01
+# _within_tolerance "foo" 0.0298 0.03 0.01
+#
+# foo: 0.0298 = 0.03 -0.01 +0.002
+# _within_tolerance "foo" 0.0298 0.03 0.01 0.002
+#
+# foo: verbose output of 0.0298 = 0.03 +/- 5% 
+# _within_tolerance "foo" 0.0298 0.03 5% -v 
+_within_tolerance()
+{
+  _name=$1
+  _given_val=$2
+  _correct_val=$3
+  _mintol=$4
+  _maxtol=$_mintol
+  _verbose=0
+  _debug=false
+
+  # maxtol arg is optional
+  # verbose arg is optional
+  if [ $# -ge 5 ]
+  then 
+     if [ "$5" = "-v" ]
+     then
+       _verbose=1
+     else
+        _maxtol=$5
+     fi
+  fi
+  if [ $# -ge 6 ]
+  then
+     [ "$6" = "-v" ] && _verbose=1
+  fi
+
+  # find min with or without %
+  _mintolerance=`echo $_mintol | sed -e 's/%//'` 
+  if [ $_mintol = $_mintolerance ]
+  then 
+      _min=`echo "scale=5; $_correct_val-$_mintolerance" | bc`
+  else
+      _min=`echo "scale=5; $_correct_val-$_mintolerance*0.01*$_correct_val" | bc`
+  fi
+
+  # find max with or without %
+  _maxtolerance=`echo $_maxtol | sed -e 's/%//'` 
+  if [ $_maxtol = $_maxtolerance ]
+  then 
+      _max=`echo "scale=5; $_correct_val+$_maxtolerance" | bc`
+  else
+      _max=`echo "scale=5; $_correct_val+$_maxtolerance*0.01*$_correct_val" | bc`
+  fi
+
+  $_debug && echo "min = $_min"
+  $_debug && echo "max = $_max"
+
+  cat <<EOF >$tmp.bc.1
+scale=5;
+if ($_min <= $_given_val) 1;
+if ($_min > $_given_val) 0; 
+EOF
+
+  cat <<EOF >$tmp.bc.2
+scale=5;
+if ($_given_val <= $_max) 1;
+if ($_given_val > $_max) 0;
+EOF
+
+  _above_min=`bc <$tmp.bc.1`
+  _below_max=`bc <$tmp.bc.2`
+
+  rm -f $tmp.bc.[12]
+
+  _in_range=`expr $_above_min \& $_below_max` 
+
+  # fix up min, max precision for output
+  # can vary for 5.3, 6.2
+  _min=`echo $_min | sed -e 's/0*$//'` # get rid of trailling zeroes
+  _max=`echo $_max | sed -e 's/0*$//'` # get rid of trailling zeroes
+
+  if [ $_in_range -eq 1 ] 
+  then
+       [ $_verbose -eq 1 ] && echo $_name is in range
+       return 0
+  else
+       [ $_verbose -eq 1 ] && echo $_name has value of $_given_val
+       [ $_verbose -eq 1 ] && echo $_name is NOT in range $_min .. $_max       
+       return 1
+  fi
+}
+
+# ctime(3) dates
+#
+_filter_date()
+{
+    sed \
+       -e 's/[A-Z][a-z][a-z] [A-z][a-z][a-z]  *[0-9][0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9]$/DATE/'
+}
+
+# prints filtered output on stdout, values (use eval) on stderr
+# 
+_filter_mkfs()
+{
+    set -
+    perl -ne '
+    if (/^meta-data=([\w|\/]+)\s+isize=(\d+)\s+agcount=(\d+), agsize=(\d+) blks/) {
+       print STDERR "ddev=$1\nisize=$2\nagcount=$3\nagsize=$4\n";
+       print STDOUT "meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks\n";
+    }
+    if (/^data\s+=\s+bsize=(\d+)\s+blocks=(\d+), imaxpct=(\d+)/) {
+       print STDERR "dbsize=$1\ndblocks=$2\nimaxpct=$3\n";
+       print STDOUT "data     = bsize=XXX blocks=XXX, imaxpct=PCT\n";
+    }
+    if (/^\s+=\s+sunit=(\d+)\s+swidth=(\d+) blks, unwritten=(\d)/) {
+       print STDERR "sunit=$1\nswidth=$2\nunwritten=$3\n";
+       print STDOUT "         = sunit=XXX swidth=XXX, unwritten=X\n";
+    }
+    if (/^naming\s+=version\s+(\d+)\s+bsize=(\d+)/) {
+       print STDERR "dirversion=$1\ndirbsize=$2\n";
+       print STDOUT "naming   =VERN bsize=XXX\n";
+    }
+    if (/^log\s+=(internal log|[\w|\/]+)\s+bsize=(\d+)\s+blocks=(\d+)/) {
+       print STDERR "ldev=\"$1\"\nlbsize=$2\nlblocks=$3\n";
+       print STDOUT "log      =LDEV bsize=XXX blocks=XXX\n";
+    }
+    if (/^realtime\s+=([\w|\/]+)\s+extsz=(\d+)\s+blocks=(\d+), rtextents=(\d+)/) {
+       print STDERR "rtdev=$1\nrtextsz=$2\nrtblocks=$3\nrtextents=$4\n";
+       print STDOUT "realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX\n";
+    }'
+}
+
+# make sure this script returns success
+/bin/true
diff --git a/common.quota b/common.quota
new file mode 100644 (file)
index 0000000..54b49cf
--- /dev/null
@@ -0,0 +1,91 @@
+##/bin/sh
+#
+# Functions useful for quota tests
+# 
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+# 
+# checks that the XFS quota support in the kernel is enabled
+# and that we have valid quota user tools installed.
+# 
+_require_quota()
+{
+    [ ! -x /usr/sbin/repquota ] && _notrun "Quota user tools not installed"
+
+    /usr/sbin/repquota -m -s -a >/dev/null 2>&1
+    [ $? -ne 0 ] && _notrun "Installed quota tools do not support XFS"
+
+    [ ! -f /proc/fs/xfs/xqm ] && _notrun "Kernel does not support XFS quota"
+}
+
+# create a file as a specific user (uid)
+# takes filename, id, type (u/g), blocksize, blockcount
+# 
+_file_as_id()
+{
+    [ $# != 5 ] && _notrun "broken call to _file_as_id in test $seq"
+
+    if [ $3 = u ]
+    then
+       magik='$>'      # perlspeak for effective uid
+    elif [ $3 = g ]
+    then
+       magik='$)'      # perlspeak for effective gid
+    else
+       _notrun "broken type in call to _file_as_id in test $seq"
+    fi
+
+    perl <<EOF
+       \$| = 1;
+       $magik = $2;
+       exec "dd if=/dev/zero of=$1 bs=$4 count=$5 >>$seq.full 2>&1";
+EOF
+}
+
+_choose_uid()
+{
+    perl -ne '@a = split(/:/); END { print $a[2]; }' /etc/passwd
+}
+
+_choose_gid()
+{
+    perl -ne '@a = split(/:/); END { print $a[2]; }' /etc/group
+}
+
+_filter_repquota()
+{
+    perl -ne 's/^(\w+)\s+([-|+])/[NAME]    \2/g; print'
+}
+
+
+# make sure this script returns success
+/bin/true
diff --git a/common.rc b/common.rc
new file mode 100644 (file)
index 0000000..a58759e
--- /dev/null
+++ b/common.rc
@@ -0,0 +1,529 @@
+##/bin/sh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+# we need common.config
+if ! . ./common.config
+then
+    echo "$iam: failed to source common.config"
+    exit 1
+fi
+
+# awk
+AWK_PROG=gawk
+
+# ps
+PS_HAVE_BSD=false
+PS_ALL_FLAGS=-efw
+
+# host os
+PLATFORM=linux
+
+# extra parameters for fsstress
+FSSTRESS_AVOID="-f resvsp=0 -f unresvsp=0"
+
+export AWK_PROG PS_HAVE_BSD PS_ALL_FLAGS PLATFORM
+
+# we override mount so we can specify mount options
+
+mount()
+{
+    case "$*"
+    in
+        *remount*)
+            /bin/mount $*
+            ;;
+        *ext2*)
+            /bin/mount $*
+            ;;
+        *xfs*)
+            /bin/mount $* $MOUNT_OPTIONS
+            ;;
+        *)
+            /bin/mount $*
+            ;;
+    esac
+}
+
+#
+
+_get_pids_by_name()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _get_pids_by_name process-name" 1>&2
+       exit 1
+    fi
+
+    # Algorithm ... all ps(1) variants have a time of the form MM:SS or
+    # HH:MM:SS before the psargs field, use this as the search anchor.
+    #
+    # Matches with $1 (process-name) occur if the first psarg is $1
+    # or ends in /$1 ... the matching uses sed's regular expressions,
+    # so passing a regex into $1 will work.
+
+    ps $PS_ALL_FLAGS \
+    | sed -n \
+       -e 's/$/ /' \
+       -e 's/[         ][      ]*/ /g' \
+       -e 's/^ //' \
+       -e 's/^[^ ]* //' \
+       -e "/[0-9]:[0-9][0-9]  *[^ ]*\/$1 /s/ .*//p" \
+       -e "/[0-9]:[0-9][0-9]  *$1 /s/ .*//p"
+}
+
+# fqdn for localhost
+#
+_get_fqdn()
+{
+    host=`hostname`
+    nslookup $host | $AWK_PROG '{ if ($1 == "Name:") print $2 }'
+}
+
+# fix malloc libs output
+#
+_fix_malloc()
+{
+    # filter out the Electric Fence notice
+    perl -e '
+        while (<>) {
+            if (defined $o && /^\s+Electric Fence/) {
+                chomp($o);
+                print "$o";
+                undef $o;
+                next;
+            }
+            print $o if (defined $o);
+
+            $o=$_;
+        }
+        print $o if (defined $o);
+    '
+}
+
+# check if run as root
+#
+_need_to_be_root()
+{
+    id=`id | sed -e 's/(.*//' -e 's/.*=//'`
+    if [ "$id" -ne 0 ]
+    then
+       echo "Arrgh ... you need to be root (not uid=$id) to run this test"
+       exit 1
+    fi
+}
+
+
+#
+# _df_device : get an IRIX style df line for a given device 
+#
+#       - returns "" if not mounted
+#       - returns fs type in field two (ala IRIX)
+#       - joins line together if split by fancy df formatting
+#       - strips header etc
+#
+
+_df_device()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _df_device device" 1>&2
+       exit 1
+    fi
+    
+    df -T 2>/dev/null | $AWK_PROG -v what=$1 '
+        match($1,what) && NF==1 { 
+            v=$1
+            getline
+            print v, $0
+            exit
+        }
+        match($1,what) {
+            print
+            exit
+        }
+    '
+}
+
+#
+# _df_dir : get an IRIX style df line for device where a directory resides
+#
+#       - returns fs type in field two (ala IRIX)
+#       - joins line together if split by fancy df formatting
+#       - strips header etc
+#
+
+_df_dir()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _df_dir device" 1>&2
+       exit 1
+    fi
+    
+    df -T $1 2>/dev/null | $AWK_PROG -v what=$1 '
+        NR == 2 && NF==1 { 
+            v=$1
+            getline 
+            print v, $0;
+            exit 0
+        }
+        NR == 2 {
+            print;
+            exit 0
+        }
+        {}
+    '
+    # otherwise, nada
+}
+
+# return percentage used disk space for mounted device
+
+_used()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _used device" 1>&2
+       exit 1
+    fi
+    
+    _df_device $1 | $AWK_PROG '{ sub("%", "") ; print $6 }'
+}
+
+# return the FS type of a mounted device
+#
+_fs_type()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _fs_type device" 1>&2
+       exit 1
+    fi
+    
+    _df_device $1 | $AWK_PROG '{ print $2 }'
+}
+
+# return the FS mount options of a mounted device
+#
+_fs_options()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _fs_options device" 1>&2
+       exit 1
+    fi
+    
+    $AWK_PROG -v dev=$1 '
+        match($1,dev) { print $4 }
+    ' </proc/mounts
+    
+}
+
+# returns device number if a file is a block device
+#
+_is_block_dev()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _is_block_dev dev" 1>&2
+       exit 1
+    fi
+    
+    [ -b $1 ] && src/lstat64 $1 | $AWK_PROG '/Device type:/ { print $9 }'
+}
+
+# bail out, setting up .notrun file
+# 
+_notrun()
+{
+    echo "$*" >$seq.notrun
+    status=0
+    exit
+}
+
+# just plain bail out
+# 
+_fail()
+{
+    echo "$*" | tee -a $seq.full
+    echo "(see $seq.full for details)"
+    status=1
+    exit 1
+}
+
+# this test needs a scratch partition - check we're ok & unmount it
+# 
+_require_scratch()
+{
+
+    if [ -z "$SCRATCH_DEV" -o "`_is_block_dev $SCRATCH_DEV`" = "" ]
+    then
+        _notrun "this test requires a valid \$SCRATCH_DEV"
+    fi
+    
+    if [ "`_is_block_dev $SCRATCH_DEV`" = "`_is_block_dev $TEST_DEV`" ]
+    then
+        _notrun "this test requires a valid \$SCRATCH_DEV"
+    fi
+    
+    # mounted?
+    if mount | grep -q $SCRATCH_DEV
+    then 
+        # if it's mounted, make sure its on $SCRATCH_MNT
+        if ! mount | grep $SCRATCH_DEV | grep -q $SCRATCH_MNT
+        then 
+            echo "\$SCRATCH_DEV is mounted but not on \$SCRATCH_MNT - aborting"
+            exit 1
+        fi
+        
+        # and then unmount it
+    
+        if ! umount $SCRATCH_DEV
+        then
+            echo "failed to unmount $SCRATCH_DEV"
+            exit 1
+        fi
+    fi
+    
+    # should be ok now
+
+}
+
+# this test needs a logdev 
+# 
+_require_logdev()
+{
+    if [ -z "$SCRATCH_LOGDEV" -o ! -b "$SCRATCH_LOGDEV" ]
+    then
+        _notrun "This test requires a valid \$SCRATCH_LOGDEV" 
+    fi
+}
+
+# this test requires loopback device support
+# 
+_require_loop()
+{
+    if grep loop /proc/devices >/dev/null 2>&1
+    then
+       :
+    else
+       _notrun "This test requires loopback device support"
+    fi
+}
+
+
+# check that a FS is mounted as XFS. if so, return mount point
+#
+_xfs_mounted()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _xfs_mounted device" 1>&2
+       exit 1
+    fi
+    
+    device=$1
+    
+    if mount | grep $device | $AWK_PROG '
+        /type xfs/  { print $3 ; exit 0 }
+        END         { exit 1 }
+    '
+    then
+        echo "_xfs_mounted: $device is not a mounted XFS FS"
+        exit 1
+    fi
+}
+
+# remount a FS to a new mode (ro or rw)
+#
+
+_remount()
+{
+    if [ $# -ne 2 ]
+    then
+       echo "Usage: _remount device ro/rw" 1>&2
+       exit 1
+    fi
+    device=$1
+    mode=$2
+    
+    if ! mount -o remount,$mode $device
+    then
+        echo "_remount: failed to remount filesystem on $device as $mode"
+        exit 1
+    fi
+    
+    # we might like to check here later
+    #options=`_fs_options $device`
+
+}
+
+# run xfs_check on a FS. 
+#
+# if the filesystem is mounted, it's either remounted ro before being
+# checked or it's unmounted and then remounted
+#
+
+USE_REMOUNT=0
+
+_check_fs()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _check_fs device" 1>&2
+       exit 1
+    fi
+    
+    device=$1
+    type=`_fs_type $device`
+    ok=1
+    
+    if [ "$type" = "xfs" ]
+    then
+        # mounted... 
+        
+        if [ $USE_REMOUNT -eq 0 ]
+        then
+            mountpoint=`_xfs_mounted $device`
+            umount $device
+        else
+            _remount $device ro
+        fi
+    fi
+
+    xfs_logprint -t $device 2>&1 | tee $tmp.fs_check | grep -q "<CLEAN>"
+    if [ $? -ne 0 ]
+    then
+        echo "_check_fs: filesystem on $device has dirty log (see $seq.full)"
+        
+        echo "_check_fs: filesystem on $device has dirty log"   >>$seq.full
+        echo "*** xfs_logprint -t output ***"                   >>$seq.full
+        cat $tmp.fs_check                                       >>$seq.full
+        echo "*** end xfs_logprint output"                      >>$seq.full
+        
+        ok=0
+    fi
+        
+    
+    xfs_check $device 2>&1 | _fix_malloc >$tmp.fs_check 
+    if [ -s $tmp.fs_check ]
+    then
+        echo "_check_fs: filesystem on $device is inconsistent (c) (see $seq.full)"
+        
+        echo "_check_fs: filesystem on $device is inconsistent" >>$seq.full
+        echo "*** xfs_check output ***"                         >>$seq.full
+        cat $tmp.fs_check                                       >>$seq.full
+        echo "*** end xfs_check output"                         >>$seq.full
+        
+        ok=0
+    fi
+    
+    if ! xfs_repair -n $device >$tmp.fs_check 2>&1
+    then
+        echo "_check_fs: filesystem on $device is inconsistent (r) (see $seq.full)"
+        
+        echo "_check_fs: filesystem on $device is inconsistent" >>$seq.full
+        echo "*** xfs_repair -n output ***"                     >>$seq.full
+        cat $tmp.fs_check | _fix_malloc                         >>$seq.full
+        echo "*** end xfs_repair output"                        >>$seq.full
+        
+        ok=0
+    fi
+    rm -f $tmp.fs_check
+    
+    if [ $ok -eq 0 ]
+    then
+        echo "*** mount output ***"                             >>$seq.full
+        mount                                                   >>$seq.full
+        echo "*** end mount output"                             >>$seq.full
+    fi
+    
+    if [ "$type" = "xfs" ]
+    then
+        # mounted... 
+        if [ $USE_REMOUNT -eq 0 ]
+        then
+            if ! mount -t xfs $device $mountpoint
+            then
+                echo "!!! failed to remount $device on $mountpoint"
+                ok=0
+            fi
+        else
+            _remount $device rw
+        fi
+    fi
+    
+    [ $ok -eq 0 ] && exit 1
+    
+}
+
+################################################################################
+
+[ -d /usr/bsd ] && PATH=$PATH:/usr/bsd
+[ -d /usr/freeware/bin ] && PATH=$PATH:/usr/freeware/bin
+
+if [ "$iam" != new ]
+then
+
+    # make some further configuration checks here
+    
+    if [ "$TEST_DEV" = ""  ]
+    then
+        echo "common.rc: Error: \$TEST_DEV is not set"
+        exit 1
+    fi
+    
+    if [ "`_fs_type $TEST_DEV`" != "xfs" ]
+    then
+        echo "common.rc: Error: \$TEST_DEV ($TEST_DEV) is not a MOUNTED XFS filesystem"
+        df -T $TEST_DEV
+        exit 1
+    fi
+
+fi
+
+# check for some required biunaries on our $PATH
+#
+for exec in mkfs.xfs xfs_logprint xfs_check xfs_repair xfs_db
+do
+    if which $exec >/dev/null 2>&1 
+    then
+       :
+    else
+       echo "common.rc: cannot find $exec on \$PATH=$PATH"
+       exit 1
+    fi
+done
+
+# make sure this script returns success
+/bin/true
diff --git a/common.repair b/common.repair
new file mode 100644 (file)
index 0000000..635e1e1
--- /dev/null
@@ -0,0 +1,103 @@
+##/bin/sh
+
+#
+# Functions useful for xfs_repair tests
+# 
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+_zero_position()
+{
+       value=$1
+       struct="$2"
+
+       # set values for off/len variables provided by db
+       eval `xfs_db -r -c "$struct" -c stack $SCRATCH_DEV | perl -ne '
+               if (/byte offset (\d+), length (\d+)/) {
+                       print "offset=$1\nlength=$2\n"; exit
+               }'`
+       if [ -z "$offset" -o -z "$length" ]; then
+               echo "cannot calculate offset ($offset) or length ($length)"
+               exit
+       fi
+       length=`expr $length / 512`
+       src/devzero -v $value -b 1 -n $length -o $offset $SCRATCH_DEV
+}
+
+_filter_repair()
+{
+       perl -ne '
+# for sb
+/- agno = / && next;   # remove each AG line (variable number)
+s/(pointer to) (\d+)/\1 INO/;
+s/(sb root inode value) (\d+)/\1 INO/;
+s/(realtime bitmap inode) (\d+)/\1 INO/;
+s/(realtime summary inode) (\d+)/\1 INO/;
+s/(inconsistent with calculated value) (\d+)/\1 INO/;
+s/\.+(found)/\1/g;     # remove "searching" output
+# for agf + agi
+s/(bad length -{0,1}\d+ for ag. 0, should be) (\d+)/\1 LENGTH/;
+s/(bad length # -{0,1}\d+ for ag. 0, should be) (\d+)/\1 LENGTH/;
+s/(bad agbno) (\d+)/\1 AGBNO/g;
+s/(max =) (\d+)/\1 MAX/g;
+# for root inos
+s/(on inode) (\d+)/\1 INO/g;
+s/(imap claims a free inode) (\d+)/\1 INO/;
+s/(cleared root inode) (\d+)/\1 INO/;
+s/(resetting inode) (\d+)/\1 INO/;
+s/(disconnected dir inode) (\d+)/\1 INO/;
+       print;'
+}
+
+_filter_dd()
+{
+       fgrep -v records        # lose records in/out lines
+}
+
+# do some controlled corrupting & ensure repair recovers us
+# 
+_check_repair()
+{
+       value=$1
+       structure="$2"
+       _zero_position $value "$structure"
+       xfs_repair $SCRATCH_DEV 2>&1 | _filter_repair
+       # some basic sanity checks...
+       _check_fs $SCRATCH_DEV
+       mount -t xfs $SCRATCH_DEV $SCRATCH_MNT              #mount
+       dd if=/bin/sh of=$SCRATCH_MNT/sh 2>&1 |_filter_dd   #open,write
+       dd if=$SCRATCH_MNT/sh of=/dev/null 2>&1 |_filter_dd #read
+       rm -f $SCRATCH_MNT/sh                               #unlink
+       umount $SCRATCH_MNT                                 #umount
+}
+
+# make sure this script returns success
+/bin/true
diff --git a/crash/README b/crash/README
new file mode 100644 (file)
index 0000000..36f2ec6
--- /dev/null
@@ -0,0 +1,151 @@
+############
+# xfscrash #  crash testing setup for XFS
+############
+
+*** disclaimers ***
+
+    work-in-progress, buyer-beware, your-mileage-may-vary, this-is-a-hack
+
+*** what xfscrash does ***
+
+    xfscrash allows realistic testing of XFS log recovery and XFS check/repair
+    by generating log activity on an XFS partition, then rebooting the machine
+    at a random point. When the machine comes back up, xfscrash is restarted
+    and then tests either the log recovery or xfs_repair on the dirtied
+    filesystem. All going well the process continues.
+
+*** getting ready for crash testing ***
+
+    Most filesystems (ext2 included) can't withstand having the machine
+    they're running on rebooted while they're active. So the crash test
+    machine needs to have all filesystems other than the test FS mounted
+    read-only so they won't get trashed when the machine reboots.
+
+*** mouting FSes read-only ***
+
+    Following is a recipe for making a redhat linux (6.2) machine with a single
+    ext2 FS mounted on root able to be booted read-only. Your Mileage May
+    Vary - don't try this on an important machine.
+
+    The idea is to move anything that needs to be r/w into the /initrd_init
+    directory, replacing the moved directories with links to the moved ones.
+    That way the /initrd_init directory may be copied to a ramdisk, and
+    mounted over /initrd on the root FS which never gets remounted r/w.
+
+        # go to single user
+        init 1
+
+        # make a mount point for the ramdisk
+        mkdir /initrd
+
+        # link across to the /initrd_init directory for when 
+        # the ramdisk isn't mounted
+        ln -s /initrd_init/dev .
+        ln -s /initrd_init/etc .
+        ln -s /initrd_init/proc .
+        ln -s /initrd_init/sbin .
+        ln -s /initrd_init/tmp .
+        ln -s /initrd_init/var .
+
+        # make the /initrd_init directory
+        mkdir /initrd_init
+        cd /initrd_init
+
+
+        # move /dev
+        mv /dev .
+        ln -s /dev /initrd/dev
+
+        # move /etc
+        mv /etc .
+        ln -s /etc /initrd/etc
+
+        # make proc mount
+        mkdir proc 
+
+        # move /tmp
+        mkdir tmp
+        rm -rf /tmp
+        ln -s /tmp /initrd/tmp
+
+        # link /sbin 
+        ln -s /sbin .
+
+        # setup a tree for parts of /var
+        mkdir var var/cache var/lock var/lock/console var/lock/subsys
+        mkdir var/log var/preserve var/run 
+
+        touch /var/run/utmp /var/log/utmp /var/log/wtmp 
+
+        # move parts of /var
+        rm -rf /var/cache /var/lock /var/log /var/preserve /var/run
+        ln -s /initrd/var/cache /var/cache
+        ln -s /initrd/var/lock /var/lock
+        ln -s /initrd/var/log /var/log
+        ln -s /initrd/var/preserve /var/preserve
+        ln -s /initrd/var/run /var/run
+
+        # make a mount for /var/shm
+        mkdir var/shm 
+        ln -s /var/shm /initrd/var/shm
+
+        # move /var/spool
+        mkdir var/spool
+        mkdir var/spool/mail var/spool/anacron var/spool/at var/spool/lpd
+        mkdir var/spool/rwho var/spool/mqueue var/spool/cron
+        rm -rf /var/spool
+        ln -s /var/spool /initrd/var/spool
+
+        # move /var/tmp
+        mkdir var/tmp
+        rm -rf /var/tmp
+        ln -s /var/tmp /initrd/var/tmp
+
+        # trim /dev - too many inodes here - remove anything you don't need
+        # (small ramdisk has a small number of inodes)
+        rm -rf /initrd/dev/<....>   
+
+    All going well, all the directories you've made should link through
+    /initrd and into /initrd_init, and the machine should come back up
+    if you restart it.
+
+    You want to keep the contents of /initrd_init to a minimum because
+    this stuff has to fit into the ramdisk.
+
+*** getting the ramdisk going ***
+
+    See the rc.sysinit file for some details of what to do to get the
+    ro-root/ramdisk up and running.
+
+    Once everything is going, the root FS should never be remounted to
+    r/w on boot and should be in r/o mode when the machine comes up.
+    
+    All going well, any open files have been redirected through the
+    symlinks onto the ramdisk, so you should be able to remount the
+    root FS to r/w and then remount it back to r/o.
+    
+    Since there's no r/w filesystems mounted, it should be ok to 
+    reboot the machine with 'reboot -fn' and everything should come
+    back without dirty filesystems and without having to fsck.
+    
+*** starting xfscrash ***
+
+    The simplest way to restart xfscrash on reboot is to start it
+    in the background from rc.local. The script logs to /dev/tty1,
+    /dev/console & a logfile by default, so the output should be
+    easy to find.
+    
+    Link the xfscrash directory off an NFS mounted FS so you can make
+    changes while the machine is rebooting and so you can touch the
+    'stop' and 'start' control files.
+
+    To configure the system, change the parameters in the configuration
+    section of the 'xfscrash' script.
+    
+    To start the system, touch the 'start' control file and then either
+    reboot or manually run the 'xfscrash' script.
+    
+    To stop the system, touch the 'stop' control file and wait for the
+    next cycle to start when the control file will be checked and
+    the test terminated.
+
diff --git a/crash/rc.sysinit b/crash/rc.sysinit
new file mode 100644 (file)
index 0000000..faf5af6
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+# xfscrash - control the XFS crash tests
+#
+
+# this is an example of what to add to rc.sysinit on a redhat linux
+# system to get the ro-root/ramdisk system up and running
+
+if [ -f /initrd.active ]
+then
+       echo "*** MAKE RAMDISK ***"
+       dd if=/dev/zero of=/dev/ram0 bs=1024k count=4
+       mkfs -i 1024 /dev/ram0 4096
+       echo "*** MOUNT RAMDISK ***"
+       mount -n -w /dev/ram0 /mnt
+       echo "*** INIT RAMDISK ***"
+       cp -a /initrd_init/* /mnt
+       rm -f /mnt/00_INITRD_REAL
+       touch /mnt/00_INITRD_RAMDISK
+       umount -n /mnt
+       echo "*** REMOUNT RAMDISK ***"
+       mount -n /dev/ram0 /initrd
+
+       echo "*** FIX MTAB ***"
+       >/etc/mtab
+       rm -f /etc/mtab~ /etc/mtab~~
+       mount -f -o ro /
+       mount -f -o rw /dev/ram0 /initrd
+else
+        # old code
+        
+       # Remount the root filesystem read-write.
+       action "Remounting root filesystem in read-write mode" mount -n -o remount,rw /
+
+       # Clear mtab
+       >/etc/mtab
+
+       # Remove stale backups
+       rm -f /etc/mtab~ /etc/mtab~~
+
+       # Enter root and /proc into mtab.
+       mount -f /
+       mount -f /proc
+
+fi
diff --git a/crash/xfscrash b/crash/xfscrash
new file mode 100755 (executable)
index 0000000..d151c4a
--- /dev/null
@@ -0,0 +1,552 @@
+#!/bin/sh
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+# xfscrash - control the XFS crash tests
+#
+
+  #######################
+### configuration stuff ########################################################
+  #######################
+
+# remount, repair or corrupt
+MODE=remount
+# where to find xfscrash
+XFSCRASH=/xfscrash
+# put log files here
+LOG=$XFSCRASH
+# put output to these places
+OUTPUT="$LOG/xfscrash.log /dev/tty1 /dev/console"
+# awk...
+AWK_PROG=gawk
+# clear FS if >= this percent full at start of run. 100 is a good
+# number - only used on corrupt test so far
+FULL_LIMIT=80
+  
+case `hostname -s`
+in
+    leesa)
+        # mount test partition here
+        TEST_MNT=/mnt/arch0
+        # build test partition here
+        TEST_DEV=/dev/hda6
+        # backup test partition to here (or empty)
+        BACKUP_DEV=/dev/hda8
+        # backup block size for dd
+        BACKUP_BS=1024k
+        # base stress time
+        STRESS_TIME=60
+        # stress random time
+        STRESS_RANDOM=60
+       ;;
+    lumpy)
+        # mount test partition here
+        TEST_MNT=/mnt/scratch_0
+        # build test partition here
+        TEST_DEV=/dev/sdc5
+        # backup test partition to here (or empty)
+        BACKUP_DEV=  ;#/dev/sdc6
+        # backup block size for dd
+        BACKUP_BS=10240k
+        # base stress time
+        STRESS_TIME=360
+        # stress random time
+        STRESS_RANDOM=360
+       ;;
+    *)
+        echo "!!! no configuration data for host `hostname -s`"
+        exit 1
+        ;;
+esac
+
+# avoid stress
+
+AVOID="-f resvsp=0 -f unresvsp=0"
+
+# DIY stress command
+STRESS="/usr/local/bin/fsstress -d $TEST_MNT/stress -n 10000000 -p 1 $AVOID"
+#STRESS="/usr/local/bin/randholes -l 10000000 -c 100000 -b 512 $TEST_MNT/stress/holes"
+
+# stress command for the corrupt test
+CORRUPT_STRESS="/usr/local/bin/fsstress -d $TEST_MNT/stress -n 10000 -p 1 $AVOID"
+
+###########################################################################
+
+reboot=-1
+
+_log()
+{
+    tee -a $OUTPUT > /dev/null
+}
+
+_echo()
+{
+    echo "$*" | _log
+}
+
+_mount()
+{
+    _echo "   *** Mounting $TEST_DEV on $TEST_MNT"
+    if ! mount -t xfs $TEST_DEV $TEST_MNT
+    then
+        _echo "   !!! unable to mount"
+        exit 1
+    fi
+}
+
+_unmount()
+{
+    _echo "   *** Unmounting $TEST_DEV"
+    if ! umount $TEST_DEV &> /dev/null
+    then
+        _echo "   !!! unable to unmount"
+        exit 1
+    fi
+}
+
+_check()
+{
+    expect=$1
+    fail=0
+    
+    if [ $expect -eq 0 ]
+    then
+        _echo "   *** Checking FS (expecting clean fs)"
+    else
+        _echo "   *** Checking FS (expecting dirty fs)"
+    fi
+    
+    
+    if [ $expect -eq 0 ]
+    then
+        _echo "      *** xfs_check ($LOG/check_clean.out)"   
+        xfs_check $TEST_DEV &> $LOG/check_clean.out || fail=1
+        [ -s /tmp/xfs_check_clean.out ] && fail=1
+    else
+        _echo "      *** xfs_check ($LOG/check_dirty.out)"   
+        xfs_check $TEST_DEV &> $LOG/check_dirty.out || fail=1
+    fi
+    
+    if [ $fail -eq 0 -a $expect -eq 0 ]
+    then
+        _echo "      *** xfs_repair -n ($LOG/repair_clean.out)"   
+        xfs_repair -n $TEST_DEV &> $LOG/repair_clean.out || fail=1
+    fi
+    
+    if [ $fail -eq 0 ]
+    then
+        _echo "         *** FS checks ok"
+    else
+        if [ $expect -eq 0 ]
+        then
+            _echo "         !!! FS check failed - inconsistent FS"
+            _echo "         !!! (see $LOG/*.out for details)"
+            exit 1
+        else
+            _echo "         *** inconsistent fs (as expected)"
+        fi
+    fi
+}
+
+_check_core()
+{        
+    if [ -e core ]
+    then
+        _echo "   !!! core file found!"
+        exit 1
+    fi
+}
+
+_repair()
+{
+    rm -f core
+    _echo "   *** repair"
+    _echo "      *** repair pass 1 (RO)"
+    xfs_repair -n $TEST_DEV &> $LOG/repair_1.out \
+        && _echo "         !!! no errors found (eh?)" \
+        || _echo "         *** errors found (expected)"
+        
+    _check_core
+        
+    _echo "      *** repair pass 2 (RW)"
+    
+    if xfs_repair $TEST_DEV &> $LOG/repair_2.out
+    then
+        _echo "         *** FS checks ok (now)"
+    else
+        _echo "         !!! xfs_repair returned error code"
+        _echo "         !!! (see $LOG/repair_*.out for details)"
+        exit 1
+    fi
+        
+    _check_core
+        
+    _echo "      *** repair pass 3 (RO)"
+    if xfs_repair -n $TEST_DEV &> $LOG/repair_3.out
+    then
+        _echo "         *** FS checks ok"
+    else
+        _echo "         !!! errors found after repair (unexpected)"
+        _echo "         !!! (see $LOG/repair_*.out for details)"
+        exit 1
+    fi
+
+    _check_core
+}
+
+_cleanup()
+{
+    rm -f $XFSCRASH/counter $XFSCRASH/start $XFSCRASH/stop $XFSCRASH/active 
+    
+    if [ $reboot != -1 ]
+    then
+        kill $reboot
+    fi
+    
+}
+
+_random()
+{
+    od -tu -N 4 /dev/random | gawk -v v=$1 'NR==1 { print $2 % v }'
+}
+
+_backup()
+{
+    if [ $count -ne 1 -a "$BACKUP_DEV" != "" ]
+    then
+        _echo "   *** Backing up $TEST_DEV to $BACKUP_DEV"
+        if ! dd if=$TEST_DEV of=$BACKUP_DEV bs=$BACKUP_BS &> $LOG/dd.out
+        then
+            _echo "   !!! unable to backup fs"
+            _echo "   !!! (see $LOG/dd.out)"
+            exit 1
+        fi
+    else
+        _echo "   *** skipping back up step"
+    fi
+}
+
+_logprint()
+{
+    _echo "   *** dumping log to $LOG/logprint.out"
+    rm -f core
+    xfs_logprint $TEST_DEV &> $LOG/logprint.out
+    if [ -e core ]
+    then
+        _echo "      !!! xfs_logprint dumped core"
+        echo "" >> $LOG/logprint.out
+        echo "*** CORE DUMPED ***" >> $LOG/logprint.out
+        echo "" >> $LOG/logprint.out
+    fi
+    
+    _echo "   *** dumping log (-t -i) to $LOG/logprint_inode.out"
+    
+    rm -f core
+    xfs_logprint -t -i $TEST_DEV &> $LOG/logprint_inode.out
+    if [ -e core ]
+    then
+        _echo "      !!! xfs_logprint dumped core"
+        echo "" >> $LOG/logprint_inode.out
+        echo "*** CORE DUMPED ***" >> $LOG/logprint_inode.out
+        echo "" >> $LOG/logprint_inode.out
+    fi
+    
+    _echo "   *** dumping log (-t -b) to $LOG/logprint_buf.out"
+    
+    rm -f core
+    xfs_logprint -t -b $TEST_DEV &> $LOG/logprint_buf.out
+    if [ -e core ]
+    then
+        _echo "      !!! xfs_logprint dumped core"
+        echo "" >> $LOG/logprint_buf.out
+        echo "*** CORE DUMPED ***" >> $LOG/logprint_buf.out
+        echo "" >> $LOG/logprint_buf.out
+    fi
+}
+#
+# _df_device : get an IRIX style df line for a given device 
+#
+#       - returns "" if not mounted
+#       - returns fs type in field two (ala IRIX)
+#       - joins line together if split by fancy df formatting
+#       - strips header etc
+#
+
+_df_device()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _df_device device" >&2
+       exit 1
+    fi
+    
+    df -T 2> /dev/null | $AWK_PROG -v what=$1 '
+        match($1,what) && NF==1 { 
+            v=$1
+            getline
+            print v, $0
+            exit
+        }
+        match($1,what) {
+            print
+            exit
+        }
+    '
+}
+
+#
+# _df_dir : get an IRIX style df line for device where a directory resides
+#
+#       - returns fs type in field two (ala IRIX)
+#       - joins line together if split by fancy df formatting
+#       - strips header etc
+#
+
+_df_dir()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _df_dir device" >&2
+       exit 1
+    fi
+    
+    df -T $1 2> /dev/null | $AWK_PROG -v what=$1 '
+        NR == 2 && NF==1 { 
+            v=$1
+            getline 
+            print v, $0;
+            exit 0
+        }
+        NR == 2 {
+            print;
+            exit 0
+        }
+        {}
+    '
+    # otherwise, nada
+}
+
+# return percentage used disk space for mounted device
+
+_used()
+{
+    if [ $# -ne 1 ]
+    then
+       echo "Usage: _used device" >&2
+       exit 1
+    fi
+    
+    _df_device $1 | $AWK_PROG '{ sub("%", "") ; print $6 }'
+}
+
+_check_free()
+{
+     used=`_used $TEST_DEV`
+
+     if [ $used -ge $FULL_LIMIT ]    
+     then
+         _echo "      *** $used % used on $TEST_DEV - deleting files"
+         rm -rf $TEST_MNT/stress
+     fi
+}       
+
+# loop, stressing, unounting and checking
+# no (expected) rebooting...
+_corrupt()
+{
+    count=0
+    
+    # don't want to restart if we reboot...
+    _cleanup
+    
+    while true
+    do
+
+        if [ -e $XFSCRASH/stop ]
+        then
+            _echo "### XFS Crash stopped "
+            exit 0
+        fi
+
+        _echo "*** run $count"
+        let "count = count + 1"
+        
+        _check 0
+        _mount
+        
+        _check_free
+        
+        $CORRUPT_STRESS | _log
+        
+        _unmount        
+    done
+}
+
+###########################################################################
+    
+_echo ""
+_echo ""
+echo "XFSCRASH [output to $OUTPUT]"
+_echo ""
+
+if [ "$1" = "start" ]
+then
+    touch $XFSCRASH/start
+fi
+
+if [ "$1" = "stop" ]
+then
+    touch $XFSCRASH/stop
+fi
+
+
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+
+if [ -e $XFSCRASH/stop ]
+then
+    _echo "### XFS Crash stopped "
+    exit 0
+fi
+
+if [ -e $XFSCRASH/start ]
+then
+    _echo "### XFS Crash started "
+    _cleanup
+    rm -f $LOG/*.out $LOG/*.log core
+    
+    touch $XFSCRASH/active
+
+    _echo "   *** Building fresh XFS FS"
+    umount $TEST_DEV &> /dev/null
+    if ! mkfs -t xfs -f $TEST_DEV &> $LOG/mkfs.out
+    then
+        _echo "   !!! unable to mkfs"
+        _echo "   !!! (see $LOG/mkfs.out)"
+        exit 1
+    fi
+fi
+
+if [ ! -e $XFSCRASH/active ]
+then
+    _echo "### XFS Crash inactive "
+    exit 0
+fi
+
+
+if [ -r $XFSCRASH/counter ]
+then
+    count=`cat $XFSCRASH/counter`
+else
+    count=0
+fi
+_echo "### Crash test run $count (mode=$MODE, log=$LOG/{*.out,*.log})"
+
+let "count = count +1"
+echo $count > $XFSCRASH/counter
+
+# real test starts here
+
+_echo "   *** Checking for R/O root"
+if ! mount | grep "on / type" | grep -q "(ro)"
+then
+    _echo "   !!! root not mounted readonly"
+    exit 1
+fi
+
+_echo "   *** Loading XFS modules"
+if ! modprobe xfs
+then
+    _echo "   !!! unable to modprobe xfs"
+    exit 1
+fi
+
+_echo "   *** Unmounting $TEST_DEV"
+umount $TEST_DEV &> /dev/null
+
+_logprint
+if [ $MODE != "corrupt" ]
+then
+    _backup
+fi
+
+case $MODE
+in
+    remount)
+        _check 1 # expect errors
+        _mount
+        _unmount
+       ;;
+    repair)
+        _repair
+       ;;
+    corrupt)
+        _corrupt
+        exit 0
+        ;;
+    *)
+       _echo "xfscrash: MODE must be remount or repair"
+       exit 1
+       ;;
+esac
+
+_check 0 # don't expect errors
+_mount
+
+_echo "   *** Cleaning XFS FS"
+if ! rm -rf $TEST_MNT/stress $TEST_MNT/lost+found &> $LOG/clean.out
+then
+    _echo "   !!! unable to clean XFS FS"
+    _echo "   !!! (see $LOG/clean.out)"
+    exit 1
+fi
+
+_echo "   *** Making stress directory"
+if ! mkdir $TEST_MNT/stress
+then
+    _echo "   !!! unable to mkdir stress"
+    exit 1
+fi
+
+let "bang = STRESS_TIME + `_random $STRESS_RANDOM`"
+
+_echo "   *** Preparing random reboot (in $bang seconds)"
+(
+    sleep $bang
+    _echo "      *** BANG ****"
+    reboot -fn
+) &
+reboot=$!
+
+_echo "   *** Causing stress & waiting for the inevitable"
+$STRESS | _log
+
+exit 0
diff --git a/group b/group
new file mode 100644 (file)
index 0000000..c7d9a97
--- /dev/null
+++ b/group
@@ -0,0 +1,102 @@
+# 
+# QA groups control file
+# Defines test groups and nominal group owners
+# - do not start group names with a digit
+# - comment line before each group is "new" description
+#
+
+# catch-all
+other          fsg@melbourne.sgi.com
+
+# read/write integrity
+rw             dxm@sgi.com
+
+# directory operations, e.g. create/unlink
+dir            dxm@sgi.com
+
+# metadata and inodes in particular
+metadata       dxm@sgi.com
+
+# xfs_db
+db             nathans@sgi.com dxm@sgi.com
+
+# xfs_attr
+attr           dxm@sgi.com
+
+# xfs_logprint
+logprint       dxm@sgi.com
+
+# xfsdump, xfsrestore, xfsinvutil, xfs_copy
+xfsdump                tes@sgi.com ivanr@sgi.com
+
+# xfs_growfs
+growfs         ajag@sgi.com
+
+# fsr.xfs
+fsr            ajag@sgi.com
+
+# mkfs.xfs
+mkfs           nathans@sgi.com
+
+# xfs_repair
+repair         nathans@sgi.com
+
+# quota tools and XFS quota kernel code (XQM)
+quota          nathans@sgi.com
+
+# auto - tests to be run as part of nightly qa
+auto           dxm@sgi.com
+
+# test-group association ... one line per test
+#
+001 rw dir auto
+002 metadata auto
+003 db auto
+004 db auto
+005 dir auto
+006 dir auto
+007 dir auto
+008 rw auto
+009 rw auto
+010 other auto
+011 dir auto
+012 rw auto
+013 other auto
+014 rw auto
+015 other auto
+016 rw auto
+017 other auto
+018 logprint auto
+019 mkfs auto
+020 metadata attr auto
+021 db attr auto
+022 xfsdump auto
+023 xfsdump auto
+024 xfsdump auto
+025 xfsdump auto
+026 xfsdump auto
+027 xfsdump auto
+028 xfsdump auto
+029 mkfs logprint auto
+030 repair auto
+031 repair mkfs auto
+032 mkfs auto
+033 repair auto
+034 other auto
+035 xfsdump auto
+036 xfsdump auto
+037 xfsdump auto
+038 xfsdump auto
+039 xfsdump auto
+040 other auto
+041 growfs auto
+042 fsr auto
+043 xfsdump auto
+044 other auto
+045 other auto
+046 xfsdump auto
+047 xfsdump auto
+048 other auto
+049 rw auto
+050 quota auto
+051 acl
diff --git a/new b/new
new file mode 100755 (executable)
index 0000000..4e56529
--- /dev/null
+++ b/new
@@ -0,0 +1,209 @@
+#! /bin/sh
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+#
+# Make a new test
+#
+# $Header: /build2/depot/linux/pcp/dev/qa/RCS/new,v 2.22 1999/10/06 19:16:53 kenmcd Exp $
+#
+
+# generic initialization
+iam=new
+. ./common.rc
+
+trap "rm -f /tmp/$$.; exit" 0 1 2 3 15
+
+_cleanup()
+{
+    :
+}
+
+if [ ! -f group ]
+then
+    echo "Creating the group index ..."
+    cat <<'End-of-File' >group
+# QA groups control
+#
+# $Id: new,v 2.22 1999/10/06 19:16:53 kenmcd Exp $
+#
+# define groups and default group owners
+# do not start group name with a digit
+#
+
+# catch-all
+#
+other          some-user-login
+
+# test-group association ... one line per test
+#
+End-of-File
+fi
+
+if [ ! -w group ]
+then
+    chmod u+w group
+    echo "Warning: making the index file \"group\" writeable"
+fi
+
+if make
+then
+    :
+else
+    echo "Warning: make failed -- some tests may be missing"
+fi
+
+last=`grep '^[0-9][0-9]* ' group | sort | tail -1 | sed -e 's/[        ].*//'`
+id=`$AWK_PROG </dev/null 'BEGIN{printf "%03d\n",'$last'+1}'`
+echo "Next test is $id"
+
+if [ -f $id ]
+then
+    echo "Error: test $id already exists!"
+    _cleanup
+    exit 1
+fi
+
+echo -n "Creating skeletal script for you to edit ..."
+
+cat <<End-of-File | sed -e '/rcsId/s//Id: 1.1 /' >$id
+#! /bin/sh
+# XFS QA Test No. $id
+# \$rcsId\$
+#
+# what am I here for?
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=$USER@`_get_fqdn`
+
+seq=\`basename \$0\`
+echo "QA output created by \$seq"
+
+here=\`pwd\`
+tmp=/tmp/\$\$
+status=1       # failure is the default!
+trap "rm -f \$tmp.*; exit \\\$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+# if error
+exit
+
+# optional stuff if your test has verbose output to help resolve problems
+#echo
+#echo "If failure, check \$seq.full (this) and \$seq.full.ok (reference)"
+
+# success, all done
+status=0
+exit
+End-of-File
+
+sleep 2                # latency to read messages to this point
+echo ""
+
+chmod 755 $id
+${EDITOR-vi} $id
+
+if [ $# -eq 0 ]
+then
+    while true
+    do
+       echo -n "Add to group(s) [other] (? for list): "
+       read ans
+       [ -z "$ans" ] && ans=other
+       if [ "X$ans" = "X?" ]
+       then
+           $AWK_PROG <group '
+BEGIN          { text = "# ???" }
+/^[a-zA-z]/    { printf "%-16.16s %s\n",$1,text; text = "# ???"; next }
+NF < 2         { next }
+               { text = $0 }' \
+           | sort
+       else
+           break
+       fi
+    done
+else
+    # expert mode, groups are on the command line
+    #
+    for g in $*
+    do
+       if grep "^$g[   ]" group >/dev/null
+       then
+           :
+       else
+           echo "Warning: group \"$g\" not defined in ./group"
+       fi
+    done
+    ans="$*"
+fi
+
+echo -n "Adding $id to group index ..."
+echo "$id $ans" >>group
+echo " done."
+
+exit 0
diff --git a/remake b/remake
new file mode 100755 (executable)
index 0000000..2f76571
--- /dev/null
+++ b/remake
@@ -0,0 +1,87 @@
+#! /bin/sh
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+#
+# Rebuild NNN.out files
+#
+# $Header: /build2/depot/linux/pcp/dev/qa/RCS/remake,v 2.11 1999/09/20 03:42:19 kenmcd Exp $
+#
+
+tmp=/tmp/$$
+trap "rm -f NO-PREVIOUS-OUTPUT $tmp.*; exit" 0 1 2 3 15
+
+# generic initialization
+iam=remake
+. ./common.rc
+
+. ./common
+
+[ -f check.time ] || touch check.time
+
+for seq in $list
+do
+    if [ ! -f $seq ]
+    then
+       echo "Remake: cannot find \"$seq\""
+    else
+       echo -n "$seq"
+       lasttime=`sed -n -e "/^$seq /s/.* //p" <check.time`
+       [ "X$lasttime" != X ] && echo -n " ${lasttime}s"
+       rm -f $seq.bak $seq.full.bak
+       if sh $seq >$seq.new 2>&1
+       then
+           if [ -f $seq.out ]
+           then
+               $diff $seq.out $seq.new
+               rm -f $seq.out.bad
+           else
+               touch NO-PREVIOUS-OUTPUT
+               $diff NO-PREVIOUS-OUTPUT $seq.new
+               rm -f NO-PREVIOUS-OUTPUT
+           fi
+           echo ""
+           [ -f $seq.out ] && mv $seq.out $seq.bak
+           if [ -f $seq.full ]
+           then
+               [ -f $seq.full.ok ] && mv $seq.full.ok $seq.full.bak
+               mv $seq.full $seq.full.ok
+           fi
+           mv $seq.new $seq.out
+       else
+           echo " - failed (exit status $?)"
+           sed 's/^/   /' $seq.new
+           exit 1
+       fi
+    fi
+done
+
+exit 0
diff --git a/soak b/soak
new file mode 100755 (executable)
index 0000000..c6a203a
--- /dev/null
+++ b/soak
@@ -0,0 +1,152 @@
+#!/bin/sh
+#-----------------------------------------------------------------------
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#-----------------------------------------------------------------------
+#
+# creator
+owner=dxm@sgi.com
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+tmp=/tmp/$$
+seq=soak
+status=1       # failure is the default!
+
+_cleanup()
+{
+    echo "        *** umount"
+    umount $SCRATCH_DEV >/dev/null 2>&1
+}
+
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+ROOT="."
+LOG="$ROOT/soak.log"
+FULL="$ROOT/soak.full"
+
+_log()
+{
+    echo "$*" 1>&2
+    echo "$*" >>$LOG
+    echo "$*" >>$FULL
+}
+
+_logp()
+{
+    tee -a $FULL
+}
+
+_fail()
+{
+    _log "$*"
+    status=1
+    exit 1
+}
+
+_require_scratch
+
+passes=-1
+stress=100000
+proc=1
+
+if [ $# -gt 0 ]
+then
+    passes=$1
+    if [ $# -gt 1 ]
+    then
+        stress=$2
+        if [ $# -gt 2 ]
+        then
+            proc=$3
+        fi
+    fi
+fi
+
+echo "" >$FULL
+echo "" >$LOG
+_log "*** soak test started (passes=$passes, stress=$stress, proc=$proc)"
+_log "***     (`date`)"
+
+
+_log "    *** init"
+_log "        *** unmounting scratch device"
+
+umount $SCRATCH_DEV 2>&1 |  _fix_malloc >>$FULL
+
+_log "        *** clean scratch device"
+
+mkfs -t xfs -f $SCRATCH_DEV 2>&1 |  _fix_malloc >>$FULL \
+                        || _fail "            !!! failed to mkfs SCRATCH_DEV"
+
+pass=1
+
+while [ $pass -le $passes -o $passes -lt 0 ]
+do
+    _log "    *** pass $pass (`date`)"
+    
+    _log "        *** check"
+    _check_fs $SCRATCH_DEV
+    
+    _log "        *** mounting scratch device"
+
+    if ! mount -t xfs $SCRATCH_DEV $SCRATCH_MNT 2>&1 | _logp
+    then
+        _fail "            !!! failed to mount"
+    fi
+                        
+    if [ $pass != 1 ]
+    then
+        _log "        *** cleanup"
+        rm -rf $SCRATCH_MNT/soak_test \
+                        || _fail "            !!! couldn't delete old dir"
+
+        _log "        *** check"
+        _check_fs $SCRATCH_DEV
+    fi
+
+    _log "        *** mkdir"
+    mkdir $SCRATCH_MNT/soak_test \
+                        || _fail "            !!! couldn't delete old dir"
+    
+    _log "        *** stress"
+    src/fsstress -d $SCRATCH_MNT/soak_test -p $proc -n $stress $FSSTRESS_AVOID 2>&1 | \
+        _fix_malloc >>$FULL
+
+    _log "        *** unmounting scratch device"
+
+    umount $SCRATCH_DEV 2>&1 | _logp \
+                            || _fail "            !!! failed to umount"
+    
+    let "pass = pass + 1"
+done
+
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..3cdf0ad
--- /dev/null
@@ -0,0 +1,84 @@
+# 
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+TOPDIR = ../..
+include $(TOPDIR)/include/builddefs
+
+TARGETS = alloc bstat dbtest devzero dirstress fault feature fsstress \
+         fill fill2 holes ioctl loggen lstat64 nametest permname \
+         randholes testrmt truncfile usemem runas
+CFILES = $(TARGETS:=.c) random.c
+HFILES = global.h
+LDIRT = $(TARGETS)
+
+DBMLIB = -lgdbm
+RMTLIB = $(TOPDIR)/dump/librmt/librmt.a
+
+default: $(TARGETS)
+
+include $(BUILDRULES)
+
+install: default
+
+# binaries using non-default objects/libs need an entry below
+# 
+RANDHOLES_OBJECTS = randholes.o random.o
+randholes:     $(HFILES) $(RANDHOLES_OBJECTS)
+               $(CCF) -o $@ $(LDFLAGS) $(RANDHOLES_OBJECTS) $(LDLIBS)
+
+TRUNCFILE_OBJECTS = truncfile.o random.o
+truncfile:     $(HFILES) $(TRUNCFILE_OBJECTS)
+               $(CCF) -o $@ $(LDFLAGS) $(TRUNCFILE_OBJECTS) $(LDLIBS)
+
+FSSTRESS_OBJECTS = fsstress.o random.o $(LIBATTR)
+fsstress:      $(HFILES) $(FSSTRESS_OBJECTS)
+               $(CCF) -o $@ $(LDFLAGS) $(FSSTRESS_OBJECTS) $(LDLIBS)
+
+DBTEST_OBJECTS = dbtest.o random.o $(DBMLIB)
+dbtest:                $(HFILES) $(DBTEST_OBJECTS)
+               $(CCF) -o $@ $(LDFLAGS) $(DBTEST_OBJECTS) $(LDLIBS)
+
+NAMETEST_OBJECTS = nametest.o random.o
+nametest:      $(HFILES) $(NAMETEST_OBJECTS)
+               $(CCF) -o $@ $(LDFLAGS) $(NAMETEST_OBJECTS) $(LDLIBS)
+
+BSTAT_OBJECTS = bstat.o $(LIBHANDLE)
+bstat:         $(HFILES) $(BSTAT_OBJECTS)
+               $(CCF) -o $@ $(LDFLAGS) $(BSTAT_OBJECTS) $(LDLIBS)
+
+TESTRMT_OBJECTS = testrmt.o $(RMTLIB)
+testrmt:       $(TESTRMT_OBJECTS)
+               $(CCF) -o $@ $(LDFLAGS) $(TESTRMT_OBJECTS) $(LDLIBS)
+
+LOGGEN_OBJECTS = loggen.o $(LIBXFS)
+loggen:                $(HFILES) $(LOGGEN_OBJECTS)
+               $(CCF) -o $@ $(LDFLAGS) $(LOGGEN_OBJECTS) $(LDLIBS)
diff --git a/src/alloc.c b/src/alloc.c
new file mode 100644 (file)
index 0000000..dce16d3
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include "global.h"
+
+#define        FSBTOBB(f)      (OFFTOBBT(FSBTOOFF(f)))
+#define        BBTOFSB(b)      (OFFTOFSB(BBTOOFF(b)))
+#define        OFFTOFSB(o)     ((o) / blocksize)
+#define        FSBTOOFF(f)     ((f) * blocksize)
+
+void usage(void)
+{
+    printf("usage: alloc [-b blocksize] [-d dir] [-f file] [-n] [-r] [-t]\n"
+           "flags:\n"
+           "    -n - non-interractive mode\n"
+           "    -r - real time file\n"
+           "    -t - truncate on open\n"
+           "\n"  
+           "commands:\n"  
+           "    r   [offset] [length] - reserve\n"
+           "    u   [offset] [length] - unreserve\n"
+           "    a   [offset] [length] - alloc      *** identical to free\n"
+           "    f   [offset] [length] - free       *** identical to alloc\n" 
+           "    m/p [offset] [length] - print map\n"
+           "    s                     - sync file\n"
+           "    t   [offset]          - truncate\n"
+           "    q                     - quit\n"
+           "    h/?                   - this help\n");
+           
+}
+
+int            fd;
+int            blocksize = 0;
+
+/* params are in bytes */
+void map(off64_t off, off64_t len)
+{
+    struct getbmap     bm[2]={{0}};
+    
+    bm[0].bmv_count = 2;
+    bm[0].bmv_offset = OFFTOBB(off);
+    if (len==(off64_t)-1) { /* unsigned... */
+        bm[0].bmv_length = -1;
+        printf("    MAP off=%lld, len=%lld [%lld-]\n", 
+                (__s64)off, (__s64)len,
+                (__s64)BBTOFSB(bm[0].bmv_offset));
+    } else {
+        bm[0].bmv_length = OFFTOBB(len);
+        printf("    MAP off=%lld, len=%lld [%lld,%lld]\n", 
+                (__s64)off, (__s64)len,
+                (__s64)BBTOFSB(bm[0].bmv_offset),
+                (__s64)BBTOFSB(bm[0].bmv_length));
+    }
+    
+    printf("        [ofs,count]: start..end\n");
+    for (;;) {
+           if (ioctl(fd, XFS_IOC_GETBMAP, bm) < 0) {
+                   perror("getbmap");
+                   break;
+           }
+           if (bm[0].bmv_entries == 0)
+                   break;
+           printf("        [%lld,%lld]: ",
+                   (__s64)BBTOFSB(bm[1].bmv_offset),
+                   (__s64)BBTOFSB(bm[1].bmv_length));
+           if (bm[1].bmv_block == -1)
+                   printf("hole");
+           else
+                   printf("%lld..%lld",
+                           (__s64)BBTOFSB(bm[1].bmv_block),
+                           (__s64)BBTOFSB(bm[1].bmv_block +
+                                   bm[1].bmv_length - 1));
+           printf("\n");
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+       int             c;
+       char            *dirname = NULL;
+       int             done = 0;
+       struct flock64  f;
+       char            *filename = NULL;
+       off64_t         len;
+       char            line[1024];
+       off64_t         off;
+       int             oflags;
+       static char     *opnames[] =
+               { "freesp", "allocsp", "unresvsp", "resvsp" };
+       int             opno;
+       static int      optab[] =
+               { XFS_IOC_FREESP64, XFS_IOC_ALLOCSP64, XFS_IOC_UNRESVSP64, XFS_IOC_RESVSP64 };
+       int             rflag = 0;
+       struct statvfs64        svfs;
+       int             tflag = 0;
+        int             nflag = 0;
+       int             unlinkit = 0;
+       __int64_t       v;
+
+       while ((c = getopt(argc, argv, "b:d:f:rtn")) != -1) {
+               switch (c) {
+               case 'b':
+                       blocksize = atoi(optarg);
+                       break;
+               case 'd':
+                       if (filename) {
+                               printf("can't specify both -d and -f\n");
+                               exit(1);
+                       }
+                       dirname = optarg;
+                       break;
+               case 'f':
+                       if (dirname) {
+                               printf("can't specify both -d and -f\n");
+                               exit(1);
+                       }
+                       filename = optarg;
+                       break;
+               case 'r':
+                       rflag = 1;
+                       break;
+               case 't':
+                       tflag = 1;
+                       break;
+               case 'n':
+                        nflag++;
+                        break;
+               default:
+                       printf("unknown option\n");
+                        usage();
+                       exit(1);
+               }
+       }
+       if (!dirname && !filename)
+               dirname = ".";
+       if (!filename) {
+               static char     tmpfile[] = "allocXXXXXX";
+
+               mktemp(tmpfile);
+               filename = malloc(strlen(tmpfile) + strlen(dirname) + 2);
+               sprintf(filename, "%s/%s", dirname, tmpfile);
+               unlinkit = 1;
+       }
+       oflags = O_RDWR | O_CREAT | (tflag ? O_TRUNC : 0);
+       fd = open(filename, oflags, 0666);
+        if (!nflag) {
+            printf("alloc:\n");
+           printf("    filename %s\n", filename);
+        }
+       if (fd < 0) {
+               perror(filename);
+               exit(1);
+       }
+       if (unlinkit)
+               unlink(filename);
+       if (!blocksize) {
+               if (fstatvfs64(fd, &svfs) < 0) {
+                       perror(filename);
+                       exit(1);
+               }
+               blocksize = (int)svfs.f_bsize;
+        }
+        if (blocksize<0) {
+                fprintf(stderr,"illegal blocksize %d\n", blocksize);
+                exit(1);
+        }
+       printf("    blocksize %d\n", blocksize);
+       if (rflag) {
+               struct fsxattr a;
+
+               if (ioctl(fd, XFS_IOC_FSGETXATTR, &a) < 0) {
+                       perror("XFS_IOC_FSGETXATTR");
+                       exit(1);
+               }
+               a.fsx_xflags |= XFS_XFLAG_REALTIME;
+               if (ioctl(fd, XFS_IOC_FSSETXATTR, &a) < 0) {
+                       perror("XFS_IOC_FSSETXATTR");
+                       exit(1);
+               }
+       }
+       while (!done) {
+                char *p;
+                
+                if (!nflag) printf("alloc> ");
+                fflush(stdout);
+                if (!fgets(line, 1024, stdin)) break;
+                
+                p=line+strlen(line);
+                if (p!=line&&p[-1]=='\n') p[-1]=0;
+                
+               opno = 0;
+               switch (line[0]) {
+               case 'r':
+                       opno++;
+               case 'u':
+                       opno++;
+               case 'a':
+                       opno++;
+               case 'f':
+                       v = strtoll(&line[2], &p, 0);
+                       if (*p == 'b') {
+                               off = FSBTOOFF(v);
+                               p++;
+                       } else
+                               off = v;
+                       f.l_whence = SEEK_SET;
+                       f.l_start = off;
+                       if (*p == '\0')
+                               v = -1;
+                       else
+                               v = strtoll(p, &p, 0);
+                       if (*p == 'b') {
+                               len = FSBTOOFF(v);
+                               p++;
+                       } else
+                               len = v;
+                        
+                        printf("    CMD %s, off=%lld, len=%lld\n", 
+                                opnames[opno], (__s64)off, (__s64)len);
+                        
+                       f.l_len = len;
+                       c = ioctl(fd, optab[opno], &f);
+                       if (c < 0) {
+                               perror(opnames[opno]);
+                               break;
+                       }
+                        
+                        map(off,len);                        
+                       break;
+               case 'p':
+               case 'm':
+                       p = &line[1];
+                       v = strtoll(p, &p, 0);
+                       if (*p == 'b') {
+                               off = FSBTOOFF(v);
+                               p++;
+                       } else
+                               off = v;
+                       if (*p == '\0')
+                               len = -1;
+                       else {
+                               v = strtoll(p, &p, 0);
+                               if (*p == 'b')
+                                       len = FSBTOOFF(v);
+                               else
+                                       len = v;
+                       }
+                        map(off,len);
+                       break;
+               case 't':
+                       p = &line[1];
+                       v = strtoll(p, &p, 0);
+                       if (*p == 'b')
+                               off = FSBTOOFF(v);
+                       else
+                               off = v;
+                        printf("    TRUNCATE off=%lld\n", (__s64)off);
+                       if (ftruncate64(fd, off) < 0) {
+                               perror("ftruncate");
+                               break;
+                       }
+                       break;
+                case 's':
+                        printf("    SYNC\n");
+                        fsync(fd);
+                        break;
+               case 'q':
+                        printf("    QUIT\n");
+                       done = 1;
+                       break;
+                case '?':
+                case 'h':
+                        usage();
+                        break;
+               default:
+                       printf("unknown command '%s'\n", line);
+                       break;
+               }
+       }
+        if (!nflag) printf("\n");
+       close(fd);
+       exit(0);
+       /* NOTREACHED */
+}
diff --git a/src/bstat.c b/src/bstat.c
new file mode 100644 (file)
index 0000000..b3aa011
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include <jdm.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+void
+dotime(void *ti, char *s)
+{
+       char    *c;
+       xfs_bstime_t *t;
+
+       t = (xfs_bstime_t *)ti;
+
+       c = ctime(&t->tv_sec);
+       printf("\t%s %19.19s.%09d %s", s, c, t->tv_nsec, c + 20);
+}
+
+void
+printbstat(xfs_bstat_t *sp)
+{
+       printf("ino %lld mode %#o nlink %d uid %d gid %d rdev %#x\n",
+               sp->bs_ino, sp->bs_mode, sp->bs_nlink,
+               sp->bs_uid, sp->bs_gid, sp->bs_rdev);
+       printf("\tblksize %d size %lld blocks %lld xflags %#x extsize %d\n",
+               sp->bs_blksize, sp->bs_size, sp->bs_blocks,
+               sp->bs_xflags, sp->bs_extsize);
+       dotime(&sp->bs_atime, "atime");
+       dotime(&sp->bs_mtime, "mtime");
+       dotime(&sp->bs_ctime, "ctime");
+       printf( "\textents %d %d gen %d\n",
+               sp->bs_extents, sp->bs_aextents, sp->bs_gen);
+       printf( "\tDMI: event mask 0x%08x state 0x%04x\n",
+               sp->bs_dmevmask, sp->bs_dmstate);
+}
+
+void
+printstat(struct stat64 *sp)
+{
+       printf("ino %lld mode %#o nlink %d uid %d gid %d rdev %#x\n",
+               (xfs_ino_t)sp->st_ino, sp->st_mode, sp->st_nlink,
+               sp->st_uid, sp->st_gid, (unsigned int)sp->st_rdev);
+       printf("\tblksize %llu size %lld blocks %lld\n",
+               (__uint64_t)sp->st_blksize, sp->st_size, sp->st_blocks);
+       dotime(&sp->st_atime, "atime");
+       dotime(&sp->st_mtime, "mtime");
+       dotime(&sp->st_ctime, "ctime");
+}
+
+int
+main(int argc, char **argv)
+{
+       __s32           count;
+       int             total = 0;
+       int             fsfd;
+       int             i;
+       __s64           last = 0;
+       char            *name;
+       int             nent;
+       int             debug = 0;
+       int             quiet = 0;
+       int             statit = 0;
+       int             verbose = 0;
+       xfs_bstat_t     *t;
+       int             ret;
+       jdm_fshandle_t  *fshandlep;
+       int             fd;
+       struct stat64   sb;
+       int nread;
+       char *cc_readlinkbufp;
+       int cc_readlinkbufsz;
+       int             c;
+       xfs_fsop_bulkreq_t bulkreq;
+
+       while ((c = getopt(argc, argv, "cdl:qv")) != -1) {
+               switch (c) {
+               case 'q':
+                       quiet = 1;
+                       break;
+               case 'v':
+                       verbose = 1;
+                       break;
+               case 'c':
+                       statit = 1;
+                       break;
+               case 'd':
+                       debug = 1;
+                       break;
+               case 'l':
+                       last = atoi(optarg);
+                       break;
+               case '?':
+               printf("usage: xfs_bstat [-c] [-q] [-v] [ dir [ batch_size ]]\n");
+               printf("   -c   Check the results against stat(3) output\n");
+               printf("   -q   Quiet\n");
+               printf("   -l _num_  Inode to start with\n");
+               printf("   -v   Verbose output\n");
+                       exit(1);
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (argc < 1)
+               name = ".";
+       else
+               name = *argv;
+
+       fsfd = open(name, O_RDONLY);
+       if (fsfd < 0) {
+               perror(name);
+               exit(1);
+       }
+       if (argc < 2)
+               nent = 4096;
+       else
+               nent = atoi(*++argv);
+
+       if (verbose)
+               printf("Bulkstat test on %s, batch size=%d statcheck=%d\n", 
+                       name, nent, statit);
+
+       if (statit) {
+               fshandlep = jdm_getfshandle( name );
+               if (! fshandlep) {
+                       printf("unable to construct sys handle for %s: %s\n",
+                         name, strerror(errno));
+                       return -1;
+               }
+       }
+
+       t = malloc(nent * sizeof(*t));
+
+       if (verbose)
+               printf(
+                 "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d\n", last, nent);
+
+       bulkreq.lastip  = &last;
+       bulkreq.icount  = nent;
+       bulkreq.ubuffer = t;
+       bulkreq.ocount  = &count;
+
+       while ((ret = ioctl(fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
+               total += count;
+
+               if (verbose)
+                       printf(
+           "XFS_IOC_FSBULKSTAT test: last=%lld ret=%d count=%d total=%d\n", 
+                                               last, ret, count, total);
+               if (count == 0)
+                       exit(0);
+
+               if ( quiet && ! statit )
+                       continue;
+
+               for (i = 0; i < count; i++) {
+                       if (! quiet) {
+                               printbstat(&t[i]);
+                       }
+       
+                       if (statit) {
+                               switch(t[i].bs_mode & S_IFMT) {
+                               case S_IFLNK:
+                                       cc_readlinkbufsz = MAXPATHLEN;
+                                       cc_readlinkbufp = (char *)calloc( 
+                                                             1, 
+                                                             cc_readlinkbufsz);
+                                       nread = jdm_readlink( 
+                                                  fshandlep,
+                                                  &t[i],
+                                                  cc_readlinkbufp,
+                                                  cc_readlinkbufsz);
+                                       if (verbose && nread > 0)
+                                               printf(
+                                                "readlink: ino %lld: <%*s>\n",
+                                                           t[i].bs_ino,
+                                                           nread,
+                                                           cc_readlinkbufp);
+                                       free(cc_readlinkbufp);
+                                       if ( nread < 0 ) {
+                                               printf(
+                                             "could not read symlink ino %llu\n",
+                                                     t[i].bs_ino );
+                                               printbstat(&t[i]);
+                                       }
+                                       break;
+
+                               case S_IFCHR:
+                               case S_IFBLK:
+                               case S_IFIFO:
+                               case S_IFSOCK:
+                                       break;
+
+                               case S_IFREG:
+                               case S_IFDIR:
+                                       fd = jdm_open( fshandlep, &t[i], O_RDONLY);
+                                       if (fd < 0) {
+                                               printf(
+                                       "unable to open handle ino %lld: %s\n",
+                                                 t[i].bs_ino, strerror(errno));
+                                               continue;
+                                       }
+                                       if (fstat64(fd, &sb) < 0) {
+                                               printf(
+                                       "unable to stat ino %lld: %s\n",
+                                                 t[i].bs_ino, strerror(errno));
+                                       }
+                                       close(fd);
+
+                                       /*
+                                        * Don't compare blksize or blocks, 
+                                        * they are used differently by stat
+                                        * and bstat.
+                                        */
+                                       if ( (t[i].bs_ino != sb.st_ino) ||
+                                            (t[i].bs_mode != sb.st_mode) ||
+                                            (t[i].bs_nlink != sb.st_nlink) ||
+                                            (t[i].bs_uid != sb.st_uid) ||
+                                            (t[i].bs_gid != sb.st_gid) ||
+                                            (t[i].bs_rdev != sb.st_rdev) ||
+                                            (t[i].bs_size != sb.st_size) ||
+                                            /* (t[i].bs_blksize != sb.st_blksize) || */
+                                            (t[i].bs_mtime.tv_sec != sb.st_mtime) ||
+                                            (t[i].bs_ctime.tv_sec != sb.st_ctime) ) {
+                                               printf("\nstat/bstat missmatch\n");
+                                               printbstat(&t[i]);
+                                               printstat(&sb);
+                                       }
+                               }
+                       }
+               }
+
+               if (debug)
+                       break;
+       }
+
+       if (fsfd)
+               close(fsfd);
+
+       if (ret < 0 )
+               perror("ioctl(XFS_IOC_FSBULKSTAT)");
+
+       if (verbose)
+               printf(
+           "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d ret=%d count=%d\n", 
+                                              last, nent, ret, count);
+
+       return 1;
+}
diff --git a/src/dbtest.c b/src/dbtest.c
new file mode 100644 (file)
index 0000000..9822000
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include "global.h"
+#include <gdbm/ndbm.h>
+
+/* #define WorkDir     "/xfs" */
+#define DBNAME "DBtest"
+#define DBRECS 100000
+#define LOOPS  100
+
+typedef struct _myDB {
+       char            data[976];
+       unsigned short  checksum;
+       long            align;
+} myDB;        
+
+int InitDbmLookup(int);
+int DoDbmLookup(void);
+void CleanupDbmLookup(void);
+void DoSysError(char *, int);
+int creatDbRec(myDB *);
+unsigned short calccksum(char *, int);
+void CkSumError(char *, unsigned short, unsigned short);
+int InsertKey(unsigned short *, int, unsigned short);
+void DumpKeys(int, unsigned short);
+
+DBM *dbm;
+int numDbmEntries, keyIdx, Dups = 0, Errors = 0;
+unsigned short *KeyArray, *DupsArray;
+int debugflg = 0;      /* are we in debugging mode? */
+int errflg = 0;                /* usage option errors */
+int ignoreflg = 1;     /* ignore errors in lookup; default = on */
+int loops = LOOPS;
+int randseed = 0;
+
+int
+main(int argc, char *argv[])
+{
+       int     numrecs = DBRECS, c, l;
+
+       while ((c = getopt(argc, argv, "idn:l:s:")) != EOF) {
+               switch(c) {
+                       case 'i':
+                               ignoreflg++; break;
+                       case 'd':
+                               debugflg++; break;
+                       case 'n':
+                               numrecs = atoi(optarg);
+                               numrecs = (numrecs < 1) ? DBRECS : numrecs;
+                               break;
+                       case 'l':
+                               loops = atoi(optarg);
+                               loops = (loops < 1) ? LOOPS : loops;
+                               break;
+                       case 's':
+                               randseed = atoi(optarg);
+                               randseed = (randseed < 0) ? 0 : randseed;
+                               break;
+                       case '?':
+                               errflg++;
+                               break;
+               }
+       }
+       if (errflg) {
+               printf("Usage: dbtest [-di] [-n number] [-l loop] [-s randseed]\n");
+               exit(0);
+       }
+       if (optind > argc) {
+               printf("Extra arguments ignored\n");
+               for ( ; optind<argc; optind++)
+                       printf("\t%s\n", argv[optind]);
+       }
+
+       printf("dbtest v1.0\n\n");
+       printf("Creating database containing %d records...\n", numrecs);
+       printf("\tperforming lookups for %d iterations...\n", loops);
+       if (randseed)
+               printf("\tusing %d as seed for srandom()...\n\n", randseed);
+       InitDbmLookup(numrecs);
+       printf("\t\nThere were %d duplicate checksums generated\n", Dups);
+       for (l=0; l<loops; l++) {
+               printf("\nPerforming lookups on database...\n");
+               if (DoDbmLookup() != numrecs)
+                       printf("\nError performing lookups!\n");
+               else
+                       printf("\nLookups succeeded...\n");
+       }
+       printf("\nCleaning up database...\n");
+       printf("\t\nThere were %d duplicate checksums generated\n", Dups);
+       CleanupDbmLookup();
+       if (debugflg)
+               for (l=0; l<Dups; l++) {
+                       if ((l % 8) == 0)
+                               putchar('\n');
+                       printf("0x%x\t", DupsArray[l]);
+               }
+
+       return 0;
+}
+
+
+int InitDbmLookup(int howmany)
+{
+       char    filename[100];
+       datum   key, content;
+       int     i, rc;
+       myDB    dbRec;
+
+       sprintf(filename, "%s-%d", DBNAME, getpid());
+       dbm = dbm_open(filename, O_WRONLY|O_CREAT, 0644);
+       if(dbm == NULL) DoSysError("\ndbm_open", (int)dbm);
+
+       if ((KeyArray = (unsigned short *)calloc( howmany,
+                               sizeof(unsigned short))) == NULL)
+               DoSysError("\ncalloc:KeyArray", -1);
+       if ((DupsArray = (unsigned short *)calloc( 100,
+                               sizeof(unsigned short))) == NULL)
+               DoSysError("\ncalloc:DupsArray", -1);
+
+       keyIdx = 0;
+       for(i=0; i<howmany; i++) {
+
+               if ( creatDbRec(&dbRec) )
+                       DoSysError("\ncreatDbRec", -1);
+               if (debugflg)
+                       printf("created rec #%-7d\t%x\r", i+1, dbRec.checksum);
+
+               if (InsertKey(KeyArray, keyIdx, dbRec.checksum))
+                       keyIdx++;
+
+               key.dptr = (char *)&(dbRec.checksum);
+               key.dsize = sizeof(dbRec.checksum);
+               content.dptr = (char *)&dbRec;
+               content.dsize = sizeof(dbRec);
+write(2, NULL, 0);
+               rc = dbm_store(dbm, key, content, DBM_INSERT);
+               if (rc < 0)
+                       DoSysError("\ndbm_store", rc);
+               else if (rc == 1) {
+                       keyIdx--;       /* key is already in database */
+                       DupsArray[Dups++] = dbRec.checksum;
+               }
+       }
+       numDbmEntries = i;
+       dbm_close(dbm); /* close to eliminate chance of in-memory caching */
+       dbm = dbm_open(filename, O_RDONLY, 0);
+       if(dbm == NULL) DoSysError("\ndbm_open", (int)dbm);
+       return 0;
+}
+
+int DoDbmLookup(void)
+{
+       datum key, content;
+       int i, j, n;
+       myDB *dbp;
+       unsigned tmpck;
+
+       printf("\n\tSequential lookups...\n");
+       for(i=0, j=0; i<numDbmEntries; i++) {
+               key.dptr = (char *)(KeyArray+j);
+               key.dsize = sizeof(KeyArray[0]);
+
+write(2, NULL, 0);
+               content = dbm_fetch(dbm, key);
+               dbp = (myDB *)content.dptr;
+               if ( !content.dptr ) {
+                       n = dbm_error(dbm);
+                       if (n) printf("\n\ndbm_error: %d\n", n);
+                       printf("\n%d: Sequential Lookup of key %4x failed!\n",
+                               i, KeyArray[j]);
+                       DumpKeys(i, KeyArray[j]);
+                       Errors++;
+                       if (ignoreflg) {
+                               j++;
+                               continue;
+                       }
+                       assert( dbp );
+               }
+
+               if (debugflg && dbp)
+                       printf("Seq rec #%-6d: checksum %4x (%4x)\r", i,
+                               dbp->checksum, KeyArray[j]);
+
+               if (content.dsize == 0) {
+                       printf("\nrec #%-8d: key = %4x (%d)\n", i, KeyArray[j], j);
+                       DoSysError("\ndbm_fetch", content.dsize);
+               }
+               if (dbp->checksum != KeyArray[j])
+                       CkSumError("KeySequential", dbp->checksum, KeyArray[j]);
+               if ((tmpck = calccksum(dbp->data, sizeof(dbp->data))) != KeyArray[j])
+                       CkSumError("DataSequential", tmpck, KeyArray[j]);
+               if (++j >= keyIdx)
+                       j = 0;
+       }
+       printf("\n\n\tRandom lookups...\n");
+       for(i=0; i<numDbmEntries; i++) {
+               n = random() % keyIdx;
+               key.dptr = (char *)(KeyArray+n);
+               key.dsize = sizeof(KeyArray[0]);
+               content = dbm_fetch(dbm, key);
+               dbp = (myDB *)content.dptr;
+               if ( !content.dptr ) {
+                       n = dbm_error(dbm);
+                       if (n) printf("\n\ndbm_error: %d\n", n);
+                       printf("\n%d: Random Lookup of key %4x failed!\n",
+                               i, KeyArray[n]);
+                       DumpKeys(n, KeyArray[n]);
+                       Errors++;
+                       if (ignoreflg) {
+                               continue;
+                       }
+                       assert( dbp );
+               }
+
+               if (debugflg && dbp)
+                       printf("Rnd rec #%-6d: checksum %4x (%4x)\r", i,
+                               dbp->checksum, KeyArray[n]);
+
+               if (content.dsize == 0)
+                       DoSysError("\ndbm_fetch", content.dsize);
+               if (dbp->checksum != KeyArray[n])
+                       CkSumError("KeyRand", dbp->checksum, KeyArray[n]);
+               if ((tmpck = calccksum(dbp->data, sizeof(dbp->data))) != KeyArray[n])
+                       CkSumError("DataRand", tmpck, KeyArray[n]);
+       }
+       return i;
+}
+
+void CleanupDbmLookup(void)
+{
+       char filename[100];
+       int rc;
+
+       dbm_close(dbm);
+       sprintf(filename, "%s-%d.dir", DBNAME, getpid());
+       rc = unlink(filename);
+       if (rc) DoSysError("\nunlink", rc);
+       sprintf(filename, "%s-%d.pag", DBNAME, getpid());
+       rc = unlink(filename);
+       if (rc) DoSysError("\nunlink", rc);
+}
+
+void DoSysError(char *msg, int rc)
+{
+       perror(msg);
+       fprintf(stderr, "Bailing out! status = %d\n", rc);
+       exit(-1);
+}
+
+int creatDbRec(myDB *dbp)
+{
+       static int once = 0;
+       int     i, j;
+       long    *ptr;
+       long    timeseed;
+
+       if (!once) {
+               once++;
+               if ( !randseed ) {
+                       timeseed = time(0);
+                       printf("\tusing %ld as seed for srandom()...\n\n",
+                               timeseed);
+                       srandom(timeseed);
+               } else
+                       srandom(randseed);
+       }
+       ptr = (long *)&(dbp->data);
+       j = sizeof(dbp->data) / sizeof(long);
+       for (i=0; i < j; i++, ptr++) {
+               *ptr = random();
+       }
+       for (i=(j*sizeof(long)); i<sizeof(dbp->data); i++)
+               dbp->data[i] = (char)time(0);
+
+       dbp->checksum = calccksum(dbp->data, sizeof(dbp->data));
+       return 0;
+}
+
+unsigned short calccksum(char *ptr, int size)
+{
+       unsigned short sum;
+       int i, n;
+
+       sum = 0;
+       n = ((size > 100) ? 100 : size);
+       for (i=0; i<n && ptr; i++, ptr++) {
+               if (sum & 01)
+                       sum = (sum >> 1) + 0x8000;
+               else
+                       sum >>= 1;
+               sum += (unsigned short)*ptr;
+               sum &= 0xffff;
+       }
+       return sum;
+}
+
+/*ARGSUSED*/
+void CkSumError(char *msg, unsigned short ck1, unsigned short ck2)
+{
+       Errors++;
+       printf("%s\n\tChecksum error, %u != %u, Total errors = %d\n",
+               msg, ck1, ck2, Errors);
+       exit(1);
+}
+
+int InsertKey(unsigned short *k, int idx, unsigned short val)
+{
+/*
+       int i, found=0;
+*/
+
+       return( (k[idx] = val) );
+
+/*
+       for (i=0; i<idx; i++) {
+               if (k[i] == val) {
+                       found++;
+                       break;
+               }
+       }
+
+       if (!found)
+               k[idx] = val;
+
+       return(!found);
+*/
+}
+
+void DumpKeys(int n, unsigned short key)
+{
+/*
+       int     i;
+       unsigned short *p;
+*/
+       FILE    *f;
+
+       if ((f = fopen("keys", "a")) == NULL) {
+               perror("open(keys)");
+               exit(1);
+       }
+/*
+       for (i=0, p=arr; i<keyIdx && p; i++, p++)
+*/
+               fprintf(f, "%d: 0x%x\n", n, key);
+
+       fclose(f);
+}
diff --git a/src/devzero.c b/src/devzero.c
new file mode 100644 (file)
index 0000000..49d3722
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <errno.h>
+
+int
+main(int argc, char **argv)
+{
+       off_t           offset = 0;
+       int             blksize = 4096;
+       long long       maxblks = -1;   /* no limit */
+       long long       nblks = 0;
+       int             value = 0;
+       int             sts = 0;
+       int             fd;
+       char            *z;
+       char            *path;
+       int             oflags = O_WRONLY;
+
+       char    *progname;
+
+       if (strrchr(argv[0],'/'))
+               progname = strrchr(argv[0],'/')+1;
+       else
+               progname = argv[0];
+
+       while ((fd = getopt(argc, argv, "b:n:o:v:ct")) != EOF) {
+               switch (fd) {
+               case 'b':
+                       blksize = atoi(optarg) * 512;
+                       break;
+               case 'n':
+                       maxblks = atoll(optarg);
+                       break;
+               case 'o':
+                       offset = atoll(optarg);
+                       break;
+               case 'v':
+                       value = atoi(optarg);
+                       break;
+               case 'c':
+                       oflags |= O_CREAT;
+                       break;
+               case 't':
+                       oflags |= O_TRUNC;
+                       break;
+               default:
+                       sts++;
+               }
+       }
+       if (sts || argc - optind != 1) {
+               fprintf(stderr,
+                       "Usage: %s [-b N*512] [-n N] [-o off] [-v val] "
+                               " [-c] [-t] <dev/file>\n",
+                       progname);
+               fprintf(stderr,"      -c: create -t: truncate\n");
+               exit(1);
+       }
+
+       path = argv[optind];
+
+       if ((fd = open(path, oflags)) < 0) {
+               fprintf(stderr,
+                       "error opening \"%s\": %s\n",
+                       path, strerror(errno));
+               exit(1);
+       }
+       if ((lseek64(fd, offset, SEEK_SET)) < 0) {
+               fprintf(stderr, "%s: error seeking to offset %llu "
+                                       "on \"%s\": %s\n",
+                       progname, offset, path, strerror(errno));
+               exit(1);
+       }
+
+       if ((z = memalign(getpagesize(), blksize)) == NULL) {
+               fprintf(stderr, "%s: can't memalign %u bytes: %s\n",
+                       progname, blksize, strerror(errno));
+               exit(1);
+       }
+       memset(z, value, blksize);
+       errno = 0;
+       for (;;) {
+               if (nblks++ == maxblks)
+                       break;
+               if ((sts = write(fd, z, blksize)) < blksize) {
+                       if (errno == ENOSPC || sts >= 0)
+                               break;
+                       fprintf(stderr, "%s: write failed: %s\n",
+                               progname, strerror(errno));
+                       break;
+               }
+       }
+       printf("Wrote %.2fKb (value 0x%x)\n",
+               (double) ((--nblks) * blksize) / 1024, value);
+       free(z);
+       return 0;
+}
diff --git a/src/dirstress.c b/src/dirstress.c
new file mode 100644 (file)
index 0000000..db548a8
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+ /*
+  * This is mostly a "crash & burn" test. -v turns on verbosity
+  * and -c actually fails on errors - but expected errors aren't
+  * expected...
+  */
+#include "global.h"
+
+int verbose;
+int pid;
+
+int checkflag=0;
+
+#define MKNOD_DEV 0
+
+static int dirstress(char *dirname, int        dirnum, int nfiles, int keep);
+static int create_entries(int nfiles);
+static int scramble_entries(int        nfiles);
+static int remove_entries(int nfiles);
+
+int
+main(
+       int     argc,
+       char    *argv[])
+{
+       char    *dirname;
+       int     nprocs;
+       int     nfiles;
+       int     c;
+       int     errflg;
+       int     i;
+       long    seed;
+       int     childpid;
+       int     nprocs_per_dir;
+       int     keep;
+        int     status, istatus;
+        
+        pid=getpid();
+
+       errflg = 0;
+       dirname = NULL;
+       nprocs = 4;
+       nfiles = 100;
+       seed = time(NULL);
+       nprocs_per_dir = 1;
+       keep = 0;
+        verbose = 0;
+       while ((c = getopt(argc, argv, "d:p:f:s:n:kvc")) != EOF) {
+               switch(c) {
+                       case 'p':
+                               nprocs = atoi(optarg);
+                               break;
+                       case 'f':
+                               nfiles = atoi(optarg);
+                               break;
+                       case 'n':
+                               nprocs_per_dir = atoi(optarg);
+                               break;
+                       case 'd':
+                               dirname = optarg;
+                               break;
+                       case 's':
+                               seed = strtol(optarg, NULL, 0);
+                               break;
+                       case 'k':
+                               keep = 1;
+                               break;
+                       case '?':
+                               errflg++;
+                               break;
+                       case 'v':
+                               verbose++;
+                               break;
+                       case 'c':
+                                checkflag++;
+                                break;
+               }
+       }
+       if (errflg || (dirname == NULL)) {
+               printf("Usage: dirstress [-d dir] [-p nprocs] [-f nfiles] [-n procs per dir]\n"
+                       "                 [-v] [-s seed] [-k] [-c]\n");
+               exit(0); 
+       }
+
+       printf("** [%d] Using seed %ld\n", pid, seed);
+       srandom(seed);
+
+       for (i = 0; i < nprocs; i++) {
+                if (verbose) fprintf(stderr,"** [%d] fork\n", pid);
+               childpid = fork();
+               if (childpid < 0) {
+                       perror("Fork failed");
+                       exit(errno);
+               }
+               if (childpid == 0) {
+                        int r;
+                       /* child */
+                        pid=getpid();
+                        
+                        if (verbose) fprintf(stderr,"** [%d] forked\n", pid);
+                       r=dirstress(dirname, i / nprocs_per_dir, nfiles, keep);
+                        if (verbose) fprintf(stderr,"** [%d] exit\n", pid);
+                       exit(r);
+               }
+       }
+        if (verbose) fprintf(stderr,"** [%d] wait\n", pid);
+        istatus=0;
+        
+        /* wait & reap children, accumulating error results */
+       while (wait(&status) != -1)
+            istatus+=status/256;
+        
+       printf("INFO: Dirstress complete\n");
+        if (verbose) fprintf(stderr,"** [%d] exit %d\n", pid, istatus);
+       return istatus;
+}
+
+
+
+int
+dirstress(
+       char    *dirname,
+       int     dirnum,
+       int     nfiles,
+       int     keep)
+{
+       int             error;
+       char            buf[1024];
+        int             r;
+        
+       sprintf(buf, "%s/stressdir", dirname);
+        if (verbose) fprintf(stderr,"** [%d] mkdir %s 0777\n", pid, buf);
+       error = mkdir(buf, 0777);
+       if (error && (errno != EEXIST)) {
+               perror("Create stressdir directory failed");
+               return 1;
+       }
+
+        if (verbose) fprintf(stderr,"** [%d] chdir %s\n", pid, buf);
+       error = chdir(buf);
+       if (error) {
+               perror("Cannot chdir to main directory");
+               return 1;
+       }
+
+       sprintf(buf, "stress.%d", dirnum);
+        if (verbose) fprintf(stderr,"** [%d] mkdir %s 0777\n", pid, buf);
+       error = mkdir(buf, 0777);
+       if (error && (errno != EEXIST)) {
+               perror("Create pid directory failed");
+               return 1;
+       }
+
+        if (verbose) fprintf(stderr,"** [%d] chdir %s\n", pid, buf);
+       error = chdir(buf);
+       if (error) {
+               perror("Cannot chdir to dirnum directory");
+               return 1;
+       }
+
+        r=1; /* assume failure */
+        if (verbose) fprintf(stderr,"** [%d] create entries\n", pid);
+       if (create_entries(nfiles)) {
+            printf("!! [%d] create failed\n", pid);
+        } else {
+            if (verbose) fprintf(stderr,"** [%d] scramble entries\n", pid);
+           if (scramble_entries(nfiles)) {
+                printf("!! [%d] scramble failed\n", pid);
+            } else {
+               if (keep) {
+                    if (verbose) fprintf(stderr,"** [%d] keep entries\n", pid);
+                    r=0; /* success */
+                } else {
+                    if (verbose) fprintf(stderr,"** [%d] remove entries\n", pid);
+                   if (remove_entries(nfiles)) {
+                        printf("!! [%d] remove failed\n", pid);
+                    } else {
+                        r=0; /* success */
+                    }
+                }
+            }
+        }
+
+        if (verbose) fprintf(stderr,"** [%d] chdir ..\n", pid);
+       error = chdir("..");
+       if (error) {
+               perror("Cannot chdir out of pid directory");
+               return 1;
+       }
+
+       if (!keep) {
+               sprintf(buf, "stress.%d", dirnum);
+                if (verbose) fprintf(stderr,"** [%d] rmdir %s\n", pid, buf);
+               if (rmdir(buf)) {
+                    perror("rmdir");
+                    if (checkflag) return 1;
+                }
+       }
+       
+        if (verbose) fprintf(stderr,"** [%d] chdir ..\n", pid);
+       error = chdir("..");
+       if (error) {
+               perror("Cannot chdir out of working directory");
+               return 1;
+       }
+
+       if (!keep) {
+                if (verbose) fprintf(stderr,"** [%d] rmdir stressdir\n", pid);
+               if (rmdir("stressdir")) {
+                    perror("rmdir");
+                    if (checkflag) return 1;
+                }
+        }
+
+       return r;
+}
+
+int
+create_entries(
+       int     nfiles)
+{
+       int     i;
+       int     fd;
+       char    buf[1024];
+
+       for (i = 0; i < nfiles; i++) {
+               sprintf(buf, "XXXXXXXXXXXX.%d", i);
+               switch (i % 4) {
+               case 0:
+                       /*
+                        * Create a file
+                        */
+                        if (verbose) fprintf(stderr,"** [%d] creat %s\n", pid, buf);
+                       fd = creat(buf, 0666);
+                       if (fd > 0) {
+                                if (verbose) fprintf(stderr,"** [%d] close %s\n", pid, buf);
+                               close(fd);
+                       } else {
+                                fprintf(stderr,"!! [%d] close %s failed\n", pid, buf);
+                                perror("close");
+                                if (checkflag) return 1;
+                        }
+                        
+                       break;
+               case 1:
+                       /*
+                        * Make a directory.
+                        */
+                        if (verbose) fprintf(stderr,"** [%d] mkdir %s 0777\n", pid, buf);
+                       if (mkdir(buf, 0777)) {
+                            fprintf(stderr,"!! [%d] mkdir %s 0777 failed\n", pid, buf);
+                            perror("mkdir");
+                            if (checkflag) return 1;
+                        }
+                        
+                       break;
+               case 2:
+                       /*
+                        * Make a symlink
+                        */
+                        if (verbose) fprintf(stderr,"** [%d] symlink %s %s\n", pid, buf, buf);
+                       if (symlink(buf, buf)) {
+                            fprintf(stderr,"!! [%d] symlink %s %s failed\n", pid, buf, buf);
+                            perror("symlink");
+                            if (checkflag) return 1;
+                        }
+                        
+                       break;
+               case 3:
+                       /*
+                        * Make a dev node
+                        */
+                        if (verbose) fprintf(stderr,"** [%d] mknod %s 0x%x\n", pid, buf, MKNOD_DEV);
+                       if (mknod(buf, S_IFCHR | 0666, MKNOD_DEV)) {
+                            fprintf(stderr,"!! [%d] mknod %s 0x%x failed\n", pid, buf, MKNOD_DEV);
+                            perror("mknod");
+                            if (checkflag) return 1;
+                        }
+                        
+                       break;
+               default:
+                       break;
+               }
+       }
+        return 0;
+}
+
+
+int
+scramble_entries(
+       int     nfiles)
+{
+       int             i;
+       char            buf[1024];
+       char            buf1[1024];
+       long            r;
+       int             fd;
+
+       for (i = 0; i < nfiles * 2; i++) {
+               switch (i % 5) {
+               case 0:
+                       /*
+                        * rename two random entries
+                        */
+                       r = random() % nfiles;
+                       sprintf(buf, "XXXXXXXXXXXX.%ld", r);
+                       r = random() % nfiles;
+                       sprintf(buf1, "XXXXXXXXXXXX.%ld", r);
+
+                        if (verbose) fprintf(stderr,"** [%d] rename %s %s\n", pid, buf, buf1);
+                       if (rename(buf, buf1)) {
+                            perror("rename");
+                            if (checkflag) return 1;
+                        }
+                       break;
+               case 1:
+                       /*
+                        * unlink a random entry
+                        */
+                       r = random() % nfiles;
+                       sprintf(buf, "XXXXXXXXXXXX.%ld", r);
+                        if (verbose) fprintf(stderr,"** [%d] unlink %s\n", pid, buf);
+                       if (unlink(buf)) {
+                            fprintf(stderr,"!! [%d] unlink %s failed\n", pid, buf);
+                            perror("unlink");
+                            if (checkflag) return 1;
+                        }
+                       break;
+               case 2:
+                       /*
+                        * rmdir a random entry
+                        */
+                       r = random() % nfiles;
+                       sprintf(buf, "XXXXXXXXXXXX.%ld", r);
+                        if (verbose) fprintf(stderr,"** [%d] rmdir %s\n", pid, buf);
+                       if (rmdir(buf)) {
+                            fprintf(stderr,"!! [%d] rmdir %s failed\n", pid, buf);
+                            perror("rmdir");
+                            if (checkflag) return 1;
+                        }
+                       break;
+               case 3:
+                       /*
+                        * create a random entry
+                        */
+                       r = random() % nfiles;
+                       sprintf(buf, "XXXXXXXXXXXX.%ld", r);
+
+                        if (verbose) fprintf(stderr,"** [%d] creat %s 0666\n", pid, buf);
+                       fd = creat(buf, 0666);
+                       if (fd > 0) {
+                                if (verbose) fprintf(stderr,"** [%d] close %s\n", pid, buf);
+                               if (close(fd)) {
+                                    fprintf(stderr,"!! [%d] close %s failed\n", pid, buf);
+                                    perror("close");
+                                    if (checkflag) return 1;
+                                }
+                       } else {
+                            fprintf(stderr,"!! [%d] creat %s 0666 failed\n", pid, buf);
+                            perror("creat");
+                            if (checkflag) return 1;
+                        }
+                       break;
+               case 4:
+                       /*
+                        * mkdir a random entry
+                        */
+                       r = random() % nfiles;
+                       sprintf(buf, "XXXXXXXXXXXX.%ld", r);
+                        if (verbose) fprintf(stderr,"** [%d] mkdir %s\n", pid, buf);
+                       if (mkdir(buf, 0777)) {
+                            fprintf(stderr,"!! [%d] mkdir %s failed\n", pid, buf);
+                            perror("mkdir");
+                            if (checkflag) return 1;
+                        }
+                       break;
+               default:
+                       break;
+               }
+       }
+        return 0;
+}
+                       
+int
+remove_entries(
+       int     nfiles)
+{
+       int             i;
+       char            buf[1024];
+       struct stat     statb;
+       int             error;
+
+       for (i = 0; i < nfiles; i++) {
+               sprintf(buf, "XXXXXXXXXXXX.%d", i);
+               error = lstat(buf, &statb);
+               if (error) {
+                        /* ignore this one */
+                       continue;
+               }
+               if (S_ISDIR(statb.st_mode)) {
+                        if (verbose) fprintf(stderr,"** [%d] rmdir %s\n", pid, buf);
+                       if (rmdir(buf)) {
+                            fprintf(stderr,"!! [%d] rmdir %s failed\n", pid, buf);
+                            perror("rmdir");
+                            if (checkflag) return 1;
+                        }
+               } else {
+                        if (verbose) fprintf(stderr,"** [%d] unlink %s\n", pid, buf);
+                       if (unlink(buf)) {
+                            fprintf(stderr,"!! [%d] unlink %s failed\n", pid, buf);
+                            perror("unlink");
+                            if (checkflag) return 1;
+                        }
+               }
+       }
+        return 0;
+}
diff --git a/src/fault.c b/src/fault.c
new file mode 100644 (file)
index 0000000..17a8d8c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+void expect_error(int r, int err)
+{
+    if (r<0) {
+        if (errno == err) {
+            printf("   --- got error %d as expected\n", err);   
+        } else {
+            perror("   !!! unexpected error");
+        }
+    } else {
+        printf("   !!! success instead of error %d as expected\n", err);
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    int                 fsfd;
+    
+    if (argc != 2) {
+        fprintf(stderr,"usage: %s <filesystem>\n",
+                argv[0]);
+        exit(0);
+    }
+
+    fsfd = open(argv[1], O_RDONLY);
+    if (fsfd < 0) {
+       perror("open");
+       exit(1);
+    }
+    
+    printf("--- ioctl with bad output address\n");
+    expect_error(ioctl(fsfd, XFS_IOC_FSCOUNTS, NULL), EFAULT);
+    printf("--- ioctl with bad input address\n");
+    expect_error(ioctl(fsfd, XFS_IOC_SET_RESBLKS, NULL), EFAULT);
+    
+    close(fsfd);
+    
+    return 0;
+}
diff --git a/src/feature.c b/src/feature.c
new file mode 100644 (file)
index 0000000..b5337c3
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/*
+ * Test for filesystem features on given mount point or device
+ *   -q  test for quota support (kernel compile option)
+ *   -u  test for user quota support (mount option)
+ *   -g  test for group quota support (mount option)
+ * Return code: 0 is true, anything else is error/not supported
+ */
+
+#include <libxfs.h>
+#include <sys/quota.h>
+#include <xqm.h>
+
+int verbose = 0;
+
+void
+usage(void)
+{
+       fprintf(stderr, "Usage: feature [-v] -<q|u|g|U|G> <filesystem>\n");
+       exit(1);
+}
+
+int
+hasxfsquota(int type, int q, char *device)
+{
+       fs_quota_stat_t qstat;
+       int             qcmd;
+
+       memset(&qstat, 0, sizeof(fs_quota_stat_t));
+       qcmd = QCMD(Q_XGETQSTAT, type);
+       if (quotactl(qcmd, device, 0, (caddr_t)&qstat) < 0) {
+               if (verbose)
+                       perror("quotactl");
+               return (1);
+       }
+       else if (q == 0)
+               return (0);
+       else if (q == XFS_QUOTA_UDQ_ENFD && qstat.qs_flags & XFS_QUOTA_UDQ_ENFD)
+               return (0);
+       else if (q == XFS_QUOTA_GDQ_ENFD && qstat.qs_flags & XFS_QUOTA_GDQ_ENFD)
+               return (0);
+       else if (q == XFS_QUOTA_UDQ_ACCT && qstat.qs_flags & XFS_QUOTA_UDQ_ACCT)
+               return (0);
+       else if (q == XFS_QUOTA_GDQ_ACCT && qstat.qs_flags & XFS_QUOTA_GDQ_ACCT)
+               return (0);
+       if (verbose)
+               fprintf(stderr, "quota type (%d) not available\n", q);
+       return (1);
+}
+
+int
+main(int argc, char **argv)
+{
+       int     c;
+       int     gflag = 0;
+       int     Gflag = 0;
+       int     qflag = 0;
+       int     uflag = 0;
+       int     Uflag = 0;
+       char    *fs;
+
+       while ((c = getopt(argc, argv, "gGquUv")) != EOF) {
+               switch (c) {
+               case 'g':
+                       gflag++;
+                       break;
+               case 'G':
+                       Gflag++;
+                       break;
+               case 'q':
+                       qflag++;
+                       break;
+               case 'u':
+                       uflag++;
+                       break;
+               case 'U':
+                       Uflag++;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               default:
+                       usage();
+               }
+       }
+
+       if (!uflag && !gflag && !qflag && !Uflag && !Gflag)
+               usage();
+       if (optind != argc-1)
+               usage();
+       fs = argv[argc-1];
+
+       if (qflag)
+               return(hasxfsquota(0, 0, fs));
+       if (gflag)
+               return(hasxfsquota(GRPQUOTA, XFS_QUOTA_GDQ_ENFD, fs));
+       if (uflag)
+               return(hasxfsquota(USRQUOTA, XFS_QUOTA_UDQ_ENFD, fs));
+       if (Gflag)
+               return(hasxfsquota(GRPQUOTA, XFS_QUOTA_GDQ_ACCT, fs));
+       if (Uflag)
+               return(hasxfsquota(USRQUOTA, XFS_QUOTA_UDQ_ACCT, fs));
+
+       fprintf(stderr, "feature: dunno what you're doing?\n");
+       return(1);
+}
diff --git a/src/fill.c b/src/fill.c
new file mode 100644 (file)
index 0000000..2af9e3f
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * fill pathname key nbyte
+ *
+ * use key to seed random number generator so data is deterministic
+ *
+ * lines are at most 72 bytes long so diff(1) does not choke
+ */
+
+int
+main(int argc, char **argv)
+{
+    FILE               *f;
+    unsigned int       seed;
+    long               i;
+    int                        nbyte;
+    char               *hdr;
+    char               *hp;
+    char               c;
+
+    /* quick and dirty, no args checking */
+    if ((f = fopen(argv[1], "w")) == NULL) {
+       fprintf(stderr, "fill: cannot create \"%s\": %s\n", argv[1], strerror(errno));
+       exit(1);
+    }
+    seed = 0;
+    i = 0;
+    while (argv[2][i]) {
+       seed <<= 8;
+       seed |= argv[2][i];
+       i++;
+    }
+    srand(seed);
+
+    nbyte = atoi(argv[3]);
+
+    /*
+     * line format
+     *
+     * byte offset @ start of this line XXXXXXXXXXXX
+     * test iteration number XXXX
+     * key (usually file name) argv[2]
+     * random bytes to fill the line
+     */
+
+    hdr = (char *)malloc(12+1+4+1+strlen(argv[2])+1+1);
+    sprintf(hdr, "%012ld %04d %s ", (long int)0, 0, argv[2]);
+    hp = hdr;
+
+    for (i = 0; i < nbyte-1; i++) {
+       if (*hp) {
+           c = *hp;
+           hp++;
+       }
+       else if ((i % 72) == 71)
+           c = '\n';
+       else
+           c = 32+(rand() % (128-32));
+       fputc(c, f);
+       if (c == '\n') {
+           hp = hdr;
+           sprintf(hdr, "%012ld %04d %s ", i+1, 0, argv[2]);
+       }
+    }
+    fputc('\n', f);
+
+    exit(0);
+}
diff --git a/src/fill2.c b/src/fill2.c
new file mode 100644 (file)
index 0000000..6108ec1
--- /dev/null
@@ -0,0 +1,386 @@
+
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+
+/*
+ * fill2:
+ *   Derived from fill.c, adds command line options, block boundary marking
+ *   and allows me to tweak to suit fill2fs without breaking other qa tests.
+ *   This version marks block boundaries (512, 1k, 4k and 16k) within the file
+ *   using characters guaranteed not to appear anywhere else, this may allow
+ *   simple checks in future which can inspect these offsets and ensure one of
+ *   of the four characters is present. Also fixes off-by-one error in fill.c
+ *   and is more careful about checking when write operations fail - this is 
+ *   needed by fill2fs to ensure that the number of bytes written is accurately
+ *   determined.
+ *
+ *   $Id$
+ */
+
+
+#include <libxfs.h>
+#include <errno.h>
+
+#define N(x) (sizeof(x)/sizeof(x[0]))
+
+/* function prototypes */
+static void illegal(char *, char *);
+static void reqval(char, char * [], int);
+static void respec(char, char * [], int);
+static void unknown(char, char *);
+static void usage(void);
+static char *progname;
+
+char *dopts[] =                { "nbytes", "linelength", "seed", "file", NULL };
+enum                   { D_NBYTES, D_LINELENGTH, D_SEED, D_FILE, D_ISSET, D_NUM };
+int dflags[D_NUM] =    { 0 };
+char *bopts[] =                { "512", "1k", "4k", "16k" };
+enum                   { B_512, B_1K, B_4K, B_16K, B_ISSET, B_NUM };
+int bflags[B_NUM] =    { 0 };
+
+
+/*
+ * block boundaries
+ *
+ */
+
+/* block boundaries which should be flagged in the output file */
+/* flag is the character that should be used to indicate each type */
+/* of block boundary */
+
+
+struct s_block_type {
+    int mark;
+    int size;
+    char flag;
+};
+
+static struct s_block_type btypes[] = {
+    { 0, 512, '!' },   /* 512 */
+    { 0, 1024, '"' },  /* 1k */
+    { 0, 4096, '#' },  /* 4k */
+    { 0, 16384, '$' }, /* 16k */
+};
+
+/*
+ * main
+ *
+ */
+
+int
+main(int argc, char **argv)
+{
+    int                        status = 0;     /* return status */
+    int                        c;              /* current option character */
+    char               *p;             /* for getsubopt calls */
+    long               nbytes;         /* total number of bytes to write */
+    int                        dlen;           /* length of normal output data line */
+    const char         *dseed;         /* input string for seeding rand */
+    unsigned int       seed;           /* seed for output data */    
+    char               *dfile;         /* where to write output */
+
+    FILE               *f;             /* output file */
+    char               *dbuf;          /* output line buffer */
+    char               bbuf[50];       /* block boundary string */
+    char               *active;        /* active buffer to copy out of */
+    size_t             hlen;           /* header length (bytes+key) in output */
+                                       /* lines */
+    char               *hptr;          /* pointer to end of header */
+    char               *ptr;           /* current position to copy from */
+    int                        blktype;        /* current block boundary type */
+    int                        boundary;       /* set if current output char lies on */
+                                       /* block boundary */
+    long               i;
+    int                        j;
+    int                        l;
+
+
+    /* defaults */
+    progname = basename(argv[0]);
+    nbytes = 1024 * 1024;
+    dlen = 73; /* includes the trailing newline */
+
+    while ((c = getopt(argc, argv, "d:b:")) != EOF) {
+       switch (c) {
+       case 'd':
+           if (dflags[D_ISSET])
+               respec('d', NULL, 0);
+           dflags[D_ISSET] = 1;
+
+           p = optarg;
+           while (*p != '\0') {
+               char *value;
+               switch (getsubopt(&p, (constpp)dopts, &value)) {
+               case D_NBYTES:
+                   if (! value) reqval('d', dopts, D_NBYTES);
+                   if (dflags[D_NBYTES]) respec('d', dopts, D_NBYTES);
+                   dflags[D_NBYTES] = 1;
+                   nbytes = strtol(value, &ptr, 10);
+                   if (ptr == value) illegal(value, "d nbytes");
+                   break;
+
+               case D_LINELENGTH:
+                   if (! value) reqval('d', dopts, D_LINELENGTH);
+                   if (dflags[D_LINELENGTH]) respec('d', dopts, D_LINELENGTH);
+                   dflags[D_LINELENGTH] = 1;
+                   dlen = (int) strtol(value, &ptr, 10) + 1;
+                   if (ptr == value) illegal(value, "d linelength");
+                   break;
+
+               case D_SEED:
+                   if (! value) reqval('d', dopts, D_SEED);
+                   if (dflags[D_SEED]) respec('D', dopts, D_SEED);
+                   dflags[D_SEED] = 1;
+                   dseed = value;
+                   break;
+
+               case D_FILE:
+                   if (! value) reqval('d', dopts, D_FILE);
+                   if (dflags[D_FILE]) respec('d', dopts, D_FILE);
+                   dflags[D_FILE] = 1;
+                   dfile = value;
+                   break;
+                   
+               default:
+                   unknown('d', value);
+               }
+           }
+           break;
+
+       case 'b':
+           if (bflags[B_ISSET])
+               respec('b', NULL, 0);
+           bflags[B_ISSET] = 1;
+
+           p = optarg;
+           while (*p != '\0') {
+               char *value;
+               switch (getsubopt(&p, (constpp)bopts, &value)) {
+               case B_512:
+                   if (value) illegal(value, "b 512");
+                   if (bflags[B_512]) respec('b', bopts, B_512);
+                   bflags[B_512] = 1;
+                   btypes[0].mark = 1;
+                   break;
+
+               case B_1K:
+                   if (value) illegal(value, "b 1k");
+                   if (bflags[B_1K]) respec('b', bopts, B_1K);
+                   bflags[B_1K] = 1;
+                   btypes[1].mark = 1;
+                   break;
+
+               case B_4K:
+                   if (value) illegal(value, "b 4k");
+                   if (bflags[B_4K]) respec('b', bopts, B_4K);
+                   bflags[B_4K] = 1;
+                   btypes[2].mark = 1;
+                   break;
+
+               case B_16K:
+                   if (value) illegal(value, "b 16k");
+                   if (bflags[B_16K]) respec('b', bopts, B_16K);
+                   bflags[B_16K] = 1;
+                   btypes[3].mark = 1;
+                   break;
+
+               default:
+                   unknown('b', value);
+                   break;
+               }
+           }
+           break;
+
+       case '?':
+           usage();
+       }
+    }
+
+    if (dflags[D_FILE] && optind != argc)
+       usage();
+
+    if (! dflags[D_FILE] && argc - optind != 1)
+       usage();
+
+    if (! dflags[D_FILE])
+       dfile = argv[optind];
+
+    if ((f = fopen(dfile, "w")) == NULL) {
+       fprintf(stderr, "fill2: cannot create \"%s\": %s\n",
+               dfile, strerror(errno));
+       status = 1;
+       goto cleanup;
+    }
+
+    if (! dflags[D_SEED]) 
+       dseed = dfile;
+
+    /* seed is an ascii string */
+    seed = 0;
+    i = 0;
+    while (dseed[i]) {
+       seed <<= 8;
+       seed |= dseed[i];
+       i++;
+    }
+    srand(seed);
+
+
+    /* normal data line format: XXXXXXXXXXXX CCCC...CCC CCCCCCCCCCCC...CCC */
+    /* block boundary format: CXXXXXXX */
+
+    dbuf = (char *) malloc(dlen + 1);
+    hlen = 12+1+strlen(dseed)+1;
+    assert(hlen < dlen);
+    hptr = dbuf + hlen;
+
+    for (i = 0; i < nbytes; i++) {
+
+       
+       /* is this a block boundary? check largest to smallest */
+       boundary = 0;
+       for (j = N(btypes) - 1; j >= 0; j--) {
+           if (btypes[j].mark) {
+               /* first time through or just before a block boundary? */
+               if (i == 0 || i % btypes[j].size == btypes[j].size - 1) {
+                   boundary = 1;
+                   blktype = j;
+                   break;
+               }
+           }
+       }
+
+
+       /* are there block boundaries to check? */
+       /* is this the first time through? */
+       /* block boundaries take priority over other output */
+       if (bflags[B_ISSET] && (i == 0 || boundary)) {
+           sprintf(bbuf, "%s%c%07ld\n",
+                   i ? "\n" : "",
+                   btypes[blktype].flag,
+                   /* remember i is one less than block boundary */
+                   i ? (i+1) / btypes[blktype].size : 0);
+           active = bbuf;
+           ptr = bbuf;
+       }
+       /* are we at the start of a new line? */
+       else if (i == 0
+                || (active == bbuf && *ptr == '\0')
+                || (active == dbuf && l == dlen))
+       {
+           sprintf(dbuf, "%012ld %s ", i, dseed);
+           assert(*hptr == '\0');
+           for (ptr = hptr; ptr != dbuf + dlen - 1; ptr++) {
+               /* characters upto 126 '~' are used */
+               /* do not use !"#$ - leave free for use as block markers */
+               *ptr = 37 + (rand() % (127 - 37)); 
+           }
+           *ptr++ = '\n';
+           *ptr = '\0';
+           assert(ptr == dbuf + dlen);
+           active = dbuf;
+           ptr = dbuf;
+           l = 0;
+       }
+       else {
+           /* continue copying from the active buffer */
+       }
+
+       /* output one new character from current buffer */
+       if (fputc(*ptr++, f) == EOF) {
+           fprintf(stderr, "fill2: could not write character to \"%s\": %s\n",
+                   dfile, strerror(errno));
+           status = 1;
+           goto cleanup;
+       }
+       if (active == dbuf) l++;
+
+    }
+
+ cleanup:
+
+    /* close file and flush buffers - check if this fails */
+    if (fclose(f) != 0) {
+       fprintf(stderr, "fill2: fclose() on \"%s\" failed: %s\n",
+               dfile, strerror(errno));
+       status = 1;
+    }
+    exit(status);
+}
+
+
+
+/*
+ * suboption checking functions
+ *
+ */
+
+static void
+illegal(char *value, char *opt)
+{
+    fprintf(stderr, "%s: Error: Illegal value \"%s\" for -%s option\n",
+           progname, value, opt);
+    usage();
+}
+static void
+reqval(char opt, char *tab[], int idx)
+{
+    fprintf(stderr, "%s: Error: -%c %s option requires a value\n",
+           progname, opt, tab[idx]);
+    usage();
+}
+static void
+respec(char opt, char *tab[], int idx)
+{
+    fprintf(stderr, "%s: Error: ", progname);
+    fprintf(stderr, "-%c ", opt);
+    if (tab) fprintf(stderr, "%s ", tab[idx]);
+    fprintf(stderr, "option respecified\n");
+    usage();
+}
+static void
+unknown(char opt, char *s)
+{
+    fprintf(stderr, "%s: Error: Unknown option -%c %s\n", progname, opt, s);
+    usage();
+}
+static void
+usage(void)
+{
+    fprintf(stderr, "Usage: %s [options] filename\n"
+"Options:\n"
+"  -d [nbytes=num,linelength=num,   output data properties\n"
+"      seed=string,file=name]\n"
+"  -b [512,1k,4k,16k]               where to mark block boundaries\n", progname);
+    exit(2);
+}
diff --git a/src/fill2fs b/src/fill2fs
new file mode 100755 (executable)
index 0000000..cf692ae
--- /dev/null
@@ -0,0 +1,367 @@
+#!/usr/bin/perl -w
+#
+
+#
+#  Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+#  
+#  This program is free software; you can redistribute it and/or modify it
+#  under the terms of version 2 of the GNU General Public License as
+#  published by the Free Software Foundation.
+#  
+#  This program is distributed in the hope that it would be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  
+#  Further, this software is distributed without any warranty that it is
+#  free of the rightful claim of any third person regarding infringement
+#  or the like.  Any license provided herein, whether implied or
+#  otherwise, applies only to this software file.  Patent licenses, if
+#  any, provided herein do not apply to combinations of this program with
+#  other software, or any other product whatsoever.
+#  
+#  You should have received a copy of the GNU General Public License along
+#  with this program; if not, write the Free Software Foundation, Inc., 59
+#  Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#  
+#  Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+#  Mountain View, CA  94043, or:
+#  
+#  http://www.sgi.com 
+#  
+#  For further information regarding this notice, see: 
+#  
+#  http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+#
+#
+# fill2fs:
+#   Fill a filesystem, or write a specified number of bits.
+#   Script runs deterministically given a seed for the random number
+#   generator. Will generate the same set of directories and files,
+#   with the only source of variation the precise point at which the
+#   filesystem fills up. When used with XFS filesystems, and when 
+#   the filesize is small, XFS pre-allocation may cause the filesystem
+#   to "fill up" before the actual disk space is gone. Using this
+#   script repeatedly, with a delay between invocations, to account
+#   for extent flushing, will allow more of the filesystem to be filled.
+#
+#   All generated files are checksummed and this sum is stored in the
+#   filename (files are named: <sequence number>.<checksum>.data.
+#   Normally script is invoked using the --list option, which causes all
+#   data files to be written to standard output (--list=-) or a file
+#   (--list=filename). This list can be fed into fill2fs_check, which
+#   recomputes the checksums and flags any errors.
+#
+#   The --stddev=0 forces all files to be precisely --filesize bytes in
+#   length, some other value (--stddev=val) produces filesizes with a 
+#   normal distribution with standard deviation val. If not specified
+#   most file sizes are set to lie within 30% of the requested file size.
+#
+#   fill2fs is not guaranteed to write the requested number of bytes, or
+#   fill the filesystem completely. However, it and fill2 are both very
+#   careful about establishing when write operations fail. When the 
+#   --verbose option is used the number of bytes "actually written"
+#   is guaranteed to be the number of bytes on disk.
+#
+#   $Id$
+#
+
+use Getopt::Long;
+use File::Basename;
+
+chomp($os = `uname`);
+
+#
+# fsinfo: get filesystem info put it into the global namespace, assigns:
+#      $dev, $type, $blocks, $used, $avail, $cap, $mnt, $mnt_options
+#      $fsblocks, $fsblocksize, $agblocks, $agcount, $imax_pct, $logblocks
+#      $logstart, $internal
+#
+# if $verbose is set then output fs info to STDERR
+#
+
+sub fsinfo {
+  my($file) = $_[0];
+
+  # filesystem space and mount point
+  
+  $cmd = "df" if ($os =~ /IRIX/);
+  $cmd = "df -P -T --block-size=512" if ($os =~ /Linux/);
+  chomp($_ = `$cmd $file | tail -1`);
+  $n = ($dev, $type, $blocks, $used, $avail, $cap, $mnt) = split(/ +/);
+  die("df failed") if ($n != 7);
+
+  if ($fscheck && $type ne "xfs") {
+    die("Error: $progname: filesystem is not xfs")
+  }
+
+  # how was this filesystem mounted
+  $_ = `grep $dev /etc/mtab`;
+  @mtab = split(/ +/);
+  $mnt_options = $mtab[3];
+
+  # xfs_db: read only, use the default superblock, print everything
+  die("Error: $progname: can't read device: \"$dev\"\n") if (! -r $dev);
+  $_=`xfs_db -r -c sb -c p $dev`;
+  # multiline matching ^$ refers to individual lines...
+  /^dblocks = (\d+)$/m;                $fsblocks=$1;
+  /^blocksize = (\d+)$/m;      $fsblocksize=$1;
+  /^agblocks = (\d+)$/m;       $agblocks=$1;
+  /^agcount = (\d+)$/m;                $agcount=$1;
+  /^imax_pct = (\d+)$/m;       $imax_pct=$1;
+  /^logblocks = (\d+)$/m;      $logblocks=$1;
+  /^logstart = (\d+)$/m;       $logstart=$1;
+  $internal = $logstart > 0 ? " (internal)" : "";
+
+  $verbose && print STDERR <<"EOF"
+Filesystem information:
+  type=$type; device=$dev
+  mount point=$mnt; mount options=$mnt_options
+  percent full=$cap; size (512 byte blocks)=$blocks; used=$used; avail=$avail
+  total filesystem size (fs blocks)=$fsblocks; fs block size=$fsblocksize; imax_pct=$imax_pct
+  agcount=$agcount; agblocks=$agblocks; logblocks=$logblocks; logstart=$logstart$internal
+EOF
+}
+
+
+# returns numbers with a normal distribution
+sub normal {
+  my($mean) = $_[0];
+  my($stddev) = $_[1];
+
+  $x = -6.0;
+  for ($i = 0; $i < 12; $i++) {
+    $x += rand;
+  }
+
+  $x = $mean + $stddev * $x;
+  return $x;
+}
+
+#
+# determine script location and find fill2
+#
+
+chomp($cwd = `pwd`);
+chomp($_ = `which fill2 2>&1 | head -1`);
+if (-x $_) {
+  # look in the path
+  $fill2 = fill2;
+}
+else {
+  # in the same directory - get absolute path
+  chomp($dirname = dirname $0);
+  if ($dirname =~ m!^/.*!) {
+    $fill2 = $dirname . "/fill2";
+  }
+  else {
+    # relative
+    $fill2 = $cwd . "/" . $dirname . "/fill2";
+  }    
+  if (! -x $fill2) {
+    die("Error: $progname: can't find fill2, tried \"$fill2\"\n");
+  }
+}
+
+#
+# process/check args
+#
+
+$progname=$0;
+GetOptions("bytes=f" => \$bytes,
+          "dir=s" => \$root,
+          "filesize=i" => \$filesize,
+          "force!" => \$force,
+          "help!" => \$help,
+          "list=s" => \$list,
+          "fscheck!" => \$fscheck,
+          "percent=f" => \$percentage,
+          "seed=i" => \$seed,
+          "stddev=i" => \$stddev,
+          "verbose!" => \$verbose);
+
+
+# check/remove output directory, get filesystem info
+if (defined $help
+    || (! defined $root && @ARGV != 1)
+    || (defined $root && @ARGV == 1))
+{
+  # newline at end of die message suppresses line number
+  print STDERR <<"EOF";
+Usage: $progname [options] root_dir
+Options:
+  --bytes=num       total number of bytes to write
+  --dir=name        where to write files
+  --filesize=num    set all files to num bytes in size
+  --force           overwrite any existing files
+  --help            print this help message
+  --list=filename   store created files to filename (- for stdout)
+  --percent=num     percentage of filesystem to fill
+  --seed=num        seed for random number generator
+  --stddev          set file size standard deviation
+  --verbose         verbose output
+EOF
+  exit(1) unless defined $help;
+  # otherwise...
+  exit(0);
+    
+}
+
+
+#
+# lots of boring argument checking
+#
+
+# root directory and filesystem info
+$root = $ARGV[0] if (@ARGV == 1);
+if (-e $root) {
+  if (! $force) {
+    die("Error: $progname: \"$root\" already exists\n");
+  }
+  else {
+    $verbose && print STDERR "Removing \"$root\"... ";
+    system("rm -rf $root");
+    $verbose && print STDERR "done\n";
+  }
+}
+chomp($root_dir = dirname $root);
+fsinfo $root_dir;
+
+# $list can be "-" for stdout, perl open ">-" opens stdout
+open LIST, ">$list" if (defined $list);
+
+# how many bytes should we write
+if (defined $bytes && defined $percentage) {
+  die("Error: $progname: can't specify --bytes and --percent\n");
+}
+# check percentage
+if (defined $percentage && ($percentage < 0 || $percentage > 100)) {
+  die("Error: $progname: invalid percentage\n");
+}
+if (! defined $bytes && ! defined $percentage) {
+  $bytes = $avail * 512;
+  $verbose && print STDERR <<"EOF";
+Neither --bytes nor --percent specified: filling filesystem ($bytes bytes)
+EOF
+}
+elsif (! defined $bytes) {
+  $bytes = int($blocks * 512 * $percentage / 100.0);
+}
+if (($bytes > $blocks * 512) || (! $force && $bytes > $avail * 512))
+{
+  die("Error: $progname: not enough free disk space, disk is $cap full\n");
+}
+
+
+
+#
+# To get fix sized files set stddev to 0. The default is to make most files
+# within 30% of the requested filesize (or 4k if filesize is not specified).
+# Set the standard deviation to be half of the required percentage: ~95% of
+# samples lie within 2 standard deviations of the mean.
+#
+
+$filesize = 4096 if (! defined $filesize);
+die("Error: $progname: --filesize must be >= 1 byte") if ($filesize < 1);
+$stddev = 0.5 * 0.3 * $filesize if (! defined $stddev);
+$seed = time ^ $$ if (! defined $seed);
+srand $seed;
+umask 0000;
+mkdir $root, 0777;
+chdir $root;
+$total = 0;
+$files = 0;
+$dirs = 0;
+$d = 0;
+
+#
+# fill filesystem
+#
+
+$verbose && print STDERR "Writing $bytes bytes (seed is $seed)... ";
+while ($total < $bytes) {
+  $r = rand(3.0);
+
+  if (($d == 0 && $r < 0.5) || ($d > 0 && $r >= 0.0 && $r < 2.4)) {
+    # create a new data file
+    $n = sprintf("%04d", $names[$d]++);
+    if ($stddev == 0) {
+      $size = $filesize;
+    }
+    else {
+      $size = int(normal($filesize, $stddev));
+    }
+    $left = $bytes - $total;
+    $size = 0 if ($size < 0);
+    $size = $left if ($size > $left);
+
+    # fill2 will fail if the filesystem is full - not an error!
+    $cmd = "$fill2 -d nbytes=$size,linelength=72,seed=$n -b 4k $n";
+    $cmd .= " > /dev/null 2>&1" if (! $verbose);
+    if (system($cmd) != 0) {
+      if ($verbose) {
+       warn("can't create a file - assuming filesystem is full\n");
+      }
+      if (-e $n && unlink($n) != 1) {
+       warn("couldn't delete \"$n\"");
+      }
+      last;
+    }
+    $_ = `sum $n`;
+    ($sum) = split(/ +/);
+    $name = "$n.$sum.data";
+    $cmd = "mv $n $name";      # perl rename failed earlier than using mv
+    $cmd .= " > /dev/null 2>&1" if (! $verbose);
+    if (system($cmd) != 0) {
+      if ($verbose) {
+       warn("can't rename a file - assuming filesystem is full\n");
+      }
+      if (-e $name && unlink($name) != 1) {
+       warn("couldn't delete \"$name\"");
+      }
+      last;
+    }
+    if (defined $list) {
+      chomp($_ = `pwd`);
+      printf LIST ("%s/%s\n", $_, $name);
+    }
+    $total += $size;
+    $files++;
+  }
+  # note that if d==0 create directories more frequently than files
+  elsif (($d == 0 && $r >= 0.5) || ($d > 0 && $r >= 2.4 && $r < 2.7)) {
+    # create a new directory and descend
+    $name = sprintf("%04d.d", $names[$d]++);
+    if (! mkdir($name, 0777)) {
+      warn("can't make a directory - assuming filesystem is full\n");
+      last;
+    }
+    chdir($name) or die();
+    $d++;
+    $dirs++;
+  }
+  elsif ($r >= 2.7 && $r < 3.0) {
+    # pop up to the parent directory same probability as descend
+    die("Error: $progname: panic: shouldn't be here!") if ($d == 0);
+    chdir("..") or die();
+    $d--;
+  }
+}
+# make sure we return to the original working directory
+chdir($cwd) or die();
+$verbose && print STDERR "done\n";
+$verbose && print STDERR "$total bytes (in $files files and $dirs directories) were actually written\n";
+close LIST;
+exit(0) if ($total = $bytes);
+exit(1) if ($total == 0);
+exit(2) if ($total > 0 && $total < $bytes);
+
+# - to sum all generated data:
+#   find /home/fill/ -name \*data | xargs ls -al | awk '{total = total + $5; } END { printf("total = %d bytes\n", total); }'
+# - to find any files not of the required size
+#   find . -name \*data -a \! -size 4096c
+# - count new files
+#   find ./fill -name \*.data | wc
+# - count new directories
+#   find ./fill -name \*.d | wc
diff --git a/src/fill2fs_check b/src/fill2fs_check
new file mode 100755 (executable)
index 0000000..1253091
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/perl -w
+#
+
+#
+#  Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+#  
+#  This program is free software; you can redistribute it and/or modify it
+#  under the terms of version 2 of the GNU General Public License as
+#  published by the Free Software Foundation.
+#  
+#  This program is distributed in the hope that it would be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  
+#  Further, this software is distributed without any warranty that it is
+#  free of the rightful claim of any third person regarding infringement
+#  or the like.  Any license provided herein, whether implied or
+#  otherwise, applies only to this software file.  Patent licenses, if
+#  any, provided herein do not apply to combinations of this program with
+#  other software, or any other product whatsoever.
+#  
+#  You should have received a copy of the GNU General Public License along
+#  with this program; if not, write the Free Software Foundation, Inc., 59
+#  Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#  
+#  Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+#  Mountain View, CA  94043, or:
+#  
+#  http://www.sgi.com 
+#  
+#  For further information regarding this notice, see: 
+#  
+#  http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+#
+#
+# fill2fs_check:
+#   Read a manifest generated by fill2fs from the command
+#   line or stdin, checksum every file listed
+#
+#   $Id$
+#
+
+use File::Basename;
+
+while (<>) {
+  chomp;
+  if ( ! -e $_) {
+    print "$0: $_ not found\n";
+    exit(1);
+  }
+  (undef, $expected) = split(/\./, basename $_);
+  chomp($sum = `sum $_`);
+  ($actual) = split(/\s+/, $sum);
+  if ($actual != $expected) {
+    print "$0: checksum is wrong for \"$_\"\n";
+    exit(1);
+  }
+}
diff --git a/src/fsstress.c b/src/fsstress.c
new file mode 100644 (file)
index 0000000..548bfd5
--- /dev/null
@@ -0,0 +1,2499 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include "global.h"
+
+/* XXX temporary hack - error injection is disabled */
+#define ERROR_INJECT_DISABLE 
+#define XFS_ERRTAG_MAX         17
+
+typedef enum {
+       OP_ALLOCSP,
+       OP_ATTR_REMOVE,
+       OP_ATTR_SET,
+       OP_BULKSTAT,
+       OP_BULKSTAT1,
+       OP_CHOWN,
+       OP_CREAT,
+       OP_DREAD,
+       OP_DWRITE,
+       OP_FDATASYNC,
+       OP_FREESP,
+       OP_FSYNC,
+       OP_GETDENTS,
+       OP_LINK,
+       OP_MKDIR,
+       OP_MKNOD,
+       OP_READ,
+       OP_READLINK,
+       OP_RENAME,
+       OP_RESVSP,
+       OP_RMDIR,
+       OP_STAT,
+       OP_SYMLINK,
+       OP_SYNC,
+       OP_TRUNCATE,
+       OP_UNLINK,
+       OP_UNRESVSP,
+       OP_WRITE,
+       OP_LAST
+} opty_t;
+
+typedef void (*opfnc_t)(int, long);
+
+typedef struct opdesc {
+       opty_t  op;
+       char    *name;
+       opfnc_t func;
+       int     freq;
+       int     iswrite;
+} opdesc_t;
+
+typedef struct fent {
+       int     id;
+       int     parent;
+} fent_t;
+
+typedef struct flist {
+       int     nfiles;
+       int     nslots;
+       int     tag;
+       fent_t  *fents;
+} flist_t;
+
+typedef struct pathname {
+       int     len;
+       char    *path;
+} pathname_t;
+
+#define        FT_DIR  0
+#define        FT_DIRm (1 << FT_DIR)
+#define        FT_REG  1
+#define        FT_REGm (1 << FT_REG)
+#define        FT_SYM  2
+#define        FT_SYMm (1 << FT_SYM)
+#define        FT_DEV  3
+#define        FT_DEVm (1 << FT_DEV)
+#define        FT_RTF  4
+#define        FT_RTFm (1 << FT_RTF)
+#define        FT_nft  5
+#define        FT_ANYm ((1 << FT_nft) - 1)
+#define        FT_REGFILE      (FT_REGm | FT_RTFm)
+#define        FT_NOTDIR       (FT_ANYm & ~FT_DIRm)
+
+#define        FLIST_SLOT_INCR 16
+#define        NDCACHE 64
+
+#define        MAXFSIZE        ((1ULL << 63) - 1ULL)
+#define        MAXFSIZE32      ((1ULL << 40) - 1ULL)
+
+void   allocsp_f(int, long);
+void   attr_remove_f(int, long);
+void   attr_set_f(int, long);
+void   bulkstat_f(int, long);
+void   bulkstat1_f(int, long);
+void   chown_f(int, long);
+void   creat_f(int, long);
+void   dread_f(int, long);
+void   dwrite_f(int, long);
+void   fdatasync_f(int, long);
+void   freesp_f(int, long);
+void   fsync_f(int, long);
+void   getdents_f(int, long);
+void   link_f(int, long);
+void   mkdir_f(int, long);
+void   mknod_f(int, long);
+void   read_f(int, long);
+void   readlink_f(int, long);
+void   rename_f(int, long);
+void   resvsp_f(int, long);
+void   rmdir_f(int, long);
+void   stat_f(int, long);
+void   symlink_f(int, long);
+void   sync_f(int, long);
+void   truncate_f(int, long);
+void   unlink_f(int, long);
+void   unresvsp_f(int, long);
+void   write_f(int, long);
+
+opdesc_t       ops[] = {
+       { OP_ALLOCSP, "allocsp", allocsp_f, 1, 1 },
+       { OP_ATTR_REMOVE, "attr_remove", attr_remove_f, /* 1 */ 0, 1 },
+       { OP_ATTR_SET, "attr_set", attr_set_f, /* 2 */ 0, 1 },
+       { OP_BULKSTAT, "bulkstat", bulkstat_f, 1, 0 },
+       { OP_BULKSTAT1, "bulkstat1", bulkstat1_f, 1, 0 },
+       { OP_CHOWN, "chown", chown_f, 3, 1 },
+       { OP_CREAT, "creat", creat_f, 4, 1 },
+       { OP_DREAD, "dread", dread_f, /* 4 */ 0, 0 },
+       { OP_DWRITE, "dwrite", dwrite_f, /* 4 */ 0, 1 },
+       { OP_FDATASYNC, "fdatasync", fdatasync_f, 1, 1 },
+       { OP_FREESP, "freesp", freesp_f, 1, 1 },
+       { OP_FSYNC, "fsync", fsync_f, 1, 1 },
+       { OP_GETDENTS, "getdents", getdents_f, 1, 0 },
+       { OP_LINK, "link", link_f, 1, 1 },
+       { OP_MKDIR, "mkdir", mkdir_f, 2, 1 },
+       { OP_MKNOD, "mknod", mknod_f, 2, 1 },
+       { OP_READ, "read", read_f, 1, 0 },
+       { OP_READLINK, "readlink", readlink_f, 1, 0 },
+       { OP_RENAME, "rename", rename_f, 2, 1 },
+       { OP_RESVSP, "resvsp", resvsp_f, 1, 1 },
+       { OP_RMDIR, "rmdir", rmdir_f, 1, 1 },
+       { OP_STAT, "stat", stat_f, 1, 0 },
+       { OP_SYMLINK, "symlink", symlink_f, 2, 1 },
+       { OP_SYNC, "sync", sync_f, 1, 0 },
+       { OP_TRUNCATE, "truncate", truncate_f, 2, 1 },
+       { OP_UNLINK, "unlink", unlink_f, 1, 1 },
+       { OP_UNRESVSP, "unresvsp", unresvsp_f, 1, 1 },
+       { OP_WRITE, "write", write_f, 4, 1 },
+}, *ops_end;
+
+flist_t        flist[FT_nft] = {
+       { 0, 0, 'd', NULL },
+       { 0, 0, 'f', NULL },
+       { 0, 0, 'l', NULL },
+       { 0, 0, 'c', NULL },
+       { 0, 0, 'r', NULL },
+};
+
+int            dcache[NDCACHE];
+int            errrange;
+int            errtag;
+opty_t         *freq_table;
+int            freq_table_size;
+xfs_fsop_geom_t        geom;
+char           *homedir;
+int            *ilist;
+int            ilistlen;
+off64_t                maxfsize;
+char           *myprog;
+int            namerand;
+int            nameseq;
+int            nops;
+int            nproc = 1;
+int            operations = 1;
+int            procid;
+int            rtpct;
+unsigned long  seed = 0;
+ino_t          top_ino;
+int            verbose = 0;
+
+void   add_to_flist(int, int, int);
+void   append_pathname(pathname_t *, char *);
+int    attr_list_path(pathname_t *, char *, const int, int,
+                      attrlist_cursor_t *);
+int    attr_remove_path(pathname_t *, const char *, int);
+int    attr_set_path(pathname_t *, const char *, const char *, const int, int);
+void   check_cwd(void);
+int    creat_path(pathname_t *, mode_t);
+void   dcache_enter(int, int);
+void   dcache_init(void);
+fent_t *dcache_lookup(int);
+void   dcache_purge(int);
+void   del_from_flist(int, int);
+int    dirid_to_name(char *, int);
+void   doproc(void);
+void   fent_to_name(pathname_t *, flist_t *, fent_t *);
+void   fix_parent(int, int);
+void   free_pathname(pathname_t *);
+int    generate_fname(fent_t *, int, pathname_t *, int *, int *);
+int    get_fname(int, long, pathname_t *, flist_t **, fent_t **, int *);
+void   init_pathname(pathname_t *);
+int    lchown_path(pathname_t *, uid_t, gid_t);
+int    link_path(pathname_t *, pathname_t *);
+int    lstat64_path(pathname_t *, struct stat64 *);
+void   make_freq_table(void);
+int    mkdir_path(pathname_t *, mode_t);
+int    mknod_path(pathname_t *, mode_t, dev_t);
+void   namerandpad(int, char *, int);
+int    open_path(pathname_t *, int);
+DIR    *opendir_path(pathname_t *);
+void   process_freq(char *);
+int    readlink_path(pathname_t *, char *, size_t);
+int    rename_path(pathname_t *, pathname_t *);
+int    rmdir_path(pathname_t *);
+void   separate_pathname(pathname_t *, char *, pathname_t *);
+void   show_ops(int, char *);
+int    stat64_path(pathname_t *, struct stat64 *);
+int    symlink_path(const char *, pathname_t *);
+int    truncate64_path(pathname_t *, off64_t);
+int    unlink_path(pathname_t *);
+void   usage(void);
+void   write_freq(void);
+void   zero_freq(void);
+
+int main(int argc, char **argv)
+{
+       char            buf[10];
+       int             c;
+       char            *dirname = NULL;
+       int             fd;
+       int             i;
+       int             j;
+       char            *p;
+       int             stat;
+       struct timeval  t;
+       ptrdiff_t       srval;
+        int             nousage=0;
+       xfs_error_injection_t   err_inj;
+
+       errrange = errtag = 0;
+       umask(0);
+       nops = sizeof(ops) / sizeof(ops[0]);
+       ops_end = &ops[nops];
+       myprog = argv[0];
+       while ((c = getopt(argc, argv, "d:e:f:i:n:p:rs:vwzHS")) != -1) {
+               switch (c) {
+               case 'd':
+                       dirname = optarg;
+                       break;
+               case 'e':
+                       sscanf(optarg, "%d", &errtag);
+                       if (errtag < 0) {
+                               errtag = -errtag;
+                               errrange = 1;
+                       } else if (errtag == 0)
+                               errtag = -1;
+                       if (errtag >= XFS_ERRTAG_MAX) {
+                               fprintf(stderr,
+                                       "error tag %d too large (max %d)\n",
+                                       errtag, XFS_ERRTAG_MAX - 1);
+                               exit(1);
+                       }
+                       break;
+               case 'f':
+                       process_freq(optarg);
+                       break;
+               case 'i':
+                       ilist = realloc(ilist, ++ilistlen * sizeof(*ilist));
+                       ilist[ilistlen - 1] = strtol(optarg, &p, 16);
+                       break;
+               case 'n':
+                       operations = atoi(optarg);
+                       break;
+               case 'p':
+                       nproc = atoi(optarg);
+                       break;
+               case 'r':
+                       namerand = 1;
+                       break;
+               case 's':
+                       seed = strtoul(optarg, NULL, 0);
+                       break;
+               case 'v':
+                       verbose = 1;
+                       break;
+               case 'w':
+                       write_freq();
+                       break;
+               case 'z':
+                       zero_freq();
+                       break;
+               case 'S':
+                       show_ops(0, NULL);
+                       printf("\n");
+                        nousage=1;
+                       break;
+               case '?':
+                       fprintf(stderr, "%s - invalid parameters\n",
+                               myprog);
+                       /* fall through */
+               case 'H':
+                       usage();
+                       exit(1);
+               }
+       }
+        
+        if (!dirname) {
+            /* no directory specified */
+            if (!nousage) usage();
+            exit(1);
+        }
+        
+       (void)mkdir(dirname, 0777);
+       if (chdir(dirname) < 0) {
+               perror(dirname);
+               exit(1);
+       }
+       sprintf(buf, "fss%x", getpid());
+       fd = creat(buf, 0666);
+       if (lseek64(fd, (off64_t)(MAXFSIZE32 + 1ULL), SEEK_SET) < 0)
+               maxfsize = (off64_t)MAXFSIZE32;
+       else
+               maxfsize = (off64_t)MAXFSIZE;
+       make_freq_table();
+       dcache_init();
+       setlinebuf(stdout);
+       if (!seed) {
+               gettimeofday(&t, (void *)NULL);
+               seed = (int)t.tv_sec ^ (int)t.tv_usec;
+               printf("seed = %ld\n", seed);
+       }
+       i = ioctl(fd, XFS_IOC_FSGEOMETRY, &geom);
+       if (i >= 0 && geom.rtblocks)
+               rtpct = MIN(MAX(geom.rtblocks * 100 /
+                               (geom.rtblocks + geom.datablocks), 1), 99);
+       else
+               rtpct = 0;
+       if (errtag != 0) {
+               if (errrange == 0) {
+                       if (errtag <= 0) {
+                               srandom(seed);
+                               j = random() % 100;
+
+                               for (i = 0; i < j; i++)
+                                       (void) random();
+
+                               errtag = (random() % (XFS_ERRTAG_MAX-1)) + 1;
+                       }
+               } else {
+                       srandom(seed);
+                       j = random() % 100;
+
+                       for (i = 0; i < j; i++)
+                               (void) random();
+
+                       errtag += (random() % (XFS_ERRTAG_MAX - errtag));
+               }
+               printf("Injecting failure on tag #%d\n", errtag);
+#ifndef ERROR_INJECT_DISABLE
+               err_inj.errtag = errtag;
+               err_inj.fd = fd;
+               srval = ioctl(fd, XFS_IOC_ERROR_INJECTION, &err_inj);
+#else
+                srval = -1;
+#endif
+               if (srval < -1) {
+                       perror("fsstress - XFS_SYSSGI error injection call");
+                       close(fd);
+                       unlink(buf);
+                       exit(1);
+               }
+       } else
+               close(fd);
+       unlink(buf);
+       for (i = 0; i < nproc; i++) {
+               if (fork() == 0) {
+                       procid = i;
+                       doproc();
+                       return 0;
+               }
+       }
+       while (wait(&stat) > 0)
+               continue;
+       if (errtag != 0) {
+#ifndef ERROR_INJECT_DISABLE
+               err_inj.errtag = 0;
+               err_inj.fd = fd;
+               if((srval = ioctl(fd, XFS_IOC_ERROR_CLEARALL, &err_inj)) != 0) {
+#else
+                if (1) {
+#endif
+                       perror("fsstress - XFS_SYSSGI clear error injection call");
+                       close(fd);
+                       exit(1);
+               }
+               close(fd);
+       }
+
+       return 0;
+}
+
+void
+add_to_flist(int ft, int id, int parent)
+{
+       fent_t  *fep;
+       flist_t *ftp;
+
+       ftp = &flist[ft];
+       if (ftp->nfiles == ftp->nslots) {
+               ftp->nslots += FLIST_SLOT_INCR;
+               ftp->fents = realloc(ftp->fents, ftp->nslots * sizeof(fent_t));
+       }
+       fep = &ftp->fents[ftp->nfiles++];
+       fep->id = id;
+       fep->parent = parent;
+}
+
+void
+append_pathname(pathname_t *name, char *str)
+{
+       int     len;
+
+       len = strlen(str);
+#ifdef DEBUG
+       if (len && *str == '/' && name->len == 0) {
+               fprintf(stderr, "fsstress: append_pathname failure\n");
+               chdir(homedir);
+               abort();
+               /* NOTREACHED */
+       }
+#endif
+       name->path = realloc(name->path, name->len + 1 + len);
+       strcpy(&name->path[name->len], str);
+       name->len += len;
+}
+
+int
+attr_list_path(pathname_t *name, char *buffer, const int buffersize, int flags,
+              attrlist_cursor_t *cursor)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = attr_list(name->path, buffer, buffersize, flags, cursor);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = attr_list_path(&newname, buffer, buffersize, flags,
+                       cursor);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+int
+attr_remove_path(pathname_t *name, const char *attrname, int flags)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = attr_remove(name->path, attrname, flags);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = attr_remove_path(&newname, attrname, flags);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+int
+attr_set_path(pathname_t *name, const char *attrname, const char *attrvalue,
+             const int valuelength, int flags)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = attr_set(name->path, attrname, attrvalue, valuelength, flags);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = attr_set_path(&newname, attrname, attrvalue, valuelength,
+                       flags);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+void
+check_cwd(void)
+{
+#ifdef DEBUG
+       struct stat64   statbuf;
+
+       if (stat64(".", &statbuf) == 0 && statbuf.st_ino == top_ino)
+               return;
+       chdir(homedir);
+       fprintf(stderr, "fsstress: check_cwd failure\n");
+       abort();
+       /* NOTREACHED */
+#endif
+}
+
+int
+creat_path(pathname_t *name, mode_t mode)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = creat(name->path, mode);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = creat_path(&newname, mode);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+void
+dcache_enter(int dirid, int slot)
+{
+       dcache[dirid % NDCACHE] = slot;
+}
+
+void
+dcache_init(void)
+{
+       int     i;
+
+       for (i = 0; i < NDCACHE; i++)
+               dcache[i] = -1;
+}
+
+fent_t *
+dcache_lookup(int dirid)
+{
+       fent_t  *fep;
+       int     i;
+
+       i = dcache[dirid % NDCACHE];
+       if (i >= 0 && (fep = &flist[FT_DIR].fents[i])->id == dirid)
+               return fep;
+       return NULL;
+}
+
+void
+dcache_purge(int dirid)
+{
+       int     *dcp;
+
+       dcp = &dcache[dirid % NDCACHE];
+       if (*dcp >= 0 && flist[FT_DIR].fents[*dcp].id == dirid)
+               *dcp = -1;
+}
+
+void
+del_from_flist(int ft, int slot)
+{
+       flist_t *ftp;
+
+       ftp = &flist[ft];
+       if (ft == FT_DIR)
+               dcache_purge(ftp->fents[slot].id);
+       if (slot != ftp->nfiles - 1) {
+               if (ft == FT_DIR)
+                       dcache_purge(ftp->fents[ftp->nfiles - 1].id);
+               ftp->fents[slot] = ftp->fents[--ftp->nfiles];
+       } else
+               ftp->nfiles--;
+}
+
+fent_t *
+dirid_to_fent(int dirid)
+{
+       fent_t  *efep;
+       fent_t  *fep;
+       flist_t *flp;
+
+       if ((fep = dcache_lookup(dirid)))
+               return fep;
+       flp = &flist[FT_DIR];
+       for (fep = flp->fents, efep = &fep[flp->nfiles]; fep < efep; fep++) {
+               if (fep->id == dirid) {
+                       dcache_enter(dirid, fep - flp->fents);
+                       return fep;
+               }
+       }
+       return NULL;
+}
+
+void
+doproc(void)
+{
+       struct stat64   statbuf;
+       char            buf[10];
+       int             opno;
+       int             rval;
+       opdesc_t        *p;
+
+       sprintf(buf, "p%x", procid);
+       (void)mkdir(buf, 0777);
+       if (chdir(buf) < 0 || stat64(".", &statbuf) < 0) {
+               perror(buf);
+               _exit(1);
+       }
+       top_ino = statbuf.st_ino;
+       homedir = getcwd(NULL, -1);
+       seed += procid;
+       srandom(seed);
+       if (namerand)
+               namerand = random();
+       for (opno = 0; opno < operations; opno++) {
+               p = &ops[freq_table[random() % freq_table_size]];
+               p->func(opno, random());
+               /*
+                * test for forced shutdown by stat'ing the test
+                * directory.  If this stat returns EIO, assume
+                * the forced shutdown happened.
+                */
+               if (errtag != 0 && opno % 100 == 0)  {
+                       rval = stat64(".", &statbuf);
+                       if (rval == EIO)  {
+                               fprintf(stderr, "Detected EIO\n");
+                               return;
+                       }
+               }
+       }
+}
+
+void
+fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
+{
+       char    buf[MAXNAMELEN];
+       int     i;
+       fent_t  *pfep;
+
+       if (fep == NULL)
+               return;
+       if (fep->parent != -1) {
+               pfep = dirid_to_fent(fep->parent);
+               fent_to_name(name, &flist[FT_DIR], pfep);
+               append_pathname(name, "/");
+       }
+       i = sprintf(buf, "%c%x", flp->tag, fep->id);
+       namerandpad(fep->id, buf, i);
+       append_pathname(name, buf);
+}
+
+void
+fix_parent(int oldid, int newid)
+{
+       fent_t  *fep;
+       flist_t *flp;
+       int     i;
+       int     j;
+
+       for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
+               for (j = 0, fep = flp->fents; j < flp->nfiles; j++, fep++) {
+                       if (fep->parent == oldid)
+                               fep->parent = newid;
+               }
+       }
+}
+
+void
+free_pathname(pathname_t *name)
+{
+       if (name->path) {
+               free(name->path);
+               name->path = NULL;
+               name->len = 0;
+       }
+}
+
+int
+generate_fname(fent_t *fep, int ft, pathname_t *name, int *idp, int *v)
+{
+       char    buf[MAXNAMELEN];
+       flist_t *flp;
+       int     id;
+       int     j;
+       int     len;
+
+       flp = &flist[ft];
+       len = sprintf(buf, "%c%x", flp->tag, id = nameseq++);
+       namerandpad(id, buf, len);
+       if (fep) {
+               fent_to_name(name, &flist[FT_DIR], fep);
+               append_pathname(name, "/");
+       }
+       append_pathname(name, buf);
+       *idp = id;
+       *v = verbose;
+       for (j = 0; !*v && j < ilistlen; j++) {
+               if (ilist[j] == id) {
+                       *v = 1;
+                       break;
+               }
+       }
+       return 1;
+}
+
+int
+get_fname(int which, long r, pathname_t *name, flist_t **flpp, fent_t **fepp,
+         int *v)
+{
+       int     c;
+       fent_t  *fep;
+       flist_t *flp;
+       int     i;
+       int     j;
+       int     x;
+
+       for (i = 0, c = 0, flp = flist; i < FT_nft; i++, flp++) {
+               if (which & (1 << i))
+                       c += flp->nfiles;
+       }
+       if (c == 0) {
+               if (flpp)
+                       *flpp = NULL;
+               if (fepp)
+                       *fepp = NULL;
+               *v = verbose;
+               return 0;
+       }
+       x = (int)(r % c);
+       for (i = 0, c = 0, flp = flist; i < FT_nft; i++, flp++) {
+               if (which & (1 << i)) {
+                       if (x < c + flp->nfiles) {
+                               fep = &flp->fents[x - c];
+                               if (name)
+                                       fent_to_name(name, flp, fep);
+                               if (flpp)
+                                       *flpp = flp;
+                               if (fepp)
+                                       *fepp = fep;
+                               *v = verbose;
+                               for (j = 0; !*v && j < ilistlen; j++) {
+                                       if (ilist[j] == fep->id) {
+                                               *v = 1;
+                                               break;
+                                       }
+                               }
+                               return 1;
+                       }
+                       c += flp->nfiles;
+               }
+       }
+#ifdef DEBUG
+       fprintf(stderr, "fsstress: get_fname failure\n");
+       abort();
+#endif
+        return -1;
+       /* NOTREACHED */
+}
+
+void
+init_pathname(pathname_t *name)
+{
+       name->len = 0;
+       name->path = NULL;
+}
+
+int
+lchown_path(pathname_t *name, uid_t owner, gid_t group)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = lchown(name->path, owner, group);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = lchown_path(&newname, owner, group);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+int
+link_path(pathname_t *name1, pathname_t *name2)
+{
+       char            buf1[MAXNAMELEN];
+       char            buf2[MAXNAMELEN];
+       int             down1;
+       pathname_t      newname1;
+       pathname_t      newname2;
+       int             rval;
+
+       rval = link(name1->path, name2->path);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name1, buf1, &newname1);
+       separate_pathname(name2, buf2, &newname2);
+       if (strcmp(buf1, buf2) == 0) {
+               if (chdir(buf1) == 0) {
+                       rval = link_path(&newname1, &newname2);
+                       chdir("..");
+               }
+       } else {
+               if (strcmp(buf1, "..") == 0)
+                       down1 = 0;
+               else if (strcmp(buf2, "..") == 0)
+                       down1 = 1;
+               else if (strlen(buf1) == 0)
+                       down1 = 0;
+               else if (strlen(buf2) == 0)
+                       down1 = 1;
+               else
+                       down1 = MAX(newname1.len, 3 + name2->len) <=
+                               MAX(3 + name1->len, newname2.len);
+               if (down1) {
+                       free_pathname(&newname2);
+                       append_pathname(&newname2, "../");
+                       append_pathname(&newname2, name2->path);
+                       if (chdir(buf1) == 0) {
+                               rval = link_path(&newname1, &newname2);
+                               chdir("..");
+                       }
+               } else {
+                       free_pathname(&newname1);
+                       append_pathname(&newname1, "../");
+                       append_pathname(&newname1, name1->path);
+                       if (chdir(buf2) == 0) {
+                               rval = link_path(&newname1, &newname2);
+                               chdir("..");
+                       }
+               }
+       }
+       free_pathname(&newname1);
+       free_pathname(&newname2);
+       return rval;
+}
+
+int
+lstat64_path(pathname_t *name, struct stat64 *sbuf)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = lstat64(name->path, sbuf);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = lstat64_path(&newname, sbuf);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+void
+make_freq_table(void)
+{
+       int             f;
+       int             i;
+       opdesc_t        *p;
+
+       for (p = ops, f = 0; p < ops_end; p++)
+               f += p->freq;
+       freq_table = malloc(f * sizeof(*freq_table));
+       freq_table_size = f;
+       for (p = ops, i = 0; p < ops_end; p++) {
+               for (f = 0; f < p->freq; f++, i++)
+                       freq_table[i] = p->op;
+       }
+}
+
+int
+mkdir_path(pathname_t *name, mode_t mode)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = mkdir(name->path, mode);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = mkdir_path(&newname, mode);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+int
+mknod_path(pathname_t *name, mode_t mode, dev_t dev)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = mknod(name->path, mode, dev);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = mknod_path(&newname, mode, dev);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+void
+namerandpad(int id, char *buf, int i)
+{
+       int             bucket;
+       static int      buckets[] =
+                               { 2, 4, 8, 16, 32, 64, 128, MAXNAMELEN - 1 };
+       int             padlen;
+       int             padmod;
+
+       if (namerand == 0)
+               return;
+       bucket = (id ^ namerand) % (sizeof(buckets) / sizeof(buckets[0]));
+       padmod = buckets[bucket] + 1 - i;
+       if (padmod <= 0)
+               return;
+       padlen = (id ^ namerand) % padmod;
+       if (padlen) {
+               memset(&buf[i], 'X', padlen);
+               buf[i + padlen] = '\0';
+       }
+}
+
+int
+open_path(pathname_t *name, int oflag)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = open(name->path, oflag);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = open_path(&newname, oflag);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+DIR *
+opendir_path(pathname_t *name)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       DIR             *rval;
+
+       rval = opendir(name->path);
+       if (rval || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = opendir_path(&newname);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+void
+process_freq(char *arg)
+{
+       opdesc_t        *p;
+       char            *s;
+
+       s = strchr(arg, '=');
+       if (s == NULL) {
+               fprintf(stderr, "bad argument '%s'\n", arg);
+               exit(1);
+       }
+       *s++ = '\0';
+       for (p = ops; p < ops_end; p++) {
+               if (strcmp(arg, p->name) == 0) {
+                       p->freq = atoi(s);
+                       return;
+               }
+       }
+       fprintf(stderr, "can't find op type %s for -f\n", arg);
+       exit(1);
+}
+
+int
+readlink_path(pathname_t *name, char *lbuf, size_t lbufsiz)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = readlink(name->path, lbuf, lbufsiz);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = readlink_path(&newname, lbuf, lbufsiz);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+int
+rename_path(pathname_t *name1, pathname_t *name2)
+{
+       char            buf1[MAXNAMELEN];
+       char            buf2[MAXNAMELEN];
+       int             down1;
+       pathname_t      newname1;
+       pathname_t      newname2;
+       int             rval;
+
+       rval = rename(name1->path, name2->path);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name1, buf1, &newname1);
+       separate_pathname(name2, buf2, &newname2);
+       if (strcmp(buf1, buf2) == 0) {
+               if (chdir(buf1) == 0) {
+                       rval = rename_path(&newname1, &newname2);
+                       chdir("..");
+               }
+       } else {
+               if (strcmp(buf1, "..") == 0)
+                       down1 = 0;
+               else if (strcmp(buf2, "..") == 0)
+                       down1 = 1;
+               else if (strlen(buf1) == 0)
+                       down1 = 0;
+               else if (strlen(buf2) == 0)
+                       down1 = 1;
+               else
+                       down1 = MAX(newname1.len, 3 + name2->len) <=
+                               MAX(3 + name1->len, newname2.len);
+               if (down1) {
+                       free_pathname(&newname2);
+                       append_pathname(&newname2, "../");
+                       append_pathname(&newname2, name2->path);
+                       if (chdir(buf1) == 0) {
+                               rval = rename_path(&newname1, &newname2);
+                               chdir("..");
+                       }
+               } else {
+                       free_pathname(&newname1);
+                       append_pathname(&newname1, "../");
+                       append_pathname(&newname1, name1->path);
+                       if (chdir(buf2) == 0) {
+                               rval = rename_path(&newname1, &newname2);
+                               chdir("..");
+                       }
+               }
+       }
+       free_pathname(&newname1);
+       free_pathname(&newname2);
+       return rval;
+}
+
+int
+rmdir_path(pathname_t *name)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = rmdir(name->path);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = rmdir_path(&newname);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+void
+separate_pathname(pathname_t *name, char *buf, pathname_t *newname)
+{
+       char    *slash;
+
+       init_pathname(newname);
+       slash = strchr(name->path, '/');
+       if (slash == NULL) {
+               buf[0] = '\0';
+               return;
+       }
+       *slash = '\0';
+       strcpy(buf, name->path);
+       *slash = '/';
+       append_pathname(newname, slash + 1);
+}
+
+#define WIDTH 80
+
+void
+show_ops(int flag, char *lead_str)
+{
+       opdesc_t        *p;
+
+        if (flag<0) {
+                /* print in list form */
+                int             x = WIDTH;
+                
+               for (p = ops; p < ops_end; p++) {
+                       if (lead_str != NULL && x+strlen(p->name)>=WIDTH-5)
+                               x=printf("%s%s", (p==ops)?"":"\n", lead_str);
+                        x+=printf("%s ", p->name);
+                }
+                printf("\n");
+        } else {
+               int             f;
+               for (f = 0, p = ops; p < ops_end; p++)
+                       f += p->freq;
+
+               if (f == 0)
+                       flag = 1;
+
+               for (p = ops; p < ops_end; p++) {
+                       if (flag != 0 || p->freq > 0) {
+                               if (lead_str != NULL)
+                                       printf("%s", lead_str);
+                               printf("%20s %d/%d %s\n",
+                               p->name, p->freq, f,
+                               (p->iswrite == 0) ? " " : "write op");
+                       }
+                }
+       }
+}
+
+int
+stat64_path(pathname_t *name, struct stat64 *sbuf)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = stat64(name->path, sbuf);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = stat64_path(&newname, sbuf);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+int
+symlink_path(const char *name1, pathname_t *name)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+        
+        if (!strcmp(name1, name->path)) {
+            printf("yikes! %s %s\n", name1, name->path);
+            return 0;
+        }
+
+       rval = symlink(name1, name->path);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = symlink_path(name1, &newname);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+int
+truncate64_path(pathname_t *name, off64_t length)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = truncate64(name->path, length);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = truncate64_path(&newname, length);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+int
+unlink_path(pathname_t *name)
+{
+       char            buf[MAXNAMELEN];
+       pathname_t      newname;
+       int             rval;
+
+       rval = unlink(name->path);
+       if (rval >= 0 || errno != ENAMETOOLONG)
+               return rval;
+       separate_pathname(name, buf, &newname);
+       if (chdir(buf) == 0) {
+               rval = unlink_path(&newname);
+               chdir("..");
+       }
+       free_pathname(&newname);
+       return rval;
+}
+
+void
+usage(void)
+{
+       printf("Usage: %s -H   or\n", myprog);
+       printf("       %s [-d dir][-e errtg][-f op_name=freq][-n nops]\n",
+               myprog);
+       printf("          [-p nproc][-r len][-s seed][-v][-w][-z][-S]\n");
+       printf("where\n");
+       printf("   -d dir           specifies the base directory for operations\n");
+       printf("   -e errtg         specifies error injection stuff\n");
+       printf("   -f op_name=freq  changes the frequency of option name to freq\n");
+       printf("                    the valid operation names are:\n");
+       show_ops(-1, "                        ");
+       printf("   -n nops          specifies the no. of operations per process (default 1)\n");
+       printf("   -p nproc         specifies the no. of processes (default 1)\n");
+       printf("   -r               specifies random name padding\n");
+       printf("   -s seed          specifies the seed for the random generator (default random)\n");
+       printf("   -v               specifies verbose mode\n");
+       printf("   -w               zeros frequencies of non-write operations\n");
+       printf("   -z               zeros frequencies of all operations\n");
+       printf("   -S               prints the table of operations (omitting zero frequency)\n");
+       printf("   -H               prints usage and exits\n");
+}
+
+void
+write_freq(void)
+{
+       opdesc_t        *p;
+
+       for (p = ops; p < ops_end; p++) {
+               if (!p->iswrite)
+                       p->freq = 0;
+       }
+}
+
+void
+zero_freq(void)
+{
+       opdesc_t        *p;
+
+       for (p = ops; p < ops_end; p++)
+               p->freq = 0;
+}
+
+void
+allocsp_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       int             fd;
+       struct flock64  fl;
+       __int64_t       lr;
+       off64_t         off;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: allocsp - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_RDWR);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: allocsp - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       if (fstat64(fd, &stb) < 0) {
+               if (v)
+                       printf("%d/%d: allocsp - fstat64 %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       lr = ((__int64_t)random() << 32) + random();
+       off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+       off %= maxfsize;
+       fl.l_whence = SEEK_SET;
+       fl.l_start = off;
+       fl.l_len = 0;
+       e = ioctl(fd, XFS_IOC_ALLOCSP64, &fl) < 0 ? errno : 0;
+       if (v)
+               printf("%d/%d: ioctl(XFS_IOC_ALLOCSP64) %s %lld 0 %d\n",
+                       procid, opno, f.path, off, e);
+       free_pathname(&f);
+       close(fd);
+}
+
+void
+attr_remove_f(int opno, long r)
+{
+       attrlist_ent_t          *aep;
+       attrlist_t              *alist;
+       char                    *aname;
+       char                    buf[4096];
+       attrlist_cursor_t       cursor;
+       int                     e;
+       int                     ent;
+       pathname_t              f;
+       int                     total;
+       int                     v;
+       int                     which;
+
+       init_pathname(&f);
+       if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
+               append_pathname(&f, ".");
+       total = 0;
+       bzero(&cursor, sizeof(cursor));
+       do {
+               e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW,
+                       &cursor);
+               check_cwd();
+               if (e)
+                       break;
+               alist = (attrlist_t *)buf;
+               total += alist->al_count;
+       } while (alist->al_more);
+       if (total == 0) {
+               if (v)
+                       printf("%d/%d: attr_remove - no attrs for %s\n",
+                               procid, opno, f.path);
+               free_pathname(&f);
+               return;
+       }
+       which = (int)(random() % total);
+       bzero(&cursor, sizeof(cursor));
+       ent = 0;
+       aname = NULL;
+       do {
+               e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW,
+                       &cursor);
+               check_cwd();
+               if (e)
+                       break;
+               alist = (attrlist_t *)buf;
+               if (which < ent + alist->al_count) {
+                       aep = (attrlist_ent_t *)
+                               &buf[alist->al_offset[which - ent]];
+                       aname = aep->a_name;
+                       break;
+               }
+               ent += alist->al_count;
+       } while (alist->al_more);
+       if (aname == NULL) {
+               if (v)
+                       printf(
+                       "%d/%d: attr_remove - name %d not found at %s\n",       
+                               procid, opno, which, f.path);
+               free_pathname(&f);
+               return;
+       }
+       e = attr_remove_path(&f, aname, ATTR_DONTFOLLOW) < 0 ? errno : 0;
+       check_cwd();
+       if (v)
+               printf("%d/%d: attr_remove %s %s %d\n",
+                       procid, opno, f.path, aname, e);
+       free_pathname(&f);
+}
+
+void
+attr_set_f(int opno, long r)
+{
+       char            aname[10];
+       char            *aval;
+       int             e;
+       pathname_t      f;
+       int             len;
+       static int      lengths[] = { 10, 100, 1000, 10000 };
+       int             li;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
+               append_pathname(&f, ".");
+       sprintf(aname, "a%x", nameseq++);
+       li = (int)(random() % (sizeof(lengths) / sizeof(lengths[0])));
+       len = (int)(random() % lengths[li]);
+       if (len == 0)
+               len = 1;
+       aval = malloc(len);
+       memset(aval, nameseq & 0xff, len);
+       e = attr_set_path(&f, aname, aval, len, ATTR_DONTFOLLOW) < 0 ?
+               errno : 0;
+       check_cwd();
+       free(aval);
+       if (v)
+               printf("%d/%d: attr_set %s %s %d\n", procid, opno, f.path,
+                       aname, e);
+       free_pathname(&f);
+}
+
+void
+bulkstat_f(int opno, long r)
+{
+       int             count;
+       int             fd;
+       __uint64_t      last;
+       int             nent;
+       xfs_bstat_t     *t;
+       __int64_t       total;
+        xfs_fsop_bulkreq_t bsr;
+
+       last = 0;
+       nent = (r % 999) + 2;
+       t = malloc(nent * sizeof(*t));
+       fd = open(".", O_RDONLY);
+       total = 0;
+    
+        bsr.lastip=&last;
+        bsr.icount=nent;
+        bsr.ubuffer=t;
+        bsr.ocount=&count;
+            
+       while (ioctl(fd, XFS_IOC_FSBULKSTAT, &bsr) == 0 && count > 0)
+               total += count;
+       free(t);
+       if (verbose)
+               printf("%d/%d: bulkstat nent %d total %lld\n",
+                       procid, opno, nent, total);
+       close(fd);
+}
+
+void
+bulkstat1_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       int             fd;
+       int             good;
+       __uint64_t      ino;
+       struct stat64   s;
+       xfs_bstat_t     t;
+       int             v;
+        xfs_fsop_bulkreq_t bsr;
+        
+
+       good = random() & 1;
+       if (good) {
+               /* use an inode we know exists */
+               init_pathname(&f);
+               if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
+                       append_pathname(&f, ".");
+               ino = stat64_path(&f, &s) < 0 ? (ino64_t)r : s.st_ino;
+               check_cwd();
+               free_pathname(&f);
+       } else {
+                /* 
+                 * pick a random inode 
+                 *
+                 * note this can generate kernel warning messages
+                 * since bulkstat_one will read the disk block that
+                 * would contain a given inode even if that disk
+                 * block doesn't contain inodes.
+                 *
+                 * this is detected later, but not until after the
+                 * warning is displayed.
+                 *
+                 * "XFS: device 0x825- bad inode magic/vsn daddr 0x0 #0"
+                 *
+                 */
+               ino = (ino64_t)r;
+               v = verbose;
+       }
+       fd = open(".", O_RDONLY);
+        
+        bsr.lastip=&ino;
+        bsr.icount=1;
+        bsr.ubuffer=&t;
+        bsr.ocount=NULL;
+        
+       e = ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bsr) < 0 ? errno : 0;
+       if (v)
+               printf("%d/%d: bulkstat1 %s ino %lld %d\n", 
+                    procid, opno, good?"real":"random", (int64_t)ino, e);
+       close(fd);
+}
+
+void
+chown_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       int             nbits;
+       uid_t           u;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
+               append_pathname(&f, ".");
+       u = (uid_t)random();
+       nbits = (int)(random() % 32);
+       u &= (1 << nbits) - 1;
+       e = lchown_path(&f, u, -1) < 0 ? errno : 0;
+       check_cwd();
+       if (v)
+               printf("%d/%d: chown %s %d %d\n", procid, opno, f.path, u, e);
+       free_pathname(&f);
+}
+
+void
+creat_f(int opno, long r)
+{
+       struct fsxattr  a;
+       int             e;
+       int             e1;
+       int             extsize;
+       pathname_t      f;
+       int             fd;
+       fent_t          *fep;
+       int             id;
+       int             parid;
+       int             type;
+       int             v;
+       int             v1;
+
+       if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v1))
+               parid = -1;
+       else
+               parid = fep->id;
+       init_pathname(&f);
+       type = rtpct ? ((random() % 100) > rtpct ? FT_REG : FT_RTF) : FT_REG;
+       if (type == FT_RTF)
+               extsize = (random() % 10) + 1;
+       else
+               extsize = 0;
+       e = generate_fname(fep, type, &f, &id, &v);
+       v |= v1;
+       if (!e) {
+               if (v) {
+                       fent_to_name(&f, &flist[FT_DIR], fep);
+                       printf("%d/%d: creat - no filename from %s\n",
+                               procid, opno, f.path);
+               }
+               free_pathname(&f);
+               return;
+       }
+       fd = creat_path(&f, 0666);
+       e = fd < 0 ? errno : 0;
+       e1 = 0;
+       check_cwd();
+       if (fd >= 0) {
+               if (extsize && ioctl(fd, XFS_IOC_FSGETXATTR, &a) >= 0) {
+                       a.fsx_xflags |= XFS_XFLAG_REALTIME;
+                       a.fsx_extsize =
+                               geom.rtextsize * geom.blocksize * extsize;
+                       if (ioctl(fd, XFS_IOC_FSSETXATTR, &a) < 0)
+                               e1 = errno;
+               }
+               add_to_flist(type, id, parid);
+               close(fd);
+       }
+       if (v)
+               printf("%d/%d: creat %s x:%d %d %d\n", procid, opno, f.path,
+                       extsize ? a.fsx_extsize : 0, e, e1);
+       free_pathname(&f);
+}
+
+void
+dread_f(int opno, long r)
+{
+       __int64_t       align;
+       char            *buf;
+       struct dioattr  diob;
+       int             e;
+       pathname_t      f;
+       int             fd;
+       size_t          len;
+       __int64_t       lr;
+       off64_t         off;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: dread - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_RDONLY|O_DIRECT);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: dread - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       if (fstat64(fd, &stb) < 0) {
+               if (v)
+                       printf("%d/%d: dread - fstat64 %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       if (stb.st_size == 0) {
+               if (v)
+                       printf("%d/%d: dread - %s zero size\n", procid, opno,
+                               f.path);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       if (ioctl(fd, XFS_IOC_DIOINFO, &diob) < 0) {
+               if (v)
+                       printf(
+                       "%d/%d: dread - ioctl(fd, XFS_IOC_DIOINFO) %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       align = (__int64_t)diob.d_miniosz;
+       lr = ((__int64_t)random() << 32) + random();
+       off = (off64_t)(lr % stb.st_size);
+       off -= (off % align);
+       lseek64(fd, off, SEEK_SET);
+       len = (random() % (getpagesize() * 32)) + 1;
+       len -= (len % align);
+       if (len <= 0)
+               len = align;
+       else if (len > diob.d_maxiosz) 
+               len = diob.d_maxiosz;
+       buf = memalign(diob.d_mem, len);
+       e = read(fd, buf, len) < 0 ? errno : 0;
+       free(buf);
+       if (v)
+               printf("%d/%d: dread %s [%lld,%d] %d\n",
+                       procid, opno, f.path, off, len, e);
+       free_pathname(&f);
+       close(fd);
+}
+
+void
+dwrite_f(int opno, long r)
+{
+       __int64_t       align;
+       char            *buf;
+       struct dioattr  diob;
+       int             e;
+       pathname_t      f;
+       int             fd;
+       size_t          len;
+       __int64_t       lr;
+       off64_t         off;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: dwrite - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_WRONLY|O_DIRECT);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: dwrite - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       if (fstat64(fd, &stb) < 0) {
+               if (v)
+                       printf("%d/%d: dwrite - fstat64 %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       if (ioctl(fd, XFS_IOC_DIOINFO, &diob) < 0) {
+               if (v)
+                       printf(
+                       "%d/%d: dwrite - ioctl(fd, XFS_IOC_DIOINFO) %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       align = (__int64_t)diob.d_miniosz;
+       lr = ((__int64_t)random() << 32) + random();
+       off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+       off -= (off % align);
+       lseek64(fd, off, SEEK_SET);
+       len = (random() % (getpagesize() * 32)) + 1;
+       len -= (len % align);
+       if (len <= 0)
+               len = align;
+       else if (len > diob.d_maxiosz) 
+               len = diob.d_maxiosz;
+       buf = memalign(diob.d_mem, len);
+       off %= maxfsize;
+       lseek64(fd, off, SEEK_SET);
+       memset(buf, nameseq & 0xff, len);
+       e = write(fd, buf, len) < 0 ? errno : 0;
+       free(buf);
+       if (v)
+               printf("%d/%d: dwrite %s [%lld,%d] %d\n",
+                       procid, opno, f.path, off, len, e);
+       free_pathname(&f);
+       close(fd);
+}
+
+void
+fdatasync_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       int             fd;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: fdatasync - no filename\n",
+                               procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_WRONLY);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: fdatasync - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       e = fdatasync(fd) < 0 ? errno : 0;
+       if (v)
+               printf("%d/%d: fdatasync %s %d\n", procid, opno, f.path, e);
+       free_pathname(&f);
+       close(fd);
+}
+
+void
+freesp_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       int             fd;
+       struct flock64  fl;
+       __int64_t       lr;
+       off64_t         off;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: freesp - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_RDWR);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: freesp - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       if (fstat64(fd, &stb) < 0) {
+               if (v)
+                       printf("%d/%d: freesp - fstat64 %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       lr = ((__int64_t)random() << 32) + random();
+       off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+       off %= maxfsize;
+       fl.l_whence = SEEK_SET;
+       fl.l_start = off;
+       fl.l_len = 0;
+       e = ioctl(fd, XFS_IOC_FREESP64, &fl) < 0 ? errno : 0;
+       if (v)
+               printf("%d/%d: ioctl(XFS_IOC_FREESP64) %s %lld 0 %d\n",
+                       procid, opno, f.path, off, e);
+       free_pathname(&f);
+       close(fd);
+}
+
+void
+fsync_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       int             fd;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: fsync - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_WRONLY);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: fsync - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       e = fsync(fd) < 0 ? errno : 0;
+       if (v)
+               printf("%d/%d: fsync %s %d\n", procid, opno, f.path, e);
+       free_pathname(&f);
+       close(fd);
+}
+
+void
+getdents_f(int opno, long r)
+{
+       DIR             *dir;
+       pathname_t      f;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_DIRm, r, &f, NULL, NULL, &v))
+               append_pathname(&f, ".");
+       dir = opendir_path(&f);
+       check_cwd();
+       if (dir == NULL) {
+               if (v)
+                       printf("%d/%d: getdents - can't open %s\n",
+                               procid, opno, f.path);
+               free_pathname(&f);
+               return;
+       }
+       while (readdir64(dir) != NULL)
+               continue;
+       if (v)
+               printf("%d/%d: getdents %s 0\n", procid, opno, f.path);
+       free_pathname(&f);
+       closedir(dir);
+}
+
+void
+link_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       fent_t          *fep;
+       flist_t         *flp;
+       int             id;
+       pathname_t      l;
+       int             parid;
+       int             v;
+       int             v1;
+
+       init_pathname(&f);
+       if (!get_fname(FT_NOTDIR, r, &f, &flp, NULL, &v1)) {
+               if (v1)
+                       printf("%d/%d: link - no file\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       if (!get_fname(FT_DIRm, random(), NULL, NULL, &fep, &v))
+               parid = -1;
+       else
+               parid = fep->id;
+       v |= v1;
+       init_pathname(&l);
+       e = generate_fname(fep, flp - flist, &l, &id, &v1);
+       v |= v1;
+       if (!e) {
+               if (v) {
+                       fent_to_name(&l, &flist[FT_DIR], fep);
+                       printf("%d/%d: link - no filename from %s\n",
+                               procid, opno, l.path);
+               }
+               free_pathname(&l);
+               free_pathname(&f);
+               return;
+       }
+       e = link_path(&f, &l) < 0 ? errno : 0;
+       check_cwd();
+       if (e == 0)
+               add_to_flist(flp - flist, id, parid);
+       if (v)
+               printf("%d/%d: link %s %s %d\n", procid, opno, f.path, l.path,
+                       e);
+       free_pathname(&l);
+       free_pathname(&f);
+}
+
+void
+mkdir_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       fent_t          *fep;
+       int             id;
+       int             parid;
+       int             v;
+       int             v1;
+
+       if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
+               parid = -1;
+       else
+               parid = fep->id;
+       init_pathname(&f);
+       e = generate_fname(fep, FT_DIR, &f, &id, &v1);
+       v |= v1;
+       if (!e) {
+               if (v) {
+                       fent_to_name(&f, &flist[FT_DIR], fep);
+                       printf("%d/%d: mkdir - no filename from %s\n",
+                               procid, opno, f.path);
+               }
+               free_pathname(&f);
+               return;
+       }
+       e = mkdir_path(&f, 0777) < 0 ? errno : 0;
+       check_cwd();
+       if (e == 0)
+               add_to_flist(FT_DIR, id, parid);
+       if (v)
+               printf("%d/%d: mkdir %s %d\n", procid, opno, f.path, e);
+       free_pathname(&f);
+}
+
+void
+mknod_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       fent_t          *fep;
+       int             id;
+       int             parid;
+       int             v;
+       int             v1;
+
+       if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
+               parid = -1;
+       else
+               parid = fep->id;
+       init_pathname(&f);
+       e = generate_fname(fep, FT_DEV, &f, &id, &v1);
+       v |= v1;
+       if (!e) {
+               if (v) {
+                       fent_to_name(&f, &flist[FT_DIR], fep);
+                       printf("%d/%d: mknod - no filename from %s\n",
+                               procid, opno, f.path);
+               }
+               free_pathname(&f);
+               return;
+       }
+       e = mknod_path(&f, S_IFCHR|0444, 0) < 0 ? errno : 0;
+       check_cwd();
+       if (e == 0)
+               add_to_flist(FT_DEV, id, parid);
+       if (v)
+               printf("%d/%d: mknod %s %d\n", procid, opno, f.path, e);
+       free_pathname(&f);
+}
+
+void
+read_f(int opno, long r)
+{
+       char            *buf;
+       int             e;
+       pathname_t      f;
+       int             fd;
+       size_t          len;
+       __int64_t       lr;
+       off64_t         off;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: read - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_RDONLY);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: read - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       if (fstat64(fd, &stb) < 0) {
+               if (v)
+                       printf("%d/%d: read - fstat64 %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       if (stb.st_size == 0) {
+               if (v)
+                       printf("%d/%d: read - %s zero size\n", procid, opno,
+                               f.path);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       lr = ((__int64_t)random() << 32) + random();
+       off = (off64_t)(lr % stb.st_size);
+       lseek64(fd, off, SEEK_SET);
+       len = (random() % (getpagesize() * 32)) + 1;
+       buf = malloc(len);
+       e = read(fd, buf, len) < 0 ? errno : 0;
+       free(buf);
+       if (v)
+               printf("%d/%d: read %s [%lld,%d] %d\n",
+                       procid, opno, f.path, off, len, e);
+       free_pathname(&f);
+       close(fd);
+}
+
+void
+readlink_f(int opno, long r)
+{
+       char            buf[PATH_MAX];
+       int             e;
+       pathname_t      f;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_SYMm, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: readlink - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       e = readlink_path(&f, buf, PATH_MAX) < 0 ? errno : 0;
+       check_cwd();
+       if (v)
+               printf("%d/%d: readlink %s %d\n", procid, opno, f.path, e);
+       free_pathname(&f);
+}
+
+void
+rename_f(int opno, long r)
+{
+       fent_t          *dfep;
+       int             e;
+       pathname_t      f;
+       fent_t          *fep;
+       flist_t         *flp;
+       int             id;
+       pathname_t      newf;
+       int             oldid;
+       int             parid;
+       int             v;
+       int             v1;
+
+       init_pathname(&f);
+       if (!get_fname(FT_ANYm, r, &f, &flp, &fep, &v1)) {
+               if (v1)
+                       printf("%d/%d: rename - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       if (!get_fname(FT_DIRm, random(), NULL, NULL, &dfep, &v))
+               parid = -1;
+       else
+               parid = dfep->id;
+       v |= v1;
+       init_pathname(&newf);
+       e = generate_fname(dfep, flp - flist, &newf, &id, &v1);
+       v |= v1;
+       if (!e) {
+               if (v) {
+                       fent_to_name(&f, &flist[FT_DIR], dfep);
+                       printf("%d/%d: rename - no filename from %s\n",
+                               procid, opno, f.path);
+               }
+               free_pathname(&newf);
+               free_pathname(&f);
+               return;
+       }
+       e = rename_path(&f, &newf) < 0 ? errno : 0;
+       check_cwd();
+       if (e == 0) {
+               if (flp - flist == FT_DIR) {
+                       oldid = fep->id;
+                       fix_parent(oldid, id);
+               }
+               del_from_flist(flp - flist, fep - flp->fents);
+               add_to_flist(flp - flist, id, parid);
+       }
+       if (v)
+               printf("%d/%d: rename %s to %s %d\n", procid, opno, f.path,
+                       newf.path, e);
+       free_pathname(&newf);
+       free_pathname(&f);
+}
+
+void
+resvsp_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       int             fd;
+       struct flock64  fl;
+       __int64_t       lr;
+       off64_t         off;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: resvsp - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_RDWR);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: resvsp - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       if (fstat64(fd, &stb) < 0) {
+               if (v)
+                       printf("%d/%d: resvsp - fstat64 %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       lr = ((__int64_t)random() << 32) + random();
+       off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+       off %= maxfsize;
+       fl.l_whence = SEEK_SET;
+       fl.l_start = off;
+       fl.l_len = (off64_t)(random() % (1024 * 1024));
+       e = ioctl(fd, XFS_IOC_RESVSP64, &fl) < 0 ? errno : 0;
+       if (v)
+               printf("%d/%d: ioctl(XFS_IOC_RESVSP64) %s %lld %lld %d\n",
+                       procid, opno, f.path, off, fl.l_len, e);
+       free_pathname(&f);
+       close(fd);
+}
+
+void
+rmdir_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       fent_t          *fep;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_DIRm, r, &f, NULL, &fep, &v)) {
+               if (v)
+                       printf("%d/%d: rmdir - no directory\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       e = rmdir_path(&f) < 0 ? errno : 0;
+       check_cwd();
+       if (e == 0)
+               del_from_flist(FT_DIR, fep - flist[FT_DIR].fents);
+       if (v)
+               printf("%d/%d: rmdir %s %d\n", procid, opno, f.path, e);
+       free_pathname(&f);
+}
+
+void
+stat_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: stat - no entries\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       e = lstat64_path(&f, &stb) < 0 ? errno : 0;
+       check_cwd();
+       if (v)
+               printf("%d/%d: stat %s %d\n", procid, opno, f.path, e);
+       free_pathname(&f);
+}
+
+void
+symlink_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       fent_t          *fep;
+       int             i;
+       int             id;
+       int             len;
+       int             parid;
+       int             v;
+       int             v1;
+       char            *val;
+
+       if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
+               parid = -1;
+       else
+               parid = fep->id;
+       init_pathname(&f);
+       e = generate_fname(fep, FT_SYM, &f, &id, &v1);
+       v |= v1;
+       if (!e) {
+               if (v) {
+                       fent_to_name(&f, &flist[FT_DIR], fep);
+                       printf("%d/%d: symlink - no filename from %s\n",
+                               procid, opno, f.path);
+               }
+               free_pathname(&f);
+               return;
+       }
+       len = (int)(random() % PATH_MAX);
+       val = malloc(len + 1);
+       if (len)
+               memset(val, 'x', len);
+       val[len] = '\0';
+       for (i = 10; i < len - 1; i += 10)
+               val[i] = '/';
+       e = symlink_path(val, &f) < 0 ? errno : 0;
+       check_cwd();
+       if (e == 0)
+               add_to_flist(FT_SYM, id, parid);
+       free(val);
+       if (v)
+               printf("%d/%d: symlink %s %d\n", procid, opno, f.path, e);
+       free_pathname(&f);
+}
+
+/* ARGSUSED */
+void
+sync_f(int opno, long r)
+{
+       sync();
+       if (verbose)
+               printf("%d/%d: sync\n", procid, opno);
+}
+
+void
+truncate_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       __int64_t       lr;
+       off64_t         off;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: truncate - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       e = stat64_path(&f, &stb) < 0 ? errno : 0;
+       check_cwd();
+       if (e > 0) {
+               if (v)
+                       printf("%d/%d: truncate - stat64 %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       lr = ((__int64_t)random() << 32) + random();
+       off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+       off %= maxfsize;
+       e = truncate64_path(&f, off) < 0 ? errno : 0;
+       check_cwd();
+       if (v)
+               printf("%d/%d: truncate %s %lld %d\n", procid, opno, f.path,
+                       off, e);
+       free_pathname(&f);
+}
+
+void
+unlink_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       fent_t          *fep;
+       flist_t         *flp;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_NOTDIR, r, &f, &flp, &fep, &v)) {
+               if (v)
+                       printf("%d/%d: unlink - no file\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       e = unlink_path(&f) < 0 ? errno : 0;
+       check_cwd();
+       if (e == 0)
+               del_from_flist(flp - flist, fep - flp->fents);
+       if (v)
+               printf("%d/%d: unlink %s %d\n", procid, opno, f.path, e);
+       free_pathname(&f);
+}
+
+void
+unresvsp_f(int opno, long r)
+{
+       int             e;
+       pathname_t      f;
+       int             fd;
+       struct flock64  fl;
+       __int64_t       lr;
+       off64_t         off;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: unresvsp - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_RDWR);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: unresvsp - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       if (fstat64(fd, &stb) < 0) {
+               if (v)
+                       printf("%d/%d: unresvsp - fstat64 %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       lr = ((__int64_t)random() << 32) + random();
+       off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+       off %= maxfsize;
+       fl.l_whence = SEEK_SET;
+       fl.l_start = off;
+       fl.l_len = (off64_t)(random() % (1 << 20));
+       e = ioctl(fd, XFS_IOC_UNRESVSP64, &fl) < 0 ? errno : 0;
+       if (v)
+               printf("%d/%d: ioctl(XFS_IOC_UNRESVSP64) %s %lld %lld %d\n",
+                       procid, opno, f.path, off, fl.l_len, e);
+       free_pathname(&f);
+       close(fd);
+}
+
+void
+write_f(int opno, long r)
+{
+       char            *buf;
+       int             e;
+       pathname_t      f;
+       int             fd;
+       size_t          len;
+       __int64_t       lr;
+       off64_t         off;
+       struct stat64   stb;
+       int             v;
+
+       init_pathname(&f);
+       if (!get_fname(FT_REGm, r, &f, NULL, NULL, &v)) {
+               if (v)
+                       printf("%d/%d: write - no filename\n", procid, opno);
+               free_pathname(&f);
+               return;
+       }
+       fd = open_path(&f, O_WRONLY);
+       e = fd < 0 ? errno : 0;
+       check_cwd();
+       if (fd < 0) {
+               if (v)
+                       printf("%d/%d: write - open %s failed %d\n",
+                               procid, opno, f.path, e);
+               free_pathname(&f);
+               return;
+       }
+       if (fstat64(fd, &stb) < 0) {
+               if (v)
+                       printf("%d/%d: write - fstat64 %s failed %d\n",
+                               procid, opno, f.path, errno);
+               free_pathname(&f);
+               close(fd);
+               return;
+       }
+       lr = ((__int64_t)random() << 32) + random();
+       off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+       off %= maxfsize;
+       lseek64(fd, off, SEEK_SET);
+       len = (random() % (getpagesize() * 32)) + 1;
+       buf = malloc(len);
+       memset(buf, nameseq & 0xff, len);
+       e = write(fd, buf, len) < 0 ? errno : 0;
+       free(buf);
+       if (v)
+               printf("%d/%d: write %s [%lld,%d] %d\n",
+                       procid, opno, f.path, off, len, e);
+       free_pathname(&f);
+       close(fd);
+}
diff --git a/src/global.h b/src/global.h
new file mode 100644 (file)
index 0000000..4301162
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+/* includes */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <getopt.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <dirent.h>
+
+/* xfs specific includes */
+
+#include <libxfs.h>
+#include <attributes.h>
+
+#endif
diff --git a/src/holes.c b/src/holes.c
new file mode 100644 (file)
index 0000000..edcb31d
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include "global.h"
+
+int verbose;           /* print lots of debugging info */
+
+void usage(char *progname);
+void writeblks(int fd, long filesize, int blocksize,
+                  int interleave, int base, int rev);
+int readblks(int fd, long filesize, int blocksize,
+                 int interleave, int count);
+
+void
+usage(char *progname)
+{
+       fprintf(stderr, "usage: %s [-l filesize] [-b blocksize] [-i interleave]\n"
+                       "\t\t[-c count] [-r(everse)] [-v(erbose)] filename\n",
+                       progname);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int interleave, blocksize, count, rev, i, ch, fd;
+       long filesize;
+       char *filename;
+        int errs;
+
+       filesize = 1024*1024;
+       blocksize = 4096;
+       count = interleave = 4;
+       rev = verbose = 0;
+       while ((ch = getopt(argc, argv, "b:l:i:c:rv")) != EOF) {
+               switch(ch) {
+               case 'b':       blocksize  = atoi(optarg);      break;
+               case 'c':       count      = atoi(optarg);      break;
+               case 'i':       interleave = atoi(optarg);      break;
+               case 'l':       filesize   = atol(optarg);      break;
+               case 'v':       verbose++;                      break;
+               case 'r':       rev++;                          break;
+               default:        usage(argv[0]);                 break;
+               }
+       }
+       if (optind == argc-1)
+               filename = argv[optind];
+       else
+               usage(argv[0]);
+       if ((filesize % (blocksize*interleave)) != 0) {
+               filesize -= filesize % (blocksize * interleave);
+               printf("filesize not a multiple of blocksize*interleave,\n");
+               printf("reducing filesize to %ld\n", filesize);
+       }
+       if (count > interleave) {
+               count = interleave;
+               printf("count of passes is too large, setting to %d\n", count);
+       } else if (count < 1) {
+               count = 1;
+               printf("count of passes is too small, setting to %d\n", count);
+       }
+
+       if ((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) {
+               perror("open");
+               return 1;
+       }
+       for (i = 0; i < count; i++) {
+               writeblks(fd, filesize, blocksize, interleave, i, rev);
+       }
+       errs=readblks(fd, filesize, blocksize, interleave, count);
+       if (close(fd) < 0) {
+               perror("close");
+               return 1;
+       }
+        if (errs) {
+            printf("%d errors detected during readback\n", errs);
+            return 1;
+        }
+       return 0;
+}
+
+void
+writeblks(int fd, long filesize, int blocksize, int interleave, int base, int rev)
+{
+       long offset;
+       char *buffer;
+
+       if ((buffer = calloc(1, blocksize)) == NULL) {
+               perror("malloc");
+               exit(1);
+       }
+
+       if (rev) {
+               offset = (filesize-blocksize) - (base * blocksize);
+       } else {
+               offset = base * blocksize;
+       }
+       for (;;) {
+               if (lseek(fd, offset, SEEK_SET) < 0) {
+                       perror("lseek");
+                       exit(1);
+               }
+               *(long *)buffer = *(long *)(buffer+256) = offset;
+               if (write(fd, buffer, blocksize) < blocksize) {
+                       perror("write");
+                       exit(1);
+               }
+               if (verbose) {
+                       printf("writing data at offset=%ld, delta=%d, value 0x%lx and 0x%lx\n",
+                                       offset-base*blocksize, base,
+                                       *(long *)buffer,
+                                       *(long *)(buffer+256));
+               }
+
+               if (rev) {
+                       offset -= interleave*blocksize;
+                       if (offset < 0)
+                               break;
+               } else {
+                       offset += interleave*blocksize;
+                       if (offset >= filesize)
+                               break;
+               }
+       }
+        
+        {
+            /* pad file out to full length */
+            char *zero="";
+            if (lseek(fd, filesize-1, SEEK_SET)<0) {
+                perror("lseek");
+                exit(1);
+            }
+            if (write(fd, zero, 1)!=1) {
+                perror("write");
+                exit(1);
+            }
+        }
+
+       free(buffer);
+}
+
+int
+readblks(int fd, long filesize, int blocksize, int interleave, int count)
+{
+       long offset;
+       char *buffer, *tmp;
+       int xfer, i;
+        int errs=0;
+
+       if ((buffer = calloc(interleave, blocksize)) == NULL) {
+               perror("malloc");
+               exit(1);
+       }
+       xfer = interleave * blocksize;
+
+       if (lseek(fd, (long)0, SEEK_SET) < 0) {
+               perror("lseek");
+               exit(1);
+       }
+       for (offset = 0; offset < filesize; offset += xfer) {
+               if ((i = read(fd, buffer, xfer) < xfer)) {
+                       if (i == 0)
+                               break;
+                        if (i < 0)
+                               perror("read");
+                        printf("short read: %d of %d bytes read\n", i, xfer);
+                        
+                       exit(1);
+               }
+               for (tmp = buffer, i = 0; i < count; i++, tmp += blocksize) {
+                       if ( (*(long *)tmp != (offset+i*blocksize)) ||
+                            (*(long *)(tmp+256) != (offset+i*blocksize)) ) {
+                               printf("mismatched data at offset=%ld, delta=%d, expected 0x%lx, got 0x%lx and 0x%lx\n",
+                                                  offset, i,
+                                                  offset+i*blocksize,
+                                                  *(long *)tmp,
+                                                  *(long *)(tmp+256));
+                                errs++;
+                       }
+               }
+       }
+
+       free(buffer);
+        return errs;
+}
diff --git a/src/ioctl.c b/src/ioctl.c
new file mode 100644 (file)
index 0000000..f3ca762
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include <jdm.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+/* simple test program to try out  a bunch of ioctls:
+ *     XFS_IOC_FSCOUNTS
+ *     XFS_IOC_GET_RESBLKS
+ *     XFS_IOC_SET_RESBLKS
+ *     XFS_IOC_PATH_TO_FSHANDLE
+ *     XFS_IOC_PATH_TO_HANDLE
+ *     XFS_IOC_FD_TO_HANDLE
+ *     XFS_IOC_OPEN_BY_HANDLE
+ *     XFS_IOC_READLINK_BY_HANDLE
+*/
+
+    
+void fscounts(int fsfd)
+{
+    xfs_fsop_counts_t   counts;
+    int                 ret;
+    
+    ret=ioctl(fsfd, XFS_IOC_FSCOUNTS, &counts);
+    if (ret) {
+        perror("ioctl(XFS_IOC_FSCOUNTS)");
+        exit(1);
+    }
+
+    printf("XFS_IOC_FSCOUNTS-\n    freedata: %lld freertx: %lld freeino: %lld allocino: %lld\n",
+            counts.freedata, counts.freertx, counts.freeino, counts.allocino);
+}
+    
+__u64 getresblks(int fsfd)
+{
+    xfs_fsop_resblks_t  res;
+    int                 ret;
+    
+    ret=ioctl(fsfd, XFS_IOC_GET_RESBLKS, &res);
+    if (ret) {
+        perror("ioctl(XFS_IOC_GET_RESBLKS)");
+        exit(1);
+    }
+    
+    printf("XFS_IOC_GET_RESBLKS-\n    resblks: %lld blksavail: %lld\n",
+            res.resblks, res.resblks_avail);
+    
+    return res.resblks;
+}
+    
+__u64 setresblks(int fsfd, __u64 blks)
+{
+    xfs_fsop_resblks_t  res;
+    int                 ret;
+    
+    res.resblks=blks;
+    ret=ioctl(fsfd, XFS_IOC_SET_RESBLKS, &res);
+    if (ret) {
+        perror("ioctl(XFS_IOC_SET_RESBLKS)");
+        exit(1);
+    }
+    
+    printf("XFS_IOC_SET_RESBLKS-\n    resblks: %lld blksavail: %lld\n",
+            res.resblks, res.resblks_avail);
+    
+    return res.resblks;
+}
+
+void handle_print(void *handle, int handlen)
+{
+    char *p=handle;
+    if (!handle||!handlen) {
+        printf("%s",handle?"<zero len>":"<NULL>");
+        return;
+    };
+    
+    printf("#");
+    while (handlen--)
+        printf("%02x", *p++);   
+}
+
+void stat_print(int fd)
+{
+    struct stat buf;
+    
+    if (fstat(fd, &buf)) {
+        perror("stat");
+        exit(1);
+    }
+    printf("dev: %llu ino: %llu mode: %o\n",
+            (__u64)buf.st_dev, (__u64)buf.st_ino, buf.st_mode);
+}
+    
+
+void handle(int fsfd, char *path)
+{
+    xfs_fsop_handlereq_t    handle;
+    char                    buffer[1024];
+    char                    link[1024];
+    int                     ret;
+    __u32                   len;
+    __u32                   linklen;
+    int                     fd;
+    
+    handle.path=path;
+    handle.ohandle=buffer;
+    handle.ohandlen=&len;
+    ret=ioctl(fsfd, XFS_IOC_PATH_TO_FSHANDLE, &handle);
+    if (ret) {
+        perror("ioctl(XFS_IOC_PATH_TO_FSHANDLE)");
+        exit(1);
+    }
+    printf("XFS_IOC_PATH_TO_FSHANDLE-\n    handle: ");
+    handle_print(handle.ohandle, *handle.ohandlen);
+    printf("\n");
+    
+    fd=open(path,O_RDONLY);
+    if (fd<0) {
+        perror("open");
+        exit(1);
+    }
+    handle.path=NULL;
+    handle.fd=fd;
+    handle.ohandle=buffer;
+    handle.ohandlen=&len;
+    ret=ioctl(fsfd, XFS_IOC_FD_TO_HANDLE, &handle);
+    if (ret) {
+        perror("ioctl(XFS_IOC_FD_TO_HANDLE)");
+        exit(1);
+    }
+    
+    printf("XFS_IOC_FD_TO_HANDLE-\n    path: %s\n    handle: ", path);
+    handle_print(handle.ohandle, *handle.ohandlen);
+    printf("\n");
+    
+    close(fd);
+    
+    handle.path=NULL;
+    handle.fd=-1;
+    handle.ihandle=buffer;
+    handle.ihandlen=len;
+    handle.ohandle=NULL;
+    handle.ohandlen=NULL;
+    ret=ioctl(fsfd, XFS_IOC_OPEN_BY_HANDLE, &handle);
+    if (ret<0) {
+        perror("ioctl(XFS_IOC_OPEN_BY_HANDLE)");
+        exit(1);
+    }
+    printf("XFS_IOC_OPEN_BY_HANDLE-\n    handle: ");
+    handle_print(handle.ihandle, handle.ihandlen);
+    printf("\n    fd: %d\n    stat- ", ret);
+    stat_print(ret);
+    close(ret);
+    
+    handle.path=path;
+    handle.ohandle=buffer;
+    handle.ohandlen=&len;
+    ret=ioctl(fsfd, XFS_IOC_PATH_TO_HANDLE, &handle);
+    if (ret) {
+        perror("ioctl(XFS_IOC_PATH_TO_HANDLE)");
+        exit(1);
+    }
+    printf("XFS_IOC_PATH_TO_HANDLE-\n    path: %s\n    handle: ", path);
+    handle_print(handle.ohandle, *handle.ohandlen);
+    printf("\n");
+
+    handle.path=NULL;
+    handle.fd=-1;
+    handle.ihandle=buffer;
+    handle.ihandlen=len;
+    handle.ohandle=link;
+    linklen=sizeof(link);
+    handle.ohandlen=&linklen;
+    ret=ioctl(fsfd, XFS_IOC_READLINK_BY_HANDLE, &handle);
+    if (ret<0) {
+        perror("ioctl(XFS_IOC_READLINK_BY_HANDLE)");
+        fprintf(stderr,"ERROR IGNORED\n");
+    } else {
+        printf("XFS_IOC_READLINK_BY_HANDLE-\n    handle: ");
+        handle_print(handle.ihandle, handle.ihandlen);
+        printf("\n    link=\"%*.*s\"\n", 
+                ret, ret, (char*)handle.ohandle);
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    int                 fsfd;
+    
+    if (argc != 3) {
+        fprintf(stderr,"usage: %s <filesystem> <file/link in FS>\n",
+                argv[0]);
+        exit(0);
+    }
+
+    fsfd = open(argv[1], O_RDONLY);
+    if (fsfd < 0) {
+       perror("open");
+       exit(1);
+    }
+    
+    /* XFS_IOC_FSCOUNTS */
+    fscounts(fsfd);
+    /* XFS_IOC_GET_RESBLKS & XFS_IOC_SET_RESBLKS */
+    getresblks(fsfd);
+    setresblks(fsfd, 1000);
+    getresblks(fsfd);
+    setresblks(fsfd, 0);
+    /* XFS_IOC_FSINUMBERS */
+    
+        /* NYI in kernel */
+    
+    /* XFS_IOC_PATH_TO_FSHANDLE */
+    /* XFS_IOC_PATH_TO_HANDLE */
+    /* XFS_IOC_FD_TO_HANDLE */
+    /* XFS_IOC_OPEN_BY_HANDLE */
+    /* XFS_IOC_READLINK_BY_HANDLE */
+    handle(fsfd, argv[2]);
+    
+    return 0;
+}
diff --git a/src/loggen.c b/src/loggen.c
new file mode 100644 (file)
index 0000000..d13ff7d
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+/*
+ *
+ * loggen: Generate log entries. Very much incomplete. The empty log
+ *         record is a bit of a misnomer since we need to jump through
+ *         hoops to get a log record that parses ok yet does nothing.
+ *
+ *                                                  - dxm 29/09/00
+ */
+
+#include <libxfs.h>
+#include <malloc.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <xfs_log.h>
+#include <xfs_log_priv.h>
+
+void
+usage()
+{
+    fprintf(stderr,"Usage: loggen\n"
+                   "           set up parameters before writing record(s):\n"
+                   "               -f f     - set format\n"
+                   "               -u u     - set uuid\n"
+                   "               -c c     - set cycle\n"
+                   "               -b b     - set block\n"
+                   "               -C c     - set tail cycle\n"
+                   "               -B b     - set tail block\n"
+                   "           write log record(s):\n"
+                   "               -z n     - write n zero block(s)     (1BB)\n"
+                   "               -e n     - write n empty record(s)   (2BB)\n"
+                   "               -m n     - write n unmount record(s) (2BB)\n"
+                   "\n"
+                   "            redirect stdout to external log partition, or pipe to\n"
+                   "            dd with appropriate parameters to stuff into internal log.\n"
+    );
+    exit(1);
+}
+
+int         bufblocks            = 0;
+void        *buf                 = NULL;
+int         param_cycle          = 1;
+int         param_block          = 0;
+int         param_tail_cycle     = 1;
+int         param_tail_block     = 0;
+int         param_fmt            = XLOG_FMT;
+uuid_t      param_uuid           = {0};
+
+void
+loggen_alloc(int blocks)
+{
+    if (!(buf=realloc(buf, blocks*BBSIZE))) {
+        fprintf(stderr,"failed to allocate %d block(s)\n", blocks);
+        exit(1);
+    }
+    memset(buf, 0, blocks*BBSIZE);
+    bufblocks=blocks;
+}
+
+void
+loggen_write()
+{         
+    if (!buf) {
+        fprintf(stderr,"no buffer allocated\n");
+        exit(1);
+    }
+
+    if (fwrite(buf, BBSIZE, bufblocks, stdout) != bufblocks) {
+        perror("fwrite");
+        exit(1);
+    }
+
+}
+
+void
+loggen_zero(int count)
+{
+    if (!count) count=1;
+    
+    fprintf(stderr,"   *** zero block (1BB) x %d\n", count);
+    loggen_alloc(1);
+    while (count--)
+        loggen_write(count);
+}      
+      
+void
+loggen_unmount(int count)
+{
+    xlog_rec_header_t       *head;
+    xlog_op_header_t        *op;
+    /* the data section must be 32 bit size aligned */
+    struct {
+        __uint16_t magic;
+        __uint16_t pad1;
+        __uint32_t pad2; /* may as well make it 64 bits */
+    } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
+    
+    if (!count) count=1;
+    
+    fprintf(stderr,"   *** unmount record (2BB) x %d\n", count);
+    loggen_alloc(2);
+    
+    head = (xlog_rec_header_t *)buf;
+    op   = (xlog_op_header_t  *)(((char*)buf)+BBSIZE);
+
+    /* note that oh_tid actually contains the cycle number
+     * and the tid is stored in h_cycle_data[0] - that's the
+     * way things end up on disk.
+     */
+
+    INT_SET(head->h_magicno,        ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
+    INT_SET(head->h_cycle,          ARCH_CONVERT, param_cycle);
+    INT_SET(head->h_version,        ARCH_CONVERT, 1);
+    INT_SET(head->h_len,            ARCH_CONVERT, 20);
+    INT_SET(head->h_chksum,         ARCH_CONVERT, 0);
+    INT_SET(head->h_prev_block,     ARCH_CONVERT, -1);
+    INT_SET(head->h_num_logops,     ARCH_CONVERT, 1);
+    INT_SET(head->h_cycle_data[0],  ARCH_CONVERT, 0xb0c0d0d0);
+    INT_SET(head->h_fmt,            ARCH_CONVERT, param_fmt);
+    
+    ASSIGN_ANY_LSN(head->h_tail_lsn,    
+            param_tail_cycle, param_tail_block, ARCH_CONVERT);
+
+    memcpy(head->h_fs_uuid,  param_uuid, sizeof(uuid_t));
+
+    /* now a log unmount op */
+    INT_SET(op->oh_tid,             ARCH_CONVERT, param_cycle);
+    INT_SET(op->oh_len,             ARCH_CONVERT, sizeof(magic));
+    INT_SET(op->oh_clientid,        ARCH_CONVERT, XFS_LOG);
+    INT_SET(op->oh_flags,           ARCH_CONVERT, XLOG_UNMOUNT_TRANS);
+    INT_SET(op->oh_res2,            ARCH_CONVERT, 0);
+
+    /* and the data for this op */
+
+    memcpy(op+1, &magic, sizeof(magic));
+    
+    while (count--) {
+        ASSIGN_ANY_LSN(head->h_lsn,         
+                param_cycle, param_block++, ARCH_CONVERT);
+        
+        loggen_write(count);
+    }
+} 
+  
+void
+loggen_empty(int count)
+{
+    xlog_rec_header_t       *head;
+    xlog_op_header_t        *op1, *op2, *op3, *op4, *op5;
+    xfs_trans_header_t      *trans;
+    xfs_buf_log_format_t    *blf;
+    int                     *data;
+    char                    *p;
+    
+    if (!count) count=1;
+    
+    fprintf(stderr,"   *** empty record (2BB) x %d\n", count);
+    loggen_alloc(2);
+    
+    p=(char*)buf;
+    head  = (xlog_rec_header_t   *)p;         p+=BBSIZE;
+    op1   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
+    op2   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
+    trans = (xfs_trans_header_t  *)p;         p+=sizeof(xfs_trans_header_t);
+    op3   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
+    blf   = (xfs_buf_log_format_t*)p;         p+=sizeof(xfs_buf_log_format_t);
+    op4   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
+    data  = (int                 *)p;         p+=sizeof(int);
+    op5   = (xlog_op_header_t    *)p;         p+=sizeof(xlog_op_header_t);
+
+    /* note that oh_tid actually contains the cycle number
+     * and the tid is stored in h_cycle_data[0] - that's the
+     * way things end up on disk.
+     */
+
+    INT_SET(head->h_magicno,        ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
+    INT_SET(head->h_cycle,          ARCH_CONVERT, param_cycle);
+    INT_SET(head->h_version,        ARCH_CONVERT, 1);
+    INT_SET(head->h_len,            ARCH_CONVERT, 5*sizeof(xlog_op_header_t) +
+                                                    sizeof(xfs_trans_header_t)+
+                                                    sizeof(xfs_buf_log_format_t)+
+                                                    sizeof(int));
+    INT_SET(head->h_chksum,         ARCH_CONVERT, 0);
+    INT_SET(head->h_prev_block,     ARCH_CONVERT, -1);
+    INT_SET(head->h_num_logops,     ARCH_CONVERT, 5);
+    INT_SET(head->h_cycle_data[0],  ARCH_CONVERT, 0xb0c0d0d0);
+    INT_SET(head->h_fmt,            ARCH_CONVERT, param_fmt);
+    
+    ASSIGN_ANY_LSN(head->h_tail_lsn,    
+            param_tail_cycle, param_tail_block, ARCH_CONVERT);
+
+    memcpy(head->h_fs_uuid,  param_uuid, sizeof(uuid_t));
+
+    /* start */
+    INT_SET(op1->oh_tid,            ARCH_CONVERT, 1);
+    INT_SET(op1->oh_len,            ARCH_CONVERT, 0);
+    INT_SET(op1->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
+    INT_SET(op1->oh_flags,          ARCH_CONVERT, XLOG_START_TRANS);
+    INT_SET(op1->oh_res2,           ARCH_CONVERT, 0);
+    /* dummy */
+    INT_SET(op2->oh_tid,            ARCH_CONVERT, 0xb0c0d0d0);
+    INT_SET(op2->oh_len,            ARCH_CONVERT, sizeof(xfs_trans_header_t));
+    INT_SET(op2->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
+    INT_SET(op2->oh_flags,          ARCH_CONVERT, 0);
+    INT_SET(op2->oh_res2,           ARCH_CONVERT, 0);
+    /* dummy transaction - this stuff doesn't get endian converted */
+    trans->th_magic     = XFS_TRANS_MAGIC;
+    trans->th_type      = XFS_TRANS_DUMMY1;
+    trans->th_tid       = 0;
+    trans->th_num_items = 1;
+    /* buffer */
+    INT_SET(op3->oh_tid,            ARCH_CONVERT, 0xb0c0d0d0);
+    INT_SET(op3->oh_len,            ARCH_CONVERT, sizeof(xfs_buf_log_format_t));
+    INT_SET(op3->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
+    INT_SET(op3->oh_flags,          ARCH_CONVERT, 0);
+    INT_SET(op3->oh_res2,           ARCH_CONVERT, 0);
+    /* an empty buffer too */
+    blf->blf_type       = XFS_LI_BUF;
+    blf->blf_size       = 2;
+    blf->blf_flags      = XFS_BLI_CANCEL;
+    blf->blf_blkno      = 1;
+    blf->blf_map_size   = 1;
+    blf->blf_data_map[0]= 0;
+    /* commit */
+    INT_SET(op4->oh_tid,            ARCH_CONVERT, 0xb0c0d0d0);
+    INT_SET(op4->oh_len,            ARCH_CONVERT, sizeof(int));
+    INT_SET(op4->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
+    INT_SET(op4->oh_flags,          ARCH_CONVERT, 0);
+    INT_SET(op4->oh_res2,           ARCH_CONVERT, 0);
+    /* and the data */
+    *data=*(int*)(char*)"FISH"; /* this won't get written (I hope) */
+    /* commit */
+    INT_SET(op5->oh_tid,            ARCH_CONVERT, 0xb0c0d0d0);
+    INT_SET(op5->oh_len,            ARCH_CONVERT, 0);
+    INT_SET(op5->oh_clientid,       ARCH_CONVERT, XFS_TRANSACTION);
+    INT_SET(op5->oh_flags,          ARCH_CONVERT, XLOG_COMMIT_TRANS);
+    INT_SET(op5->oh_res2,           ARCH_CONVERT, 0);
+
+    while (count--) {
+        ASSIGN_ANY_LSN(head->h_lsn,         
+                param_cycle, param_block++, ARCH_CONVERT);
+        
+        loggen_write(count);
+    }
+}   
+
+int
+main(int argc, char *argv[])
+{
+    int c;
+    
+    fprintf(stderr,"*** loggen\n");
+    
+    if (argc<2) usage();
+    
+    while ((c = getopt(argc, argv, "f:u:c:b:C:B:z:e:m:")) != -1) {
+       switch (c) {
+           case 'f':
+                param_fmt=atoi(optarg);
+                break;
+           case 'u':
+                memset(param_uuid, atoi(optarg), sizeof(param_uuid));
+                break;
+           case 'c':
+                param_cycle=atoi(optarg);
+                break;
+           case 'b':
+                param_block=atoi(optarg);
+                break;
+           case 'C':
+                param_tail_cycle=atoi(optarg);
+                break;
+           case 'B':
+                param_tail_block=atoi(optarg);
+                break;
+                
+           case 'z':
+                loggen_zero(atoi(optarg));
+                break;
+           case 'e':
+                loggen_empty(atoi(optarg));
+                break;
+           case 'm':
+                loggen_unmount(atoi(optarg));
+                break;
+                
+           default:
+               fprintf(stderr, "unknown option\n");
+                usage();
+       }
+    }
+    return 0;   
+}
+
+
diff --git a/src/lstat64.c b/src/lstat64.c
new file mode 100644 (file)
index 0000000..b8f1631
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/sysmacros.h>
+
+long   timebuf;
+
+void
+timesince(long timesec)
+{
+       long    d_since;        /* days */
+       long    h_since;        /* hours */
+       long    m_since;        /* minutes */
+       long    s_since;        /* seconds */
+
+       s_since = timebuf - timesec;
+       d_since = s_since / 86400l ;
+       s_since -= d_since * 86400l ;
+       h_since = s_since / 3600l ;
+       s_since -= h_since * 3600l ;
+       m_since = s_since / 60l ;
+       s_since -= m_since * 60l ;
+
+       printf("(%05ld.%02ld:%02ld:%02ld)\n",
+                       d_since, h_since, m_since, s_since);
+}
+
+int
+main(int argc, char **argv)
+{
+       struct stat64   sbuf;
+       char            mode[10];
+       int             i;
+
+       time(&timebuf);
+
+       for (i = 1; i < argc; i++) {
+
+               if( lstat64(argv[i], &sbuf) < 0) {
+                       perror(argv[i]);
+                       continue;
+               }
+
+               printf("  File: \"%s\"\n", argv[i]);
+               printf("  Size: %-10llu", sbuf.st_size);
+
+               strcpy(mode,"----------");
+               if (sbuf.st_mode & (S_IEXEC>>6))
+                       mode[9] = 'x';
+               if (sbuf.st_mode & (S_IWRITE>>6))
+                       mode[8] = 'w';
+               if (sbuf.st_mode & (S_IREAD>>6))
+                       mode[7] = 'r';
+               if (sbuf.st_mode & (S_IEXEC>>3))
+                       mode[6] = 'x';
+               if (sbuf.st_mode & (S_IWRITE>>3))
+                       mode[5] = 'w';
+               if (sbuf.st_mode & (S_IREAD>>3))
+                       mode[4] = 'r';
+               if (sbuf.st_mode & S_IEXEC)
+                       mode[3] = 'x';
+               if (sbuf.st_mode & S_IWRITE)
+                       mode[2] = 'w';
+               if (sbuf.st_mode & S_IREAD)
+                       mode[1] = 'r';
+               if (sbuf.st_mode & S_ISVTX)
+                       mode[9] = 't';
+               if (sbuf.st_mode & S_ISGID)
+                       mode[6] = 's';
+               if (sbuf.st_mode & S_ISUID)
+                       mode[3] = 's';
+
+               printf("   Filetype: ");
+               switch (sbuf.st_mode & S_IFMT) {
+               case S_IFSOCK:  
+                       puts("Socket");
+                       mode[0] = 's';
+                       break;
+               case S_IFDIR:   
+                       puts("Directory");
+                       mode[0] = 'd';
+                       break;
+               case S_IFCHR:   
+                       puts("Character Device");
+                       mode[0] = 'c';
+                       break;
+               case S_IFBLK:   
+                       puts("Block Device");
+                       mode[0] = 'b';
+                       break;
+               case S_IFREG:   
+                       puts("Regular File");
+                       mode[0] = '-';
+                       break;
+               case S_IFLNK:   
+                       puts("Symbolic Link");
+                       mode[0] = 'l';
+                       break;
+               case S_IFIFO:   
+                       puts("Fifo File");
+                       mode[0] = 'f';
+                       break;
+               default:        
+                       puts("Unknown");
+                       mode[0] = '?';
+               }
+
+               printf("  Mode: (%04o/%s)", sbuf.st_mode & 07777, mode);
+               printf("         Uid: (%d)", sbuf.st_uid);
+               printf("  Gid: (%d)\n", sbuf.st_gid);
+               printf("Device: %2d,%-2d", major(sbuf.st_dev),
+                               minor(sbuf.st_dev));
+               printf("  Inode: %-10lu", sbuf.st_ino);
+               printf("Links: %-5d", sbuf.st_nlink);
+
+               if ( ((sbuf.st_mode & S_IFMT) == S_IFCHR)
+                   || ((sbuf.st_mode & S_IFMT) == S_IFBLK) )
+                       printf("     Device type: %2d,%-2d\n",
+                               major(sbuf.st_rdev), minor(sbuf.st_rdev));
+               else
+                       printf("\n");
+
+               printf("Access: %.24s",ctime(&sbuf.st_atime));
+               timesince(sbuf.st_atime);
+               printf("Modify: %.24s",ctime(&sbuf.st_mtime));
+               timesince(sbuf.st_mtime);
+               printf("Change: %.24s",ctime(&sbuf.st_ctime));
+               timesince(sbuf.st_ctime);
+
+               if (i+1 < argc)
+                       printf("\n");
+       }
+       if (i == 1) {
+               fprintf(stderr, "Usage: lstat64 filename...\n");
+               exit(1);
+       }
+       exit(0);
+}
diff --git a/src/nametest.c b/src/nametest.c
new file mode 100644 (file)
index 0000000..23d837c
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include "global.h"
+
+/*
+ * nametest.c
+ *
+ * Run a fully automatic, random test of the directory routines.
+ *
+ * Given an input file of a list of filenames (one per line)
+ * It does a number of iterations of operations
+ * chosen pseudo-randomly in certain percentages: 
+ *   creating (open), 
+ *   deleting (unlink) and 
+ *   looking up (stat)
+ * on a pseudo-randomly chosen filename (from input file). 
+ *
+ * The percentage thresholds for operation selection change
+ * every <number-of-names> iterations. 
+ * e.g.
+ * If had 100 names then:
+ * iterations:
+ * 1-100:      pct_remove = 33; pct_create = 33;  
+ * 101-200:    pct_remove = 60; pct_create = 20;
+ * 201-300:    pct_remove = 20; pct_create = 60;
+ * 301-400:    pct_remove = 33; pct_create = 33;  
+ * 401-500:    pct_remove = 60; pct_create = 20;
+ * 501-600:    pct_remove = 20; pct_create = 60;
+ * etc...
+ *
+ * op > (pct_remove + pct_create) => auto_lookup(ip);
+ * op > pct_remove                => auto_create(ip);
+ * t                              => auto_remove(ip);
+ *
+ * Each iteration an op is chosen as shown above
+ * and a filename is randomly chosen.
+ *
+ * The operation is done and any error codes are
+ * verified considering whether file exists (info.exists)
+ * or not. The stat(3) call also compares inode number. 
+ */
+
+
+#define        DOT_COUNT       100     /* print a '.' every X operations */
+
+struct info {
+       ino64_t inumber;
+       char    *name;
+       short   namelen;
+       short   exists;
+} *table;
+
+char *table_data;      /* char string storage for info table */
+
+int good_adds, good_rms, good_looks, good_tot; /* ops that suceeded */
+int bad_adds, bad_rms, bad_looks, bad_tot;     /* ops that failed */
+
+int verbose;
+
+int    auto_lookup(struct info *);
+int    auto_create(struct info *);
+int    auto_remove(struct info *);
+
+void   usage(void);
+
+void
+usage(void)
+{
+       printf("usage: nametest [-l srcfile] [-i iterations] [-s seed] [-z] [-v]\n");
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       char *sourcefile, *c;
+       int totalnames, iterations, zeroout;
+       int zone, op, pct_remove, pct_create, ch, i, retval, fd;
+       struct stat64 statb;
+       struct info *ip;
+       int seed, linedots;
+
+       linedots = zeroout = verbose = 0;
+       seed = (int)time(NULL) % 1000;
+       iterations = 100000;
+       sourcefile = "input";
+       while ((ch = getopt(argc, argv, "l:i:s:zv")) != EOF) {
+               switch (ch) {
+               case 'l':       sourcefile = optarg;            break;
+               case 's':       seed = atoi(optarg);            break;
+               case 'i':       iterations = atoi(optarg);      break;
+               case 'z':       zeroout++;                      break;
+               case 'v':       verbose++;                      break;
+               default:        usage();                        break;
+               }
+       }
+
+       /*
+        * Read in the source file.
+        */
+       if (stat64(sourcefile, &statb) < 0) {
+               perror(sourcefile);
+               usage();
+               return 1;
+       }
+       if ((table_data = malloc(statb.st_size)) == NULL) {
+               perror("calloc");
+               return 1;
+       }
+       if ((fd = open(sourcefile, O_RDONLY)) < 0) {
+               perror(sourcefile);
+               return 1;
+       }
+       if (read(fd, table_data, statb.st_size) < 0) {
+               perror(sourcefile);
+               return 1;
+       }
+       close(fd);
+
+       /*
+        * Allocate space for the info table and fill it in.
+        */
+
+        /* 
+         * Add up number of lines in file 
+         * and replace '\n' by '\0'
+         */
+       totalnames = 0;
+       for (c = table_data, i = 0; i < statb.st_size; c++, i++) {
+               if (*c == '\n') {
+                       *c = 0;
+                       totalnames++;
+               }
+       }
+        if (!totalnames) {
+                printf("no names found in input file\n");
+                return 1;
+        }
+        
+       table = (struct info *)calloc(totalnames+1, sizeof(struct info));
+       if (table == NULL) {
+               perror("calloc");
+               return 1;
+       }
+        /*
+         * Copy over names from file (in <table_data>) into name fields 
+         * of info structures in <table>.
+         */
+        ip = table;
+       ip->name = c = table_data;
+       for (i = 0; i < totalnames;  ) {
+               if (*c++ == 0) {
+                       ip++;
+                       ip->name = c;
+                       i++;
+               } else {
+                       ip->namelen++;
+               }
+       }
+        /*
+         * Check table of names.
+         * Name are of files and not commands.
+         *
+         * ??? I guess use of an input file with commands
+         *     has been done before ???
+         * "touch fred" => "fred"
+         * "rm fred" => error
+         * "ls fred" => error
+         */
+       for (ip = table, i = 0; i < totalnames; ip++, i++) {
+               if (strncmp(ip->name, "touch ", strlen("touch ")) == 0) {
+                        /* make name skip over "touch " string */
+                       ip->name += strlen("touch ");
+                       ip->namelen -= strlen("touch ");
+               } else if (strncmp(ip->name, "rm ", strlen("rm ")) == 0) {
+                       printf("bad input file, \"rm\" cmds not allowed\n");
+                       return 1;
+               } else if (strncmp(ip->name, "ls ", strlen("ls ")) == 0) {
+                       printf("bad input file, \"ls\" cmds not allowed\n");
+                       return 1;
+               }
+       }
+
+       /*
+        * Run random transactions against the directory.
+        */
+       zone = -1;
+       printf("Seed = %d (use \"-s %d\" to re-execute this test)\n", seed, seed);
+        srandom(seed);
+
+       for (i = 0; i < iterations; i++) {
+               /*
+                * The distribution of transaction types changes over time.
+                * At first we have an equal distribution which gives us
+                * a steady state directory of 50% total size.
+                * Later, we have an unequal distribution which gives us
+                * more creates than removes, growing the directory.
+                * Later still, we have an unequal distribution which gives
+                * us more removes than creates, shrinking the directory.
+                */
+               if ((i % totalnames) == 0) {
+                       zone++;
+                       switch(zone % 3) {
+                       case 0: pct_remove = 20; pct_create = 60; break;
+                       case 1: pct_remove = 33; pct_create = 33; break;
+                       case 2: pct_remove = 60; pct_create = 20; break;
+                       }
+               }
+
+               /*
+                * Choose an operation based on the current distribution.
+                */
+               ip = &table[ random() % totalnames ];
+               op = random() % 100;
+               if (op > (pct_remove + pct_create)) {
+                       retval = auto_lookup(ip);
+               } else if (op > pct_remove) {
+                       retval = auto_create(ip);
+               } else {
+                       retval = auto_remove(ip);
+               }
+
+                /* output '.' every DOT_COUNT ops
+                 * and output '\n" every 72 dots
+                 */
+               if ((i % DOT_COUNT) == 0) {
+                       if (linedots++ == 72) {
+                               linedots = 0;
+                               write(1, "\n", 1);
+                       }
+                       write(1, ".", 1);
+                       fflush(stdout);
+               }
+       }
+       printf("\n");
+
+       printf("creates: %6d OK, %6d EEXIST  (%6d total, %2d%% EEXIST)\n",
+                        good_adds, bad_adds, good_adds + bad_adds,
+                        (good_adds+bad_adds)
+                                ? (bad_adds*100) / (good_adds+bad_adds)
+                                : 0);
+       printf("removes: %6d OK, %6d ENOENT  (%6d total, %2d%% ENOENT)\n",
+                        good_rms, bad_rms, good_rms + bad_rms,
+                        (good_rms+bad_rms)
+                                ? (bad_rms*100) / (good_rms+bad_rms)
+                                : 0);
+       printf("lookups: %6d OK, %6d ENOENT  (%6d total, %2d%% ENOENT)\n",
+                        good_looks, bad_looks, good_looks + bad_looks,
+                        (good_looks+bad_looks)
+                                ? (bad_looks*100) / (good_looks+bad_looks)
+                                : 0);
+       good_tot = good_looks + good_adds + good_rms;
+       bad_tot = bad_looks + bad_adds + bad_rms;
+       printf("total  : %6d OK, %6d w/error (%6d total, %2d%% w/error)\n",
+                        good_tot, bad_tot, good_tot + bad_tot,
+                        (good_tot + bad_tot)
+                                ? (bad_tot*100) / (good_tot+bad_tot)
+                                : 0);
+
+       /*
+        * If asked to clear the directory out after the run,
+        * remove everything that is left.
+        */
+       if (zeroout) {
+               good_rms = 0;
+               for (ip = table, i = 0; i < totalnames; ip++, i++) {
+                       if (!ip->exists)
+                               continue;
+                       good_rms++;
+                       retval = unlink(ip->name);
+                       if (retval < 0) {
+                               if (errno == ENOENT) {
+                                       printf("\"%s\"(%lu) not removed, should have existed\n",
+                                                     ip->name, ip->inumber);
+                               } else {
+                                       printf("\"%s\"(%lu) on remove: ",
+                                                     ip->name, ip->inumber);
+                                       perror("unlink");
+                               }
+                       }
+
+                       if ((good_rms % DOT_COUNT) == 0) {
+                               write(1, ".", 1);
+                               fflush(stdout);
+                       }
+               }
+               printf("\ncleanup: %6d removes\n", good_rms);
+       }
+       return 0;
+}
+
+int
+auto_lookup(struct info *ip)
+{
+       struct stat64 statb;
+       int retval;
+
+       retval = stat64(ip->name, &statb);
+       if (retval >= 0) {
+               good_looks++;
+               retval = 0;
+               if (ip->exists == 0) {
+                       printf("\"%s\"(%lu) lookup, should not exist\n",
+                                     ip->name, statb.st_ino);
+                       retval = 1;
+               } else if (ip->inumber != statb.st_ino) {
+                       printf("\"%s\"(%lu) lookup, should be inumber %lu\n",
+                                     ip->name, statb.st_ino, ip->inumber);
+                       retval = 1;
+               } else if (verbose) {
+                       printf("\"%s\"(%lu) lookup ok\n",
+                               ip->name, statb.st_ino);
+               }
+       } else if (errno == ENOENT) {
+               bad_looks++;
+               retval = 0;
+               if (ip->exists == 1) {
+                       printf("\"%s\"(%lu) lookup, should exist\n",
+                                     ip->name, ip->inumber);
+                       retval = 1;
+               } else if (verbose) {
+                       printf("\"%s\"(%lu) lookup ENOENT ok\n",
+                               ip->name, ip->inumber);
+               }
+       } else {
+               retval = errno;
+               printf("\"%s\"(%lu) on lookup: ", ip->name, ip->inumber);
+               perror("stat64");
+       }
+       return(retval);
+}
+
+int
+auto_create(struct info *ip)
+{
+       struct stat64 statb;
+       int retval;
+
+       retval = open(ip->name, O_RDWR|O_EXCL|O_CREAT, 0666);
+       if (retval >= 0) {
+               close(retval);
+               good_adds++;
+               retval = 0;
+               if (stat64(ip->name, &statb) < 0) {
+                       perror("stat64");
+                       exit(1);
+               }
+               if (ip->exists == 1) {
+                       printf("\"%s\"(%lu) created, but already existed as inumber %lu\n",
+                                     ip->name, statb.st_ino, ip->inumber);
+                       retval = 1;
+               } else if (verbose) {
+                       printf("\"%s\"(%lu) create new ok\n",
+                               ip->name, statb.st_ino);
+               }
+               ip->exists = 1;
+               ip->inumber = statb.st_ino;
+       } else if (errno == EEXIST) {
+               bad_adds++;
+               retval = 0;
+               if (ip->exists == 0) {
+                       if (stat64(ip->name, &statb) < 0) {
+                               perror("stat64");
+                               exit(1);
+                       }
+                       printf("\"%s\"(%lu) not created, should not exist\n",
+                                     ip->name, statb.st_ino);
+                       retval = 1;
+               } else if (verbose) {
+                       printf("\"%s\"(%lu) not created ok\n",
+                               ip->name, ip->inumber);
+               }
+               ip->exists = 1;
+       } else {
+               retval = errno;
+               printf("\"%s\"(%lu) on create: ", ip->name, ip->inumber);
+               perror("creat");
+       }
+       return(retval);
+}
+
+int
+auto_remove(struct info *ip)
+{
+       int retval;
+
+       retval = unlink(ip->name);
+       if (retval >= 0) {
+               good_rms++;
+               retval = 0;
+               if (ip->exists == 0) {
+                       printf("\"%s\"(%lu) removed, should not have existed\n",
+                                     ip->name, ip->inumber);
+                       retval = 1;
+               } else if (verbose) {
+                       printf("\"%s\"(%lu) remove ok\n",
+                               ip->name, ip->inumber);
+               }
+               ip->exists = 0;
+               ip->inumber = 0;
+       } else if (errno == ENOENT) {
+               bad_rms++;
+               retval = 0;
+               if (ip->exists == 1) {
+                       printf("\"%s\"(%lu) not removed, should have existed\n",
+                                     ip->name, ip->inumber);
+                       retval = 1;
+               } else if (verbose) {
+                       printf("\"%s\"(%lu) not removed ok\n",
+                               ip->name, ip->inumber);
+               }
+               ip->exists = 0;
+       } else {
+               retval = errno;
+               printf("\"%s\"(%lu) on remove: ", ip->name, ip->inumber);
+               perror("unlink");
+       }
+       return(retval);
+}
diff --git a/src/permname.c b/src/permname.c
new file mode 100644 (file)
index 0000000..d96f80d
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include "global.h"
+
+char   *alpha;
+int    asize = 1;
+int    asplit;
+char   *buf;
+int    dflag;
+int    len = 1;
+int    nproc = 1;
+int    nflag;
+int    vflag;
+int     pid;
+
+void   mkf(int idx, int p);
+
+int
+main(int argc, char **argv)
+{
+       int             a;
+       int             stat;
+       long long       tot;
+        int             usage=0;
+        char *          argv0=argv[0];
+
+       argc--;
+       argv++;
+        pid=getpid();
+        
+        if (!argc) usage++;
+       while (argc) {
+               if (strcmp(*argv, "-c") == 0) {
+                       argc--;
+                       argv++;
+                       asize = atoi(*argv);
+                       if (asize > 64 || asize < 1) {
+                               fprintf(stderr, "bad alpha size %s\n", *argv);
+                               return 1;
+                       }
+               } else if (strcmp(*argv, "-d") == 0) {
+                       dflag = 1;
+               } else if (strcmp(*argv, "-l") == 0) {
+                       argc--;
+                       argv++;
+                       len = atoi(*argv);
+                       if (len < 1) {
+                               fprintf(stderr, "bad name length %s\n", *argv);
+                               return 1;
+                       }
+               } else if (strcmp(*argv, "-p") == 0) {
+                       argc--;
+                       argv++;
+                       nproc = atoi(*argv);
+                       if (nproc < 1) {
+                               fprintf(stderr, "bad process count %s\n",
+                                       *argv);
+                               return 1;
+                       }
+               } else if (strcmp(*argv, "-n") == 0) {
+                       nflag = 1; 
+               } else if (strcmp(*argv, "-v") == 0) {
+                       vflag = 1;
+               } else if (strcmp(*argv, "-h") == 0) {
+                        usage++;
+               } else {
+                        fprintf(stderr,"unknown switch \"%s\"\n", *argv);
+                        usage++;
+                }
+               argc--;
+               argv++;
+       }
+        
+        if (usage) {
+                fprintf(stderr,"permname: usage %s [-c alpha size] [-l name length] "
+                               "[-p proc count] [-n] [-v] [-d] [-h]\n", argv0);
+                fprintf(stderr,"          -n : don't actually perform action\n");
+                fprintf(stderr,"          -v : be verbose\n");
+                fprintf(stderr,"          -d : create directories, not files\n");
+                exit(1);
+        }
+        
+       if (asize % nproc) {
+               fprintf(stderr,
+                       "alphabet size must be multiple of process count\n");
+               return 1;
+       }
+       asplit = asize / nproc;
+       alpha = malloc(asize + 1);
+       buf = malloc(len + 1);
+       for (a = 0, tot = 1; a < len; a++)
+               tot *= asize;
+        if (vflag) fprintf(stderr,"[%d] ",pid);
+       fprintf(stderr,
+               "alpha size = %d, name length = %d, total files = %lld, nproc=%d\n",
+               asize, len, tot, nproc);
+       fflush(stderr);
+       for (a = 0; a < asize; a++) {
+               if (a < 26)
+                       alpha[a] = 'a' + a;
+               else if (a < 52)
+                       alpha[a] = 'A' + a - 26;
+               else if (a < 62)
+                       alpha[a] = '0' + a - 52;
+               else if (a == 62)
+                       alpha[62] = '_';
+               else if (a == 63)
+                       alpha[63] = '@';
+       }
+       for (a = 0; a < nproc; a++) {
+                int r=fork();
+                if (r<0) {
+                        perror("fork");
+                        exit(1);
+                }
+               if (!r) {
+                        pid=getpid();
+                       mkf(0, a);
+                       return 0;
+               }
+       }
+        while (1) {
+                int r=wait(&stat);
+                if (r<0) {
+                        if (errno==ECHILD) break;
+                        perror("wait");
+                        exit(1);
+                }
+                if (!r) break;
+        }
+        
+       return 0;
+}
+
+void
+mkf(int idx, int p)
+{
+       int     i;
+       int     last;
+
+       last = (idx == len - 1);
+       if (last) {
+               buf[len] = '\0';
+               for (i = p * asplit; i < (p + 1) * asplit; i++) {
+                       buf[idx] = alpha[i];
+                        
+                        if (dflag) {
+                                if (vflag) printf("[%d] mkdir %s\n", pid, buf);
+                                if (!nflag) {
+                                    if (mkdir(buf, 0777)<0) {
+                                        perror("mkdir");
+                                        exit(1);
+                                    }
+                                }
+                        } else {
+                                if (vflag) printf("[%d] touch %s\n", pid, buf);
+                               if (!nflag) {
+                                    int f=creat(buf, 0666);
+                                    if (f<0) {
+                                        perror("creat");
+                                        exit(1);
+                                    }
+                                    if (close(f)) {
+                                        perror("close");
+                                        exit(1);
+                                    }
+                                }
+                        }
+               }
+       } else {
+               for (i = 0; i < asize; i++) {
+                       buf[idx] = alpha[i];
+                       mkf(idx + 1, p);
+               }
+       }
+}
diff --git a/src/randholes.c b/src/randholes.c
new file mode 100644 (file)
index 0000000..3a8f4db
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include "global.h"
+
+unsigned char  *valid; /* Bit-vector array showing which blocks have been written */
+int            nvalid; /* number of bytes in valid array */
+#define        SETBIT(ARRAY, N)        ((ARRAY)[(N)/8] |= (1 << ((N)%8)))
+#define        BITVAL(ARRAY, N)        ((ARRAY)[(N)/8] & (1 << ((N)%8)))
+
+off64_t filesize;
+int blocksize;
+int count;
+int verbose;
+int wsync;
+int direct;
+int alloconly;
+int rt;
+int extsize;
+int preserve;
+int test;
+off64_t fileoffset;
+struct dioattr diob;
+struct fsxattr rtattr;
+
+#define        READ_XFER       10      /* block to read at a time when checking */
+
+void usage(char *progname);
+int findblock(void);
+void writeblks(int fd);
+int readblks(int fd);
+void dumpblock(int *buffer, off64_t offset, int blocksize);
+
+void
+usage(char *progname)
+{
+       fprintf(stderr, "usage: %s [-l filesize] [-b blocksize] [-c count] [-o write offset] [-s seed] [-x extentsize] [-w] [-v] [-d] [-r] [-a] [-p] filename\n",
+                       progname);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int seed, ch, fd, oflags;
+       char *filename;
+        int r;
+
+       filesize = ((off64_t)256)*1024*1024;
+       blocksize = 512;
+       count = filesize/blocksize;
+       verbose = 0;
+       wsync = 0;
+       seed = time(NULL);
+        test = 0;
+       while ((ch = getopt(argc, argv, "b:l:s:c:o:x:vwdrapt")) != EOF) {
+               switch(ch) {
+               case 'b':       blocksize  = atoi(optarg);      break;
+               case 'l':       filesize   = strtoll(optarg, NULL, 16); break;
+               case 's':       seed       = atoi(optarg);      break;
+               case 'c':       count      = atoi(optarg);      break;
+               case 'o':       fileoffset = strtoll(optarg, NULL, 16); break;
+               case 'x':       extsize    = atoi(optarg);      break;
+               case 'v':       verbose++;                      break;
+               case 'w':       wsync++;                        break;
+               case 'd':       direct++;                       break;
+               case 'r':       rt++;                           break;
+               case 'a':       alloconly++;                    break;
+               case 'p':       preserve++;                     break;
+                case 't':       test++; preserve++;             break;
+               default:        usage(argv[0]);                 break;
+               }
+       }
+       if (optind == argc-1)
+               filename = argv[optind];
+       else
+               usage(argv[0]);
+       if ((filesize % blocksize) != 0) {
+               filesize -= filesize % blocksize;
+               printf("filesize not a multiple of blocksize, reducing filesize to %lld\n",
+                                filesize);
+       }
+       if ((fileoffset % blocksize) != 0) {
+               fileoffset -= fileoffset % blocksize;
+               printf("fileoffset not a multiple of blocksize, reducing fileoffset to %lld\n",
+                      fileoffset);
+       }
+       if (count > (filesize/blocksize)) {
+               count = (filesize/blocksize);
+               printf("count of blocks written is too large, setting to %d\n",
+                             count);
+       } else if (count < 1) {
+               count = 1;
+               printf("count of blocks written is too small, setting to %d\n",
+                             count);
+       }
+       printf("randholes: Seed = %d (use \"-s %d\" to re-execute this test)\n", seed, seed);
+       srandom(seed);
+        
+        printf("randholes: blocksize=%d, filesize=%Ld, seed=%d\n"
+               "randholes: count=%d, offset=%Ld, extsize=%d\n",
+                blocksize, filesize, seed, count, fileoffset, extsize);
+        printf("randholes: verbose=%d, wsync=%d, direct=%d, rt=%d, alloconly=%d, preserve=%d, test=%d\n",
+                verbose, wsync, direct, rt, alloconly, preserve, test);
+        
+       /*
+        * Open the file, write rand block in random places, read them all
+        * back to check for correctness, then close the file.
+        */
+       nvalid = (filesize / blocksize) / 8 + 1;
+       if ((valid = (unsigned char *)calloc(1, (unsigned)nvalid)) == NULL) {
+               perror("malloc");
+               return 1;
+       }
+       if (rt)
+               direct++;
+        
+        oflags=test?(O_RDONLY):(O_RDWR | O_CREAT);
+       oflags |=   (preserve ? 0 : O_TRUNC) |
+                   (wsync ? O_SYNC : 0) |
+                   (direct ? O_DIRECT : 0);
+        
+       if ((fd = open(filename, oflags, 0666)) < 0) {
+               perror("open");
+               return 1;
+       }
+       if (rt) {
+               if (ioctl(fd, XFS_IOC_FSGETXATTR, &rtattr) < 0) {
+                       perror("ioctl(XFS_IOC_FSGETXATTR)");
+                       return 1;
+               }
+               if ((rtattr.fsx_xflags & XFS_XFLAG_REALTIME) == 0 ||
+                   (extsize && rtattr.fsx_extsize != extsize * blocksize)) {
+                       rtattr.fsx_xflags |= XFS_XFLAG_REALTIME;
+                       if (extsize)
+                               rtattr.fsx_extsize = extsize * blocksize;
+                       if (ioctl(fd, XFS_IOC_FSSETXATTR, &rtattr) < 0) {
+                               perror("ioctl(XFS_IOC_FSSETXATTR)");
+                               return 1;
+                       }
+               }
+       }
+       if (direct) {
+               if (ioctl(fd, XFS_IOC_DIOINFO, &diob) < 0) {
+                       perror("ioctl(XFS_IOC_FIOINFO)");
+                       return 1;
+               }
+               if (blocksize % diob.d_miniosz) {
+                       fprintf(stderr, "blocksize %d must be a multiple of %d for direct I/O\n", blocksize, diob.d_miniosz);
+                       return 1;
+               }
+       }
+        printf(test?"write (skipped)\n":"write\n");
+       writeblks(fd);
+        printf("readback\n");
+       r=readblks(fd);
+       if (close(fd) < 0) {
+               perror("close");
+               return 1;
+       }
+       free(valid);
+        
+        if (r) {
+            printf("randholes: %d errors found during readback\n", r);
+            return 2;
+        } else {
+            printf("randholes: ok\n");
+            return 0;
+        }
+}
+
+void
+writeblks(int fd)
+{
+       off64_t offset;
+       char *buffer;
+       int block;
+       struct flock64 fl;
+
+       if (direct)
+               buffer = memalign(diob.d_mem, blocksize);
+       else
+               buffer = malloc(blocksize);
+       if (buffer == NULL) {
+               perror("malloc");
+               exit(1);
+       }
+       memset(buffer, 0, blocksize);
+
+       for (  ; count > 0; count--) {
+               if (verbose && ((count % 100) == 0)) {
+                       printf(".");
+                       fflush(stdout);
+               }
+               block = findblock();
+               offset = (off64_t)block * blocksize;
+               if (alloconly) {
+                        if (test) continue;
+                        
+                       fl.l_start = offset;
+                       fl.l_len = blocksize;
+                       fl.l_whence = 0;
+                       if (ioctl(fd, XFS_IOC_RESVSP64, &fl) < 0) {
+                               perror("ioctl(XFS_IOC_RESVSP64)");
+                               exit(1);
+                       }
+                       continue;
+               }
+               SETBIT(valid, block);
+                if (!test) {
+                       if (lseek64(fd, fileoffset + offset, SEEK_SET) < 0) {
+                               perror("lseek");
+                               exit(1);
+                       }
+                }
+               *(off64_t *)buffer = *(off64_t *)(buffer+256) =
+                       fileoffset + offset;
+                if (!test) {
+                       if (write(fd, buffer, blocksize) < blocksize) {
+                               perror("write");
+                               exit(1);
+                       }
+                }
+                if (test && verbose>1) printf("NOT ");
+               if (verbose > 1) {
+                       printf("writing data at offset=%llx, value 0x%llx and 0x%llx\n",
+                              fileoffset + offset,
+                              *(off64_t *)buffer, *(off64_t *)(buffer+256));
+               }
+       }
+
+       free(buffer);
+}
+
+int
+readblks(int fd)
+{
+       long offset;
+       char *buffer, *tmp;
+       int xfer, block, i;
+        int err=0;
+
+       if (alloconly)
+               return 0;
+       xfer = READ_XFER*blocksize;
+       if (direct)
+               buffer = memalign(diob.d_mem, xfer);
+       else
+               buffer = malloc(xfer);
+       if (buffer == NULL) {
+               perror("malloc");
+               exit(1);
+       }
+       memset(buffer, 0, xfer);
+       if (verbose)
+               printf("\n");
+
+       if (lseek64(fd, fileoffset, SEEK_SET) < 0) {
+               perror("lseek");
+               exit(1);
+       }
+       for (offset = 0, block = 0; offset < filesize; offset += xfer) {
+               if ((i = read(fd, buffer, xfer) < xfer)) {
+                       if (i < 2)
+                               break;
+                       perror("read");
+                       exit(1);
+               }
+               for (tmp = buffer, i = 0; i < READ_XFER; i++, block++, tmp += blocksize) {
+                       if (verbose && ((block % 100) == 0)) {
+                               printf("+");
+                               fflush(stdout);
+                       }
+                       if (BITVAL(valid, block) == 0) {
+                               if ((*(off64_t *)tmp != 0LL) ||
+                                   (*(off64_t *)(tmp+256) != 0LL)) {
+                                       printf("mismatched data at offset=%llx, expected 0x%llx, got 0x%llx and 0x%llx\n",
+                                              fileoffset + block * blocksize,
+                                              0LL,
+                                              *(off64_t *)tmp,
+                                              *(off64_t *)(tmp+256));
+                                        err++;
+                               }
+                       } else {
+                               if ( (*(off64_t *)tmp !=
+                                     fileoffset + block * blocksize) ||
+                                    (*(off64_t *)(tmp+256) !=
+                                     fileoffset + block * blocksize) ) {
+                                       printf("mismatched data at offset=%llx, expected 0x%llx, got 0x%llx and 0x%llx\n",
+                                              fileoffset + block * blocksize,
+                                              fileoffset + block * blocksize,
+                                              *(off64_t *)tmp,
+                                              *(off64_t *)(tmp+256));
+                                        err++;
+                               }
+                       }
+                       if (verbose > 2) {
+                               printf("block %d blocksize %d\n", block,
+                                      blocksize);
+                               dumpblock((int *)tmp,
+                                         fileoffset + block * blocksize,
+                                         blocksize);
+                       }
+               }
+       }
+       if (verbose)
+               printf("\n");
+
+       free(buffer);
+        return err;
+}
+
+int
+findblock(void)
+{
+       int block, numblocks;
+
+       numblocks = filesize / blocksize;
+       block = random() % numblocks;
+       if (BITVAL(valid, block) == 0)
+               return(block);
+
+       for (  ; BITVAL(valid, block) != 0; block++) {
+               if (block == (numblocks-1))
+                       block = -1;
+       }
+       if (block == -1)
+               printf("returning block -1\n");
+       return(block);
+}
+
+void
+dumpblock(int *buffer, off64_t offset, int blocksize)
+{
+       int     i;
+
+       for (i = 0; i < (blocksize / 16); i++) {
+               printf("%llx: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                      offset, *buffer, *(buffer + 1), *(buffer + 2),
+                      *(buffer + 3));
+               offset += 16;
+               buffer += 4;
+       }
+}
diff --git a/src/random.c b/src/random.c
new file mode 100644 (file)
index 0000000..65e6af4
--- /dev/null
@@ -0,0 +1,239 @@
+/**************************************************************************
+ *
+ * random.c -- pseudo random number generator
+ * Copyright (C) 1994  Chris Wallace (csw@bruce.cs.monash.edu.au)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************/
+
+
+/*
+ * modified by dxm@sgi.com so that this file acts as a drop in replacement
+ * for srandom and random.
+ */
+
+/*
+ *     A random number generator called as a function by
+ *     random (iseed)  or      irandm (iseed)
+ *     The parameter should be a pointer to a 2-element long vector.
+ *     The first function returns a double uniform in 0 .. 1.
+ *     The second returns a long integer uniform in 0 .. 2**31-1
+ *     Both update iseed[] in exactly the same way.
+ *     iseed[] must be a 2-element integer vector.
+ *     The initial value of the second element may be anything.
+ *
+ *     The period of the random sequence is 2**32 * (2**32-1)
+ *     The table mt[0:127] is defined by mt[i] = 69069 ** (128-i)
+ */
+
+#define MASK ((long) 593970775)
+/*     or in hex, 23674657     */
+
+#define SCALE ((double) 1.0 / (1024.0 * 1024.0 * 1024.0 * 2.0))
+/*     i.e. 2 to power -31     */
+
+static long mt [128] =   {
+      902906369,
+     2030498053,
+     -473499623,
+     1640834941,
+      723406961,
+     1993558325,
+     -257162999,
+    -1627724755,
+      913952737,
+      278845029,
+     1327502073,
+    -1261253155,
+      981676113,
+    -1785280363,
+     1700077033,
+      366908557,
+    -1514479167,
+     -682799163,
+      141955545,
+     -830150595,
+      317871153,
+     1542036469,
+     -946413879,
+    -1950779155,
+      985397153,
+      626515237,
+      530871481,
+      783087261,
+    -1512358895,
+     1031357269,
+    -2007710807,
+    -1652747955,
+    -1867214463,
+      928251525,
+     1243003801,
+    -2132510467,
+     1874683889,
+     -717013323,
+      218254473,
+    -1628774995,
+    -2064896159,
+       69678053,
+      281568889,
+    -2104168611,
+     -165128239,
+     1536495125,
+      -39650967,
+      546594317,
+     -725987007,
+     1392966981,
+     1044706649,
+      687331773,
+    -2051306575,
+     1544302965,
+     -758494647,
+    -1243934099,
+      -75073759,
+      293132965,
+    -1935153095,
+      118929437,
+      807830417,
+    -1416222507,
+    -1550074071,
+      -84903219,
+     1355292929,
+     -380482555,
+    -1818444007,
+     -204797315,
+      170442609,
+    -1636797387,
+      868931593,
+     -623503571,
+     1711722209,
+      381210981,
+     -161547783,
+     -272740131,
+    -1450066095,
+     2116588437,
+     1100682473,
+      358442893,
+    -1529216831,
+     2116152005,
+     -776333095,
+     1265240893,
+     -482278607,
+     1067190005,
+      333444553,
+       86502381,
+      753481377,
+       39000101,
+     1779014585,
+      219658653,
+     -920253679,
+     2029538901,
+     1207761577,
+    -1515772851,
+     -236195711,
+      442620293,
+      423166617,
+    -1763648515,
+     -398436623,
+    -1749358155,
+     -538598519,
+     -652439379,
+      430550625,
+    -1481396507,
+     2093206905,
+    -1934691747,
+     -962631983,
+     1454463253,
+    -1877118871,
+     -291917555,
+    -1711673279,
+      201201733,
+     -474645415,
+      -96764739,
+    -1587365199,
+     1945705589,
+     1303896393,
+     1744831853,
+      381957665,
+     2135332261,
+      -55996615,
+    -1190135011,
+     1790562961,
+    -1493191723,
+      475559465,
+          69069
+               };
+
+double 
+_random (long is [2])
+{
+       long it, leh, nit;
+
+       it = is [0];
+       leh = is [1];
+       if (it <= 0)    
+               it = (it + it) ^ MASK;
+       else
+               it = it + it;
+       nit = it - 1;
+/*     to ensure all-ones pattern omitted    */
+       leh = leh * mt[nit & 127] + nit;
+       is [0] = it;    is [1] = leh;
+       if (leh < 0) leh = ~leh;
+       return (SCALE * ((long) (leh | 1)));
+}
+
+
+
+long 
+_irandm (long is [2])
+{
+       long it, leh, nit;
+
+       it = is [0];
+       leh = is [1];
+       if (it <= 0)    
+               it = (it + it) ^ MASK;
+       else
+               it = it + it;
+       nit = it - 1;
+/*     to ensure all-ones pattern omitted    */
+       leh = leh * mt[nit & 127] + nit;
+       is [0] = it;    is [1] = leh;
+       if (leh < 0) leh = ~leh;
+       return (leh);
+}
+
+/*
+ * make this a drop in replacement for random and srandom
+ *
+ * XXX not thread safe I guess.
+ */
+
+static long saved_seed[2];
+
+long random(void)
+{
+    return _irandm(saved_seed);
+}
+
+void srandom(unsigned seed)
+{
+    saved_seed[0]=seed;
+    saved_seed[1]=0;
+    _irandm(saved_seed);
+}
+
diff --git a/src/runas.c b/src/runas.c
new file mode 100644 (file)
index 0000000..b7a18c6
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/*
+ * Run a command with a particular 
+ *    - effective user id
+ *    - effective group id
+ *    - supplementary group list
+ */
+#include "global.h"
+#include <grp.h>
+
+
+
+char *prog;
+
+void usage(void)
+{
+    fprintf(stderr, "usage: %s [-u uid] [-g gid] [-s gid] cmd\n"
+           "flags:\n"
+           "    -u - effective user-id\n"
+           "    -g - effective group-id\n"
+           "    -s - supplementary group-id\n", prog);
+           
+}
+
+#define SUP_MAX 20
+
+int
+main(int argc, char **argv)
+{
+       int c;
+        uid_t uid = -1;
+        gid_t gid = -1;
+        char *cmd=NULL;
+        gid_t sgids[SUP_MAX];
+        int sup_cnt = 0;
+       int status;
+
+        prog = basename(argv[0]);
+
+       while ((c = getopt(argc, argv, "u:g:s:")) != -1) {
+               switch (c) {
+               case 'u':
+                       uid = atoi(optarg);
+                       break;
+               case 'g':
+                       gid = atoi(optarg);
+                       break;
+               case 's':
+                       if (sup_cnt+1 > SUP_MAX) {
+                           fprintf(stderr, "%s: too many sup groups\n", prog);
+                           exit(1);
+                       }
+                       sgids[sup_cnt++] = atoi(optarg);
+                       break;
+               case '?':
+                        usage();
+                       exit(1);
+               }
+       }
+
+        /* build up the cmd */
+       for ( ; optind < argc; optind++) {
+           cmd = realloc(cmd, (cmd==NULL?0:strlen(cmd)) + 
+                               strlen(argv[optind]) + 4);
+           strcat(cmd, " ");
+           strcat(cmd, argv[optind]);
+       }
+
+        if (gid != -1) {
+           if (setegid(gid) == -1) {
+               fprintf(stderr, "%s: setegid(%d) failed: %s\n",
+                       prog, gid, strerror(errno));
+               exit(1);
+           }   
+        }
+
+        if (sup_cnt > 0) {
+           if (setgroups(sup_cnt, sgids) == -1) {
+               fprintf(stderr, "%s: setgroups() failed: %s\n",
+                       prog, strerror(errno));
+               exit(1);
+           }   
+       }
+
+        if (uid != -1) {
+           if (seteuid(uid) == -1) {
+               fprintf(stderr, "%s: seteuid(%d) failed: %s\n",
+                       prog, uid, strerror(errno));
+               exit(1);
+           }   
+        }
+
+       status = system(cmd);
+
+       if (WIFSIGNALED(status)) {
+           fprintf(stderr, "%s: command terminated with signal %d\n", 
+                 prog, WTERMSIG(status));
+           exit(1);
+       }
+       else if (WIFEXITED(status)) {
+           exit(WEXITSTATUS(status));
+        }
+       else {
+           fprintf(stderr, "%s: command bizarre wait status 0x%x\n", 
+               prog, status);
+           exit(1);
+       }
+
+       exit(0);
+       /* NOTREACHED */
+}
diff --git a/src/truncfile.c b/src/truncfile.c
new file mode 100644 (file)
index 0000000..e5fcde9
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include "global.h"
+
+long filesize;
+int blocksize;
+int count;
+int verbose;
+off64_t fileoffset;
+
+void usage(char *progname);
+void writeblk(int fd);
+void truncfile(int fd);
+
+void
+usage(char *progname)
+{
+       fprintf(stderr, "usage: %s [-l filesize] [-b blocksize] [-c count] [-s seed] [-o fileoffset (hex)] [-v] filename\n",
+                       progname);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int seed, i, ch, fd;
+       char *filename;
+
+       filesize = 256*1024*1024;
+       blocksize = 512;
+       count = filesize/blocksize;
+       verbose = 0;
+       fileoffset = 0;
+       seed = time(NULL);
+       while ((ch = getopt(argc, argv, "b:l:s:c:o:v")) != EOF) {
+               switch(ch) {
+               case 'b':       blocksize  = atoi(optarg);      break;
+               case 'l':       filesize   = atol(optarg);      break;
+               case 's':       seed       = atoi(optarg);      break;
+               case 'c':       count      = atoi(optarg);      break;
+               case 'o':       fileoffset = strtoll(optarg, NULL, 16); break;
+               case 'v':       verbose++;                      break;
+               default:        usage(argv[0]);                 break;
+               }
+       }
+       if (optind == argc-1)
+               filename = argv[optind];
+       else
+               usage(argv[0]);
+       printf("Seed = %d (use \"-s %d\" to re-execute this test)\n", seed, seed);
+       srandom(seed);
+
+       /*
+        * Open the file, write rand block in random places, truncate the file,
+        * repeat ad-nauseum, then close the file.
+        */
+       if ((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) {
+               perror("open");
+               return 1;
+       }
+       for (i = 0; i < count; i++) {
+               writeblk(fd);
+               truncfile(fd);
+               if (verbose && ((i % 100) == 0)) {
+                       printf(".");
+                       fflush(stdout);
+               }
+       }
+       if (close(fd) < 0) {
+               perror("close");
+               return 1;
+       }
+       return 0;
+}
+
+void
+writeblk(int fd)
+{
+       off_t offset;
+       static char *buffer = NULL;
+
+       if ((buffer == NULL) && ((buffer = calloc(1, blocksize)) == NULL)) {
+               perror("malloc");
+               exit(1);
+       }
+
+       offset = random() % filesize;
+       if (lseek64(fd, (off64_t)(fileoffset + offset), SEEK_SET) < 0) {
+               perror("lseek");
+               exit(1);
+       }
+       *(long *)buffer = *(long *)(buffer+256) = (long)offset;
+       if (write(fd, buffer, blocksize) < blocksize) {
+               perror("write");
+               exit(1);
+       }
+       if (verbose > 1)
+               printf("writing   data at offset=%llx\n",
+                      (fileoffset + offset));
+}
+
+void
+truncfile(int fd)
+{
+       off_t offset;
+
+       offset = random() % filesize;
+       if (ftruncate64(fd, (off64_t)(fileoffset + offset)) < 0) {
+               perror("truncate");
+               exit(1);
+       }
+       if (verbose > 1)
+               printf("truncated file to offset %llx\n",
+                      (fileoffset + offset));
+}
diff --git a/src/usemem.c b/src/usemem.c
new file mode 100644 (file)
index 0000000..60ad9ef
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+/*
+ *
+ * usemem: allocate and lock a chunk of memory effectively removing
+ *         it from the usable physical memory range
+ *
+ *                                                  - dxm 04/10/00
+ */
+
+#include <stdio.h>
+#include <malloc.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+
+void
+usage(char *argv0)
+{
+    fprintf(stderr,"Usage: %s <mb>\n", argv0);
+    exit(1);
+}
+
+static void
+signalled(int sig)
+{
+    printf("*** signal\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+    int mb;
+    char *buf;
+    
+    if (argc!=2) usage(argv[0]);
+    mb=atoi(argv[1]);
+    if (mb<=0) usage(argv[0]);
+    
+    buf=malloc(mb*1024*1024);
+    if (!buf) {
+        perror("malloc");
+        exit(1);
+    }
+    if (mlock(buf,mb*1024*1024)) {
+        perror("mlock");
+        exit(1);
+    }
+    
+    printf("%s: %d mb locked - interrupt to release\n", argv[0], mb);
+    signal(SIGINT, signalled);
+    pause();
+    printf("%s: %d mb unlocked\n", argv[0], mb);
+    
+    return 0;
+}
+
+