| #!/bin/sh | 
 | # | 
 | # Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved. | 
 | # | 
 | # 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. | 
 | # | 
 | # 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.  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 the Free Software Foundation, | 
 | # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | 
 | # | 
 | # | 
 | # automatic qa system. 31/08/00 dxm@sgi.com | 
 | # | 
 | # Usage: auto_qa start-state [stop-state] | 
 | # Do auto_qa from start-state up to stop-state inclusive | 
 | # or if no stop-state given then do it until reach "done" state. | 
 | # | 
 |  | 
 | _log() | 
 | { | 
 |     echo "$*" >&2 | 
 |     echo "$*" >> $LOG | 
 |     sync | 
 | } | 
 |  | 
 | _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" $EMAIL < $LOG 2>&1 | 
 | 	;; | 
 |     esac | 
 |  | 
 |     status=1 | 
 |     exit 1 | 
 | } | 
 |  | 
 | _get_kernel_version() | 
 | { | 
 |     [ -x "$KWORKAREA" ] || return | 
 |     [ -r "$KWORKAREA/Makefile" ] \ | 
 | 	|| _fail "can't read kernel makefile $KWORKAREA/Makefile" | 
 |  | 
 |     eval `awk ' | 
 | 	BEGIN { FS = "[ \t=]+" } | 
 | 	/^VERSION =/ { a=$2 } | 
 | 	/^PATCHLEVEL =/ { b=$2 } | 
 | 	/^SUBLEVEL =/ { c=$2 } | 
 | 	/^EXTRAVERSION =/ { d=$2 } | 
 | 	END {  | 
 | 	    print "VERSION=" a "." b "." c d " ; SVERSION=" a "." b "." c | 
 | 	} | 
 |    ' < $KWORKAREA/Makefile` | 
 | } | 
 |  | 
 | # this should be constant | 
 |  | 
 | ROOT="$HOME/qa" | 
 | HOST=`hostname -s` | 
 | if [ ! -z "$CVSROOT" ]; then | 
 |     export WORKAREA="$ROOT/xfs-cmds" | 
 | else | 
 |     [ -z "$WORKAREA" ] && export WORKAREA="$ROOT/xfs-cmds" | 
 | fi | 
 |  | 
 |  | 
 | export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin/ptools:/usr/local/bin" | 
 | STATE=$ROOT/qa.state | 
 | QADIR="$WORKAREA/xfstests" | 
 | SUDO="su -c" | 
 | CONFIG="$ROOT/$HOST.config" | 
 | COMMON_CONFIG="$QADIR/common/config" | 
 | SH="/bin/sh" | 
 | LOG="$ROOT/qa.log" | 
 |  | 
 | # 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 | 
 |  | 
 |     # if have state XXXX-state then preserve XXXX-newstate | 
 |      | 
 |     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 now \"auto-qa rebooting\" )&" < /dev/null | 
 | } | 
 |  | 
 | _update_workarea() | 
 | { | 
 |     if [ -z "$CVSROOT" ]; then | 
 | 	_log "	*** p_tupdate" | 
 | 	cd "$1" | 
 | 	WORKAREA="$1" p_tupdate 2>&1 \ | 
 | 			|| _fail "	    !!! p_tupdate failed" | 
 |  | 
 | 	_log "	*** non-trunk files" | 
 | 	cd "$1" | 
 | 	WORKAREA="$1" p_list -c 2>&1 \ | 
 | 			|| _fail "	    !!! p_list failed" | 
 |     else | 
 | 	_log "	*** cvs update" | 
 | 	cd "$1" | 
 | 	cvs -z3 update -d | 
 |     fi | 
 | } | 
 |  | 
 | _test_mkfs_xfs() | 
 | { | 
 |     TEST_OPTIONS="" | 
 |     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \ | 
 |         TEST_OPTIONS="$TEST_OPTIONS -rrtdev=$TEST_RTDEV" | 
 |     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \ | 
 |         TEST_OPTIONS="$TEST_OPTIONS -llogdev=$TEST_LOGDEV" | 
 |     _sudo /sbin/mkfs.xfs -f $TEST_OPTIONS $MKFS_OPTIONS $* $TEST_DEV | 
 |     mkfs_status=$? | 
 |     if [ "$USE_BIG_LOOPFS" = yes ]; then | 
 |         [ -z "$RETAIN_AG_BYTES" ] && RETAIN_AG_BYTES=0 | 
 |         _sudo $QADIR/tools/ag-wipe -q -r $RETAIN_AG_BYTES $TEST_DEV | 
 |     fi | 
 |     return $mkfs_status | 
 | } | 
 |  | 
 | _test_mount() | 
 | { | 
 |     TEST_OPTIONS="" | 
 |     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \ | 
 |         TEST_OPTIONS="$TEST_OPTIONS -ortdev=$TEST_RTDEV" | 
 |     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \ | 
 |         TEST_OPTIONS="$TEST_OPTIONS -ologdev=$TEST_LOGDEV" | 
 |     _sudo mount -t xfs $TEST_OPTIONS $MOUNT_OPTIONS $* $TEST_DEV $TEST_DIR | 
 | } | 
 |  | 
 | _i386_install() | 
 | { | 
 |     _sudo cp -f "$KWORKAREA/arch/i386/boot/bzImage" "$IMAGE" 2>&1 \ | 
 | 		|| _fail "	    !!! install kernel failed" | 
 |     _sudo cp -f "$KWORKAREA/System.map" "$SYSTEMMAP" 2>&1 \ | 
 | 		|| _fail "	    !!! install kernel failed" | 
 |     if [ -z "$KMODULES" -o "$KMODULES" = yes ]; then | 
 | 	_sudo make EXTRAVERSION=-$EXTRA modules_install 2>&1 \ | 
 | 		|| _fail "	    !!! install modules failed" | 
 |     fi | 
 |  | 
 |  | 
 |     if [ -z "$KINSTALL" -o "$KINSTALL" = lilo ]; then | 
 | 	_log "	*** reinit lilo" | 
 | 	_sudo /sbin/lilo 2>&1 \ | 
 | 		|| _fail "	    !!! reinit lilo failed" | 
 |     fi | 
 | } | 
 |  | 
 | _i386_restart() | 
 | { | 
 |     if [ -z "$KINSTALL" -o "$KINSTALL" = lilo ]; then | 
 | 	_sudo /sbin/lilo -R $EXTRA $KERNEL_OPTIONS 2>&1 \ | 
 | 		|| _fail "	    !!! lilo failed" | 
 |     fi | 
 | } | 
 |  | 
 | _ia64_install() | 
 | { | 
 |     echo not yet implemented | 
 | } | 
 |  | 
 | _ia64_restart() | 
 | { | 
 |     echo not yet implemented | 
 | } | 
 |  | 
 | _check_kernel() | 
 | { | 
 |     [ -d "$KWORKAREA" ]	|| _fail "    !!! QA kernel workarea \"$KWORKAREA\" not found" | 
 |     [ -r "$CONFIG" ]	|| _fail "    !!! Can't read config file $CONFIG" | 
 | } | 
 |  | 
 |  | 
 | _log "*** 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 | 
 |  | 
 | [ -n "$1" ] && _set_state $1 | 
 | [ -n "$2" ] && stop_state=$2 | 
 |  | 
 | [ "$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" | 
 | cd $QADIR | 
 | . "$COMMON_CONFIG" 	|| _fail "    !!! Couldn't source $COMMON_CONFIG" | 
 |  | 
 | _get_kernel_version | 
 | IMAGE="$BOOT/vmlinuz-$EXTRA" | 
 | SYSTEMMAP="$BOOT/System.map-$VERSION-$EXTRA" | 
 | MODULES="/lib/modules/$SVERSION" | 
 |  | 
 | 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="" | 
 |  | 
 |     start_state=$state | 
 |  | 
 |     case $state | 
 |     in | 
 | 	*init) | 
 | 	    echo "" > $ROOT/qa.log | 
 | 	    echo "" > $ROOT/qa.full | 
 | 	    _log "******************************************************" | 
 | 	    _log "QA init $VERSION (`date`)" | 
 | 	    _log "******************************************************" | 
 | 	    new_state="updatetools" | 
 | 	    ;; | 
 | 	 | 
 | 	*updatetools) | 
 | 	    _update_workarea "$WORKAREA" | 
 | 	    new_state="cleantools" | 
 | 	    ;; | 
 |  | 
 | 	*cleantools) | 
 | 	    # we need to configure or else we might fail to clean | 
 | 	    for pkg in attr acl xfsprogs dmapi xfsdump xfstests | 
 | 	    do | 
 | 		[ -d $WORKAREA/$pkg ] || continue | 
 | 		cd $WORKAREA/$pkg | 
 | 		_log "	*** clean $pkg tools" | 
 | 		make realclean 2>&1 \ | 
 | 			|| _fail "	    !!! clean $pkg failed" | 
 | 	    done | 
 | 	    new_state="buildtools" | 
 | 	    ;; | 
 |  | 
 | 	*buildtools) | 
 | 	    _log "	*** build and install tools" | 
 | 	    for pkg in attr acl xfsprogs dmapi xfsdump xfstests  | 
 | 	    do | 
 | 		[ -d $WORKAREA/$pkg ] || continue | 
 | 		cd $WORKAREA/$pkg | 
 |  | 
 | 		make configure 2>&1 \ | 
 | 			|| _fail "	    !!! configure $pkg failed" | 
 | 		make default 2>&1 \ | 
 | 			|| _fail "	    !!! build $pkg failed" | 
 |  | 
 | 		_sudo make install install-dev 2>&1 \ | 
 | 			|| _fail "	    !!! install $pkg failed" | 
 |  | 
 | 		# attr and acl now have install-lib targets as well | 
 | 		[ "$pkg" = "attr" -o "$pkg" = "acl" ] || continue | 
 | 		_sudo make install-lib 2>&1 \ | 
 | 			|| _fail "	    !!! install $pkg failed" | 
 | 	    done | 
 |  | 
 | 	    new_state="updatekernel" | 
 | 	    ;; | 
 |  | 
 | 	*updatekernel) | 
 | 	    _check_kernel | 
 | 	    _update_workarea "$KWORKAREA" | 
 | 	    new_state="cleankernel" | 
 | 	    ;; | 
 |  | 
 | 	*cleankernel) | 
 | 	    _check_kernel | 
 | 	    _log "	*** clean kernel" | 
 | 	    cd "$KWORKAREA" | 
 | 	    make mrproper 2>&1 \ | 
 | 			|| _fail "	    !!! clean kernel failed" | 
 |  | 
 | 	    _log "	*** install configuration file" | 
 | 	    cp -f $CONFIG "$KWORKAREA/.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) | 
 | 	    _check_kernel | 
 | 	    _log "	*** reconfig kernel" | 
 | 	     | 
 | 	    # we better start from scratch if this fails | 
 | 	    _change_state "cleankernel" | 
 | 	     | 
 | 	    cd "$KWORKAREA" | 
 | 	    # 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="buildkernel" | 
 | 	    ;; | 
 | 	     | 
 | 	*buildkernel) | 
 | 	    _check_kernel | 
 | 	    _log "	*** build kernel" | 
 | 	    _log "          --- kernel ($IMAGE)" | 
 | 	    [ -z "$KMODULES" -o "$KMODULES" = yes ] && \ | 
 |             _log "          --- modules ($MODULES)" | 
 | 	     | 
 | 	    _change_state "cleankernel" ; # we better start from scratch if this fails | 
 | 	     | 
 | 	    cd "$KWORKAREA" | 
 | 	    [ -z "$KTARGET" ] && KTARGET=bzImage | 
 | 	    [ -z "$KMODULES" -o "$KMODULES" = yes ] && \ | 
 | 		KTARGET="$KTARGET modules" | 
 | 	    make -j4 EXTRAVERSION=-$EXTRA $KTARGET 2>&1 \ | 
 | 			|| _fail "	    !!! build $KTARGET failed" | 
 | 	    new_state="install" | 
 | 	    ;; | 
 |  | 
 | 	*install) | 
 | 	    _check_kernel | 
 | 	    _log "	*** blat old modules" | 
 | 	    _sudo rm -rf $MODULES | 
 | 	     | 
 | 	    _log "	*** install kernel" | 
 | 	    cd "$KWORKAREA" | 
 | 	    case `uname -m` | 
 | 	    in | 
 | 		i386|i686)	_i386_install ;; | 
 | 		ia64)		_ia64_install ;; | 
 | 	    esac | 
 |  | 
 | 	    new_state="restart" | 
 | 	    ;; | 
 | 	     | 
 | 	*restart) | 
 | 	    _log "	    *** select qa kernel" | 
 | 	    case `uname -m` | 
 | 	    in | 
 | 		i386|i686)	_i386_restart ;; | 
 | 		ia64)		_ia64_restart ;; | 
 | 	    esac | 
 |  | 
 | 	    _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 -a` | 
 | 	    _log "	    *** uname $uname" | 
 |  | 
 | 	    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 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" | 
 | 	    _test_mkfs_xfs 2>&1 \ | 
 | 			|| _fail "	    !!! failed to mkfs TEST_DEV" | 
 | 	     | 
 | 	    _log "	    *** mounting TEST_DEV" | 
 | 	    _test_mount 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" | 
 | 	    ;; | 
 | 	     | 
 | 	bench-run) | 
 | 	    cd $QADIR | 
 | 	     | 
 | 	    # $BENCHMARK is typically unset, which equates to "all" | 
 | 	    # | 
 | 	    _log "	    *** run benchmarks" | 
 | 	    _sudo ./bench $BENCH_PASSES `id -nu && id -ng` $BENCHMARK \ | 
 | 			|| _fail "	    !!! failed to run benchmarks" | 
 |  | 
 | 	    _log "" | 
 | 	    _log "	    *** send results mail" | 
 | 	    mail -s "XFS QA benchmark results" $EMAIL < $QADIR/bench.out 2>&1 | 
 | 	 | 
 | 	    new_state="done" | 
 | 	    ;; | 
 | 	     | 
 | 	*run) | 
 | 	    cd $QADIR | 
 | 	     | 
 | 	    _log "	    *** run tests ($CHECK_OPTIONS)" | 
 | 	    _sudo ./check -l $CHECK_OPTIONS 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 "*** requested QA state transitions 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" | 
 |  | 
 |     if [ -n "$stop_state" ] | 
 |     then | 
 |         # remove hyphen prefixes | 
 | 	s1=`echo $start_state | sed 's/.*-//'` | 
 | 	s2=`echo $stop_state | sed 's/.*-//'` | 
 |  | 
 | 	if [ $s1 = $s2 ] | 
 | 	then | 
 | 	    # we have been requested to stop here and not go on | 
 | 	    new_state="done" | 
 | 	fi | 
 |     fi | 
 |  | 
 |     _change_state $new_state | 
 |      | 
 | done |