Whamcloud - gitweb
60bf747be5c456a8ed1e394d2c7125c7cadac2b5
[fs/lustre-release.git] / contrib / lbuild / 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 # Assume that lbuild's support files can be found in the same
19 # canonicalized path as this very script.
20 LBUILD_SCRIPT=$(readlink -f ${0})
21 LBUILD_DIR=${LBUILD_DIR:-$(dirname ${LBUILD_SCRIPT})}
22
23 # include the exit_traps library
24 . ${LBUILD_DIR}/exit_traps.sh
25 . ${LBUILD_DIR}/funcs.sh
26
27 # our children should die when we do
28 push_exit_trap "kill -INT -$$ || true" kill_children
29
30 # increment this if you have made a change that should force a new kernel
31 # to build built
32 #BUILD_GEN=1
33 #BUILD_GEN=2    # bz19952: remove -lustre tag from kernel RPM names
34 #BUILD_GEN=3    # bz19975: enable the building of src.rpms by default
35 #BUILD_GEN=4    # bz22281: use the git hash in the kernel extra version
36 #BUILD_GEN=5    # TT-107: don't cache the BUILD dir
37 BUILD_GEN=6     # TT-1092: don't cache the BUILD dir, to rebuild external OFED
38
39 TOPDIR=$PWD
40
41 KERNELDIR=
42 LINUX=
43 LUSTRE=
44 RELEASE=false
45 # XXX - some recent hacking has pretty much neutered this option.
46 #       search through this file for "-bb" and see how many places
47 #       simply don't account for this option
48 DO_SRC=true
49 DOWNLOAD=true
50 CANONICAL_TARGET=
51 TARGET=
52 TARGET_ARCH="$(uname -m)"
53 # change default behavior to only build for the current arch
54 TARGET_ARCHS="$TARGET_ARCH"
55 TARGET_ARCHS_ALL="$TARGET_ARCH"
56 [ "$TARGET_ARCH" = "i686" ] && TARGET_ARCHS_ALL="i686 i586 i386"
57 CONFIGURE_FLAGS=
58 EXTERNAL_PATCHES=
59 EXTRA_VERSION=
60 STAGEDIR=
61 TMPDIR=${TMPDIR:-"/var/tmp"}
62 TIMESTAMP=
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 OSDLDISKFSRPM=true
71 OSDZFSRPM=false
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 RPMBUILD=
107
108 export CC=${CC:-gcc}
109
110 # Readlink is not present on some older distributions: emulate it.
111 readlink() {
112     local path=$1 ll
113
114     if [ -L "$path" ]; then
115         ll="$(LC_ALL=C ls -l "$path" 2> /dev/null)" &&
116         echo "${ll/* -> }"
117     else
118         return 1
119     fi
120 }
121
122 usage() {
123     cat <<EOF
124 Usage: ${0##*/} [OPTION]... [-- <lustre configure options>]
125
126   --external-patches=EXTERNAL_PATCHES
127     Directory similar to lustre/lustre/kernel_patches/ that lbuild should
128     look for seres and config files in before looking in the lustre
129     tree.
130
131   --extraversion=EXTRAVERSION
132     Text to use for the rpm release and kernel extraversion.
133
134   --timestamp=TIMESTAMP
135     Date of building lustre in format YYYYMMDDhhmmss
136
137   --reusebuild=DIR
138     Try to reuse old kernel builds from DIR
139
140   --kernelrpm=DIR
141     Path to distro kernel RPM collection
142
143   --ccache
144     Use ccache
145
146   --norpm
147     Do not build RPMs (compile only mode)
148
149   --patchless
150     Build lustre client only
151
152   --distro=DISTRO
153     Which distro using. Autodetect by default
154
155   --kerneldir=KERNELDIR
156     Directory containing Linux source tarballs referenced by target
157     files.
158
159   --kerneltree=KERNELTREE
160     Directory containing dirs with Linux source tarballs referenced by target
161     files. Dir names in format kernel version ('2.6.9', etc.)
162
163   --linux=LINUX --with-linux=LINUX
164     Directory of Linux kernel sources.  When this option is used, only
165     Lustre modules and userspace are built.
166
167   --lustre=LUSTRE
168     Path to an existing lustre source tarball to use.
169
170   --nodownload
171     Do not try to download a kernel from downloads.hpdd.intel.com
172
173   --nosrc
174     Do not build a .src.rpm, a full kernel patch, or a patched kernel
175     tarball.
176
177   --ldiskfs
178     Build with ldiskfs support. (Deprecated, always true)
179
180   --noiokit
181     Do not build lustre-iokit RPM. Now true by default
182
183   --publish
184     Unused.
185
186   --release
187     Specifies that the files generated do not include timestamps, and
188     that this is an official release.
189
190   --src
191     Build a .src.rpm, a full kernel patch, and a patched kernel tarball.
192
193   --stage=DIR
194     Directory used to stage packages for release.  RPMs will be placed
195     more or less in DIR/<target>-<arch>, and the tarball will be
196     placed in DIR.
197
198   --target=TARGET
199     The name of the target to build.  The available targets are listed
200     below.
201
202   --target-archs=TARGET_ARCHS
203     A (space delimited) list of architectures to build.  By default,
204     all of the archs supported by the TARGET will be built, in
205     addition to a .src.rpm.  This option can limit those, for machines
206     that can only build certain archs or if you only want a certain
207     arch built (for testing, or a one-off kernel).
208
209     Also note that by using a non-"base" arch (eg, i386) only kernels
210     will be built - there will be no lustre-lite-utils package.
211
212   --xen
213     Builds a Xen domX kernel.
214
215   --set-value
216     Sets a variable to a given value.
217
218 EOF
219
220 #   list_targets
221
222     fatal "$1" "$2"
223 }
224
225 # canonicalize a relative path to a file
226 canon_filepath() {
227     local PATH="$1"
228
229     if [ ! -f "$PATH" ]; then
230         return 1
231     fi
232
233     local FILE=${PATH##*/}
234     local DIR=${PATH%/*}
235
236     echo $(canon_path "$DIR")/$FILE
237     return 0
238 }
239
240 # canonicalize a relative path to a dir
241 canon_path() {
242     local PATH="$1"
243
244     if [ ! -d "$PATH" ]; then
245         return 1
246     fi
247
248     pushd "$PATH" >/dev/null || return 1
249     local CANONPATH=$PWD
250     popd >/dev/null
251
252     echo "$CANONPATH"
253     return 0
254 }
255
256 check_options() {
257
258     if [ -z "$LUSTRE" -o ! -r "$LUSTRE" ]; then
259         usage 1 "Could not find Lustre source tarball '$LUSTRE'."
260     fi
261
262     if [ -z "$DISTRO" ] ; then
263         DISTRO=$(autodetect_distro)
264         # remove separator
265         DISTRO=${DISTRO/-/}
266     fi
267     DISTROMAJ=${DISTRO%%.*}
268
269     [ -z "$TARGET" ] && TARGET=$(autodetect_target "$DISTRO")
270
271     if [ -z "$LINUX" ]; then
272         [ "$KERNELDIR" -o "$KERNELTREE" ] || \
273             usage 1 "A kernel directory must be specified with --kerneldir or --kerneltree."
274
275         [ -d "$KERNELDIR" -o -d "$KERNELTREE" ] || \
276             usage 1 "$KERNELDIR and $KERNELTREE are not a directory."
277
278 #       TARGET_FILE="$TOPDIR/lustre/kernel_patches/targets/$TARGET.target"
279 #       [ -r "$TARGET_FILE" ] || \
280 #               usage 1 "Target '$TARGET' was not found."
281     fi
282
283     case $TARGET in
284         3.10-rhel7)
285             CANONICAL_TARGET="rhel7"
286             ;;
287         2.6-rhel6)
288             CANONICAL_TARGET="rhel6"
289             ;;
290         2.6-rhel5)
291             CANONICAL_TARGET="rhel5"
292             ;;
293         2.6-rhel4)
294             CANONICAL_TARGET="rhel-2.6"
295             ;;
296         2.6-suse)
297             CANONICAL_TARGET="sles-2.6"
298             ;;
299         2.6-sles10)
300             CANONICAL_TARGET="sles10-2.6"
301             ;;
302         2.6-sles11 | 3.0-sles11)
303             CANONICAL_TARGET="sles11"
304             ;;
305         2.6-oel5)
306             CANONICAL_TARGET="oel5"
307             ;;
308         hp_pnnl-2.4)
309             CANONICAL_TARGET="hp-pnnl-2.4"
310             ;;
311         2.6-vanilla \
312             | suse-2.4.21-2 \
313             | rh-2.4 \
314             | rhel-2.4 \
315             | sles-2.4 \
316             | 2.6-patchless)
317                 CANONICAL_TARGET="$TARGET"
318                 ;;
319     esac
320
321     local timestampnodig=$(echo $TIMESTAMP | sed -e s/[0-9]*//g)
322     [ "$timestampnodig" = "" ] || TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M%S")
323     local timestamplength="${#TIMESTAMP}"
324     if [ $timestamplength -eq 12 ]; then
325         TIMESTAMP="${TIMESTAMP}00"
326     elif [ $timestamplength -ne 14 ]; then
327         TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M%S")
328     fi
329
330     RPMBUILD=$(which rpmbuild 2>/dev/null | head -1)
331     if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
332         RPMBUILD=$(which rpm 2>/dev/null | head -1)
333         if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
334             usage 1 "Could not find binary for making rpms (tried rpmbuild and rpm)."
335         fi
336     fi
337
338     if [ -n "$CCACHE" ]; then
339         which "$DISTCC" &>/dev/null && export DISTCC RPM_BUILD_NCPUS
340
341         if which "$CCACHE" &>/dev/null; then
342             local ccache=$(which "$CCACHE")
343             local bindir="$TOPDIR/bin"
344
345             if [ ! -d $bindir ]; then
346                 mkdir -p $bindir || fatal 1 "error trying to create $bindir"
347             else
348                 rm ${bindir}/* > /dev/null 2>&1 || true
349             fi
350             ln -s "$ccache" ${bindir}/ccache
351             ln -s "$ccache" ${bindir}/cc
352             ln -s "$ccache" ${bindir}/$CC
353             export PATH=$bindir:$PATH
354             export CCACHE && export CC="ccache $CC"
355             # zero the cache so we can see how effective we are being with it
356             echo -n "ccache "
357             ccache -z
358
359             # get some ccache stats when we are done
360             push_exit_trap '[ -n "$CCACHE" ] && ccache -s' "ccache_summary"
361             # should remove the ccache trap if lbuild is interrupted
362             trap 'echo "Received an INT TERM or HUP signal, terminating."; delete_exit_trap "ccache_summary"; exit 1' INT TERM HUP
363         fi
364     fi
365
366     return 0
367
368 }
369
370 # compare two versions $1 and $2. if $1 < $2, return 0 otherwise return 1.
371 compare_version () {
372     [[ $1 == $2 ]] && return 1
373     local IFS=.
374     local i val1=($1) val2=($2)
375
376     # padding zero to val1 if it needs
377     for ((i=${#val1[@]}; i<${#val2[@]}; i++)); do
378         val1[i]=0
379     done
380     for ((i=0; i<${#val1[@]}; i++)); do
381         [[ -z ${val2[i]} ]] && return 1
382
383         if [[ ${val1[i]} < ${val2[i]} ]]; then
384             return 0
385         elif [[ ${val1[i]} > ${val2[i]} ]]; then
386             return 1
387         fi
388     done
389 }
390
391 uniqify() {
392
393     echo $(echo "$*" | xargs -n 1 | sort -u)
394
395 }
396
397 fetch_url() {
398     local url="$1"
399     local target="$2"
400
401     if [ -z "$target" ]; then
402         fatal 1 "fetch_url() called without a target to fetch to"
403     fi
404
405     if [ -d $target ]; then
406         target+="/${url##*/}"
407     fi
408
409     local rc=0
410     if which wget >/dev/null 2>&1; then
411         if ! wget -nv "$url" -O "$target"; then
412             rc=${PIPESTATUS[0]}
413         fi
414     elif which curl >/dev/null 2>&1; then
415         if ! curl -n -L -s -o "$target" "$url"; then
416             rc=${PIPESTATUS[0]}
417         fi
418     else
419         fatal 1 "Could not find either wget or curl to fetch URLs."
420     fi
421
422     return $rc
423
424 }
425
426 download_srpm() {
427     local target=$1
428     local srpm=$2
429     local force="${3:-false}"
430
431     if $force || [ ! -r "$KERNELDIR/$srpm" ] ||
432        [ ! -s "$KERNELDIR/$srpm" ]; then
433         if $DOWNLOAD; then
434             local location="https://downloads.hpdd.intel.com/public/kernels/$target/old"
435             # get the location from a distro specific method if it exists
436             if type -p kernel_srpm_location; then
437                 location=$(kernel_srpm_location)
438             fi
439             echo "Downloading $location/$srpm..."
440             if ! fetch_url "$location/$srpm" "$KERNELDIR/$srpm" 2>&1 ||
441                [ ! -s "$KERNELDIR/$srpm" ]; then
442                 rm -f $KERNELDIR/$srpm
443                 # punt to a distro specific method if it exists
444                 if ! type -p download_srpm-$DISTROMAJ; then
445                     fatal 1 "Could not download target $target's kernel SRPM $srpm from $location."
446                 else
447                     if ! download_srpm-$DISTROMAJ "$target" "$srpm" "$force"; then
448                         fatal 1 "Could not download target $target's kernel SRPM $srpm using download_srpm-$DISTROMAJ."
449                     fi
450                 fi
451             fi
452         else
453             fatal 1 "$srpm not found in directory $KERNELDIR."
454         fi
455     fi
456
457 }
458
459 download_file() {
460     local from="$1"
461     local to="$2"
462     local force="$3"
463
464     local file=${from##*/}
465
466     if [ -d $to ]; then
467         to="$to/$file"
468     fi
469
470     local semaphore="$to-downloading"
471
472     is_downloading() {
473         if [ ! -f $semaphore ]; then
474             return 1
475         fi
476
477         # make sure the download has not been aborted
478         local now=$(date +%s)
479         local file_mtime=$(stat -c %Y "$to")
480         local staleness=$((now - file_mtime))
481         # let's assume an active download will write at least once a minute
482         if [ $staleness -gt 60 ]; then
483             return 1
484         fi
485
486         return 0
487     }
488
489     is_downloaded() {
490         # if the semaphore file exists, the file is either still downloading
491         # or a download was aborted and we cannot trust the target file
492         if [ -f $semaphore ]; then
493             return 1
494         fi
495
496         if ! is_downloading && [ -r "$to" ] && [ -s "$to" ]; then
497             return 0
498         fi
499
500         return 1
501     }
502
503     if $force || ! is_downloaded; then
504         if is_downloading; then
505             echo "Somebody else is downloading $from..."
506             while is_downloading; do
507                 echo "Waiting for $to to finish downloading"
508                 sleep 60
509             done
510             if is_downloaded; then
511                 return 0
512             else
513                 echo "The download we were waiting for seems to have been aborted"
514             fi
515
516         fi
517
518         if $DOWNLOAD; then
519             echo "Downloading $from..."
520             # flag others so they don't try to download also
521             push_exit_trap "rm -f $to $semaphore" "download"
522             touch $semaphore
523             if ! fetch_url "$from" "$to" || [ ! -s "$to" ]; then
524                 # the trap will remove the files via the fatal below
525                 fatal 1 "Could not download ${to##*/} from ${from%/*}/."
526             fi
527             rm -f $semaphore
528             delete_exit_trap "download"
529         else
530             fatal 1 "${to##*/} not found in directory ${to%/*}."
531         fi
532     fi
533
534     return 0
535
536 }
537
538 download_ofed() {
539     local force="${1:-false}"
540
541     if [ -z "$OFED_VERSION" -o "$OFED_VERSION" = "inkernel" ]; then
542         return 0
543     fi
544
545     local OFED_BASE_VERSION=$OFED_VERSION
546     if [[ $OFED_VERSION = *.*.*.* ]]; then
547         OFED_BASE_VERSION=${OFED_VERSION%.*}
548     fi
549
550     local location="https://www.openfabrics.org/downloads/OFED/ofed-${OFED_BASE_VERSION}/"
551
552     if [[ $OFED_VERSION = *-[rR][cC][0-9] ]]; then
553         local Mmv
554         Mmv=${OFED_VERSION%%-[rR][cC][0-9]}
555         location="https://www.openfabrics.org/downloads/OFED/ofed-${Mmv}/"
556     fi
557
558     if [[ $OFED_VERSION = daily-* ]]; then
559         local Mmv
560         Mmv=${OFED_VERSION/daily-/}
561         daily=${OFED_VERSION##$Mmv-}
562         location="https://www.openfabrics.org/downloads/OFED/ofed-${Mmv}-daily/"
563         # find the filename for the version for the date specified
564         OFED_VERSION=$(curl -s "$location" | sed -nre "/${Mmv}-/s/.*href=\"OFED-(${Mmv}-[0-9]{8,8}-[0-9]{4,4}).tgz.*$/\1/p" | tail -1)
565         if [ -z "$OFED_VERSION" ]; then
566             fatal 1 "Could not determine the filename of the OFED snapshot for ${daily}"
567         fi
568     fi
569
570     local file="OFED-${OFED_VERSION}.tgz"
571     download_file "$location/$file" "$KERNELTREE" "$force"
572
573 }
574
575 parse_mpss_info() {
576     local file="$1"
577     local build="$2"
578     local distro="$3"
579
580     [ -r "$file" ] || fatal 1 "Could not find MPSS info file"
581
582     # convert to MPSS distro naming
583     distro=${distro/sles/suse}
584     distro_name=${distro%%-*}
585
586     # extract links from MPSS info file
587     local urls=$(cat "$file" | \
588         tr -d '\t\r\n' | sed -e 's?\(</[a-zA-Z]*>\)?\1\n?g' | \
589         grep '.intel.com/' | \
590         sed -e 's/^.*[hH][rR][eE][fF]="\([^>"]\+\)".*$/\1/g' | \
591         grep '.tar')
592     local res2=""
593     local res3=""
594     for url in $urls; do
595         local ver2=""
596         local ver3=""
597         # Try to match with MPSS 3.x or 3.x.x distro package
598         if [[ $url =~ mpss-[0-9].[0-9](.[0-9]*)?-$distro.tar ]]; then
599             ver3=${url##*mpss-}
600             ver3=${ver3%%-$distro.tar}
601         # Try to match with MPSS 3.x or 3.x.x source package
602         elif [[ $url =~ mpss-src-[0-9].[0-9](.[0-9]*)?.tar ]]; then
603             ver3=${url##*mpss-src-}
604             ver3=${ver3%%.tar}
605         # Try to match with MPSS 3.x or 3.x.x cross compiler package
606         elif [[ $url =~ mpss-[0-9].[0-9](.[0-9]*)?-k1om.tar ]]; then
607             ver3=${url##*mpss-}
608             ver3=${ver3%%-k1om.tar}
609         # Try to match with MPSS 2.1.x source package
610         elif [[ $url =~ _src-[0-9].[0-9].[0-9]*-[0-9]*_$distro_name.tar ]]; then
611             ver2=${url##*_src-}
612             ver2=${ver2%%_$distro_name.tar}
613         fi
614
615         if [ -n "$ver3" ]; then
616             # Check for MPSS 3.x or MPSS 3.x.x
617             if [[ $ver3 =~ [0-9].[0-9].[0-9]* ]]; then
618                 ver3="${ver3}-0"
619             else
620                 ver3="${ver3}.0-0"
621             fi
622             if [ -z "$build" ]; then
623                 res3="$ver3"
624             elif [ "$build" = "$ver3" ]; then
625                 res3="$res3 $url"
626             fi
627         elif [ -n "$ver2" ]; then
628             if [ -z "$build" ]; then
629                 res2="$ver2"
630             elif [ "$build" = "$ver2" ]; then
631                 res2="$res2 $url"
632             fi
633         fi
634
635     done
636
637     if [ -z "$build" ]; then
638         # return a last version of MPSS
639         if [ -n "$res3" ]; then
640             echo "$res3"
641         else
642             echo "$res2"
643         fi
644     elif [ "${build%%.*}" = "3" ]; then
645         local ver=${build%%-*}
646         local bid=${build##*-}
647         if [ $bid -eq 0 ]; then
648             # return URLs from MPSS info file
649             echo "$res3"
650         else
651             # Check for MPSS 3.x or MPSS 3.x.x
652             if [ ${ver##*.} -eq 0 ]; then
653                 ver=${ver%.*}
654             fi
655             # return URLs from internal site with MPSS builds
656             # kernel sources:
657             echo "${MPSS_BUILDS:-"http://mic-bld.pdx.intel.com/release"}/$ver/$bid/release/knightscorner/package/mpss-src-$ver.tar"
658             # kernel configs:
659             echo "${MPSS_BUILDS:-"http://mic-bld.pdx.intel.com/release"}/$ver/$bid/release/knightscorner/package/mpss-$ver-k1om.tar"
660             # OFED headers:
661             echo "${MPSS_BUILDS:-"http://mic-bld.pdx.intel.com/release"}/$ver/$bid/release/knightscorner/package/mpss-$ver-$distro.tar"
662         fi
663     else
664         # return URLs from MPSS info file
665         echo "$res2"
666     fi
667 }
668
669 # Get public information about last releases of
670 # Intel Manycore Platform Software Stack (MPSS)
671 download_mpss_info() {
672     local file="$1"
673     local force="${2:-true}"
674     local url=${MPSS_URL:-"http://software.intel.com/en-us/articles/intel-manycore-platform-software-stack-mpss"}
675
676     download_file "$url" "$file" "$force"
677 }
678
679 download_mpss() {
680     local file="$1"
681     local force="${2:-false}"
682     local urls=$(parse_mpss_info "$file" ${MPSS_VERSION} ${MPSS_DISTRO})
683
684     [ -z "$urls" ] && fatal 1 "Could not determine the URLs of MPSS $MPSS_VERSION"
685
686     # force re-download if build number is zero
687     [[ $MPSS_VERSION = [0-9].[0-9].[0-9]*-0 ]] && force=true
688
689     local url
690     local i=0
691     for url in $urls; do
692         file="$KERNELTREE/mpss_src-${MPSS_VERSION}-${MPSS_DISTRO}-part$i.tar"
693         download_file "$url" "$file" "$force"
694         i=$((i+1))
695     done
696 }
697
698 load_target() {
699
700     EXTRA_VERSION_save="$EXTRA_VERSION"
701     for patchesdir in "$EXTERNAL_PATCHES" \
702                       "$TOPDIR/lustre/lustre/kernel_patches"; do
703         TARGET_FILE="$patchesdir/targets/$TARGET.target"
704         [ -r "$TARGET_FILE" ] && break
705     done
706     [ -r "$TARGET_FILE" ] || fatal 1 "Target $TARGET was not found."
707
708     echo "Loading target config file $TARGET.target..."
709
710     # if the caller specified an OFED_VERSION it should override whatever
711     # the target file specifies
712     local env_OFED_VERSION="$OFED_VERSION"
713
714     . "$TARGET_FILE"
715
716     if [ -n "$env_OFED_VERSION" ]; then
717         OFED_VERSION="$env_OFED_VERSION"
718     fi
719
720     # doesn't make any sense to build OFED for xen domX's
721     if $XEN; then
722         OFED_VERSION=""
723     fi
724
725     # XXX - set_rpm_smp_type is an ugly undeterministic hack.  it needs to
726     #       go away and the target just specify the $RPMSMPTYPE
727     [ -z "$RPMSMPTYPE" ] && set_rpm_smp_type
728
729     # CC might have been overwriten in TARGET_FILE
730     if [[ $CC != ccache\ * ]] && which "$CCACHE" &>/dev/null; then
731         export CCACHE && export CC="ccache $CC"
732     fi
733
734     if [ ! "$KERNELTREE" = "" ] && [ -d "$KERNELTREE" ]; then
735         KERNELDIR="$KERNELTREE/${lnxmaj}"
736         [ -d "$KERNELDIR" ] || mkdir "$KERNELDIR"
737     fi
738
739     # verify the series is available
740     if [ "$SERIES" ]; then
741         for series in $SERIES; do
742             for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches"; do
743                 [ -r "$patchesdir/series/$series" ] && continue 2
744             done
745             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."
746         done
747     fi
748
749     # set the location of the .config file
750     local XENPOSTFIX=""
751     if $XEN; then
752         XENPOSTFIX="-xen"
753     fi
754
755     if [ -f $TOPDIR/lustre/lustre/kernel_patches/kernel_configs/kernel-$lnxmaj-$TARGET-$TARGET_ARCH.config ]; then
756         CONFIG_FILE="$TOPDIR/lustre/lustre/kernel_patches/kernel_configs/kernel-$lnxmaj-$TARGET$XENPOSTFIX-$TARGET_ARCH.config"
757     fi
758
759     local lnxrelnew=${lnxrel//-/_}
760
761     # remember the EXTRA_VERSION before we diddle it here
762     # XXX - we really should not diddle with any values read in from the
763     #       target file.  if we want to modify a value, we should create
764     #       a new variable.
765     PRISTINE_EXTRA_VERSION=$EXTRA_VERSION
766
767     if ! $PATCHLESS && [ ! -f "$CONFIG_FILE" ]; then
768         fatal 1 "Config file for target $TARGET missing from $TOPDIR/lustre/lustre/kernel_patches/kernel_configs/."
769     fi
770
771     if [ "$EXTRA_VERSION_save" ]; then
772         EXTRA_VERSION="$EXTRA_VERSION_save"
773     elif ! $RELEASE; then
774         # if there is no patch series, then this is not a lustre specific
775         # kernel.  don't make it look like one
776         if $PATCHLESS || [ -n "$SERIES" ]; then
777             EXTRA_VERSION=$(echo $EXTRA_VERSION | sed -e "s/\(.*_lustre\)\..*/\1/")
778             if ! $PATCHLESS && [ -n "$BUILDID" ]; then
779                 EXTRA_VERSION="${EXTRA_VERSION}.${BUILDID}"
780             fi
781         fi
782     fi
783     # EXTRA_VERSION=${EXTRA_VERSION//-/_}
784
785     ALL_ARCHS="$BASE_ARCHS $BIGMEM_ARCHS $BOOT_ARCHS $JENSEN_ARCHS $SMP_ARCHS $BIGSMP_ARCHS $PSERIES64_ARCHS $UP_ARCHS"
786
787     BUILD_ARCHS=
788     for arch in $(uniqify "$ALL_ARCHS"); do
789         if [ -z "$TARGET_ARCHS" ] ||
790            [[ \ $TARGET_ARCHS\  = *\ $arch\ * ]]; then
791             BUILD_ARCHS="$BUILD_ARCHS $arch"
792         fi
793     done
794     [ "$BUILD_ARCHS" ] || usage 1 "No available target archs to build."
795     echo "Building for: $BUILD_ARCHS"
796 }
797
798 tarflags() {
799     local file="$1"
800
801     echo -n '--wildcards '
802     case "$file" in
803         '')
804             fatal 1 "tarflags(): File name argument missing."
805             ;;
806         *.tar.gz | *.tgz)
807             echo '-zxf'
808             ;;
809         *.tar.bz2)
810             echo '-jxf'
811             ;;
812         *.tar)
813             echo '-xf'
814             ;;
815         *)
816             fatal 1 "tarflags(): Unrecognized tar extension in file: $1"
817             ;;
818     esac
819
820 }
821
822 untar() {
823     local tarfile="$1"
824     shift
825     local extractfile="$@"
826
827     echo "Untarring ${tarfile##*/}..."
828     tar $(tarflags "$tarfile") "$tarfile" $extractfile
829
830 }
831
832 unpack_ofed() {
833
834     if ! untar "$KERNELTREE/OFED-${OFED_VERSION}.tgz"; then
835         return 1
836     fi
837     [ -d OFED ] || ln -sf OFED-[0-9].[0-9]* OFED
838
839 }
840
841 unpack_lustre() {
842
843     untar "$LUSTRE" || fatal 1 "Error unpacking Lustre tarball"
844     [ -d lustre ] || ln -sf lustre-[0-9].[0-9]* lustre
845
846 }
847
848 unpack_mpss() {
849
850     [ -d mpss ] && return 0
851
852     if [ "${MPSS_VERSION%%.*}" = "3" ]; then
853         local ver=${MPSS_VERSION%%-*}
854         local file
855         local i
856         # Check for MPSS 3.x or MPSS 3.x.x
857         if [ ${ver##*.} -eq 0 ]; then
858             ver=${ver%.*}
859         fi
860         for i in $(seq 0 9); do
861             file="$KERNELTREE/mpss_src-${MPSS_VERSION}-${MPSS_DISTRO}-part$i.tar"
862             if [ -r "$file" ]; then
863                 untar "$file" \
864                     "mpss-$ver/*/linux-*.tar.bz2" \
865                     "mpss-$ver/*/kernel-dev-*.rpm" \
866                     "mpss-$ver/*/ofed-driver-*-devel-*.rpm"
867             fi
868         done
869         # Extract kernel configs
870         file=$(find mpss-$ver -type f -path "*/kernel-dev-*.rpm")
871         if ! rpm2cpio "$file" | cpio -idm; then
872             echo "Error extracting MPSS kernel configs"
873             return 1
874         fi
875         # Unpack kernel sources
876         file=$(find mpss-$ver -type f -path "*/linux-*.tar.bz2")
877         if ! untar "$file"; then
878             echo "Error unpacking MPSS kernel sources"
879             return 1
880         fi
881         # Extract OFED headers
882         file=$(find mpss-$ver -type f -path "*/ofed-driver-*-devel-*.rpm")
883         if ! rpm2cpio "$file" | cpio -idm; then
884             echo "Error extracting MPSS OFED headers"
885             return 1
886         fi
887         # Remove unpacked archives to save space
888         rm -rf mpss-$ver
889         # Make link to MPSS kernel sources
890         ln -sf linux-* mpss
891     else
892         local dir="mpss-${MPSS_VERSION}-${MPSS_DISTRO%%-*}"
893
894         mkdir $dir || return 255
895         pushd $dir >/dev/null || return 255
896         if ! untar "$KERNELTREE/mpss_src-${MPSS_VERSION}-${MPSS_DISTRO}-part0.tar" "*/gpl/*full_src*"; then
897             popd >/dev/null
898             rm -rf $dir
899             echo "Error unpacking MPSS tarball 1"
900             return 1
901         fi
902         local file=$(find . -type f -path "*/gpl/*full_src*")
903         if ! untar "$file"; then
904             popd >/dev/null
905             rm -rf $dir
906             echo "Error unpacking MPSS tarball 2"
907             return 1
908         fi
909         popd >/dev/null
910         ln -sf $dir mpss
911     fi
912
913 }
914
915 do_patch_linux() {
916
917     local do_patch=${1:-true}
918
919     FULL_PATCH="$PWD/lustre-kernel-${TARGET}-${EXTRA_VERSION}.patch"
920     [ -f "$FULL_PATCH" ] && rm -f "$FULL_PATCH"
921     $do_patch && pushd linux >/dev/null
922     for series in $SERIES; do
923         echo -n "Applying series $series:"
924         for patchesdir in "$EXTERNAL_PATCHES" "$TOPDIR/lustre/lustre/kernel_patches"; do
925             [ -r "$patchesdir/series/$series" ] || continue
926             SERIES_FILE="$patchesdir/series/$series"
927             for patch in $(<"$SERIES_FILE"); do
928                 echo -n " $patch"
929                 PATCH_FILE="$patchesdir/patches/$patch"
930                 [ -r "$PATCH_FILE" ] || \
931                     fatal 1 "Patch $patch does not exist in Lustre tree."
932                 cat "$PATCH_FILE" >> "$FULL_PATCH" || {
933                     rm -f $FULL_PATCH
934                     fatal 1 "Error adding patch $patch to full patch."
935                 }
936                 if $do_patch; then
937                     patch -s -p1 < "$PATCH_FILE" 2>&1 || {
938                         rm -f $FULL_PATCH
939                         fatal 1 "Error applying patch $patch."
940                     }
941                 fi
942             done
943             break
944         done
945         echo
946     done
947     $do_patch && popd >/dev/null
948     echo "Full patch has been saved in ${FULL_PATCH##*/}."
949
950 }
951
952 build_lustre() {
953     local linux="$1"
954     local linuxobj="$2"
955
956     cp "$LUSTRE" SOURCES
957
958     pushd lustre >/dev/null
959
960     if ! build_lustre_dkms; then
961         popd >/dev/null # pushd lustre
962         return 255
963     fi
964
965     echo "Building Lustre RPMs for: $BUILD_ARCHS..."
966     local targets arch
967     for arch in $BUILD_ARCHS; do
968         targets="--target $arch $targets"
969     done
970
971     local confoptions=""
972
973     if $PATCHLESS; then
974         confoptions="$confoptions --disable-server"
975     fi
976
977     local rpmbuildopt='-tb'
978     if $NORPM; then
979         rpmbuildopt='-tc'
980         echo NORPM mode. Only compiling.
981     fi
982
983     # If server we now build the spl and zfs modules against the lustre kernel.
984     # These are required prior to the building of lustre server. Client does
985     # not require spl/zfs. Use !PATCHLESS to indicate server which follows the
986     # line above so is at least consistant.
987     if [ $PATCHLESS == false ] && [ "x$ZFSNOTSUPPORTED" == "x" ]; then
988         if ! build_spl_zfs; then
989             popd >/dev/null # pushd lustre
990             return 255
991         fi
992     fi
993
994     if $PATCHLESS; then
995         RPMBUILD_DEFS="$RPMBUILD_DEFS --without servers"
996         if [ -n "$CROSS_SUFFIX" ]; then
997             RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"lustre_name lustre-client$CROSS_SUFFIX\""
998         fi
999     fi
1000
1001     # ditto for the lustre-tests boolean
1002     if ! $LUSTRE_TESTS; then
1003         RPMBUILD_DEFS="$RPMBUILD_DEFS --without lustre_tests"
1004     fi
1005
1006     if ! $IOKITRPM; then
1007         RPMBUILD_DEFS="$RPMBUILD_DEFS --without lustre_iokit"
1008     fi
1009
1010     local osd_zfs=""
1011     if $OSDZFSRPM; then
1012         osd_zfs="yes"
1013     fi
1014
1015     local osd_ldiskfs=""
1016     if $OSDLDISKFSRPM; then
1017         osd_ldiskfs="yes"
1018     fi
1019
1020     RPMBUILD_DEFS="$RPMBUILD_DEFS ${FIND_REQUIRES:+--define \"__find_requires $FIND_REQUIRES\"}"
1021     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"configure_args $confoptions ${CONFIGURE_FLAGS}\""
1022     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"kdir $linux\""
1023     RPMBUILD_DEFS="$RPMBUILD_DEFS ${linuxobj:+--define \"kobjdir $linuxobj\"}"
1024     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"_tmppath $TMPDIR\""
1025     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"_topdir $TOPDIR\""
1026
1027     eval $RPMBUILD $targets $rpmbuildopt "$LUSTRE" $RPMBUILD_DEFS \
1028         ${osd_zfs:+--with zfs} \
1029         ${osd_ldiskfs:+--with ldiskfs} 2>&1 || \
1030         fatal 1 "Error building rpms for $BUILD_ARCHS."
1031
1032     if $DO_SRC; then
1033         if ! eval $RPMBUILD -ts "$LUSTRE" $RPMBUILD_DEFS 2>&1; then
1034             popd >/dev/null
1035             return 255
1036         fi
1037     fi
1038     popd >/dev/null
1039
1040 }
1041
1042 build_lustre_dkms() {
1043     [ -n "$MPSS_VERSION" ] && return 0
1044     local ver=$(eval echo  $(awk '/LUSTRE_VERSION_STRING/ {print $3}'  lustre/include/lustre_ver.h))
1045     echo "Building Lustre DKMS RPMs for: $BUILD_ARCHS..."
1046     ./configure --enable-dist || return 255
1047     $RPMBUILD --define="_topdir $TOPDIR" -bs lustre-dkms.spec || return 255
1048     $RPMBUILD --rebuild --define="_topdir $TOPDIR" $TOPDIR/SRPMS/lustre-dkms-$ver-*.src.rpm || return 255
1049     return 0
1050 }
1051
1052 ###
1053 # build_spl_zfs
1054 #
1055 # Fetch spl/zfs from the git repo and prepare for lustre build
1056 #
1057 # Overrides:
1058 #   SPLZFSGITREPO - URI of directory where spl.git and zfs.git are located
1059 #   SPLZFSTAG     - Tag to checkout of clone repositories
1060 #   SPLZFSVER     - Version to checkout of both (format zfs/spl-$SPLZFSVER)
1061 #
1062 # return 0 if successful, else 255
1063 build_spl_zfs() {
1064     # make sure the RPM build environment is set up
1065     pushd $TOPDIR
1066     create_rpmbuild_dirs
1067     popd
1068
1069     # The spl/zfs spec files expect RPM_BUILD_ROOT to point to the root of the
1070     # destination for the rpms
1071     export RPM_BUILD_ROOT=$TOPDIR
1072     SPLZFSVER=${SPLZFSVER:-0.6.3}
1073     SPLZFSTAG=${SPLZFSTAG:-}
1074
1075     # The files expect a kver to be set to the kernel version .
1076     local kver=$(find_linux_release)
1077
1078     # build and install the spl and zfs (and -devel) RPMs for lustre to use
1079     local pkg
1080     for pkg in spl zfs; do
1081
1082         local rpmpkg
1083
1084         [ "$pkg" == "zfs" ] && spldir="$(ls -d $TOPDIR/usr/src/spl-*/|tail -1)"
1085
1086         # need to fetch the repo in order to build it.
1087         # default to github but allow override
1088         git clone ${SPLZFSGITREPO:-"https://github.com/zfsonlinux"}/$pkg.git $pkg 2>&1
1089
1090         pushd $pkg || return 255
1091         if [ -n "$SPLZFSTAG" ]; then
1092             git checkout $SPLZFSTAG
1093         else
1094             git checkout -b lbuild $pkg-$SPLZFSVER
1095         fi
1096
1097         # This differentiates between older zfs versions
1098         if [ -f $pkg-modules.spec.in ]; then
1099             rpmpkg=$pkg-modules
1100             specdir=.
1101             speclist="$pkg.spec $rpmpkg.spec"
1102         else
1103             rpmpkg=kmod-$pkg-devel
1104             specdir=rpm/generic
1105             speclist="$pkg.spec $pkg-kmod.spec $pkg-dkms.spec"
1106         fi
1107
1108         sh autogen.sh || return 255
1109
1110         if  ! ./configure --with-linux=${LINUX} --with-linux-obj=${LINUXOBJ:-$LINUX} \
1111                           ${spldir:+--with-spl="${spldir}"} 2>&1 ||
1112             ! make dist 2>&1; then
1113             popd
1114             return 255
1115         fi
1116         popd
1117
1118         ln -f $pkg/$pkg-*.tar.gz $TOPDIR/SOURCES ||
1119            error "failed to link $pkg/$pkg-*.tar.gz into $TOPDIR/SOURCES"
1120         if [ -f $pkg/scripts/kmodtool ]; then
1121             ln -f $pkg/scripts/kmodtool $TOPDIR/SOURCES/
1122         fi
1123
1124         local rpmb
1125         if $DO_SRC; then
1126             rpmb=-ba
1127         else
1128             rpmb=-bb
1129         fi
1130
1131         # set search dir for our own kmodtool to find correct
1132         # directories
1133         export KERNELSOURCE=$(dirname ${LINUX})
1134         # Manually build rpms
1135         for spec in $speclist; do
1136             echo "Building RPMs from $pkg/$specdir/$spec"
1137             if ! $RPMBUILD $rpmb $pkg/$specdir/$spec \
1138                 --nodeps -v \
1139                 --define "require_kdir ${LINUX}" \
1140                 ${LINUXOBJ:+--define "require_kobj ${LINUXOBJ}"} \
1141                 ${spldir:+--define "require_spldir ${spldir}"} \
1142                 --define "kver $kver" \
1143                 --define "kernels $kver" \
1144                 --define "_tmppath /var/tmp" \
1145                 --define "kernelbuildroot $TOPDIR/reused" \
1146                 --define "_topdir $TOPDIR" 2>&1; then
1147                 return 255
1148             fi
1149         done
1150
1151         # We have built the rpms for the package. Now we need to extract the
1152         # contained files so we can build further things against them
1153         local rpms=$(ls -1 $TOPDIR/RPMS/*/$rpmpkg-*.rpm)
1154
1155         # cpio only extract to pwd so we need to go there.
1156         pushd $TOPDIR
1157         local rpm
1158         for rpm in $rpms; do
1159             rpm2cpio $rpm | cpio -id
1160         done
1161
1162         if [ "$pkg" == "zfs" ]; then
1163             # We also need to extract both the zfs and zfs-devel rpms
1164             # the zfs rpm is needed because it has the actual libraries in
1165             # it and the zfs-devel rpm only has unversioned symlinks to the
1166             # libraries in the zfs rpm
1167             # this will all change one day when we have a libzfs rpm per
1168             # https://github.com/zfsonlinux/zfs/issues/2329
1169             # and it looks like it could be one day soon:
1170             # https://github.com/zfsonlinux/zfs/pull/2341
1171             local devel_rpms=$(ls -1 $TOPDIR/RPMS/*/{$pkg-devel,$pkg-$SPLZFSVER,lib*}-*.rpm)
1172             for rpm in $devel_rpms; do
1173                 rpm2cpio $rpm | cpio -id
1174             done
1175             CONFIGURE_FLAGS="--with-$pkg-devel=$TOPDIR ${CONFIGURE_FLAGS}"
1176         fi
1177         popd
1178
1179         CONFIGURE_FLAGS="--with-$pkg=$(ls -d $TOPDIR/usr/src/$pkg-*/|tail -1) ${CONFIGURE_FLAGS}"
1180         CONFIGURE_FLAGS="--with-$pkg-obj=$(ls -d $TOPDIR/usr/src/$pkg-*/$kver*|tail -1) ${CONFIGURE_FLAGS}"
1181     done
1182
1183     OSDZFSRPM=true
1184
1185     return 0
1186 }
1187
1188 prepare_mpss() {
1189
1190     pushd mpss >/dev/null || return 255
1191     if [ "${MPSS_VERSION%%.*}" = "3" ]; then
1192         cp -f ../boot/config-* .config
1193         if ! make ARCH=k1om silentoldconfig ; then
1194             popd >/dev/null
1195             return 1
1196         fi
1197         if ! make ARCH=k1om modules_prepare ; then
1198             popd >/dev/null
1199             return 1
1200         fi
1201         cp -f ../boot/Module.symvers-* Module.symvers
1202     else
1203         if ! make defconfig-miclinux; then
1204             popd >/dev/null
1205             return 1
1206         fi
1207         if ! make -C card/kernel ARCH=k1om modules_prepare ; then
1208             popd >/dev/null
1209             return 1
1210         fi
1211     fi
1212     popd >/dev/null
1213
1214 }
1215
1216 stage() {
1217
1218     [ "$STAGEDIR" ] || return 0
1219
1220     for arch in $BUILD_ARCHS; do
1221         rpmdir="${STAGEDIR}/${CANONICAL_TARGET}-${arch}"
1222         echo "${0##*/}: Copying RPMs into ${rpmdir}"
1223         mkdir -p "${rpmdir}"
1224         cp -v RPMS/${arch}/*.rpm "${rpmdir}"
1225         if [ -d RPMS/noarch ]; then
1226             cp -v RPMS/noarch/*.rpm "${rpmdir}"
1227         fi
1228     done
1229
1230     cp -v "$LUSTRE" "$STAGEDIR"
1231
1232 }
1233
1234 set_rpm_smp_type() {
1235
1236     local infact_arch="${TARGET_ARCH}"
1237
1238     RPMSMPTYPE=""
1239     [ "$infact_arch" == "i586" ] && infact_arch="i686"
1240
1241     local smp_type
1242     for smp_type in $SMP_ARCHS; do
1243         [ $infact_arch == $smp_type ] && RPMSMPTYPE=smp && break
1244     done
1245
1246     for smp_type in $BIGSMP_ARCHS; do
1247         [ $infact_arch == $smp_type ] && RPMSMPTYPE=bigsmp && break
1248     done
1249
1250     for smp_type in $PPC64_ARCHS; do
1251         [ $infact_arch == $smp_type ] && RPMSMPTYPE=ppc64 && break
1252     done
1253
1254     for smp_type in $DEFAULT_ARCHS; do
1255         [ $infact_arch == $smp_type ] && RPMSMPTYPE=default && break
1256     done
1257
1258 }
1259
1260 # This function takes a linux include tree and digs out the linux release
1261 # from it. It is never called directly, only called from the distro
1262 # specific function find_linux_release() in lbuild-{rhel,sles}.
1263 _find_linux_release() {
1264     local SRC="$1"
1265     local LINUXRELEASEHEADER=""
1266
1267     LINUXRELEASEHEADER=$SRC/include/linux/version.h
1268     if [ -s $SRC/include/generated/utsrelease.h ]; then
1269         LINUXRELEASEHEADER=$SRC/include/generated/utsrelease.h
1270     elif [ -s $SRC/include/linux/utsrelease.h ]; then
1271         LINUXRELEASEHEADER=$SRC/include/linux/utsrelease.h
1272     fi
1273
1274     if [ ! -s $LINUXRELEASEHEADER ]; then
1275         fatal 1 "could not find UTS_RELEASE"
1276     fi
1277
1278     sed -ne 's/#define UTS_RELEASE "\(.*\)"$/\1/p' $LINUXRELEASEHEADER
1279 }
1280
1281 # unpack kernel(/source/devel) RPM
1282 #
1283 # This function and it's setting of $LINUX and $LINUXOBJ is a total hack that
1284 # needs to completely refactored.  It completely ingores that $BUILD_ARCHS may
1285 # contain a list of arches for which rpmbuild commands (including the one for
1286 # lustre itself)
1287 unpack_linux_devel_rpm() {
1288     local kernelrpm="${1}"
1289
1290     [ -f "$kernelrpm" ] || return 255
1291     [ -d $TOPDIR/reused ] || mkdir $TOPDIR/reused || return 255
1292
1293     pushd $TOPDIR/reused &>/dev/null || return 255
1294
1295     if ! rpm2cpio < "$kernelrpm" | cpio -id > /dev/null 2>&1; then
1296         return 255
1297     fi
1298
1299     # call a distro specific hook, if available
1300     if type -p unpack_linux_devel_rpm-$DISTROMAJ; then
1301         if ! unpack_linux_devel_rpm-$DISTROMAJ "$kernelrpm"; then
1302             return 255
1303         fi
1304     fi
1305
1306     popd &>/dev/null
1307
1308     find_linux_devel_paths $TOPDIR/reused
1309
1310     return 0
1311
1312 }
1313
1314 build_kernel_ib() {
1315     local linux="$1"
1316     local kib_prefix="$2"
1317     local kib_rpm="$3"
1318
1319     # build kernel-ib{,-devel}/compat-rdma{,-devel}
1320     local K_SRC="K_SRC"
1321     # ofed 1.3 had a bug in the rpm spec
1322     if [ "$OFED_VERSION" = "1.3" ]; then
1323         K_SRC="KSRC"
1324     fi
1325
1326     local OFED_CORE="--with-core-mod --with-ipoib-mod --with-user_mad-mod --with-user_access-mod --with-addr_trans-mod"
1327     local OFED_HARDWARE="--with-mthca-mod --with-mlx4-mod --with-mlx4_en-mod --with-cxgb3-mod --with-nes-mod --with-qib-mod"
1328
1329     if compare_version $OFED_VERSION 3.0; then
1330         OFED_CORE="$OFED_CORE --with-madeye-mod --with-rds-mod"
1331     else
1332         OFED_HARDWARE="$OFED_HARDWARE --with-mlx5-mod --with-cxgb4-mod --with-ocrdma-mod --with-qib-mod"
1333     fi
1334
1335     # some I/B drivers are architecture dependent and kernel-ib's configure
1336     # does not figure it out for us ~sigh~
1337     case "$TARGET_ARCH" in
1338         ppc64)
1339             OFED_HARDWARE="$OFED_HARDWARE --with-ehca-mod"
1340             ;;
1341     esac
1342     # we're no longer shipping the OFED iSCSI target
1343     #OFED_ISCSI="--with-srp-mod --with-srp-target-mod"
1344     OFED_ISCSI="--with-srp-mod"
1345     ## ISER module has no backport support as of OFED 1.5 (i.e. only builds on
1346     ##kernels >= 2.6.30)
1347     #if [[ $OFED_VERSION = 1.[0-4]* ]]; then
1348     #   OFED_ISCSI="$OFED_ISCSI --with-iser-mod"
1349     #fi
1350
1351     # assume we are just rebuilding the SRPM
1352     local BUILD_TYPE=${BUILD_TYPE:-"--rebuild"}
1353     local SOURCE="${TOPDIR}/OFED/SRPMS/${kib_prefix}-*.src.rpm"
1354
1355     # but switch to building from the SPEC if we need to apply patches
1356     if ls ${TOPDIR}/lustre/contrib/patches/ofed/* >/dev/null; then
1357         BUILD_TYPE="-bb"
1358         rpm --define "_topdir ${TOPDIR}" -ivh $SOURCE
1359         SOURCE="${TOPDIR}/SPECS/${kib_prefix}.spec"
1360         local file ed_fragment1 ed_fragment2 n=1
1361         for file in $(ls ${TOPDIR}/lustre/contrib/patches/ofed/*.patch); do
1362             ed_fragment1="$ed_fragment1
1363 Patch$n: ${file%%*/}"
1364             ed_fragment2="$ed_fragment2
1365 %patch$n -p0"
1366             cp $file ${TOPDIR}/SOURCES
1367             let n=$n+1
1368         done
1369         for file in $(ls ${TOPDIR}/lustre/contrib/patches/ofed/*.ed); do
1370             # Only apply the ed-scripts that should be used for the canonical target
1371             # ed-files in ${TOPDIR}/lustre/contrib/patches/ofed/ have to follow the naming
1372             # convention
1373             # <two-digits>-<descriptive-name>:<canonical_target_1>: ...:<canonical_target_N>.ed
1374             # To apply the same change to multiple canonical target simply specify
1375             # a list of colon separated canoncial target names in the file name.
1376             echo "$file" | grep -q -e ":${CANONICAL_TARGET}:" \
1377                                    -e ":${CANONICAL_TARGET}.ed$"
1378             if [ $? -eq 0 ] ; then
1379                 ed_fragment3="$ed_fragment3
1380 $(cat $file)"
1381                 let n=$n+1
1382             fi
1383         done
1384
1385         if [ $n -gt 1 ]; then
1386             ed $SOURCE <<EOF
1387 /^Source: /a
1388 $ed_fragment1
1389 .
1390 /^%setup /a
1391 $ed_fragment2
1392 .
1393 $ed_fragment3
1394 wq
1395 EOF
1396         fi
1397     fi
1398
1399     local linuxrelease=$(find_linux_release)
1400     if compare_version $OFED_VERSION 3.0; then
1401         local OFA_KERNEL_RELEASE=$(echo -n ${linuxrelease} | sed -e 's/-/_/g')
1402     fi
1403     if ! $RPMBUILD $BUILD_TYPE --define 'build_kernel_ib 1' --define 'build_kernel_ib_devel 1' \
1404                   ${FIND_REQUIRES:+--define "__find_requires $FIND_REQUIRES"} \
1405                   --define "_topdir ${TOPDIR}" --target ${TARGET_ARCH} \
1406                   --define "KVERSION ${linuxrelease}" \
1407                   --define "$K_SRC ${linux}" \
1408                   --define "LIB_MOD_DIR /lib/modules/${linuxrelease}/updates" \
1409                   ${OFA_KERNEL_RELEASE:+--define "_release $OFA_KERNEL_RELEASE"} \
1410                   --define "configure_options --without-quilt $OFED_CORE $OFED_HARDWARE $OFED_ISCSI" \
1411                   ${SOURCE} 2>&1; then
1412         fatal 1 "Error building ${kib_rpm}"
1413     fi
1414
1415 }
1416
1417 store_for_reuse() {
1418     local articles="$1"
1419     local module="$2"
1420     local location="$3"
1421     local signature="$4"
1422     local use_links="$5"
1423
1424     local linkflag=""
1425     if $use_links; then
1426         linkflag="l"
1427     fi
1428
1429     local default_iface=$(/sbin/ip route get 192.1.1.1 | sed -ne 's/.* dev \(.*\)  * src .*/\1/p')
1430     if [ -z "$default_iface" ]; then
1431         fatal 1 "Failed to determine the default route interface"
1432     fi
1433     local unique_id=$(/sbin/ip addr show dev $default_iface | sed -ne '/ inet /s/ *inet \(.*\)\/.*/\1/p' | head -1)
1434     if [ -z "$unique_id" ]; then
1435         fatal 1 "Failed to determine a unique id from interface $default_interface"
1436     fi
1437
1438     local finallocation="$location"/"$signature"/"$module"
1439     location="$location"/"$signature-${unique_id}"/"$module"
1440     mkdir -p "$location"
1441     # the cleanup script removes any directory that doesn't have a
1442     # .lastused, so let's try to prevent that as soon as we can
1443     # this solution still slightly racy with the cleanup script
1444     # but the race is a lot tighter now
1445     touch -t 197001010000 "$location/.lastused"
1446     ## use eval/echo here to make sure shell expansions are performed
1447     #if ! cp -a${linkflag} $(eval echo $articles) "$location"; then
1448     local article
1449     for article in $(eval echo $articles); do
1450         if ! cp -a${linkflag} "$article" "$location"; then
1451             error "Failed to copy \"$article\" to \"$location\" in store_for_reuse()"
1452             # rename the cache location so that it's not cached
1453             # product, but is around for analysis
1454             mv "$location"{,-bad-$(date +%s)} ||
1455                 error "failed to clean up a failed cache attempt" \
1456                       "in \"$location\" -- manual cleanup will be" \
1457                       "necessary"
1458             return 1
1459         fi
1460     done
1461
1462     # flag the cache as complete (i.e. in case lbuild was previously
1463     # interrupted while caching)
1464     touch "$location/.lastused"
1465
1466     # put the temporary location into the final location
1467     # (last one wins)
1468     mkdir -p "${finallocation%/*}"
1469     mv "$location" "$finallocation"
1470     rmdir "${location%/*}"
1471     return 0
1472
1473 }
1474
1475 reuse() {
1476     local module="$1"
1477     local dest="$2"
1478     local use_links="${3:-false}"
1479     local signature="$4"
1480
1481     if [ -n "$REUSEBUILD" ] && [ -d "$REUSEBUILD/$signature/$module" ]; then
1482         if [ ! -f "$REUSEBUILD/$signature/$module/.lastused" ]; then
1483             # the .lastused flag is populated at the end of the caching to
1484             # signal that the caching was completed.  if that flag is not
1485             # there, then the cache is invalid (and should be removed in fact)
1486             mv "$REUSEBUILD/$signature/$module"{,-bad-$(date +%s)} ||
1487                 fatal 1 "failed to clean up a bad cache in location $REUSEBUILD/$signature/$module\" -- manual cleanup will be necessary"
1488             return 1
1489         fi
1490
1491         # so that we know how stale this entry is
1492         touch $REUSEBUILD/$signature/$module/.lastused
1493
1494         if $use_links; then
1495             if ls $REUSEBUILD/$signature/$module/* >/dev/null 2>&1; then
1496                 cp -al $REUSEBUILD/$signature/$module/* $dest/
1497             fi
1498         else
1499             # copying is pretty heavy
1500             # cp -a $REUSEBUILD/$signature/$module/* $dest/
1501             # do some creative symlinking instead
1502             local dir
1503             for dir in BUILD SRPMS SPECS; do
1504                 if ls $REUSEBUILD/$signature/$module/$dir/* >/dev/null 2>&1; then
1505                     ln -s $REUSEBUILD/$signature/$module/$dir/* $dest/$dir
1506                 fi
1507             done
1508             # sources have to be copied by file because we need SOURCES to
1509             # be a dir we can write into
1510 # could overrun ls's arg list here
1511             #ls $REUSEBUILD/$signature/$module/SOURCES/* |
1512             find $REUSEBUILD/$signature/$module/SOURCES/ -type f |
1513                 xargs ln -t $dest/SOURCES -s
1514
1515             # same for RPMS/* dirs
1516 # could overrun ls's arg list here
1517             #ls $REUSEBUILD/$signature/$module/RPMS/$TARGET_ARCH/* |
1518             local dir
1519             for dir in $REUSEBUILD/$signature/$module/RPMS/*; do
1520                 mkdir -p $dest/RPMS/${dir##*/}
1521                 find $dir -type f |
1522                   xargs ln -t $dest/RPMS/${dir##*/} -s
1523             done
1524         fi
1525         return 0
1526     else
1527         return 1
1528     fi
1529 }
1530
1531 basearch() {
1532     local arch="$1"
1533
1534     if [[ $arch = i[3456]86 ]]; then
1535         echo "i386"
1536     else
1537         echo "$arch"
1538     fi
1539
1540 }
1541
1542 build_kernel_with_srpm() {
1543     local outfd=$1
1544
1545     if [ -z "$outfd" ] || [ $outfd = 1 ]; then
1546         fatal 1 "You must supply a file descriptor to ${FUNCNAME[0]} and it cannot be 1"
1547     fi
1548
1549     # need to generate the patch for this target
1550     do_patch_linux false >&${outfd}    # sets global $FULL_PATCH (yeah, yuck)
1551
1552     # get an md5sum of the kernel patch + config for reuse check
1553     # XXX really, there needs to be a signature and a CONFIG_FILE per arch
1554     #     in BUILD_ARCHS
1555     local release_str
1556     if $RELEASE; then
1557         local release_str="RELEASE=$RELEASE\n"
1558     fi
1559
1560     if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
1561         local REUSE_SIGNATURE=$({ echo -en $release_str;
1562                                   echo $BUILD_GEN;
1563                                   cat "$CONFIG_FILE";
1564                                   cat "$TARGET_FILE";
1565                                   cat "$FULL_PATCH";
1566                                   cat "$LBUILD_DIR/lbuild";
1567                                   cat "$LBUILD_DIR/lbuild-$DISTROMAJ"; } |
1568                                 md5sum | cut -d" " -f1)
1569         # see if we can link to the reuse pool
1570         # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
1571         #       "library"
1572         local CAN_LINK_FOR_REUSE=false
1573         touch $REUSEBUILD/$$
1574         if cp -al $REUSEBUILD/$$ $TOPDIR/ 2>/dev/null; then
1575             CAN_LINK_FOR_REUSE=true
1576         fi
1577         rm $REUSEBUILD/$$
1578     fi
1579
1580     # the extra version string to use for the kernel (which might be a reused
1581     # kernel, remember)
1582     local kernel_extra_version=""
1583     if ! $USE_BUILD_CACHE || ! reuse kernel "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
1584                                    "$REUSE_SIGNATURE"; then
1585         # nothing cached, build from scratch
1586         if [ ! -r "$KERNELDIR/$KERNEL_SRPM" ]; then
1587             echo "Downloading kernel SRPM" >&${outfd}
1588             download_srpm "$CANONICAL_TARGET" "$KERNEL_SRPM" >&${outfd}
1589         fi
1590
1591         if ! rpm -ivh $KERNELDIR/$KERNEL_SRPM \
1592                   --define "_topdir $TOPDIR" >&${outfd} 2>&1; then
1593             # should we clean this up or leave it for analysis?
1594             #rm -rf $RPMTOPDIR
1595             fatal 1 "Error installing kernel SRPM."
1596         fi
1597
1598         # put the Lustre kernel patch into the RPM build tree
1599         cp $FULL_PATCH $TOPDIR/SOURCES/linux-${lnxmaj}-lustre.patch
1600         prepare_and_build_srpm >&${outfd} ||
1601             fatal 1 "failed to prepare_and_build_srpm"
1602
1603         if [ -z "$REUSE_SIGNATURE" ]; then
1604             echo "No reuse signature was caculated so not storing the built kernel" >&${outfd}
1605         else
1606             # store the resulting kernel RPM build tree for future use
1607             echo "Storing the built kernel for future reuse" >&${outfd}
1608             if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,SRPMS,RPMS}" \
1609                                  "kernel" "$REUSEBUILD" "$REUSE_SIGNATURE" \
1610                                  "$CAN_LINK_FOR_REUSE"; then
1611                 error "Failed to store kernel RPMS for reuse"
1612                 echo "unknown" >&${outfd}
1613                 return 1
1614             fi
1615         fi
1616     fi  # build reuse
1617
1618     # figure out the EXTRA_VERSION of the kernel we built or are re-using
1619     local KERNEL_RPM
1620     if ! KERNEL_RPM=$(find_rpm "$TOPDIR/RPMS/$TARGET_ARCH/" provides "^kernel(-default)? ="); then
1621         fatal 1 "Failed to find a kernel RPM in $TOPDIR/RPMS/$TARGET_ARCH/"
1622     fi
1623     kernel_extra_version=$(rpm -q --queryformat "%{RELEASE}" -p $TOPDIR/RPMS/$TARGET_ARCH/$KERNEL_RPM)
1624
1625     # should now have the following RPMs
1626     # $TOPDIR/RPMS/$arch/kernel-lustre-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1627     # $TOPDIR/RPMS/$arch/kernel-lustre-devel-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1628     # $TOPDIR/RPMS/$arch/kernel-lustre-headers-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1629     # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-common-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1630     # $TOPDIR/RPMS/$arch/kernel-lustre-debuginfo-2.6.18-53.1.21.el5_lustre.1.6.5.1.$arch.rpm
1631
1632     echo $kernel_extra_version
1633     return 0
1634
1635 }
1636
1637 # build OFED
1638 # globals used:
1639 #    TOPDIR
1640 #    REUSEBUILD, USE_BUILD_CACHE
1641 #    CONFIGURE_FLAGS
1642
1643 build_ofed() {
1644     local linux="$1"
1645     local ofed_version="$2"
1646     local kib_prefix
1647     local kib_rpm
1648
1649     # if an ofed version is given, then it means use OFED proper,
1650     # not any vendor specific "inkernel" version
1651     if [ -z "$ofed_version" ]; then
1652         return 0
1653     fi
1654
1655     if [ "$ofed_version" = "inkernel" ]; then
1656         # see if there is a distro specific override for this and use
1657         # that if it exists
1658         # XXX we need to better integrate a distro specific override with
1659         #     the rest of this function so that all of the reuse cache
1660         #     stuff is leveraged given that 80% of this function is reuse
1661         if type -p build_ofed-$DISTROMAJ; then
1662             local ofed_location
1663             ofed_location=$(build_ofed-$DISTROMAJ ${STDOUT})
1664             local rc=${PIPESTATUS[0]}
1665             CONFIGURE_FLAGS="--with-o2ib=${ofed_location} ${CONFIGURE_FLAGS}"
1666             return $rc
1667         else
1668             return 0
1669         fi
1670     elif compare_version $OFED_VERSION 3.0; then
1671         kib_prefix="ofa_kernel"
1672         kib_rpm="kernel-ib"
1673     else
1674         kib_prefix="compat-rdma"
1675         kib_rpm="compat-rdma"
1676     fi
1677
1678     # build kernel-ib/compat-rdma
1679     if $USE_BUILD_CACHE && [ -n "$REUSEBUILD" ]; then
1680         local REUSE_SIGNATURE=$({ echo "$ofed_version";
1681                                   echo "$(find_linux_release;
1682                                   echo "$BUILD_GEN")";
1683                                   cat "${linux}/include/linux/autoconf.h";
1684                                   cat "$LBUILD_DIR/lbuild";
1685                                   cat "$LBUILD_DIR/lbuild-$DISTROMAJ"; } |
1686                                 md5sum | cut -d" " -f1)
1687         # see if we can link to the reuse pool
1688         # XXX - hrm.  i'm not convinced this doesn't belong in the reuse
1689         #       "library"
1690         local CAN_LINK_FOR_REUSE=false
1691         touch $REUSEBUILD/$$
1692         if cp -al $REUSEBUILD/$$ $TOPDIR/; then
1693             CAN_LINK_FOR_REUSE=true
1694         fi
1695         rm $REUSEBUILD/$$
1696     fi
1697
1698     if ! $USE_BUILD_CACHE || ! reuse ofed "$TOPDIR" "$CAN_LINK_FOR_REUSE" \
1699                                    "$REUSE_SIGNATURE"; then
1700         if [ -n "$REUSE_SIGNATURE" ]; then
1701             # stash away the existing built articles for a moment
1702             mkdir bak
1703             mv {BUILD,{S,}RPMS,S{OURCE,PEC}S} bak
1704             function mv_back {
1705                 pushd bak
1706                 find . | cpio -pudlm ..
1707                 popd
1708                 rm -rf bak
1709             }
1710             create_rpmbuild_dirs
1711         fi
1712         # build it
1713         build_kernel_ib "${linux}" "${kib_prefix}" "${kib_rpm}"
1714
1715         if [ -z "$REUSE_SIGNATURE" ]; then
1716             echo "No reuse signature was caculated so not storing the built ofed"
1717         else
1718             # store the resulting RPM build tree for future use
1719             echo "Storing the built ofed for future reuse"
1720             if ! store_for_reuse "$TOPDIR/{SPECS,SOURCES,BUILD,SRPMS,RPMS}" \
1721                                  "ofed" "$REUSEBUILD" "$REUSE_SIGNATURE" \
1722                                  "$CAN_LINK_FOR_REUSE"; then
1723                 error "Failed to store OFED RPMS for reuse"
1724                 mv_back
1725                 return 1
1726             fi
1727             # put the stuff we stashed away back
1728             mv_back
1729         fi
1730     fi
1731
1732     pushd "$TOPDIR" >/dev/null
1733     rm -rf ${kib_rpm}-devel
1734     mkdir ${kib_rpm}-devel
1735     cd ${kib_rpm}-devel
1736     # the actual ofed RPMs don't have the -rc$n or -$date string appened that
1737     # might be present on the file
1738     #local linuxrelease=$(find_linux_release)
1739     #ofed_version=$(echo $ofed_version |
1740     #               sed -re 's/-(20[0-9]{6,6}-[0-9]{4,4}|rc[0-9]*)$//')
1741     # FIXME
1742     # OFED version will have 'hyphen' for minor release. (e.g. 3.5-1, instead
1743     # of 3.5.1) compat-rdma and compat-rdma-devel could have same version
1744     # number, but currectly not. Once OFED fix this in the future release, we
1745     # can remove following filter.
1746     #ofed_version=$(echo $ofed_version |
1747     #               sed -re 's/-([0-9]*-[rR][cC][0-9]*)$//')
1748     #local rpm=$(ls $TOPDIR/RPMS/*/${kib_rpm}-devel-${ofed_version}-${linuxrelease//-/_}.*.rpm)
1749     # I dont' know why we have gone through the trouble to filter out the name
1750     # of the rpm there should only be one ${kib_rpm}-devel built
1751     local rpm=$(ls $TOPDIR/RPMS/*/${kib_rpm}-devel-*.rpm)
1752     if ! rpm2cpio < $rpm | cpio -id; then
1753         fatal 1 "could not unpack the ${kib_rpm}-devel rpm."
1754     fi
1755     CONFIGURE_FLAGS="--with-o2ib=$(pwd)/usr/src/${kib_prefix} ${CONFIGURE_FLAGS}"
1756     popd >/dev/null
1757
1758 }
1759
1760 build_with_srpm() {
1761
1762     if ! $PATCHLESS; then
1763         local kernel_extra_version
1764         if ! kernel_extra_version=$(build_kernel_with_srpm ${STDOUT}); then
1765             fatal 1 "Failed to build the kernel from it's SRPM"
1766         fi
1767
1768         for arch in $BUILD_ARCHS; do
1769             local kernel_devel_rpm
1770             if ! kernel_devel_rpm=$(find_rpm "$TOPDIR/RPMS/$arch/" provides "^$(devel_kernel_name $KERNEL_LUSTRE_NAMING) ="); then
1771                 fatal 1 "Failed to find a kernel development RPM in $TOPDIR/RPMS/$arch/"
1772             fi
1773
1774             # install the -devel RPM in preparation for modules builds
1775             if ! lnxrel="$kernel_extra_version" unpack_linux_devel_rpm \
1776                            "$TOPDIR/RPMS/$arch/$kernel_devel_rpm"; then
1777                 fatal 1 "Could not find the Linux tree in $TOPDIR/RPMS/$arch/$kernel_devel_rpm"
1778             fi
1779         done
1780     else
1781         # need to find and unpack the vendor's own kernel-devel for patchless
1782         # client build
1783         local kernelrpm
1784         if ! kernelrpm=$(find_linux_rpm "-$DEVEL_KERNEL_TYPE"); then
1785             fatal 1 "Could not find the kernel-$DEVEL_KERNEL_TYPE RPM in $KERNELRPMSBASE/$lnxmaj/$DISTROMAJ"
1786         fi
1787         if ! lnxrel="$lnxrel" unpack_linux_devel_rpm "$kernelrpm" "-"; then
1788             fatal 1 "Could not find the Linux tree in $kernelrpm"
1789         fi
1790     fi
1791
1792     # ~sigh~  have to make copies of and modify some of the rpm
1793     # infrastructure files so that find-requires can find our unpacked
1794     # kernel-devel artifacts
1795     cp $RPM_HELPERS_DIR/{symset-table,find-requires{,.ksyms}} .
1796     FIND_REQUIRES="$(pwd)/find-requires"
1797     chmod 755 {symset-table,find-requires{,.ksyms}}
1798     local tmp="$(pwd)"
1799     tmp="${tmp//\//\\/}"
1800     ed find-requires <<EOF
1801 1a
1802 set -x
1803 .
1804 /|.*find-requires.ksyms/s/|/| bash -x/
1805 g/ [^ ]*\/\(find-requires\.ksyms\)/s// $tmp\/\1/g
1806 wq
1807 EOF
1808     ed find-requires.ksyms <<EOF
1809 1a
1810 set -x
1811 .
1812 g/\/.*\/\(symset-table\)/s//$tmp\/\1/g
1813 wq
1814 EOF
1815     ed symset-table <<EOF
1816 1a
1817 set -x
1818 .
1819 g/\(\/boot\/\)/s//$tmp\/reused\1/g
1820 g/\(\/usr\/src\/kernels\/\)/s//$tmp\/reused\1/g
1821 wq
1822 EOF
1823
1824     build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
1825         fatal 1 "error building OFED"
1826
1827     # now build Lustre
1828     if build_lustre "$LINUX" "$LINUXOBJ"; then
1829         # the build worked.  resolve any symlinked files (i.e. from reuse)
1830         # in RPMS/$arch to real files so that that that huge mess of
1831         # complication known as LTS can copy them yet somewhere else.
1832         # is it any wonder this whole process is so damn so?  anyone ever
1833         # heard of hardlinks?  it's this cool new thing that allows you save
1834         # tons of time and space by creating... well you can go read about
1835         # them if you have not heard about them yet.
1836         # can i say how much the implemenation of all of this really impedes
1837         # RPM reuse?
1838         local dir
1839         for dir in RPMS/*; do
1840             pushd $dir
1841             for file in $(ls); do
1842                 if [ -h $file ]; then
1843                     cp $file foo
1844                     mv foo $file
1845                 fi
1846             done
1847             popd
1848         done
1849         # also, for i?86, make sure all of the RPMs are in RPMS/$TARGET_ARCH
1850         # as that's where LTS expects to find them
1851         for dir in RPMS/*; do
1852             if [ $dir = RPMS/$TARGET_ARCH ]; then
1853                 continue
1854             fi
1855             pushd $dir
1856             local files=$(ls)
1857             if [ -n "$files" ]; then
1858                 cp -al $files ../$TARGET_ARCH
1859             fi
1860             popd
1861         done
1862     else
1863         return 1
1864     fi
1865
1866 }
1867
1868 create_rpmbuild_dirs() {
1869
1870     [ -d RPMS ] || mkdir RPMS
1871     for arch in $BUILD_ARCHS; do
1872         if [[ $arch = i?86 ]]; then
1873             # some stupidity in the sles11 kernel spec requires an RPMS/i386
1874             # even if the target arch is i686
1875             [ -d RPMS/i386 ] || mkdir RPMS/i386
1876         fi
1877         [ -d RPMS/$arch ] || mkdir RPMS/$arch
1878     done
1879     [ -d RPMS/noarch ] || mkdir RPMS/noarch
1880     [ -d BUILD ] || mkdir BUILD
1881     [ -d SOURCES ] || mkdir SOURCES
1882     [ -d SPECS ] || mkdir SPECS
1883     [ -d SRPMS ] || mkdir SRPMS
1884
1885 }
1886
1887 new_list() {
1888
1889     echo ""
1890
1891 }
1892
1893 add_list() {
1894     local list="$1"
1895     local item="$2"
1896
1897     echo "$list $item"
1898
1899 }
1900
1901 is_list_member() {
1902     local list="$1"
1903     local item="$2"
1904
1905     [[ $list\  == *\ $item\ * ]]
1906
1907 }
1908
1909 #########################################################################
1910 # Generate a backtrace through the call stack.
1911 #
1912 # Input: None
1913 # Output: None
1914 #########################################################################
1915 backtrace() {
1916     local strip=${1:-1}
1917
1918     local funcname="" sourcefile="" lineno="" n
1919
1920     echo "Call stack: (most recent first)"
1921     for (( n = $strip ; n < ${#FUNCNAME[@]} ; ++n )) ; do
1922         funcname=${FUNCNAME[$n - 1]}
1923         sourcefile=$(basename ${BASH_SOURCE[$n]})
1924         lineno=${BASH_LINENO[$n - 1]}
1925         if [ $n = 1 ]; then
1926             let lineno-=11
1927         fi
1928         # Display function arguments
1929         if [[ ! -z "${BASH_ARGV[@]}" ]]; then
1930             local args newarg j p=0
1931             for (( j = ${BASH_ARGC[$n - 1]}; j > 0; j-- )); do
1932                 newarg=${BASH_ARGV[$j + $p - 1]}
1933                 args="${args:+${args} }'${newarg}'"
1934             done
1935             let p+=${BASH_ARGC[$n - 1]}
1936         fi
1937         echo "  ${funcname} ${args:+${args} }at ${sourcefile}:${lineno}"
1938     done
1939
1940     echo
1941     echo "BEGIN BACKTRACE"
1942
1943     #echo ${BASH_LINENO[*]}
1944     #echo ${BASH_SOURCE[*]}
1945     #echo ${FUNCNAME[*]}
1946     local i=$((${#FUNCNAME[@]} - 1))
1947     while [ $i -ge 0 ]; do
1948         local lineno=${BASH_LINENO[$i]}
1949         if [ $i = 0 ]; then
1950             let lineno-=11
1951         fi
1952         local SOURCELINE="${BASH_SOURCE[$i + 1]}:${lineno}"
1953         # Can't figure out how to get function args from other frames...
1954         local FUNCTION="${FUNCNAME[$i]}()"
1955         echo "$SOURCELINE:$FUNCTION"
1956         i=$((i - 1))
1957     done
1958
1959     echo "END BACKTRACE"
1960
1961     echo $BACKTRACE
1962
1963 }
1964
1965 seen_list=$(new_list)
1966 trap 'set +x;
1967 echo "An unexpected error has occurred at ${BASH_SOURCE[0]##*/}:$((LINENO-1)).
1968 Unfortunately the above line number in the message may or may not be correct,
1969 but details have been send to the lbuild maintainer.  Attempting to continue."; (echo "Untrapped error"
1970 echo
1971 # have we seen this one
1972 echo "checking seen list for ${BASH_SOURCE[0]}:${BASH_LINENO[0]}"
1973
1974 if is_list_member "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}"; then
1975   echo "seen this one already"
1976 else
1977   seen_list=$(add_list "$seen_list" "${BASH_SOURCE[0]}:${BASH_LINENO[0]}")
1978 fi
1979 backtrace
1980 ) ; set $xtrace' ERR
1981 set -E
1982
1983 [ -r ~/.lbuildrc ] && . ~/.lbuildrc
1984
1985 options=$(getopt -o D:h -l kerneltree:,distro:,kernelrpm:,reusebuild:,patchless,ccache,norpm,external-patches:,timestamp:,extraversion:,kerneldir:,linux:,lustre:,nodownload,nosrc,noiokit,ofed-version:,mpss-version:,publish,release,set-value:,src,stage:,target:,target-archs:,with-linux:,xen -- "$@")
1986
1987 if [ $? != 0 ]; then
1988     usage 1
1989 fi
1990
1991 eval set -- "$options"
1992
1993 while [ "$1" ]; do
1994     case "$1" in
1995         '')
1996             usage 1
1997             ;;
1998         --ccache)
1999             CCACHE='ccache'
2000             shift
2001             ;;
2002         -D)
2003             DATE=$2
2004             shift 2
2005             ;;
2006         --external-patches)
2007             EXTERNAL_PATCHES=$2
2008             shift 2
2009             ;;
2010         --extraversion)
2011             EXTRA_VERSION=$2
2012             shift 2
2013             ;;
2014         --help | -h)
2015             usage 0
2016             ;;
2017         --kerneldir)
2018             KERNELDIR=$2
2019             shift 2
2020             ;;
2021         --kerneltree)
2022             if ! KERNELTREE=$(canon_path "$2"); then
2023                 fatal 1 "Could not determine the canonical location of $2"
2024             fi
2025             shift 2
2026             ;;
2027         --linux | --with-linux)
2028             if ! LINUX=$(canon_path "$2"); then
2029                 fatal 1 "Could not determine the canonical location of $2"
2030             fi
2031             shift 2
2032             ;;
2033         --distro)
2034             DISTRO=$2
2035             shift 2
2036             ;;
2037         --reusebuild)
2038             if ! REUSEBUILD=$(canon_path "$2"); then
2039                 fatal 1 "Could not determine the canonical location of $2"
2040             fi
2041             shift 2
2042             ;;
2043         --norpm)
2044             NORPM=true
2045             shift
2046             ;;
2047         --noiokit)
2048             IOKITRPM=false
2049             shift
2050             ;;
2051         --patchless)
2052             PATCHLESS=true
2053             shift
2054             ;;
2055         --kernelrpm)
2056             if ! KERNELRPMSBASE=$(canon_path "$2"); then
2057                 fatal 1 "Could not determine the canonical location of $2"
2058             fi
2059             shift 2
2060             ;;
2061         --timestamp)
2062             TIMESTAMP=$2
2063             shift 2
2064             ;;
2065         --lustre)
2066             if ! LUSTRE=$(canon_filepath "$2"); then
2067                 fatal 1 "Could not determine the canonical location of $2"
2068             fi
2069             shift 2
2070             ;;
2071         --nodownload)
2072             DOWNLOAD=false
2073             shift 1
2074             ;;
2075         --nosrc)
2076             DO_SRC=false
2077             shift 1
2078             ;;
2079         --ofed-version)
2080             OFED_VERSION="$2"
2081             shift 2
2082             ;;
2083         --mpss-version)
2084             MPSS_VERSION="$2"
2085             shift 2
2086             ;;
2087         --publish)
2088             shift
2089             ;;
2090         --release)
2091             RELEASE=true
2092             shift
2093             ;;
2094         --src)
2095             DO_SRC=true
2096             shift 1
2097             ;;
2098         --stage)
2099             STAGEDIR=$2
2100             shift 2
2101             ;;
2102         --target)
2103             TARGET=$2
2104             shift 2
2105             ;;
2106         --target-archs)
2107             TARGET_ARCHS=$2
2108             shift 2
2109             ;;
2110         --xen)
2111             XEN=true
2112             shift
2113             ;;
2114         --set-value)
2115             eval $2
2116             shift 2
2117             ;;
2118         --)
2119             shift
2120             # there are actually some lustre configure flags that we need to
2121             # handle ourselves (but we still give them to configure)
2122             if [[ \ $@\  == *\ --disable-tests\ * ]]; then
2123                 LUSTRE_TESTS=false
2124             fi
2125             CONFIGURE_FLAGS=$@
2126             break
2127             ;;
2128         *)
2129             usage 1 "Unrecognized option: $1"
2130             ;;
2131     esac
2132 done
2133
2134 check_options
2135
2136 unpack_lustre
2137
2138 # XXX - should we _always_ get the buildid from the META file?  what are the
2139 # other (i.e. non-lustre-tarball use cases of lbuild)?
2140 BUILDID=$(sed -n -e 's/^BUILDID = //p' lustre/META)
2141
2142 load_target
2143
2144 if [ -n "$OFED_VERSION" -a "$OFED_VERSION" != "inkernel" ]; then
2145     download_ofed
2146     unpack_ofed || fatal 1 "Error unpacking OFED tarball"
2147 fi
2148
2149 if [ -n "$MPSS_VERSION" ]; then
2150     [ -z "$MPSS_DISTRO" ] && MPSS_DISTRO=$(autodetect_distro)
2151
2152     MPSS_INFO=$(mktemp -u mpss-info-XXXXXXXXXX.html)
2153     download_mpss_info "$MPSS_INFO"
2154
2155     if [ "$MPSS_VERSION" = "last" ]; then
2156         MPSS_VERSION=$(parse_mpss_info "$MPSS_INFO" "" ${MPSS_DISTRO})
2157         [ -z "$MPSS_VERSION" ] &&
2158             fatal 1 "Could not determine the last MPSS version"
2159     fi
2160
2161     download_mpss "$MPSS_INFO"
2162     [ -r "$MPSS_INFO" ] && rm -f "$MPSS_INFO"
2163     echo "Building with MPSS $MPSS_VERSION"
2164     unpack_mpss  || fatal 1 "Error unpacking MPSS tarballs"
2165     prepare_mpss || fatal 1 "Error preparing MPSS for kernel modules build"
2166
2167     if [ -z "$MPSS_OFED" ]; then
2168         MPSS_OFED=$(find $PWD -type f -path "*/ofed-driver-*/Module.symvers")
2169         if [ -n "$MPSS_OFED" ]; then
2170             MPSS_OFED="--with-o2ib=$(dirname $MPSS_OFED)"
2171         else
2172             MPSS_OFED="--without-o2ib"
2173         fi
2174     fi
2175
2176     # disable unsupported parts:
2177     PATCHLESS=true
2178     IOKITRPM=false
2179     LDISKFSRPM=false
2180     ZFSNOTSUPPORTED="yes"
2181
2182     # define variables for cross compilation:
2183     CROSS_SUFFIX="-mic"
2184     if [ "${MPSS_VERSION%%.*}" = "3" ]; then
2185         CC_TARGET_ARCH=k1om-mpss-linux
2186         LINUX="$TOPDIR/mpss"
2187         RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"cross_requires /bin/sh\""
2188     else
2189         CC_TARGET_ARCH=x86_64-k1om-linux
2190         LINUX="$TOPDIR/mpss/card/kernel"
2191         RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"cross_requires intel-mic-gpl = ${MPSS_VERSION%%-*}\""
2192     fi
2193     LUSTRE_VERSION=$(sed -n -e 's/^VERSION = //p' lustre/META)
2194     CONFIGURE_FLAGS="$CONFIGURE_FLAGS $MPSS_OFED --host=$CC_TARGET_ARCH --build=x86_64-pc-linux"
2195     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"post_script build/gen_filelist.sh\""
2196     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"make_args ARCH=k1om CROSS_COMPILE=${CC_TARGET_ARCH}-\""
2197     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"cross_path ${CROSS_PATH:=/opt/lustre/${LUSTRE_VERSION}/${CC_TARGET_ARCH}}\""
2198     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"rootdir %{cross_path}\""
2199     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"_prefix %{cross_path}/usr\""
2200     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"_mandir %{_prefix}/share/man\""
2201     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"_sysconfdir %{cross_path}/etc\""
2202     RPMBUILD_DEFS="$RPMBUILD_DEFS --define \"kmoddir extra\""
2203
2204     # redefine CC for proper ./configure during rpmbuild
2205     export CC=${CC_TARGET_ARCH}-gcc
2206 fi
2207
2208 # make sure the RPM build environment is set up
2209 create_rpmbuild_dirs
2210
2211 # if an unpacked kernel source tree was given on the command line
2212 # just build lustre with it (nothing distro kernel specific here)
2213 if [ -n "$LINUX" ]; then
2214     find_linux_release() {
2215         _find_linux_release $LINUX
2216     }
2217     build_ofed "${LINUXOBJ:-$LINUX}" "$OFED_VERSION" ||
2218         fatal 1 "error building OFED"
2219     build_lustre "$LINUX" "$LINUXOBJ"
2220 else
2221     if [ ! -f "${LBUILD_DIR}/lbuild-$DISTROMAJ" ]; then
2222         fatal 1 "${LBUILD_DIR}/lbuild-$DISTROMAJ not found"
2223     fi
2224     source ${LBUILD_DIR}/lbuild-$DISTROMAJ
2225     build_with_srpm || fatal 1 "Failed to build_with_srpm"
2226 fi
2227
2228 stage