Whamcloud - gitweb
b=22281 refactor packaging and versioning
[fs/lustre-release.git] / build / lbuild
index 450236d..fd97a12 100755 (executable)
@@ -1,35 +1,85 @@
-#!/bin/sh
+#!/bin/bash
 
 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
 
 
 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
 
+# this is an alternative FD for stdout, to be used especially when we are
+# taking stdout from a function as it's return value.  i.e. foo=$(bar)
+# this is a workaround until a version of bash where we can put xtrace
+# on a specific FD
+exec 3>&1; STDOUT=3
+
+#set -x
+xtrace="+x"
+if [[ $SHELLOPTS = *xtrace* ]]; then
+    xtrace="-x"
+fi
+shopt -s extdebug
+
+# include the exit_traps library
+. ${0%/lbuild}/exit_traps.sh
+
+# our children should die when we do
+push_exit_trap "kill -INT -$$ || true" kill_children
+
+# increment this if you have made a change that should force a new kernel
+# to build built
+#BUILD_GEN=1
+#BUILD_GEN=2   # bz19952: remove -lustre tag from kernel RPM names
+#BUILD_GEN=3   # bz19975: enable the building of src.rpms by default
+BUILD_GEN=4    # bz22281: use the git hash in the kernel extra version
+
 TOPDIR=$PWD
 
 # CVSROOT is inherited from the environment
 KERNELDIR=
 LINUX=
 LUSTRE=
 TOPDIR=$PWD
 
 # CVSROOT is inherited from the environment
 KERNELDIR=
 LINUX=
 LUSTRE=
-RELEASE=0
-DO_SRC=0
-DOWNLOAD=1
+RELEASE=false
+# XXX - some recent hacking has pretty much neutered this option.
+#       search through this file (and lbuild.old_school -- but that will
+#       be going away soon) for "-bb" and see how many places
+#       simply don't account for this option
+DO_SRC=true
+DOWNLOAD=true
 TAG=
 TAG=
+CANONICAL_TARGET=
 TARGET=
 TARGET=
+TARGET_ARCH=$(uname -m)
 TARGET_ARCHS=
 TARGET_ARCHS=
+TARGET_ARCHS_ALL=$TARGET_ARCH
+[ "$TARGET_ARCH" = "i686" ] && TARGET_ARCHS_ALL="i686 i586 i386"
 CONFIGURE_FLAGS=
 EXTERNAL_PATCHES=
 EXTRA_VERSION=
 STAGEDIR=
 CONFIGURE_FLAGS=
 EXTERNAL_PATCHES=
 EXTRA_VERSION=
 STAGEDIR=
+TMPDIR=${TMPDIR:-"/var/tmp"}
+TIMESTAMP=
+# this is a dir to try reuse old kernel RPMs in (although, it seems to be
+# unused in any real manner
+REUSERPM=
+# this is the dir that should be used to store reuse products
+REUSEBUILD=
+# should cached products be used or force rebuilding?
+USE_BUILD_CACHE=true
+# what does this do exactly?  does it imply no kernel build?
+NORPM=false
+LDISKFSRPM=true
+SKIPLDISKFSRPM="v1_4_* b1_4"
+SMPTYPES="smp bigsmp default ''"
+PATCHLESS=false
+XEN=false
+LINUXOBJ=
+DISTRO=
+KERNELTREE=
+# default to not adding -lustre- into the kernel RPM package names
+KERNEL_LUSTRE_NAMING=false
+
+# patchless build
+KERNELRPMSBASE=
+RPMSMPTYPE=
 
 # from target file
 
 # from target file
-KERNEL=
 SERIES=
 SERIES=
-CONFIG=
-VERSION=
-
-RHBUILD=0
-SUSEBUILD=0
-LINUX26=0
-SUSEBUILD=0
-
 BASE_ARCHS=
 BIGMEM_ARCHS=
 BOOT_ARCHS=
 BASE_ARCHS=
 BIGMEM_ARCHS=
 BOOT_ARCHS=
@@ -39,11 +89,19 @@ BIGSMP_ARCHS=
 PSERIES64_ARCHS=
 UP_ARCHS=
 
 PSERIES64_ARCHS=
 UP_ARCHS=
 
+# not in the target file any more
+CONFIG=
+
+# build the lustre-tests rpm?
+LUSTRE_TESTS=true
+
 DATE=$(date)
 
 USE_DATESTAMP=1
 RPMBUILD=
 
 DATE=$(date)
 
 USE_DATESTAMP=1
 RPMBUILD=
 
+OLD_SCHOOL=false
+
 export CC=${CC:-gcc}
 
 # Readlink is not present on some older distributions: emulate it.
 export CC=${CC:-gcc}
 
 # Readlink is not present on some older distributions: emulate it.
@@ -58,40 +116,27 @@ readlink() {
     fi
 }
 
     fi
 }
 
-cleanup()
-{
+cleanup() {
+
     true
 }
 
     true
 }
 
-error()
-{
-    [ "$1" ] && echo -e "\n${0##*/}: $1"
+error() {
+    local msg="$1"
+
+    [ -n "$msg" ] && echo -e "\n${0##*/}: $msg" >&3
+
 }
 
 }
 
-fatal()
-{
+fatal() {
+
     cleanup
     error "$2"
     exit $1
     cleanup
     error "$2"
     exit $1
-}
 
 
-is_release()
-{
-    (( $RELEASE )) || return 0
-}
-
-list_targets()
-{
-    echo -n "Available targets:"
-    for target in $TOPDIR/lustre/lustre/kernel_patches/targets/*.target ; do
-        target_file=${target##*/}
-        echo -n " ${target_file%%.target}"
-    done
-    echo
 }
 
 }
 
