Date: Mon, 03 Aug 2026 18:15:42 +0000 From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Abdelkader Boudih <freebsd@seuros.com> Subject: git: 9590878fca68 - main - kqueue: stream the knote report instead of buffering all of it Message-ID: <6a70dace.1d7e0.11c0a964@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=9590878fca68e62c63d607da73139698e204d0f0 commit 9590878fca68e62c63d607da73139698e204d0f0 Author: Abdelkader Boudih <freebsd@seuros.com> AuthorDate: 2026-08-03 18:12:19 +0000 Commit: Adrian Chadd <adrian@FreeBSD.org> CommitDate: 2026-08-03 18:15:15 +0000 kqueue: stream the knote report instead of buffering all of it kern_proc_kqueues_out() sized its intermediate sbuf from the preceding sizing pass, so dumping core for a process with many knotes wired a buffer as large as the entire report. Shrank the intermediate to one page and added a drain that copied into the caller's sbuf up to maxlen, stopping the walk once it was reached. Truncation stayed byte exact. A dump of 384k knotes peaked at 20 KB of M_SBUF instead of 445 MB. Reviewed by: adrian, markj Differential Revision: https://reviews.freebsd.org/D58584 MFC after: 1 week --- sys/kern/kern_event.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 31dab74bd7bd..507451ce4492 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -3351,27 +3351,53 @@ kern_proc_kqueues_out1(struct thread *td, struct proc *p, struct sbuf *s, return (fget_remote_foreach(td, p, kern_proc_kqueues_out1_cb, &a)); } +struct kern_proc_kqueues_drain_ctx { + struct sbuf *sb; + size_t remaining; + bool full; +}; + +static int +kern_proc_kqueues_drain(void *arg, const char *data, int len) +{ + struct kern_proc_kqueues_drain_ctx *c; + size_t n; + + c = arg; + n = MIN((size_t)len, c->remaining); + if (n != 0) { + if (sbuf_bcat(c->sb, data, n) != 0) + return (-ENOMEM); + c->remaining -= n; + } + if (c->remaining == 0) { + c->full = true; + return (-ENOSPC); + } + return (len); +} + int kern_proc_kqueues_out(struct proc *p, struct sbuf *sb, size_t maxlen, bool compat32) { + struct kern_proc_kqueues_drain_ctx c; struct sbuf *s, sm; - size_t sb_len; int error; if (maxlen == -1) return (kern_proc_kqueues_out1(curthread, p, sb, compat32)); - if (maxlen == 0) - sb_len = 128; - else - sb_len = maxlen; - s = sbuf_new(&sm, NULL, sb_len + 1, SBUF_FIXEDLEN); + c.sb = sb; + c.remaining = maxlen; + c.full = false; + s = sbuf_new(&sm, NULL, PAGE_SIZE, SBUF_FIXEDLEN); + sbuf_set_drain(s, kern_proc_kqueues_drain, &c); error = kern_proc_kqueues_out1(curthread, p, s, compat32); sbuf_finish(s); - if (error == 0) - sbuf_bcat(sb, sbuf_data(s), MIN(sbuf_len(s), maxlen)); sbuf_delete(s); + if (c.full) + error = 0; return (error); }home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a70dace.1d7e0.11c0a964>
