summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authormdf <mdf@FreeBSD.org>2011-01-27 00:34:12 +0000
committermdf <mdf@FreeBSD.org>2011-01-27 00:34:12 +0000
commit7fc649fc41274dcd3ffbed0d354a418b71e65786 (patch)
treee4eadeb1ff33d6db2e7b3001b1b8a9e9c21e2a2f /sys/kern
parent886222db75f8a2f0e19f97934a5375f602e0987a (diff)
downloadFreeBSD-src-7fc649fc41274dcd3ffbed0d354a418b71e65786.zip
FreeBSD-src-7fc649fc41274dcd3ffbed0d354a418b71e65786.tar.gz
Explicitly wire the user buffer rather than doing it implicitly in
sbuf_new_for_sysctl(9). This allows using an sbuf with a SYSCTL_OUT drain for extremely large amounts of data where the caller knows that appropriate references are held, and sleeping is not an issue. Inspired by: rwatson
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_malloc.c6
-rw-r--r--sys/kern/kern_sysctl.c6
-rw-r--r--sys/kern/subr_lock.c3
-rw-r--r--sys/kern/subr_sleepqueue.c3
-rw-r--r--sys/kern/subr_witness.c4
5 files changed, 18 insertions, 4 deletions
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index 9c7ff40..a3a9795 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -862,6 +862,9 @@ sysctl_kern_malloc_stats(SYSCTL_HANDLER_ARGS)
int error, i;
struct sbuf sbuf;
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
mtx_lock(&malloc_mtx);
@@ -1019,6 +1022,9 @@ sysctl_kern_mprof(SYSCTL_HANDLER_ARGS)
waste = 0;
mem = 0;
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
sbuf_printf(&sbuf,
"\n Size Requests Real Size\n");
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 7769a6d..cde8a0c 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1591,7 +1591,8 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
}
/*
- * Drain into a sysctl struct. The user buffer must be wired.
+ * Drain into a sysctl struct. The user buffer should be wired if a page
+ * fault would cause issue.
*/
static int
sbuf_sysctl_drain(void *arg, const char *data, int len)
@@ -1609,9 +1610,6 @@ sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length,
struct sysctl_req *req)
{
- /* Wire the user buffer, so we can write without blocking. */
- sysctl_wire_old_buffer(req, 0);
-
s = sbuf_new(s, buf, length, SBUF_FIXEDLEN);
sbuf_set_drain(s, sbuf_sysctl_drain, req);
return (s);
diff --git a/sys/kern/subr_lock.c b/sys/kern/subr_lock.c
index 25c1965..be9fa31 100644
--- a/sys/kern/subr_lock.c
+++ b/sys/kern/subr_lock.c
@@ -393,6 +393,9 @@ dump_lock_prof_stats(SYSCTL_HANDLER_ARGS)
int error, cpu, t;
int enabled;
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
sb = sbuf_new_for_sysctl(NULL, NULL, LPROF_SBUF_SIZE, req);
sbuf_printf(sb, "\n%8s %9s %11s %11s %11s %6s %6s %2s %6s %s\n",
"max", "wait_max", "total", "wait_total", "count", "avg", "wait_avg", "cnt_hold", "cnt_lock", "name");
diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c
index 5d1ae86..4ef7c48 100644
--- a/sys/kern/subr_sleepqueue.c
+++ b/sys/kern/subr_sleepqueue.c
@@ -1130,6 +1130,9 @@ dump_sleepq_prof_stats(SYSCTL_HANDLER_ARGS)
int error;
int i;
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
sb = sbuf_new_for_sysctl(NULL, NULL, SLEEPQ_SBUFSIZE, req);
sbuf_printf(sb, "\nwmesg\tcount\n");
enabled = prof_enabled;
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 3fec4c4..e1c00fe 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -2544,6 +2544,10 @@ sysctl_debug_witness_fullgraph(SYSCTL_HANDLER_ARGS)
return (error);
}
error = 0;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
sb = sbuf_new_for_sysctl(NULL, NULL, FULLGRAPH_SBUF_SIZE, req);
if (sb == NULL)
return (ENOMEM);
OpenPOWER on IntegriCloud