-usage()
-{
+usage() {
     cat <<EOF
 Usage: ${0##*/} [OPTION]... [-- <lustre configure options>]
 
     cat <<EOF
 Usage: ${0##*/} [OPTION]... [-- <lustre configure options>]
 
@@ -108,11 +153,39 @@ Usage: ${0##*/} [OPTION]... [-- <lustre configure options>]
   --extraversion=EXTRAVERSION
     Text to use for the rpm release and kernel extraversion.
 
   --extraversion=EXTRAVERSION
     Text to use for the rpm release and kernel extraversion.
 
+  --timestamp=TIMESTAMP
+    Date of building lustre in format YYYYMMDDhhmmss
+
+  --reuserpm=DIR
+    Try to reuse old kernel RPMs from DIR
+
+  --reusebuild=DIR
+    Try to reuse old kernel builds from DIR
+
+  --kernelrpm=DIR
+    Path to distro kernel RPM collection
+
+  --ccache
+    Use ccache
+
+  --norpm
+    Do not build RPMs (compile only mode)
+
+  --patchless
+    Build lustre client only
+
+  --distro=DISTRO
+    Which distro using. Autodetect by default
+
   --kerneldir=KERNELDIR
     Directory containing Linux source tarballs referenced by target
     files.
 
   --kerneldir=KERNELDIR
     Directory containing Linux source tarballs referenced by target
     files.
 
-  --linux=LINUX
+  --kerneltree=KERNELTREE
+    Directory containing dirs with Linux source tarballs referenced by target
+    files. Dir names in format kernel version ('2.6.9', etc.)
+
+  --linux=LINUX --with-linux=LINUX
     Directory of Linux kernel sources.  When this option is used, only
     Lustre modules and userspace are built.
 
     Directory of Linux kernel sources.  When this option is used, only
     Lustre modules and userspace are built.
 
@@ -121,12 +194,15 @@ Usage: ${0##*/} [OPTION]... [-- <lustre configure options>]
     pulling from CVS.
 
   --nodownload
     pulling from CVS.
 
   --nodownload
-    Do not try to download a kernel from ftp.lustre.org
+    Do not try to download a kernel from downloads.lustre.org
 
   --nosrc
     Do not build a .src.rpm, a full kernel patch, or a patched kernel
     tarball.
 
 
   --nosrc
     Do not build a .src.rpm, a full kernel patch, or a patched kernel
     tarball.
 
+  --ldiskfs
+    Do ldiskfs RPM. Now true by default
+
   --publish
     Unused.
 
   --publish
     Unused.
 
@@ -160,10 +236,16 @@ Usage: ${0##*/} [OPTION]... [-- <lustre configure options>]
     will be built - there will be no lustre-lite-utils package.
 
   --disable-datestamp
     will be built - there will be no lustre-lite-utils package.
 
   --disable-datestamp
-    Prevents the datestamp flag (-D) from being passed to cvs for 
-    checkouts. This is a workaround for a problem encountered when 
+    Prevents the datestamp flag (-D) from being passed to cvs for
+    checkouts. This is a workaround for a problem encountered when
     using lbuild with tinderbox.
 
     using lbuild with tinderbox.
 
+  --xen
+    Builds a Xen domX kernel.
+
+  --set-value
+    Set's a variable to a given value.
+
 EOF
 
 #   list_targets
 EOF
 
 #   list_targets
@@ -171,9 +253,40 @@ EOF
     fatal "$1" "$2"
 }
 
     fatal "$1" "$2"
 }
 
-check_options()
-{
-    if [ "$LUSTRE" ] ; then
+# canonicalize a relative path to a file
+canon_filepath() {
+    local PATH="$1"
+
+    if [ ! -f "$PATH" ]; then
+        return 1
+    fi
+
+    local FILE=${PATH##*/}
+    local DIR=${PATH%/*}
+
+    echo $(canon_path "$DIR")/$FILE
+    return 0
+}
+
+# canonicalize a relative path to a dir
+canon_path() {
+    local PATH="$1"
+
+    if [ ! -d "$PATH" ]; then
+        return 1
+    fi
+
+    pushd "$PATH" >/dev/null || return 1
+    local CANONPATH=$PWD
+    popd >/dev/null
+
+    echo "$CANONPATH"
+    return 0
+}
+
+check_options() {
+
+    if [ "$LUSTRE" ]; then
         [ -r "$LUSTRE" ] || \
             usage 1 "Could not find Lustre source tarball '$LUSTRE'."
     else
         [ -r "$LUSTRE" ] || \
             usage 1 "Could not find Lustre source tarball '$LUSTRE'."
     else
@@ -183,14 +296,14 @@ check_options()
             usage 1 "A branch/tag name must be specified with --tag when not building from a tarball."
     fi
 
             usage 1 "A branch/tag name must be specified with --tag when not building from a tarball."
     fi
 
-    if [ -z "$LINUX" ] ; then
-        [ "$KERNELDIR" ] || \
-            usage 1 "A kernel directory must be specified with --kerneldir."
+    if [ -z "$LINUX" ]; then
+        [ "$KERNELDIR" -o "$KERNELTREE" ] || \
+            usage 1 "A kernel directory must be specified with --kerneldir or --kerneltree."
 
 
-        [ -d "$KERNELDIR" ] || \
-            usage 1 "$KERNELDIR is not a directory."
+        [ -d "$KERNELDIR" -o -d "$KERNELTREE" ] || \
+            usage 1 "$KERNELDIR and $KERNELTREE are not a directory."
 
 
-        if ! (( $RELEASE )) ; then
+        if ! $RELEASE; then
             [ "$TAG" ] || \
                 usage 1 "When building a snapshot, a tag name must be used."
         fi
             [ "$TAG" ] || \
                 usage 1 "When building a snapshot, a tag name must be used."
         fi
@@ -202,12 +315,24 @@ check_options()
     fi
 
     case $TARGET in
     fi
 
     case $TARGET in
+        2.6-rhel5)
+            CANONICAL_TARGET="rhel5"
+            ;;
         2.6-rhel4)
             CANONICAL_TARGET="rhel-2.6"
             ;;
         2.6-suse)
             CANONICAL_TARGET="sles-2.6"
             ;;
         2.6-rhel4)
             CANONICAL_TARGET="rhel-2.6"
             ;;
         2.6-suse)
             CANONICAL_TARGET="sles-2.6"
             ;;
+        2.6-sles10)
+            CANONICAL_TARGET="sles10-2.6"
+            ;;
+        2.6-sles11)
+            CANONICAL_TARGET="sles11"
+            ;;
+        2.6-oel5)
+            CANONICAL_TARGET="oel5"
+            ;;
         hp_pnnl-2.4)
             CANONICAL_TARGET="hp-pnnl-2.4"
             ;;
         hp_pnnl-2.4)
             CANONICAL_TARGET="hp-pnnl-2.4"
             ;;
@@ -221,7 +346,14 @@ check_options()
                 ;;
     esac
 
                 ;;
     esac
 
-    TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M")
+    local timestampnodig=$(echo $TIMESTAMP | sed -e s/[0-9]*//g)
+    [ "$timestampnodig" = "" ] || TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M%S")
+    local timestamplength="${#TIMESTAMP}"
+    if [ $timestamplength -eq 12 ]; then
+        TIMESTAMP="${TIMESTAMP}00"
+    elif [ $timestamplength -ne 14 ]; then
+        TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M%S")
+    fi
 
     RPMBUILD=$(which rpmbuild 2>/dev/null | head -1)
     if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
 
     RPMBUILD=$(which rpmbuild 2>/dev/null | head -1)
     if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
@@ -230,128 +362,293 @@ check_options()
             usage 1 "Could not find binary for making rpms (tried rpmbuild and rpm)."
         fi
     fi
             usage 1 "Could not find binary for making rpms (tried rpmbuild and rpm)."
         fi
     fi
+
+    if [ -n "$CCACHE" ]; then
+        which "$DISTCC" &>/dev/null && export DISTCC RPM_BUILD_NCPUS
+
+        if which "$CCACHE" &>/dev/null; then
+            local ccache=$(which "$CCACHE")
+            local bindir="$TOPDIR/bin"
+
+            if [ ! -d $bindir ]; then
+                mkdir -p $bindir || fatal 1 "error trying to create $bindir"
+            else
+                rm ${bindir}/* > /dev/null 2>&1 || true
+            fi
+            ln -s "$ccache" ${bindir}/ccache
+            ln -s "$ccache" ${bindir}/cc
+            ln -s "$ccache" ${bindir}/$CC
+            export PATH=$bindir:$PATH
+            export CCACHE && export CC="ccache $CC"
+            # zero the cache so we can see how effective we are being with it
+            echo -n "ccache "
+            ccache -z
+
+            # get some ccache stats when we are done
+            push_exit_trap '[ -n "$CCACHE" ] && ccache -s' "ccache_summary"
+            # should remove the ccache trap if lbuild is interrupted
+            trap 'echo "Received an INT TERM or HUP signal, terminating."; delete_exit_trap "ccache_summary"; exit 1' INT TERM HUP
+        fi
+    fi
+
+    [ -z "$DISTRO" ] && DISTRO=$(autodetect_distro)
+
+    return 0
+
+}
+
+# autodetect used Distro
+autodetect_distro() {
+
+    local name
+    local version
+
+    if [ -f /etc/SuSE-release ]; then
+        name=sles
+        version=$(grep ^VERSION /etc/SuSE-release)
+        version=${version#*= }
+    elif [ -f /etc/redhat-release ]; then
+        name=$(head -1 /etc/redhat-release)
+        version=$(echo "$distroname" |
+                  sed -e 's/^[^0-9.]*//g' | sed -e 's/[ \.].*//')
+    fi
+    if [ -z "$name" -o -z "$version" ]; then
+        fatal 1 "I don't know how to determine distro type/version.\nEither update autodetect_distro() or use the --distro argument"
+    fi
+
+    echo ${name}${version}
+    return 0
+
 }
 
 }
 
-uniqify()
-{
+uniqify() {
+
     echo $(echo "$*" | xargs -n 1 | sort -u)
     echo $(echo "$*" | xargs -n 1 | sort -u)
+
+}
+
+download_srpm() {
+    local target=$1
+    local srpm=$2
+    local force="${3:-false}"
+
+    if $force || [ ! -r "$KERNELDIR/$srpm" ] ||
+       [ ! -s "$KERNELDIR/$srpm" ]; then
+        if $DOWNLOAD; then
+            local location="http://downloads.lustre.org/public/kernels/$target/old"
+            echo "Downloading $location/$srpm..."
+            if ! wget -nv "$location/$srpm" -O "$KERNELDIR/$srpm" 2>&1 ||
+               [ ! -s "$KERNELDIR/$srpm" ]; then
+                rm -f $KERNELDIR/$srpm
+                fatal 1 "Could not download target $target's kernel SRPM $srpm from $location."
+            fi
+        else
+            fatal 1 "$srpm not found in directory $KERNELDIR."
+        fi
+    fi
+
 }
 
 }
 
-build_tarball() {
-    local TARGET=$1
-    local SRPM=$2
-
-    if [ "$TARGET" = "rhel-2.6" -o "$TARGET" = "rhel-2.4" ]; then
-        local SPEC=""
-        if [ "$TARGET" = "rhel-2.6" ]; then
-            SPEC=kernel-2.6.spec
-            OLDCONFIG=nonint_oldconfig
-        elif [ "$TARGET" = "rhel-2.4" ]; then
-            SPEC=kernel-2.4.spec
-            OLDCONFIG=oldconfig
-        fi
-
-        RPMTOPDIR=$(mktemp -d $KERNELDIR/rpm_XXXXXX)
-        mkdir $RPMTOPDIR/BUILD/
-        rpm -ivh $KERNELDIR/$SRPM --define "_topdir $RPMTOPDIR" || \
-            { rm -rf $RPMTOPDIR; fatal 1 "Error installing kernel SRPM."; }
-        $RPMBUILD -bp --nodeps --target i686 $RPMTOPDIR/SPECS/$SPEC --define "_topdir $RPMTOPDIR"
-        pushd $RPMTOPDIR/BUILD/kernel-${lnxmaj}/linux-${lnxmaj} && {
-            make mrproper
-            cp configs/kernel-${lnxmaj}-i686-smp.config .config
-            if ! make $OLDCONFIG > /dev/null; then
-                fatal 1 "error trying to make $OLDCONFIG while building a tarball from SRPM."
+download_file() {
+    local from="$1"
+    local to="$2"
+    local force="$3"
+
+    local file=${from##*/}
+
+    if [ -d $to ]; then
+        to="$to/$file"
+    fi
+
+    local semaphore="$to-downloading"
+
+    is_downloading() {
+        if [ ! -f $semaphore ]; then
+            return 1
+        fi
+
+        # make sure the download has not been aborted
+        local now=$(date +%s)
+        local file_mtime=$(stat -c %Y "$to")
+        local staleness=$((now - file_mtime))
+        # let's assume an active download will write at least once a minute
+        if [ $staleness -gt 60 ]; then
+            return 1
+        fi
+
+        return 0
+    }
+
+    is_downloaded() {
+        # if the semaphore file exists, the file is either still downloading
+        # or a download was aborted and we cannot trust the target file
+        if [ -f $semaphore ]; then
+            return 1
+        fi
+
+        if ! is_downloading && [ -r "$to" ] && [ -s "$to" ]; then
+            return 0
+        fi
+
+        return 1
+    }
+
+    if $force || ! is_downloaded; then
+        if is_downloading; then
+            echo "Somebody else is downloading $from..."
+            while is_downloading; do
+                echo "Waiting for $to to finish downloading"
+                sleep 60
+            done
+            if is_downloaded; then
+                return 0
+            else
+                echo "The download we were waiting for seems to have been aborted"
             fi
             fi
-            make include/linux/version.h 
-            rm -f .config
-            cd ..
-            tar cjf $KERNEL_FILE linux-${lnxmaj}
-        }
-        popd
-        rm -rf $RPMTOPDIR
+
+        fi
+
+        if $DOWNLOAD; then
+            echo "Downloading $from..."
+            # flag others so they don't try to download also
+            push_exit_trap "rm -f $to $semaphore" "download"
+            touch $semaphore
+            if ! wget -nv "$from" -O "$to" || [ ! -s "$to" ]; then
+                # the trap will remove the files via the fatal below
+                fatal 1 "Could not download ${to##*/} from ${from%/*}/."
+            fi
+            rm -f $semaphore
+            delete_exit_trap "download"
+        else
+            fatal 1 "${to##*/} not found in directory ${to%/*}."
+        fi
     fi
     fi
+
+    return 0
+
 }
 
 }
 
-download_and_build_tarball() {
-    local TARGET=$1
-    local KERNEL_FILE=$2
+download_ofed() {
+    local force="${1:-false}"
 
 
-    local SRPM=kernel-${lnxmaj}-${lnxrel}.src.rpm
+    if [ -z "$OFED_VERSION" -o "$OFED_VERSION" = "inkernel" ]; then
+        return 0
+    fi
 
 
-    echo "Downloading http://ftp.lustre.org/kernels/$TARGET/old/$SRPM..."
-    if ! wget -nv "http://ftp.lustre.org/kernels/$TARGET/old/$SRPM" \
-        -O "$KERNELDIR/$SRPM" ; then
-        fatal 1 "Could not download target $TARGET's kernel SRPM $SRPM from ftp.lustre.org."
+    local location="http://www.openfabrics.org/downloads/OFED/ofed-${OFED_VERSION}/"
+
+    if [[ $OFED_VERSION = daily-* ]]; then
+        local Mmv daily
+        OFED_VERSION=${OFED_VERSION/daily-/}
+        Mmv=${OFED_VERSION%%-*}
+        daily=${OFED_VERSION##$Mmv-}
+        location="http://www.openfabrics.org/downloads/OFED/ofed-${Mmv}-daily/"
+        # find the filename for the version for the date specified
+        OFED_VERSION=$(curl -s "$location" | sed -nre "/${daily}-/s/.*href=\"OFED-(${Mmv//./\\.}-${daily}-[0-9]{4,4}).tgz.*$/\1/p" | tail -1)
+        if [ -z "$OFED_VERSION" ]; then
+            fatal 1 "Could not determine the filename of the OFED snapshot for ${daily}"
+        fi
     fi
 
     fi
 
-    build_tarball $TARGET $SRPM
+    local file="OFED-${OFED_VERSION}.tgz"
+    download_file "$location/$file" "$KERNELTREE" "$force"
+
 }
 
 }
 
-load_target()
-{
+load_target() {
+
     EXTRA_VERSION_save="$EXTRA_VERSION"
     EXTRA_VERSION_save="$EXTRA_VERSION"
-    for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches" ; do
+    for patchesdir in "$EXTERNAL_PATCHES" \
+                      "$TOPDIR/lustre/lustre/kernel_patches"; do
         TARGET_FILE="$patchesdir/targets/$TARGET.target"
         [ -r "$TARGET_FILE" ] && break
     done
         TARGET_FILE="$patchesdir/targets/$TARGET.target"
         [ -r "$TARGET_FILE" ] && break
     done
-    [ -r "$TARGET_FILE" ] || \
-        fatal 1 "Target $TARGET was not found."
+    [ -r "$TARGET_FILE" ] || fatal 1 "Target $TARGET was not found."
 
 
-    echo "Loading target config file $TARGET.target..."        
+    echo "Loading target config file $TARGET.target..."
+
+    # if the caller specified an OFED_VERSION it should override whatever
+    # the target file specifies
+    local env_OFED_VERSION="$OFED_VERSION"
 
     . "$TARGET_FILE"
 
 
     . "$TARGET_FILE"
 
-    [ "$KERNEL"  ] || fatal 1 "Target $TARGET did not specify a kernel."
-    [ "$VERSION" ] || fatal 1 "Target $TARGET did not specify a kernel version."
+    if [ -n "$env_OFED_VERSION" ]; then
+        OFED_VERSION="$env_OFED_VERSION"
+    fi
 
 
-    if [ "$KERNELDIR" ] ; then
-        KERNEL_FILE="$KERNELDIR/$KERNEL"
-        if [ ! -r "$KERNELDIR/$KERNEL" ] ; then
-            # see if we have an SRPM we can build a tarball for
-            KERNEL_SRPM=kernel-${lnxmaj}-${lnxrel}.src.rpm
-            if [ -r "$KERNELDIR/$KERNEL_SRPM" ] ; then
-                build_tarball $CANONICAL_TARGET $KERNEL_SRPM
-            else
-                if (( $DOWNLOAD )) ; then
-                    echo "Downloading http://ftp.lustre.org/kernels/$CANONICAL_TARGET/old/$KERNEL..."
-                    if ! wget -nv "http://ftp.lustre.org/kernels/$CANONICAL_TARGET/old/$KERNEL" -O "$KERNELDIR/$KERNEL" ; then
-                        # see if we can do it with an SRPM from the download site
-                        download_and_build_tarball $CANONICAL_TARGET $KERNEL_FILE
-                    fi
-                else
-                    fatal 1 "Target $TARGET's kernel file $KERNEL not found in kernel directory $KERNELDIR."
-                fi
-            fi
-        fi
+    # doesn't make any sense to build OFED for xen domX's
+    if $XEN; then
+        OFED_VERSION=""
+    fi
+
+    # XXX - set_rpm_smp_type is an ugly undeterministic hack.  it needs to
+    #       go away and the target just specify the $RPMSMPTYPE
+    [ -z "$RPMSMPTYPE" ] && set_rpm_smp_type
+
+    # CC might have been overwriten in TARGET_FILE
+    if [[ $CC != ccache\ * ]] && which "$CCACHE" &>/dev/null; then
+        export CCACHE && export CC="ccache $CC"
+    fi
+
+    if [ ! "$KERNELTREE" = "" ] && [ -d "$KERNELTREE" ]; then
+        KERNELDIR="$KERNELTREE/${lnxmaj}"
+        [ -d "$KERNELDIR" ] || mkdir "$KERNELDIR"
     fi
 
     fi
 
-    if [ "$SERIES" ] ; then
-        for series in $SERIES ; do
-            for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches" ; do
+    # verify the series is available
+    if [ "$SERIES" ]; then
+        for series in $SERIES; do
+            for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches"; do
                 [ -r "$patchesdir/series/$series" ] && continue 2
             done
             fatal 1 "Target $TARGET's series $SERIES could not be found.\nSearched:\n\t$EXTERNAL_PATCHES/series\n\t$TOPDIR/lustre/lustre/kernel_patches/series."
         done
     fi
 
                 [ -r "$patchesdir/series/$series" ] && continue 2
             done
             fatal 1 "Target $TARGET's series $SERIES could not be found.\nSearched:\n\t$EXTERNAL_PATCHES/series\n\t$TOPDIR/lustre/lustre/kernel_patches/series."
         done
     fi
 
-    CONFIG_FILE="$TOPDIR/lustre/lustre/kernel_patches/kernel_configs/$CONFIG"
-    [ -r "$CONFIG_FILE" ] || \
-        fatal 1 "Target $TARGET's config file $CONFIG missing from $TOPDIR/lustre/lustre/kernel_patches/kernel_configs/."
+    # set the location of the .config file
+    local XENPOSTFIX=""
+    if $XEN; then
+        XENPOSTFIX="-xen"
+    fi
 
 
-    if [ "$EXTRA_VERSION_save" ] ; then
+    if [ -f $TOPDIR/lustre/lustre/kernel_patches/kernel_configs/kernel-$lnxmaj-$TARGET-$TARGET_ARCH.config ]; then
+        CONFIG_FILE="$TOPDIR/lustre/lustre/kernel_patches/kernel_configs/kernel-$lnxmaj-$TARGET$XENPOSTFIX-$TARGET_ARCH${RPMSMPTYPE:+-}${RPMSMPTYPE}.config"
+    fi
+
+    local lnxrelnew=${lnxrel//-/_}
+
+    # remember the EXTRA_VERSION before we diddle it here
+    # XXX - we really should not diddle with any values read in from the
+    #       target file.  if we want to modify a value, we should create
+    #       a new variable.
+    PRISTINE_EXTRA_VERSION=$EXTRA_VERSION
+
+    if ! $PATCHLESS && [ ! -f "$CONFIG_FILE" ]; then
+        fatal 1 "Config file for target $TARGET missing from $TOPDIR/lustre/lustre/kernel_patches/kernel_configs/."
+    fi
+
+    if [ "$EXTRA_VERSION_save" ]; then
         EXTRA_VERSION="$EXTRA_VERSION_save"
         EXTRA_VERSION="$EXTRA_VERSION_save"
-    elif ! (( $RELEASE )) ; then
-        #remove the @VERSION@ (lustre version)
-        EXTRA_VERSION=$(echo $EXTRA_VERSION | sed -e "s/\(.*_lustre\)\..*/\1/")
-        EXTRA_VERSION="${EXTRA_VERSION}-${TAG}.${TIMESTAMP}"
+    elif ! $RELEASE; then
+        # if there is no patch series, then this is not a lustre specific
+        # kernel.  don't make it look like one
+        if $PATCHLESS || [ -n "$SERIES" ]; then
+            EXTRA_VERSION=$(echo $EXTRA_VERSION | sed -e "s/\(.*_lustre\)\..*/\1/")
+#            EXTRA_VERSION="${EXTRA_VERSION}-${TAG}.${TIMESTAMP}"
+            if ! $PATCHLESS && [ -n "$BUILDID" ]; then
+                EXTRA_VERSION="${EXTRA_VERSION}.${BUILDID}"
+            fi
+        fi
     fi
     # EXTRA_VERSION=${EXTRA_VERSION//-/_}
 
     ALL_ARCHS="$BASE_ARCHS $BIGMEM_ARCHS $BOOT_ARCHS $JENSEN_ARCHS $SMP_ARCHS $BIGSMP_ARCHS $PSERIES64_ARCHS $UP_ARCHS"
 
     BUILD_ARCHS=
     fi
     # EXTRA_VERSION=${EXTRA_VERSION//-/_}
 
     ALL_ARCHS="$BASE_ARCHS $BIGMEM_ARCHS $BOOT_ARCHS $JENSEN_ARCHS $SMP_ARCHS $BIGSMP_ARCHS $PSERIES64_ARCHS $UP_ARCHS"
 
     BUILD_ARCHS=
-    for arch in $(uniqify "$ALL_ARCHS") ; do
-        if [ -z "$TARGET_ARCHS" ] || echo "$TARGET_ARCHS" | grep "$arch" >/dev/null 2>/dev/null ; then
+    for arch in $(uniqify "$ALL_ARCHS"); do
+        if [ -z "$TARGET_ARCHS" ] ||
+           [[ \ $TARGET_ARCHS\  = *\ $arch\ * ]]; then
             BUILD_ARCHS="$BUILD_ARCHS $arch"
         fi
     done
             BUILD_ARCHS="$BUILD_ARCHS $arch"
         fi
     done
@@ -359,9 +656,10 @@ load_target()
     echo "Building for: $BUILD_ARCHS"
 }
 
     echo "Building for: $BUILD_ARCHS"
 }
 
-tarflags()
-{
-    case "$1" in
+tarflags() {
+    local file="$1"
+
+    case "$file" in
         '')
             fatal 1 "tarflags(): File name argument missing."
             ;;
         '')
             fatal 1 "tarflags(): File name argument missing."
             ;;
@@ -378,26 +676,38 @@ tarflags()
             fatal 1 "tarflags(): Unrecognized tar extension in file: $1"
             ;;
     esac
             fatal 1 "tarflags(): Unrecognized tar extension in file: $1"
             ;;
     esac
+
 }
 
 }
 
-untar()
-{
-    echo "Untarring ${1##*/}..."
-    tar $(tarflags "$1") "$1"
+untar() {
+    local tarfile="$1"
+    shift
+    local extractfile="$@"
+
+    echo "Untarring ${tarfile##*/}..."
+    tar $(tarflags "$tarfile") "$tarfile" $extractfile
+
 }
 
 }
 
-unpack_lustre()
-{
-    DIRNAME="lustre-$TAG-$TIMESTAMP"
-    if [ "$LUSTRE" ] ; then
-        untar "$LUSTRE"
-        [ -d lustre ] || ln -sf lustre* lustre
-    else
-        if [ "$USE_DATESTAMP" ]; then
+unpack_ofed() {
+
+    if ! untar "$KERNELTREE/OFED-${OFED_VERSION}.tgz"; then
+        return 1
+    fi
+    [ -d OFED ] || ln -sf OFED-[0-9].[0-9]* OFED
+
+}
+
+unpack_lustre() {
+
+    if [ -z "$LUSTRE" ]; then
+        local DATESTAMP=""
+
+        if [ -n "$USE_DATESTAMP" ]; then
             DATESTAMP="-D '$DATE'"
             DATESTAMP="-D '$DATE'"
-        else
-            DATESTAMP=""
-        fi            
+        fi
+
+        local DIRNAME="lustre-$TAG-$TIMESTAMP"
 
         cvs -d "$CVSROOT" -qz3 co $DATESTAMP -d "$DIRNAME" lustre || \
             fatal 1 "There was an error checking out toplevel Lustre from CVS."
 
         cvs -d "$CVSROOT" -qz3 co $DATESTAMP -d "$DIRNAME" lustre || \
             fatal 1 "There was an error checking out toplevel Lustre from CVS."
@@ -406,209 +716,961 @@ unpack_lustre()
             fatal 1 "There was an error checking out Lustre/Portals/Build from CVS."
         echo "Creating lustre tarball..."
         sh autogen.sh || fatal 1 "There was an error running autogen.sh."
             fatal 1 "There was an error checking out Lustre/Portals/Build from CVS."
         echo "Creating lustre tarball..."
         sh autogen.sh || fatal 1 "There was an error running autogen.sh."
-        ./configure --disable-{modules,utils,liblustre,tests,doc} || \
+        ./configure --enable-dist || \
             fatal 1 "There was an error running ./configure to create makefiles."
         make dist || fatal 1 "There was an error running 'make dist'."
             fatal 1 "There was an error running ./configure to create makefiles."
         make dist || fatal 1 "There was an error running 'make dist'."
+        LUSTRE=$PWD/lustre-*.tar.gz
         popd > /dev/null
         popd > /dev/null
-        fname=`basename $DIRNAME/lustre-*.tar.gz`
-        cp $DIRNAME/$fname . || fatal 1 "There was an error copying lustre tarball."
-        LUSTRE="$PWD/$fname"
-        ln -sf "$DIRNAME" lustre
     fi
     fi
-}
 
 
-unpack_linux()
-{
-    untar "$KERNEL_FILE"
-    [ -d linux ] || ln -sf linux* linux
+    untar "$LUSTRE" || fatal 1 "Error unpacking Lustre tarball"
+    [ -d lustre ] || ln -sf lustre-[0-9].[0-9]* lustre
+
 }
 
 }
 
-patch_linux()
-{
-    [ "$SERIES" ] || return 0
+do_patch_linux() {
+
+    local do_patch=${1:-true}
+
     FULL_PATCH="$PWD/lustre-kernel-${TARGET}-${EXTRA_VERSION}.patch"
     [ -f "$FULL_PATCH" ] && rm -f "$FULL_PATCH"
     FULL_PATCH="$PWD/lustre-kernel-${TARGET}-${EXTRA_VERSION}.patch"
     [ -f "$FULL_PATCH" ] && rm -f "$FULL_PATCH"
-    pushd linux >/dev/null
-    for series in $SERIES ; do
+    $do_patch && pushd linux >/dev/null
+    for series in $SERIES; do
         echo -n "Applying series $series:"
         echo -n "Applying series $series:"
-        for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches" ; do
+        for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches"; do
             [ -r "$patchesdir/series/$series" ] || continue
             SERIES_FILE="$patchesdir/series/$series"
             [ -r "$patchesdir/series/$series" ] || continue
             SERIES_FILE="$patchesdir/series/$series"
-            for patch in $(<"$SERIES_FILE") ; do
+            for patch in $(<"$SERIES_FILE"); do
                 echo -n " $patch"
                 PATCH_FILE="$patchesdir/patches/$patch"
                 [ -r "$PATCH_FILE" ] || \
                     fatal 1 "Patch $patch does not exist in Lustre tree."
                 echo -n " $patch"
                 PATCH_FILE="$patchesdir/patches/$patch"
                 [ -r "$PATCH_FILE" ] || \
                     fatal 1 "Patch $patch does not exist in Lustre tree."
-                cat "$PATCH_FILE" >> "$FULL_PATCH" || \
+                cat "$PATCH_FILE" >> "$FULL_PATCH" || {
+                    rm -f $FULL_PATCH
                     fatal 1 "Error adding patch $patch to full patch."
                     fatal 1 "Error adding patch $patch to full patch."
-                patch -s -p1 < "$PATCH_FILE" || fatal 1 "Error applying patch $patch."
+                }
+                if $do_patch; then
+                    patch -s -p1 < "$PATCH_FILE" 2>&1 || {
+                        rm -f $FULL_PATCH
+                        fatal 1 "Error applying patch $patch."
+                    }
+                fi
             done
             break
         done
         echo
     done
             done
             break
         done
         echo
     done
-    popd >/dev/null
+    $do_patch && popd >/dev/null
     echo "Full patch has been saved in ${FULL_PATCH##*/}."
     echo "Full patch has been saved in ${FULL_PATCH##*/}."
-    echo "Replacing .config files..."
-    [ -d linux/configs ] || mkdir linux/configs || \
-        fatal 1 "Error creating configs directory."
-    rm -f linux/configs/*
-    copysuccess=0
-    for patchesdir in "$EXTERNAL_PATCHES" "lustre/lustre/kernel_patches" ; do
-        [ "$patchesdir" ] && \
-            cp -v $patchesdir/kernel_configs/kernel-${VERSION}-${TARGET}*.config linux/configs/ >/dev/null && copysuccess=1
-    done
-    [ "$copysuccess" = "1" ] || \
-        fatal 1 "Error copying in kernel configs."
-}
-
-pack_linux()
-{
-    TARBALL="$(readlink linux)-$EXTRA_VERSION.tar.gz"
-    echo "Creating patched linux tarball $TARBALL..."
-    tar zcf "$TARBALL" "$(readlink linux)" \
-        --exclude "CVS" --exclude ".cvsignore" || \
-        --exclude "*.orig" --exclude "*~" --exclude "*.rej" || \
-        fatal 1 "Error creating patched Linux tarball."
-}
-
-clean_linux()
-{
-    [ -d linux ] || return 0
-    echo "Cleaning linux..."
-    [ -L linux ] && rm -rf $(readlink linux)
-    rm -rf linux
-}
-
-prep_kernel_build()
-{
-    # make .spec file
-    ENABLE_INIT_SCRIPTS=""
-    sed \
-        -e "s^@BASE_ARCHS@^$BASE_ARCHS^g" \
-        -e "s^@BIGMEM_ARCHS@^$BIGMEM_ARCHS^g" \
-        -e "s^@BIGSMP_ARCHS@^$BIGSMP_ARCHS^g" \
-        -e "s^@BOOT_ARCHS@^$BOOT_ARCHS^g" \
-        -e "s^@CONFIGURE_FLAGS@^$CONFIGURE_FLAGS^g" \
-        -e "s^@ENABLE_INIT_SCRIPTS@^$ENABLE_INIT_SCRIPTS^g" \
-        -e "s^@JENSEN_ARCHS@^$BOOT_ARCHS^g" \
-        -e "s^@KERNEL_EXTRA_VERSION@^$EXTRA_VERSION^g" \
-        -e "s^@KERNEL_RELEASE@^${EXTRA_VERSION//-/_}^g" \
-        -e "s^@KERNEL_SOURCE@^$KERNEL^g" \
-        -e "s^@KERNEL_VERSION@^$VERSION^g" \
-        -e "s^@LINUX26@^$LINUX26^g" \
-        -e "s^@LUSTRE_SOURCE@^${LUSTRE##*/}^g" \
-        -e "s^@LUSTRE_TARGET@^$TARGET^g" \
-        -e "s^@PSERIES64_ARCHS@^$PSERIES64_ARCHS^g" \
-        -e "s^@RHBUILD@^$RHBUILD^g" \
-        -e "s^@SMP_ARCHS@^$SMP_ARCHS^g" \
-        -e "s^@SUSEBUILD@^$SUSEBUILD^g" \
-        -e "s^@SUSEBUILD@^$SUSEBUILD^g" \
-        -e "s^@UP_ARCHS@^$UP_ARCHS^g" \
-        < $TOPDIR/lustre/build/lustre-kernel-2.4.spec.in \
-        > lustre-kernel-2.4.spec
-    [ -d SRPMS ] || mkdir SRPMS
-    [ -d RPMS ] || mkdir RPMS
-    [ -d BUILD ] || mkdir BUILD
-    [ -d SOURCES ] || mkdir SOURCES
-    for script in linux-{rhconfig.h,merge-config.awk,merge-modules.awk} \
-        suse-{functions.sh,post.sh,postun.sh,trigger-script.sh.in} \
-        sles8-{pre,post,postun,update_{INITRD_MODULES,rcfile_setting}}.sh ; do
-        cp $TOPDIR/lustre/build/$script SOURCES
-    done
-    cp "$LUSTRE" "$KERNEL_FILE" SOURCES
-    if [ "$EXTERNAL_PATCHES" -a -d "$EXTERNAL_PATCHES" ] ; then
-        tar zcf SOURCES/external-patches.tar.gz -C "$EXTERNAL_PATCHES" series targets patches kernel_configs
-    else
-        touch SOURCES/external-patches.tar.gz
-    fi
-}
 
 
-clean_lustre()
-{
-    [ -d lustre ] || return 0
-    echo "Cleaning Lustre..."
-    [ -L lustre ] && rm -rf $(readlink lustre)
-    rm -rf lustre
 }
 
 }
 
-build_kernel()
-{
-    echo "Building kernel + Lustre RPMs for: $BUILD_ARCHS..."
-    targets=
-    for arch in $BUILD_ARCHS ; do
+build_lustre() {
+    local linux="$1"
+    local linuxobj="$2"
+
+    cp "$LUSTRE" SOURCES
+
+    pushd lustre >/dev/null
+
+    echo "Building Lustre RPMs for: $BUILD_ARCHS..."
+    local targets arch
+    for arch in $BUILD_ARCHS; do
         targets="--target $arch $targets"
     done
 
         targets="--target $arch $targets"
     done
 
-    $RPMBUILD $targets -bb lustre-kernel-2.4.spec \
-        --define "_topdir $TOPDIR" || \
-        fatal 1 "Error building rpms for $BUILD_ARCHS."
+    local confoptions=""
 
 
-    if (( $DO_SRC )) ; then
-        $RPMBUILD -bs lustre-kernel-2.4.spec \
-            --define "_topdir $TOPDIR" || \
-            fatal 1 "Error building .src.rpm."
+    if $PATCHLESS; then
+        confoptions="$confoptions --disable-server"
     fi
     fi
-}
 
 
-build_lustre()
-{
-    [ -d SRPMS ] || mkdir SRPMS
-    [ -d RPMS ] || mkdir RPMS
-    [ -d BUILD ] || mkdir BUILD
-    [ -d SOURCES ] || mkdir SOURCES
+    local rpmbuildopt='-tb'
+    if $NORPM; then
+        rpmbuildopt='-tc'
+        echo NORPM mode. Only compiling.
+    fi
 
 
-    cp "$LUSTRE" SOURCES
+    ( $(skeep_ldiskfs_rpm $TAG) ) || {
 
 
-    pushd lustre >/dev/null
+        pushd ldiskfs > /dev/null || return 255
 
 
-    echo "Building Lustre RPMs for: $BUILD_ARCHS..."
-    targets=
-    for arch in $BUILD_ARCHS ; do
-        targets="--target $arch $targets"
-    done
+        if !  ./configure --enable-dist; then
+            echo "failed to configure in ldiskfs"
+            popd >/dev/null # pushd ldiskfs
+            popd >/dev/null # pushd lustre
+            return 255
+        fi
+
+        if ! make dist 2>&1; then
+            popd >/dev/null # pushd ldiskfs
+            popd >/dev/null # pushd lustre
+            return 255
+        fi
 
 
-    ./configure "--with-linux=${LINUX}" ${CONFIGURE_FLAGS}
+        #cp lustre-ldiskfs*.tar.gz $TOPDIR/SOURCES || \
+        #    fatal 1 "Could not copy lustre-ldiskfs*.tar.gz to $TOPDIR/SOURCES"
+
+        if ! $RPMBUILD $targets $rpmbuildopt lustre-ldiskfs*.tar.gz \
+            --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
+            --define "kdir $linux" \
+            ${linuxobj:+--define "kobjdir $linuxobj"} \
+            --define "_tmppath /var/tmp" \
+            --define "_topdir $TOPDIR" 2>&1; then
+            popd >/dev/null # pushd ldiskfs
+            popd >/dev/null # pushd lustre
+            return 255
+        fi
 
 
-    $RPMBUILD $targets -bb build/lustre.spec \
-        --define "_topdir $TOPDIR" || \
+        if $DO_SRC; then
+            if ! $RPMBUILD -ts lustre-ldiskfs*.tar.gz \
+                --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
+                --define "kdir $linux" \
+                ${linuxobj:+--define "kobjdir $linuxobj"} \
+                --define "_tmppath /var/tmp" \
+                --define "_topdir $TOPDIR" 2>&1; then
+                popd >/dev/null # pushd ldiskfs
+                popd >/dev/null # pushd lustre
+                return 255
+            fi
+        fi
+        popd >/dev/null # pushd ldiskfs
+
+        # tell lustre where ldiskfs is
+        # XXX - pointing to the RPM BUILD dir is a hack.  we need to flesh
+        #       out the ldiskfs RPM build so that it builds a
+        #       lustre-ldiskfs-devel RPM and install that and point lustre
+        #       to that instead
+        confoptions="$confoptions --with-ldiskfs=$(ls -d $TOPDIR/BUILD/lustre-ldiskfs-*)"
+    }
+
+    # convert the $PATCHLESS boolean to an empty/not-empty boolean
+    # as silly as this seems, it makes the syntax of the rpmbuild command
+    # simpler and not need an eval to deal with the quotes in the quotes
+    local is_patchless=""
+    if $PATCHLESS; then
+        is_patchless="yes"
+    fi
+
+    # ditto for the lustre-tests boolean
+    local lustre_tests=""
+    if ! $LUSTRE_TESTS; then
+        lustre_tests="no"
+    fi
+
+    $RPMBUILD $targets $rpmbuildopt "$LUSTRE" \
+        ${is_patchless:+--define "lustre_name lustre-client"} \
+        ${lustre_tests:+--define "build_lustre_tests 0"} \
+        ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
+        --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
+        --define "kdir $linux" \
+        ${linuxobj:+--define "kobjdir $linuxobj"} \
+        --define "_tmppath $TMPDIR" \
+        --define "_topdir $TOPDIR" 2>&1 || \
         fatal 1 "Error building rpms for $BUILD_ARCHS."
 
     popd >/dev/null
         fatal 1 "Error building rpms for $BUILD_ARCHS."
 
     popd >/dev/null
+
 }
 
 }
 
-stage()
-{
+stage() {
+
     [ "$STAGEDIR" ] || return 0
 
     [ "$STAGEDIR" ] || return 0
 
-    for arch in $BUILD_ARCHS ; do
+    for arch in $BUILD_ARCHS; do
         rpmdir="${STAGEDIR}/${CANONICAL_TARGET}-${arch}"
         echo "${0##*/}: Copying RPMs into ${rpmdir}"
         mkdir -p "${rpmdir}"
         cp -v RPMS/${arch}/*.rpm "${rpmdir}"
         rpmdir="${STAGEDIR}/${CANONICAL_TARGET}-${arch}"
         echo "${0##*/}: Copying RPMs into ${rpmdir}"
         mkdir -p "${rpmdir}"
         cp -v RPMS/${arch}/*.rpm "${rpmdir}"
-        if [ -d RPMS/noarch ] ; then
+        if [ -d RPMS/noarch ]; then
             cp -v RPMS/noarch/*.rpm "${rpmdir}"
         fi
     done
 
     cp -v "$LUSTRE" "$STAGEDIR"
             cp -v RPMS/noarch/*.rpm "${rpmdir}"
         fi
     done
 
     cp -v "$LUSTRE" "$STAGEDIR"
+
+}
+
+#check if we need to build separate ldiskfs RPM
+skeep_ldiskfs_rpm() {
+    local tag="$1"
+
+    local skip=false
+
+    if ! $LDISKFSRPM; then
+        skip=true
+    elif $PATCHLESS; then
+        skip=true
+    else
+        for skiptag in $SKIPLDISKFSRPM; do
+            [[ $tag == $skiptag ]] && skip=true && break
+        done
+    fi
+
+    echo $skip
+
+}
+
+set_rpm_smp_type() {
+
+    local infact_arch="${TARGET_ARCH}"
+
+    RPMSMPTYPE=""
+    [ "$infact_arch" == "i586" ] && infact_arch="i686"
+
+    local smp_type
+    for smp_type in $SMP_ARCHS; do
+        [ $infact_arch == $smp_type ] && RPMSMPTYPE=smp && break
+    done
+
+    for smp_type in $BIGSMP_ARCHS; do
+        [ $infact_arch == $smp_type ] && RPMSMPTYPE=bigsmp && break
+    done
+
+    for smp_type in $PPC64_ARCHS; do
+        [ $infact_arch == $smp_type ] && RPMSMPTYPE=ppc64 && break
+    done
+
+    for smp_type in $DEFAULT_ARCHS; do
+        [ $infact_arch == $smp_type ] && RPMSMPTYPE=default && break
+    done
+
+}
+
+# This function takes a linux source pool and digs out the linux release
+# from it
+find_linux_release() {
+    local SRCDIR="$1"
+
+    local LINUXRELEASEHEADER=$SRCDIR/include/linux/version.h
+    if [ -s $SRCDIR/include/linux/utsrelease.h ]; then
+        LINUXRELEASEHEADER=$SRCDIR/include/linux/utsrelease.h
+    fi
+
+    sed -ne 's/#define UTS_RELEASE "\(.*\)"$/\1/p' $LINUXRELEASEHEADER
+
+}
+
+# XXX this needs to be re-written as a wrapper around find_rpm
+#     or just gotten rid of.  :-)
+find_linux_rpm() {
+    local prefix="$1"
+
+    local pathtorpms="${KERNELRPMSBASE}/${lnxmaj}/${DISTRO}"
+    [ -d $pathtorpms ] || return 255
+
+    local kernelbinaryrpm rpmfile
+    local wanted_kernel="${lnxmaj}${lnxmin}-${lnxrel}"
+
+    local arch ret=1
+    for arch in $TARGET_ARCHS_ALL; do
+        local found_rpm="" rpm
+        for rpm in ${pathtorpms}/${arch}/*.rpm; do
+            if rpm -q --provides -p "$rpm" 2>&3 | grep -q "kernel${prefix} = $wanted_kernel" 2>&3; then
+
+                found_rpm="$rpm"
+                ret=0
+                break
+            fi
+        done
+        [ -f "$found_rpm" ] && break
+    done
+
+    echo "$found_rpm"
+    return $ret
+
+}
+
+# unpack kernel(/source/devel) RPM
+#
+# This function and it's setting of $LINUX and $LINUXOBJ is a total hack that
+# needs to completely refactored.  It completely ingores that $BUILD_ARCHS may
+# contain a list of arches for which rpmbuild commands (including the one for
+# lustre itself)
+unpack_linux_devel_rpm() {
+    local kernelrpm="${1}"
+
+    [ -f "$kernelrpm" ] || return 255
+    [ -d $TOPDIR/reused ] || mkdir $TOPDIR/reused || return 255
+
+    pushd $TOPDIR/reused &>/dev/null || return 255
+
+    if ! rpm2cpio < "$kernelrpm" | cpio -id > /dev/null 2>&1; then
+        return 255
+    fi
+
+    # call a distro specific hook, if available
+    if type -p unpack_linux_devel_rpm-$DISTRO; then
+        if ! unpack_linux_devel_rpm-$DISTRO "$kernelrpm"; then
+            return 255
+        fi
+    fi
+
+    popd &>/dev/null
+
+    find_linux_devel_paths $TOPDIR/reused
+
+    return 0
+
+}
+
+build_kernel_ib() {
+    local linux="$1"
+
+    # build kernel-ib{,-devel}
+    local K_SRC="K_SRC"
+    # ofed 1.3 had a bug in the rpm spec
+    if [ "$OFED_VERSION" = "1.3" ]; then
+        K_SRC="KSRC"
+    fi
+
+    local OFED_CORE="--with-core-mod --with-ipoib-mod --with-sdp-mod --with-user_mad-mod --with-user_access-mod --with-addr_trans-mod --with-rds-mod --with-qlgc_vnic-mod --with-madeye-mod"
+    local OFED_HARDWARE="--with-mthca-mod --with-mlx4-mod --with-mlx4_en-mod --with-cxgb3-mod --with-nes-mod"
+    # some I/B drivers are architecture dependent and kernel-ib's configure
+    # does not figure it out for us ~sigh~
+    case "$TARGET_ARCH" in
+        ppc64)
+            OFED_HARDWARE="$OFED_HARDWARE --with-ehca-mod"
+            ;;
+    esac
+    # we're no longer shipping the OFED iSCSI
+    #OFED_ISCSI="--with-srp-mod --with-srp-target-mod"
+    ## ISER module has no backport support as of OFED 1.5 (i.e. only builds on
+    ##kernels >= 2.6.30)
+    #if [[ $OFED_VERSION = 1.[0-4]* ]]; then
+    #   OFED_ISCSI="$OFED_ISCSI --with-iser-mod"
+    #fi
+
+    # assume we are just rebuilding the SRPM
+    local BUILD_TYPE=${BUILD_TYPE:-"--rebuild"}
+    local SOURCE="${TOPDIR}/OFED/SRPMS/ofa_kernel-*.src.rpm"
+
+    # but switch to building from the SPEC if we need to apply patches
+    if ls ${TOPDIR}/lustre/build/patches/ofed/* >/dev/null; then
+        BUILD_TYPE="-bb"
+        rpm --define "_topdir ${TOPDIR}" -ivh $SOURCE
+        SOURCE="${TOPDIR}/SPECS/ofa_kernel.spec"
+        local file ed_fragment1 ed_fragment2 n=1
+        for file in $(ls ${TOPDIR}/lustre/build/patches/ofed/*); do
+            ed_fragment1="$ed_fragment1
+Patch$n: ${file%%*/}"
+            ed_fragment2="$ed_fragment2
+%patch$n -p0"
+            cp $file ${TOPDIR}/SOURCES
+            let n=$n+1
+        done
+
+        if [ $n -gt 1 ]; then
+            ed $SOURCE <<EOF
+/^Source: /a
+$ed_fragment1
+.
+/^%setup /a
+$ed_fragment2
+.
+wq
+EOF
+        fi
+    fi
+
+    local linuxrelease=$(find_linux_release "$linux")
+    if ! $RPMBUILD $BUILD_TYPE --define 'build_kernel_ib 1' --define 'build_kernel_ib_devel 1' \
+                  ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
+                  --define "_topdir ${TOPDIR}" --target ${TARGET_ARCH} \
+                  --define "KVERSION ${linuxrelease}" \
+                  --define "$K_SRC ${linux}" \
+                  --define "LIB_MOD_DIR /lib/modules/${linuxrelease}/updates" \
+                  ${OFA_KERNEL_RELEASE:+--define "_release $OFA_KERNEL_RELEASE"} \
+                  --define "configure_options --without-quilt $OFED_CORE $OFED_HARDWARE $OFED_ISCSI" \
+                  ${SOURCE} 2>&1; then
+        fatal 1 "Error building kernel-ib"
+    fi
+
+}
+
+store_for_reuse() {
+        local articles="$1"
+        local module="$2"
+        local location="$3"
+        local signature="$4"
+        local use_links="$5"
+
+        local linkflag=""
+        if $use_links; then
+            linkflag="l"
+        fi
+
+        location="$location"/"$signature"/"$module"
+        mkdir -p "$location"
+        # the cleanup script removes any directory that doesn't have a
+        # .lastused, so let's try to prevent that as soon as we can
+        # this solution still slightly racy with the cleanup script
+        # but the race is a lot tighter now
+        touch -t 197001010000 "$location/.lastused"
+        ## use eval/echo here to make sure shell expansions are performed
+        #if ! cp -a${linkflag} $(eval echo $articles) "$location"; then
+        local article
+        for article in $(eval echo $articles); do
+            if ! cp -a${linkflag} "$article" "$location"; then
+                error "Failed to copy \"$article\" to \"$location\" in store_for_reuse()"
+                # rename the cache location so that it's not cached
+                # product, but is around for analysis
+                mv "$location"{,-bad-$(date +%s)} ||
+                    error "failed to clean up a failed cache attempt" \
+                          "in \"$location\" -- manual cleanup will be" \
+                          "necessary"
+                return 1
+            fi
+        done
+
+        # flag the cache as complete (i.e. in case lbuild was previously
+        # interrupted while caching)
+        touch "$location/.lastused"
+
+        return 0
+
+}
+
+reuse() {
+    local module="$1"
+    local dest="$2"
+    local use_links="${3:-false}"
+    local signature="$4"
+
+    if [ -n "$REUSEBUILD" ] && [ -d "$REUSEBUILD/$signature/$module" ]; then
+        if [ ! -f "$REUSEBUILD/$signature/$module/.lastused" ]; then
+            # the .lastused flag is populated at the end of the caching to
+            # signal that the caching was completed.  if that flag is not
+            # there, then the cache is invalid (and should be removed in fact)
+            mv "$REUSEBUILD/$signature/$module"{,-bad-$(date +%s)} ||
+                fatal 1 "failed to clean up a bad cache in location $REUSEBUILD/$signature/$module\" -- manual cleanup will be necessary"
+            return 1
+        fi
+
+        # so that we know how stale this entry is
+        touch $REUSEBUILD/$signature/$module/.lastused
+
+        if $use_links; then
+            if ls $REUSEBUILD/$signature/$module/* >/dev/null 2>&1; then
+                cp -al $REUSEBUILD/$signature/$module/* $dest/
+            fi
+        else
+            # copying is pretty heavy
+            # cp -a $REUSEBUILD/$signature/$module/* $dest/
+            # do some creative symlinking instead
+            local dir
+            for dir in BUILD SRPMS SPECS; do
+                if ls $REUSEBUILD/$signature/$module/$dir/* >/dev/null 2>&1; then
+                    ln -s $REUSEBUILD/$signature/$module/$dir/* $dest/$dir
+                fi
+            done
+            # sources have to be copied by file because we need SOURCES to
+            # be a dir we can write into
+# could overrun ls's arg list here
+            #ls $REUSEBUILD/$signature/$module/SOURCES/* |
+            find $REUSEBUILD/$signature/$module/SOURCES/ -type f |
+                xargs ln -t $dest/SOURCES -s
+
+            # same for RPMS/* dirs
+# could overrun ls's arg list here
+            #ls $REUSEBUILD/$signature/$module/RPMS/$TARGET_ARCH/* |
+            local dir
+            for dir in $REUSEBUILD/$signature/$module/RPMS/*; do
+                mkdir -p $dest/RPMS/${dir##*/}
+                find $dir -type f |
+                  xargs ln -t $dest/RPMS/${dir##*/} -s
+            done
+        fi
+        return 0
+    else
+        return 1
+    fi
+}
+
+basearch() {
+    local arch="$1"
+
+    if [[ $arch = i[3456]86 ]]; then
+        echo "i386"
+    else
+        echo "$arch"
+    fi
+
+}
+
+#
+# in a given directory, find the first rpm matching given requirements
+#
+find_rpm() {
+    local dir="$1"
+    local match_type="$2"
+    local match="$3"
+
+    pushd "$dir" > /dev/null || \
+        fatal 1 "Unable to chdir to directory \"$dir\" in find_rpm()"
+
+    local file
+    for file in $(ls *.rpm); do
+        if [ ! -f "$file" ]; then
+            continue
+        fi
+        case "$match_type" in
+            provides)
+                # match is any valid ERE (i.e. given to egrep) match
+                if rpm -q --provides -p "$file" 2>&3 | egrep -q "$match"; then
+                    echo "$file"
+                    popd >/dev/null
+                    return 0
+                fi
+                ;;
+            *)
+                popd >/dev/null
+                fatal 1 "Unknown match type \"$match_type\" given to find_rpm()"
+                ;;
+        esac
+    done
+
+    popd >/dev/null
+    return 1
+}
+
+build_kernel_with_srpm() {
+    local outfd=$1
+
+    if [ -z "$outfd" ] || [ $outfd = 1 ]; then
+        fatal 1 "You must supply a file descriptor to ${FUNCNAME[0]} and it cannot be 1"
+    fi
+
+    # need to generate the patch for this target
+    do_patch_linux false >&${outfd}    # sets global $FULL_PATCH (yeah, yuck)
+
+    # get an md5sum of the kernel patch + config for reuse check
+    # XXX really, there needs to be a signature and a CONFIG_FILE per arch
+    #     in BUILD_ARCHS
+    local release_str
+    if $RELEASE; then
+        local release_str="RELEASE=$RELEASE\n"
+    fi
+
+    if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
+        local REUSE_SIGNATURE=$({ echo -en $release_str;
+                                  echo $BUILD_GEN;
+                                  cat $CONFIG_FILE $TARGET_FILE $FULL_PATCH; } |
+                                md5sum | cut -d" " -f1)
+        # see if we can link to the reuse pool
+        # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
+        #       "library"
+        local CAN_LINK_FOR_REUSE=false
+        touch $REUSEBUILD/$$
+        if cp -al $REUSEBUILD/$$ $TOPDIR/ 2>/dev/null; then
+            CAN_LINK_FOR_REUSE=true
+        fi
+        rm $REUSEBUILD/$$
+    fi
+
+    # the extra version string to use for the kernel (which might be a reused
+    # kernel, remember)
+    local kernel_extra_version=""
+    if ! $USE_BUILD_CACHE || ! reuse kernel "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
+                                   "$REUSE_SIGNATURE"; then
+        # nothing cached, build from scratch
+        if [ ! -r "$KERNELDIR/$KERNEL_SRPM" ]; then
+            echo "Downloading kernel SRPM"
+            download_srpm "$CANONICAL_TARGET" "$KERNEL_SRPM" >&${outfd}
+        fi
+
+        if ! rpm -ivh $KERNELDIR/$KERNEL_SRPM \
+                  --define "_topdir $TOPDIR" >&${outfd} 2>&1; then
+            # should we clean this up or leave it for analysis?
+            #rm -rf $RPMTOPDIR
+            fatal 1 "Error installing kernel SRPM."
+        fi
+
+        # put the Lustre kernel patch into the RPM build tree
+        cp $FULL_PATCH $TOPDIR/SOURCES/linux-${lnxmaj}-lustre.patch
+        prepare_and_build_srpm >&${outfd} ||
+            fatal 1 "failed to prepare_and_build_srpm"
+
+        if [ -z "$REUSE_SIGNATURE" ]; then
+            echo "No reuse signature was caculated so not storing the built kernel" >&${outfd}
+        else
+            # store the resulting kernel RPM build tree for future use
+            echo "Storing the built kernel for future reuse" >&${outfd}
+            if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,BUILD,SRPMS,RPMS}" \
+                                 "kernel" "$REUSEBUILD" "$REUSE_SIGNATURE" \
+                                 "$CAN_LINK_FOR_REUSE"; then
+                error "Failed to store kernel RPMS for reuse"
+                echo "unknown"
+                return 1
+            fi
+        fi
+    fi  # build reuse
+
+    # figure out the EXTRA_VERSION of the kernel we built or are re-using
+    local KERNEL_RPM
+    if ! KERNEL_RPM=$(find_rpm "$TOPDIR/RPMS/$TARGET_ARCH/" provides "^kernel ="); then
+        fatal 1 "Failed to find a kernel RPM in $TOPDIR/RPMS/$TARGET_ARCH/"
+    fi
+    kernel_extra_version=$(rpm -q --queryformat "%{RELEASE}" -p $TOPDIR/RPMS/$TARGET_ARCH/$KERNEL_RPM)
+
+    # should now have the following RPMs
+    # $TOPDIR/RPMS/$arch/kernel-lustre-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
+    # $TOPDIR/RPMS/$arch/kernel-lustre-devel-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
+    # $TOPDIR/RPMS/$arch/kernel-lustre-headers-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
+    # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-common-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
+    # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
+
+    echo $kernel_extra_version
+    return 0
+
 }
 
 }
 
+# build OFED
+# globals used:
+#    TOPDIR
+#    REUSEBUILD, USE_BUILD_CACHE
+#    CONFIGURE_FLAGS
+
+build_ofed() {
+    local linux="$1"
+    local ofed_version="$2"
+
+    # if an ofed version is given, then it means use OFED proper,
+    # not any vendor specific "inkernel" version
+    if [ -z "$ofed_version" ]; then
+        return 0
+    fi
+
+    if [ "$ofed_version" = "inkernel" ]; then
+        # see if there is a distro specific override for this and use
+        # that if it exists
+        # XXX we need to better integrate a distro specific override with
+        #     the rest of this function so that all of the reuse cache
+        #     stuff is leveraged given that 80% of this function is reuse
+        if type -p build_ofed-${DISTRO}; then
+            local ofed_location
+            ofed_location=$(build_ofed-${DISTRO} ${STDOUT})
+            local rc=${PIPESTATUS[0]}
+            CONFIGURE_FLAGS="--with-o2ib=${ofed_location} ${CONFIGURE_FLAGS}"
+            return $rc
+        else
+            return 0
+        fi
+    fi
+
+    # build kernel-ib
+    if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
+        local REUSE_SIGNATURE=$({ echo "$ofed_version";
+                                  echo "$(find_linux_release ${linux})";
+                                  cat "${linux}/include/linux/autoconf.h"; } |
+                                md5sum | cut -d" " -f1)
+        # see if we can link to the reuse pool
+        # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
+        #       "library"
+        local CAN_LINK_FOR_REUSE=false
+        touch $REUSEBUILD/$$
+        if cp -al $REUSEBUILD/$$ $TOPDIR/; then
+            CAN_LINK_FOR_REUSE=true
+        fi
+        rm $REUSEBUILD/$$
+    fi
+
+    if ! $USE_BUILD_CACHE || ! reuse ofed "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
+                                   "$REUSE_SIGNATURE"; then
+        if [ -n "$REUSE_SIGNATURE" ]; then
+            # stash away the existing built articles for a moment
+            mkdir bak
+            mv {BUILD,{S,}RPMS,S{OURCE,PEC}S} bak
+            function mv_back {
+                pushd bak
+                find . | cpio -pudlm ..
+                popd
+                rm -rf bak
+            }
+            create_rpmbuild_dirs
+        fi
+        # build it
+        build_kernel_ib "${linux}"
+
+        if [ -z "$REUSE_SIGNATURE" ]; then
+            echo "No reuse signature was caculated so not storing the built ofed"
+        else
+            # store the resulting RPM build tree for future use
+            echo "Storing the built ofed for future reuse"
+            if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,BUILD,SRPMS,RPMS}" \
+                                 "ofed" "$REUSEBUILD" "$REUSE_SIGNATURE" \
+                                 "$CAN_LINK_FOR_REUSE"; then
+                error "Failed to store OFED RPMS for reuse"
+                mv_back
+                return 1
+            fi
+            # put the stuff we stashed away back
+            mv_back
+        fi
+    fi
+
+    pushd "$TOPDIR" >/dev/null
+    rm -rf kernel-ib-devel
+    mkdir kernel-ib-devel
+    cd kernel-ib-devel
+    # the actual ofed RPMs don't have the -rc$n or -$date string appened that
+    # might be present on the file
+    local linuxrelease=$(find_linux_release "$linux")
+    ofed_version=$(echo $ofed_version |
+                   sed -re 's/-(20[0-9]{6,6}-[0-9]{4,4}|rc[0-9]*)$//')
+    local rpm=$(ls $TOPDIR/RPMS/*/kernel-ib-devel-${ofed_version}-${linuxrelease//-/_}.*.rpm)
+    if ! rpm2cpio < $rpm | cpio -id; then
+        fatal 1 "could not unpack the kernel-ib-devel rpm."
+    fi
+    CONFIGURE_FLAGS="--with-o2ib=$(pwd)/usr/src/ofa_kernel ${CONFIGURE_FLAGS}"
+    popd >/dev/null
+
+}
+
+build_with_srpm() {
+
+    if ! $PATCHLESS; then
+        local kernel_extra_version
+        if ! kernel_extra_version=$(build_kernel_with_srpm ${STDOUT}); then
+            fatal 1 "Failed to build the kernel from it's SRPM"
+        fi
+
+        for arch in $BUILD_ARCHS; do
+            local kernel_devel_rpm
+            if ! kernel_devel_rpm=$(find_rpm "$TOPDIR/RPMS/$arch/" provides "^$(devel_kernel_name $KERNEL_LUSTRE_NAMING) ="); then
+                fatal 1 "Failed to find a kernel development RPM in $TOPDIR/RPMS/$arch/"
+            fi
+
+            # install the -devel RPM in preparation for modules builds
+            if ! lnxrel="$kernel_extra_version" unpack_linux_devel_rpm \
+                           "$TOPDIR/RPMS/$arch/$kernel_devel_rpm"; then
+                fatal 1 "Could not find the Linux tree in $TOPDIR/RPMS/$arch/$kernel_devel_rpm"
+            fi
+        done
+    else
+        # need to find and unpack the vendor's own kernel-devel for patchless
+        # client build
+        local kernelrpm
+        if ! kernelrpm=$(find_linux_rpm "-$DEVEL_KERNEL_TYPE"); then
+            fatal 1 "Could not find the kernel-$DEVEL_KERNEL_TYPE RPM in ${KERNELRPMSBASE}/${lnxmaj}/${DISTRO}"
+        fi
+        if ! lnxrel="$lnxrel" unpack_linux_devel_rpm "$kernelrpm" "-"; then
+            fatal 1 "Could not find the Linux tree in $kernelrpm"
+        fi
+    fi
+
+    # ~sigh~  have to make copies of and modify some of the rpm
+    # infrastructure files so that find-requires can find our unpacked
+    # kernel-devel artifacts
+    cp $RPM_HELPERS_DIR/{symset-table,find-requires{,.ksyms}} .
+    FIND_REQUIRES="$(pwd)/find-requires"
+    chmod 755 {symset-table,find-requires{,.ksyms}}
+    local tmp="$(pwd)"
+    tmp="${tmp//\//\\/}"
+    ed find-requires <<EOF
+1a
+set -x
+.
+/|.*find-requires.ksyms/s/|/| bash -x/
+g/ [^ ]*\/\(find-requires\.ksyms\)/s// $tmp\/\1/g
+wq
+EOF
+    ed find-requires.ksyms <<EOF
+1a
+set -x
+.
+g/\/.*\/\(symset-table\)/s//$tmp\/\1/g
+wq
+EOF
+    ed symset-table <<EOF
+1a
+set -x
+.
+g/\(\/boot\/\)/s//$tmp\/reused\1/g
+g/\(\/usr\/src\/kernels\/\)/s//$tmp\/reused\1/g
+wq
+EOF
+
+    build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
+        fatal 1 "error building OFED"
+
+    # now build Lustre
+    if build_lustre "$LINUX" "$LINUXOBJ"; then
+        # the build worked.  resolve any symlinked files (i.e. from reuse)
+        # in RPMS/$arch to real files so that that that huge mess of
+        # complication known as LTS can copy them yet somewhere else.
+        # is it any wonder this whole process is so damn so?  anyone ever
+        # heard of hardlinks?  it's this cool new thing that allows you save
+        # tons of time and space by creating... well you can go read about
+        # them if you have not heard about them yet.
+        # can i say how much the implemenation of all of this really impedes
+        # RPM reuse?
+        local dir
+        for dir in RPMS/*; do
+            pushd $dir
+            for file in $(ls); do
+                if [ -h $file ]; then
+                    cp $file foo
+                    mv foo $file
+                fi
+            done
+            popd
+        done
+        # also, for i?86, make sure all of the RPMs are in RPMS/$TARGET_ARCH
+        # as that's where LTS expects to find them
+        for dir in RPMS/*; do
+            if [ $dir = RPMS/$TARGET_ARCH ]; then
+                continue
+            fi
+            pushd $dir
+            local files=$(ls)
+            if [ -n "$files" ]; then
+                cp -al $files ../$TARGET_ARCH
+            fi
+            popd
+        done
+    else
+        return 1
+    fi
+
+}
+
+create_rpmbuild_dirs() {
+
+    [ -d RPMS ] || mkdir RPMS
+    for arch in $BUILD_ARCHS; do
+        if [[ $arch = i?86 ]]; then
+            # some stupidity in the sles11 kernel spec requires an RPMS/i386
+            # even if the target arch is i686
+            [ -d RPMS/i386 ] || mkdir RPMS/i386
+        fi
+        [ -d RPMS/$arch ] || mkdir RPMS/$arch
+    done
+    [ -d BUILD ] || mkdir BUILD
+    [ -d SOURCES ] || mkdir SOURCES
+    [ -d SPECS ] || mkdir SPECS
+    [ -d SRPMS ] || mkdir SRPMS
+
+}
+
+new_list() {
+
+    echo ""
+
+}
+
+add_list() {
+    local list="$1"
+    local item="$2"
+
+    echo "$list $item"
+
+}
+
+is_list_member() {
+    local list="$1"
+    local item="$2"
+
+    [[ $list\  == *\ $item\ * ]]
+
+}
+
+#########################################################################
+# Generate a backtrace through the call stack.
+#
+# Input: None
+# Output: None
+#########################################################################
+backtrace() {
+    local strip=${1:-1}
+
+    local funcname="" sourcefile="" lineno="" n
+
+    echo "Call stack: (most recent first)"
+    for (( n = $strip ; n < ${#FUNCNAME[@]} ; ++n )) ; do
+        funcname=${FUNCNAME[$n - 1]}
+        sourcefile=$(basename ${BASH_SOURCE[$n]})
+        lineno=${BASH_LINENO[$n - 1]}
+        if [ $n = 1 ]; then
+            let lineno-=11
+        fi
+        # Display function arguments
+        if [[ ! -z "${BASH_ARGV[@]}" ]]; then
+            local args newarg j p=0
+            for (( j = ${BASH_ARGC[$n - 1]}; j > 0; j-- )); do
+                newarg=${BASH_ARGV[$j + $p - 1]}
+                args="${args:+${args} }'${newarg}'"
+            done
+            let p+=${BASH_ARGC[$n - 1]}
+        fi
+        echo "  ${funcname} ${args:+${args} }at ${sourcefile}:${lineno}"
+    done
+
+    echo
+    echo "BEGIN BACKTRACE"
+
+    #echo ${BASH_LINENO[*]}
+    #echo ${BASH_SOURCE[*]}
+    #echo ${FUNCNAME[*]}
+    local i=$((${#FUNCNAME[@]} - 1))
+    while [ $i -ge 0 ]; do
+        local lineno=${BASH_LINENO[$i]}
+        if [ $i = 0 ]; then
+            let lineno-=11
+        fi
+        local SOURCELINE="${BASH_SOURCE[$i + 1]}:${lineno}"
+        # Can't figure out how to get function args from other frames...
+        local FUNCTION="${FUNCNAME[$i]}()"
+        echo "$SOURCELINE:$FUNCTION"
+        i=$((i - 1))
+    done
+
+    echo "END BACKTRACE"
+
+    echo $BACKTRACE
+
+}
+
+seen_list=$(new_list)
+trap 'set +x;
+echo "An unexpected error has occurred at ${BASH_SOURCE[0]##*/}:$((LINENO-1)).
+Unfortunately the above line number in the message may or may not be correct,
+but details have been send to the lbuild maintainer.  Attempting to continue."; (echo "Untrapped error"
+echo
+# have we seen this one
+echo "checking seen list for ${BASH_SOURCE[0]}:${BASH_LINENO[0]}"
+
+if is_list_member "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}"; then
+  echo "seen this one already"
+else
+  seen_list=$(add_list "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}")
+fi
+backtrace
+echo
+echo "Environment:"
+set
+) | mail -s "Untrapped error at ${BASH_SOURCE[0]##*/}:$((LINENO-15)) on $HOSTNAME" brian@sun.com >&2; set $xtrace' ERR
+set -E
+
 [ -r ~/.lbuildrc ] && . ~/.lbuildrc
 
 [ -r ~/.lbuildrc ] && . ~/.lbuildrc
 
