From: Song Liu <song@kernel.org>
To: live-patching@vger.kernel.org, linux-kselftest@vger.kernel.org
Cc: jpoimboe@kernel.org, jikos@kernel.org, mbenes@suse.cz,
pmladek@suse.com, joe.lawrence@redhat.com, shuah@kernel.org,
linux-kernel@vger.kernel.org, Song Liu <song@kernel.org>
Subject: [PATCH 01/11] klp-build: Fix dependent patches in a series
Date: Fri, 16 Oct 2026 17:24:31 -0700 [thread overview]
Message-ID: <20261017002441.716615-2-song@kernel.org> (raw)
In-Reply-To: <20261017002441.716615-1-song@kernel.org>
fix_patches() refreshes each patch on its own against the original
source: it applies the patch, copies the patched files, and reverts it.
If a later patch in the series depends on an earlier one, it doesn't
apply to the original source, and klp-build fails even though
validate_patches(), which applies the patches in order, accepted the
series:
$ ./scripts/livepatch/klp-build 0001-dummy.patch 0002-Revert-dummy.patch
Validating patch(es)
Building original kernel
Copying original object files
Fixing patch(es)
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
1 out of 1 hunk ignored
error: klp-build: .../klp-tmp/tmp.patch did not apply
Refreshing each patch on top of the previous ones wouldn't work either.
fix-patch-lines adds #line directives to each fixed patch, so the next
patch's context wouldn't match. The #line numbers in later patches
would also refer to the intermediate source rather than the original
source, which defeats the purpose of preserving __LINE__.
Instead, apply all the patches in order and diff the result against the
original source to get a single combined patch, then run fix-patch-lines
on that. If the patches have no net effect, fail early with "no changes
detected" instead of building the patched kernel for nothing.
Fixes: 24ebfcd65a87 ("livepatch/klp-build: Introduce klp-build script for generating livepatch modules")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Song Liu <song@kernel.org>
---
scripts/livepatch/klp-build | 93 +++++++++++++++++++++----------------
1 file changed, 54 insertions(+), 39 deletions(-)
diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index b52a8489d9f6..6cdc36e97c21 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -467,60 +467,75 @@ do_init() {
set_kernelversion
}
-# Refresh the patch hunk headers, specifically the line numbers and counts.
-refresh_patch() {
- local patch="$1"
+# Combine the patches into a single patch against the original source, with
+# refreshed hunk headers. The patches may depend on each other, so they can't
+# be refreshed individually.
+combine_patches() {
+ local outfile="$1"
local tmpdir="$PATCH_TMP_DIR"
- local input_files=()
- local output_files=()
+ local files=()
+ local patch
+ local file
rm -rf "$tmpdir"
- mkdir -p "$tmpdir/a"
- mkdir -p "$tmpdir/b"
+ mkdir -p "$tmpdir"
- # Get all source files affected by the patch
- get_patch_input_files "$patch" | mapfile -t input_files
- get_patch_output_files "$patch" | mapfile -t output_files
+ # Get all source files affected by the patches
+ for patch in "${PATCHES[@]}"; do
+ get_patch_files "$patch"
+ done | sort -u | mapfile -t files
- # Copy orig source files to 'a'
- echo "${input_files[@]}" | xargs cp --parents --target-directory="$tmpdir/a"
+ # Copy orig source files to $tmpdir
+ for file in "${files[@]}"; do
+ if [[ -e "$file" ]]; then
+ cp --parents "$file" "$tmpdir"
+ fi
+ done
- # Copy patched source files to 'b'
- apply_patch "$patch" "--silent"
- echo "${output_files[@]}" | xargs cp --parents --target-directory="$tmpdir/b"
- revert_patch "$patch"
+ # Diff the orig source files against the patched ones in place to make a
+ # clean patch. Use /dev/null for created and deleted files.
+ : > "$outfile"
+ apply_patches "--silent"
+ for file in "${files[@]}"; do
+ local old="$tmpdir/$file"
+ local new="$file"
+ local old_label="a/$file"
+ local new_label="b/$file"
+ local status=0
+
+ if [[ ! -e "$old" ]]; then
+ old=/dev/null
+ old_label=/dev/null
+ fi
+ if [[ ! -e "$new" ]]; then
+ new=/dev/null
+ new_label=/dev/null
+ fi
- # Diff 'a' and 'b' to make a clean patch
- ( cd "$tmpdir" && diff -Nupr a b > "$patch" ) || true
+ diff -up --label "$old_label" --label "$new_label" "$old" "$new" >> "$outfile" || status=$?
+ if (( status > 1 )); then
+ die "diff failed for $file"
+ fi
+ done
+ revert_patches
}
-# Copy the patches to a temporary directory, fix their lines so as not to
-# affect the __LINE__ macro for otherwise unchanged functions further down the
-# file, and update $PATCHES to point to the fixed patches.
+# Combine the patches into a single patch, fix its lines so as not to affect
+# the __LINE__ macro for otherwise unchanged functions further down the file,
+# and update $PATCHES to point to the fixed patch.
fix_patches() {
- local idx
- local i
+ local tmp_patch="$TMP_DIR/tmp.patch"
+ local new_patch="$TMP_DIR/fixed.patch"
rm -f "$TMP_DIR"/*.patch
- idx=0001
- for i in "${!PATCHES[@]}"; do
- local old_patch="${PATCHES[$i]}"
- local tmp_patch="$TMP_DIR/tmp.patch"
- local patch="${PATCHES[$i]}"
- local new_patch
-
- new_patch="$TMP_DIR/$idx-fixed-$(basename "$patch")"
+ combine_patches "$tmp_patch"
+ [[ ! -s "$tmp_patch" ]] && die "no changes detected"
- cp -f "$old_patch" "$tmp_patch"
- refresh_patch "$tmp_patch"
- "$FIX_PATCH_LINES" "$tmp_patch" | recountdiff > "$new_patch"
+ "$FIX_PATCH_LINES" "$tmp_patch" | recountdiff > "$new_patch"
+ PATCHES=("$new_patch")
- PATCHES[i]="$new_patch"
-
- rm -f "$tmp_patch"
- idx=$(printf "%04d" $(( 10#$idx + 1 )))
- done
+ rm -f "$tmp_patch"
}
clean_kernel() {
--
2.53.0-Meta
next prev parent reply other threads:[~2026-10-17 0:24 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-17 0:24 [PATCH 00/11] klp-build: Fix dependent patches, add selftests Song Liu
2026-10-17 0:24 ` Song Liu [this message]
2026-10-17 0:24 ` [PATCH 02/11] klp-build: Add --patch-only option Song Liu
2026-10-17 0:24 ` [PATCH 03/11] selftests/livepatch: Add tests for klp-build's patch handling Song Liu
2026-10-17 0:24 ` [PATCH 04/11] selftests/livepatch: Test klp-build with dependent patches Song Liu
2026-10-17 0:24 ` [PATCH 05/11] selftests/livepatch: Test klp-build with patches to different functions Song Liu
2026-10-17 0:24 ` [PATCH 06/11] selftests/livepatch: Test klp-build with patches which cancel out Song Liu
2026-10-17 0:24 ` [PATCH 07/11] selftests/livepatch: Test klp-build with created and deleted files Song Liu
2026-10-17 0:24 ` [PATCH 08/11] selftests/livepatch: Test where klp-build adds #line directives Song Liu
2026-10-17 0:24 ` [PATCH 09/11] selftests/livepatch: Test klp-build's rejection of unsupported files Song Liu
2026-10-17 0:24 ` [PATCH 10/11] selftests/livepatch: Test klp-build with patches which don't apply Song Liu
2026-10-17 0:24 ` [PATCH 11/11] selftests/livepatch: Test klp-build with patches which need offset or fuzz Song Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261017002441.716615-2-song@kernel.org \
--to=song@kernel.org \
--cc=jikos@kernel.org \
--cc=joe.lawrence@redhat.com \
--cc=jpoimboe@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=live-patching@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=pmladek@suse.com \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox