git: fee6a52e4338 - main - sysctl_kern_proc_kqueue(): convert to use sbuf

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 24 Mar 2025 02:24:46 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=fee6a52e433811fde5a9f6be06bb446b5336aba3

commit fee6a52e433811fde5a9f6be06bb446b5336aba3
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-03-13 22:30:32 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-03-24 02:24:13 +0000

    sysctl_kern_proc_kqueue(): convert to use sbuf
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D49372
---
 sys/kern/kern_event.c | 74 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 44 insertions(+), 30 deletions(-)

diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 14aa3abd1901..b0106b5fa9ce 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -58,6 +58,7 @@
 #include <sys/poll.h>
 #include <sys/protosw.h>
 #include <sys/resourcevar.h>
+#include <sys/sbuf.h>
 #include <sys/sigio.h>
 #include <sys/signalvar.h>
 #include <sys/socket.h>
@@ -2871,7 +2872,7 @@ knote_status_export(int kn_status)
 }
 
 static int
-sysctl_kern_proc_kqueue_report_one(struct proc *p, struct sysctl_req *req,
+kern_proc_kqueue_report_one(struct sbuf *s, struct proc *p,
     struct kqueue *kq, struct knote *kn)
 {
 	struct kinfo_knote kin;
@@ -2887,13 +2888,41 @@ sysctl_kern_proc_kqueue_report_one(struct proc *p, struct sysctl_req *req,
 	KQ_UNLOCK_FLUX(kq);
 	if (kn->kn_fop->f_userdump != NULL)
 		(void)kn->kn_fop->f_userdump(p, kn, &kin);
-	error = SYSCTL_OUT(req, &kin, sizeof(kin));
-	maybe_yield();
+	error = sbuf_bcat(s, &kin, sizeof(kin));
 	KQ_LOCK(kq);
 	kn_leave_flux(kn);
 	return (error);
 }
 
+static int
+kern_proc_kqueue_report(struct sbuf *s, struct proc *p, struct kqueue *kq)
+{
+	struct knote *kn;
+	int error, i;
+
+	error = 0;
+	KQ_LOCK(kq);
+	for (i = 0; i < kq->kq_knlistsize; i++) {
+		SLIST_FOREACH(kn, &kq->kq_knlist[i], kn_link) {
+			error = kern_proc_kqueue_report_one(s, p, kq, kn);
+			if (error != 0)
+				goto out;
+		}
+	}
+	if (kq->kq_knhashmask == 0)
+		goto out;
+	for (i = 0; i <= kq->kq_knhashmask; i++) {
+		SLIST_FOREACH(kn, &kq->kq_knhash[i], kn_link) {
+			error = kern_proc_kqueue_report_one(s, p, kq, kn);
+			if (error != 0)
+				goto out;
+		}
+	}
+out:
+	KQ_UNLOCK_FLUX(kq);
+	return (error);
+}
+
 static int
 sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
 {
@@ -2901,8 +2930,8 @@ sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
 	struct proc *p;
 	struct file *fp;
 	struct kqueue *kq;
-	struct knote *kn;
-	int error, i, *name;
+	struct sbuf *s, sm;
+	int error, error1, *name;
 
 	name = (int *)arg1;
 	if ((u_int)arg2 != 2)
@@ -2928,34 +2957,19 @@ sysctl_kern_proc_kqueue(SYSCTL_HANDLER_ARGS)
 		goto out2;
 	}
 
-	kq = fp->f_data;
-	if (req->oldptr == NULL) {
-		error = SYSCTL_OUT(req, NULL, sizeof(struct kinfo_knote) *
-		    kq->kq_knlistsize * 11 / 10);
+	s = sbuf_new_for_sysctl(&sm, NULL, 0, req);
+	if (s == NULL) {
+		error = ENOMEM;
 		goto out2;
 	}
+	sbuf_clear_flags(s, SBUF_INCLUDENUL);
 
-	KQ_LOCK(kq);
-	for (i = 0; i < kq->kq_knlistsize; i++) {
-		SLIST_FOREACH(kn, &kq->kq_knlist[i], kn_link) {
-			error = sysctl_kern_proc_kqueue_report_one(p, req,
-			    kq, kn);
-			if (error != 0)
-				goto out3;
-		}
-	}
-	if (kq->kq_knhashmask == 0)
-		goto out3;
-	for (i = 0; i <= kq->kq_knhashmask; i++) {
-		SLIST_FOREACH(kn, &kq->kq_knhash[i], kn_link) {
-			error = sysctl_kern_proc_kqueue_report_one(p, req,
-			    kq, kn);
-			if (error != 0)
-				goto out3;
-		}
-	}
-out3:
-	KQ_UNLOCK_FLUX(kq);
+	kq = fp->f_data;
+	error = kern_proc_kqueue_report(s, p, kq);
+	error1 = sbuf_finish(s);
+	if (error == 0)
+		error = error1;
+	sbuf_delete(s);
 out2:
 	fdrop(fp, td);
 out1: