blob: 7a3bcb90443421bb4471684ab45d6e7d6e09bd15 [file] [log] [blame]
#!/bin/bash
############################################################################
#
# Script for converting the SCST source tree as it exists in the Subversion
# repository to a Linux kernel patch.
#
# Copyright (C) 2008-2020 Bart Van Assche <bvanassche@acm.org>
#
# 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.
#
############################################################################
########################
# Function definitions #
########################
# shellcheck source=./kernel-functions
source "$(dirname "$0")/kernel-functions"
function usage {
echo "Usage: $0 [-d] [-h] [-n] [-p <dir>] [-s] [-u] <kernel version>"
echo "where: "
echo " -d - enable patch specialization debugging"
echo " -h - show this text"
echo " -n - do not delete code disabled via preprocessor statements"
echo " -p - generate multiple patches instead of one big patch into"\
"the specified directory."
echo " -s - disable patch specialization."
echo " -u - enables #define GENERATING_UPSTREAM_PATCH."
}
# Convert an existing patch.
# $1: path of patch to be added.
# $2: path in kernel tree of file to be patched.
function add_patch {
if [ ! -e "$1" ]; then
echo "Error: could not find $1." >&2
exit 1
fi
sed -e "s:^--- [^ ]*:--- linux-${kver}/$2:" \
-e "s:^+++ [^ ]*:+++ linux-${kver}/$2:" \
< "$1"
}
# Generate a patch for a file to be added to the kernel source tree, and strip
# trailing whitespace from C source files while converting the file to patch
# format.
# $1: path of file to be added.
# $2: path in kernel tree where file should be added.
function add_file {
local a b
if [ ! -e "$1" ]; then
echo "Error: could not find $1." >&2
exit 1
fi
# Only include files that were not generated by the build process
# -- skip *.mod.c.
if [ "$1" = "${1%.mod.c}" ] && [ "$1" ]; then
cat <<EOF
diff -uprN linux-${kver}/$2 linux-${kver}/$2
--- linux-${kver}/$2
+++ linux-${kver}/$2
@@ -0,0 +1,$(wc -l "$1" | { read -r a b; echo "$a"; echo "$b" >/dev/null; }) @@
EOF
# Insert a '+'-sign at the start of each line.
sed -e 's/^/+/' < "$1" | \
if [ "${replace_sbug_by_bug}" = "true" ]; then
sed -e 's/sBUG(\([^)]*\)/BUG(\1/g' -e 's/sBUG_ON(\([^)]*\)/BUG_ON(\1/g'
else
cat
fi \
| \
if [ "${2%.[ch]}" != "$2" ]; then
# Make sure that labels (goto-targets) are left-aligned.
sed -e 's/^ \([^ ]*:\)$/\1/'
else
cat
fi
fi
}
function add_empty_file {
cat <<EOF
diff -uprN linux-${kver}/$1 linux-${kver}/$1
--- linux-${kver}/$1
+++ linux-${kver}/$1
@@ -0,0 +1,1 @@
+
EOF
}
# Run the script specialize_patch with appropriate options on the patch
# passed via stdin and send the specialized patch to stdout.
function specialize_patch {
local ao
set -- ${1//^/ }
local kver=$1
local distro=$2
local release=$3
set -- ${release//./ }
local releasevermajor="$1"
local releaseverminor="$2"
case "$distro" in
CentOS|AlmaLinux)
if [ -n "$releasevermajor" ]; then
ao=(
-v "RHEL_MAJOR=$releasevermajor"
-v "RHEL_MINOR=$releaseverminor"
-v "RHEL_RELEASE_CODE=$((releasevermajor * 256 +
releaseverminor))"
)
fi
;;
UEK)
ao=(-v UEK_KABI_RENAME=1 -v UEK_RELEASE=${releasevermajor})
;;
esac
local kver3
set -- ${kver//[.-]/ }
if [ -n "$3" ]; then
kver3=$1.$2.$3
else
kver3=$1.$2
fi
if [ "${enable_specialize}" = "true" ]; then
if [ "${generating_upstream_patch}" = "true" ]; then
scripts/filter-trace-entry-exit
else
cat
fi |
"$(dirname "$0")/specialize-patch" \
"${specialize_patch_options[@]}" \
-v kernel_version="${kver3}" \
-v SCST_IO_CONTEXT="${scst_io_context}" "${ao[@]}"
else
cat
fi
}
# Read a patch from stdin, specialize it for kernel version ${full_kver}
# and write the output either to stdout or to the file $1 (if not empty),
# depending on the value of the variable ${multiple_patches}.
function process_patch {
local tmppatch
if [ "${multiple_patches}" = "true" ]; then
if [ "$1" != "" ]; then
if [ -e "${patchdir}/$1" ]; then
echo "Warning: overwriting ${patchdir}/$1"
fi
tmppatch="$(/bin/mktemp)"
(
specialize_patch "${full_kver}"
) >"${tmppatch}"
touch "${tmppatch}"
{
if [ -e /usr/bin/diffstat ]; then
awk 'BEGIN{h=1}/^diff/{h=0}/^---/{h=0}h!=0{print}' < "${tmppatch}"
echo "---"
diffstat "${tmppatch}"
echo ""
awk 'BEGIN{h=1}/^diff/{h=0}/^---/{h=0}h==0{print}' < "${tmppatch}"
fi
} \
> "${patchdir}/$(basename "$1")"
rm -f "${tmppatch}"
else
# echo "Discarded $(wc -l) lines."
true
fi
else
specialize_patch "${full_kver}"
fi
}
# Returns 0 (true) if SCST core file "$1" should be added in a separate patch,
# and 1 (false) if not.
function in_separate_patch {
echo "${source_files_in_separate_patch}" | grep -qE "^$1 | $1 | $1\$|^$1\$"
}
#########################
# Argument verification #
#########################
debug_specialize="false"
enable_specialize="true"
generating_upstream_patch="false"
multiple_patches="false"
patchdir=""
replace_sbug_by_bug="true"
specialize_patch_options=(-v "delete_disabled_code=1")
srpt="true"
if [ ! -e scst ] || [ ! -e iscsi-scst ] || [ ! -e srpt ] ||
[ ! -e scst_local ]; then
echo "Please run this script from inside the SCST subversion source tree."
exit 1
fi
# shellcheck disable=SC2046
set -- $(/usr/bin/getopt dhlmnp:su "$@")
while [ "$1" != "${1#-}" ]
do
case "$1" in
'-d') debug_specialize="true"; shift;;
'-h') usage; exit 1;;
'-l') shift;;
'-n') specialize_patch_options=(-v "blank_deleted_code=1")
shift
;;
'-p') multiple_patches="true"; patchdir="$2"; shift; shift;;
'-s') enable_specialize="false"; shift;;
'-u') generating_upstream_patch="true"; shift;;
'--') shift;;
*) usage; exit 1;;
esac
done
if [ $# != 1 ]; then
usage
exit 1
fi
# Strip patch level from the kernel version number.
full_kver="$1"
kver="$(kernel_version "$1")"
# Include fcst in the patch for kernel versions 2.6.33 and later.
if kernel_version_le "2.6.37" "${kver}"; then
include_fcst="true"
else
include_fcst="false"
fi
# See also commit 89d9a567952b ("[SCSI] add support for per-host cmd pools";
# v3.15).
if kernel_version_lt "$kver" 3.18; then
qla2x00t="true"
qla2x00t_32gbit="false"
else
qla2x00t="false"
qla2x00t_32gbit="true"
fi
if [ -e "scst/kernel/in-tree/Makefile.scst-${kver}" ]; then
scst_makefile="Makefile.scst-${kver}"
else
scst_makefile="Makefile.scst"
fi
# Make sure that for kernel 2.6.26 and later the line
# "#define CONFIG_SCST_PROC" is removed from scst/include/scst.h.
if grep -qw scst_sysfs scst/kernel/in-tree/${scst_makefile} \
|| [ "${generating_upstream_patch}" = "true" ];
then
specialize_patch_options+=(-v "config_scst_proc_undefined=1")
else
include_proc_impl="true"
fi
if [ "${debug_specialize}" = "true" ]; then
specialize_patch_options+=(-v "debug=1")
fi
if [ "${generating_upstream_patch}" = "true" ]; then
specialize_patch_options+=(-v "generating_upstream_patch_defined=1"
-v "config_tcp_zero_copy_transfer_completion_notification_undefined=1")
fi
if [ "${multiple_patches}" = "true" ]; then
if [ -e "${patchdir}" ]; then
echo "Patch output directory ${patchdir} already exists."
fi
mkdir -p "${patchdir}"
if [ ! -d "${patchdir}" ]; then
echo "Error: ${patchdir} is not a directory."
fi
fi
####################
# Patch Generation #
####################
for f in fcst/linux-patches/series-"${kver}"*
do
if [ -e "$f" ]; then
fcst_patch_series="$f"
fi
done
# General kernel patches.
scst_io_context=0
scst_03_public_headers="scst/include/scst.h scst/include/scst_const.h \
scst/include/scst_event.h scst/include/backport.h"
scst_04_main="scst/src/scst_main.c scst/src/scst_module.c scst/src/scst_priv.h \
scst/src/scst_copy_mgr.c scst/src/scst_dlm.c scst/src/scst_dlm.h \
scst/src/scst_event.c scst/src/scst_no_dlm.c"
scst_05_targ="scst/src/scst_targ.c scst/src/scst_local_cmd.c \
scst/src/scst_local_cmd.h"
scst_06_lib="scst/src/scst_lib.c"
scst_07_pres="scst/src/scst_pres.h scst/src/scst_pres.c"
scst_08_sysfs="scst/src/scst_sysfs.c"
scst_09_debug="scst/include/scst_debug.h scst/src/scst_debug.c"
scst_proc="scst/src/scst_proc.c"
scst_10_sgv="scst/include/scst_sgv.h scst/src/scst_mem.h scst/src/scst_mem.c doc/scst_pg.sgml"
scst_user="scst/include/scst_user.h scst/src/dev_handlers/scst_user.c"
scst_13_vdisk="scst/src/dev_handlers/scst_vdisk.c"
scst_14_tg="scst/src/scst_tg.c"
separate_patches="scst_03_public_headers scst_04_main scst_05_targ scst_06_lib scst_07_pres scst_08_sysfs scst_09_debug scst_10_sgv scst_user scst_13_vdisk scst_14_tg"
# Suppress shellcheck warnings about unused variables.
echo "$scst_03_public_headers $scst_04_main $scst_05_targ $scst_06_lib $scst_07_pres $scst_08_sysfs $scst_09_debug $scst_proc $scst_10_sgv $scst_user $scst_13_vdisk $scst_14_tg" >/dev/null
if [ "$include_proc_impl" = "true" ]; then
separate_patches+=" scst_proc"
fi
source_files_in_separate_patch=""
for s in ${separate_patches}
do
source_files_in_separate_patch+=" $(set | \
sed -n -e "s/^$s='\(.*\)'$/\1/p" -e "s/^$s=\(.*\)$/\1/p")"
done
# Directory drivers/
(
if [ -e "scst/kernel/in-tree/Kconfig.drivers.Linux-${kver}.patch" ]; then
add_patch "scst/kernel/in-tree/Kconfig.drivers.Linux-${kver}.patch" \
"drivers/Kconfig"
else
add_patch "scst/kernel/in-tree/Kconfig.drivers.Linux.patch" \
"drivers/Kconfig"
fi
if [ "${full_kver#2.6.32-}" = "${full_kver}" ] &&
[ -e "scst/kernel/in-tree/Makefile.drivers.Linux-${kver}.patch" ]; then
add_patch "scst/kernel/in-tree/Makefile.drivers.Linux-${kver}.patch"\
"drivers/Makefile"
else
add_patch "scst/kernel/in-tree/Makefile.drivers.Linux.patch"\
"drivers/Makefile"
fi
) \
| process_patch "scst_01_drivers_kbuild.diff"
# Directory drivers/scst/
(
tmpdir="/tmp/scst-$$"
mkdir -p "${tmpdir}"
tmp_Kconfig="${tmpdir}/Kconfig.scst-${kver}"
# shellcheck disable=SC2002
cat "scst/kernel/in-tree/Kconfig.scst" | \
if [ "${include_fcst}" = true ]; then
cat
else
grep -v '^source "drivers/scst/fcst/Kconfig"$'
fi >"${tmp_Kconfig}"
add_file "${tmp_Kconfig}" "drivers/scst/Kconfig"
tmp_Makefile="${tmpdir}/${scst_makefile}"
# shellcheck disable=SC2002
cat "scst/kernel/in-tree/${scst_makefile}" | \
if [ "$include_proc_impl" != "true" ]; then
grep -v 'scst_proc'
else
cat
fi | \
if [ "${include_fcst}" = true ] && [ "${kver}" != "2.6.37" ] &&
[ "${kver}" != "2.6.38" ]; then
cat
else
sed -e 's: fcst/* : :'
fi >"$tmp_Makefile"
add_file "$tmp_Makefile" "drivers/scst/Makefile"
rm -rf "${tmpdir}"
) \
| process_patch "scst_02_scst_kbuild.diff"
for s in ${separate_patches}
do
{
for f in $(eval 'echo "$'"{$s}"'"')
do
if [ "${f#scst/include}" != "${f}" ]; then
add_file "${f}" "include/scst/${f#scst/include/}"
elif [ "${f#doc}" != "${f}" ]; then
add_file "${f}" "Documentation/scst/${f#doc/}"
else
add_file "${f}" "drivers/scst/${f#scst/src/}"
fi
done
if grep -q /scst_itf_ver.h scst/src/Makefile &&
[ "$s" = "scst_03_public_headers" ]; then
tmp_itf_ver="$(mktemp /tmp/scst-itf-ver.h.XXXXXXXXXX)"
cat <<"EOF" >"$tmp_itf_ver"
/* Autogenerated, don't edit */
#define SCST_INTF_VER "SCST_INTF_VER"
#define SCST_CONST_INTF_VER "SCST_CONST_INTF_VER"
#define DEV_USER_INTF_VER "DEV_USER_INTF_VER"
EOF
add_file "$tmp_itf_ver" "include/scst/scst_itf_ver.h"
rm -f "$tmp_itf_ver"
fi
} |
process_patch "${s}.diff"
done
{
if [ -e scst/README_in-tree ]; then
add_file "scst/README_in-tree" "Documentation/scst/README.scst"
fi
add_file "scst/SysfsRules" "Documentation/scst/SysfsRules"
} | process_patch "scst_11_core_doc.diff"
# Directory drivers/scst/dev_handlers/
if [ -e "scst/kernel/in-tree/Makefile.dev_handlers-${kver}" ]
then
add_file "scst/kernel/in-tree/Makefile.dev_handlers-${kver}" \
"drivers/scst/dev_handlers/Makefile" \
| process_patch "scst_11_dev_handlers_makefile.diff"
else
add_file "scst/kernel/in-tree/Makefile.dev_handlers" \
"drivers/scst/dev_handlers/Makefile" \
| process_patch "scst_11_dev_handlers_makefile.diff"
fi
for f in scst/src/dev_handlers/*.[ch]; do
[ -e "$f" ] || continue
if ! in_separate_patch "${f}"; then
add_file "${f}" "drivers/scst/dev_handlers/${f#scst/src/dev_handlers/}"
fi
done \
| process_patch "scst_14_passthrough.diff"
# Directory drivers/scst/fcst/
if [ "${include_fcst}" = true ]; then
if [ -e "${fcst_patch_series}" ]; then
grep -v '^#' "${fcst_patch_series}" |
while read -r f; do
cat "fcst/linux-patches/${f}"
done
fi
for f in fcst/Kbuild fcst/Makefile_in-tree; do
[ -e "$f" ] && add_file "$f" "drivers/scst/fcst/Makefile"
done
add_file "fcst/Kconfig" "drivers/scst/fcst/Kconfig"
for f in fcst/*.[ch]; do
[ -e "$f" ] || continue
add_file "${f}" "drivers/scst/fcst/${f#fcst/}"
done
fi \
| process_patch "fcst.diff"
add_file "fcst/README" "Documentation/scst/README.fcst" \
| process_patch "fcst-doc.diff"
# Directory drivers/scst/iscsi-scst/
# Make sure the file iscsi-scst/iscsi_scst_itf_ver.h is up to date.
make -s -C iscsi-scst include/iscsi_scst_itf_ver.h
(
for f in iscsi-scst/include/*h; do
[ -e "$f" ] || continue
case "${f}" in
"iscsi-scst/include/iscsi_scst_itf_ver.h")
;;
"iscsi-scst/include/iscsit_transport.h")
add_file "${f}" "include/scst/${f#iscsi-scst/include/}"
;;
*)
add_file "${f}" "include/scst/${f#iscsi-scst/include/}"
;;
esac
done
add_file "iscsi-scst/include/iscsi_scst_itf_ver.h" "include/scst/iscsi_scst_itf_ver.h"
add_file "iscsi-scst/kernel/Makefile.in-kernel" \
"drivers/scst/iscsi-scst/Makefile"
add_file "iscsi-scst/kernel/Kconfig" "drivers/scst/iscsi-scst/Kconfig"
for f in iscsi-scst/kernel/*.[ch]; do
[ -e "$f" ] || continue
add_file "${f}" "drivers/scst/iscsi-scst/${f#iscsi-scst/kernel/}"
done
for f in iscsi-scst/kernel/isert-scst/*.[ch]; do
[ -e "$f" ] || continue
add_file "${f}" "drivers/scst/iscsi-scst/isert-scst/${f#iscsi-scst/kernel/isert-scst/}"
done
add_file "iscsi-scst/kernel/isert-scst/Makefile.in-kernel" "drivers/scst/iscsi-scst/isert-scst/Makefile"
add_file "iscsi-scst/kernel/isert-scst/Kconfig" "drivers/scst/iscsi-scst/isert-scst/Kconfig"
) \
| process_patch "iscsi-scst.diff"
add_file "iscsi-scst/README_in-tree" "Documentation/scst/README.iscsi" \
| process_patch "iscsi-scst-doc.diff"
# Directory drivers/scsi/qla2xxx/
if [ "${qla2x00t}" = "true" ]; then
( cd qla2x00t && "$PWD/generate-in-tree-patches" "$1" ) || exit $?
for f in qla2x00t/in-tree-patches/"$1"/*.patch; do
[ -e "$f" ] || continue
g="${f#qla2x00t/in-tree-patches/$1/}"
g="${g%.patch}"
add_patch "${f}" "drivers/scsi/qla2xxx/${g}"
done
add_file "qla2x00t/qla2x_tgt.h" \
"drivers/scsi/qla2xxx/qla2x_tgt.h"
add_file "qla2x00t/qla2x_tgt_def.h" \
"drivers/scsi/qla2xxx/qla2x_tgt_def.h"
for f in qla2x00t/qla2x00-target/*.[ch]; do
[ -e "$f" ] &&
add_file "${f}" "drivers/scsi/qla2xxx/${f#qla2x00t/qla2x00-target/}"
done
add_file "qla2x00t/qla2x00-target/README" \
"Documentation/scst/README.qla2x00t" \
| process_patch "qla2x00t-doc.diff"
elif [ "${qla2x00t_32gbit}" = "true" ]; then
( cd qla2x00t-32gbit && "$PWD/generate-in-tree-patches" "$1" ) || exit $?
for f in qla2x00t-32gbit/in-tree-patches/"$1"/*.patch; do
[ -e "$f" ] || continue
g="${f#qla2x00t-32gbit/in-tree-patches/$1/}"
g="${g%.patch}"
if [ "$g" = "qla.h" ]; then
add_patch "${f}" "include/trace/events/${g}"
else
add_patch "${f}" "drivers/scsi/qla2xxx/${g}"
fi
done
for f in qla2x00t-32gbit/qla2x00-target/*.[ch]; do
[ -e "$f" ] || continue
add_file "${f}" "drivers/scsi/qla2xxx/${f#qla2x00t-32gbit/qla2x00-target/}"
done
add_file "qla2x00t-32gbit/qla2x00-target/README" \
"Documentation/scst/README.qla2x00t" \
| process_patch "qla2x00t-doc.diff"
fi \
| process_patch "qla2x00t.diff"
# Directory drivers/scst/srpt
{
cat <<EOF
This patch adds the kernel module ib_srpt, which is a SCSI RDMA Protocol (SRP)
target implementation. This driver uses the InfiniBand stack and the SCST core.
It is a high performance driver capable of handling 600K+ 4K random write
IOPS by a single target as well as 2.5+ GB/s sequential throughput over
a single QDR IB port.
It was originally developed by Vu Pham (Mellanox) and has been optimized by
Bart Van Assche.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Vu Pham <vu@mellanox.com>
Cc: Roland Dreier <rdreier@cisco.com>
Cc: David Dillow <dillowda@ornl.gov>
EOF
if [ "$srpt" = "true" ]; then
add_file "srpt/README_in-tree" "Documentation/scst/README.srpt"
add_file "srpt/src/Kconfig" "drivers/scst/srpt/Kconfig"
add_file "srpt/src/Makefile.in_kernel" "drivers/scst/srpt/Makefile"
for f in srpt/src/*.[ch]; do
[ -e "$f" ] || continue
add_file "${f}" "drivers/scst/srpt/${f#srpt/src/}"
done
else
add_empty_file "drivers/scst/srpt/Kconfig"
add_empty_file "drivers/scst/srpt/Makefile"
fi \
} | process_patch "scst_17_srpt.diff"
# Directory drivers/scst/scst_local
(
add_file "scst_local/README" "Documentation/scst/README.scst_local"
add_file "scst_local/in-tree/Kconfig" "drivers/scst/scst_local/Kconfig"
if [ -e "scst_local/in-tree/Makefile-${kver}" ]; then
add_file "scst_local/in-tree/Makefile-${kver}" "drivers/scst/scst_local/Makefile"
else
add_file "scst_local/in-tree/Makefile" "drivers/scst/scst_local/Makefile"
fi
add_file "scst_local/scst_local.c" "drivers/scst/scst_local/scst_local.c"
) \
| process_patch "scst_16_local.diff"