Add PTRTOUINT64() and UINT64TOPTR() macros to sys/sysctl.h for use by

kern.proc, kern.proc2, kern.lwp, and kern.buf.

Define more MIB for kern.buf so that specific buffers can be selected
(only all/all is supported right now), and use a 32/64 bit agnostic
structure for communcating buffer information to userland.

Convert systat to the new kern.buf method.

Clean up the vm.buf* handling a little.  There's no actual need to
record the dynamically assigned OIDs, since sysctl_data can tell us
what we're looking at.

Oh, and fix a typo in a comment.
This commit is contained in:
atatat 2004-02-19 03:56:30 +00:00
parent cb57c6f8e9
commit caea20e952
3 changed files with 134 additions and 59 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_bio.c,v 1.116 2004/02/16 09:34:15 yamt Exp $ */
/* $NetBSD: vfs_bio.c,v 1.117 2004/02/19 03:56:30 atatat Exp $ */
/*-
* Copyright (c) 1982, 1986, 1989, 1993
@ -81,7 +81,7 @@
#include "opt_softdep.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.116 2004/02/16 09:34:15 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.117 2004/02/19 03:56:30 atatat Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -1434,54 +1434,96 @@ fail:;
return nbusy;
}
static void
sysctl_fillbuf(struct buf *i, struct buf_sysctl *o)
{
o->b_flags = i->b_flags;
o->b_error = i->b_error;
o->b_prio = i->b_prio;
o->b_dev = i->b_dev;
o->b_bufsize = i->b_bufsize;
o->b_bcount = i->b_bcount;
o->b_resid = i->b_resid;
o->b_addr = PTRTOUINT64(i->b_un.b_addr);
o->b_blkno = i->b_blkno;
o->b_rawblkno = i->b_rawblkno;
o->b_iodone = PTRTOUINT64(i->b_iodone);
o->b_proc = PTRTOUINT64(i->b_proc);
o->b_vp = PTRTOUINT64(i->b_vp);
o->b_saveaddr = PTRTOUINT64(i->b_saveaddr);
o->b_lblkno = i->b_lblkno;
}
#define KERN_BUFSLOP 20
static int
sysctl_dobuf(SYSCTLFN_ARGS)
{
struct buf *bp;
struct buf_sysctl bs;
char *dp;
u_int i, elem_size;
size_t len, buflen, needed;
int error, s;
u_int i, op, arg;
size_t len, needed, elem_size, out_size;
int error, s, elem_count;
if (namelen == 1 && name[0] == CTL_QUERY)
return (sysctl_query(SYSCTLFN_CALL(rnode)));
if (namelen != 4)
return (EINVAL);
dp = oldp;
len = buflen = oldp != NULL ? *oldlenp : 0;
len = (oldp != NULL) ? *oldlenp : 0;
op = name[0];
arg = name[1];
elem_size = name[2];
elem_count = name[3];
out_size = MIN(sizeof(bs), elem_size);
/*
* at the moment, these are just "placeholders" to make the
* API for retrieving kern.buf data more extensible in the
* future.
*
* XXX kern.buf currently has "netbsd32" issues. hopefully
* these will be resolved at a later point.
*/
if (op != KERN_BUF_ALL || arg != KERN_BUF_ALL ||
elem_size < 1 || elem_count < 0)
return (EINVAL);
error = 0;
needed = 0;
elem_size = sizeof(struct buf);
s = splbio();
simple_lock(&bqueue_slock);
for (i = 0; i < BQUEUES; i++) {
TAILQ_FOREACH(bp, &bufqueues[i], b_freelist) {
if (len >= elem_size) {
error = copyout(bp, dp, elem_size);
if (len >= elem_size && elem_count > 0) {
sysctl_fillbuf(bp, &bs);
error = copyout(&bs, dp, out_size);
if (error)
goto cleanup;
dp += elem_size;
len -= elem_size;
}
needed += elem_size;
if (elem_count > 0) {
needed += elem_size;
if (elem_count != INT_MAX)
elem_count--;
}
}
}
cleanup:
simple_unlock(&bqueue_slock);
splx(s);
if (oldp != NULL) {
*oldlenp = (char *)dp - (char *)oldp;
if (needed > *oldlenp)
error = ENOMEM;
} else {
needed += KERN_BUFSLOP;
*oldlenp = needed;
}
*oldlenp = needed;
if (oldp == NULL)
*oldlenp += KERN_BUFSLOP * sizeof(struct buf);
return (error);
}
static int sysctlnum_bufcache, sysctlnum_bufmemhiwater, sysctlnum_bufmemlowater;
static int
sysctl_bufvm_update(SYSCTLFN_ARGS)
{
@ -1495,7 +1537,7 @@ sysctl_bufvm_update(SYSCTLFN_ARGS)
if (error || newp == NULL)
return (error);
if (rnode->sysctl_num == sysctlnum_bufcache) {
if (rnode->sysctl_data == &bufcache) {
if (t < 0 || t > 100)
return (EINVAL);
bufcache = t;
@ -1505,9 +1547,9 @@ sysctl_bufvm_update(SYSCTLFN_ARGS)
/* Ensure a reasonable minimum value */
bufmem_lowater = 64 * 1024;
} else if (rnode->sysctl_num == sysctlnum_bufmemlowater) {
} else if (rnode->sysctl_data == &bufmem_lowater) {
bufmem_lowater = t;
} else if (rnode->sysctl_num == sysctlnum_bufmemhiwater) {
} else if (rnode->sysctl_data == &bufmem_hiwater) {
bufmem_hiwater = t;
} else
return (EINVAL);
@ -1536,33 +1578,24 @@ SYSCTL_SETUP(sysctl_kern_buf_setup, "sysctl kern.buf subtree setup")
SYSCTL_SETUP(sysctl_vm_buf_setup, "sysctl vm.buf* subtree setup")
{
struct sysctlnode *rnode;
sysctl_createv(SYSCTL_PERMANENT,
CTLTYPE_NODE, "vm", NULL,
NULL, 0, NULL, 0,
CTL_VM, CTL_EOL);
rnode = NULL;
if (sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE,
CTLTYPE_INT, "bufcache", &rnode,
sysctl_bufvm_update, 0, &bufcache, 0,
CTL_VM, CTL_CREATE, CTL_EOL) == 0)
sysctlnum_bufcache = rnode->sysctl_num;
rnode = NULL;
if (sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE,
CTLTYPE_INT, "bufmem_lowater", &rnode,
sysctl_bufvm_update, 0, &bufmem_lowater, 0,
CTL_VM, CTL_CREATE, CTL_EOL) == 0)
sysctlnum_bufmemlowater = rnode->sysctl_num;
rnode = NULL;
if (sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE,
CTLTYPE_INT, "bufmem_hiwater", &rnode,
sysctl_bufvm_update, 0, &bufmem_hiwater, 0,
CTL_VM, CTL_CREATE, CTL_EOL) == 0)
sysctlnum_bufmemhiwater = rnode->sysctl_num;
sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE,
CTLTYPE_INT, "bufcache", NULL,
sysctl_bufvm_update, 0, &bufcache, 0,
CTL_VM, CTL_CREATE, CTL_EOL);
sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE,
CTLTYPE_INT, "bufmem_lowater", NULL,
sysctl_bufvm_update, 0, &bufmem_lowater, 0,
CTL_VM, CTL_CREATE, CTL_EOL);
sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE,
CTLTYPE_INT, "bufmem_hiwater", NULL,
sysctl_bufvm_update, 0, &bufmem_hiwater, 0,
CTL_VM, CTL_CREATE, CTL_EOL);
}
#ifdef DEBUG

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysctl.h,v 1.108 2004/02/13 11:36:23 wiz Exp $ */
/* $NetBSD: sysctl.h,v 1.109 2004/02/19 03:56:30 atatat Exp $ */
/*
* Copyright (c) 1989, 1993
@ -382,6 +382,13 @@ struct kinfo_proc {
} kp_eproc;
};
/*
* Convert pointer to 64 bit unsigned integer for struct
* kinfo_proc2, etc.
*/
#define PTRTOUINT64(p) ((u_int64_t)(uintptr_t)(p))
#define UINT64TOPTR(u) ((void *)(uintptr_t)(u))
/*
* KERN_PROC2 subtype ops return arrays of relatively fixed size
* structures of process info. Use 8 byte alignment, and new
@ -573,7 +580,7 @@ struct kinfo_lwp {
}
/*
* kern.drivers returns and array of these.
* kern.drivers returns an array of these.
*/
struct kinfo_drivers {
@ -582,6 +589,38 @@ struct kinfo_drivers {
char d_name[24];
};
/*
* KERN_BUF subtypes, like KERN_PROC2, where the four following mib
* entries specify "which type of buf", "which particular buf",
* "sizeof buf", and "how many". Currently, only "all buf" is
* defined.
*/
#define KERN_BUF_ALL 0 /* all buffers */
/*
* kern.buf returns an array of these structures, which are designed
* both to be immune to 32/64 bit emulation issues and to provide
* backwards compatibility. Note that the order here differs slightly
* from the real struct buf in order to achieve proper 64 bit
* alignment.
*/
struct buf_sysctl {
uint32_t b_flags; /* LONG: B_* flags */
int32_t b_error; /* INT: Errno value */
int32_t b_prio; /* INT: Hint for buffer queue discipline */
uint32_t b_dev; /* DEV_T: Device associated with buffer */
uint64_t b_bufsize; /* LONG: Allocated buffer size */
uint64_t b_bcount; /* LONG: Valid bytes in buffer */
uint64_t b_resid; /* LONG: Remaining I/O */
uint64_t b_addr; /* CADDR_T: Memory, superblocks, indirect... */
uint64_t b_blkno; /* DADDR_T: Underlying physical block number */
uint64_t b_rawblkno; /* DADDR_T: Raw underlying physical block */
uint64_t b_iodone; /* PTR: Function called upon completion */
uint64_t b_proc; /* PTR: Associated proc if B_PHYS set */
uint64_t b_vp; /* PTR: File vnode */
uint64_t b_saveaddr; /* PTR: Original b_addr for physio */
uint64_t b_lblkno; /* DADDR_T: Logical block number */
};
/*
* CTL_HW identifiers

View File

@ -1,4 +1,4 @@
/* $NetBSD: bufcache.c,v 1.15 2003/12/30 12:52:48 pk Exp $ */
/* $NetBSD: bufcache.c,v 1.16 2004/02/19 03:56:30 atatat Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: bufcache.c,v 1.15 2003/12/30 12:52:48 pk Exp $");
__RCSID("$NetBSD: bufcache.c,v 1.16 2004/02/19 03:56:30 atatat Exp $");
#endif /* not lint */
#include <sys/param.h>
@ -237,13 +237,12 @@ void
fetchbufcache(void)
{
int count;
struct buf *bp;
struct buf_sysctl *bp, *buffers;
struct vnode *vn;
struct mount *mt;
struct ml_entry *ml;
int mib[2];
int mib[6];
size_t size;
struct buf *buffers;
int extraslop = 0;
/* Re-read pages used for vnodes & executables */
@ -254,25 +253,29 @@ fetchbufcache(void)
ml_init();
/* Get metadata buffers */
again:
size = 0;
buffers = NULL;
mib[0] = CTL_KERN;
mib[1] = KERN_BUF;
if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0) {
mib[2] = KERN_BUF_ALL;
mib[3] = KERN_BUF_ALL;
mib[4] = (int)sizeof(struct buf_sysctl);
mib[5] = INT_MAX; /* we want them all */
again:
if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
error("can't get buffers size: %s\n", strerror(errno));
return;
}
if (size == 0)
return;
size += extraslop * sizeof(struct buf);
size += extraslop * sizeof(struct buf_sysctl);
buffers = malloc(size);
if (buffers == NULL) {
error("can't allocate buffers: %s\n", strerror(errno));
return;
}
if (sysctl(mib, 2, buffers, &size, NULL, 0) < 0) {
if (sysctl(mib, 6, buffers, &size, NULL, 0) < 0) {
free(buffers);
if (extraslop == 0) {
extraslop = 100;
@ -282,11 +285,11 @@ again:
return;
}
nbuf = size / sizeof(struct buf);
nbuf = size / sizeof(struct buf_sysctl);
for (bp = buffers; bp < buffers + nbuf; bp++) {
if (bp->b_vp != NULL) {
if (UINT64TOPTR(bp->b_vp) != NULL) {
struct mount *mp;
vn = vc_lookup(bp->b_vp);
vn = vc_lookup(UINT64TOPTR(bp->b_vp));
if (vn == NULL)
break;