summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_prf.c
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2009-11-03 21:06:19 +0000
committered <ed@FreeBSD.org>2009-11-03 21:06:19 +0000
commitda18b1b80b0a91169134a3de012b7a7057a31ea2 (patch)
treeb1831228fc9c75d881dcef9aa5a2a860de274f46 /sys/kern/subr_prf.c
parent9c5e20b3b30bf122c0916cf06233432a77c450c8 (diff)
downloadFreeBSD-src-da18b1b80b0a91169134a3de012b7a7057a31ea2.zip
FreeBSD-src-da18b1b80b0a91169134a3de012b7a7057a31ea2.tar.gz
Make /dev/klog and kern.msgbuf* MPSAFE.
Normally msgbufp is locked using Giant. Switch it to use the msgbuf_lock. Instead of changing the tsleep() calls to msleep(), just convert it to condvar(9). In my opinion the locking around msgbuf_peekbytes() still remains questionable. It looks like locks are dropped while performing copies of multiple blocks to userspace, which may cause the msgbuf to be reset in the mean time. At least getting it underneath from Giant should make it a little easier for us to figure out how to solve that. Reminded by: rdivacky
Diffstat (limited to 'sys/kern/subr_prf.c')
-rw-r--r--sys/kern/subr_prf.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c
index 5c34f40..30e92cb 100644
--- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -923,16 +923,24 @@ sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
}
/* Read the whole buffer, one chunk at a time. */
+ mtx_lock(&msgbuf_lock);
msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
- while ((len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq)) > 0) {
+ for (;;) {
+ len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
+ mtx_unlock(&msgbuf_lock);
+ if (len == 0)
+ return (0);
+
error = sysctl_handle_opaque(oidp, buf, len, req);
if (error)
return (error);
+
+ mtx_lock(&msgbuf_lock);
}
- return (0);
}
-SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD,
+SYSCTL_PROC(_kern, OID_AUTO, msgbuf,
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
NULL, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
static int msgbuf_clearflag;
@@ -943,15 +951,18 @@ sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
int error;
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
if (!error && req->newptr) {
+ mtx_lock(&msgbuf_lock);
msgbuf_clear(msgbufp);
+ mtx_unlock(&msgbuf_lock);
msgbuf_clearflag = 0;
}
return (error);
}
SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clearflag, 0,
- sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer");
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE,
+ &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I",
+ "Clear kernel message buffer");
#ifdef DDB
OpenPOWER on IntegriCloud