cmd/xfs/tools/README.auto-qa 1.1 Renamed to cmd/xfstests/tools/README.auto-qa

This commit is contained in:
Nathan Scott
2001-01-15 05:23:30 +00:00
parent 27fba05e66
commit 08299f2370
7 changed files with 1383 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
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.
Executable
+537
View File
File diff suppressed because it is too large Load Diff
Executable
+211
View File
@@ -0,0 +1,211 @@
#!/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);
}
Executable
+117
View File
@@ -0,0 +1,117 @@
#!/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/$_");
}
}
Executable
+99
View File
@@ -0,0 +1,99 @@
#!/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();
Executable
+267
View File
@@ -0,0 +1,267 @@
#!/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';
+81
View File
@@ -0,0 +1,81 @@
#!/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