Files
scst/scripts/run-regression-tests
Bart Van Assche 706eee64fd Only apply patch d9ad8bc0ca823705413f75b50c442a88cc518b35 to kernels
2.6.29 up to and including 2.6.29.3 since this patch is included in
2.6.29.4 and higher and also in 2.6.30 and higher.


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@868 d57e44dd-8a1f-0410-8b47-8ef2f437770f
2009-05-20 16:48:14 +00:00

554 lines
18 KiB
Bash
Executable File

#!/bin/bash
############################################################################
#
# Script for running those SCST regression tests that can be run automatically.
#
# Copyright (C) 2008 Bart Van Assche <bart.vanassche@gmail.com>
#
# 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.
#
############################################################################
############################################################################
# This script performs the following actions:
# - Creates a temporary directory for storing the output of the regression
# tests. No existing files are modified by this script.
# - Verifies whether the top-level *.patch files apply cleanly to the SCST
# tree.
# - Duplicates the entire source tree to the temporary directory and
# compiles the SCST source code.
# - Duplicates the entire source tree to the temporary directory, applies
# the full-perf patches and again compiles the SCST source code.
# - Checks whether the specified kernel version is present
# in the directory specified through option -c.
# - If the source code of the specified kernel version is not present,
# download it.
# - Convert the SCST source code into a kernel patch.
# - Extract the kernel sources.
# - Run checkpatch on the SCST kernel patch.
# - Apply the SCST kernel patch to the kernel tree.
# - Run 'make allmodconfig'.
# - Run the sparse source code checker on the SCST directory.
# - Run 'make headers_check'.
# - Compile the kernel tree.
# - Run 'make checkstack'.
# - Run 'make namespacecheck'.
# - Run 'make htmldocs'.
#
# Note: the results of the individual steps are not verified by this script
# -- the output generated by the individual steps has to be verified by
# reviewing the output files written into the temporary directory.
############################################################################
########################
# Function definitions #
########################
function usage {
echo "Usage: $0 [-c] [-d] [-f] [-h] [-j] [-q] <kver1> <kver2> ..."
echo " -c - cache directory for Linux kernel tarballs."
echo " -d - directory for temporary regression test files."
echo " -f - full check -- do not only compile SCST but the whole" \
"kernel tree."
echo " -h - display this help information."
echo " -j - number of jobs that 'make' should run simultaneously."
echo " -q - download kernel sources silently."
echo " <kver1> <kver2> ... - kernel versions to test."
}
# First three components of the kernel version number.
function kernel_version {
echo "$1" | sed -n 's/^\([0-9]*\.[0-9]*\.[0-9]*\).*$/\1/p'
}
# Last component of the kernel version, or the empty string if $1 has only
# three components.
function patchlevel {
echo "$1" | sed -n 's/^\([0-9]*\.[0-9]*\.[0-9]*\)[.-]\(.*\)$/\2/p'
}
# Create a linux-$1 tree in the current directory, where $1 is a kernel
# version number with either three or four components.
function extract_kernel_tree {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local tmpdir=kernel-tree-tmp-$$
rm -rf "linux-$1" "${tmpdir}"
mkdir "${tmpdir}" || return $?
(
cd "${tmpdir}" || return $?
tar xjf "${kernel_sources}/linux-${kver}.tar.bz2" || return $?
cd "linux-${kver}" || return $?
if [ "${plevel}" != "" ]; then
bzip2 -cd "${kernel_sources}/patch-$1.bz2" \
| patch -p1 -f -s || return $?
fi
cd ..
mv "linux-${kver}" "../linux-$1" || return $?
if [ "$1" = "2.6.29" -o "$1" = "2.6.29.1" -o "$1" = "2.6.29.2" -o "$1" = "2.6.29.3" ]
then
cd "../linux-$1" || return $?
patch -f -s -p1 <<'EOF'
Make sure that branch profiling does not trigger sparse warnings.
See also http://bugzilla.kernel.org/show_bug.cgi?id=12925
--- orig/linux-2.6.29/include/linux/compiler.h 2009-03-23 19:12:14.000000000 -0400
+++ linux-2.6.29/include/linux/compiler.h 2009-03-24 08:46:46.000000000 -0400
@@ -75,7 +75,8 @@ struct ftrace_branch_data {
* Note: DISABLE_BRANCH_PROFILING can be used by special lowlevel code
* to disable branch tracing on a per file basis.
*/
-#if defined(CONFIG_TRACE_BRANCH_PROFILING) && !defined(DISABLE_BRANCH_PROFILING)
+#if defined(CONFIG_TRACE_BRANCH_PROFILING) \
+ && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)
void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
#define likely_notrace(x) __builtin_expect(!!(x), 1)
EOF
fi
)
rmdir "${tmpdir}"
}
# Test whether the *.patch files in the SCST top-level directory apply cleanly
# to the SCST tree. Does not modify any files nor produce any output files.
function test_scst_tree_patches {
local rc=0
echo "Testing whether the SCST patches apply cleanly to the SCST tree ..."
for p in *.patch srpt/patches/scst_increase_max_tgt_cmds.patch
do
if ! patch -p0 -f --dry-run -s <$p &>/dev/null; then
echo "ERROR: patch $p does not apply cleanly."
rc=1
fi
done
if [ "${rc}" = 0 ]; then
echo "OK"
fi
}
# Copy the entire SCST source code tree from "$1" into the current directory.
# Only copy those files which are administered by Subversion.
function duplicate_scst_source_tree {
if [ -e "$1/AskingQuestions" ]; then
( cd "$1" && svn status -v | cut -c41- \
| while read f; do [ ! -d "$f" ] && echo "$f"; done ) \
| tar -C "$1" --files-from=- -c -f - | tar -x -f -
else
return 1
fi
}
# Compile the unpatched SCST source code.
function compile_scst_unpatched {
local scst="$PWD"
local outputfile="${outputdir}/compilation-output-unpatched.txt"
local workingdirectory="${outputdir}/scst-unpatched"
echo "Testing whether the SCST tree compiles fine ..."
(
if mkdir -p "${workingdirectory}" \
&& cd "${workingdirectory}" \
&& duplicate_scst_source_tree "${scst}" \
&& (make -s clean \
&& make -s scst iscsi-scst \
&& if "${scst_local}" = "true" ; then make -C scst_local clean; fi \
&& if "${scst_local}" = "true" ; then make -C scst_local -s ; fi \
&& if "${mpt_scst}" = "true" ; then make -C mpt clean; fi \
&& if "${mpt_scst}" = "true" ; then make -C mpt -s ; fi \
&& make -C srpt -s clean \
&& make -C srpt -s ) \
&> "${outputfile}"
then
echo "OK"
else
echo "FAILED"
fi
)
}
# Test out-of-tree compilation agains the kernel header files in
# /lib/modules/$(uname -r)/build.
function compile_scst_patched {
local scst="$PWD"
local outputfile="${outputdir}/compilation-output-patched.txt"
local workingdirectory="${outputdir}/scst-patched"
echo "Testing whether the full-perf SCST tree compiles fine ..."
(
if mkdir -p "${workingdirectory}" \
&& cd "${workingdirectory}" \
&& duplicate_scst_source_tree "${scst}" \
&& patch -p0 -f -s <"${scst}/iscsi-full_perf.patch" \
&& patch -p0 -f -s <"${scst}/qla2x00t-full_perf.patch" \
&& patch -p0 -f -s <"${scst}/scst-full_perf.patch" \
&& (make -s clean \
&& make -s scst iscsi-scst \
&& if "${scst_local}" = "true" ; then make -C scst_local clean; fi \
&& if "${scst_local}" = "true" ; then make -C scst_local -s ; fi \
&& if "${mpt_scst}" = "true" ; then make -C mpt clean; fi \
&& if "${mpt_scst}" = "true" ; then make -C mpt -s ; fi \
&& make -C srpt -s clean \
&& make -C srpt -s ) \
&> "${outputfile}"
then
echo "OK"
else
echo "FAILED"
fi
)
}
# Download the file from URL $1 and save it in the current directory.
function download_file {
if [ ! -e "$(basename "$1")" ]; then
if [ "${quiet_download}" = "false" ]; then
echo "Downloading $1 ..."
fi
if ! wget -q -nc "$1"; then
echo "Downloading $1 failed."
return 1
fi
fi
}
# Make sure the kernel tarball and patch file are present in directory
# ${kernel_sources}. Download any missing files from ${kernel_mirror}.
function download_kernel {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
mkdir -p "${kernel_sources}" || return $?
test -w "${kernel_sources}" || return $?
(
cd "${kernel_sources}" || return $?
download_file "${kernel_mirror}/linux-$(kernel_version $1).tar.bz2" \
|| return $?
if [ "${plevel}" != "" ]; then
download_file "${kernel_mirror}/patch-$1.bz2" || return $?
fi
)
}
# Generate a kernel patch from the SCST source tree for kernel version $1.
function generate_kernel_patch {
local scst_dir="${PWD}"
local kver="$(kernel_version $1)"
local patchfile="${outputdir}/scst-$1-kernel.patch"
SIGNED_OFF_BY="..." \
scripts/generate-kernel-patch \
$([ "${scst_local}" = "true" ] && echo -- "-l") \
$([ "${mpt_scst}" = "true" ] && echo -- "-m") \
$([ "${qla2x00t}" = "true" ] && echo -- "-q") \
${kver} > "${patchfile}"
}
# Generate a kernel patch through scripts/generate-kernel-patch and test
# whether it applies cleanly to kernel version $1. Leaves a vanilla kernel
# in directory "${outputdir}/linux-$1" at exit.
function test_if_patch_applies_cleanly {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local outputfile="${outputdir}/kernel-$1-patch-output.txt"
local patchfile="${outputdir}/scst-$1-kernel.patch"
local rc=0
echo "Testing whether the generated kernel patch applies cleanly ..."
( cd "${outputdir}" && extract_kernel_tree "$1" )
( cd "${outputdir}/linux-$1" \
&& patch -p1 --dry-run -f < "${patchfile}" &> "${outputfile}" )
if [ $? != 0 ]; then
echo "FAILED"
rc=1
fi
return $rc
}
# Run checkpatch on the generated kernel patch. Assumes that there is a
# vanilla kernel tree present in directory "${outputdir}/linux-$1", and leaves
# this kernel tree clean.
function run_checkpatch {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local outputfile="${outputdir}/checkpatch-$1-output.txt"
local patchfile="${outputdir}/scst-$1-kernel.patch"
if [ -e "${outputdir}/linux-$1/scripts/checkpatch.pl" ]
then
echo "Running checkpatch on the SCST kernel patch ..."
( cd "${outputdir}/linux-$1" \
&& scripts/checkpatch.pl - < "${patchfile}" &> "${outputfile}")
local errors=$(grep -c '^ERROR' "${outputfile}")
local warnings=$(grep -c '^WARNING' "${outputfile}")
echo "${errors} errors / ${warnings} warnings."
grep -E '^WARNING|^ERROR' "${outputfile}" | sort | uniq -c
else
echo "Skipping checkpatch step for kernel $1."
fi
return 0
}
function patch_and_configure_kernel {
local patchfile="${outputdir}/scst-$1-kernel.patch"
echo "Patching and configuring kernel ..."
(
cd "${outputdir}/linux-$1" \
&& patch -p1 -f -s <"${patchfile}" \
>"${outputdir}/patch-command-output-$1.txt" \
&& make -s allmodconfig &>/dev/null
)
}
# Patches and compiles a kernel tree. Assumes that there is a vanilla kernel
# tree present in directory "${outputdir}/linux-$1".
function compile_patched_kernel {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local outputfile="${outputdir}/kernel-$1-compilation-output.txt"
echo "Compiling kernel $1 ..."
(
(
cd "${outputdir}/linux-$1" \
&& LC_ALL=C make -s -k bzImage modules
)
) &> "${outputfile}"
echo "See also ${outputfile}."
return 0
}
# Compile subdirectory $2 of the patched kernel tree linux-$1.
function compile_kernel {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local outputfile="${outputdir}/compilation-$1-output.txt"
local subdir="$2"
echo "Compiling the patched kernel ..."
(
cd "${outputdir}/linux-$1" \
&& make -s prepare \
&& make -s scripts \
&& LC_ALL=C make -k M="${subdir}"
) &> "${outputfile}"
local errors=$(grep -c ' error:' "${outputfile}")
local warnings=$(grep -c ' warning:' "${outputfile}")
echo "${errors} errors / ${warnings} warnings."
cat "${outputfile}" | grep -E 'warning:|error:' | sort | uniq -c
return 0
}
# Run the source code verification tool 'sparse' on the SCST code. Assumes that
# there is a patched kernel tree present in directory "${outputdir}/linux-$1".
# For more information about endianness annotations, see also
# http://lwn.net/Articles/205624/.
function run_sparse {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local outputfile="${outputdir}/sparse-$1-output.txt"
local subdir="$2"
echo "Running sparse on the patched kernel ..."
(
cd "${outputdir}/linux-$1" \
&& make -s prepare \
&& make -s scripts \
&& LC_ALL=C make -k C=2 M="${subdir}" # CF=-D__CHECK_ENDIAN__
) &> "${outputfile}"
local errors=$(grep -c ' error:' "${outputfile}")
local warnings=$(grep -c ' warning:' "${outputfile}")
echo "${errors} errors / ${warnings} warnings."
cat "${outputfile}" \
| grep -E 'warning:|error:' \
| sed -e 's/^[^ ]*:[^ ]*:[^ ]*: //' \
-e "s/context imbalance in '[^']*':/context imbalance in <function>:/g" \
-e "s/context problem in '[^']*': '[^']*'/context problem in <function>: <function>/g" \
-e "s/function '[^']*'/function/g" \
-e "s/symbol '[^']*'/symbol/g" \
| sort \
| uniq -c
return 0
}
function run_checkstack {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local outputfile="${outputdir}/checkstack-$1-output.txt"
echo "Running checkstack on the patched $1 kernel ..."
(
cd "${outputdir}/linux-$1" \
&& make -s prepare \
&& make -s scripts \
&& LC_ALL=C make -k checkstack
) &> "${outputfile}"
echo "See also ${outputfile}."
return 0
}
function run_namespacecheck {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local outputfile="${outputdir}/namespacecheck-$1-output.txt"
echo "Running namespacecheck on the patched $1 kernel ..."
(
cd "${outputdir}/linux-$1" \
&& make -s prepare \
&& make -s scripts \
&& LC_ALL=C make -k namespacecheck
) &> "${outputfile}"
echo "See also ${outputfile}."
return 0
}
function run_headers_check {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local outputfile="${outputdir}/headers_check-$1-output.txt"
echo "Running headers check on the patched $1 kernel ..."
(
cd "${outputdir}/linux-$1" \
&& make -s prepare \
&& make -s scripts \
&& LC_ALL=C make -k headers_check
) &> "${outputfile}"
local errors=$(grep -c '^[^ ]' "${outputfile}")
echo "${errors} errors."
grep '^[^ ]' "${outputfile}" | sed 's/.*: //' | sort | uniq -c
return 0
}
function run_make_htmldocs {
local kver="$(kernel_version $1)"
local plevel="$(patchlevel $1)"
local outputfile="${outputdir}/htmldocs-$1-output.txt"
echo "Generating HTML documentation for the patched $1 kernel ..."
(
cd "${outputdir}/linux-$1" \
&& make -s prepare \
&& make -s scripts \
&& LC_ALL=C make -k htmldocs
) &> "${outputfile}"
echo "See also ${outputfile}."
return 0
}
#########################
# Argument verification #
#########################
if [ ! -e scst -o ! -e iscsi-scst -o ! -e srpt ]; then
echo "Please run this script from inside the SCST subversion source tree."
exit 1
fi
full_check="false"
# Where to store persistenly downloaded kernel tarballs and kernel patches.
kernel_sources="$HOME/software/downloads"
# URL for downloading kernel tarballs and kernel patches.
kernel_mirror="ftp://ftp.eu.kernel.org/pub/linux/kernel/v2.6"
kernel_versions=""
# Directory in which the regression test output files will be stored. Must be
# an absolute path.
outputdir="${PWD}/regression-test-output-$(date +%Y-%m-%d_%Hh%Mm%Ss)"
# Driver configuration.
mpt_scst="false"
qla2x00t="false"
scst_local="true"
quiet_download="false"
set -- $(/usr/bin/getopt "c:d:fj:hq" "$@")
while [ "$1" != "${1#-}" ]
do
case "$1" in
'-c') kernel_sources="$2"; shift; shift;;
'-d') outputdir="$2"; shift; shift;;
'-f') full_check="true"; shift;;
'-h') usage; exit 1;;
'-j') export MAKEFLAGS="-j$2"; shift; shift;;
'-q') quiet_download="true"; shift;;
'--') shift;;
*) usage; exit 1;;
esac
done
kernel_versions="$*"
# RHEL 4.x / CentOS 4.x has a kernel based on version 2.6.9.
# RHEL 5.x / CentOS 5.x has a kernel based on version 2.6.18.
# Ubuntu 8.04 (Hardy Heron) has a kernel based on version 2.6.24.
# Ubuntu 8.10 (Intrepid Ibex) has a kernel based on version 2.6.27.
# openSUSE 11.0 has a kernel based on version 2.6.25.
# openSUSE 11.1 has a kernel based on version 2.6.27.
#kernel_versions="2.6.23.17 2.6.24.7 2.6.25.20 2.6.26.8 2.6.27.21 2.6.28.9 2.6.29.1"
if [ "${kernel_versions}" = "" ]; then
usage
exit 1
fi
####################
# Regression tests #
####################
if [ "$(type -p sparse)" = "" ]; then
echo "Error: sparse has not yet been installed."
echo "See also http://www.kernel.org/pub/software/devel/sparse/."
fi
if ! mkdir -p "${outputdir}"; then
if [ -e "${outputdir}" ]; then
echo "Error: directory ${outputdir} already exists."
else
echo "Error: could not create directory ${outputdir}."
fi
fi
test_scst_tree_patches || exit $?
compile_scst_unpatched || exit $?
compile_scst_patched || exit $?
first_iteration="true"
for k in ${kernel_versions}
do
echo "===================="
printf "= kernel %-9s =\n" "${k}"
echo "===================="
download_kernel $k || continue
generate_kernel_patch $k || continue
test_if_patch_applies_cleanly $k || continue
if [ "${first_iteration}" = "true" ]; then
first_iteration="false"
run_checkpatch $k
patch_and_configure_kernel $k
run_sparse $k drivers/scst
else
patch_and_configure_kernel $k
compile_kernel $k drivers/scst
fi
# run_headers_check $k
[ "${full_check}" = "true" ] || continue
compile_patched_kernel $k
run_checkstack $k
run_namespacecheck $k
run_make_htmldocs $k
done