-options=$(getopt -o d:D:h -l disable-datestamp,external-patches:,extraversion:,kerneldir:,linux:,lustre:,nodownload,nosrc,publish,release,stage:,tag:,target:,target-archs:,with-linux: -- "$@")
+options=$(getopt -o d:D:h -l kerneltree:,distro:,kernelrpm:,reusebuild:,patchless,ldiskfs,ccache,reuse:,norpm,disable-datestamp,external-patches:,timestamp:,extraversion:,kerneldir:,linux:,lustre:,nodownload,nosrc,ofed-version:,publish,release,set-value:,src,stage:,tag:,target:,target-archs:,with-linux:,xen -- "$@")
 
 
-if [ $? != 0 ] ; then
+if [ $? != 0 ]; then
     usage 1
 fi
 
 eval set -- "$options"
     usage 1
 fi
 
 eval set -- "$options"
-    
-while [ "$1" ] ; do
+
+while [ "$1" ]; do
     case "$1" in
         '')
             usage 1
             ;;
     case "$1" in
         '')
             usage 1
             ;;
+        --ccache)
+            CCACHE='ccache'
+            shift
+            ;;
         -d)
             CVSROOT=$2
             shift 2
         -d)
             CVSROOT=$2
             shift 2
@@ -632,31 +1694,81 @@ while [ "$1" ] ; do
             KERNELDIR=$2
             shift 2
             ;;
             KERNELDIR=$2
             shift 2
             ;;
