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