aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNate Williams <nate@FreeBSD.org>1996-06-10 16:23:42 +0000
committerNate Williams <nate@FreeBSD.org>1996-06-10 16:23:42 +0000
commit1c346c709215b42b13b762c12a256d333b98f1bc (patch)
treefac0a614ca641dfd02698e370948ecda7255db86 /sys
parent8cd6893074819b6a537e42ecfa98a51508c4cbb7 (diff)
downloadsrc-1c346c709215b42b13b762c12a256d333b98f1bc.tar.gz
src-1c346c709215b42b13b762c12a256d333b98f1bc.zip
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.
Notes
Notes: svn path=/head/; revision=16282
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_sysctl.c68
-rw-r--r--sys/sys/sysctl.h3
2 files changed, 65 insertions, 6 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 51c78b9a1cc2..1d26922369d5 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.
*/
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 90b9f61a894e..f69f26d9a306 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)sysctl.h 8.1 (Berkeley) 6/2/93
- * $Id: sysctl.h,v 1.40 1996/02/24 14:32:53 peter Exp $
+ * $Id: sysctl.h,v 1.41 1996/03/11 02:17:53 hsu Exp $
*/
#ifndef _SYS_SYSCTL_H_
@@ -370,6 +370,7 @@ extern char machine[];
extern char osrelease[];
extern char ostype[];
+int kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen, int *retval);
int userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, int *retval);
/*
int sysctl_clockrate __P((char *, size_t*));