#!/bin/bash ############################################################################ # # Copyright (C) 2008-2009 Bart Van Assche # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation, version 2 # of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ############################################################################ ############################################################################ # # The recommended way to use this script is as follows: # - Create an additional user, e.g. builder # - Add a line to the sudoers file that allows that user to invoke yum and # yum-builddep. One way to do that is by invoking the following shell # commands as root: # useradd builder # echo 'builder ALL=(ALL) NOPASSWD: /usr/bin/yum, /usr/bin/yum-builddep' >>/etc/sudoers # visudo -sc # # For more information about building a custom RHEL / CentOS / Scientific Linux # kernel RPM, see also: # * CentOS wiki, "I Need to Build a Custom Kernel" # (http://wiki.centos.org/HowTos/Custom_Kernel). # * Fedora wiki, "Building a custom kernel" # (http://fedoraproject.org/wiki/Building_a_custom_kernel). # ############################################################################ scriptdir="$(dirname "$0")" if [ "${scriptdir:0:1}" != "/" ]; then scriptdir="$PWD/${scriptdir}" fi scriptdir="${scriptdir%/.}" source "${scriptdir}/rhel-rpm-functions" scst_dir="$(dirname "$scriptdir")" downloaddir=$HOME/software/downloads rpmbuild_dir=$HOME/rpmbuild if echo "$(uname -r)" | grep -q uek; then kernel="kernel-uek-$(uname -r)" else kernel="kernel-$(uname -r)" fi releasever="$(sed -n -e 's/^.* release \([0-9.]*\).*$/\1/p' /etc/redhat-release)" distro="$(sed -n -e 's/^\(.*\) release .*$/\1/p' /etc/redhat-release)" install_prerequisites=true usage() { echo "$(basename "$0") [-d ] [-h] [-i] [-k ] [-r ]" } type /usr/bin/getopt >/dev/null || exit 1 options="$(/usr/bin/getopt d:hik:r: "$@")" || { usage; exit 1; } set -- $options while [ "$1" != "${1#-}" ]; do case "$1" in '-d') distro="$2"; shift; shift;; '-i') install_prerequisites="false"; shift;; '-k') kernel="$2"; shift; shift;; '-r') releasever="$2"; shift; shift;; '--') shift; break;; *) usage; exit 1;; esac done arch="$(uname -m)" kernel="${kernel%.${arch}}" kernel_src_rpm="${kernel}.src.rpm" kver="${kernel#kernel-}" srpm_urls="$(get_srpm_urls "$distro" "$releasever" "$arch")" || exit $? function log { echo printf "$@" echo } copy_best_matching_patch() { local f v v="${kver}" while [ "${v%[0-9a-z]}" != "$v" ]; do f="${1}-${v}.patch" if [ -e "$f" ]; then copy_patch "$f" "$2" return 0 fi while [ "${v%[0-9a-z]}" != "$v" ]; do v="${v%[0-9a-z]}" done v="${v%.}" v="${v%-}" done return 1 } function copy_patch { local p="$1" while [ ! -e "$p" ] do local q="$(echo "$p" | sed 's/[.-][a-z0-9]*\.patch$/.patch/')" if [ "$q" = "$p" ]; then break; fi p="$q" done if [ ! -e "$p" ]; then echo "Error: patch $1 not found" echo "Please report this on the scst-devel mailing list" exit 1 fi ln -s "$p" "$2" } function rpmbuild { /usr/bin/rpmbuild \ --define="%_topdir ${rpmbuild_dir}" \ --define="%buildid .scst" \ "$@" } if [ -e ${rpmbuild_dir} ]; then echo "You have to remove the ${rpmbuild_dir} directory before starting $0" exit 1 fi if [ ! -e "${scst_dir}" ]; then echo "Error: directory ${scst_dir} not found. Please modify scst_dir in $0." exit 1 fi log "Installing prerequisites" if $install_prerequisites; then for p in \ asciidoc \ audit-libs-devel \ binutils-devel \ elfutils-devel \ elfutils-libelf-devel \ hmaccalc \ ncurses-devel \ newt-devel \ patchutils \ numactl-devel \ pciutils-devel \ 'perl(ExtUtils::Embed)' \ pesign \ python-devel \ redhat-rpm-config \ rng-tools \ rpm-build \ rpmdevtools \ unifdef \ wget \ xmlto \ yum-utils \ zlib-devel \ ; do sudo yum install -y -q "$p"; done fi rc=$?; if [ $rc != 0 ]; then exit $rc; fi log "Creating directory ${rpmbuild_dir}" mkdir -p ${rpmbuild_dir}/{BUILD,RPMS,SOURCES,SPECS,SRPMS} log "Installing, unpacking and preparing kernel source files" mkdir -p ${downloaddir} if [ ! -e ${downloaddir}/${kernel_src_rpm} ]; then cd ${downloaddir} for dir in ${srpm_urls} do url="$dir/${kernel_src_rpm}" echo "Trying $url ..." if wget -q "$url"; then break fi done if [ ! -e ${downloaddir}/${kernel_src_rpm} ]; then echo "Downloading kernel source RPM ${kernel_src_rpm} failed." exit 1 fi fi log "Installing kernel build prerequisites" if $install_prerequisites; then sudo yum-builddep -q -y ${downloaddir}/${kernel_src_rpm} fi log "Installing kernel sources in ${rpmbuild_dir}" cd ${rpmbuild_dir} rpm --define="%_topdir ${rpmbuild_dir}" -i ${downloaddir}/${kernel_src_rpm} 2>&1 \ | grep -v ' does not exist' cd SPECS { rpmbuild -bp --target=${arch} kernel*.spec rc=$? if [ rc != 0 ]; then exit $rc fi } 2>&1 | tee prep-err.log log "Copying SCST patches to the SOURCES directory" cd ${rpmbuild_dir}/SOURCES copy_best_matching_patch $scst_dir/scst/kernel/rhel/scst_exec_req_fifo scst_exec_req_fifo.patch copy_best_matching_patch $scst_dir/iscsi-scst/kernel/patches/rhel/put_page_callback put_page_callback.patch || { echo "No matching put_page_callback patch found for kernel version $kver"; exit 1; } log "Adding SCST patches in kernel.spec" if [ ${kver#2.6.18} != $kver ]; then if [ -e ${rpmbuild_dir}/SPECS/kernel-2.6.spec ]; then # RHEL/CentOS/SL 5.6 patch -p1 ${rpmbuild_dir}/SPECS/kernel-2.6.spec <<'EOF' || exit $? diff -u SPECS/kernel-2.6.spec{.orig,} --- SPECS/kernel-2.6.spec.orig +++ SPECS/kernel-2.6.spec @@ -6386,6 +6386,9 @@ # empty final patch file to facilitate testing of kernel patches Patch99999: linux-kernel-test.patch +Patch200: scst_exec_req_fifo.patch +Patch201: put_page_callback.patch + # END OF PATCH DEFINITIONS BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -12593,6 +12596,10 @@ rm -f kernel-%{kversion}-*-debug.config %endif +%patch200 -p1 +%patch201 -p1 +sed -i.tmp -e 's/^CONFIG_SCSI_QLA_FC=.*/CONFIG_SCSI_QLA_FC=n/' *.config + # now run oldconfig over all the config files for i in *.config do EOF else # RHEL/CentOS/SL 5.7 patch -p1 ${rpmbuild_dir}/SPECS/kernel.spec <<'EOF' || exit $? --- SPECS/kernel.spec.orig +++ SPECS/kernel.spec @@ -425,6 +425,9 @@ Patch2: xen-config-2.6.18-redhat.patch Patch3: xen-2.6.18-redhat.patch +Patch200: scst_exec_req_fifo.patch +Patch201: put_page_callback.patch + # empty final patch file to facilitate testing of kernel patches Patch99999: linux-kernel-test.patch @@ -733,6 +736,10 @@ rm -f kernel-%{version}-*-debug.config %endif +%patch200 -p1 +%patch201 -p1 +sed -i.tmp -e 's/^CONFIG_SCSI_QLA_FC=.*/CONFIG_SCSI_QLA_FC=n/' *.config + # now run oldconfig over all the config files for i in *.config do EOF fi elif [ ${kver#2.6.32-71} != $kver ]; then # RHEL/CentOS/SL 6.0 patch -p1 ${rpmbuild_dir}/SPECS/kernel.spec <<'EOF' || exit $? diff -u SPECS/kernel.spec{.orig,} --- SPECS/kernel.spec.orig +++ SPECS/kernel.spec @@ -601,6 +601,9 @@ Source82: config-s390x-debug Source83: config-s390x-debug-rhel +#Patch200: scst_exec_req_fifo.patch +Patch201: put_page_callback.patch + # empty final patch file to facilitate testing of kernel patches Patch999999: linux-kernel-test.patch @@ -891,6 +894,9 @@ # Dynamically generate kernel .config files from config-* files make -f %{SOURCE20} VERSION=%{version} configs +#ApplyPatch scst_exec_req_fifo.patch +ApplyPatch put_page_callback.patch + ApplyOptionalPatch linux-kernel-test.patch # Any further pre-build tree manipulations happen here. @@ -917,6 +923,8 @@ for i in *.config do mv $i .config + echo "CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION=y" >> .config + sed -i.tmp -e 's/^CONFIG_SCSI_QLA_FC=.*/CONFIG_SCSI_QLA_FC=n/' .config Arch=`head -1 .config | cut -b 3-` make ARCH=$Arch %{oldconfig_target} > /dev/null echo "# $Arch" > configs/$i EOF elif [ ${kver#2.6.32-131} != $kver -o ${kver#2.6.32-220} != $kver \ -o ${kver#2.6.32-279} != $kver -o ${kver#2.6.32-358} != $kver \ -o ${kver#2.6.32-431} != $kver ]; then # RHEL/CentOS/SL 6.1, 6.2, 6.3, 6.4 or 6.5 patch -p1 ${rpmbuild_dir}/SPECS/kernel.spec <<'EOF' || exit $? # RHEL/CentOS/SL 6.x diff -u SPECS/kernel.spec{.orig,} --- SPECS/kernel.spec.orig +++ SPECS/kernel.spec @@ -601,6 +601,9 @@ Source82: config-generic Source83: config-x86_64-debug-rhel +#Patch200: scst_exec_req_fifo.patch +Patch201: put_page_callback.patch + # empty final patch file to facilitate testing of kernel patches Patch999999: linux-kernel-test.patch @@ -891,6 +894,9 @@ # Dynamically generate kernel .config files from config-* files make -f %{SOURCE20} VERSION=%{version} configs +#ApplyPatch scst_exec_req_fifo.patch +ApplyPatch put_page_callback.patch + ApplyOptionalPatch linux-kernel-test.patch # Any further pre-build tree manipulations happen here. @@ -917,6 +923,8 @@ for i in *.config do mv $i .config + echo "CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION=y" >> .config + sed -i.tmp -e 's/^CONFIG_SCSI_QLA_FC=.*/CONFIG_SCSI_QLA_FC=n/' .config Arch=`head -1 .config | cut -b 3-` make ARCH=$Arch %{oldconfig_target} > /dev/null echo "# $Arch" > configs/$i EOF elif [ ${kver#2.6.32-504.} != $kver ]; then # RHEL/CentOS/SL 6.6 patch -p1 ${rpmbuild_dir}/SPECS/kernel.spec <<'EOF' || exit $? diff -u SPECS/kernel.spec{.orig,} --- kernel.spec.orig 2014-12-03 16:20:14.764118318 +0100 +++ kernel.spec 2014-12-03 16:21:36.606089530 +0100 @@ -610,6 +610,9 @@ Source85: config-powerpc64-debug-rhel Source86: config-s390x-debug-rhel +#Patch200: scst_exec_req_fifo.patch +Patch201: put_page_callback.patch + # empty final patch file to facilitate testing of kernel patches Patch999999: linux-kernel-test.patch @@ -932,6 +935,9 @@ # Dynamically generate kernel .config files from config-* files make -f %{SOURCE20} VERSION=%{version} configs +#ApplyPatch scst_exec_req_fifo.patch +ApplyPatch put_page_callback.patch + ApplyOptionalPatch linux-kernel-test.patch # Any further pre-build tree manipulations happen here. @@ -958,6 +964,8 @@ for i in *.config do mv $i .config + echo "CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION=y" >> .config + sed -i.tmp -e 's/^CONFIG_SCSI_QLA_FC=.*/CONFIG_SCSI_QLA_FC=n/' .config Arch=`head -1 .config | cut -b 3-` make ARCH=$Arch %{oldconfig_target} > /dev/null echo "# $Arch" > configs/$i EOF elif [ ${kver#3.10.0-12[13]} != $kver ]; then # RHEL/CentOS/SL 7.0 patch -p1 ${rpmbuild_dir}/SPECS/kernel.spec <<'EOF' || exit $? --- kernel.spec.orig 2014-05-23 10:09:17.707202148 +0200 +++ kernel.spec 2014-05-23 10:15:50.883937952 +0200 @@ -4,6 +4,7 @@ Summary: The Linux kernel # % define buildid .local +%define buildid .scst # For a stable, released kernel, released_kernel should be 1. For rawhide # and/or a kernel built from an rc or git snapshot, released_kernel should @@ -367,6 +368,9 @@ Source2000: cpupower.service Source2001: cpupower.config +#Patch200: scst_exec_req_fifo.patch +Patch201: put_page_callback.patch + # empty final patch to facilitate testing of kernel patches Patch999999: linux-kernel-test.patch @@ -668,6 +672,9 @@ # Drop some necessary files from the source dir into the buildroot cp $RPM_SOURCE_DIR/kernel-%{version}-*.config . +#ApplyPatch scst_exec_req_fifo.patch +ApplyPatch put_page_callback.patch + ApplyOptionalPatch linux-kernel-test.patch # Any further pre-build tree manipulations happen here. @@ -700,6 +707,8 @@ for i in *.config do mv $i .config + echo "CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION=y" >> .config + sed -i.tmp -e 's/^CONFIG_SCSI_QLA_FC=.*/CONFIG_SCSI_QLA_FC=n/' .config Arch=`head -1 .config | cut -b 3-` make %{?cross_opts} ARCH=$Arch listnewconfig | grep -E '^CONFIG_' >.newoptions || true %if %{listnewconfig_fail} EOF else log "Unrecognized kernel version ${kver}" fi log "Rebuilding kernel" cd ${rpmbuild_dir}/SPECS { rpmbuild -bb --target=${arch} --nodeps --with baseonly --with firmware --without kabichk kernel*.spec rc=$? if [ $rc != 0 ]; then exit $rc fi } 2>&1 | tee build.log log "Ready. You can now install the freshly built kernel RPM as follows:\nsudo rpm -ivh --force $HOME/rpmbuild/RPMS/${arch}/kernel-*.rpm"