--- /dev/null
+Quick guide to auto-qa dxm 04/10/2000
+______________________ ______________
+
+
+ - pick/create a user to run auto-qa and check they
+ can use ptools to check out of the tree
+ - add your host to cmd/xfs/stress/common.config
+ - add your host to cmd/xfs/tools/auto-qa
+ check both these files in
+ - make a directory "$HOME/qa"
+ - make a workarea "$HOME/qa/linux-xfs" for linux-xfs
+ (easiest to copy one from elsewhere)
+ - cd $HOME/qa ; ln -s linux-xfs/cmd/xfs/tools/auto-qa .
+ (auto-qa must be a link into it's own source tree
+ so it can update itself)
+ - copy an appropriate .config file to
+ $HOME/qa/$HOSTNAME-2.4.0-xfs-qa.config
+ - You'll need a hacked version of 'su' in $HOME/qa that
+ lets your user su to root/root without a password
+ (if you want to run from cron, it mustn't require
+ /dev/tty). Warning - this is a massive security
+ hole.
+ - chown root.root $HOME/qa/su
+ - chmod 6755 $HOME/qa/su
+ - add the soon to be kernel to /etc/lilo.conf
+
+ image=/boot/vmlinuz-2.4.0-xfs-qa
+ label=linux-xfs-qa
+ append = "console=ttyS0,38400n8"
+
+ - $HOME/qa/auto-qa init
+
+At this point, the script should update the workarea, clean it,
+rebuild it, install it and reboot.
+
+Then run
+
+ - $HOME/qa/auto-qa restarted
+
+And the tests should happen... and all pass, of course.
+
+To get it going automagically:
+
+ - add some lines to the appropriate user's crontab:
+
+ 0 4 * * * $HOME/qa/auto-qa cron-init
+ 30 4 * * * $HOME/qa/auto-qa cron-restarted
+
+Notes:
+ - if MODULAR=1 in auto-qa XFS and pagebuf are expected to
+ be modules. if MODULAR=0 they should be built into
+ the kernel
+ - the test device is cleaned at the start of the QA run
+ (to stop nightly QA being stuffed up if someone
+ leaves the device inconsistant etc)
+ - I'm using a hacked su because PCP sudo won't set the
+ gid properly, and normal linux su won't run
+ without a tty even if PAM is pissed-off.
+ - The QA is restarted after reboot by a second cron entry
+ to avoid the test being able to get itself into
+ some stupid loop and so that it's always started
+ by the appropriate user. You might have to make
+ the second cron run later if your build takes ages.
+ - Point the email addresses somewhere appropriate
+ - When run in "cron-init" or "init" states, the script
+ will p_tupdate itself and restart. If you start
+ with an empty source tree, you'll need to check
+ out the cmd/xfs/tools/auto-qa script before it'll
+ work (duh).
+
+good luck.
--- /dev/null
+#!/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/
+#
+
+# automatic qa system. 31/08/00 dxm@sgi.com
+
+_log()
+{
+ echo "$*" >&2
+ echo "$*" >> $LOG
+}
+
+_fail()
+{
+ if [ "$started" = "1" ]
+ then
+ echo "auto-qa stopped" | wall
+ started=0
+ fi
+
+ _log "$*"
+
+ # send special email if a cron'd qa run fails
+ case $state
+ in
+ cron*)
+ mail -s "xfs qa status report" $ADMINEMAIL \
+ < $LOG 2>&1
+ ;;
+ esac
+
+ status=1
+ exit 1
+}
+
+# configuration (you could tune this)
+
+EXTRA="-xfs-qa"
+VERSION="2.4.0"
+BOOT="/boot"
+SOAK_PASSES="-1"
+SOAK_STRESS="10000"
+SOAK_PROC="3"
+
+# this should be constant
+
+ROOT="$HOME/qa"
+HOST=`hostname -s`
+export WORKAREA="$ROOT/linux-xfs"
+
+export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin/ptools:/usr/local/bin"
+STATE=$ROOT/qa.state
+QADIR="$WORKAREA/cmd/xfs/stress"
+SUDO="su -c"
+IMAGE="$BOOT/vmlinuz-$VERSION$EXTRA"
+SYSTEMMAP="$BOOT/System.map-$VERSION$EXTRA"
+CONFIG="$ROOT/$HOST-$VERSION$EXTRA.config"
+MODULES="/lib/modules/$VERSION$EXTRA"
+SELF="$ROOT/auto-qa"
+SELF_UPDATE="cmd/xfs/tools/auto-qa"
+COMMON_CONFIG="$WORKAREA/cmd/xfs/stress/common.config"
+SH="/bin/sh"
+LOG="$ROOT/qa.log"
+
+# need to add auto-qa hosts here
+
+case $HOST
+in
+ fuzzy)
+ EMAIL="dxm@larry"
+ ADMINEMAIL="dxm@larry"
+ MODULAR=1
+ ;;
+ bruce)
+ EMAIL="dxm@larry"
+ ADMINEMAIL="dxm@larry"
+ MODULAR=1
+ ;;
+ sagan)
+ EMAIL="dxm@larry"
+ ADMINEMAIL="dxm@larry"
+ MODULAR=0
+ ;;
+ troppo)
+ EMAIL="nathans@larry"
+ ADMINEMAIL="nathans@larry"
+ MODULAR=0
+ ;;
+ *)
+ _fail "auto-qa: no configuration information for host '$HOST'"
+ ;;
+esac
+
+# do some cleanup on exit
+
+_cleanup()
+{
+ umount $SCRATCH_DEV &> /dev/null
+ umount $TEST_DEV &> /dev/null
+ if [ "$started" = 1 ]
+ then
+ echo "auto-qa stopped" | wall
+ started=0
+ fi
+}
+status=1
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# clean exit
+
+_success()
+{
+ status=0
+ exit 0
+}
+
+_get_state()
+{
+ state=`cat $STATE`
+}
+
+_set_state()
+{
+ echo $1 > $STATE
+ _get_state
+}
+
+_change_state()
+{
+ new=$1
+
+ case $state
+ in
+ *-*)
+ case $new
+ in
+ *-*)
+ _set_state $new
+ ;;
+ *)
+ _set_state `echo $state | sed "s/-.*$/-$new/"`
+ ;;
+ esac
+ ;;
+ *)
+ _set_state $new
+ ;;
+ esac
+}
+
+_sudo()
+{
+ $ROOT/su -c "$*" < /dev/null ;# HACK - we need a hacked su at the mo
+}
+
+_restart()
+{
+ exec $ROOT/su -c "shutdown -r 2 \"auto-qa rebooting\" &" < /dev/null
+}
+
+_log "*** linux-xfs QA (`date`)"
+
+_get_state
+
+# check preconditions for starting state
+case $1
+in
+ cron-init)
+ case $state
+ in
+ *done)
+ ;;
+ *)
+ _fail " !!! cron-init while not in \"*done\" state"
+ ;;
+ esac
+ ;;
+ cron-restarted)
+ # we don't auto restart after reboot, but cron the restart
+ # to happen a bit later - it's much easier and safer that way
+ if [ $state != "cron-restarted" ]
+ then
+ _fail " !!! cron-restarted while not in \"cron-restarted\" state"
+ fi
+ ;;
+esac
+
+if [ "$1" != "" ]
+then
+ _set_state $1
+fi
+
+[ $UID -eq 0 ] && _fail " !!! QA most be run as a normal user"
+[ -d $ROOT ] || _fail " !!! QA root \"$ROOT\" not found"
+[ -d $WORKAREA ] || _fail " !!! QA workarea \"$WORKAREA\" not found"
+[ -r $CONFIG ] || _fail " !!! Can't read config file $CONFIG"
+. $COMMON_CONFIG || _fail " !!! Couldn't source $COMMON_CONFIG"
+
+cd $ROOT
+
+started=1
+echo "auto-qa started" | wall
+
+while true
+do
+ _get_state
+
+ _log " *** state $state start (`date`)"
+ _log " (user=$USER, host=$HOST)"
+ new_state=""
+
+ case $state
+ in
+ *init)
+ echo "" > $ROOT/qa.log
+ echo "" > $ROOT/qa.full
+ _log "******************************************"
+ _log "QA init (`date`)"
+ _log "******************************************"
+
+ _change_state "inited"
+ exec $SH -c "cd $WORKAREA ; p_tupdate $SELF_UPDATE ; chmod +x $SELF_UPDATE ; exec $SELF"
+ ;;
+
+ *inited)
+ _log " *** QA initialized"
+ new_state="update"
+ ;;
+
+ *update)
+ _log " *** p_tupdate"
+ cd $WORKAREA
+ p_tupdate 2>&1 \
+ || _fail " !!! p_tupdate failed"
+
+ _log " *** p_check/p_purge"
+ cd $WORKAREA
+ p_check -s | p_purge -yiu 2>&1 \
+ || _fail " !!! p_check/p_purge failed"
+
+ _log " *** non-trunk files"
+ cd $WORKAREA
+ p_list -c 2>&1 \
+ || _fail " !!! p_list failed"
+
+ new_state="clean"
+ ;;
+
+ *clean)
+ # we need to configure or else we might fail to clean stress/src
+ _log " *** configure for clean"
+ cd $WORKAREA/cmd/xfs
+ make configure 2>&1 \
+ || _fail " !!! configure for clean failed"
+
+ _log " *** clean stress/src"
+ cd $WORKAREA/cmd/xfs/stress/src
+ make clobber 2>&1 \
+ || _fail " !!! clean stress/src failed"
+
+ _log " *** clean xfs tools"
+ cd $WORKAREA/cmd/xfs
+ make realclean 2>&1 \
+ || _fail " !!! clean tools failed"
+
+ _log " *** clean quota tools"
+ cd $WORKAREA/cmd/quota
+ ( rm -f configure ; autoconf ; sh configure ; make clean ) 2>&1 \
+ || _fail " !!! clean quota failed"
+
+ _log " *** clean qa"
+ cd $WORKAREA/cmd/xfs/stress
+ rm -f *.full *.bad *.log *.time *.core core 2>&1 \
+ || _fail " !!! clean qa failed"
+
+ _log " *** clean linux"
+ cd $WORKAREA/linux
+ make mrproper 2>&1 \
+ || _fail " !!! clean linux failed"
+
+ _log " *** install configuration file"
+ cp -f $CONFIG $WORKAREA/linux/.config 2>&1 \
+ || _fail " !!! failed to install config"
+
+ _log " *** remove version file"
+ rm -f include/linux/version.h 2>&1 \
+ || _fail " !!! failed to clean version"
+
+ new_state="reconfig"
+ ;;
+
+ *reconfig)
+
+ _log " *** reconfig kernel"
+
+ _change_state "clean" ;# if this fails, we'd better start from scratch
+
+ cd $WORKAREA/linux
+ # we want to use default options for any new config options.
+ echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" | \
+ make EXTRAVERSION=$EXTRA oldconfig 2>&1 \
+ || _fail " !!! reconfig oldconfig failed"
+ make EXTRAVERSION=$EXTRA dep 2>&1 \
+ || _fail " !!! reconfig dep failed"
+
+ new_state="build"
+ ;;
+
+ *build)
+ _log " *** build kernel"
+
+ _change_state "clean" ;# if this fails, we'd better start from scratch
+
+ cd $WORKAREA/linux
+ make -j2 EXTRAVERSION=$EXTRA bzImage 2>&1 \
+ || _fail " !!! build bzImage failed"
+ make -j2 EXTRAVERSION=$EXTRA modules 2>&1 \
+ || _fail " !!! build modules failed"
+
+ _log " *** build tools"
+ cd $WORKAREA/cmd/xfs
+
+ # use e-fence - but this will only take effect on configure
+ export MALLOCLIB=/usr/lib/libefence.a
+ make configure 2>&1 \
+ || _fail " !!! configure tools failed"
+ make default 2>&1 \
+ || _fail " !!! build tools failed"
+
+ _log " *** build quota tools"
+ cd $WORKAREA/cmd/quota
+
+ # use e-fence - but this will only take effect on configure
+ export MALLOCLIB=/usr/lib/libefence.a
+ ( rm -f configure ; autoconf ; sh configure ; make all ) 2>&1 \
+ || _fail " !!! build quota failed"
+
+ _log " *** build stress/src"
+ cd $WORKAREA/cmd/xfs/stress/src
+
+ make default 2>&1 \
+ || _fail " !!! build stress/src failed"
+
+ new_state="install"
+ ;;
+
+ *install)
+ _log " *** blat old modules"
+
+ _sudo rm -rf $MODULES
+
+ _log " *** install kernel"
+ cd $WORKAREA/linux
+ _sudo cp -f $WORKAREA/linux/arch/i386/boot/bzImage $IMAGE 2>&1 \
+ || _fail " !!! install kernel failed"
+ _sudo cp -f $WORKAREA/linux/System.map $SYSTEMMAP 2>&1 \
+ || _fail " !!! install kernel failed"
+ _sudo make EXTRAVERSION=$EXTRA modules_install 2>&1 \
+ || _fail " !!! install modules failed"
+
+ _log " *** install xfs tools"
+ cd $WORKAREA/cmd/xfs
+ _sudo make install 2>&1 \
+ || _fail " !!! install tools failed"
+
+ _log " *** install quota tools"
+ cd $WORKAREA/cmd/quota
+ _sudo make install 2>&1 \
+ || _fail " !!! install quota failed"
+
+ _log " *** reinit lilo"
+ _sudo /sbin/lilo 2>&1 \
+ || _fail " !!! reinit lilo failed"
+ new_state="restart"
+ ;;
+
+ *restart)
+ _log " *** select qa kernel"
+ _sudo /sbin/lilo -R linux-xfs-qa 2>&1 \
+ || _fail " !!! lilo failed"
+
+ _log " *** prepare to restart"
+ _change_state "restarted"
+
+ _log " *** restarting"
+
+ _restart # doesn't return
+ ;;
+
+ *restarted)
+ _log " *** QA reentered after restart"
+
+ new_state="check"
+ ;;
+
+ *check)
+ uname=`uname -ar`
+ _log " *** uname $uname"
+ _log " *** user tools"
+ ls -l /sbin/*xfs* /usr/sbin/*xfs* 2>&1
+ _log " *** kernel"
+ ls -l /boot/*$EXTRA* 2>&1
+ _log " *** kernel modules"
+ ls -l /lib/modules/$VERSION$EXTRA/kernel/fs/pagebuf/* \
+ /lib/modules/$VERSION$EXTRA/kernel/fs/xfs/* \
+ /lib/modules/$VERSION$EXTRA/kernel/fs/xfs/support/*
+
+ if [ $MODULAR -eq 0 ]
+ then
+ new_state="reset"
+ else
+ new_state="probe"
+ fi
+ ;;
+
+ *probe)
+ _log " *** modules dependencies"
+
+ _sudo depmod -a 2>&1 \
+ || _fail " !!! failed to depmod -a"
+
+ _log " *** unmounting XFS mounts"
+
+ _sudo umount -a -t xfs 2>&1
+
+ _log " *** removing modules"
+
+ for m in xfsidbg xfs pagebuf kdbm_pg kdbm_vm
+ do
+ _sudo rmmod $m 2> /dev/null
+ done
+
+ _log " *** installing modules"
+
+ _sudo modprobe xfs 2>&1 \
+ || _fail " !!! failed to modprobe xfs"
+
+ new_state="reset"
+ ;;
+
+ *reset)
+
+ _log " *** unmounting TEST_DEV"
+
+ _sudo umount $TEST_DEV 2>&1
+
+ _log " *** unmounting SCRATCH_DEV"
+
+ _sudo umount $SCRATCH_DEV 2>&1
+
+ _log " *** clean TEST_DEV"
+
+ _sudo mkfs -t xfs -f $TEST_DEV 2>&1 \
+ || _fail " !!! failed to mkfs TEST_DEV"
+
+ _log " *** mounting TEST_DEV"
+
+ _sudo mount -t xfs $TEST_DEV $TEST_DIR 2>&1 \
+ || _fail " !!! failed to mount"
+
+ new_state="run"
+ ;;
+
+
+ soak-run)
+ cd $QADIR
+
+ _log " *** run soak test"
+ _sudo ./soak $SOAK_PASSES $SOAK_STRESS $SOAK_PROC\
+ || _fail " !!! failed to run soak test"
+
+ new_state="done"
+ ;;
+
+ *run)
+ cd $QADIR
+
+ _log " *** run tests"
+ _sudo ./check -l -g auto 2>&1 | tee $ROOT/qa.out
+
+ _log ""
+ _log " *** send status mail"
+ mail -s "xfs qa status report" $EMAIL < $ROOT/qa.out 2>&1
+
+ new_state="done"
+ ;;
+
+ *done)
+ _log "*** QA run complete"
+
+ _success
+ ;;
+
+ *nothing)
+ new_state="done"
+ _log " *** do nothing"
+ ;;
+
+ *)
+ _fail " !!! unknown state $state"
+ ;;
+ esac
+
+ _log " *** state $state done (`date`)"
+ [ "$new_state" = "" ] && _fail " !!! no new state set"
+ _change_state $new_state
+
+done
--- /dev/null
+#!/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/
+#
+
+#
+# use db to try to traverse the entire filesystem starting at the root
+#
+# dxm 5/10/00
+
+my $device;
+my $rootino;
+my $agcount;
+my $versionnum;
+my $dir_version;
+my @dir_inodes;
+my @bmap_blocks;
+my @block_inodes;
+my $mode;
+
+sub db($)
+{
+ my ($args)=@_;
+ my ($ret);
+
+ $ret=`xfs_db -r $args $device 2> /dev/null`;
+ die "ERROR executing xfs_db -r $args $device" if ($?);
+
+ return $ret;
+}
+
+sub fmt($)
+{
+ my ($text)=@_;
+ my $c=0;
+ print " ";
+ foreach (split("\n",$text)) {
+ s/^core\.//;
+
+ if ($c+length($_) >= 70) {
+ $c=0;
+ print ",\n ";
+ }
+ if ($c) {
+ print ", ";
+ $c+=2;
+ }
+ print "$_";
+ $c+=length($_)+2;
+ }
+ print "\n";
+}
+
+sub inode($)
+{
+ my ($num)=@_;
+ my ($t);
+
+ @dir_inodes=();
+
+ $t=db("-c \"inode $num\" -c \"print\"");
+ print " *** Inode $num\n";
+ fmt($t);
+
+ ($mode)= $t=~ /^core.mode = (\d+)$/m;
+
+ if ($t=~ /a\.bmx/m) {
+ bmap("inode $num","attr");
+ foreach (@bmap_blocks) {
+ attr_block($_);
+ }
+ }
+ if (eval "$mode & 040000") {
+ if ( $t=~ /sfdir/m) {
+ while ($t=~ /inumber(?:\.i[48])? = (\d+)$/mg) {
+ push(@dir_inodes,$1);
+ }
+ }
+ if ( $t=~ /u\.bmx/m) {
+ bmap("inode $num","dir");
+ foreach (@bmap_blocks) {
+ dir_block($_);
+ push(@dir_inodes,@block_inodes);
+ }
+ }
+ } else {
+ bmap("inode $num","file") if ( $t=~ /u\.bmx/m);
+ }
+}
+
+sub bmap($$)
+{
+ my ($cmd,$type)=@_;
+ my ($t);
+
+ @bmap_blocks=();
+
+ $flag=($type eq "attr")?"-a":"";
+
+ $t=db("-c \"$cmd\" -c \"bmap $flag\"");
+ print " *** bmap $type $cmd\n";
+ fmt($t);
+
+ if ($type eq "dir" || $type eq "attr") {
+ while ($t=~ /startblock (\d+) \(.+\) count (\d+)/mg) {
+ for ($b=$1;$b<$1+$2;$b++) {
+ push(@bmap_blocks,$b);
+ }
+ }
+ }
+}
+
+sub dir_block($)
+{
+ my ($num)=@_;
+ my ($t);
+
+ @block_inodes=();
+
+ $type=($dir_version==2)?"dir2":"dir";
+
+ $t=db("-c \"fsblock $num\" -c \"type $type\" -c \"print\"");
+ print " *** $type block $num\n";
+ # need to drop . and ..
+ ($self)= $t=~ /\[(\d+)\].name = \"\.\"/m;
+ ($parent)= $t=~ /\[(\d+)\].name = \"\.\.\"/m;
+ fmt($t);
+
+
+ while ($t=~ /\[(\d+)\].inumber = (\d+)/mg) {
+ next if (defined $self && $1 == $self);
+ next if (defined $parent && $1 == $parent);
+ push(@block_inodes, $2);
+ }
+}
+
+sub attr_block($)
+{
+ my ($num)=@_;
+ my ($t);
+
+ $t=db("-c \"fsblock $num\" -c \"type attr\" -c \"print\"");
+ print " *** attr block $num\n";
+
+ fmt($t);
+}
+
+sub sb($)
+{
+ my ($num)=@_;
+ my ($t);
+
+ $t=db("-c \"sb $num\" -c \"print\"");
+ print " *** SB $num\n";
+ fmt($t);
+
+ ($rootino)= $t=~ /^rootino = (\d+)$/m;
+ ($agcount)= $t=~ /^agcount = (\d+)$/m;
+ ($versionnum)= $t=~ /^versionnum = (0x[\da-f]+)$/m;
+ $dir_version = (eval "$versionnum & 0x2000")?2:1;
+}
+
+die "Usage: $0 <XFS device>\n" unless (@ARGV == 1);
+
+$device=shift @ARGV;
+die "can't read $device\n" unless (-r $device);
+die "$device is not a block device\n" unless (-b _);
+
+chomp($HOST = `hostname -s`);
+
+print "*** db-walk host $HOST device $device\n";
+
+sb(0);
+for ($ag=1;$ag<$agcount;$ag++) {
+ sb($ag);
+}
+
+@inodes=($rootino);
+while ($_ = shift @inodes) {
+ inode($_);
+ push(@inodes,@dir_inodes);
+}
--- /dev/null
+#!/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/
+#
+
+#
+# traverse the entire filesystem dumping info.
+#
+# dxm 5/10/00
+use MD5;
+use Getopt::Std;
+
+my %opt;
+
+sub scan($)
+{
+ my ($file)=@_;
+ my ($md5)=new MD5;
+ my (@stat);
+
+ unless (@stat=lstat("$file")) {
+ printf("%-" . ($opt{v}?65:32) . "s $file\n", "!!! could not lstat");
+ return;
+ }
+
+ $stat[0]=$stat[8]=""; # wipe the device and access time
+ $md5->reset;
+ $md5->add(join(" ",@stat));
+
+ print join(" ",@stat), "\n";
+
+ if ($opt{v}) {
+ print $md5->hexdigest . " ";
+ $md5->reset;
+ }
+
+ if (-l "$file") {
+ if (!defined($link = readlink $file)) {
+ printf("%-32s $file\n", "!!! could not readlink");
+ return;
+ }
+ $md5->add($link);
+ } elsif (-f "$file") {
+ if (!open(FILE, "$file")) {
+ printf("%-32s $file\n", "!!! could not read");
+ return;
+ }
+ $md5->addfile(FILE);
+ close (FILE);
+ }
+ print $md5->hexdigest . " $file\n";
+}
+
+getopts('vs', \%opt);
+
+die "Usage: $0 <dir>\n" unless (@ARGV == 1);
+
+$dir=shift @ARGV;
+die "can't read $dir\n" unless (-r $dir);
+die "$dir is not a directory\n" unless (-d _);
+
+chomp($HOST = `hostname -s`);
+
+print "*** fs-walk host $HOST dir $dir\n";
+
+@todo=$dir;
+while ($dir = shift @todo) {
+ scan($dir);
+ unless (opendir(DIR,$dir)) {
+ printf("%-" . ($opt{v}?65:32) . "s $dir\n", "!!! could not opendir");
+ next;
+ }
+ unless (@all=readdir(DIR)) {
+ printf("%-" . ($opt{v}?65:32) . "s $dir\n", "!!! could not readdir");
+ next;
+ }
+ closedir(DIR);
+ @dirs=grep(-d "$dir/$_" && !-l "$dir/$_", @all);
+ foreach (@all) {
+ next if /^\.\.?$/;
+ scan("$dir/$_");
+ }
+
+ foreach (grep(!/^\.\.?$/, @dirs)) {
+ push (@todo,"$dir/$_");
+ }
+}
+
--- /dev/null
+#!/usr/sbin/perl
+
+sub setup()
+{
+ $PATH="$PATH:/usr/local/bin/ptools:/sbin:/usr/sbin";
+ $DISPLAY="clouds:0";
+
+ if ("$HOST" eq "bruce") {
+ $TOOLS="/home/dxm/isms/slinx-xfs/cmd/xfs/tools";
+ $SCRATCH_DEV="/dev/sdf1";
+ $SCRATCH_MNT="/mnt/xfs3";
+ $MKFS="/sbin/mkfs -t xfs -f";
+ $SUDO="/home/dxm/su -c";
+ $MOUNT="/bin/mount -t xfs";
+ $UMOUNT="/bin/umount";
+ $MKFS_EXTRA="-f";
+ } elsif ("$HOST" eq "whack") {
+ $TOOLS="/hosts/snort/build1/people/dxm/isms/slinx-xfs/cmd/xfs/tools";
+ $SCRATCH_DEV="/dev/dsk/20000080e5114459/lun2s0/c2p1";
+ $SCRATCH_MNT="/lun2";
+ $MKFS="/sbin/mkfs";
+ $SUDO="su root -c";
+ $MOUNT="/sbin/mount -t xfs";
+ $UMOUNT="/sbin/umount";
+ $MKFS_EXTRA="";
+ } else {
+ die "unconfigured host \"$HOST\"\n"
+ }
+}
+
+sub run_no_check(@)
+{
+ system(@_);
+}
+
+sub run(@)
+{
+ system(@_) == 0
+ || die "ERROR \"" . join(" ",@_) . "\" returned error\n";
+}
+
+sub run_expect_fail(@)
+{
+ system(@_) == 0
+ && die "ERROR \"" . join(" ",@_) . "\" returned non-error\n";
+}
+
+sub umount_no_check()
+{
+ run_no_check("umount $SCRATCH_DEV");
+}
+
+sub umount()
+{
+ run("umount $SCRATCH_DEV");
+}
+
+sub mount($)
+{
+ my ($ops)=@_;
+ run("mount -t xfs $ops $SCRATCH_DEV $SCRATCH_MNT");
+}
+
+chomp($HOST=`hostname -s`);
+
+die "usage: $ARGV0 <operation> [parameters]\n" unless (scalar(@ARGV));
+print "*** $HOST: Interop started\n";
+print " *** ", join(" ", @ARGV), "\n";
+
+setup();
+
+$op=shift(@ARGV);
+
+umount_no_check();
+
+if ($op eq "init") {
+
+ run("mkfs -t xfs $MKFS_EXTRA $SCRATCH_DEV");
+
+} elsif ($op eq "test") {
+
+ run("xfs_repair -n $SCRATCH_DEV");
+
+} elsif ($op eq "easy") {
+
+ mount("");
+ system("mount");
+ mkdir("$SCRATCH_MNT/fish",0777);
+
+} elsif ($op eq "check") {
+
+ mount("-o ro");
+ system("cd $SCRATCH_MNT ; $TOOLS/fs-walk .");
+
+} else {
+ die "unknown operation \"$op\"\n";
+}
+
+umount_no_check();
--- /dev/null
+#!/usr/bin/perl -w
+use strict;
+#
+# srcdiff is used to compare current user level code with the current
+# kernel code and advise of any differences between files which are
+# sharing some or all of their content.
+#
+# There are two classes of sharing which we will check - header files
+# in the include directory, which must be exactly the same (use diff)
+# and source files which contain routines which must be exactly the
+# same (but the userland file is always a subset of the kernel file,
+# and hence a more flexible mechanism to "diff" is required).
+#
+# NB: to cross check that srcdiff is finding all the functions in the
+# user source file, providing you have "mkproto" installed, you
+# can "cd cmd/xfs/libxfs" and cut&paste this into a bourne shell:
+# $ for file in xfs_*.c; do
+# > mkproto -nps < $file | perl -ne '
+# > END { print " $count\t- " }
+# > s/^.* (xfs\w+|\*xfs\w+|xlog\w+|\*xlog\w+) \(.*/\1/ && { $count++ }'
+# > echo $file
+# > done
+# (compare this to "srcdiff | fgrep Total:") ... repeat for logprint.
+#
+
+die "WORKAREA not set" unless defined $ENV{'WORKAREA'};
+chdir $ENV{'WORKAREA'};
+my $xdiff = $ENV{'XDIFF'};
+my $quiet=0;
+my $usage=0;
+
+foreach (@ARGV) {
+ if (/^-q$/) {
+ $quiet++;
+ } else {
+ print STDERR "Illegal option $_\n";
+ $usage++;
+ }
+}
+
+if ($usage) {
+ print STDERR "Usage: $0 [-q]\n";
+ exit 1;
+}
+
+my @difflist = qw(
+ xfs_ag.h xfs_alloc.h xfs_alloc_btree.h xfs_arch.h
+ xfs_attr_leaf.h xfs_attr_sf.h xfs_bit.h xfs_bmap.h
+ xfs_bmap_btree.h xfs_btree.h xfs_buf_item.h
+ xfs_da_btree.h xfs_dfrag.h xfs_dinode.h xfs_dir.h
+ xfs_dir2.h xfs_dir2_block.h xfs_dir2_data.h
+ xfs_dir2_leaf.h xfs_dir2_node.h xfs_dir2_sf.h
+ xfs_dir_leaf.h xfs_dir_sf.h xfs_dqblk.h xfs_dquot_item.h
+ xfs_extfree_item.h xfs_ialloc.h xfs_imap.h
+ xfs_ialloc_btree.h xfs_inode.h xfs_inode_item.h
+ xfs_inum.h xfs_log.h xfs_log_priv.h xfs_log_recover.h
+ xfs_mount.h xfs_quota.h xfs_rtalloc.h
+ xfs_sb.h xfs_trans.h xfs_trans_space.h xfs_types.h
+);
+
+sub straightdiff {
+ my ( $file, $prefix1, $prefix2 ) = @_;
+
+ `diff $prefix1/$file $prefix2/$file >/dev/null 2>&1`;
+ if (!$quiet) {
+ print sprintf("\t%-35s ... ", $file);
+ if ($? != 0) { print "FAILED\n"; }
+ else { print "ok\n"; }
+ } elsif ($? != 0) {
+ printf("\t%-35s ... ", $file);
+ print "FAILED\n";
+ }
+}
+
+print "\n=== Checking headers ===\n";
+foreach (@difflist) {
+ straightdiff $_, 'cmd/xfs/include', 'linux/fs/xfs';
+}
+straightdiff 'xfs_cred.h', 'cmd/xfs/include', 'linux/fs/xfs/linux';
+straightdiff 'xfs_fs.h', 'cmd/xfs/include', 'linux/include/linux';
+straightdiff 'attributes.h', 'cmd/xfs/include', 'linux/include/linux';
+straightdiff 'acl.h', 'cmd/xfs/include', 'linux/fs/xfs/pseudo-inc/sys';
+straightdiff 'arch.h', 'cmd/xfs/include', 'linux/fs/xfs/support';
+straightdiff 'xqm.h', 'cmd/xfs/include', 'linux/include/linux';
+
+#
+# setstate
+# Implements a tri-state FSA, see comments for state transitions
+# (knows about the way the XFS kernel code is written, & makes
+# some assumptions so as to not need to parse generic C code).
+# Accepts one line at a time from a source file, picking out the
+# function bodies so they can be subsequently compared.
+#
+
+my $line; # line number in current source file
+my $state; # current FSA state
+my $funcbody; # current function body (contents)
+
+sub setstate {
+ my ( $newline ) = @_;
+ $line++;
+
+ # - state 0:
+ # if line looks like start of a function, transition to 1
+ # & squirrel line away as line 1 of current function
+ if ($state == 0) {
+ if ($newline =~ m/^[xfs|xlog]/) {
+ $state = 1;
+ $funcbody = $newline;
+ }
+ }
+
+ # - state 1:
+ # if line looks like start of a function, stay here
+ # & squirrel line away as line 1 of current function
+ # otherwise if line isn't start of function body,
+ # squirrel line away as next line of current function
+ # (args/..., but not sure this is a real function yet)
+ # otherwise (start of function)
+ # squirrel line away as next line of current function
+ # transition to state 2
+ elsif ($state == 1) {
+ if ($newline =~ m/^[xfs|xlog]/) {
+ $funcbody = $newline;
+ }
+ elsif ($newline =~ m/^\{/) {
+ $state = 2;
+ $funcbody .= $newline;
+ }
+ }
+
+ # - state 2:
+ # if line looks like end of function body,
+ # squirrel line away as last line of current function
+ # tell someone we have a complete function ready
+ # transition to state 0
+ # otherwise
+ # squirrel line away as next line of current function
+ elsif ($state == 2) {
+ $funcbody .= $newline;
+ if ($newline =~ m/^\}/) {
+ $state = 0;
+ return $funcbody;
+ }
+ }
+
+ else {
+ die "unknown state transition";
+ }
+ return undef; # i.e. not at end of a function
+}
+
+sub listfuncs {
+ my ( $file ) = @_;
+ my @funcs;
+
+ $funcbody = '';
+ $state = $line = 0;
+
+ open(USER, "$file") || die "cannot open $file";
+ while (<USER>) {
+ my $func = setstate($_);
+ push @funcs, $func if (defined($func)); # store function away
+ }
+ close USER;
+ return @funcs;
+}
+
+sub hashfuncs {
+ my ( $file ) = @_;
+ my %funcs;
+
+ $funcbody = '';
+ $state = $line = 0;
+
+ open(KERN, "$file") || die "cannot open $file";
+ while (<KERN>) {
+ my $func = setstate($_);
+ if (defined($func)) {
+ $func =~ m/^([xfs|xlog]\w+)\s*\(/;
+ next unless defined($1);
+ my $name = $1;
+ if (defined($func)) {
+ $funcs{$name} = $func; # store function away
+ }
+ }
+ }
+ close KERN;
+ return %funcs;
+}
+
+sub diffme {
+ my ( $sa, $sb ) = @_;
+
+ return unless defined($xdiff);
+
+ open(FILEA, "> /tmp/diff.user.$$") || die "cannot write to /tmp/diff.user.$$";
+ open(FILEB, "> /tmp/diff.kern.$$") || die "cannot write to /tmp/diff.kern.$$";
+ print FILEA $sa;
+ print FILEB $sb;
+ close FILEA;
+ close FILEB;
+ `$xdiff /tmp/diff.user.$$ /tmp/diff.kern.$$`;
+ unlink ("/tmp/diff.user.$$","/tmp/diff.kern.$$");
+}
+
+sub functiondiff {
+ my ( $file, $prefix1, $prefix2 ) = @_;
+ my $plural = '';
+ my $count = 0;
+ my $name;
+ my $found = 0;
+
+ print "\n=== Checking $file routines ===\n" unless ($quiet);
+
+ # iterate over user funcs, match up to kernel funcs
+ #
+ my @user = listfuncs "$prefix1/$file";
+ my %kern = hashfuncs "$prefix2/$file";
+
+ foreach my $userfunc (@user) {
+
+ $userfunc =~ m/^([xfs|xlog]\w+)\s*\(/;
+ next unless (defined($1));
+ $name = $1;
+ $count++;
+
+ if (exists($kern{$name})) {
+ if ($userfunc ne $kern{$name}) {
+ print "\n=== $file routines ===\n"
+ if (!$found++ && $quiet);
+
+ printf("\t%-35s ... ", $name);
+ print "FAILED\n";
+ diffme $userfunc, $kern{$name};
+ }
+ elsif (!$quiet) {
+ printf("\t%-35s ... ", $name);
+ print "ok\n";
+ }
+ }
+ else {
+ print "Cannot find kernel function $userfunc";
+ print " in file $prefix2/$file\n";
+ }
+ }
+ ($count != 1) && ( $plural = 's' );
+ print "( Total: $count routine$plural checked in $file )\n" unless ($quiet);
+}
+
+# cmd/xfs/{libxfs,logprint}/* fs/xfs/*
+my @funclist = qw(
+ xfs_alloc.c xfs_alloc_btree.c xfs_attr_leaf.c xfs_bit.c
+ xfs_bmap.c xfs_bmap_btree.c xfs_btree.c xfs_da_btree.c
+ xfs_dir.c xfs_dir2.c xfs_dir2_block.c xfs_dir2_data.c
+ xfs_dir2_leaf.c xfs_dir2_node.c xfs_dir2_sf.c
+ xfs_dir_leaf.c xfs_ialloc.c xfs_ialloc_btree.c
+ xfs_inode.c xfs_rtalloc.c xfs_rtbit.c xfs_mount.c
+ xfs_trans.c
+);
+
+print "\n=== Checking libxfs code ===\n";
+foreach (@funclist) {
+ functiondiff $_, 'cmd/xfs/libxfs', 'linux/fs/xfs';
+}
+print "\n=== Checking logprint code ===\n";
+functiondiff 'xfs_log_recover.c', 'cmd/xfs/logprint', 'linux/fs/xfs';
--- /dev/null
+#!/bin/sh -x
+#
+# Simple script which does the following:
+# o Generates a src tarball from a WORKAREA
+# o Copies it over to ~/test and unpacks it
+# o Generates a src tarball from src tarball
+# o Compares the build status' ... reports problems
+# o removes ~/test
+#
+
+tmpdir="$HOME/test"
+
+if [ -z "$WORKAREA" ]
+then
+ echo "WORKAREA is not set -- aborting."
+ exit 1
+fi
+
+if [ -d $tmpdir ]
+then
+ echo "$tmpdir exists already -- aborting."
+ exit 1
+else
+ mkdir $tmpdir
+ if [ ! -d $tmpdir ]
+ then
+ echo "Cannot create $tmpdir -- aborting."
+ exit 1
+ fi
+fi
+
+#
+# Pleasantries are now out of the way, lets proceed.
+# NB: If something goes wrong we'll leave the unpacked
+# source alone for consumption by a human.
+#
+
+_cleanup()
+{
+ if [ $status -eq 0 ]
+ then
+ rm -fr $tmpdir
+ else
+ echo "Problem? -- leaving $tmpdir for inspection"
+ fi
+}
+
+_buildme()
+{
+ cd $1
+
+ if ./Makepkgs
+ then
+ :
+ else
+ echo Makepkgs thinks theres a problem in $1
+ exit 1
+ fi
+
+ if [ ! -f build/xfs-cmds-*.src.tar.gz ]
+ then
+ echo Makepkgs failed to create build/xfs-cmds-*.src.tar.gz
+ exit 1
+ fi
+}
+
+status=1
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# first, build from the WORKAREA
+_buildme $WORKAREA/cmd/xfs
+
+cp $WORKAREA/cmd/xfs/build/xfs-cmds-*.src.tar.gz $tmpdir
+cd $tmpdir
+tar xzf xfs-cmds-*.src.tar.gz
+rm xfs-cmds-*.src.tar.gz # must delete for _buildme "cd" to work
+
+# now, cross check the src build
+_buildme $tmpdir/xfs-cmds-*
+
+status=0