[PATCH v8 09/11] kexec: Add kexec_rollback_segments() helper
From: Jinjie Ruan
Date: Thu Nov 12 2026 - 08:37:07 EST
A load attempt that cannot place all of its segments drops the segments
it added, but the CMA pages backing them become unreachable.
Add a helper that releases those pages and truncates nr_segments,
so the loaders do not have to open code it.
The helper also invalidates the recorded elfcorehdr segment index when
the header is among the dropped segments, so that a retry does not leave
a stale index behind for crash hotplug.
Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Cc: Baoquan He <baoquan.he@xxxxxxxxx>
Cc: Mike Rapoport <rppt@xxxxxxxxxx>
Suggested-by: Mike Rapoport <rppt@xxxxxxxxxx>
Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
include/linux/kexec.h | 1 +
kernel/kexec_file.c | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index be7c827e8f7e..464ab4dd36b1 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -259,6 +259,7 @@ int kexec_kernel_verify_pe_sig(const char *kernel, unsigned long kernel_len);
extern int kexec_add_buffer(struct kexec_buf *kbuf);
int kexec_locate_mem_hole(struct kexec_buf *kbuf);
int kexec_add_initrd(struct kimage *image, struct kexec_buf *kbuf);
+void kexec_rollback_segments(struct kimage *image, unsigned long nr_segments);
#ifdef CONFIG_CRASH_DUMP
int kexec_prepare_elf_core_header(struct kimage *image, bool need_kernel_map,
unsigned long *nr_ranges);
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 25c9bef639d2..b4fe5c418842 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -1419,3 +1419,15 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
return 0;
}
#endif /* CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY */
+
+/*
+ * Undo a partial load attempt: release the CMA pages backing
+ * the segments above @nr_segments and drop them from the image.
+ */
+void kexec_rollback_segments(struct kimage *image, unsigned long nr_segments)
+{
+ while (image->nr_segments > nr_segments) {
+ kexec_free_segment_cma(image, image->nr_segments - 1);
+ image->nr_segments--;
+ }
+}
--
2.34.1