From: Christian Brauner <brauner@kernel.org>
To: Jacob Lalonde <jalalonde@meta.com>, Josef Bacik <josef@toxicpanda.com>
Cc: 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-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, linux-kselftest@vger.kernel.org,
"Christian Brauner (Amutable)" <brauner@kernel.org>
Subject: [PATCH 10/11] coredump: describe the holes when COREDUMP_SPARSE is negotiated
Date: Tue, 11 Aug 2026 17:27:31 +0200 [thread overview]
Message-ID: <20260811-work-coredump-sparse-v1-10-cd3e8b1e356d@kernel.org> (raw)
In-Reply-To: <20260811-work-coredump-sparse-v1-0-cd3e8b1e356d@kernel.org>
Offer COREDUMP_SPARSE in coredump_req->mask now that there is something
behind it. Refuse it without COREDUMP_HEADER. A zero frame cannot exist
outside a framed stream.
A trailing hole is flushed by coredump_write() the way it always was. So
its last byte goes out as a one-byte data frame and the frames cover the
whole coredump.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
fs/coredump.c | 34 +++++++++++++++++++++-
.../selftests/coredump/coredump_test_helpers.c | 3 +-
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/fs/coredump.c b/fs/coredump.c
index 364c89c5f82a..bdf2eae948d0 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -799,7 +799,7 @@ static bool coredump_sock_request(struct core_name *cn, struct coredump_params *
.size = sizeof(struct coredump_req),
.mask = COREDUMP_KERNEL | COREDUMP_USERSPACE |
COREDUMP_REJECT | COREDUMP_WAIT |
- COREDUMP_HEADER,
+ COREDUMP_HEADER | COREDUMP_SPARSE,
.size_ack = sizeof(struct coredump_ack),
};
struct coredump_ack ack = {};
@@ -854,6 +854,12 @@ static bool coredump_sock_request(struct core_name *cn, struct coredump_params *
return false;
}
+ /* Zero frames only exist inside a framed stream. */
+ if ((ack.mask & COREDUMP_SPARSE) && !(ack.mask & COREDUMP_HEADER)) {
+ coredump_sock_mark(cprm->file, COREDUMP_MARK_CONFLICTING);
+ return false;
+ }
+
if (ack.spare) {
coredump_sock_mark(cprm->file, COREDUMP_MARK_UNSUPPORTED);
return false;
@@ -1229,6 +1235,11 @@ static bool dump_framed(const struct coredump_params *cprm)
return cprm->mask & COREDUMP_HEADER;
}
+static bool dump_sparse(const struct coredump_params *cprm)
+{
+ return cprm->mask & COREDUMP_SPARSE;
+}
+
/* Describe the next @len bytes of the coredump. Returns the header size. */
static size_t dump_frame_init(struct coredump_params *cprm,
enum coredump_frame_type type, u64 len)
@@ -1292,11 +1303,32 @@ static int __dump_emit(struct coredump_params *cprm, const void *addr, int nr)
return dump_write_iter(cprm, &iter, nr);
}
+/* Hand the server the length of the hole instead of the hole itself. */
+static int dump_skip_frame(struct coredump_params *cprm, size_t nr)
+{
+ struct kvec kvec;
+ struct iov_iter iter;
+ size_t hdr;
+
+ if (dump_interrupted())
+ return 0;
+
+ hdr = dump_frame_init(cprm, COREDUMP_FRAME_ZERO, nr);
+ kvec.iov_base = cprm->frame;
+ kvec.iov_len = hdr;
+ iov_iter_kvec(&iter, ITER_SOURCE, &kvec, 1, hdr);
+
+ return dump_write_iter(cprm, &iter, nr);
+}
+
static int __dump_skip(struct coredump_params *cprm, size_t nr)
{
static char zeroes[PAGE_SIZE];
struct file *file = cprm->file;
+ if (dump_sparse(cprm))
+ return dump_skip_frame(cprm, nr);
+
if (file->f_mode & FMODE_LSEEK) {
if (dump_interrupted() || vfs_llseek(file, nr, SEEK_CUR) < 0)
return 0;
diff --git a/tools/testing/selftests/coredump/coredump_test_helpers.c b/tools/testing/selftests/coredump/coredump_test_helpers.c
index bfe10bc51618..ee669969605b 100644
--- a/tools/testing/selftests/coredump/coredump_test_helpers.c
+++ b/tools/testing/selftests/coredump/coredump_test_helpers.c
@@ -290,7 +290,8 @@ bool send_coredump_ack(int fd, const struct coredump_req *req,
/* Every option the kernel is expected to advertise in coredump_req->mask. */
#define COREDUMP_REQ_MASK_ALL \
(COREDUMP_KERNEL | COREDUMP_USERSPACE | \
- COREDUMP_REJECT | COREDUMP_WAIT | COREDUMP_HEADER)
+ COREDUMP_REJECT | COREDUMP_WAIT | \
+ COREDUMP_HEADER | COREDUMP_SPARSE)
bool check_coredump_req(const struct coredump_req *req)
{
--
2.53.0
next prev parent reply other threads:[~2026-08-11 15:28 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-11 15:27 [PATCH 00/11] coredump: allow to create sparse coredumps on the coredump socket Christian Brauner
2026-08-11 15:27 ` [PATCH 01/11] selftests/coredump: discard the right amount after the coredump request Christian Brauner
2026-08-11 15:27 ` [PATCH 02/11] selftests/coredump: collapse the expected request check into the helper Christian Brauner
2026-08-11 15:27 ` [PATCH 03/11] coredump: pin the protocol struct sizes Christian Brauner
2026-08-11 15:27 ` [PATCH 04/11] coredump: move the negotiated mask into struct coredump_params Christian Brauner
2026-08-11 15:27 ` [PATCH 05/11] coredump: deduplicate the to_skip flush Christian Brauner
2026-08-11 15:27 ` [PATCH 06/11] coredump: add COREDUMP_HEADER to the coredump socket protocol Christian Brauner
2026-08-11 15:27 ` [PATCH 07/11] coredump: add COREDUMP_SPARSE " Christian Brauner
2026-08-11 15:27 ` [PATCH 08/11] tools: sync coredump.h header Christian Brauner
2026-08-11 15:27 ` [PATCH 09/11] coredump: frame the coredump when COREDUMP_HEADER is negotiated Christian Brauner
2026-08-11 15:27 ` Christian Brauner [this message]
2026-08-11 15:27 ` [PATCH 11/11] selftests/coredump: test COREDUMP_HEADER and COREDUMP_SPARSE Christian Brauner
2026-08-11 19:07 ` [PATCH 00/11] coredump: allow to create sparse coredumps on the coredump socket Jann Horn
2026-08-11 19:39 ` Jann Horn
2026-08-11 20:55 ` 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=20260811-work-coredump-sparse-v1-10-cd3e8b1e356d@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=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=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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox