Skip site navigation (1)Skip section navigation (2)
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>