[PATCHv7 06/13] kexec_file: Chain the stages into a pipeline
Pingfan Liu
piliu at redhat.com
Sat Mar 21 18:43:55 PDT 2026
Images may consist of multiple layers, each with a distinct format. For
example, an AArch64 UKI image typically embeds a zboot image in the
.linux section. The parser therefore determines whether its output
should be forwarded to the next stage.
Intermediate results are stored in next_parsing_buf and then promoted to
parsing_buf for the subsequent stage.
Signed-off-by: Pingfan Liu <piliu at redhat.com>
Cc: Baoquan He <bhe at redhat.com>
Cc: Dave Young <dyoung at redhat.com>
Cc: Andrew Morton <akpm at linux-foundation.org>
Cc: Philipp Rudo <prudo at redhat.com>
To: kexec at lists.infradead.org
---
kernel/kexec_bpf_loader.c | 47 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)
diff --git a/kernel/kexec_bpf_loader.c b/kernel/kexec_bpf_loader.c
index af16f7b685d9a..7f7884411e2c7 100644
--- a/kernel/kexec_bpf_loader.c
+++ b/kernel/kexec_bpf_loader.c
@@ -41,6 +41,8 @@ struct kexec_context {
bool parsed;
char *parsing_buf[MAX_PARSING_BUF_NUM];
unsigned long parsing_buf_sz[MAX_PARSING_BUF_NUM];
+ char *next_parsing_buf[MAX_PARSING_BUF_NUM];
+ unsigned long next_parsing_buf_sz[MAX_PARSING_BUF_NUM];
char *kernel;
unsigned long kernel_sz;
@@ -278,8 +280,9 @@ static int kexec_buff_parser(struct bpf_parser_context *parser)
struct bpf_parser_buf *pbuf = parser->buf;
struct kexec_context *ctx = (struct kexec_context *)parser->data;
struct cmd_hdr *cmd = (struct cmd_hdr *)pbuf->buf;
- char *decompressed_buf, *buf, *p;
+ char *decompressed_buf, *buf, *p, *pn;
unsigned long decompressed_sz;
+ bool fill_pipeline = false;
int ret = 0;
buf = pbuf->buf + sizeof(struct cmd_hdr);
@@ -288,6 +291,7 @@ static int kexec_buff_parser(struct bpf_parser_context *parser)
cmd->payload_len, pbuf->size);
return -EINVAL;
}
+ fill_pipeline = cmd->pipeline_flag & KEXEC_BPF_PIPELINE_FILL;
switch (cmd->cmd) {
case KEXEC_BPF_CMD_DONE:
ctx->parsed = true;
@@ -301,6 +305,23 @@ static int kexec_buff_parser(struct bpf_parser_context *parser)
vfree(ctx->kernel);
ctx->kernel = decompressed_buf;
ctx->kernel_sz = decompressed_sz;
+ if (fill_pipeline) {
+ int i;
+
+ for (i = 0; i < MAX_PARSING_BUF_NUM; i++) {
+ if (ctx->next_parsing_buf[i])
+ continue;
+ ctx->next_parsing_buf[i] = decompressed_buf;
+ ctx->next_parsing_buf_sz[i] = decompressed_sz;
+ break;
+ }
+ /* No enough parsing slot */
+ if (i == MAX_PARSING_BUF_NUM) {
+ ctx->kernel = NULL;
+ vfree(decompressed_buf);
+ return -ENOMEM;
+ }
+ }
break;
default:
vfree(decompressed_buf);
@@ -313,6 +334,22 @@ static int kexec_buff_parser(struct bpf_parser_context *parser)
if (!p)
return -ENOMEM;
memcpy(p, buf, cmd->payload_len);
+ if (fill_pipeline) {
+ pn = __vmalloc(cmd->payload_len, GFP_KERNEL | __GFP_ACCOUNT);
+ if (!pn) {
+ vfree(p);
+ return -ENOMEM;
+ }
+ memcpy(pn, buf, cmd->payload_len);
+ for (int i = 0; i < MAX_PARSING_BUF_NUM; i++) {
+ if (!ctx->next_parsing_buf[i]) {
+ ctx->next_parsing_buf[i] = pn;
+ ctx->next_parsing_buf_sz[i] = cmd->payload_len;
+ break;
+ }
+ }
+ }
+
switch (cmd->subcmd) {
case KEXEC_BPF_SUBCMD_KERNEL:
vfree(ctx->kernel);
@@ -637,6 +674,14 @@ static int process_bpf_parsers_container(const char *elf_buf, size_t elf_sz,
context->parsing_buf[i] = NULL;
context->parsing_buf_sz[i] = 0;
}
+ for (int i = 0; i < MAX_PARSING_BUF_NUM; i++) {
+ if (!context->next_parsing_buf[i])
+ break;
+ context->parsing_buf[i] = context->next_parsing_buf[i];
+ context->parsing_buf_sz[i] = context->next_parsing_buf_sz[i];
+ context->next_parsing_buf[i] = NULL;
+ context->next_parsing_buf_sz[i] = 0;
+ }
put_bpf_parser_context(bpf);
/* If the bpf-prog success, it flags by KEXEC_BPF_CMD_DONE */
--
2.49.0
More information about the kexec
mailing list