From: Christian Brauner <brauner@kernel.org>
To: linux-fsdevel@vger.kernel.org
Cc: Jacob Lalonde <jalalonde@meta.com>,
Josef Bacik <josef@toxicpanda.com>, Jann Horn <jannh@google.com>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Jan Kara <jack@suse.cz>,
Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>,
Omar Sandoval <osandov@osandov.com>,
Jacob Lalonde <jalalonde@fb.com>, Shuah Khan <shuah@kernel.org>,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-kselftest@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
"Christian Brauner (Amutable)" <brauner@kernel.org>
Subject: [PATCH v2 19/22] selftests/coredump: hand the record stream to a sink
Date: Thu, 20 Aug 2026 01:09:36 +0200 [thread overview]
Message-ID: <20260820-work-coredump-sparse-v2-19-ba32dd718c51@kernel.org> (raw)
In-Reply-To: <20260820-work-coredump-sparse-v2-0-ba32dd718c51@kernel.org>
Currently recv_coredump_records() parses the record stream and dumps it
into a file. A coredump server may want to process the data it gets. So
split the parsing from the processing.
No functional changes.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
.../selftests/coredump/coredump_test_helpers.c | 91 +++++++++++++++++-----
1 file changed, 72 insertions(+), 19 deletions(-)
diff --git a/tools/testing/selftests/coredump/coredump_test_helpers.c b/tools/testing/selftests/coredump/coredump_test_helpers.c
index 5b2ffe17f7b7..45d76fa0f469 100644
--- a/tools/testing/selftests/coredump/coredump_test_helpers.c
+++ b/tools/testing/selftests/coredump/coredump_test_helpers.c
@@ -71,9 +71,19 @@ void crashing_child_sparse(size_t size)
*(volatile int *)NULL = 0;
}
-/* Read @len bytes off the socket, writing them at @offset if @fd_out >= 0. */
-static ssize_t recv_record_bytes(int fd_coredump, __u64 len, int fd_out,
- off_t offset)
+/* Sink a reassembled record stream is handed to, record by record. */
+struct coredump_record_sink {
+ /* @len bytes of coredump data that belong at @offset. */
+ int (*data)(void *ctx, const void *buf, size_t len, __u64 offset);
+ /* @len zero bytes that belong at @offset. */
+ int (*zero)(void *ctx, __u64 offset, __u64 len);
+ void *ctx;
+};
+
+/* Read @len bytes off the socket and hand them to @sink, if there is one. */
+static ssize_t recv_record_bytes(int fd_coredump, __u64 len,
+ const struct coredump_record_sink *sink,
+ __u64 offset)
{
ssize_t received = 0;
@@ -89,11 +99,8 @@ static ssize_t recv_record_bytes(int fd_coredump, __u64 len, int fd_out,
return -1;
}
- if (fd_out >= 0 &&
- pwrite(fd_out, buffer, ret, offset + received) != ret) {
- fprintf(stderr, "%s: pwrite failed: %m\n", __func__);
+ if (sink && sink->data(sink->ctx, buffer, ret, offset + received))
return -1;
- }
received += ret;
len -= ret;
@@ -102,14 +109,34 @@ static ssize_t recv_record_bytes(int fd_coredump, __u64 len, int fd_out,
return received;
}
+/* Put the data where the records say it goes and leave the holes alone. */
+static int file_sink_data(void *ctx, const void *buf, size_t len, __u64 offset)
+{
+ int fd = *(int *)ctx;
+
+ if (pwrite(fd, buf, len, offset) != (ssize_t)len) {
+ fprintf(stderr, "%s: pwrite failed: %m\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int file_sink_zero(void *ctx, __u64 offset, __u64 len)
+{
+ /* Nothing has to be written for a hole. */
+ return 0;
+}
+
/*
- * Reassemble a record stream. If @fd_peer_pidfd is valid the task behind
- * it is killed once a data record has arrived, so the kernel has to cut
- * the coredump short with the stream already under way.
+ * Read a coredump strea and funnel it into @sink. Allow to pass in a
+ * @fd_peer_pidfd to simulate coredump truncation by killing it after having
+ * received a coredump record.
*/
-ssize_t recv_coredump_records(int fd_coredump, int fd_core_file,
- off_t *coredump_size, bool *truncated,
- int fd_peer_pidfd)
+static ssize_t __recv_coredump_records(int fd_coredump,
+ const struct coredump_record_sink *sink,
+ off_t *coredump_size, bool *truncated,
+ int fd_peer_pidfd)
{
ssize_t received = 0;
off_t size = 0;
@@ -169,7 +196,8 @@ ssize_t recv_coredump_records(int fd_coredump, int fd_core_file,
}
/* Discard any part of the header we have no use for. */
- ret = recv_record_bytes(fd_coredump, record.size - known_size, -1, 0);
+ ret = recv_record_bytes(fd_coredump, record.size - known_size,
+ NULL, 0);
if (ret < 0)
return -1;
received += ret;
@@ -185,10 +213,12 @@ ssize_t recv_coredump_records(int fd_coredump, int fd_core_file,
switch (record.type) {
case COREDUMP_RECORD_ZERO:
/* A hole. It comes with no data and needs none. */
+ if (sink->zero(sink->ctx, record.offset, record.len))
+ return -1;
break;
case COREDUMP_RECORD_DATA:
- ret = recv_record_bytes(fd_coredump, record.len,
- fd_core_file, size);
+ ret = recv_record_bytes(fd_coredump, record.len, sink,
+ record.offset);
if (ret < 0)
return -1;
received += ret;
@@ -230,6 +260,32 @@ ssize_t recv_coredump_records(int fd_coredump, int fd_core_file,
if (truncated)
*truncated = is_truncated;
+ *coredump_size = size;
+
+ fprintf(stderr, "Received %zd bytes for a %s coredump of %llu bytes\n",
+ received, is_truncated ? "truncated" : "complete",
+ (unsigned long long)size);
+ return received;
+}
+
+/* Reassemble a record stream into the coredump it describes. */
+ssize_t recv_coredump_records(int fd_coredump, int fd_core_file,
+ off_t *coredump_size, bool *truncated,
+ int fd_peer_pidfd)
+{
+ struct coredump_record_sink sink = {
+ .data = file_sink_data,
+ .zero = file_sink_zero,
+ .ctx = &fd_core_file,
+ };
+ ssize_t received;
+ off_t size = 0;
+
+ received = __recv_coredump_records(fd_coredump, &sink, &size, truncated,
+ fd_peer_pidfd);
+ if (received < 0)
+ return -1;
+
/*
* Nothing is written for a hole, so grow the file to the size the
* records describe in case the coredump ended in one.
@@ -243,9 +299,6 @@ ssize_t recv_coredump_records(int fd_coredump, int fd_core_file,
if (coredump_size)
*coredump_size = size;
- fprintf(stderr, "Received %zd bytes for a %s coredump of %llu bytes\n",
- received, is_truncated ? "truncated" : "complete",
- (unsigned long long)size);
return received;
}
--
2.53.0
next prev parent reply other threads:[~2026-08-19 23:11 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-19 23:09 [PATCH v2 00/22] coredump: allow to create sparse coredumps on the coredump socket Christian Brauner
2026-08-19 23:09 ` [PATCH v2 01/22] powerpc/spufs: don't dump more than the note supports Christian Brauner
2026-08-19 23:09 ` [PATCH v2 02/22] coredump: refuse negative skips Christian Brauner
2026-08-19 23:09 ` [PATCH v2 03/22] coredump: set the minimum send buffer size Christian Brauner
2026-08-19 23:09 ` [PATCH v2 04/22] selftests/coredump: discard the right amount after the coredump request Christian Brauner
2026-08-19 23:09 ` [PATCH v2 05/22] selftests/coredump: collapse the expected request check into the helper Christian Brauner
2026-08-19 23:09 ` [PATCH v2 06/22] selftests/coredump: add a separate helper header Christian Brauner
2026-08-19 23:09 ` [PATCH v2 07/22] coredump: pin the protocol struct sizes Christian Brauner
2026-08-19 23:09 ` [PATCH v2 08/22] coredump: move the negotiated mask into struct coredump_params Christian Brauner
2026-08-19 23:09 ` [PATCH v2 09/22] coredump: deduplicate the to_skip flush Christian Brauner
2026-08-19 23:09 ` [PATCH v2 10/22] coredump: make the dump helper return bool Christian Brauner
2026-08-19 23:09 ` [PATCH v2 11/22] coredump: always chunk writes Christian Brauner
2026-08-19 23:09 ` [PATCH v2 12/22] coredump: clean up coredump state handling Christian Brauner
2026-08-19 23:09 ` [PATCH v2 13/22] coredump: add COREDUMP_RECORDS to the coredump socket protocol Christian Brauner
2026-08-19 23:09 ` [PATCH v2 14/22] coredump: add COREDUMP_SPARSE " Christian Brauner
2026-08-19 23:09 ` [PATCH v2 15/22] tools: sync coredump.h header Christian Brauner
2026-08-19 23:09 ` [PATCH v2 16/22] coredump: send the coredump in records if requested Christian Brauner
2026-08-19 23:09 ` [PATCH v2 17/22] coredump: describe the holes when COREDUMP_SPARSE is negotiated Christian Brauner
2026-08-19 23:09 ` [PATCH v2 18/22] selftests/coredump: test COREDUMP_RECORDS and COREDUMP_SPARSE Christian Brauner
2026-08-19 23:09 ` Christian Brauner [this message]
2026-08-19 23:09 ` [PATCH v2 20/22] selftests/coredump: put a hole in the middle of a sparse mapping Christian Brauner
2026-08-19 23:09 ` [PATCH v2 21/22] selftests/coredump: simulate a blob store Christian Brauner
2026-08-19 23:09 ` [PATCH v2 22/22] selftests/coredump: show how to inspect the task to decide how the coredump should be sent Christian Brauner
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=20260820-work-coredump-sparse-v2-19-ba32dd718c51@kernel.org \
--to=brauner@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=david@kernel.org \
--cc=jack@suse.cz \
--cc=jalalonde@fb.com \
--cc=jalalonde@meta.com \
--cc=jannh@google.com \
--cc=josef@toxicpanda.com \
--cc=liam@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=osandov@osandov.com \
--cc=rppt@kernel.org \
--cc=shuah@kernel.org \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=viro@zeniv.linux.org.uk \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.