+        --kerneltree)
+            if ! KERNELTREE=$(canon_path "$2"); then
+                fatal 1 "Could not determine the canonical location of $2"
+            fi
+            shift 2
+            ;;
         --linux | --with-linux)
         --linux | --with-linux)
-            LINUX=$2
+            if ! LINUX=$(canon_path "$2"); then
+                fatal 1 "Could not determine the canonical location of $2"
+            fi
+            shift 2
+            ;;
+        --distro)
+            DISTRO=$2
+            shift 2
+            ;;
+        --reuserpm)
+            REUSERPM=$2
+            shift 2
+            ;;
+        --reusebuild)
+            if ! REUSEBUILD=$(canon_path "$2"); then
+                fatal 1 "Could not determine the canonical location of $2"
+            fi
+            shift 2
+            ;;
+        --norpm)
+            NORPM=true
+            shift
+            ;;
+        --ldiskfs)
+            LDISKFSRPM=true
+            shift
+            ;;
+        --patchless)
+            PATCHLESS=true
+            shift
+            ;;
+        --kernelrpm)
+            if ! KERNELRPMSBASE=$(canon_path "$2"); then
+                fatal 1 "Could not determine the canonical location of $2"
+            fi
+            shift 2
+            ;;
+        --timestamp)
+            TIMESTAMP=$2
             shift 2
             ;;
         --lustre)
             shift 2
             ;;
         --lustre)
