Whamcloud - gitweb
LU-633 iokit: mds-survey script for MD echo client test
[fs/lustre-release.git] / build / lbuild
1 #!/bin/bash
2
3 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
4
5 # this is an alternative FD for stdout, to be used especially when we are
6 # taking stdout from a function as it's return value.  i.e. foo=$(bar)
7 # this is a workaround until a version of bash where we can put xtrace
8 # on a specific FD
9 exec 3>&1; STDOUT=3
10
11 #set -x
12 xtrace="+x"
13 if [[ $SHELLOPTS = *xtrace* ]]; then
14     xtrace="-x"
15 fi
16 shopt -s extdebug
17
18 # include the exit_traps library
19 . ${0%/lbuild}/exit_traps.sh
20 . ${0%/lbuild}/funcs.sh
21
22 # our children should die when we do
23 push_exit_trap "kill -INT -$$ || true" kill_children
24
25 # increment this if you have made a change that should force a new kernel
26 # to build built
27 #BUILD_GEN=1
28 #BUILD_GEN=2    # bz19952: remove -lustre tag from kernel RPM names
29 #BUILD_GEN=3    # bz19975: enable the building of src.rpms by default
30 #BUILD_GEN=4    # bz22281: use the git hash in the kernel extra version
31 BUILD_GEN=5     # TT-107: don't cache the BUILD dir
32
33 TOPDIR=$PWD
34
35 # CVSROOT is inherited from the environment
36 KERNELDIR=
37 LINUX=
38 LUSTRE=
39 RELEASE=false
40 # XXX - some recent hacking has pretty much neutered this option.
41 #       search through this file (and lbuild.old_school -- but that will
42 #       be going away soon) for "-bb" and see how many places
43 #       simply don't account for this option
44 DO_SRC=true
45 DOWNLOAD=true
46 TAG=
47 CANONICAL_TARGET=
48 TARGET=
49 TARGET_ARCH="$(uname -m)"
50 # change default behavior to only build for the current arch
51 TARGET_ARCHS="$TARGET_ARCH"
52 TARGET_ARCHS_ALL="$TARGET_ARCH"
53 [ "$TARGET_ARCH" = "i686" ] && TARGET_ARCHS_ALL="i686 i586 i386"
54 CONFIGURE_FLAGS=
55 EXTERNAL_PATCHES=
56 EXTRA_VERSION=
57 STAGEDIR=
58 TMPDIR=${TMPDIR:-"/var/tmp"}
59 TIMESTAMP=
60 # this is a dir to try reuse old kernel RPMs in (although, it seems to be
61 # unused in any real manner
62 REUSERPM=
63 # this is the dir that should be used to store reuse products
64 REUSEBUILD=
65 # should cached products be used or force rebuilding?
66 USE_BUILD_CACHE=true
67 # what does this do exactly?  does it imply no kernel build?
68 NORPM=false
69 IOKITRPM=true
70 LDISKFSRPM=true
71 SKIPLDISKFSRPM="v1_4_* b1_4"
72 SMPTYPES="smp bigsmp default ''"
73 PATCHLESS=false
74 XEN=false
75 LINUXOBJ=
76 DISTRO=
77 KERNELTREE=
78 # default to not adding -lustre- into the kernel RPM package names
79 KERNEL_LUSTRE_NAMING=false
80 # default not use kabi check.
81 USE_KABI=false
82
83 # patchless build
84 KERNELRPMSBASE=
85 RPMSMPTYPE=
86
87 # from target file
88 SERIES=
89 BASE_ARCHS=
90 BIGMEM_ARCHS=
91 BOOT_ARCHS=
92 JENSEN_ARCHS=
93 SMP_ARCHS=
94 BIGSMP_ARCHS=
95 PSERIES64_ARCHS=
96 UP_ARCHS=
97
98 # not in the target file any more
99 CONFIG=
100
101 # build the lustre-tests rpm?
102 LUSTRE_TESTS=true
103
104 DATE=$(date)
105
106 USE_DATESTAMP=1
107 RPMBUILD=
108
109 OLD_SCHOOL=false
110
111 export CC=${CC:-gcc}
112
113 # Readlink is not present on some older distributions: emulate it.
114 readlink() {
115     local path=$1 ll
116
117     if [ -L "$path" ]; then
118         ll="$(LC_ALL=C ls -l "$path" 2> /dev/null)" &&
119         echo "${ll/* -> }"
120     else
121         return 1
122     fi
123 }
124
125 usage() {
126     cat <<EOF
127 Usage: ${0##*/} [OPTION]... [-- <lustre configure options>]
128
129   -d CVSROOT
130     Specifies the CVS Root to use when pulling files from CVS.  The
131     environment variable \$CVSROOT is used if this option is not
132     present.
133
134   --external-patches=EXTERNAL_PATCHES
135     Directory similar to lustre/lustre/kernel_patches/ that lbuild should
136     look for seres and config files in before looking in the lustre
137     tree.
138
139   --extraversion=EXTRAVERSION
140     Text to use for the rpm release and kernel extraversion.
141
142   --timestamp=TIMESTAMP
143     Date of building lustre in format YYYYMMDDhhmmss
144
145   --reuserpm=DIR
146     Try to reuse old kernel RPMs from DIR
147
148   --reusebuild=DIR
149     Try to reuse old kernel builds from DIR
150
151   --kernelrpm=DIR
152     Path to distro kernel RPM collection
153
154   --ccache
155     Use ccache
156
157   --norpm
158     Do not build RPMs (compile only mode)
159
160   --patchless
161     Build lustre client only
162
163   --distro=DISTRO
164     Which distro using. Autodetect by default
165
166   --kerneldir=KERNELDIR
167     Directory containing Linux source tarballs referenced by target
168     files.
169
170   --kerneltree=KERNELTREE
171     Directory containing dirs with Linux source tarballs referenced by target
172     files. Dir names in format kernel version ('2.6.9', etc.)
173
174   --linux=LINUX --with-linux=LINUX
175     Directory of Linux kernel sources.  When this option is used, only
176     Lustre modules and userspace are built.
177
178   --lustre=LUSTRE
179     Path to an existing lustre source tarball to use instead of
180     pulling from CVS.
181
182   --nodownload
183     Do not try to download a kernel from downloads.lustre.org
184
185   --nosrc
186     Do not build a .src.rpm, a full kernel patch, or a patched kernel
187     tarball.
188
189   --ldiskfs
190     Do ldiskfs RPM. Now true by default
191
192   --noiokit
193     Do not build lustre-iokit RPM. Now true by default
194
195   --publish
196     Unused.
197
198   --release
199     Specifies that the files generated do not include timestamps, and
200     that this is an official release.
201
202   --src
203     Build a .src.rpm, a full kernel patch, and a patched kernel tarball.
204
205   --stage=DIR
206     Directory used to stage packages for release.  RPMs will be placed
207     more or less in DIR/<target>-<arch>, and the tarball will be
208     placed in DIR.
209
210   --tag=TAG
211     A CVS branch/tag name to build from when pulling from CVS.
212
213   --target=TARGET
214     The name of the target to build.  The available targets are listed
215     below.
216
217   --target-archs=TARGET_ARCHS
218     A (space delimited) list of architectures to build.  By default,
219     all of the archs supported by the TARGET will be built, in
220     addition to a .src.rpm.  This option can limit those, for machines
221     that can only build certain archs or if you only want a certain
222     arch built (for testing, or a one-off kernel).
223
224     Also note that by using a non-"base" arch (eg, i386) only kernels
225     will be built - there will be no lustre-lite-utils package.
226
227   --disable-datestamp
228     Prevents the datestamp flag (-D) from being passed to cvs for
229     checkouts. This is a workaround for a problem encountered when
230     using lbuild with tinderbox.
231
232   --xen
233     Builds a Xen domX kernel.
234
235   --set-value
236     Set's a variable to a given value.
237
238 EOF
239
240 #   list_targets
241
242     fatal "$1" "$2"
243 }
244
245 # canonicalize a relative path to a file
246 canon_filepath() {
247     local PATH="$1"
248
249     if [ ! -f "$PATH" ]; then
250         return 1
251     fi
252
253     local FILE=${PATH##*/}
254     local DIR=${PATH%/*}
255
256     echo $(canon_path "$DIR")/$FILE
257     return 0
258 }
259
260 # canonicalize a relative path to a dir
261 canon_path() {
262     local PATH="$1"
263
264     if [ ! -d "$PATH" ]; then
265         return 1
266     fi
267
268     pushd "$PATH" >/dev/null || return 1
269     local CANONPATH=$PWD
270     popd >/dev/null
271
272     echo "$CANONPATH"
273     return 0
274 }
275
276 check_options() {
277
278     if [ "$LUSTRE" ]; then
279         [ -r "$LUSTRE" ] || \
280             usage 1 "Could not find Lustre source tarball '$LUSTRE'."
281     else
282         [ "$CVSROOT" ] || \
283             usage 1 "Either specify a CVS Root with -d, or a Lustre source tarball with --lustre."
284         [ "$TAG" ] || \
285             usage 1 "A branch/tag name must be specified with --tag when not building from a tarball."
286     fi
287
288     [ -z "$DISTRO" ] && DISTRO=$(autodetect_distro)
289
290     if [ -z "$LINUX" ]; then
291         [ "$KERNELDIR" -o "$KERNELTREE" ] || \
292             usage 1 "A kernel directory must be specified with --kerneldir or --kerneltree."
293
294         [ -d "$KERNELDIR" -o -d "$KERNELTREE" ] || \
295             usage 1 "$KERNELDIR and $KERNELTREE are not a directory."
296
297         if ! $RELEASE; then
298             [ "$TAG" ] || \
299                 usage 1 "When building a snapshot, a tag name must be used."
300         fi
301
302         [ "$TARGET" ] || TARGET=$(autodetect_target "$DISTRO")
303 #       TARGET_FILE="$TOPDIR/lustre/kernel_patches/targets/$TARGET.target"
304 #       [ -r "$TARGET_FILE" ] || \
305 #               usage 1 "Target '$TARGET' was not found."
306     fi
307
308     case $TARGET in
309         2.6-rhel6)
310             CANONICAL_TARGET="rhel6"
311             ;;
312         2.6-rhel5)
313             CANONICAL_TARGET="rhel5"
314             ;;
315         2.6-rhel4)
316             CANONICAL_TARGET="rhel-2.6"
317             ;;
318         2.6-suse)
319             CANONICAL_TARGET="sles-2.6"
320             ;;
321         2.6-sles10)
322             CANONICAL_TARGET="sles10-2.6"
323             ;;
324         2.6-sles11)
325             CANONICAL_TARGET="sles11"
326             ;;
327         2.6-oel5)
328             CANONICAL_TARGET="oel5"
329             ;;
330         hp_pnnl-2.4)
331             CANONICAL_TARGET="hp-pnnl-2.4"
332             ;;
333         2.6-vanilla \
334             | suse-2.4.21-2 \
335             | rh-2.4 \
336             | rhel-2.4 \
337             | sles-2.4 \
338             | 2.6-patchless)
339                 CANONICAL_TARGET="$TARGET"
340                 ;;
341     esac
342
343     local timestampnodig=$(echo $TIMESTAMP | sed -e s/[0-9]*//g)
344     [ "$timestampnodig" = "" ] || TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M%S")
345     local timestamplength="${#TIMESTAMP}"
346     if [ $timestamplength -eq 12 ]; then
347         TIMESTAMP="${TIMESTAMP}00"
348     elif [ $timestamplength -ne 14 ]; then
349         TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M%S")
350     fi
351
352     RPMBUILD=$(which rpmbuild 2>/dev/null | head -1)
353     if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
354         RPMBUILD=$(which rpm 2>/dev/null | head -1)
355         if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
356             usage 1 "Could not find binary for making rpms (tried rpmbuild and rpm)."
357         fi
358     fi
359
360     if [ -n "$CCACHE" ]; then
361         which "$DISTCC" &>/dev/null && export DISTCC RPM_BUILD_NCPUS
362
363         if which "$CCACHE" &>/dev/null; then
364             local ccache=$(which "$CCACHE")
365             local bindir="$TOPDIR/bin"
366
367             if [ ! -d $bindir ]; then
368                 mkdir -p $bindir || fatal 1 "error trying to create $bindir"
369             else
370                 rm ${bindir}/* > /dev/null 2>&1 || true
371             fi
372             ln -s "$ccache" ${bindir}/ccache
373             ln -s "$ccache" ${bindir}/cc
374             ln -s "$ccache" ${bindir}/$CC
375             export PATH=$bindir:$PATH
376             export CCACHE && export CC="ccache $CC"
377             # zero the cache so we can see how effective we are being with it
378             echo -n "ccache "
379             ccache -z
380
381             # get some ccache stats when we are done
382             push_exit_trap '[ -n "$CCACHE" ] && ccache -s' "ccache_summary"
383             # should remove the ccache trap if lbuild is interrupted
384             trap 'echo "Received an INT TERM or HUP signal, terminating."; delete_exit_trap "ccache_summary"; exit 1' INT TERM HUP
385         fi
386     fi
387
388     return 0
389
390 }
391
392 uniqify() {
393
394     echo $(echo "$*" | xargs -n 1 | sort -u)
395
396 }
397
398 fetch_url() {
399     local url="$1"
400     local target="$2"
401
402     local rc=0
403     if which wget >/dev/null 2>&1; then
404         if ! wget -nv "$url" -O "$target"; then
405             rc=${PIPESTATUS[0]}
406         fi
407     elif which curl >/dev/null 2>&1; then
408         if ! curl -L -s -o "$target" "$url"; then
409             rc=${PIPESTATUS[0]}
410         fi
411     else
412         fatal 1 "Could not find either wget or curl to fetch URLs."
413     fi
414
415     return $rc
416
417 }
418
419 download_srpm() {
420     local target=$1
421     local srpm=$2
422     local force="${3:-false}"
423
424     if $force || [ ! -r "$KERNELDIR/$srpm" ] ||
425        [ ! -s "$KERNELDIR/$srpm" ]; then
426         if $DOWNLOAD; then
427             local location="http://downloads.lustre.org/public/kernels/$target/old"
428             # get the location from a distro specific method if it exists
429             if type -p kernel_srpm_location; then
430                 location=$(kernel_srpm_location)
431             fi
432             echo "Downloading $location/$srpm..."
433             if ! fetch_url "$location/$srpm" "$KERNELDIR/$srpm" 2>&1 ||
434                [ ! -s "$KERNELDIR/$srpm" ]; then
435                 rm -f $KERNELDIR/$srpm
436                 # punt to a distro specific method if it exists
437                 if ! type -p download_srpm-$DISTRO; then
438                     fatal 1 "Could not download target $target's kernel SRPM $srpm from $location."
439                 else
440                     if ! download_srpm-$DISTRO "$target" "$srpm" "$force"; then
441                         fatal 1 "Could not download target $target's kernel SRPM $srpm using download_srpm-$DISTRO."
442                     fi
443                 fi
444             fi
445         else
446             fatal 1 "$srpm not found in directory $KERNELDIR."
447         fi
448     fi
449
450 }
451
452 download_file() {
453     local from="$1"
454     local to="$2"
455     local force="$3"
456
457     local file=${from##*/}
458
459     if [ -d $to ]; then
460         to="$to/$file"
461     fi
462
463     local semaphore="$to-downloading"
464
465     is_downloading() {
466         if [ ! -f $semaphore ]; then
467             return 1
468         fi
469
470         # make sure the download has not been aborted
471         local now=$(date +%s)
472         local file_mtime=$(stat -c %Y "$to")
473         local staleness=$((now - file_mtime))
474         # let's assume an active download will write at least once a minute
475         if [ $staleness -gt 60 ]; then
476             return 1
477         fi
478
479         return 0
480     }
481
482     is_downloaded() {
483         # if the semaphore file exists, the file is either still downloading
484         # or a download was aborted and we cannot trust the target file
485         if [ -f $semaphore ]; then
486             return 1
487         fi
488
489         if ! is_downloading && [ -r "$to" ] && [ -s "$to" ]; then
490             return 0
491         fi
492
493         return 1
494     }
495
496     if $force || ! is_downloaded; then
497         if is_downloading; then
498             echo "Somebody else is downloading $from..."
499             while is_downloading; do
500                 echo "Waiting for $to to finish downloading"
501                 sleep 60
502             done
503             if is_downloaded; then
504                 return 0
505             else
506                 echo "The download we were waiting for seems to have been aborted"
507             fi
508
509         fi
510
511         if $DOWNLOAD; then
512             echo "Downloading $from..."
513             # flag others so they don't try to download also
514             push_exit_trap "rm -f $to $semaphore" "download"
515             touch $semaphore
516             if ! fetch_url "$from" "$to" || [ ! -s "$to" ]; then
517                 # the trap will remove the files via the fatal below
518                 fatal 1 "Could not download ${to##*/} from ${from%/*}/."
519             fi
520             rm -f $semaphore
521             delete_exit_trap "download"
522         else
523             fatal 1 "${to##*/} not found in directory ${to%/*}."
524         fi
525     fi
526
527     return 0
528
529 }
530
531 download_ofed() {
532     local force="${1:-false}"
533
534     if [ -z "$OFED_VERSION" -o "$OFED_VERSION" = "inkernel" ]; then
535         return 0
536     fi
537
538     local OFED_BASE_VERSION=$OFED_VERSION
539     if [[ $OFED_VERSION = *.*.*.* ]]; then
540         OFED_BASE_VERSION=${OFED_VERSION%.*}
541     fi
542
543     local location="http://www.openfabrics.org/downloads/OFED/ofed-${OFED_BASE_VERSION}/"
544
545     if [[ $OFED_VERSION = daily-* ]]; then
546         local Mmv daily
547         OFED_VERSION=${OFED_VERSION/daily-/}
548         Mmv=${OFED_VERSION%%-*}
549         daily=${OFED_VERSION##$Mmv-}
550         location="http://www.openfabrics.org/downloads/OFED/ofed-${Mmv}-daily/"
551         # find the filename for the version for the date specified
552         OFED_VERSION=$(curl -s "$location" | sed -nre "/${daily}-/s/.*href=\"OFED-(${Mmv//./\\.}-${daily}-[0-9]{4,4}).tgz.*$/\1/p" | tail -1)
553         if [ -z "$OFED_VERSION" ]; then
554             fatal 1 "Could not determine the filename of the OFED snapshot for ${daily}"
555         fi
556     fi
557
558     local file="OFED-${OFED_VERSION}.tgz"
559     download_file "$location/$file" "$KERNELTREE" "$force"
560
561 }
562
563 load_target() {
564
565     EXTRA_VERSION_save="$EXTRA_VERSION"
566     for patchesdir in "$EXTERNAL_PATCHES" \
567                       "$TOPDIR/lustre/lustre/kernel_patches"; do
568         TARGET_FILE="$patchesdir/targets/$TARGET.target"
569         [ -r "$TARGET_FILE" ] && break
570     done
571     [ -r "$TARGET_FILE" ] || fatal 1 "Target $TARGET was not found."
572
573     echo "Loading target config file $TARGET.target..."
574
575     # if the caller specified an OFED_VERSION it should override whatever
576     # the target file specifies
577     local env_OFED_VERSION="$OFED_VERSION"
578
579     . "$TARGET_FILE"
580
581     if [ -n "$env_OFED_VERSION" ]; then
582         OFED_VERSION="$env_OFED_VERSION"
583     fi
584
585     # doesn't make any sense to build OFED for xen domX's
586     if $XEN; then
587         OFED_VERSION=""
588     fi
589
590     # XXX - set_rpm_smp_type is an ugly undeterministic hack.  it needs to
591     #       go away and the target just specify the $RPMSMPTYPE
592     [ -z "$RPMSMPTYPE" ] && set_rpm_smp_type
593
594     # CC might have been overwriten in TARGET_FILE
595     if [[ $CC != ccache\ * ]] && which "$CCACHE" &>/dev/null; then
596         export CCACHE && export CC="ccache $CC"
597     fi
598
599     if [ ! "$KERNELTREE" = "" ] && [ -d "$KERNELTREE" ]; then
600         KERNELDIR="$KERNELTREE/${lnxmaj}"
601         [ -d "$KERNELDIR" ] || mkdir "$KERNELDIR"
602     fi
603
604     # verify the series is available
605     if [ "$SERIES" ]; then
606         for series in $SERIES; do
607             for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches"; do
608                 [ -r "$patchesdir/series/$series" ] && continue 2
609             done
610             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."
611         done
612     fi
613
614     # set the location of the .config file
615     local XENPOSTFIX=""
616     if $XEN; then
617         XENPOSTFIX="-xen"
618     fi
619
620     if [ -f $TOPDIR/lustre/lustre/kernel_patches/kernel_configs/kernel-$lnxmaj-$TARGET-$TARGET_ARCH.config ]; then
621         CONFIG_FILE="$TOPDIR/lustre/lustre/kernel_patches/kernel_configs/kernel-$lnxmaj-$TARGET$XENPOSTFIX-$TARGET_ARCH${RPMSMPTYPE:+-}${RPMSMPTYPE}.config"
622     fi
623
624     local lnxrelnew=${lnxrel//-/_}
625
626     # remember the EXTRA_VERSION before we diddle it here
627     # XXX - we really should not diddle with any values read in from the
628     #       target file.  if we want to modify a value, we should create
629     #       a new variable.
630     PRISTINE_EXTRA_VERSION=$EXTRA_VERSION
631
632     if ! $PATCHLESS && [ ! -f "$CONFIG_FILE" ]; then
633         fatal 1 "Config file for target $TARGET missing from $TOPDIR/lustre/lustre/kernel_patches/kernel_configs/."
634     fi
635
636     if [ "$EXTRA_VERSION_save" ]; then
637         EXTRA_VERSION="$EXTRA_VERSION_save"
638     elif ! $RELEASE; then
639         # if there is no patch series, then this is not a lustre specific
640         # kernel.  don't make it look like one
641         if $PATCHLESS || [ -n "$SERIES" ]; then
642             EXTRA_VERSION=$(echo $EXTRA_VERSION | sed -e "s/\(.*_lustre\)\..*/\1/")
643 #            EXTRA_VERSION="${EXTRA_VERSION}-${TAG}.${TIMESTAMP}"
644             if ! $PATCHLESS && [ -n "$BUILDID" ]; then
645                 EXTRA_VERSION="${EXTRA_VERSION}.${BUILDID}"
646             fi
647         fi
648     fi
649     # EXTRA_VERSION=${EXTRA_VERSION//-/_}
650
651     ALL_ARCHS="$BASE_ARCHS $BIGMEM_ARCHS $BOOT_ARCHS $JENSEN_ARCHS $SMP_ARCHS $BIGSMP_ARCHS $PSERIES64_ARCHS $UP_ARCHS"
652
653     BUILD_ARCHS=
654     for arch in $(uniqify "$ALL_ARCHS"); do
655         if [ -z "$TARGET_ARCHS" ] ||
656            [[ \ $TARGET_ARCHS\  = *\ $arch\ * ]]; then
657             BUILD_ARCHS="$BUILD_ARCHS $arch"
658         fi
659     done
660     [ "$BUILD_ARCHS" ] || usage 1 "No available target archs to build."
661     echo "Building for: $BUILD_ARCHS"
662 }
663
664 tarflags() {
665     local file="$1"
666
667     case "$file" in
668         '')
669             fatal 1 "tarflags(): File name argument missing."
670             ;;
671         *.tar.gz | *.tgz)
672             echo 'zxf'
673             ;;
674         *.tar.bz2)
675             echo 'jxf'
676             ;;
677         *.tar)
678             echo 'xf'
679             ;;
680         *)
681             fatal 1 "tarflags(): Unrecognized tar extension in file: $1"
682             ;;
683     esac
684
685 }
686
687 untar() {
688     local tarfile="$1"
689     shift
690     local extractfile="$@"
691
692     echo "Untarring ${tarfile##*/}..."
693     tar $(tarflags "$tarfile") "$tarfile" $extractfile
694
695 }
696
697 unpack_ofed() {
698
699     if ! untar "$KERNELTREE/OFED-${OFED_VERSION}.tgz"; then
700         return 1
701     fi
702     [ -d OFED ] || ln -sf OFED-[0-9].[0-9]* OFED
703
704 }
705
706 unpack_lustre() {
707
708     if [ -z "$LUSTRE" ]; then
709         local DATESTAMP=""
710
711         if [ -n "$USE_DATESTAMP" ]; then
712             DATESTAMP="-D '$DATE'"
713         fi
714
715         local DIRNAME="lustre-$TAG-$TIMESTAMP"
716
717         cvs -d "$CVSROOT" -qz3 co $DATESTAMP -d "$DIRNAME" lustre || \
718             fatal 1 "There was an error checking out toplevel Lustre from CVS."
719         pushd "$DIRNAME" > /dev/null
720         ./lustrecvs "$TAG" || \
721             fatal 1 "There was an error checking out Lustre/Portals/Build from CVS."
722         echo "Creating lustre tarball..."
723         sh autogen.sh || fatal 1 "There was an error running autogen.sh."
724         ./configure --enable-dist || \
725             fatal 1 "There was an error running ./configure to create makefiles."
726         make dist || fatal 1 "There was an error running 'make dist'."
727         LUSTRE=$PWD/lustre-*.tar.gz
728         popd > /dev/null
729     fi
730
731     untar "$LUSTRE" || fatal 1 "Error unpacking Lustre tarball"
732     [ -d lustre ] || ln -sf lustre-[0-9].[0-9]* lustre
733
734 }
735
736 do_patch_linux() {
737
738     local do_patch=${1:-true}
739
740     FULL_PATCH="$PWD/lustre-kernel-${TARGET}-${EXTRA_VERSION}.patch"
741     [ -f "$FULL_PATCH" ] && rm -f "$FULL_PATCH"
742     $do_patch && pushd linux >/dev/null
743     for series in $SERIES; do
744         echo -n "Applying series $series:"
745         for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches"; do
746             [ -r "$patchesdir/series/$series" ] || continue
747             SERIES_FILE="$patchesdir/series/$series"
748             for patch in $(<"$SERIES_FILE"); do
749                 echo -n " $patch"
750                 PATCH_FILE="$patchesdir/patches/$patch"
751                 [ -r "$PATCH_FILE" ] || \
752                     fatal 1 "Patch $patch does not exist in Lustre tree."
753                 cat "$PATCH_FILE" >> "$FULL_PATCH" || {
754                     rm -f $FULL_PATCH
755                     fatal 1 "Error adding patch $patch to full patch."
756                 }
757                 if $do_patch; then
758                     patch -s -p1 < "$PATCH_FILE" 2>&1 || {
759                         rm -f $FULL_PATCH
760                         fatal 1 "Error applying patch $patch."
761                     }
762                 fi
763             done
764             break
765         done
766         echo
767     done
768     $do_patch && popd >/dev/null
769     echo "Full patch has been saved in ${FULL_PATCH##*/}."
770
771 }
772
773 build_iokit() {
774     local rpmbuildopt="$1"
775
776     pushd lustre-iokit > /dev/null || return 255
777
778     if ! ./configure; then
779         echo "failed to configure in lustre-iokit"
780         popd >/dev/null # pushd lustre-iokit
781         return 255
782     fi
783
784     if ! make dist; then
785         echo "failed to make dist in lustre-iokit"
786         popd >/dev/null # pushd lustre-iokit
787         return 255
788     fi
789
790     if ! $RPMBUILD $rpmbuildopt lustre-iokit*.tar.gz \
791         --define "_tmppath /var/tmp" \
792         --define "_topdir $TOPDIR" 2>&1; then
793         popd >/dev/null # pushd lustre-iokit
794         return 255
795     fi
796
797     if $DO_SRC && ! $RPMBUILD -ts lustre-iokit*.tar.gz \
798             --define "_tmppath /var/tmp" \
799             --define "_topdir $TOPDIR" 2>&1; then
800             popd >/dev/null # pushd lustre-iokit
801             return 255
802     fi
803     popd >/dev/null # pushd lustre-iokit
804 }
805
806 build_lustre() {
807     local linux="$1"
808     local linuxobj="$2"
809
810     cp "$LUSTRE" SOURCES
811
812     pushd lustre >/dev/null
813
814     echo "Building Lustre RPMs for: $BUILD_ARCHS..."
815     local targets arch
816     for arch in $BUILD_ARCHS; do
817         targets="--target $arch $targets"
818     done
819
820     local confoptions=""
821
822     if $PATCHLESS; then
823         confoptions="$confoptions --disable-server"
824     fi
825
826     local rpmbuildopt='-tb'
827     if $NORPM; then
828         rpmbuildopt='-tc'
829         echo NORPM mode. Only compiling.
830     fi
831
832     ( $(skeep_ldiskfs_rpm $TAG) ) || {
833
834         pushd ldiskfs > /dev/null || return 255
835
836         if !  ./configure --enable-dist; then
837             echo "failed to configure in ldiskfs"
838             popd >/dev/null # pushd ldiskfs
839             popd >/dev/null # pushd lustre
840             return 255
841         fi
842
843         if ! make dist 2>&1; then
844             popd >/dev/null # pushd ldiskfs
845             popd >/dev/null # pushd lustre
846             return 255
847         fi
848
849         #cp lustre-ldiskfs*.tar.gz $TOPDIR/SOURCES || \
850         #    fatal 1 "Could not copy lustre-ldiskfs*.tar.gz to $TOPDIR/SOURCES"
851
852         if ! $RPMBUILD $targets $rpmbuildopt lustre-ldiskfs*.tar.gz \
853             --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
854             --define "kdir $linux" \
855             ${linuxobj:+--define "kobjdir $linuxobj"} \
856             --define "_tmppath /var/tmp" \
857             --define "_topdir $TOPDIR" 2>&1; then
858             popd >/dev/null # pushd ldiskfs
859             popd >/dev/null # pushd lustre
860             return 255
861         fi
862
863         if $DO_SRC; then
864             if ! $RPMBUILD -ts lustre-ldiskfs*.tar.gz \
865                 --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
866                 --define "kdir $linux" \
867                 ${linuxobj:+--define "kobjdir $linuxobj"} \
868                 --define "_tmppath /var/tmp" \
869                 --define "_topdir $TOPDIR" 2>&1; then
870                 popd >/dev/null # pushd ldiskfs
871                 popd >/dev/null # pushd lustre
872                 return 255
873             fi
874         fi
875         popd >/dev/null # pushd ldiskfs
876
877         # tell lustre where ldiskfs is
878         # XXX - pointing to the RPM BUILD dir is a hack.  we need to flesh
879         #       out the ldiskfs RPM build so that it builds a
880         #       lustre-ldiskfs-devel RPM and install that and point lustre
881         #       to that instead
882         confoptions="$confoptions --with-ldiskfs=$(ls -d $TOPDIR/BUILD/lustre-ldiskfs-*)"
883     }
884
885     if $IOKITRPM; then
886         if ! build_iokit $rpmbuildopt; then
887             echo "failed to build lustre-iokit"
888             popd >/dev/null # pushd lustre
889             return 255
890         fi
891     fi
892
893     # convert the $PATCHLESS boolean to an empty/not-empty boolean
894     # as silly as this seems, it makes the syntax of the rpmbuild command
895     # simpler and not need an eval to deal with the quotes in the quotes
896     local is_patchless=""
897     if $PATCHLESS; then
898         is_patchless="yes"
899     fi
900
901     # ditto for the lustre-tests boolean
902     local lustre_tests=""
903     if ! $LUSTRE_TESTS; then
904         lustre_tests="no"
905     fi
906
907     $RPMBUILD $targets $rpmbuildopt "$LUSTRE" \
908         ${is_patchless:+--define "lustre_name lustre-client"} \
909         ${lustre_tests:+--define "build_lustre_tests 0"} \
910         ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
911         --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
912         --define "kdir $linux" \
913         ${linuxobj:+--define "kobjdir $linuxobj"} \
914         --define "_tmppath $TMPDIR" \
915         --define "_topdir $TOPDIR" 2>&1 || \
916         fatal 1 "Error building rpms for $BUILD_ARCHS."
917
918     if $DO_SRC; then
919         if ! $RPMBUILD -ts "$LUSTRE" \
920                  ${is_patchless:+--define "lustre_name lustre-client"} \
921                  ${lustre_tests:+--define "build_lustre_tests 0"} \
922                  ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
923                  --define "configure_args $confoptions ${CONFIGURE_FLAGS}" \
924                  --define "kdir $linux" \
925                  ${linuxobj:+--define "kobjdir $linuxobj"} \
926                  --define "_tmppath $TMPDIR" \
927                  --define "_topdir $TOPDIR" 2>&1; then
928             popd
929             return 255
930         fi
931     fi
932     popd >/dev/null
933
934 }
935
936 stage() {
937
938     [ "$STAGEDIR" ] || return 0
939
940     for arch in $BUILD_ARCHS; do
941         rpmdir="${STAGEDIR}/${CANONICAL_TARGET}-${arch}"
942         echo "${0##*/}: Copying RPMs into ${rpmdir}"
943         mkdir -p "${rpmdir}"
944         cp -v RPMS/${arch}/*.rpm "${rpmdir}"
945         if [ -d RPMS/noarch ]; then
946             cp -v RPMS/noarch/*.rpm "${rpmdir}"
947         fi
948     done
949
950     cp -v "$LUSTRE" "$STAGEDIR"
951
952 }
953
954 #check if we need to build separate ldiskfs RPM
955 skeep_ldiskfs_rpm() {
956     local tag="$1"
957
958     local skip=false
959
960     if ! $LDISKFSRPM; then
961         skip=true
962     elif $PATCHLESS; then
963         skip=true
964     else
965         for skiptag in $SKIPLDISKFSRPM; do
966             [[ $tag == $skiptag ]] && skip=true && break
967         done
968     fi
969
970     echo $skip
971
972 }
973
974 set_rpm_smp_type() {
975
976     local infact_arch="${TARGET_ARCH}"
977
978     RPMSMPTYPE=""
979     [ "$infact_arch" == "i586" ] && infact_arch="i686"
980
981     local smp_type
982     for smp_type in $SMP_ARCHS; do
983         [ $infact_arch == $smp_type ] && RPMSMPTYPE=smp && break
984     done
985
986     for smp_type in $BIGSMP_ARCHS; do
987         [ $infact_arch == $smp_type ] && RPMSMPTYPE=bigsmp && break
988     done
989
990     for smp_type in $PPC64_ARCHS; do
991         [ $infact_arch == $smp_type ] && RPMSMPTYPE=ppc64 && break
992     done
993
994     for smp_type in $DEFAULT_ARCHS; do
995         [ $infact_arch == $smp_type ] && RPMSMPTYPE=default && break
996     done
997
998 }
999
1000 # This function takes a linux source pool and digs out the linux release
1001 # from it
1002 find_linux_release() {
1003     local SRCDIR="$1"
1004
1005     local LINUXRELEASEHEADER=$SRCDIR/include/linux/version.h
1006     if [ -s $SRCDIR/include/linux/utsrelease.h ]; then
1007         LINUXRELEASEHEADER=$SRCDIR/include/linux/utsrelease.h
1008     fi
1009
1010     sed -ne 's/#define UTS_RELEASE "\(.*\)"$/\1/p' $LINUXRELEASEHEADER
1011
1012 }
1013
1014 # unpack kernel(/source/devel) RPM
1015 #
1016 # This function and it's setting of $LINUX and $LINUXOBJ is a total hack that
1017 # needs to completely refactored.  It completely ingores that $BUILD_ARCHS may
1018 # contain a list of arches for which rpmbuild commands (including the one for
1019 # lustre itself)
1020 unpack_linux_devel_rpm() {
1021     local kernelrpm="${1}"
1022
1023     [ -f "$kernelrpm" ] || return 255
1024     [ -d $TOPDIR/reused ] || mkdir $TOPDIR/reused || return 255
1025
1026     pushd $TOPDIR/reused &>/dev/null || return 255
1027
1028     if ! rpm2cpio < "$kernelrpm" | cpio -id > /dev/null 2>&1; then
1029         return 255
1030     fi
1031
1032     # call a distro specific hook, if available
1033     if type -p unpack_linux_devel_rpm-$DISTRO; then
1034         if ! unpack_linux_devel_rpm-$DISTRO "$kernelrpm"; then
1035             return 255
1036         fi
1037     fi
1038
1039     popd &>/dev/null
1040
1041     find_linux_devel_paths $TOPDIR/reused
1042
1043     return 0
1044
1045 }
1046
1047 build_kernel_ib() {
1048     local linux="$1"
1049
1050     # build kernel-ib{,-devel}
1051     local K_SRC="K_SRC"
1052     # ofed 1.3 had a bug in the rpm spec
1053     if [ "$OFED_VERSION" = "1.3" ]; then
1054         K_SRC="KSRC"
1055     fi
1056
1057     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-madeye-mod"
1058     local OFED_HARDWARE="--with-mthca-mod --with-mlx4-mod --with-mlx4_en-mod --with-cxgb3-mod --with-nes-mod"
1059     # some I/B drivers are architecture dependent and kernel-ib's configure
1060     # does not figure it out for us ~sigh~
1061     case "$TARGET_ARCH" in
1062         ppc64)
1063             OFED_HARDWARE="$OFED_HARDWARE --with-ehca-mod"
1064             ;;
1065     esac
1066     # we're no longer shipping the OFED iSCSI
1067     #OFED_ISCSI="--with-srp-mod --with-srp-target-mod"
1068     ## ISER module has no backport support as of OFED 1.5 (i.e. only builds on
1069     ##kernels >= 2.6.30)
1070     #if [[ $OFED_VERSION = 1.[0-4]* ]]; then
1071     #   OFED_ISCSI="$OFED_ISCSI --with-iser-mod"
1072     #fi
1073
1074     # assume we are just rebuilding the SRPM
1075     local BUILD_TYPE=${BUILD_TYPE:-"--rebuild"}
1076     local SOURCE="${TOPDIR}/OFED/SRPMS/ofa_kernel-*.src.rpm"
1077
1078     # but switch to building from the SPEC if we need to apply patches
1079     if ls ${TOPDIR}/lustre/build/patches/ofed/* >/dev/null; then
1080         BUILD_TYPE="-bb"
1081         rpm --define "_topdir ${TOPDIR}" -ivh $SOURCE
1082         SOURCE="${TOPDIR}/SPECS/ofa_kernel.spec"
1083         local file ed_fragment1 ed_fragment2 n=1
1084         for file in $(ls ${TOPDIR}/lustre/build/patches/ofed/*.patch); do
1085             ed_fragment1="$ed_fragment1
1086 Patch$n: ${file%%*/}"
1087             ed_fragment2="$ed_fragment2
1088 %patch$n -p0"
1089             cp $file ${TOPDIR}/SOURCES
1090             let n=$n+1
1091         done
1092         for file in $(ls ${TOPDIR}/lustre/build/patches/ofed/*.ed); do
1093             ed_fragment3="$ed_fragment3
1094 $(cat $file)"
1095             let n=$n+1
1096         done
1097
1098         if [ $n -gt 1 ]; then
1099             ed $SOURCE <<EOF
1100 /^Source: /a
1101 $ed_fragment1
1102 .
1103 /^%setup /a
1104 $ed_fragment2
1105 .
1106 $ed_fragment3
1107 wq
1108 EOF
1109         fi
1110     fi
1111
1112     local linuxrelease=$(find_linux_release "$linux")
1113     if ! $RPMBUILD $BUILD_TYPE --define 'build_kernel_ib 1' --define 'build_kernel_ib_devel 1' \
1114                   ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
1115                   --define "_topdir ${TOPDIR}" --target ${TARGET_ARCH} \
1116                   --define "KVERSION ${linuxrelease}" \
1117                   --define "$K_SRC ${linux}" \
1118                   --define "LIB_MOD_DIR /lib/modules/${linuxrelease}/updates" \
1119                   ${OFA_KERNEL_RELEASE:+--define "_release $OFA_KERNEL_RELEASE"} \
1120                   --define "configure_options --without-quilt $OFED_CORE $OFED_HARDWARE $OFED_ISCSI" \
1121                   ${SOURCE} 2>&1; then
1122         fatal 1 "Error building kernel-ib"
1123     fi
1124
1125 }
1126
1127 store_for_reuse() {
1128     local articles="$1"
1129     local module="$2"
1130     local location="$3"
1131     local signature="$4"
1132     local use_links="$5"
1133
1134     local linkflag=""
1135     if $use_links; then
1136         linkflag="l"
1137     fi
1138
1139     local default_iface=$(/sbin/ip route get 192.1.1.1 | sed -ne 's/.* dev \(.*\)  * src .*/\1/p')
1140     if [ -z "$default_iface" ]; then
1141         fatal 1 "Failed to determine the default route interface"
1142     fi
1143     local unique_id=$(/sbin/ip addr show dev $default_iface | sed -ne '/ inet /s/ *inet \(.*\)\/.*/\1/p' | head -1)
1144     if [ -z "$unique_id" ]; then
1145         fatal 1 "Failed to determine a unique id from interface $default_interface"
1146     fi
1147
1148     local finallocation="$location"/"$signature"/"$module"
1149     location="$location"/"$signature-${unique_id}"/"$module"
1150     mkdir -p "$location"
1151     # the cleanup script removes any directory that doesn't have a
1152     # .lastused, so let's try to prevent that as soon as we can
1153     # this solution still slightly racy with the cleanup script
1154     # but the race is a lot tighter now
1155     touch -t 197001010000 "$location/.lastused"
1156     ## use eval/echo here to make sure shell expansions are performed
1157     #if ! cp -a${linkflag} $(eval echo $articles) "$location"; then
1158     local article
1159     for article in $(eval echo $articles); do
1160         if ! cp -a${linkflag} "$article" "$location"; then
1161             error "Failed to copy \"$article\" to \"$location\" in store_for_reuse()"
1162             # rename the cache location so that it's not cached
1163             # product, but is around for analysis
1164             mv "$location"{,-bad-$(date +%s)} ||
1165                 error "failed to clean up a failed cache attempt" \
1166                       "in \"$location\" -- manual cleanup will be" \
1167                       "necessary"
1168             return 1
1169         fi
1170     done
1171
1172     # flag the cache as complete (i.e. in case lbuild was previously
1173     # interrupted while caching)
1174     touch "$location/.lastused"
1175
1176     # put the temporary location into the final location
1177     # (last one wins)
1178     mkdir -p "${finallocation%/*}"
1179     mv "$location" "$finallocation"
1180     rmdir "${location%/*}"
1181     return 0
1182
1183 }
1184
1185 reuse() {
1186     local module="$1"
1187     local dest="$2"
1188     local use_links="${3:-false}"
1189     local signature="$4"
1190
1191     if [ -n "$REUSEBUILD" ] && [ -d "$REUSEBUILD/$signature/$module" ]; then
1192         if [ ! -f "$REUSEBUILD/$signature/$module/.lastused" ]; then
1193             # the .lastused flag is populated at the end of the caching to
1194             # signal that the caching was completed.  if that flag is not
1195             # there, then the cache is invalid (and should be removed in fact)
1196             mv "$REUSEBUILD/$signature/$module"{,-bad-$(date +%s)} ||
1197                 fatal 1 "failed to clean up a bad cache in location $REUSEBUILD/$signature/$module\" -- manual cleanup will be necessary"
1198             return 1
1199         fi
1200
1201         # so that we know how stale this entry is
1202         touch $REUSEBUILD/$signature/$module/.lastused
1203
1204         if $use_links; then
1205             if ls $REUSEBUILD/$signature/$module/* >/dev/null 2>&1; then
1206                 cp -al $REUSEBUILD/$signature/$module/* $dest/
1207             fi
1208         else
1209             # copying is pretty heavy
1210             # cp -a $REUSEBUILD/$signature/$module/* $dest/
1211             # do some creative symlinking instead
1212             local dir
1213             for dir in BUILD SRPMS SPECS; do
1214                 if ls $REUSEBUILD/$signature/$module/$dir/* >/dev/null 2>&1; then
1215                     ln -s $REUSEBUILD/$signature/$module/$dir/* $dest/$dir
1216                 fi
1217             done
1218             # sources have to be copied by file because we need SOURCES to
1219             # be a dir we can write into
1220 # could overrun ls's arg list here
1221             #ls $REUSEBUILD/$signature/$module/SOURCES/* |
1222             find $REUSEBUILD/$signature/$module/SOURCES/ -type f |
1223                 xargs ln -t $dest/SOURCES -s
1224
1225             # same for RPMS/* dirs
1226 # could overrun ls's arg list here
1227             #ls $REUSEBUILD/$signature/$module/RPMS/$TARGET_ARCH/* |
1228             local dir
1229             for dir in $REUSEBUILD/$signature/$module/RPMS/*; do
1230                 mkdir -p $dest/RPMS/${dir##*/}
1231                 find $dir -type f |
1232                   xargs ln -t $dest/RPMS/${dir##*/} -s
1233             done
1234         fi
1235         return 0
1236     else
1237         return 1
1238     fi
1239 }
1240
1241 basearch() {
1242     local arch="$1"
1243
1244     if [[ $arch = i[3456]86 ]]; then
1245         echo "i386"
1246     else
1247         echo "$arch"
1248     fi
1249
1250 }
1251
1252 build_kernel_with_srpm() {
1253     local outfd=$1
1254
1255     if [ -z "$outfd" ] || [ $outfd = 1 ]; then
1256         fatal 1 "You must supply a file descriptor to ${FUNCNAME[0]} and it cannot be 1"
1257     fi
1258
1259     # need to generate the patch for this target
1260     do_patch_linux false >&${outfd}    # sets global $FULL_PATCH (yeah, yuck)
1261
1262     # get an md5sum of the kernel patch + config for reuse check
1263     # XXX really, there needs to be a signature and a CONFIG_FILE per arch
1264     #     in BUILD_ARCHS
1265     local release_str
1266     if $RELEASE; then
1267         local release_str="RELEASE=$RELEASE\n"
1268     fi
1269
1270     if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
1271         local REUSE_SIGNATURE=$({ echo -en $release_str;
1272                                   echo $BUILD_GEN;
1273                                   cat $CONFIG_FILE $TARGET_FILE $FULL_PATCH; } |
1274                                 md5sum | cut -d" " -f1)
1275         # see if we can link to the reuse pool
1276         # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
1277         #       "library"
1278         local CAN_LINK_FOR_REUSE=false
1279         touch $REUSEBUILD/$$
1280         if cp -al $REUSEBUILD/$$ $TOPDIR/ 2>/dev/null; then
1281             CAN_LINK_FOR_REUSE=true
1282         fi
1283         rm $REUSEBUILD/$$
1284     fi
1285
1286     # the extra version string to use for the kernel (which might be a reused
1287     # kernel, remember)
1288     local kernel_extra_version=""
1289     if ! $USE_BUILD_CACHE || ! reuse kernel "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
1290                                    "$REUSE_SIGNATURE"; then
1291         # nothing cached, build from scratch
1292         if [ ! -r "$KERNELDIR/$KERNEL_SRPM" ]; then
1293             echo "Downloading kernel SRPM" >&${outfd}
1294             download_srpm "$CANONICAL_TARGET" "$KERNEL_SRPM" >&${outfd}
1295         fi
1296
1297         if ! rpm -ivh $KERNELDIR/$KERNEL_SRPM \
1298                   --define "_topdir $TOPDIR" >&${outfd} 2>&1; then
1299             # should we clean this up or leave it for analysis?
1300             #rm -rf $RPMTOPDIR
1301             fatal 1 "Error installing kernel SRPM."
1302         fi
1303
1304         # put the Lustre kernel patch into the RPM build tree
1305         cp $FULL_PATCH $TOPDIR/SOURCES/linux-${lnxmaj}-lustre.patch
1306         prepare_and_build_srpm >&${outfd} ||
1307             fatal 1 "failed to prepare_and_build_srpm"
1308
1309         if [ -z "$REUSE_SIGNATURE" ]; then
1310             echo "No reuse signature was caculated so not storing the built kernel" >&${outfd}
1311         else
1312             # store the resulting kernel RPM build tree for future use
1313             echo "Storing the built kernel for future reuse" >&${outfd}
1314             if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,SRPMS,RPMS}" \
1315                                  "kernel" "$REUSEBUILD" "$REUSE_SIGNATURE" \
1316                                  "$CAN_LINK_FOR_REUSE"; then
1317                 error "Failed to store kernel RPMS for reuse"
1318                 echo "unknown" >&${outfd}
1319                 return 1
1320             fi
1321         fi
1322     fi  # build reuse
1323
1324     # figure out the EXTRA_VERSION of the kernel we built or are re-using
1325     local KERNEL_RPM
1326     if ! KERNEL_RPM=$(find_rpm "$TOPDIR/RPMS/$TARGET_ARCH/" provides "^kernel ="); then
1327         fatal 1 "Failed to find a kernel RPM in $TOPDIR/RPMS/$TARGET_ARCH/"
1328     fi
1329     kernel_extra_version=$(rpm -q --queryformat "%{RELEASE}" -p $TOPDIR/RPMS/$TARGET_ARCH/$KERNEL_RPM)
1330
1331     # should now have the following RPMs
1332     # $TOPDIR/RPMS/$arch/kernel-lustre-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1333     # $TOPDIR/RPMS/$arch/kernel-lustre-devel-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1334     # $TOPDIR/RPMS/$arch/kernel-lustre-headers-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1335     # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-common-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1336     # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1337
1338     echo $kernel_extra_version
1339     return 0
1340
1341 }
1342
1343 # build OFED
1344 # globals used:
1345 #    TOPDIR
1346 #    REUSEBUILD, USE_BUILD_CACHE
1347 #    CONFIGURE_FLAGS
1348
1349 build_ofed() {
1350     local linux="$1"
1351     local ofed_version="$2"
1352
1353     # if an ofed version is given, then it means use OFED proper,
1354     # not any vendor specific "inkernel" version
1355     if [ -z "$ofed_version" ]; then
1356         return 0
1357     fi
1358
1359     if [ "$ofed_version" = "inkernel" ]; then
1360         # see if there is a distro specific override for this and use
1361         # that if it exists
1362         # XXX we need to better integrate a distro specific override with
1363         #     the rest of this function so that all of the reuse cache
1364         #     stuff is leveraged given that 80% of this function is reuse
1365         if type -p build_ofed-${DISTRO}; then
1366             local ofed_location
1367             ofed_location=$(build_ofed-${DISTRO} ${STDOUT})
1368             local rc=${PIPESTATUS[0]}
1369             CONFIGURE_FLAGS="--with-o2ib=${ofed_location} ${CONFIGURE_FLAGS}"
1370             return $rc
1371         else
1372             return 0
1373         fi
1374     fi
1375
1376     # build kernel-ib
1377     if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
1378         local REUSE_SIGNATURE=$({ echo "$ofed_version";
1379                                   echo "$(find_linux_release ${linux})";
1380                                   cat "${linux}/include/linux/autoconf.h"; } |
1381                                 md5sum | cut -d" " -f1)
1382         # see if we can link to the reuse pool
1383         # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
1384         #       "library"
1385         local CAN_LINK_FOR_REUSE=false
1386         touch $REUSEBUILD/$$
1387         if cp -al $REUSEBUILD/$$ $TOPDIR/; then
1388             CAN_LINK_FOR_REUSE=true
1389         fi
1390         rm $REUSEBUILD/$$
1391     fi
1392
1393     if ! $USE_BUILD_CACHE || ! reuse ofed "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
1394                                    "$REUSE_SIGNATURE"; then
1395         if [ -n "$REUSE_SIGNATURE" ]; then
1396             # stash away the existing built articles for a moment
1397             mkdir bak
1398             mv {BUILD,{S,}RPMS,S{OURCE,PEC}S} bak
1399             function mv_back {
1400                 pushd bak
1401                 find . | cpio -pudlm ..
1402                 popd
1403                 rm -rf bak
1404             }
1405             create_rpmbuild_dirs
1406         fi
1407         # build it
1408         build_kernel_ib "${linux}"
1409
1410         if [ -z "$REUSE_SIGNATURE" ]; then
1411             echo "No reuse signature was caculated so not storing the built ofed"
1412         else
1413             # store the resulting RPM build tree for future use
1414             echo "Storing the built ofed for future reuse"
1415             if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,BUILD,SRPMS,RPMS}" \
1416                                  "ofed" "$REUSEBUILD" "$REUSE_SIGNATURE" \
1417                                  "$CAN_LINK_FOR_REUSE"; then
1418                 error "Failed to store OFED RPMS for reuse"
1419                 mv_back
1420                 return 1
1421             fi
1422             # put the stuff we stashed away back
1423             mv_back
1424         fi
1425     fi
1426
1427     pushd "$TOPDIR" >/dev/null
1428     rm -rf kernel-ib-devel
1429     mkdir kernel-ib-devel
1430     cd kernel-ib-devel
1431     # the actual ofed RPMs don't have the -rc$n or -$date string appened that
1432     # might be present on the file
1433     local linuxrelease=$(find_linux_release "$linux")
1434     ofed_version=$(echo $ofed_version |
1435                    sed -re 's/-(20[0-9]{6,6}-[0-9]{4,4}|rc[0-9]*)$//')
1436     local rpm=$(ls $TOPDIR/RPMS/*/kernel-ib-devel-${ofed_version}-${linuxrelease//-/_}.*.rpm)
1437     if ! rpm2cpio < $rpm | cpio -id; then
1438         fatal 1 "could not unpack the kernel-ib-devel rpm."
1439     fi
1440     CONFIGURE_FLAGS="--with-o2ib=$(pwd)/usr/src/ofa_kernel ${CONFIGURE_FLAGS}"
1441     popd >/dev/null
1442
1443 }
1444
1445 build_with_srpm() {
1446
1447     if ! $PATCHLESS; then
1448         local kernel_extra_version
1449         if ! kernel_extra_version=$(build_kernel_with_srpm ${STDOUT}); then
1450             fatal 1 "Failed to build the kernel from it's SRPM"
1451         fi
1452
1453         for arch in $BUILD_ARCHS; do
1454             local kernel_devel_rpm
1455             if ! kernel_devel_rpm=$(find_rpm "$TOPDIR/RPMS/$arch/" provides "^$(devel_kernel_name $KERNEL_LUSTRE_NAMING) ="); then
1456                 fatal 1 "Failed to find a kernel development RPM in $TOPDIR/RPMS/$arch/"
1457             fi
1458
1459             # install the -devel RPM in preparation for modules builds
1460             if ! lnxrel="$kernel_extra_version" unpack_linux_devel_rpm \
1461                            "$TOPDIR/RPMS/$arch/$kernel_devel_rpm"; then
1462                 fatal 1 "Could not find the Linux tree in $TOPDIR/RPMS/$arch/$kernel_devel_rpm"
1463             fi
1464         done
1465     else
1466         # need to find and unpack the vendor's own kernel-devel for patchless
1467         # client build
1468         local kernelrpm
1469         if ! kernelrpm=$(find_linux_rpm "-$DEVEL_KERNEL_TYPE"); then
1470             fatal 1 "Could not find the kernel-$DEVEL_KERNEL_TYPE RPM in ${KERNELRPMSBASE}/${lnxmaj}/${DISTRO}"
1471         fi
1472         if ! lnxrel="$lnxrel" unpack_linux_devel_rpm "$kernelrpm" "-"; then
1473             fatal 1 "Could not find the Linux tree in $kernelrpm"
1474         fi
1475     fi
1476
1477     # ~sigh~  have to make copies of and modify some of the rpm
1478     # infrastructure files so that find-requires can find our unpacked
1479     # kernel-devel artifacts
1480     cp $RPM_HELPERS_DIR/{symset-table,find-requires{,.ksyms}} .
1481     FIND_REQUIRES="$(pwd)/find-requires"
1482     chmod 755 {symset-table,find-requires{,.ksyms}}
1483     local tmp="$(pwd)"
1484     tmp="${tmp//\//\\/}"
1485     ed find-requires <<EOF
1486 1a
1487 set -x
1488 .
1489 /|.*find-requires.ksyms/s/|/| bash -x/
1490 g/ [^ ]*\/\(find-requires\.ksyms\)/s// $tmp\/\1/g
1491 wq
1492 EOF
1493     ed find-requires.ksyms <<EOF
1494 1a
1495 set -x
1496 .
1497 g/\/.*\/\(symset-table\)/s//$tmp\/\1/g
1498 wq
1499 EOF
1500     ed symset-table <<EOF
1501 1a
1502 set -x
1503 .
1504 g/\(\/boot\/\)/s//$tmp\/reused\1/g
1505 g/\(\/usr\/src\/kernels\/\)/s//$tmp\/reused\1/g
1506 wq
1507 EOF
1508
1509     build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
1510         fatal 1 "error building OFED"
1511
1512     # now build Lustre
1513     if build_lustre "$LINUX" "$LINUXOBJ"; then
1514         # the build worked.  resolve any symlinked files (i.e. from reuse)
1515         # in RPMS/$arch to real files so that that that huge mess of
1516         # complication known as LTS can copy them yet somewhere else.
1517         # is it any wonder this whole process is so damn so?  anyone ever
1518         # heard of hardlinks?  it's this cool new thing that allows you save
1519         # tons of time and space by creating... well you can go read about
1520         # them if you have not heard about them yet.
1521         # can i say how much the implemenation of all of this really impedes
1522         # RPM reuse?
1523         local dir
1524         for dir in RPMS/*; do
1525             pushd $dir
1526             for file in $(ls); do
1527                 if [ -h $file ]; then
1528                     cp $file foo
1529                     mv foo $file
1530                 fi
1531             done
1532             popd
1533         done
1534         # also, for i?86, make sure all of the RPMs are in RPMS/$TARGET_ARCH
1535         # as that's where LTS expects to find them
1536         for dir in RPMS/*; do
1537             if [ $dir = RPMS/$TARGET_ARCH ]; then
1538                 continue
1539             fi
1540             pushd $dir
1541             local files=$(ls)
1542             if [ -n "$files" ]; then
1543                 cp -al $files ../$TARGET_ARCH
1544             fi
1545             popd
1546         done
1547     else
1548         return 1
1549     fi
1550
1551 }
1552
1553 create_rpmbuild_dirs() {
1554
1555     [ -d RPMS ] || mkdir RPMS
1556     for arch in $BUILD_ARCHS; do
1557         if [[ $arch = i?86 ]]; then
1558             # some stupidity in the sles11 kernel spec requires an RPMS/i386
1559             # even if the target arch is i686
1560             [ -d RPMS/i386 ] || mkdir RPMS/i386
1561         fi
1562         [ -d RPMS/$arch ] || mkdir RPMS/$arch
1563     done
1564     [ -d BUILD ] || mkdir BUILD
1565     [ -d SOURCES ] || mkdir SOURCES
1566     [ -d SPECS ] || mkdir SPECS
1567     [ -d SRPMS ] || mkdir SRPMS
1568
1569 }
1570
1571 new_list() {
1572
1573     echo ""
1574
1575 }
1576
1577 add_list() {
1578     local list="$1"
1579     local item="$2"
1580
1581     echo "$list $item"
1582
1583 }
1584
1585 is_list_member() {
1586     local list="$1"
1587     local item="$2"
1588
1589     [[ $list\  == *\ $item\ * ]]
1590
1591 }
1592
1593 #########################################################################
1594 # Generate a backtrace through the call stack.
1595 #
1596 # Input: None
1597 # Output: None
1598 #########################################################################
1599 backtrace() {
1600     local strip=${1:-1}
1601
1602     local funcname="" sourcefile="" lineno="" n
1603
1604     echo "Call stack: (most recent first)"
1605     for (( n = $strip ; n < ${#FUNCNAME[@]} ; ++n )) ; do
1606         funcname=${FUNCNAME[$n - 1]}
1607         sourcefile=$(basename ${BASH_SOURCE[$n]})
1608         lineno=${BASH_LINENO[$n - 1]}
1609         if [ $n = 1 ]; then
1610             let lineno-=11
1611         fi
1612         # Display function arguments
1613         if [[ ! -z "${BASH_ARGV[@]}" ]]; then
1614             local args newarg j p=0
1615             for (( j = ${BASH_ARGC[$n - 1]}; j > 0; j-- )); do
1616                 newarg=${BASH_ARGV[$j + $p - 1]}
1617                 args="${args:+${args} }'${newarg}'"
1618             done
1619             let p+=${BASH_ARGC[$n - 1]}
1620         fi
1621         echo "  ${funcname} ${args:+${args} }at ${sourcefile}:${lineno}"
1622     done
1623
1624     echo
1625     echo "BEGIN BACKTRACE"
1626
1627     #echo ${BASH_LINENO[*]}
1628     #echo ${BASH_SOURCE[*]}
1629     #echo ${FUNCNAME[*]}
1630     local i=$((${#FUNCNAME[@]} - 1))
1631     while [ $i -ge 0 ]; do
1632         local lineno=${BASH_LINENO[$i]}
1633         if [ $i = 0 ]; then
1634             let lineno-=11
1635         fi
1636         local SOURCELINE="${BASH_SOURCE[$i + 1]}:${lineno}"
1637         # Can't figure out how to get function args from other frames...
1638         local FUNCTION="${FUNCNAME[$i]}()"
1639         echo "$SOURCELINE:$FUNCTION"
1640         i=$((i - 1))
1641     done
1642
1643     echo "END BACKTRACE"
1644
1645     echo $BACKTRACE
1646
1647 }
1648
1649 seen_list=$(new_list)
1650 trap 'set +x;
1651 echo "An unexpected error has occurred at ${BASH_SOURCE[0]##*/}:$((LINENO-1)).
1652 Unfortunately the above line number in the message may or may not be correct,
1653 but details have been send to the lbuild maintainer.  Attempting to continue."; (echo "Untrapped error"
1654 echo
1655 # have we seen this one
1656 echo "checking seen list for ${BASH_SOURCE[0]}:${BASH_LINENO[0]}"
1657
1658 if is_list_member "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}"; then
1659   echo "seen this one already"
1660 else
1661   seen_list=$(add_list "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}")
1662 fi
1663 backtrace
1664 echo
1665 echo "Environment:"
1666 set
1667 ) | mail -s "Untrapped error at ${BASH_SOURCE[0]##*/}:$((LINENO-15)) on $HOSTNAME" brian@whamcloud.com >&2; set $xtrace' ERR
1668 set -E
1669
1670 [ -r ~/.lbuildrc ] && . ~/.lbuildrc
1671
1672 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 -- "$@")
1673
1674 if [ $? != 0 ]; then
1675     usage 1
1676 fi
1677
1678 eval set -- "$options"
1679
1680 while [ "$1" ]; do
1681     case "$1" in
1682         '')
1683             usage 1
1684             ;;
1685         --ccache)
1686             CCACHE='ccache'
1687             shift
1688             ;;
1689         -d)
1690             CVSROOT=$2
1691             shift 2
1692             ;;
1693         -D)
1694             DATE=$2
1695             shift 2
1696             ;;
1697         --external-patches)
1698             EXTERNAL_PATCHES=$2
1699             shift 2
1700             ;;
1701         --extraversion)
1702             EXTRA_VERSION=$2
1703             shift 2
1704             ;;
1705         --help | -h)
1706             usage 0
1707             ;;
1708         --kerneldir)
1709             KERNELDIR=$2
1710             shift 2
1711             ;;
1712         --kerneltree)
1713             if ! KERNELTREE=$(canon_path "$2"); then
1714                 fatal 1 "Could not determine the canonical location of $2"
1715             fi
1716             shift 2
1717             ;;
1718         --linux | --with-linux)
1719             if ! LINUX=$(canon_path "$2"); then
1720                 fatal 1 "Could not determine the canonical location of $2"
1721             fi
1722             shift 2
1723             ;;
1724         --distro)
1725             DISTRO=$2
1726             shift 2
1727             ;;
1728         --reuserpm)
1729             REUSERPM=$2
1730             shift 2
1731             ;;
1732         --reusebuild)
1733             if ! REUSEBUILD=$(canon_path "$2"); then
1734                 fatal 1 "Could not determine the canonical location of $2"
1735             fi
1736             shift 2
1737             ;;
1738         --norpm)
1739             NORPM=true
1740             shift
1741             ;;
1742         --ldiskfs)
1743             LDISKFSRPM=true
1744             shift
1745             ;;
1746         --noiokit)
1747             IOKITRPM=false
1748             shift
1749             ;;
1750         --patchless)
1751             PATCHLESS=true
1752             shift
1753             ;;
1754         --kernelrpm)
1755             if ! KERNELRPMSBASE=$(canon_path "$2"); then
1756                 fatal 1 "Could not determine the canonical location of $2"
1757             fi
1758             shift 2
1759             ;;
1760         --timestamp)
1761             TIMESTAMP=$2
1762             shift 2
1763             ;;
1764         --lustre)
1765             if ! LUSTRE=$(canon_filepath "$2"); then
1766                 fatal 1 "Could not determine the canonical location of $2"
1767             fi
1768             shift 2
1769             ;;
1770         --nodownload)
1771             DOWNLOAD=false
1772             shift 1
1773             ;;
1774         --nosrc)
1775             DO_SRC=false
1776             shift 1
1777             ;;
1778         --ofed-version)
1779             OFED_VERSION="$2"
1780             shift 2
1781             ;;
1782         --publish)
1783             shift
1784             ;;
1785         --release)
1786             RELEASE=true
1787             shift
1788             ;;
1789         --src)
1790             DO_SRC=true
1791             shift 1
1792             ;;
1793         --stage)
1794             STAGEDIR=$2
1795             shift 2
1796             ;;
1797         --tag)
1798             TAG=$2
1799             shift 2
1800             ;;
1801         --target)
1802             TARGET=$2
1803             shift 2
1804             ;;
1805         --target-archs)
1806             TARGET_ARCHS=$2
1807             shift 2
1808             ;;
1809         --disable-datestamp)
1810             USE_DATESTAMP=
1811             shift
1812             ;;
1813         --xen)
1814             XEN=true
1815             shift
1816             ;;
1817         --set-value)
1818             eval $2
1819             shift 2
1820             ;;
1821         --)
1822             shift
1823             # there are actually some lustre configure flags that we need to
1824             # handle ourselves (but we still give them to configure)
1825             if [[ \ $@\  == *\ --disable-tests\ * ]]; then
1826                 LUSTRE_TESTS=false
1827             fi
1828             CONFIGURE_FLAGS=$@
1829             CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-liblustre --enable-liblustre-tests"
1830             break
1831             ;;
1832         *)
1833             usage 1 "Unrecognized option: $1"
1834             ;;
1835     esac
1836 done
1837
1838 check_options
1839
1840 unpack_lustre
1841
1842 # XXX - should we _always_ get the buildid from the META file?  what are the
1843 # other (i.e. non-lustre-tarball use cases of lbuild)?
1844 BUILDID=$(sed -ne '/^BUILDID =/s/.*= *//p' lustre/META)
1845
1846 load_target
1847
1848 if [ -n "$OFED_VERSION" -a "$OFED_VERSION" != "inkernel" ]; then
1849     download_ofed
1850     unpack_ofed || fatal 1 "Error unpacking OFED tarball"
1851 fi
1852
1853 # make sure the RPM build environment is set up
1854 create_rpmbuild_dirs
1855
1856 # if an unpacked kernel source tree was given on the command line
1857 # just build lustre with it (nothing distro kernel specific here)
1858 if [ -n "$LINUX" ]; then
1859     build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
1860         fatal 1 "error building OFED"
1861     build_lustre "$LINUX" "$LINUXOBJ"
1862 else
1863     if [ -f "${0%/*}/lbuild-$DISTRO" ]; then
1864         source ${0%/*}/lbuild-$DISTRO
1865
1866         build_with_srpm || fatal 1 "Failed to build_with_srpm"
1867     else
1868         EXTRA_VERSION_DELIMITER=${EXTRA_VERSION_DELIMITER:-"-"}
1869         source ${0%/*}/lbuild.old_school
1870
1871         old_school_download_kernel
1872
1873         build_success=false
1874         if $PATCHLESS; then
1875             patchless_build_sequence && build_success=true
1876         else
1877             [ "$DISTRO" = "sles9" ] && build_sequence_rpm_reuse && build_success=true
1878             if ! $build_success; then
1879                 build_sequence_reuse && build_success=true
1880                 if ! $build_success; then
1881                     build_sequence && build_success=true
1882                     if $build_success; then
1883                         store_for_reuse || echo "Cannot store for future reuse"
1884                     fi
1885                 fi
1886             fi
1887         fi
1888         ( $build_success ) || fatal 1 "Cannot build lustre"
1889     fi
1890 fi
1891
1892 stage