scripts/specialize-patch: Rebuild filtered hunks

The regression became visible after commit 91517609cd
("scripts/generate-kernel-patch: Preserve split patches") preserved split
output that had previously been empty without diffstat.
specialize-patch kept the original hunk coordinates after dropping
version-dependent lines, so GNU patch rejected the generated qla.h patch.

Recalculate hunk coordinates and context after specialization removes added
lines. This prevents GNU patch from rejecting QLogic qla.h hunks for Linux
7.1 and 7.2.

Add a focused regression test for the normal and matching-line-number
specialization modes.
This commit is contained in:
Gleb Chesnokov
2026-08-26 16:25:41 +03:00
parent 3c7a6df0a8
commit 487b52c2f9
2 changed files with 154 additions and 5 deletions
+38 -5
View File
@@ -613,21 +613,48 @@ function reset_hunk_state_variables() {
function dump_lines() {
# Detect empty hunks
first_modif = -1
last_modif = -1
for (i = 0; i < lines; i++)
{
if (line[i] ~ "^[+-]")
{
first_modif = i
break
if (first_modif < 0)
first_modif = i
last_modif = i
}
}
# Dump line[] as a hunk, but only if the hunk is not empty.
if (first_modif >= 0)
{
if (h[0] != "")
printf "@@ -%d,%d +%d,%d @@%s\n",h[1],h[2]-lines_less_deleted,h[3],h[4]-lines_less_added,h[5]
for (i = 0; i < lines; i++) {
# Restore standard unified diff context after discarding added lines.
first_line = first_modif > context_lines ? first_modif - context_lines : 0
last_line = last_modif + context_lines < lines ? \
last_modif + context_lines : lines - 1
if (h[0] != "") {
old_start = h[1]
new_start = h[3] + new_line_adjustment
for (i = 0; i < first_line; i++) {
if (line[i] !~ "^\\+" && line[i] !~ "^\\\\")
old_start++
if (line[i] !~ "^-" && line[i] !~ "^\\\\")
new_start++
}
old_count = 0
new_count = 0
for (i = first_line; i <= last_line; i++) {
if (line[i] !~ "^\\+" && line[i] !~ "^\\\\")
old_count++
if (line[i] !~ "^-" && line[i] !~ "^\\\\")
new_count++
}
printf "@@ -%d,%d +%d,%d @@%s\n", old_start, old_count, \
new_start, new_count, h[5]
}
for (i = first_line; i <= last_line; i++) {
modifier = (LINUX_VERSION_CODE < version_code("4.19.0") &&
(RHEL_MAJOR == "" ||
RHEL_MAJOR * 256 + RHEL_MINOR < 7 * 256 + 7 ||
@@ -638,6 +665,9 @@ function dump_lines() {
print line[i]
}
}
if (h[0] != "")
new_line_adjustment += lines_less_deleted - lines_less_added
}
BEGIN {
@@ -660,6 +690,7 @@ BEGIN {
if (config_tcp_zero_copy_transfer_completion_notification_undefined != 0 && config_tcp_zero_copy_transfer_completion_notification_undefined != 1)
config_tcp_zero_copy_transfer_completion_notification_undefined = 0
# Variable initialization.
context_lines = 3
process_file = 0
reset_hunk_state_variables()
}
@@ -667,11 +698,13 @@ BEGIN {
{
if (match($0, "^diff[ \t]+[^ \t]+[ \t]+[^ \t]+[ \t]+([^ \t]+)$", filename) \
|| match($0, "^---[ \t]+([^ \t]+)[ \t]+", filename) \
|| match($0, "^\\+\\+\\+[ \t]+([^ \t]+)[ \t]+", filename))
{
# Start of new file.
dump_lines()
reset_hunk_state_variables()
new_line_adjustment = 0
process_file = match(filename[1], "\\.[ch]$") != 0 &&
match(filename[1], "drivers/scsi/qla2xxx/") == 0
}
+116
View File
@@ -0,0 +1,116 @@
#!/bin/bash
set -euo pipefail
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
scst_dir="$(dirname -- "$script_dir")"
test_dir="$(mktemp -d)"
trap 'rm -rf -- "$test_dir"' EXIT
mkdir -p "$test_dir/orig"
cat > "$test_dir/orig/qla.h" <<'EOF'
/* SPDX-License-Identifier: GPL-2.0 */
#if !defined(_TRACE_QLA_H_) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_QLA_H_
#include <linux/tracepoint.h>
#undef TRACE_SYSTEM
#define TRACE_SYSTEM qla
#define QLA_MSG_MAX 256
#pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
#endif
DECLARE_EVENT_CLASS(qla_log_event,
TP_PROTO(const char *buf,
struct va_format *vaf),
TP_ARGS(buf, vaf),
TP_STRUCT__entry(
__string(buf, buf)
__vstring(msg, vaf->fmt, vaf->va)
),
TP_fast_assign(
__assign_str(buf);
__assign_vstr(msg, vaf->fmt, vaf->va);
),
TP_printk("%s %s", __get_str(buf), __get_str(msg))
);
#pragma GCC diagnostic pop
DEFINE_EVENT(qla_log_event, ql_dbg_log,
TP_PROTO(const char *buf, struct va_format *vaf),
TP_ARGS(buf, vaf)
);
#endif /* _TRACE_QLA_H */
#define TRACE_INCLUDE_FILE qla
#include <trace/define_trace.h>
EOF
if diff -up "$test_dir/orig/qla.h" \
"$scst_dir/qla2x00t-32gbit/include/trace/events/qla.h" \
> "$test_dir/qla.raw.patch"; then
echo "Error: qla.h test inputs do not differ." >&2
exit 1
else
diff_status=$?
if [ "$diff_status" -gt 1 ]; then
exit "$diff_status"
fi
fi
for kernel_version in 7.1 7.2; do
mkdir -p "$test_dir/linux-$kernel_version/include/trace/events"
cp "$test_dir/orig/qla.h" \
"$test_dir/linux-$kernel_version/include/trace/events/qla.h"
sed -e "s:^--- [^ ]*:--- linux-$kernel_version/include/trace/events/qla.h:" \
-e "s:^+++ [^ ]*:+++ linux-$kernel_version/include/trace/events/qla.h:" \
< "$test_dir/qla.raw.patch" > "$test_dir/qla-$kernel_version.patch"
cat >> "$test_dir/qla-$kernel_version.patch" <<EOF
--- linux-$kernel_version/drivers/scst/next.c 2026-08-26 00:00:00.000000000 +0300
+++ linux-$kernel_version/drivers/scst/next.c 2026-08-26 00:00:00.000000000 +0300
@@ -1,1 +1,1 @@
-old
+new
EOF
mkdir -p "$test_dir/linux-$kernel_version/drivers/scst"
echo old > "$test_dir/linux-$kernel_version/drivers/scst/next.c"
"$script_dir/specialize-patch" -v delete_disabled_code=1 \
-v kernel_version="$kernel_version" -v SCST_IO_CONTEXT=0 \
< "$test_dir/qla-$kernel_version.patch" \
> "$test_dir/qla-$kernel_version.specialized.patch"
grep -qF '@@ -9,8 +9,8 @@' \
"$test_dir/qla-$kernel_version.specialized.patch"
grep -qF '@@ -32,13 +32,15 @@' \
"$test_dir/qla-$kernel_version.specialized.patch"
patch --dry-run -f -s -p0 -d "$test_dir" \
< "$test_dir/qla-$kernel_version.specialized.patch"
"$script_dir/specialize-patch" -v blank_deleted_code=1 \
-v kernel_version="$kernel_version" -v SCST_IO_CONTEXT=0 \
< "$test_dir/qla-$kernel_version.patch" \
> "$test_dir/qla-$kernel_version.specialized-n.patch"
patch --dry-run -f -s -p0 -d "$test_dir" \
< "$test_dir/qla-$kernel_version.specialized-n.patch"
done
echo "specialize-patch qla.h regression: PASS"