-            LUSTRE=$2
+            if ! LUSTRE=$(canon_filepath "$2"); then
+                fatal 1 "Could not determine the canonical location of $2"
+            fi
             shift 2
             ;;
         --nodownload)
             shift 2
             ;;
         --nodownload)
-            DOWNLOAD=0
+            DOWNLOAD=false
             shift 1
             ;;
         --nosrc)
             shift 1
             ;;
         --nosrc)
-            DO_SRC=0
+            DO_SRC=false
             shift 1
             ;;
             shift 1
             ;;
+        --ofed-version)
+            OFED_VERSION="$2"
+            shift 2
+            ;;
         --publish)
             shift
             ;;
         --release)
         --publish)
             shift
             ;;
         --release)
-            RELEASE=1
+            RELEASE=true
             shift
             ;;
         --src)
             shift
             ;;
         --src)
-            DO_SRC=1
+            DO_SRC=true
             shift 1
             ;;
         --stage)
             shift 1
             ;;
         --stage)
@@ -679,11 +1791,25 @@ while [ "$1" ] ; do
             USE_DATESTAMP=
             shift
             ;;
             USE_DATESTAMP=
             shift
             ;;
+        --xen)
+            XEN=true
+            shift
+            ;;
+        --set-value)
+            eval $2
+            shift 2
+            ;;
         --)
             shift
         --)
             shift
