diff options
author | Nate Williams <nate@FreeBSD.org> | 1996-06-10 16:23:42 +0000 |
---|---|---|
committer | Nate Williams <nate@FreeBSD.org> | 1996-06-10 16:23:42 +0000 |
commit | 1c346c709215b42b13b762c12a256d333b98f1bc (patch) | |
tree | fac0a614ca641dfd02698e370948ecda7255db86 /sys | |
parent | 8cd6893074819b6a537e42ecfa98a51508c4cbb7 (diff) | |
download | src-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.c | 68 | ||||
-rw-r--r-- | sys/sys/sysctl.h | 3 |
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*)); |