Get rid of setgid kmem for systat, and while being there, fix some bugs
and compiler warnings. The data for network statistics are still obtained via the kvm interface if systat was started with the needed privileges, otherwise sysctls are used. The reason for this is that with really many open sockets, the sysctl method is probably slower, but it systat -netstat is probably not really usable in either mode under these conditions. Approved by: rwatson
This commit is contained in:
parent
368d2edce4
commit
342e2faa09
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=74671
@ -8,7 +8,5 @@ SRCS= cmds.c cmdtab.c devs.c fetch.c iostat.c keyboard.c main.c \
|
||||
vmstat.c
|
||||
DPADD= ${LIBCURSES} ${LIBM} ${LIBKVM} ${LIBDEVSTAT}
|
||||
LDADD= -lcurses -lm -lkvm -ldevstat
|
||||
BINGRP= kmem
|
||||
BINMODE=2555
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -31,6 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 6/6/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
@ -67,6 +68,8 @@ extern int num_selected;
|
||||
extern int num_selections;
|
||||
extern long select_generation;
|
||||
|
||||
extern struct nlist namelist[];
|
||||
|
||||
int checkhost __P((struct inpcb *));
|
||||
int checkport __P((struct inpcb *));
|
||||
void closeiostat __P((WINDOW *));
|
||||
@ -97,6 +100,7 @@ void fetchnetstat __P((void));
|
||||
void fetchpigs __P((void));
|
||||
void fetchswap __P((void));
|
||||
void fetchtcp __P((void));
|
||||
void getsysctl __P((char *, void *, size_t));
|
||||
int initicmp __P((void));
|
||||
int initip __P((void));
|
||||
int initiostat __P((void));
|
||||
@ -145,3 +149,4 @@ void showswap __P((void));
|
||||
void showtcp __P((void));
|
||||
void status __P((void));
|
||||
void suspend __P((int));
|
||||
char *sysctl_dynread __P((char *, size_t *));
|
||||
|
@ -29,6 +29,8 @@
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
@ -36,6 +38,13 @@ static char sccsid[] = "@(#)fetch.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "systat.h"
|
||||
#include "extern.h"
|
||||
|
||||
@ -46,9 +55,94 @@ kvm_ckread(a, b, l)
|
||||
{
|
||||
if (kvm_read(kd, (u_long)a, b, l) != l) {
|
||||
if (verbose)
|
||||
error("error reading kmem at %x\n", a);
|
||||
error("error reading kmem at %x", a);
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
|
||||
void getsysctl(name, ptr, len)
|
||||
char *name;
|
||||
void *ptr;
|
||||
size_t len;
|
||||
{
|
||||
int err;
|
||||
size_t nlen = len;
|
||||
if ((err = sysctlbyname(name, ptr, &nlen, NULL, 0)) != 0) {
|
||||
error("sysctl(%s...) failed: %s", name,
|
||||
strerror(errno));
|
||||
}
|
||||
if (nlen != len) {
|
||||
error("sysctl(%s...) expected %d, got %d", name,
|
||||
len, nlen);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read sysctl data with variable size. Try some times (with increasing
|
||||
* buffers), fail if still too small.
|
||||
* This is needed sysctls with possibly raplidly increasing data sizes,
|
||||
* but imposes little overhead in the case of constant sizes.
|
||||
* Returns NULL on error, or a pointer to freshly malloc()'ed memory that holds
|
||||
* the requested data.
|
||||
* If szp is not NULL, the size of the returned data will be written into *szp.
|
||||
*/
|
||||
|
||||
/* Some defines: Number of tries. */
|
||||
#define SD_NTRIES 10
|
||||
/* Percent of over-allocation (initial) */
|
||||
#define SD_MARGIN 10
|
||||
/*
|
||||
* Factor for over-allocation in percent (the margin is increased by this on
|
||||
* any failed try).
|
||||
*/
|
||||
#define SD_FACTOR 50
|
||||
/* Maximum supported MIB depth */
|
||||
#define SD_MAXMIB 16
|
||||
|
||||
char *
|
||||
sysctl_dynread(n, szp)
|
||||
char *n;
|
||||
size_t *szp;
|
||||
{
|
||||
char *rv = NULL;
|
||||
int mib[SD_MAXMIB];
|
||||
size_t mibsz = SD_MAXMIB;
|
||||
size_t mrg = SD_MARGIN;
|
||||
size_t sz;
|
||||
int i;
|
||||
|
||||
/* cache the MIB */
|
||||
if (sysctlnametomib(n, mib, &mibsz) == -1) {
|
||||
if (errno == ENOMEM) {
|
||||
error("XXX: SD_MAXMIB too small, please bump!");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < SD_NTRIES; i++) {
|
||||
/* get needed buffer size */
|
||||
if (sysctl(mib, mibsz, NULL, &sz, NULL, 0) == -1)
|
||||
break;
|
||||
sz += sz * mrg / 100;
|
||||
if ((rv = (char *)malloc(sz)) == NULL) {
|
||||
error("Out of memory!");
|
||||
return NULL;
|
||||
}
|
||||
if (sysctl(mib, mibsz, rv, &sz, NULL, 0) == -1) {
|
||||
free(rv);
|
||||
rv = NULL;
|
||||
if (errno == ENOMEM) {
|
||||
mrg += mrg * SD_FACTOR / 100;
|
||||
} else
|
||||
break;
|
||||
} else {
|
||||
/* success */
|
||||
if (szp != NULL)
|
||||
*szp = sz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93";
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/dkstat.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -110,7 +111,7 @@ closeiostat(w)
|
||||
int
|
||||
initiostat()
|
||||
{
|
||||
if (num_devices = getnumdevs() < 0)
|
||||
if ((num_devices = getnumdevs()) < 0)
|
||||
return(0);
|
||||
|
||||
cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo));
|
||||
|
@ -47,6 +47,7 @@ static const char rcsid[] =
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <locale.h>
|
||||
@ -74,6 +75,7 @@ char *namp;
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
WINDOW *wnd;
|
||||
int CMDLINE;
|
||||
int use_kvm = 1;
|
||||
|
||||
static WINDOW *wload; /* one line window for load average */
|
||||
|
||||
@ -82,7 +84,7 @@ main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char errbuf[80];
|
||||
char errbuf[80], dummy;
|
||||
size_t size;
|
||||
int err;
|
||||
|
||||
@ -107,9 +109,29 @@ main(argc, argv)
|
||||
argc--, argv++;
|
||||
}
|
||||
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
|
||||
if (kd != NULL) {
|
||||
/*
|
||||
* Try to actually read something, we may be in a jail, and
|
||||
* have /dev/null opened as /dev/mem.
|
||||
*/
|
||||
if (kvm_nlist(kd, namelist) != 0 || namelist[0].n_value == 0 ||
|
||||
kvm_read(kd, namelist[0].n_value, &dummy, sizeof(dummy)) !=
|
||||
sizeof(dummy)) {
|
||||
kvm_close(kd);
|
||||
kd = NULL;
|
||||
}
|
||||
}
|
||||
if (kd == NULL) {
|
||||
error("%s", errbuf);
|
||||
exit(1);
|
||||
/*
|
||||
* Maybe we are lacking permissions? Retry, this time with bogus
|
||||
* devices. We can now use sysctl only.
|
||||
*/
|
||||
use_kvm = 0;
|
||||
kd = kvm_openfiles("/dev/null", "/dev/null", "/dev/null", O_RDONLY, errbuf);
|
||||
if (kd == NULL) {
|
||||
error("%s", errbuf);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
signal(SIGINT, die);
|
||||
signal(SIGQUIT, die);
|
||||
|
@ -253,7 +253,7 @@ showports()
|
||||
|
||||
for (p = ports; p < ports+nports; p++) {
|
||||
sp = getservbyport(p->port,
|
||||
protos == TCP|UDP ? 0 : protos == TCP ? "tcp" : "udp");
|
||||
protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
|
||||
if (!p->onoff)
|
||||
addch('!');
|
||||
if (sp)
|
||||
|
@ -60,6 +60,7 @@ static const char rcsid[] =
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/tcpip.h>
|
||||
#include <netinet/tcp_seq.h>
|
||||
#include <netinet/tcp_var.h>
|
||||
#define TCPSTATES
|
||||
#include <netinet/tcp_fsm.h>
|
||||
#include <netinet/tcp_timer.h>
|
||||
@ -76,7 +77,11 @@ static const char rcsid[] =
|
||||
#include "systat.h"
|
||||
#include "extern.h"
|
||||
|
||||
static void enter __P((struct inpcb *, struct socket *, int, char *));
|
||||
static struct netinfo *enter __P((struct inpcb *, int, char *));
|
||||
static void enter_kvm __P((struct inpcb *, struct socket *, int, char *));
|
||||
static void enter_sysctl __P((struct inpcb *, struct xsocket *, int, char *));
|
||||
static void fetchnetstat_kvm __P((void));
|
||||
static void fetchnetstat_sysctl __P((void));
|
||||
static char *inetname __P((struct in_addr));
|
||||
static void inetprint __P((struct in_addr *, int, char *));
|
||||
|
||||
@ -113,7 +118,6 @@ TAILQ_HEAD(netinfohead, netinfo) netcb = TAILQ_HEAD_INITIALIZER(netcb);
|
||||
static int aflag = 0;
|
||||
static int nflag = 0;
|
||||
static int lastrow = 1;
|
||||
static void enter(), inetprint();
|
||||
static char *inetname();
|
||||
|
||||
void
|
||||
@ -136,31 +140,37 @@ closenetstat(w)
|
||||
}
|
||||
}
|
||||
|
||||
static struct nlist namelist[] = {
|
||||
static char *miblist[] = {
|
||||
"net.inet.tcp.pcblist",
|
||||
"net.inet.udp.pcblist"
|
||||
};
|
||||
|
||||
struct nlist namelist[] = {
|
||||
#define X_TCB 0
|
||||
{ "_tcb" },
|
||||
{ "tcb" },
|
||||
#define X_UDB 1
|
||||
{ "_udb" },
|
||||
{ "udb" },
|
||||
{ "" },
|
||||
};
|
||||
|
||||
int
|
||||
initnetstat()
|
||||
{
|
||||
if (kvm_nlist(kd, namelist)) {
|
||||
nlisterr(namelist);
|
||||
return(0);
|
||||
}
|
||||
if (namelist[X_TCB].n_value == 0) {
|
||||
error("No symbols in namelist");
|
||||
return(0);
|
||||
}
|
||||
protos = TCP|UDP;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void
|
||||
fetchnetstat()
|
||||
{
|
||||
if (use_kvm)
|
||||
fetchnetstat_kvm();
|
||||
else
|
||||
fetchnetstat_sysctl();
|
||||
}
|
||||
|
||||
static void
|
||||
fetchnetstat_kvm()
|
||||
{
|
||||
register struct inpcb *next;
|
||||
register struct netinfo *p;
|
||||
@ -201,9 +211,9 @@ fetchnetstat()
|
||||
KREAD(inpcb.inp_socket, &sockb, sizeof (sockb));
|
||||
if (istcp) {
|
||||
KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
|
||||
enter(&inpcb, &sockb, tcpcb.t_state, "tcp");
|
||||
enter_kvm(&inpcb, &sockb, tcpcb.t_state, "tcp");
|
||||
} else
|
||||
enter(&inpcb, &sockb, 0, "udp");
|
||||
enter_kvm(&inpcb, &sockb, 0, "udp");
|
||||
}
|
||||
if (istcp && (protos&UDP)) {
|
||||
istcp = 0;
|
||||
@ -213,7 +223,84 @@ fetchnetstat()
|
||||
}
|
||||
|
||||
static void
|
||||
enter(inp, so, state, proto)
|
||||
fetchnetstat_sysctl()
|
||||
{
|
||||
register struct netinfo *p;
|
||||
int idx;
|
||||
struct xinpgen *inpg;
|
||||
char *cur, *end;
|
||||
struct inpcb *inpcb;
|
||||
struct xinpcb *xip;
|
||||
struct xtcpcb *xtp;
|
||||
int plen;
|
||||
size_t lsz;
|
||||
|
||||
TAILQ_FOREACH(p, &netcb, chain)
|
||||
p->ni_seen = 0;
|
||||
if (protos&TCP) {
|
||||
idx = 0;
|
||||
} else if (protos&UDP) {
|
||||
idx = 1;
|
||||
} else {
|
||||
error("No protocols to display");
|
||||
return;
|
||||
}
|
||||
|
||||
for (;idx < 2; idx++) {
|
||||
if (idx == 1 && !(protos&UDP))
|
||||
break;
|
||||
inpg = (struct xinpgen *)sysctl_dynread(miblist[idx], &lsz);
|
||||
if (inpg == NULL) {
|
||||
error("sysctl(%s...) failed", miblist[idx]);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* We currently do no require a consistent pcb list.
|
||||
* Try to be robust in case of struct size changes
|
||||
*/
|
||||
cur = ((char *)inpg) + inpg->xig_len;
|
||||
/* There is also a trailing struct xinpgen */
|
||||
end = ((char *)inpg) + lsz - inpg->xig_len;
|
||||
if (end <= cur) {
|
||||
free(inpg);
|
||||
continue;
|
||||
}
|
||||
if (idx == 0) { /* TCP */
|
||||
xtp = (struct xtcpcb *)cur;
|
||||
plen = xtp->xt_len;
|
||||
} else {
|
||||
xip = (struct xinpcb *)cur;
|
||||
plen = xip->xi_len;
|
||||
}
|
||||
while (cur + plen <= end) {
|
||||
if (idx == 0) { /* TCP */
|
||||
xtp = (struct xtcpcb *)cur;
|
||||
inpcb = &xtp->xt_inp;
|
||||
} else {
|
||||
xip = (struct xinpcb *)cur;
|
||||
inpcb = &xip->xi_inp;
|
||||
}
|
||||
cur += plen;
|
||||
|
||||
if (!aflag && inet_lnaof(inpcb->inp_laddr) ==
|
||||
INADDR_ANY)
|
||||
continue;
|
||||
if (nhosts && !checkhost(inpcb))
|
||||
continue;
|
||||
if (nports && !checkport(inpcb))
|
||||
continue;
|
||||
if (idx == 0) /* TCP */
|
||||
enter_sysctl(inpcb, &xtp->xt_socket,
|
||||
xtp->xt_tp.t_state, "tcp");
|
||||
else /* UDP */
|
||||
enter_sysctl(inpcb, &xip->xi_socket, 0, "udp");
|
||||
}
|
||||
free(inpg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
enter_kvm(inp, so, state, proto)
|
||||
register struct inpcb *inp;
|
||||
register struct socket *so;
|
||||
int state;
|
||||
@ -221,6 +308,36 @@ enter(inp, so, state, proto)
|
||||
{
|
||||
register struct netinfo *p;
|
||||
|
||||
if ((p = enter(inp, state, proto)) != NULL) {
|
||||
p->ni_rcvcc = so->so_rcv.sb_cc;
|
||||
p->ni_sndcc = so->so_snd.sb_cc;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
enter_sysctl(inp, so, state, proto)
|
||||
register struct inpcb *inp;
|
||||
register struct xsocket *so;
|
||||
int state;
|
||||
char *proto;
|
||||
{
|
||||
register struct netinfo *p;
|
||||
|
||||
if ((p = enter(inp, state, proto)) != NULL) {
|
||||
p->ni_rcvcc = so->so_rcv.sb_cc;
|
||||
p->ni_sndcc = so->so_snd.sb_cc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct netinfo *
|
||||
enter(inp, state, proto)
|
||||
register struct inpcb *inp;
|
||||
int state;
|
||||
char *proto;
|
||||
{
|
||||
register struct netinfo *p;
|
||||
|
||||
/*
|
||||
* Only take exact matches, any sockets with
|
||||
* previously unbound addresses will be deleted
|
||||
@ -241,7 +358,7 @@ enter(inp, so, state, proto)
|
||||
if (p == NULL) {
|
||||
if ((p = malloc(sizeof(*p))) == NULL) {
|
||||
error("Out of memory");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
TAILQ_INSERT_HEAD(&netcb, p, chain);
|
||||
p->ni_line = -1;
|
||||
@ -252,10 +369,9 @@ enter(inp, so, state, proto)
|
||||
p->ni_proto = proto;
|
||||
p->ni_flags = NIF_LACHG|NIF_FACHG;
|
||||
}
|
||||
p->ni_rcvcc = so->so_rcv.sb_cc;
|
||||
p->ni_sndcc = so->so_snd.sb_cc;
|
||||
p->ni_state = state;
|
||||
p->ni_seen = 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* column locations */
|
||||
@ -270,7 +386,7 @@ enter(inp, so, state, proto)
|
||||
void
|
||||
labelnetstat()
|
||||
{
|
||||
if (namelist[X_TCB].n_type == 0)
|
||||
if (use_kvm && namelist[X_TCB].n_type == 0)
|
||||
return;
|
||||
wmove(wnd, 0, 0); wclrtobot(wnd);
|
||||
mvwaddstr(wnd, 0, LADDR, "Local Address");
|
||||
@ -291,9 +407,12 @@ shownetstat()
|
||||
* away and adjust the position of connections
|
||||
* below to reflect the deleted line.
|
||||
*/
|
||||
TAILQ_FOREACH(p, &netcb, chain) {
|
||||
if (p->ni_line == -1 || p->ni_seen)
|
||||
p = TAILQ_FIRST(&netcb);
|
||||
while (p != NULL) {
|
||||
if (p->ni_line == -1 || p->ni_seen) {
|
||||
p = TAILQ_NEXT(p, chain);
|
||||
continue;
|
||||
}
|
||||
wmove(wnd, p->ni_line, 0); wdeleteln(wnd);
|
||||
TAILQ_FOREACH(q, &netcb, chain)
|
||||
if (q != p && q->ni_line > p->ni_line) {
|
||||
@ -302,7 +421,7 @@ shownetstat()
|
||||
q->ni_flags |= NIF_LACHG|NIF_FACHG;
|
||||
}
|
||||
lastrow--;
|
||||
q = TAILQ_PREV(p, netinfohead, chain);
|
||||
q = TAILQ_NEXT(p, chain);
|
||||
TAILQ_REMOVE(&netcb, p, chain);
|
||||
free(p);
|
||||
p = q;
|
||||
|
@ -92,11 +92,8 @@ closeswap(w)
|
||||
int
|
||||
initswap()
|
||||
{
|
||||
int i;
|
||||
char msgbuf[BUFSIZ];
|
||||
char *cp;
|
||||
static int once = 0;
|
||||
u_long ptr;
|
||||
struct kvm_swap dummy;
|
||||
|
||||
if (once)
|
||||
@ -124,7 +121,7 @@ fetchswap()
|
||||
void
|
||||
labelswap()
|
||||
{
|
||||
char *header, *p;
|
||||
char *header;
|
||||
int row, i;
|
||||
|
||||
fetchswap();
|
||||
|
@ -49,12 +49,20 @@ struct cmdtab {
|
||||
char c_flags; /* see below */
|
||||
};
|
||||
|
||||
/*
|
||||
* If we are started with privileges, use a kmem interface for netstat handling,
|
||||
* otherwise use sysctl.
|
||||
* In case of many open sockets, the sysctl handling might become slow.
|
||||
*/
|
||||
extern int use_kvm;
|
||||
|
||||
#define CF_INIT 0x1 /* been initialized */
|
||||
#define CF_LOADAV 0x2 /* display w/ load average */
|
||||
|
||||
#define TCP 0x1
|
||||
#define UDP 0x2
|
||||
|
||||
#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
|
||||
#define KREAD(addr, buf, len) kvm_ckread((addr), (buf), (len))
|
||||
#define NVAL(indx) namelist[(indx)].n_value
|
||||
#define NPTR(indx) (void *)NVAL((indx))
|
||||
|
@ -74,7 +74,43 @@ static const char rcsid[] =
|
||||
|
||||
static struct Info {
|
||||
long time[CPUSTATES];
|
||||
struct vmmeter Cnt;
|
||||
u_int v_swtch; /* context switches */
|
||||
u_int v_trap; /* calls to trap */
|
||||
u_int v_syscall; /* calls to syscall() */
|
||||
u_int v_intr; /* device interrupts */
|
||||
u_int v_soft; /* software interrupts */
|
||||
/*
|
||||
* Virtual memory activity.
|
||||
*/
|
||||
u_int v_vm_faults; /* number of address memory faults */
|
||||
u_int v_cow_faults; /* number of copy-on-writes */
|
||||
u_int v_zfod; /* pages zero filled on demand */
|
||||
u_int v_ozfod; /* optimized zero fill pages */
|
||||
u_int v_swapin; /* swap pager pageins */
|
||||
u_int v_swapout; /* swap pager pageouts */
|
||||
u_int v_swappgsin; /* swap pager pages paged in */
|
||||
u_int v_swappgsout; /* swap pager pages paged out */
|
||||
u_int v_vnodein; /* vnode pager pageins */
|
||||
u_int v_vnodeout; /* vnode pager pageouts */
|
||||
u_int v_vnodepgsin; /* vnode_pager pages paged in */
|
||||
u_int v_vnodepgsout; /* vnode pager pages paged out */
|
||||
u_int v_intrans; /* intransit blocking page faults */
|
||||
u_int v_reactivated; /* number of pages reactivated from free list */
|
||||
u_int v_pdwakeups; /* number of times daemon has awaken from sleep */
|
||||
u_int v_pdpages; /* number of pages analyzed by daemon */
|
||||
|
||||
u_int v_dfree; /* pages freed by daemon */
|
||||
u_int v_pfree; /* pages freed by exiting processes */
|
||||
u_int v_tfree; /* total pages freed */
|
||||
/*
|
||||
* Distribution of page usages.
|
||||
*/
|
||||
u_int v_page_size; /* page size in bytes */
|
||||
u_int v_free_count; /* number of pages free */
|
||||
u_int v_wire_count; /* number of pages wired down */
|
||||
u_int v_active_count; /* number of pages active */
|
||||
u_int v_inactive_count; /* number of pages inactive */
|
||||
u_int v_cache_count; /* number of pages on buffer cache queue */
|
||||
struct vmtotal Total;
|
||||
struct nchstats nchstats;
|
||||
long nchcount;
|
||||
@ -88,8 +124,6 @@ static struct Info {
|
||||
|
||||
struct statinfo cur, last, run;
|
||||
|
||||
#define cnt s.Cnt
|
||||
#define oldcnt s1.Cnt
|
||||
#define total s.Total
|
||||
#define nchtotal s.nchstats
|
||||
#define oldnchtotal s1.nchstats
|
||||
@ -142,21 +176,6 @@ closekre(w)
|
||||
wrefresh(w);
|
||||
}
|
||||
|
||||
|
||||
static struct nlist namelist[] = {
|
||||
#define X_CNT 0
|
||||
{ "_cnt" },
|
||||
#define X_INTRNAMES 1
|
||||
{ "_intrnames" },
|
||||
#define X_EINTRNAMES 2
|
||||
{ "_eintrnames" },
|
||||
#define X_INTRCNT 3
|
||||
{ "_intrcnt" },
|
||||
#define X_EINTRCNT 4
|
||||
{ "_eintrcnt" },
|
||||
{ "" },
|
||||
};
|
||||
|
||||
/*
|
||||
* These constants define where the major pieces are laid out
|
||||
*/
|
||||
@ -191,18 +210,7 @@ initkre()
|
||||
char *intrnamebuf, *cp;
|
||||
int i;
|
||||
|
||||
if (namelist[0].n_type == 0) {
|
||||
if (kvm_nlist(kd, namelist)) {
|
||||
nlisterr(namelist);
|
||||
return(0);
|
||||
}
|
||||
if (namelist[0].n_type == 0) {
|
||||
error("No namelist");
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (num_devices = getnumdevs() < 0) {
|
||||
if ((num_devices = getnumdevs()) < 0) {
|
||||
warnx("%s", devstat_errbuf);
|
||||
return(0);
|
||||
}
|
||||
@ -218,14 +226,13 @@ initkre()
|
||||
return(0);
|
||||
|
||||
if (nintr == 0) {
|
||||
nintr = (namelist[X_EINTRCNT].n_value -
|
||||
namelist[X_INTRCNT].n_value) / sizeof (long);
|
||||
GETSYSCTL("hw.nintr", nintr);
|
||||
intrloc = calloc(nintr, sizeof (long));
|
||||
intrname = calloc(nintr, sizeof (long));
|
||||
intrnamebuf = malloc(namelist[X_EINTRNAMES].n_value -
|
||||
namelist[X_INTRNAMES].n_value);
|
||||
if (intrnamebuf == 0 || intrname == 0 || intrloc == 0) {
|
||||
error("Out of memory\n");
|
||||
intrnamebuf = sysctl_dynread("hw.intrnames", NULL);
|
||||
if (intrnamebuf == NULL || intrname == NULL ||
|
||||
intrloc == NULL) {
|
||||
error("Out of memory");
|
||||
if (intrnamebuf)
|
||||
free(intrnamebuf);
|
||||
if (intrname)
|
||||
@ -235,8 +242,6 @@ initkre()
|
||||
nintr = 0;
|
||||
return(0);
|
||||
}
|
||||
NREAD(X_INTRNAMES, intrnamebuf, NVAL(X_EINTRNAMES) -
|
||||
NVAL(X_INTRNAMES));
|
||||
for (cp = intrnamebuf, i = 0; i < nintr; i++) {
|
||||
intrname[i] = cp;
|
||||
cp += strlen(cp) + 1;
|
||||
@ -453,7 +458,7 @@ showkre()
|
||||
putfloat(avenrun[1], STATROW, STATCOL + 23, 6, 2, 0);
|
||||
putfloat(avenrun[2], STATROW, STATCOL + 29, 6, 2, 0);
|
||||
mvaddstr(STATROW, STATCOL + 53, buf);
|
||||
#define pgtokb(pg) ((pg) * cnt.v_page_size / 1024)
|
||||
#define pgtokb(pg) ((pg) * s.v_page_size / 1024)
|
||||
putint(pgtokb(total.t_arm), MEMROW + 2, MEMCOL + 3, 8);
|
||||
putint(pgtokb(total.t_armshr), MEMROW + 2, MEMCOL + 11, 8);
|
||||
putint(pgtokb(total.t_avm), MEMROW + 2, MEMCOL + 19, 9);
|
||||
@ -469,34 +474,34 @@ showkre()
|
||||
putint(total.t_sl, PROCSROW + 1, PROCSCOL + 12, 3);
|
||||
putint(total.t_sw, PROCSROW + 1, PROCSCOL + 15, 3);
|
||||
if (extended_vm_stats == 0) {
|
||||
PUTRATE(Cnt.v_zfod, VMSTATROW + 0, VMSTATCOL + 4, 5);
|
||||
PUTRATE(v_zfod, VMSTATROW + 0, VMSTATCOL + 4, 5);
|
||||
}
|
||||
PUTRATE(Cnt.v_cow_faults, VMSTATROW + 1, VMSTATCOL + 3, 6);
|
||||
putint(pgtokb(cnt.v_wire_count), VMSTATROW + 2, VMSTATCOL, 9);
|
||||
putint(pgtokb(cnt.v_active_count), VMSTATROW + 3, VMSTATCOL, 9);
|
||||
putint(pgtokb(cnt.v_inactive_count), VMSTATROW + 4, VMSTATCOL, 9);
|
||||
putint(pgtokb(cnt.v_cache_count), VMSTATROW + 5, VMSTATCOL, 9);
|
||||
putint(pgtokb(cnt.v_free_count), VMSTATROW + 6, VMSTATCOL, 9);
|
||||
PUTRATE(Cnt.v_dfree, VMSTATROW + 7, VMSTATCOL, 9);
|
||||
PUTRATE(Cnt.v_pfree, VMSTATROW + 8, VMSTATCOL, 9);
|
||||
PUTRATE(Cnt.v_reactivated, VMSTATROW + 9, VMSTATCOL, 9);
|
||||
PUTRATE(Cnt.v_pdwakeups, VMSTATROW + 10, VMSTATCOL, 9);
|
||||
PUTRATE(Cnt.v_pdpages, VMSTATROW + 11, VMSTATCOL, 9);
|
||||
PUTRATE(Cnt.v_intrans, VMSTATROW + 12, VMSTATCOL, 9);
|
||||
PUTRATE(v_cow_faults, VMSTATROW + 1, VMSTATCOL + 3, 6);
|
||||
putint(pgtokb(s.v_wire_count), VMSTATROW + 2, VMSTATCOL, 9);
|
||||
putint(pgtokb(s.v_active_count), VMSTATROW + 3, VMSTATCOL, 9);
|
||||
putint(pgtokb(s.v_inactive_count), VMSTATROW + 4, VMSTATCOL, 9);
|
||||
putint(pgtokb(s.v_cache_count), VMSTATROW + 5, VMSTATCOL, 9);
|
||||
putint(pgtokb(s.v_free_count), VMSTATROW + 6, VMSTATCOL, 9);
|
||||
PUTRATE(v_dfree, VMSTATROW + 7, VMSTATCOL, 9);
|
||||
PUTRATE(v_pfree, VMSTATROW + 8, VMSTATCOL, 9);
|
||||
PUTRATE(v_reactivated, VMSTATROW + 9, VMSTATCOL, 9);
|
||||
PUTRATE(v_pdwakeups, VMSTATROW + 10, VMSTATCOL, 9);
|
||||
PUTRATE(v_pdpages, VMSTATROW + 11, VMSTATCOL, 9);
|
||||
PUTRATE(v_intrans, VMSTATROW + 12, VMSTATCOL, 9);
|
||||
|
||||
if (extended_vm_stats) {
|
||||
PUTRATE(Cnt.v_zfod, VMSTATROW + 11, VMSTATCOL - 16, 9);
|
||||
PUTRATE(Cnt.v_ozfod, VMSTATROW + 12, VMSTATCOL - 16, 9);
|
||||
PUTRATE(v_zfod, VMSTATROW + 11, VMSTATCOL - 16, 9);
|
||||
PUTRATE(v_ozfod, VMSTATROW + 12, VMSTATCOL - 16, 9);
|
||||
putint(
|
||||
((s.Cnt.v_ozfod < s.Cnt.v_zfod) ?
|
||||
s.Cnt.v_ozfod * 100 / s.Cnt.v_zfod :
|
||||
((s.v_ozfod < s.v_zfod) ?
|
||||
s.v_ozfod * 100 / s.v_zfod :
|
||||
0
|
||||
),
|
||||
VMSTATROW + 13,
|
||||
VMSTATCOL - 16,
|
||||
9
|
||||
);
|
||||
PUTRATE(Cnt.v_tfree, VMSTATROW + 14, VMSTATCOL - 16, 9);
|
||||
PUTRATE(v_tfree, VMSTATROW + 14, VMSTATCOL - 16, 9);
|
||||
}
|
||||
|
||||
putint(s.bufspace/1024, VMSTATROW + 13, VMSTATCOL, 9);
|
||||
@ -504,20 +509,20 @@ showkre()
|
||||
putint(s.desiredvnodes, VMSTATROW + 15, VMSTATCOL, 9);
|
||||
putint(s.numvnodes, VMSTATROW + 16, VMSTATCOL, 9);
|
||||
putint(s.freevnodes, VMSTATROW + 17, VMSTATCOL, 9);
|
||||
PUTRATE(Cnt.v_vnodein, PAGEROW + 2, PAGECOL + 5, 5);
|
||||
PUTRATE(Cnt.v_vnodeout, PAGEROW + 2, PAGECOL + 10, 5);
|
||||
PUTRATE(Cnt.v_swapin, PAGEROW + 2, PAGECOL + 17, 5);
|
||||
PUTRATE(Cnt.v_swapout, PAGEROW + 2, PAGECOL + 22, 5);
|
||||
PUTRATE(Cnt.v_vnodepgsin, PAGEROW + 3, PAGECOL + 5, 5);
|
||||
PUTRATE(Cnt.v_vnodepgsout, PAGEROW + 3, PAGECOL + 10, 5);
|
||||
PUTRATE(Cnt.v_swappgsin, PAGEROW + 3, PAGECOL + 17, 5);
|
||||
PUTRATE(Cnt.v_swappgsout, PAGEROW + 3, PAGECOL + 22, 5);
|
||||
PUTRATE(Cnt.v_swtch, GENSTATROW + 1, GENSTATCOL, 5);
|
||||
PUTRATE(Cnt.v_trap, GENSTATROW + 1, GENSTATCOL + 5, 5);
|
||||
PUTRATE(Cnt.v_syscall, GENSTATROW + 1, GENSTATCOL + 10, 5);
|
||||
PUTRATE(Cnt.v_intr, GENSTATROW + 1, GENSTATCOL + 15, 5);
|
||||
PUTRATE(Cnt.v_soft, GENSTATROW + 1, GENSTATCOL + 20, 5);
|
||||
PUTRATE(Cnt.v_vm_faults, GENSTATROW + 1, GENSTATCOL + 25, 5);
|
||||
PUTRATE(v_vnodein, PAGEROW + 2, PAGECOL + 5, 5);
|
||||
PUTRATE(v_vnodeout, PAGEROW + 2, PAGECOL + 10, 5);
|
||||
PUTRATE(v_swapin, PAGEROW + 2, PAGECOL + 17, 5);
|
||||
PUTRATE(v_swapout, PAGEROW + 2, PAGECOL + 22, 5);
|
||||
PUTRATE(v_vnodepgsin, PAGEROW + 3, PAGECOL + 5, 5);
|
||||
PUTRATE(v_vnodepgsout, PAGEROW + 3, PAGECOL + 10, 5);
|
||||
PUTRATE(v_swappgsin, PAGEROW + 3, PAGECOL + 17, 5);
|
||||
PUTRATE(v_swappgsout, PAGEROW + 3, PAGECOL + 22, 5);
|
||||
PUTRATE(v_swtch, GENSTATROW + 1, GENSTATCOL, 5);
|
||||
PUTRATE(v_trap, GENSTATROW + 1, GENSTATCOL + 5, 5);
|
||||
PUTRATE(v_syscall, GENSTATROW + 1, GENSTATCOL + 10, 5);
|
||||
PUTRATE(v_intr, GENSTATROW + 1, GENSTATCOL + 15, 5);
|
||||
PUTRATE(v_soft, GENSTATROW + 1, GENSTATCOL + 20, 5);
|
||||
PUTRATE(v_vm_faults, GENSTATROW + 1, GENSTATCOL + 25, 5);
|
||||
mvprintw(DISKROW, DISKCOL + 5, " ");
|
||||
for (i = 0, c = 0; i < num_devices && c < MAXDRIVES; i++)
|
||||
if (dev_select[i].selected) {
|
||||
@ -721,51 +726,48 @@ getinfo(s, st)
|
||||
enum state st;
|
||||
{
|
||||
struct devinfo *tmp_dinfo;
|
||||
size_t len, size;
|
||||
int mib[2], err;
|
||||
size_t size;
|
||||
int mib[2];
|
||||
|
||||
len = sizeof(s->time);
|
||||
err = sysctlbyname("kern.cp_time", &s->time, &len, NULL, 0);
|
||||
if (err || len != sizeof(s->time))
|
||||
perror("kern.cp_time");
|
||||
|
||||
len = sizeof(cur.cp_time);
|
||||
err = sysctlbyname("kern.cp_time", &cur.cp_time, &len, NULL, 0);
|
||||
if (err || len != sizeof(cur.cp_time))
|
||||
perror("kern.cp_time");
|
||||
|
||||
NREAD(X_CNT, &s->Cnt, sizeof s->Cnt);
|
||||
|
||||
len = sizeof(s->bufspace);
|
||||
err = sysctlbyname("vfs.bufspace", &s->bufspace, &len, NULL, 0);
|
||||
if (err || len != sizeof(s->bufspace))
|
||||
perror("vfs.bufspace");
|
||||
|
||||
len = sizeof(s->desiredvnodes);
|
||||
err = sysctlbyname("kern.maxvnodes", &s->desiredvnodes, &len, NULL, 0);
|
||||
if (err || len != sizeof(s->desiredvnodes))
|
||||
perror("kern.maxvnodes");
|
||||
|
||||
len = sizeof(s->numvnodes);
|
||||
err = sysctlbyname("debug.numvnodes", &s->numvnodes, &len, NULL, 0);
|
||||
if (err || len != sizeof(s->numvnodes))
|
||||
perror("debug.numvnodes");
|
||||
|
||||
len = sizeof(s->freevnodes);
|
||||
err = sysctlbyname("debug.freevnodes", &s->freevnodes, &len, NULL, 0);
|
||||
if (err || len != sizeof(s->freevnodes))
|
||||
perror("debug.freevnodes");
|
||||
|
||||
len = sizeof(s->nchstats);
|
||||
err = sysctlbyname("vfs.cache.nchstats", &s->nchstats, &len, NULL, 0);
|
||||
if (err || len != sizeof(s->nchstats))
|
||||
perror("vfs.cache.nchstats");
|
||||
|
||||
NREAD(X_INTRCNT, s->intrcnt, nintr * LONG);
|
||||
|
||||
len = sizeof(s->numdirtybuffers);
|
||||
err = sysctlbyname("vfs.numdirtybuffers", &s->numdirtybuffers, &len,
|
||||
NULL, 0);
|
||||
GETSYSCTL("kern.cp_time", s->time);
|
||||
GETSYSCTL("kern.cp_time", cur.cp_time);
|
||||
GETSYSCTL("vm.stats.sys.v_swtch", s->v_swtch);
|
||||
GETSYSCTL("vm.stats.sys.v_trap", s->v_trap);
|
||||
GETSYSCTL("vm.stats.sys.v_syscall", s->v_syscall);
|
||||
GETSYSCTL("vm.stats.sys.v_intr", s->v_intr);
|
||||
GETSYSCTL("vm.stats.sys.v_soft", s->v_soft);
|
||||
GETSYSCTL("vm.stats.vm.v_vm_faults", s->v_vm_faults);
|
||||
GETSYSCTL("vm.stats.vm.v_cow_faults", s->v_cow_faults);
|
||||
GETSYSCTL("vm.stats.vm.v_zfod", s->v_zfod);
|
||||
GETSYSCTL("vm.stats.vm.v_ozfod", s->v_ozfod);
|
||||
GETSYSCTL("vm.stats.vm.v_swapin", s->v_swapin);
|
||||
GETSYSCTL("vm.stats.vm.v_swapout", s->v_swapout);
|
||||
GETSYSCTL("vm.stats.vm.v_swappgsin", s->v_swappgsin);
|
||||
GETSYSCTL("vm.stats.vm.v_swappgsout", s->v_swappgsout);
|
||||
GETSYSCTL("vm.stats.vm.v_vnodein", s->v_vnodein);
|
||||
GETSYSCTL("vm.stats.vm.v_vnodeout", s->v_vnodeout);
|
||||
GETSYSCTL("vm.stats.vm.v_vnodepgsin", s->v_vnodepgsin);
|
||||
GETSYSCTL("vm.stats.vm.v_vnodepgsout", s->v_vnodepgsout);
|
||||
GETSYSCTL("vm.stats.vm.v_intrans", s->v_intrans);
|
||||
GETSYSCTL("vm.stats.vm.v_reactivated", s->v_reactivated);
|
||||
GETSYSCTL("vm.stats.vm.v_pdwakeups", s->v_pdwakeups);
|
||||
GETSYSCTL("vm.stats.vm.v_pdpages", s->v_pdpages);
|
||||
GETSYSCTL("vm.stats.vm.v_dfree", s->v_dfree);
|
||||
GETSYSCTL("vm.stats.vm.v_pfree", s->v_pfree);
|
||||
GETSYSCTL("vm.stats.vm.v_tfree", s->v_tfree);
|
||||
GETSYSCTL("vm.stats.vm.v_page_size", s->v_page_size);
|
||||
GETSYSCTL("vm.stats.vm.v_free_count", s->v_free_count);
|
||||
GETSYSCTL("vm.stats.vm.v_wire_count", s->v_wire_count);
|
||||
GETSYSCTL("vm.stats.vm.v_active_count", s->v_active_count);
|
||||
GETSYSCTL("vm.stats.vm.v_inactive_count", s->v_inactive_count);
|
||||
GETSYSCTL("vm.stats.vm.v_cache_count", s->v_cache_count);
|
||||
GETSYSCTL("vfs.bufspace", s->bufspace);
|
||||
GETSYSCTL("kern.maxvnodes", s->desiredvnodes);
|
||||
GETSYSCTL("debug.numvnodes", s->numvnodes);
|
||||
GETSYSCTL("debug.freevnodes", s->freevnodes);
|
||||
GETSYSCTL("vfs.cache.nchstats", s->nchstats);
|
||||
GETSYSCTL("vfs.numdirtybuffers", s->numdirtybuffers);
|
||||
getsysctl("hw.intrcnt", s->intrcnt, nintr * LONG);
|
||||
|
||||
size = sizeof(s->Total);
|
||||
mib[0] = CTL_VM;
|
||||
|
Loading…
Reference in New Issue
Block a user