+            # there are actually some lustre configure flags that we need to
+            # handle ourselves (but we still give them to configure)
+            if [[ \ $@\  == *\ --disable-tests\ * ]]; then
+                LUSTRE_TESTS=false
+            fi
             CONFIGURE_FLAGS=$@
             CONFIGURE_FLAGS=$@
+            CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-liblustre --enable-liblustre-tests"
             break
             break
-            ;; 
+            ;;
         *)
             usage 1 "Unrecognized option: $1"
             ;;
         *)
             usage 1 "Unrecognized option: $1"
             ;;
@@ -694,22 +1820,54 @@ check_options
 
 unpack_lustre
 
 
 unpack_lustre
 
-# prep_build needs the .spec.in from the lustre source
-if [ -z "$LINUX" ] ; then
-    load_target
-    if (( $DO_SRC )) ; then
-        unpack_linux
-        patch_linux
-        pack_linux
-        clean_linux
-    fi
+# XXX - should we _always_ get the buildid from the META file?  what are the
+# other (i.e. non-lustre-tarball use cases of lbuild)?
+BUILDID=$(sed -ne '/^BUILDID =/s/.*= *//p' lustre/META)
+
+load_target
+
+if [ -n "$OFED_VERSION" -a "$OFED_VERSION" != "inkernel" ]; then
+    download_ofed
+    unpack_ofed || fatal 1 "Error unpacking OFED tarball"
+fi
 
 
-    prep_kernel_build
-    clean_lustre
+# make sure the RPM build environment is set up
+create_rpmbuild_dirs
 
 
-    build_kernel
+# if an unpacked kernel source tree was given on the command line
+# just build lustre with it (nothing distro kernel specific here)
+if [ -n "$LINUX" ]; then
+    build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
+        fatal 1 "error building OFED"
+    build_lustre "$LINUX" "$LINUXOBJ"
 else
 else
-    build_lustre
+    if [ -f "${0%/*}/lbuild-$DISTRO" ]; then
+        source ${0%/*}/lbuild-$DISTRO
+
+        build_with_srpm || fatal 1 "Failed to build_with_srpm"
+    else
+        EXTRA_VERSION_DELIMITER=${EXTRA_VERSION_DELIMITER:-"-"}
+        source ${0%/*}/lbuild.old_school
+
+        old_school_download_kernel
+
+        build_success=false
+        if $PATCHLESS; then
+            patchless_build_sequence && build_success=true
+        else
+            [ "$DISTRO" = "sles9" ] && build_sequence_rpm_reuse && build_success=true
+            if ! $build_success; then
+                build_sequence_reuse && build_success=true
+                if ! $build_success; then
+                    build_sequence && build_success=true
+                    if $build_success; then
+                        store_for_reuse || echo "Cannot store for future reuse"
+                    fi
+                fi
+            fi
+        fi
+        ( $build_success ) || fatal 1 "Cannot build lustre"
+    fi
 fi
 
 stage
 fi
 
 stage