Whamcloud - gitweb
LU-1479 build: enable srp initiator module with lbuild
[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 target
1067     #OFED_ISCSI="--with-srp-mod --with-srp-target-mod"
1068     OFED_ISCSI="--with-srp-mod"
1069     ## ISER module has no backport support as of OFED 1.5 (i.e. only builds on
1070     ##kernels >= 2.6.30)
1071     #if [[ $OFED_VERSION = 1.[0-4]* ]]; then
1072     #   OFED_ISCSI="$OFED_ISCSI --with-iser-mod"
1073     #fi
1074
1075     # assume we are just rebuilding the SRPM
1076     local BUILD_TYPE=${BUILD_TYPE:-"--rebuild"}
1077     local SOURCE="${TOPDIR}/OFED/SRPMS/ofa_kernel-*.src.rpm"
1078
1079     # but switch to building from the SPEC if we need to apply patches
1080     if ls ${TOPDIR}/lustre/build/patches/ofed/* >/dev/null; then
1081         BUILD_TYPE="-bb"
1082         rpm --define "_topdir ${TOPDIR}" -ivh $SOURCE
1083         SOURCE="${TOPDIR}/SPECS/ofa_kernel.spec"
1084         local file ed_fragment1 ed_fragment2 n=1
1085         for file in $(ls ${TOPDIR}/lustre/build/patches/ofed/*.patch); do
1086             ed_fragment1="$ed_fragment1
1087 Patch$n: ${file%%*/}"
1088             ed_fragment2="$ed_fragment2
1089 %patch$n -p0"
1090             cp $file ${TOPDIR}/SOURCES
1091             let n=$n+1
1092         done
1093         for file in $(ls ${TOPDIR}/lustre/build/patches/ofed/*.ed); do
1094             ed_fragment3="$ed_fragment3
1095 $(cat $file)"
1096             let n=$n+1
1097         done
1098
1099         if [ $n -gt 1 ]; then
1100             ed $SOURCE <<EOF
1101 /^Source: /a
1102 $ed_fragment1
1103 .
1104 /^%setup /a
1105 $ed_fragment2
1106 .
1107 $ed_fragment3
1108 wq
1109 EOF
1110         fi
1111     fi
1112
1113     local linuxrelease=$(find_linux_release "$linux")
1114     if ! $RPMBUILD $BUILD_TYPE --define 'build_kernel_ib 1' --define 'build_kernel_ib_devel 1' \
1115                   ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
1116                   --define "_topdir ${TOPDIR}" --target ${TARGET_ARCH} \
1117                   --define "KVERSION ${linuxrelease}" \
1118                   --define "$K_SRC ${linux}" \
1119                   --define "LIB_MOD_DIR /lib/modules/${linuxrelease}/updates" \
1120                   ${OFA_KERNEL_RELEASE:+--define "_release $OFA_KERNEL_RELEASE"} \
1121                   --define "configure_options --without-quilt $OFED_CORE $OFED_HARDWARE $OFED_ISCSI" \
1122                   ${SOURCE} 2>&1; then
1123         fatal 1 "Error building kernel-ib"
1124     fi
1125
1126 }
1127
1128 store_for_reuse() {
1129     local articles="$1"
1130     local module="$2"
1131     local location="$3"
1132     local signature="$4"
1133     local use_links="$5"
1134
1135     local linkflag=""
1136     if $use_links; then
1137         linkflag="l"
1138     fi
1139
1140     local default_iface=$(/sbin/ip route get 192.1.1.1 | sed -ne 's/.* dev \(.*\)  * src .*/\1/p')
1141     if [ -z "$default_iface" ]; then
1142         fatal 1 "Failed to determine the default route interface"
1143     fi
1144     local unique_id=$(/sbin/ip addr show dev $default_iface | sed -ne '/ inet /s/ *inet \(.*\)\/.*/\1/p' | head -1)
1145     if [ -z "$unique_id" ]; then
1146         fatal 1 "Failed to determine a unique id from interface $default_interface"
1147     fi
1148
1149     local finallocation="$location"/"$signature"/"$module"
1150     location="$location"/"$signature-${unique_id}"/"$module"
1151     mkdir -p "$location"
1152     # the cleanup script removes any directory that doesn't have a
1153     # .lastused, so let's try to prevent that as soon as we can
1154     # this solution still slightly racy with the cleanup script
1155     # but the race is a lot tighter now
1156     touch -t 197001010000 "$location/.lastused"
1157     ## use eval/echo here to make sure shell expansions are performed
1158     #if ! cp -a${linkflag} $(eval echo $articles) "$location"; then
1159     local article
1160     for article in $(eval echo $articles); do
1161         if ! cp -a${linkflag} "$article" "$location"; then
1162             error "Failed to copy \"$article\" to \"$location\" in store_for_reuse()"
1163             # rename the cache location so that it's not cached
1164             # product, but is around for analysis
1165             mv "$location"{,-bad-$(date +%s)} ||
1166                 error "failed to clean up a failed cache attempt" \
1167                       "in \"$location\" -- manual cleanup will be" \
1168                       "necessary"
1169             return 1
1170         fi
1171     done
1172
1173     # flag the cache as complete (i.e. in case lbuild was previously
1174     # interrupted while caching)
1175     touch "$location/.lastused"
1176
1177     # put the temporary location into the final location
1178     # (last one wins)
1179     mkdir -p "${finallocation%/*}"
1180     mv "$location" "$finallocation"
1181     rmdir "${location%/*}"
1182     return 0
1183
1184 }
1185
1186 reuse() {
1187     local module="$1"
1188     local dest="$2"
1189     local use_links="${3:-false}"
1190     local signature="$4"
1191
1192     if [ -n "$REUSEBUILD" ] && [ -d "$REUSEBUILD/$signature/$module" ]; then
1193         if [ ! -f "$REUSEBUILD/$signature/$module/.lastused" ]; then
1194             # the .lastused flag is populated at the end of the caching to
1195             # signal that the caching was completed.  if that flag is not
1196             # there, then the cache is invalid (and should be removed in fact)
1197             mv "$REUSEBUILD/$signature/$module"{,-bad-$(date +%s)} ||
1198                 fatal 1 "failed to clean up a bad cache in location $REUSEBUILD/$signature/$module\" -- manual cleanup will be necessary"
1199             return 1
1200         fi
1201
1202         # so that we know how stale this entry is
1203         touch $REUSEBUILD/$signature/$module/.lastused
1204
1205         if $use_links; then
1206             if ls $REUSEBUILD/$signature/$module/* >/dev/null 2>&1; then
1207                 cp -al $REUSEBUILD/$signature/$module/* $dest/
1208             fi
1209         else
1210             # copying is pretty heavy
1211             # cp -a $REUSEBUILD/$signature/$module/* $dest/
1212             # do some creative symlinking instead
1213             local dir
1214             for dir in BUILD SRPMS SPECS; do
1215                 if ls $REUSEBUILD/$signature/$module/$dir/* >/dev/null 2>&1; then
1216                     ln -s $REUSEBUILD/$signature/$module/$dir/* $dest/$dir
1217                 fi
1218             done
1219             # sources have to be copied by file because we need SOURCES to
1220             # be a dir we can write into
1221 # could overrun ls's arg list here
1222             #ls $REUSEBUILD/$signature/$module/SOURCES/* |
1223             find $REUSEBUILD/$signature/$module/SOURCES/ -type f |
1224                 xargs ln -t $dest/SOURCES -s
1225
1226             # same for RPMS/* dirs
1227 # could overrun ls's arg list here
1228             #ls $REUSEBUILD/$signature/$module/RPMS/$TARGET_ARCH/* |
1229             local dir
1230             for dir in $REUSEBUILD/$signature/$module/RPMS/*; do
1231                 mkdir -p $dest/RPMS/${dir##*/}
1232                 find $dir -type f |
1233                   xargs ln -t $dest/RPMS/${dir##*/} -s
1234             done
1235         fi
1236         return 0
1237     else
1238         return 1
1239     fi
1240 }
1241
1242 basearch() {
1243     local arch="$1"
1244
1245     if [[ $arch = i[3456]86 ]]; then
1246         echo "i386"
1247     else
1248         echo "$arch"
1249     fi
1250
1251 }
1252
1253 build_kernel_with_srpm() {
1254     local outfd=$1
1255
1256     if [ -z "$outfd" ] || [ $outfd = 1 ]; then
1257         fatal 1 "You must supply a file descriptor to ${FUNCNAME[0]} and it cannot be 1"
1258     fi
1259
1260     # need to generate the patch for this target
1261     do_patch_linux false >&${outfd}    # sets global $FULL_PATCH (yeah, yuck)
1262
1263     # get an md5sum of the kernel patch + config for reuse check
1264     # XXX really, there needs to be a signature and a CONFIG_FILE per arch
1265     #     in BUILD_ARCHS
1266     local release_str
1267     if $RELEASE; then
1268         local release_str="RELEASE=$RELEASE\n"
1269     fi
1270
1271     if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
1272         local REUSE_SIGNATURE=$({ echo -en $release_str;
1273                                   echo $BUILD_GEN;
1274                                   cat $CONFIG_FILE $TARGET_FILE $FULL_PATCH; } |
1275                                 md5sum | cut -d" " -f1)
1276         # see if we can link to the reuse pool
1277         # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
1278         #       "library"
1279         local CAN_LINK_FOR_REUSE=false
1280         touch $REUSEBUILD/$$
1281         if cp -al $REUSEBUILD/$$ $TOPDIR/ 2>/dev/null; then
1282             CAN_LINK_FOR_REUSE=true
1283         fi
1284         rm $REUSEBUILD/$$
1285     fi
1286
1287     # the extra version string to use for the kernel (which might be a reused
1288     # kernel, remember)
1289     local kernel_extra_version=""
1290     if ! $USE_BUILD_CACHE || ! reuse kernel "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
1291                                    "$REUSE_SIGNATURE"; then
1292         # nothing cached, build from scratch
1293         if [ ! -r "$KERNELDIR/$KERNEL_SRPM" ]; then
1294             echo "Downloading kernel SRPM" >&${outfd}
1295             download_srpm "$CANONICAL_TARGET" "$KERNEL_SRPM" >&${outfd}
1296         fi
1297
1298         if ! rpm -ivh $KERNELDIR/$KERNEL_SRPM \
1299                   --define "_topdir $TOPDIR" >&${outfd} 2>&1; then
1300             # should we clean this up or leave it for analysis?
1301             #rm -rf $RPMTOPDIR
1302             fatal 1 "Error installing kernel SRPM."
1303         fi
1304
1305         # put the Lustre kernel patch into the RPM build tree
1306         cp $FULL_PATCH $TOPDIR/SOURCES/linux-${lnxmaj}-lustre.patch
1307         prepare_and_build_srpm >&${outfd} ||
1308             fatal 1 "failed to prepare_and_build_srpm"
1309
1310         if [ -z "$REUSE_SIGNATURE" ]; then
1311             echo "No reuse signature was caculated so not storing the built kernel" >&${outfd}
1312         else
1313             # store the resulting kernel RPM build tree for future use
1314             echo "Storing the built kernel for future reuse" >&${outfd}
1315             if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,SRPMS,RPMS}" \
1316                                  "kernel" "$REUSEBUILD" "$REUSE_SIGNATURE" \
1317                                  "$CAN_LINK_FOR_REUSE"; then
1318                 error "Failed to store kernel RPMS for reuse"
1319                 echo "unknown" >&${outfd}
1320                 return 1
1321             fi
1322         fi
1323     fi  # build reuse
1324
1325     # figure out the EXTRA_VERSION of the kernel we built or are re-using
1326     local KERNEL_RPM
1327     if ! KERNEL_RPM=$(find_rpm "$TOPDIR/RPMS/$TARGET_ARCH/" provides "^kernel ="); then
1328         fatal 1 "Failed to find a kernel RPM in $TOPDIR/RPMS/$TARGET_ARCH/"
1329     fi
1330     kernel_extra_version=$(rpm -q --queryformat "%{RELEASE}" -p $TOPDIR/RPMS/$TARGET_ARCH/$KERNEL_RPM)
1331
1332     # should now have the following RPMs
1333     # $TOPDIR/RPMS/$arch/kernel-lustre-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1334     # $TOPDIR/RPMS/$arch/kernel-lustre-devel-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1335     # $TOPDIR/RPMS/$arch/kernel-lustre-headers-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1336     # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-common-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1337     # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1338
1339     echo $kernel_extra_version
1340     return 0
1341
1342 }
1343
1344 # build OFED
1345 # globals used:
1346 #    TOPDIR
1347 #    REUSEBUILD, USE_BUILD_CACHE
1348 #    CONFIGURE_FLAGS
1349
1350 build_ofed() {
1351     local linux="$1"
1352     local ofed_version="$2"
1353
1354     # if an ofed version is given, then it means use OFED proper,
1355     # not any vendor specific "inkernel" version
1356     if [ -z "$ofed_version" ]; then
1357         return 0
1358     fi
1359
1360     if [ "$ofed_version" = "inkernel" ]; then
1361         # see if there is a distro specific override for this and use
1362         # that if it exists
1363         # XXX we need to better integrate a distro specific override with
1364         #     the rest of this function so that all of the reuse cache
1365         #     stuff is leveraged given that 80% of this function is reuse
1366         if type -p build_ofed-${DISTRO}; then
1367             local ofed_location
1368             ofed_location=$(build_ofed-${DISTRO} ${STDOUT})
1369             local rc=${PIPESTATUS[0]}
1370             CONFIGURE_FLAGS="--with-o2ib=${ofed_location} ${CONFIGURE_FLAGS}"
1371             return $rc
1372         else
1373             return 0
1374         fi
1375     fi
1376
1377     # build kernel-ib
1378     if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
1379         local REUSE_SIGNATURE=$({ echo "$ofed_version";
1380                                   echo "$(find_linux_release ${linux})";
1381                                   cat "${linux}/include/linux/autoconf.h"; } |
1382                                 md5sum | cut -d" " -f1)
1383         # see if we can link to the reuse pool
1384         # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
1385         #       "library"
1386         local CAN_LINK_FOR_REUSE=false
1387         touch $REUSEBUILD/$$
1388         if cp -al $REUSEBUILD/$$ $TOPDIR/; then
1389             CAN_LINK_FOR_REUSE=true
1390         fi
1391         rm $REUSEBUILD/$$
1392     fi
1393
1394     if ! $USE_BUILD_CACHE || ! reuse ofed "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
1395                                    "$REUSE_SIGNATURE"; then
1396         if [ -n "$REUSE_SIGNATURE" ]; then
1397             # stash away the existing built articles for a moment
1398             mkdir bak
1399             mv {BUILD,{S,}RPMS,S{OURCE,PEC}S} bak
1400             function mv_back {
1401                 pushd bak
1402                 find . | cpio -pudlm ..
1403                 popd
1404                 rm -rf bak
1405             }
1406             create_rpmbuild_dirs
1407         fi
1408         # build it
1409         build_kernel_ib "${linux}"
1410
1411         if [ -z "$REUSE_SIGNATURE" ]; then
1412             echo "No reuse signature was caculated so not storing the built ofed"
1413         else
1414             # store the resulting RPM build tree for future use
1415             echo "Storing the built ofed for future reuse"
1416             if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,BUILD,SRPMS,RPMS}" \
1417                                  "ofed" "$REUSEBUILD" "$REUSE_SIGNATURE" \
1418                                  "$CAN_LINK_FOR_REUSE"; then
1419                 error "Failed to store OFED RPMS for reuse"
1420                 mv_back
1421                 return 1
1422             fi
1423             # put the stuff we stashed away back
1424             mv_back
1425         fi
1426     fi
1427
1428     pushd "$TOPDIR" >/dev/null
1429     rm -rf kernel-ib-devel
1430     mkdir kernel-ib-devel
1431     cd kernel-ib-devel
1432     # the actual ofed RPMs don't have the -rc$n or -$date string appened that
1433     # might be present on the file
1434     local linuxrelease=$(find_linux_release "$linux")
1435     ofed_version=$(echo $ofed_version |
1436                    sed -re 's/-(20[0-9]{6,6}-[0-9]{4,4}|rc[0-9]*)$//')
1437     local rpm=$(ls $TOPDIR/RPMS/*/kernel-ib-devel-${ofed_version}-${linuxrelease//-/_}.*.rpm)
1438     if ! rpm2cpio < $rpm | cpio -id; then
1439         fatal 1 "could not unpack the kernel-ib-devel rpm."
1440     fi
1441     CONFIGURE_FLAGS="--with-o2ib=$(pwd)/usr/src/ofa_kernel ${CONFIGURE_FLAGS}"
1442     popd >/dev/null
1443
1444 }
1445
1446 build_with_srpm() {
1447
1448     if ! $PATCHLESS; then
1449         local kernel_extra_version
1450         if ! kernel_extra_version=$(build_kernel_with_srpm ${STDOUT}); then
1451             fatal 1 "Failed to build the kernel from it's SRPM"
1452         fi
1453
1454         for arch in $BUILD_ARCHS; do
1455             local kernel_devel_rpm
1456             if ! kernel_devel_rpm=$(find_rpm "$TOPDIR/RPMS/$arch/" provides "^$(devel_kernel_name $KERNEL_LUSTRE_NAMING) ="); then
1457                 fatal 1 "Failed to find a kernel development RPM in $TOPDIR/RPMS/$arch/"
1458             fi
1459
1460             # install the -devel RPM in preparation for modules builds
1461             if ! lnxrel="$kernel_extra_version" unpack_linux_devel_rpm \
1462                            "$TOPDIR/RPMS/$arch/$kernel_devel_rpm"; then
1463                 fatal 1 "Could not find the Linux tree in $TOPDIR/RPMS/$arch/$kernel_devel_rpm"
1464             fi
1465         done
1466     else
1467         # need to find and unpack the vendor's own kernel-devel for patchless
1468         # client build
1469         local kernelrpm
1470         if ! kernelrpm=$(find_linux_rpm "-$DEVEL_KERNEL_TYPE"); then
1471             fatal 1 "Could not find the kernel-$DEVEL_KERNEL_TYPE RPM in ${KERNELRPMSBASE}/${lnxmaj}/${DISTRO}"
1472         fi
1473         if ! lnxrel="$lnxrel" unpack_linux_devel_rpm "$kernelrpm" "-"; then
1474             fatal 1 "Could not find the Linux tree in $kernelrpm"
1475         fi
1476     fi
1477
1478     # ~sigh~  have to make copies of and modify some of the rpm
1479     # infrastructure files so that find-requires can find our unpacked
1480     # kernel-devel artifacts
1481     cp $RPM_HELPERS_DIR/{symset-table,find-requires{,.ksyms}} .
1482     FIND_REQUIRES="$(pwd)/find-requires"
1483     chmod 755 {symset-table,find-requires{,.ksyms}}
1484     local tmp="$(pwd)"
1485     tmp="${tmp//\//\\/}"
1486     ed find-requires <<EOF
1487 1a
1488 set -x
1489 .
1490 /|.*find-requires.ksyms/s/|/| bash -x/
1491 g/ [^ ]*\/\(find-requires\.ksyms\)/s// $tmp\/\1/g
1492 wq
1493 EOF
1494     ed find-requires.ksyms <<EOF
1495 1a
1496 set -x
1497 .
1498 g/\/.*\/\(symset-table\)/s//$tmp\/\1/g
1499 wq
1500 EOF
1501     ed symset-table <<EOF
1502 1a
1503 set -x
1504 .
1505 g/\(\/boot\/\)/s//$tmp\/reused\1/g
1506 g/\(\/usr\/src\/kernels\/\)/s//$tmp\/reused\1/g
1507 wq
1508 EOF
1509
1510     build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
1511         fatal 1 "error building OFED"
1512
1513     # now build Lustre
1514     if build_lustre "$LINUX" "$LINUXOBJ"; then
1515         # the build worked.  resolve any symlinked files (i.e. from reuse)
1516         # in RPMS/$arch to real files so that that that huge mess of
1517         # complication known as LTS can copy them yet somewhere else.
1518         # is it any wonder this whole process is so damn so?  anyone ever
1519         # heard of hardlinks?  it's this cool new thing that allows you save
1520         # tons of time and space by creating... well you can go read about
1521         # them if you have not heard about them yet.
1522         # can i say how much the implemenation of all of this really impedes
1523         # RPM reuse?
1524         local dir
1525         for dir in RPMS/*; do
1526             pushd $dir
1527             for file in $(ls); do
1528                 if [ -h $file ]; then
1529                     cp $file foo
1530                     mv foo $file
1531                 fi
1532             done
1533             popd
1534         done
1535         # also, for i?86, make sure all of the RPMs are in RPMS/$TARGET_ARCH
1536         # as that's where LTS expects to find them
1537         for dir in RPMS/*; do
1538             if [ $dir = RPMS/$TARGET_ARCH ]; then
1539                 continue
1540             fi
1541             pushd $dir
1542             local files=$(ls)
1543             if [ -n "$files" ]; then
1544                 cp -al $files ../$TARGET_ARCH
1545             fi
1546             popd
1547         done
1548     else
1549         return 1
1550     fi
1551
1552 }
1553
1554 create_rpmbuild_dirs() {
1555
1556     [ -d RPMS ] || mkdir RPMS
1557     for arch in $BUILD_ARCHS; do
1558         if [[ $arch = i?86 ]]; then
1559             # some stupidity in the sles11 kernel spec requires an RPMS/i386
1560             # even if the target arch is i686
1561             [ -d RPMS/i386 ] || mkdir RPMS/i386
1562         fi
1563         [ -d RPMS/$arch ] || mkdir RPMS/$arch
1564     done
1565     [ -d BUILD ] || mkdir BUILD
1566     [ -d SOURCES ] || mkdir SOURCES
1567     [ -d SPECS ] || mkdir SPECS
1568     [ -d SRPMS ] || mkdir SRPMS
1569
1570 }
1571
1572 new_list() {
1573
1574     echo ""
1575
1576 }
1577
1578 add_list() {
1579     local list="$1"
1580     local item="$2"
1581
1582     echo "$list $item"
1583
1584 }
1585
1586 is_list_member() {
1587     local list="$1"
1588     local item="$2"
1589
1590     [[ $list\  == *\ $item\ * ]]
1591
1592 }
1593
1594 #########################################################################
1595 # Generate a backtrace through the call stack.
1596 #
1597 # Input: None
1598 # Output: None
1599 #########################################################################
1600 backtrace() {
1601     local strip=${1:-1}
1602
1603     local funcname="" sourcefile="" lineno="" n
1604
1605     echo "Call stack: (most recent first)"
1606     for (( n = $strip ; n < ${#FUNCNAME[@]} ; ++n )) ; do
1607         funcname=${FUNCNAME[$n - 1]}
1608         sourcefile=$(basename ${BASH_SOURCE[$n]})
1609         lineno=${BASH_LINENO[$n - 1]}
1610         if [ $n = 1 ]; then
1611             let lineno-=11
1612         fi
1613         # Display function arguments
1614         if [[ ! -z "${BASH_ARGV[@]}" ]]; then
1615             local args newarg j p=0
1616             for (( j = ${BASH_ARGC[$n - 1]}; j > 0; j-- )); do
1617                 newarg=${BASH_ARGV[$j + $p - 1]}
1618                 args="${args:+${args} }'${newarg}'"
1619             done
1620             let p+=${BASH_ARGC[$n - 1]}
1621         fi
1622         echo "  ${funcname} ${args:+${args} }at ${sourcefile}:${lineno}"
1623     done
1624
1625     echo
1626     echo "BEGIN BACKTRACE"
1627
1628     #echo ${BASH_LINENO[*]}
1629     #echo ${BASH_SOURCE[*]}
1630     #echo ${FUNCNAME[*]}
1631     local i=$((${#FUNCNAME[@]} - 1))
1632     while [ $i -ge 0 ]; do
1633         local lineno=${BASH_LINENO[$i]}
1634         if [ $i = 0 ]; then
1635             let lineno-=11
1636         fi
1637         local SOURCELINE="${BASH_SOURCE[$i + 1]}:${lineno}"
1638         # Can't figure out how to get function args from other frames...
1639         local FUNCTION="${FUNCNAME[$i]}()"
1640         echo "$SOURCELINE:$FUNCTION"
1641         i=$((i - 1))
1642     done
1643
1644     echo "END BACKTRACE"
1645
1646     echo $BACKTRACE
1647
1648 }
1649
1650 seen_list=$(new_list)
1651 trap 'set +x;
1652 echo "An unexpected error has occurred at ${BASH_SOURCE[0]##*/}:$((LINENO-1)).
1653 Unfortunately the above line number in the message may or may not be correct,
1654 but details have been send to the lbuild maintainer.  Attempting to continue."; (echo "Untrapped error"
1655 echo
1656 # have we seen this one
1657 echo "checking seen list for ${BASH_SOURCE[0]}:${BASH_LINENO[0]}"
1658
1659 if is_list_member "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}"; then
1660   echo "seen this one already"
1661 else
1662   seen_list=$(add_list "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}")
1663 fi
1664 backtrace
1665 echo
1666 echo "Environment:"
1667 set
1668 ) | mail -s "Untrapped error at ${BASH_SOURCE[0]##*/}:$((LINENO-15)) on $HOSTNAME" brian@whamcloud.com >&2; set $xtrace' ERR
1669 set -E
1670
1671 [ -r ~/.lbuildrc ] && . ~/.lbuildrc
1672
1673 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 -- "$@")
1674
1675 if [ $? != 0 ]; then
1676     usage 1
1677 fi
1678
1679 eval set -- "$options"
1680
1681 while [ "$1" ]; do
1682     case "$1" in
1683         '')
1684             usage 1
1685             ;;
1686         --ccache)
1687             CCACHE='ccache'
1688             shift
1689             ;;
1690         -d)
1691             CVSROOT=$2
1692             shift 2
1693             ;;
1694         -D)
1695             DATE=$2
1696             shift 2
1697             ;;
1698         --external-patches)
1699             EXTERNAL_PATCHES=$2
1700             shift 2
1701             ;;
1702         --extraversion)
1703             EXTRA_VERSION=$2
1704             shift 2
1705             ;;
1706         --help | -h)
1707             usage 0
1708             ;;
1709         --kerneldir)
1710             KERNELDIR=$2
1711             shift 2
1712             ;;
1713         --kerneltree)
1714             if ! KERNELTREE=$(canon_path "$2"); then
1715                 fatal 1 "Could not determine the canonical location of $2"
1716             fi
1717             shift 2
1718             ;;
1719         --linux | --with-linux)
1720             if ! LINUX=$(canon_path "$2"); then
1721                 fatal 1 "Could not determine the canonical location of $2"
1722             fi
1723             shift 2
1724             ;;
1725         --distro)
1726             DISTRO=$2
1727             shift 2
1728             ;;
1729         --reuserpm)
1730             REUSERPM=$2
1731             shift 2
1732             ;;
1733         --reusebuild)
1734             if ! REUSEBUILD=$(canon_path "$2"); then
1735                 fatal 1 "Could not determine the canonical location of $2"
1736             fi
1737             shift 2
1738             ;;
1739         --norpm)
1740             NORPM=true
1741             shift
1742             ;;
1743         --ldiskfs)
1744             LDISKFSRPM=true
1745             shift
1746             ;;
1747         --noiokit)
1748             IOKITRPM=false
1749             shift
1750             ;;
1751         --patchless)
1752             PATCHLESS=true
1753             shift
1754             ;;
1755         --kernelrpm)
1756             if ! KERNELRPMSBASE=$(canon_path "$2"); then
1757                 fatal 1 "Could not determine the canonical location of $2"
1758             fi
1759             shift 2
1760             ;;
1761         --timestamp)
1762             TIMESTAMP=$2
1763             shift 2
1764             ;;
1765         --lustre)
1766             if ! LUSTRE=$(canon_filepath "$2"); then
1767                 fatal 1 "Could not determine the canonical location of $2"
1768             fi
1769             shift 2
1770             ;;
1771         --nodownload)
1772             DOWNLOAD=false
1773             shift 1
1774             ;;
1775         --nosrc)
1776             DO_SRC=false
1777             shift 1
1778             ;;
1779         --ofed-version)
1780             OFED_VERSION="$2"
1781             shift 2
1782             ;;
1783         --publish)
1784             shift
1785             ;;
1786         --release)
1787             RELEASE=true
1788             shift
1789             ;;
1790         --src)
1791             DO_SRC=true
1792             shift 1
1793             ;;
1794         --stage)
1795             STAGEDIR=$2
1796             shift 2
1797             ;;
1798         --tag)
1799             TAG=$2
1800             shift 2
1801             ;;
1802         --target)
1803             TARGET=$2
1804             shift 2
1805             ;;
1806         --target-archs)
1807             TARGET_ARCHS=$2
1808             shift 2
1809             ;;
1810         --disable-datestamp)
1811             USE_DATESTAMP=
1812             shift
1813             ;;
1814         --xen)
1815             XEN=true
1816             shift
1817             ;;
1818         --set-value)
1819             eval $2
1820             shift 2
1821             ;;
1822         --)
1823             shift
1824             # there are actually some lustre configure flags that we need to
1825             # handle ourselves (but we still give them to configure)
1826             if [[ \ $@\  == *\ --disable-tests\ * ]]; then
1827                 LUSTRE_TESTS=false
1828             fi
1829             CONFIGURE_FLAGS=$@
1830             CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-liblustre --enable-liblustre-tests"
1831             break
1832             ;;
1833         *)
1834             usage 1 "Unrecognized option: $1"
1835             ;;
1836     esac
1837 done
1838
1839 check_options
1840
1841 unpack_lustre
1842
1843 # XXX - should we _always_ get the buildid from the META file?  what are the
1844 # other (i.e. non-lustre-tarball use cases of lbuild)?
1845 BUILDID=$(sed -ne '/^BUILDID =/s/.*= *//p' lustre/META)
1846
1847 load_target
1848
1849 if [ -n "$OFED_VERSION" -a "$OFED_VERSION" != "inkernel" ]; then
1850     download_ofed
1851     unpack_ofed || fatal 1 "Error unpacking OFED tarball"
1852 fi
1853
1854 # make sure the RPM build environment is set up
1855 create_rpmbuild_dirs
1856
1857 # if an unpacked kernel source tree was given on the command line
1858 # just build lustre with it (nothing distro kernel specific here)
1859 if [ -n "$LINUX" ]; then
1860     build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
1861         fatal 1 "error building OFED"
1862     build_lustre "$LINUX" "$LINUXOBJ"
1863 else
1864     if [ -f "${0%/*}/lbuild-$DISTRO" ]; then
1865         source ${0%/*}/lbuild-$DISTRO
1866
1867         build_with_srpm || fatal 1 "Failed to build_with_srpm"
1868     else
1869         EXTRA_VERSION_DELIMITER=${EXTRA_VERSION_DELIMITER:-"-"}
1870         source ${0%/*}/lbuild.old_school
1871
1872         old_school_download_kernel
1873
1874         build_success=false
1875         if $PATCHLESS; then
1876             patchless_build_sequence && build_success=true
1877         else
1878             [ "$DISTRO" = "sles9" ] && build_sequence_rpm_reuse && build_success=true
1879             if ! $build_success; then
1880                 build_sequence_reuse && build_success=true
1881                 if ! $build_success; then
1882                     build_sequence && build_success=true
1883                     if $build_success; then
1884                         store_for_reuse || echo "Cannot store for future reuse"
1885                     fi
1886                 fi
1887             fi
1888         fi
1889         ( $build_success ) || fatal 1 "Cannot build lustre"
1890     fi
1891 fi
1892
1893 stage