summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sysctl.c
diff options
context:
space:
mode:
authornate <nate@FreeBSD.org>1996-06-10 16:23:42 +0000
committernate <nate@FreeBSD.org>1996-06-10 16:23:42 +0000
commit68b3f1ce70e0dec9ed0b3454f40628b409196f2d (patch)
treefac0a614ca641dfd02698e370948ecda7255db86 /sys/kern/kern_sysctl.c
parent6ae6d3340ac8335cf0acd5587e8bd8fa075656ba (diff)
downloadFreeBSD-src-68b3f1ce70e0dec9ed0b3454f40628b409196f2d.zip
FreeBSD-src-68b3f1ce70e0dec9ed0b3454f40628b409196f2d.tar.gz
Implemented 'kern_sysctl', which differs from 'userland_sysctl' in that
it assumes all of the data exists in the kernel. Also, fix sysctl_new-kernel (unused until now) which had reversed operands to bcopy(). Reviewed by: phk Poul writes: ... actually the lock/sleep/wakeup cruft shouldn't be needed in the kernel version I think, but just leave it there for now.
Diffstat (limited to 'sys/kern/kern_sysctl.c')
-rw-r--r--sys/kern/kern_sysctl.c68
1 files changed, 63 insertions, 5 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 51c78b9..1d26922 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -37,7 +37,7 @@
* SUCH DAMAGE.
*
* @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
- * $Id: kern_sysctl.c,v 1.62 1996/04/13 13:28:54 phk Exp $
+ * $Id: kern_sysctl.c,v 1.63 1996/06/06 17:17:54 phk Exp $
*/
#include <sys/param.h>
@@ -571,24 +571,82 @@ sysctl_old_kernel(struct sysctl_req *req, const void *p, int l)
bcopy(p, req->oldptr + req->oldidx, i);
}
req->oldidx += l;
- if (i != l)
+ if (req->oldptr && i != l)
return (ENOMEM);
return (0);
-
}
static int
-sysctl_new_kernel(struct sysctl_req *req, const void *p, int l)
+sysctl_new_kernel(struct sysctl_req *req, void *p, int l)
{
if (!req->newptr)
return 0;
if (req->newlen - req->newidx < l)
return (EINVAL);
- bcopy(p, req->newptr + req->newidx, l);
+ bcopy(req->newptr + req->newidx, p, l);
req->newidx += l;
return (0);
}
+int
+kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen, int *retval)
+{
+ int error = 0;
+ struct sysctl_req req;
+
+ bzero(&req, sizeof req);
+
+ req.p = p;
+
+ if (oldlenp) {
+ req.oldlen = *oldlenp;
+ }
+
+ if (old) {
+ req.oldptr= old;
+ }
+
+ if (newlen) {
+ req.newlen = newlen;
+ req.newptr = new;
+ }
+
+ req.oldfunc = sysctl_old_kernel;
+ req.newfunc = sysctl_new_kernel;
+ req.lock = 1;
+
+ /* XXX this should probably be done in a general way */
+ while (memlock.sl_lock) {
+ memlock.sl_want = 1;
+ (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0);
+ memlock.sl_locked++;
+ }
+ memlock.sl_lock = 1;
+
+ error = sysctl_root(0, name, namelen, &req);
+
+ if (req.lock == 2)
+ vsunlock(req.oldptr, req.oldlen, B_WRITE);
+
+ memlock.sl_lock = 0;
+
+ if (memlock.sl_want) {
+ memlock.sl_want = 0;
+ wakeup((caddr_t)&memlock);
+ }
+
+ if (error && error != ENOMEM)
+ return (error);
+
+ if (retval) {
+ if (req.oldptr && req.oldidx > req.oldlen)
+ *retval = req.oldlen;
+ else
+ *retval = req.oldidx;
+ }
+ return (error);
+}
+
/*
* Transfer function to/from user space.
*/
OpenPOWER on IntegriCloud