New userland code to read the statistics kept by the NetBSD generic
disk framework, from John M. Vinopal <banshee@gabriella.resort.com>
This commit is contained in:
parent
e3937c848b
commit
1eaf5ee379
@ -1,16 +1,15 @@
|
||||
# $NetBSD: Makefile,v 1.4 1995/12/22 08:04:24 jonathan Exp $
|
||||
# $NetBSD: Makefile,v 1.5 1996/05/10 23:16:30 thorpej Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= systat
|
||||
.if (${MACHINE_ARCH} == "m68k")
|
||||
CFLAGS+=-D${MACHINE}
|
||||
.endif
|
||||
CFLAGS+=-I${.CURDIR}/../../sys/arch -I${.CURDIR}/../vmstat
|
||||
|
||||
SRCS= cmds.c cmdtab.c disks.c fetch.c iostat.c keyboard.c main.c mbufs.c \
|
||||
netcmds.c netstat.c pigs.c swap.c vmstat.c
|
||||
LDADD= -lcurses -ltermcap -lm -lkvm
|
||||
.PATH: ${.CURDIR}/../../usr.bin/vmstat
|
||||
|
||||
CFLAGS+=-I${.CURDIR}/../../usr.bin/vmstat
|
||||
SRCS= cmds.c cmdtab.c disks.c dkstats.c fetch.c iostat.c keyboard.c \
|
||||
main.c mbufs.c netcmds.c netstat.c pigs.c swap.c vmstat.c
|
||||
DPADD= ${LIBCURSES} ${LIBTERMCAP} ${LIBM} ${LIBKVM}
|
||||
LDADD= -lcurses -ltermcap -lm -lkvm
|
||||
BINGRP= kmem
|
||||
BINMODE=2555
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cmds.c,v 1.3 1995/08/31 22:20:18 jtc Exp $ */
|
||||
/* $NetBSD: cmds.c,v 1.4 1996/05/10 23:16:32 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1992, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/29/95";
|
||||
#endif
|
||||
static char rcsid[] = "$NetBSD: cmds.c,v 1.3 1995/08/31 22:20:18 jtc Exp $";
|
||||
static char rcsid[] = "$NetBSD: cmds.c,v 1.4 1996/05/10 23:16:32 thorpej Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -110,6 +110,8 @@ command(cmd)
|
||||
}
|
||||
p = lookup(cmd);
|
||||
if (p == (struct cmdtab *)-1) {
|
||||
/* if not a primary command, try a display specific one */
|
||||
if (curcmd->c_cmd == 0 || !(*curcmd->c_cmd)(cmd, cp))
|
||||
error("%s: Ambiguous command.", cmd);
|
||||
goto done;
|
||||
}
|
||||
@ -140,8 +142,6 @@ command(cmd)
|
||||
status();
|
||||
goto done;
|
||||
}
|
||||
if (curcmd->c_cmd == 0 || !(*curcmd->c_cmd)(cmd, cp))
|
||||
error("%s: Unknown command.", cmd);
|
||||
done:
|
||||
sigsetmask(omask);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: disks.c,v 1.3 1996/03/15 22:19:23 ragge Exp $ */
|
||||
/* $NetBSD: disks.c,v 1.4 1996/05/10 23:16:33 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1992, 1993
|
||||
@ -37,104 +37,13 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)disks.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
static char rcsid[] = "$NetBSD: disks.c,v 1.3 1996/03/15 22:19:23 ragge Exp $";
|
||||
static char rcsid[] = "$NetBSD: disks.c,v 1.4 1996/05/10 23:16:33 thorpej Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/buf.h>
|
||||
|
||||
#include <nlist.h>
|
||||
#include <ctype.h>
|
||||
#include <paths.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "systat.h"
|
||||
#include "extern.h"
|
||||
static void dkselect(char *args, int truefalse, int selections[]);
|
||||
|
||||
static void dkselect __P((char *, int, int []));
|
||||
static int read_names __P((void));
|
||||
|
||||
static struct nlist namelist[] = {
|
||||
#define X_DK_NDRIVE 0
|
||||
{ "_dk_ndrive" },
|
||||
#define X_DK_WPMS 1
|
||||
{ "_dk_wpms" },
|
||||
#ifdef sun
|
||||
#define X_MBDINIT (X_DK_WPMS+1)
|
||||
{ "_mbdinit" },
|
||||
#endif
|
||||
#ifdef tahoe
|
||||
#define X_VBDINIT (X_DK_WPMS+1)
|
||||
{ "_vbdinit" },
|
||||
#endif
|
||||
#if defined(hp300) || defined(luna68k)
|
||||
#define X_HPDINIT (X_DK_WPMS+1)
|
||||
{ "_hp_dinit" },
|
||||
#endif
|
||||
#ifdef mips
|
||||
#define X_SCSI_DINIT (X_DK_WPMS+1)
|
||||
{ "_scsi_dinit" },
|
||||
#endif
|
||||
{ "" },
|
||||
};
|
||||
|
||||
float *dk_mspw;
|
||||
int dk_ndrive, *dk_select;
|
||||
char **dr_name;
|
||||
|
||||
#include "names.c" /* XXX */
|
||||
|
||||
int
|
||||
dkinit()
|
||||
{
|
||||
register int i;
|
||||
register char *cp;
|
||||
static int once = 0;
|
||||
static char buf[1024];
|
||||
|
||||
if (once)
|
||||
return(1);
|
||||
|
||||
if (kvm_nlist(kd, namelist)) {
|
||||
nlisterr(namelist);
|
||||
return(0);
|
||||
}
|
||||
if (namelist[X_DK_NDRIVE].n_value == 0) {
|
||||
error("dk_ndrive undefined in kernel");
|
||||
return(0);
|
||||
}
|
||||
NREAD(X_DK_NDRIVE, &dk_ndrive, LONG);
|
||||
if (dk_ndrive <= 0) {
|
||||
error("dk_ndrive=%d according to %s", dk_ndrive, _PATH_UNIX);
|
||||
return(0);
|
||||
}
|
||||
dk_mspw = (float *)calloc(dk_ndrive, sizeof (float));
|
||||
{
|
||||
long *wpms = (long *)calloc(dk_ndrive, sizeof(long));
|
||||
KREAD(NPTR(X_DK_WPMS), wpms, dk_ndrive * sizeof (long));
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
*(dk_mspw + i) = (*(wpms + i) == 0)? 0.0:
|
||||
(float) 1.0 / *(wpms + i);
|
||||
free(wpms);
|
||||
}
|
||||
dr_name = (char **)calloc(dk_ndrive, sizeof (char *));
|
||||
dk_select = (int *)calloc(dk_ndrive, sizeof (int));
|
||||
for (cp = buf, i = 0; i < dk_ndrive; i++) {
|
||||
dr_name[i] = cp;
|
||||
sprintf(dr_name[i], "dk%d", i);
|
||||
cp += strlen(dr_name[i]) + 1;
|
||||
if (dk_mspw[i] != 0.0)
|
||||
dk_select[i] = 1;
|
||||
}
|
||||
if (!read_names()) {
|
||||
free(dr_name);
|
||||
free(dk_select);
|
||||
free(dk_mspw);
|
||||
return(0);
|
||||
}
|
||||
once = 1;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
dkcmd(cmd, args)
|
||||
@ -153,7 +62,6 @@ dkcmd(cmd, args)
|
||||
|
||||
move(CMDLINE, 0); clrtoeol();
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dk_mspw[i] != 0.0)
|
||||
printw("%s ", dr_name[i]);
|
||||
return (1);
|
||||
}
|
||||
@ -184,11 +92,7 @@ dkselect(args, truefalse, selections)
|
||||
break;
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (strcmp(args, dr_name[i]) == 0) {
|
||||
if (dk_mspw[i] != 0.0)
|
||||
selections[i] = truefalse;
|
||||
else
|
||||
error("%s: drive not configured",
|
||||
dr_name[i]);
|
||||
break;
|
||||
}
|
||||
if (i >= dk_ndrive)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: extern.h,v 1.2 1995/01/20 08:51:54 jtc Exp $ */
|
||||
/* $NetBSD: extern.h,v 1.3 1996/05/10 23:16:34 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
@ -76,7 +76,7 @@ struct cmdtab *lookup __P((char *));
|
||||
void command __P((char *));
|
||||
void die __P((int));
|
||||
void display __P((int));
|
||||
int dkinit __P((void));
|
||||
int dkinit __P((int));
|
||||
int dkcmd __P((char *, char *));
|
||||
void error __P((const char *fmt, ...));
|
||||
void fetchiostat __P((void));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: iostat.c,v 1.4 1996/03/15 22:19:25 ragge Exp $ */
|
||||
/* $NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1992, 1993
|
||||
@ -37,12 +37,13 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
static char rcsid[] = "$NetBSD: iostat.c,v 1.4 1996/03/15 22:19:25 ragge Exp $";
|
||||
static char rcsid[] = "$NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $";
|
||||
#endif not lint
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/dkstat.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -51,39 +52,13 @@ static char rcsid[] = "$NetBSD: iostat.c,v 1.4 1996/03/15 22:19:25 ragge Exp $";
|
||||
#include "systat.h"
|
||||
#include "extern.h"
|
||||
|
||||
static struct nlist namelist[] = {
|
||||
#define X_DK_BUSY 0
|
||||
{ "_dk_busy" },
|
||||
#define X_DK_TIME 1
|
||||
{ "_dk_time" },
|
||||
#define X_DK_XFER 2
|
||||
{ "_dk_xfer" },
|
||||
#define X_DK_WDS 3
|
||||
{ "_dk_wds" },
|
||||
#define X_DK_SEEK 4
|
||||
{ "_dk_seek" },
|
||||
#define X_CP_TIME 5
|
||||
{ "_cp_time" },
|
||||
#ifdef tahoe
|
||||
#define X_VBDINIT (X_CP_TIME+1)
|
||||
{ "_vbdinit" },
|
||||
#endif
|
||||
{ "" },
|
||||
};
|
||||
|
||||
static struct {
|
||||
int dk_busy;
|
||||
long cp_time[CPUSTATES];
|
||||
long *dk_time;
|
||||
long *dk_wds;
|
||||
long *dk_seek;
|
||||
long *dk_xfer;
|
||||
} s, s1;
|
||||
#include "dkstats.h"
|
||||
extern struct _disk cur;
|
||||
|
||||
static int linesperregion;
|
||||
static double etime;
|
||||
static int numbers = 0; /* default display bar graphs */
|
||||
static int msps = 0; /* default ms/seek shown */
|
||||
static int secs = 0; /* default seconds shown */
|
||||
|
||||
static int barlabels __P((int));
|
||||
static void histogram __P((double, int, double));
|
||||
@ -112,42 +87,16 @@ closeiostat(w)
|
||||
int
|
||||
initiostat()
|
||||
{
|
||||
if (namelist[X_DK_BUSY].n_type == 0) {
|
||||
if (kvm_nlist(kd, namelist)) {
|
||||
nlisterr(namelist);
|
||||
return(0);
|
||||
}
|
||||
if (namelist[X_DK_BUSY].n_type == 0) {
|
||||
error("Disk init information isn't in namelist");
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
if (! dkinit())
|
||||
return(0);
|
||||
if (dk_ndrive) {
|
||||
#define allocate(e, t) \
|
||||
s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
|
||||
s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
|
||||
allocate(dk_time, long);
|
||||
allocate(dk_wds, long);
|
||||
allocate(dk_seek, long);
|
||||
allocate(dk_xfer, long);
|
||||
#undef allocate
|
||||
}
|
||||
return(1);
|
||||
dkinit(1);
|
||||
dkreadstats();
|
||||
}
|
||||
|
||||
void
|
||||
fetchiostat()
|
||||
{
|
||||
if (namelist[X_DK_BUSY].n_type == 0)
|
||||
if (dk_ndrive == 0)
|
||||
return;
|
||||
NREAD(X_DK_BUSY, &s.dk_busy, LONG);
|
||||
NREAD(X_DK_TIME, s.dk_time, dk_ndrive * LONG);
|
||||
NREAD(X_DK_XFER, s.dk_xfer, dk_ndrive * LONG);
|
||||
NREAD(X_DK_WDS, s.dk_wds, dk_ndrive * LONG);
|
||||
NREAD(X_DK_SEEK, s.dk_seek, dk_ndrive * LONG);
|
||||
NREAD(X_CP_TIME, s.cp_time, sizeof s.cp_time);
|
||||
dkreadstats();
|
||||
}
|
||||
|
||||
#define INSET 10
|
||||
@ -157,8 +106,8 @@ labeliostat()
|
||||
{
|
||||
int row;
|
||||
|
||||
if (namelist[X_DK_BUSY].n_type == 0) {
|
||||
error("No dk_busy defined.");
|
||||
if (dk_ndrive == 0) {
|
||||
error("No drives defined.");
|
||||
return;
|
||||
}
|
||||
row = 0;
|
||||
@ -185,7 +134,7 @@ numlabels(row)
|
||||
#define COLWIDTH 14
|
||||
#define DRIVESPERLINE ((wnd->maxx - INSET) / COLWIDTH)
|
||||
for (ndrives = 0, i = 0; i < dk_ndrive; i++)
|
||||
if (dk_select[i])
|
||||
if (cur.dk_select[i])
|
||||
ndrives++;
|
||||
regions = howmany(ndrives, DRIVESPERLINE);
|
||||
/*
|
||||
@ -200,14 +149,14 @@ numlabels(row)
|
||||
linesperregion = 3;
|
||||
col = 0;
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dk_select[i] && dk_mspw[i] != 0.0) {
|
||||
if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
|
||||
if (col + COLWIDTH >= wnd->maxx - INSET) {
|
||||
col = 0, row += linesperregion + 1;
|
||||
if (row > wnd->maxy - (linesperregion + 1))
|
||||
break;
|
||||
}
|
||||
mvwaddstr(wnd, row, col + 4, dr_name[i]);
|
||||
mvwaddstr(wnd, row + 1, col, "bps tps msps");
|
||||
mvwaddstr(wnd, row, col + 4, cur.dk_name[i]);
|
||||
mvwaddstr(wnd, row + 1, col, "Kps tps sec");
|
||||
col += COLWIDTH;
|
||||
}
|
||||
if (col)
|
||||
@ -222,16 +171,16 @@ barlabels(row)
|
||||
int i;
|
||||
|
||||
mvwaddstr(wnd, row++, INSET,
|
||||
"/0 /5 /10 /15 /20 /25 /30 /35 /40 /45 /50");
|
||||
linesperregion = 2 + msps;
|
||||
"/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
|
||||
linesperregion = 2 + secs;
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dk_select[i] && dk_mspw[i] != 0.0) {
|
||||
if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
|
||||
if (row > wnd->maxy - linesperregion)
|
||||
break;
|
||||
mvwprintw(wnd, row++, 0, "%3.3s bps|", dr_name[i]);
|
||||
mvwprintw(wnd, row++, 0, "%3.3s Kps|", cur.dk_name[i]);
|
||||
mvwaddstr(wnd, row++, 0, " tps|");
|
||||
if (msps)
|
||||
mvwaddstr(wnd, row++, 0, " msps|");
|
||||
if (secs)
|
||||
mvwaddstr(wnd, row++, 0, " msec|");
|
||||
}
|
||||
return (row);
|
||||
}
|
||||
@ -240,19 +189,16 @@ barlabels(row)
|
||||
void
|
||||
showiostat()
|
||||
{
|
||||
register long t;
|
||||
register u_int64_t t;
|
||||
register int i, row, col;
|
||||
|
||||
if (namelist[X_DK_BUSY].n_type == 0)
|
||||
if (dk_ndrive == 0)
|
||||
return;
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
#define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t
|
||||
X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time);
|
||||
}
|
||||
dkswap();
|
||||
|
||||
etime = 0;
|
||||
for(i = 0; i < CPUSTATES; i++) {
|
||||
X(cp_time);
|
||||
etime += s.cp_time[i];
|
||||
etime += cur.cp_time[i];
|
||||
}
|
||||
if (etime == 0.0)
|
||||
etime = 1.0;
|
||||
@ -267,7 +213,7 @@ showiostat()
|
||||
if (!numbers) {
|
||||
row += 2;
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dk_select[i] && dk_mspw[i] != 0.0) {
|
||||
if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
|
||||
if (row > wnd->maxy - linesperregion)
|
||||
break;
|
||||
row = stats(row, INSET, i);
|
||||
@ -280,7 +226,7 @@ showiostat()
|
||||
wmove(wnd, row + 3, 0);
|
||||
winsertln(wnd);
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dk_select[i] && dk_mspw[i] != 0.0) {
|
||||
if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
|
||||
if (col + COLWIDTH >= wnd->maxx) {
|
||||
col = 0, row += linesperregion + 1;
|
||||
if (row > wnd->maxy - (linesperregion + 1))
|
||||
@ -299,31 +245,26 @@ static int
|
||||
stats(row, col, dn)
|
||||
int row, col, dn;
|
||||
{
|
||||
double atime, words, xtime, itime;
|
||||
double atime, words;
|
||||
|
||||
atime = s.dk_time[dn];
|
||||
atime /= (float) hz;
|
||||
words = s.dk_wds[dn]*32.0; /* number of words transferred */
|
||||
xtime = dk_mspw[dn]*words; /* transfer time */
|
||||
itime = atime - xtime; /* time not transferring */
|
||||
if (xtime < 0)
|
||||
itime += xtime, xtime = 0;
|
||||
if (itime < 0)
|
||||
xtime += itime, itime = 0;
|
||||
/* time busy in disk activity */
|
||||
atime = (double)cur.dk_time[dn].tv_sec +
|
||||
((double)cur.dk_time[dn].tv_usec / (double)1000000);
|
||||
|
||||
words = cur.dk_bytes[dn] / 1024.0; /* # of K transferred */
|
||||
if (numbers) {
|
||||
mvwprintw(wnd, row, col, "%3.0f%4.0f%5.1f",
|
||||
words / 512 / etime, s.dk_xfer[dn] / etime,
|
||||
s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0.0);
|
||||
words / etime, cur.dk_xfer[dn] / etime, atime / etime);
|
||||
return (row);
|
||||
}
|
||||
wmove(wnd, row++, col);
|
||||
histogram(words / 512 / etime, 50, 1.0);
|
||||
histogram(words / etime, 50, 0.5);
|
||||
wmove(wnd, row++, col);
|
||||
histogram(s.dk_xfer[dn] / etime, 50, 1.0);
|
||||
if (msps) {
|
||||
histogram(cur.dk_xfer[dn] / etime, 50, 0.5);
|
||||
if (secs) {
|
||||
wmove(wnd, row++, col);
|
||||
histogram(s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0,
|
||||
50, 1.0);
|
||||
atime *= 1000; /* In milliseconds */
|
||||
histogram(atime / etime, 50, 0.5);
|
||||
}
|
||||
return (row);
|
||||
}
|
||||
@ -337,12 +278,12 @@ stat1(row, o)
|
||||
|
||||
time = 0;
|
||||
for (i = 0; i < CPUSTATES; i++)
|
||||
time += s.cp_time[i];
|
||||
time += cur.cp_time[i];
|
||||
if (time == 0.0)
|
||||
time = 1.0;
|
||||
wmove(wnd, row, INSET);
|
||||
#define CPUSCALE 0.5
|
||||
histogram(100.0 * s.cp_time[o] / time, 50, CPUSCALE);
|
||||
histogram(100.0 * cur.cp_time[o] / time, 50, CPUSCALE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -362,6 +303,7 @@ histogram(val, colwidth, scale)
|
||||
while (k--)
|
||||
waddch(wnd, 'X');
|
||||
waddstr(wnd, buf);
|
||||
wclrtoeol(wnd);
|
||||
return;
|
||||
}
|
||||
while (k--)
|
||||
@ -374,8 +316,8 @@ cmdiostat(cmd, args)
|
||||
char *cmd, *args;
|
||||
{
|
||||
|
||||
if (prefix(cmd, "msps"))
|
||||
msps = !msps;
|
||||
if (prefix(cmd, "secs"))
|
||||
secs = !secs;
|
||||
else if (prefix(cmd, "numbers"))
|
||||
numbers = 1;
|
||||
else if (prefix(cmd, "bars"))
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: main.c,v 1.7 1996/03/21 18:04:25 jtc Exp $ */
|
||||
/* $NetBSD: main.c,v 1.8 1996/05/10 23:16:36 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1992, 1993
|
||||
@ -43,7 +43,7 @@ static char copyright[] =
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
static char rcsid[] = "$NetBSD: main.c,v 1.7 1996/03/21 18:04:25 jtc Exp $";
|
||||
static char rcsid[] = "$NetBSD: main.c,v 1.8 1996/05/10 23:16:36 thorpej Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -53,6 +53,7 @@ static char rcsid[] = "$NetBSD: main.c,v 1.7 1996/03/21 18:04:25 jtc Exp $";
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "systat.h"
|
||||
#include "extern.h"
|
||||
@ -68,6 +69,8 @@ static struct nlist namelist[] = {
|
||||
static int dellave;
|
||||
|
||||
kvm_t *kd;
|
||||
char *memf = NULL;
|
||||
char *nlistf = NULL;
|
||||
sig_t sigtstpdfl;
|
||||
double avenrun[3];
|
||||
int col;
|
||||
@ -82,32 +85,59 @@ int CMDLINE;
|
||||
|
||||
static WINDOW *wload; /* one line window for load average */
|
||||
|
||||
static void usage();
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int ch;
|
||||
char errbuf[80];
|
||||
|
||||
argc--, argv++;
|
||||
while (argc > 0) {
|
||||
if (argv[0][0] == '-') {
|
||||
struct cmdtab *p;
|
||||
while ((ch = getopt(argc, argv, "M:N:w:")) != EOF)
|
||||
switch(ch) {
|
||||
case 'M':
|
||||
memf = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
nlistf = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
if ((naptime = atoi(optarg)) <= 0)
|
||||
errx(1, "interval <= 0.");
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/*
|
||||
* Discard setgid privileges if not the running kernel so that bad
|
||||
* guys can't print interesting stuff from kernel memory.
|
||||
*/
|
||||
if (nlistf != NULL || memf != NULL)
|
||||
setgid(getgid());
|
||||
|
||||
p = lookup(&argv[0][1]);
|
||||
if (p == (struct cmdtab *)-1)
|
||||
errx(1, "ambiguous request: %s", &argv[0][1]);
|
||||
if (p == 0)
|
||||
errx(1, "unknown request: %s", &argv[0][1]);
|
||||
curcmd = p;
|
||||
} else {
|
||||
while (argc > 0) {
|
||||
if (isdigit(argv[0][0])) {
|
||||
naptime = atoi(argv[0]);
|
||||
if (naptime <= 0)
|
||||
naptime = 5;
|
||||
} else {
|
||||
struct cmdtab *p;
|
||||
|
||||
p = lookup(&argv[0][0]);
|
||||
if (p == (struct cmdtab *)-1)
|
||||
errx(1, "ambiguous request: %s", &argv[0][0]);
|
||||
if (p == 0)
|
||||
errx(1, "unknown request: %s", &argv[0][0]);
|
||||
curcmd = p;
|
||||
}
|
||||
argc--, argv++;
|
||||
}
|
||||
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
|
||||
kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
|
||||
if (kd == NULL) {
|
||||
error("%s", errbuf);
|
||||
exit(1);
|
||||
@ -162,6 +192,14 @@ main(argc, argv)
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "usage: systat [-M core] [-N system] [-w wait]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
labels()
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: swap.c,v 1.4 1995/08/31 22:20:19 jtc Exp $ */
|
||||
/* $NetBSD: swap.c,v 1.5 1996/05/10 23:16:38 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1992, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)swap.c 8.3 (Berkeley) 4/29/95";
|
||||
#endif
|
||||
static char rcsid[] = "$NetBSD: swap.c,v 1.4 1995/08/31 22:20:19 jtc Exp $";
|
||||
static char rcsid[] = "$NetBSD: swap.c,v 1.5 1996/05/10 23:16:38 thorpej Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
@ -64,8 +64,6 @@ static char rcsid[] = "$NetBSD: swap.c,v 1.4 1995/08/31 22:20:19 jtc Exp $";
|
||||
extern char *getbsize __P((int *headerlenp, long *blocksizep));
|
||||
void showspace __P((char *header, int hlen, long blocksize));
|
||||
|
||||
kvm_t *kd;
|
||||
|
||||
struct nlist syms[] = {
|
||||
{ "_swapmap" }, /* list of free swap areas */
|
||||
#define VM_SWAPMAP 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: systat.1,v 1.5 1995/09/27 19:46:12 jtc Exp $
|
||||
.\" $NetBSD: systat.1,v 1.6 1996/05/10 23:16:39 thorpej Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1985, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@ -41,7 +41,10 @@
|
||||
.Nd display system statistics on a crt
|
||||
.Sh SYNOPSIS
|
||||
.Nm systat
|
||||
.Op Fl display
|
||||
.Op Fl M Ar core
|
||||
.Op Fl N Ar system
|
||||
.Op Fl w Ar wait
|
||||
.Op Ar display
|
||||
.Op Ar refresh-interval
|
||||
.Sh DESCRIPTION
|
||||
.Nm Systat
|
||||
@ -78,12 +81,20 @@ allows each display to have certain display-specific commands.
|
||||
.Pp
|
||||
Command line options:
|
||||
.Bl -tag -width "refresh_interval"
|
||||
.It Fl Ns Ar display
|
||||
.It Fl M Ar core
|
||||
Extract values associated with the name list from
|
||||
.Ar core
|
||||
instead of the default
|
||||
.Pa /dev/mem .
|
||||
.It Fl N Ar system
|
||||
Extracr the name list from
|
||||
.Ar system
|
||||
instead of the default
|
||||
.Pa /netbsd .
|
||||
.It Ar display
|
||||
The
|
||||
.Fl
|
||||
flag expects
|
||||
.Ar display
|
||||
to be one of:
|
||||
argument expects to be one of:
|
||||
.Ic pigs ,
|
||||
.Ic iostat ,
|
||||
.Ic swap ,
|
||||
@ -91,14 +102,17 @@ to be one of:
|
||||
.Ic vmstat
|
||||
or
|
||||
.Ic netstat .
|
||||
These displays can also be requested interactively (without the
|
||||
.Dq Fl )
|
||||
and are described in
|
||||
These displays can also be requested interactively and are described in
|
||||
full detail below.
|
||||
.It Ar refresh-interval
|
||||
The
|
||||
.Ar refresh-value
|
||||
specifies the screen refresh time interval in seconds.
|
||||
.Ar refresh-interval
|
||||
specifies the screen refresh time interval in seconds. This is provided
|
||||
for backwards compatibility, and overrides the
|
||||
.Ar refresh-interval
|
||||
specified with the
|
||||
.Fl w
|
||||
flag.
|
||||
.El
|
||||
.Pp
|
||||
Certain characters cause immediate action by
|
||||
@ -162,7 +176,7 @@ bar graphs of the amount of time executing in user mode (``user''),
|
||||
in user mode running low priority processes (``nice''), in
|
||||
system mode (``system''), and idle (``idle''). Statistics
|
||||
on disk throughput show, for each drive, kilobytes of data transferred,
|
||||
number of disk transactions performed, and average seek time
|
||||
number of disk transactions performed, and time spent in disk accesses
|
||||
(in milliseconds). This information may be displayed as
|
||||
bar graphs or as rows of numbers which scroll downward. Bar
|
||||
graphs are shown by default;
|
||||
@ -181,9 +195,9 @@ displayed in numeric columns which scroll downward.
|
||||
Show the disk
|
||||
.Tn I/O
|
||||
statistics in bar graph form (default).
|
||||
.It Cm msps
|
||||
Toggle the display of average seek time (the default is to
|
||||
not display seek times).
|
||||
.It Cm secs
|
||||
Toggle the display of time in disk activity (the default is to
|
||||
not display time).
|
||||
.El
|
||||
.It Ic swap
|
||||
Show information about swap space usage on all the
|
||||
@ -226,10 +240,10 @@ Finally the last column shows the number of physical pages
|
||||
on the free list.
|
||||
.Pp
|
||||
Below the memory display is the disk usage display.
|
||||
It reports the number of seeks, transfers, and number
|
||||
It reports the number of seeks, transfers, number
|
||||
of kilobyte blocks transferred per second averaged over the
|
||||
refresh period of the display (by default, five seconds).
|
||||
For some disks it also reports the average milliseconds per seek.
|
||||
refresh period of the display (by default, five seconds), and
|
||||
the time spent in disk accesses.
|
||||
Note that the system only keeps statistics on at most four disks.
|
||||
.Pp
|
||||
Below the disk display is a list of the
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vmstat.c,v 1.4 1995/04/29 05:54:55 cgd Exp $ */
|
||||
/* $NetBSD: vmstat.c,v 1.5 1996/05/10 23:16:40 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1983, 1989, 1992, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 1/12/94";
|
||||
#endif
|
||||
static char rcsid[] = "$NetBSD: vmstat.c,v 1.4 1995/04/29 05:54:55 cgd Exp $";
|
||||
static char rcsid[] = "$NetBSD: vmstat.c,v 1.5 1996/05/10 23:16:40 thorpej Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
@ -72,16 +72,15 @@ static struct Info {
|
||||
long time[CPUSTATES];
|
||||
struct vmmeter Cnt;
|
||||
struct vmtotal Total;
|
||||
long *dk_time;
|
||||
long *dk_wds;
|
||||
long *dk_seek;
|
||||
long *dk_xfer;
|
||||
int dk_busy;
|
||||
struct nchstats nchstats;
|
||||
long nchcount;
|
||||
long *intrcnt;
|
||||
} s, s1, s2, z;
|
||||
|
||||
#include "dkstats.h"
|
||||
extern struct _disk cur;
|
||||
|
||||
|
||||
#define cnt s.Cnt
|
||||
#define oldcnt s1.Cnt
|
||||
#define total s.Total
|
||||
@ -215,7 +214,7 @@ initkre()
|
||||
}
|
||||
}
|
||||
hertz = stathz ? stathz : hz;
|
||||
if (! dkinit())
|
||||
if (! dkinit(1))
|
||||
return(0);
|
||||
if (dk_ndrive && !once) {
|
||||
#define allocate(e, t) \
|
||||
@ -223,10 +222,6 @@ initkre()
|
||||
s1./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
|
||||
s2./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
|
||||
z./**/e = (t *)calloc(dk_ndrive, sizeof (t));
|
||||
allocate(dk_time, long);
|
||||
allocate(dk_wds, long);
|
||||
allocate(dk_seek, long);
|
||||
allocate(dk_xfer, long);
|
||||
once = 1;
|
||||
#undef allocate
|
||||
}
|
||||
@ -331,8 +326,8 @@ labelkre()
|
||||
mvprintw(DISKROW, DISKCOL, "Discs");
|
||||
mvprintw(DISKROW + 1, DISKCOL, "seeks");
|
||||
mvprintw(DISKROW + 2, DISKCOL, "xfers");
|
||||
mvprintw(DISKROW + 3, DISKCOL, " blks");
|
||||
mvprintw(DISKROW + 4, DISKCOL, " msps");
|
||||
mvprintw(DISKROW + 3, DISKCOL, "Kbyte");
|
||||
mvprintw(DISKROW + 4, DISKCOL, " sec");
|
||||
j = 0;
|
||||
for (i = 0; i < dk_ndrive && j < MAXDRIVES; i++)
|
||||
if (dk_select[i]) {
|
||||
@ -367,9 +362,9 @@ showkre()
|
||||
int i, l, c;
|
||||
static int failcnt = 0;
|
||||
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time);
|
||||
}
|
||||
|
||||
if (state == TIME)
|
||||
dkswap();
|
||||
etime = 0;
|
||||
for(i = 0; i < CPUSTATES; i++) {
|
||||
X(time);
|
||||
@ -617,13 +612,9 @@ getinfo(s, st)
|
||||
size_t size;
|
||||
extern int errno;
|
||||
|
||||
dkreadstats();
|
||||
NREAD(X_CPTIME, s->time, sizeof s->time);
|
||||
NREAD(X_CNT, &s->Cnt, sizeof s->Cnt);
|
||||
NREAD(X_DK_BUSY, &s->dk_busy, LONG);
|
||||
NREAD(X_DK_TIME, s->dk_time, dk_ndrive * LONG);
|
||||
NREAD(X_DK_XFER, s->dk_xfer, dk_ndrive * LONG);
|
||||
NREAD(X_DK_WDS, s->dk_wds, dk_ndrive * LONG);
|
||||
NREAD(X_DK_SEEK, s->dk_seek, dk_ndrive * LONG);
|
||||
NREAD(X_NCHSTATS, &s->nchstats, sizeof s->nchstats);
|
||||
NREAD(X_INTRCNT, s->intrcnt, nintr * LONG);
|
||||
size = sizeof(s->Total);
|
||||
@ -649,21 +640,10 @@ static void
|
||||
copyinfo(from, to)
|
||||
register struct Info *from, *to;
|
||||
{
|
||||
long *time, *wds, *seek, *xfer;
|
||||
long *intrcnt;
|
||||
|
||||
/*
|
||||
* time, wds, seek, and xfer are malloc'd so we have to
|
||||
* save the pointers before the structure copy and then
|
||||
* copy by hand.
|
||||
*/
|
||||
time = to->dk_time; wds = to->dk_wds; seek = to->dk_seek;
|
||||
xfer = to->dk_xfer; intrcnt = to->intrcnt;
|
||||
intrcnt = to->intrcnt;
|
||||
*to = *from;
|
||||
bcopy(from->dk_time, to->dk_time = time, dk_ndrive * sizeof (long));
|
||||
bcopy(from->dk_wds, to->dk_wds = wds, dk_ndrive * sizeof (long));
|
||||
bcopy(from->dk_seek, to->dk_seek = seek, dk_ndrive * sizeof (long));
|
||||
bcopy(from->dk_xfer, to->dk_xfer = xfer, dk_ndrive * sizeof (long));
|
||||
bcopy(from->intrcnt, to->intrcnt = intrcnt, nintr * sizeof (int));
|
||||
}
|
||||
|
||||
@ -671,23 +651,18 @@ static void
|
||||
dinfo(dn, c)
|
||||
int dn, c;
|
||||
{
|
||||
double words, atime, itime, xtime;
|
||||
double words, atime;
|
||||
|
||||
c = DISKCOL + c * 5;
|
||||
atime = s.dk_time[dn];
|
||||
atime /= hertz;
|
||||
words = s.dk_wds[dn]*32.0; /* number of words transferred */
|
||||
xtime = dk_mspw[dn]*words; /* transfer time */
|
||||
itime = atime - xtime; /* time not transferring */
|
||||
if (xtime < 0)
|
||||
itime += xtime, xtime = 0;
|
||||
if (itime < 0)
|
||||
xtime += itime, itime = 0;
|
||||
putint((int)((float)s.dk_seek[dn]/etime+0.5), DISKROW + 1, c, 5);
|
||||
putint((int)((float)s.dk_xfer[dn]/etime+0.5), DISKROW + 2, c, 5);
|
||||
putint((int)(words/etime/512.0 + 0.5), DISKROW + 3, c, 5);
|
||||
if (s.dk_seek[dn])
|
||||
putfloat(itime*1000.0/s.dk_seek[dn], DISKROW + 4, c, 5, 1, 1);
|
||||
else
|
||||
putint(0, DISKROW + 4, c, 5);
|
||||
|
||||
/* time busy in disk activity */
|
||||
atime = (double)cur.dk_time[dn].tv_sec +
|
||||
((double)cur.dk_time[dn].tv_usec / (double)1000000);
|
||||
|
||||
words = cur.dk_bytes[dn] / 1024.0; /* # of K transferred */
|
||||
|
||||
putint((int)((float)cur.dk_seek[dn]/etime+0.5), DISKROW + 1, c, 5);
|
||||
putint((int)((float)cur.dk_xfer[dn]/etime+0.5), DISKROW + 2, c, 5);
|
||||
putint((int)(words/etime + 0.5), DISKROW + 3, c, 5);
|
||||
putfloat(atime/etime, DISKROW + 4, c, 5, 1, 1);
|
||||
}
|
||||
|
@ -1,15 +1,13 @@
|
||||
# $NetBSD: Makefile,v 1.14 1995/05/07 22:15:57 cgd Exp $
|
||||
# $NetBSD: Makefile,v 1.15 1996/05/10 23:19:25 thorpej Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= vmstat
|
||||
.if (${MACHINE_ARCH} == "m68k")
|
||||
CFLAGS+=-D${MACHINE}
|
||||
.endif
|
||||
CFLAGS+=-I${.CURDIR}/../../sys/arch
|
||||
|
||||
SRCS= dkstats.c vmstat.c
|
||||
MAN= vmstat.8
|
||||
DPADD= ${LIBKVM}
|
||||
LDADD= -lkvm
|
||||
BINGRP= kmem
|
||||
BINMODE=2555
|
||||
DPADD= names.c ${LIBKVM}
|
||||
LDADD= -lkvm
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
271
usr.bin/vmstat/dkstats.c
Normal file
271
usr.bin/vmstat/dkstats.c
Normal file
@ -0,0 +1,271 @@
|
||||
/* $NetBSD: dkstats.c,v 1.1 1996/05/10 23:19:27 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 John M. Vinopal
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project
|
||||
* by John M. Vinopal.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 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.
|
||||
*/
|
||||
|
||||
#include <sys/dkstat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/disk.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <kvm.h>
|
||||
#include <limits.h>
|
||||
#include <nlist.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "dkstats.h"
|
||||
|
||||
static struct nlist namelist[] = {
|
||||
#define X_TK_NIN 0
|
||||
{ "_tk_nin" }, /* tty characters in */
|
||||
#define X_TK_NOUT 1
|
||||
{ "_tk_nout" }, /* tty characters out */
|
||||
#define X_CP_TIME 2
|
||||
{ "_cp_time" }, /* system timer ticks */
|
||||
#define X_HZ 3
|
||||
{ "_hz" }, /* ticks per second */
|
||||
#define X_STATHZ 4
|
||||
{ "_stathz" },
|
||||
#define X_DISK_COUNT 5
|
||||
{ "_disk_count" }, /* number of disks */
|
||||
#define X_DISKLIST 6
|
||||
{ "_disklist" }, /* TAILQ of disks */
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
/* Structures to hold the statistics. */
|
||||
struct _disk cur, last;
|
||||
|
||||
/* Kernel pointers: nlistf and memf defined in calling program. */
|
||||
static kvm_t *kd = NULL;
|
||||
extern char *nlistf;
|
||||
extern char *memf;
|
||||
|
||||
/* Pointer to list of disks. */
|
||||
static struct disk *dk_drivehead = NULL;
|
||||
|
||||
/* Backward compatibility references. */
|
||||
int dk_ndrive = 0;
|
||||
int *dk_select;
|
||||
char **dr_name;
|
||||
|
||||
#define KVM_ERROR(_string) { \
|
||||
warnx((_string)); \
|
||||
errx(1, kvm_geterr(kd)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Dereference the namelist pointer `v' and fill in the local copy
|
||||
* 'p' which is of size 's'.
|
||||
*/
|
||||
#define deref_nl(v, p, s) deref_kptr((void *)namelist[(v)].n_value, (p), (s));
|
||||
|
||||
/* Missing from <sys/time.h> */
|
||||
#define timerset(tvp, uvp) ((uvp)->tv_sec = (tvp)->tv_sec); \
|
||||
((uvp)->tv_usec = (tvp)->tv_usec)
|
||||
|
||||
void dkswap __P((void));
|
||||
void dkreadstats __P((void));
|
||||
int dkinit __P((int));
|
||||
static void deref_kptr __P((void *, void *, size_t));
|
||||
|
||||
/*
|
||||
* Take the delta between the present values and the last recorded
|
||||
* values, storing the present values in the 'last' structure, and
|
||||
* the delta values in the 'cur' structure.
|
||||
*/
|
||||
void
|
||||
dkswap()
|
||||
{
|
||||
#define SWAP(fld) tmp = cur.fld; \
|
||||
cur.fld -= last.fld; \
|
||||
last.fld = tmp
|
||||
u_int64_t tmp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
struct timeval tmp_timer;
|
||||
|
||||
if (!cur.dk_select[i])
|
||||
continue;
|
||||
|
||||
/* Delta Values. */
|
||||
SWAP(dk_xfer[i]);
|
||||
SWAP(dk_seek[i]);
|
||||
SWAP(dk_bytes[i]);
|
||||
|
||||
/* Delta Time. */
|
||||
timerclear(&tmp_timer);
|
||||
timerset(&(cur.dk_time[i]), &tmp_timer);
|
||||
timersub(&tmp_timer, &(last.dk_time[i]), &(cur.dk_time[i]));
|
||||
timerclear(&(last.dk_time[i]));
|
||||
timerset(&tmp_timer, &(last.dk_time[i]));
|
||||
}
|
||||
for (i = 0; i < CPUSTATES; i++) {
|
||||
SWAP(cp_time[i]);
|
||||
}
|
||||
SWAP(tk_nin);
|
||||
SWAP(tk_nout);
|
||||
|
||||
#undef SWAP
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the disk statistics for each disk in the disk list.
|
||||
* Also collect statistics for tty i/o and cpu ticks.
|
||||
*/
|
||||
void
|
||||
dkreadstats()
|
||||
{
|
||||
struct disk cur_disk, *p;
|
||||
int i;
|
||||
|
||||
p = dk_drivehead;
|
||||
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
deref_kptr(p, &cur_disk, sizeof(cur_disk));
|
||||
cur.dk_xfer[i] = cur_disk.dk_xfer;
|
||||
cur.dk_seek[i] = cur_disk.dk_seek;
|
||||
cur.dk_bytes[i] = cur_disk.dk_bytes;
|
||||
timerset(&(cur_disk.dk_time), &(cur.dk_time[i]));
|
||||
p = cur_disk.dk_link.tqe_next;
|
||||
}
|
||||
deref_nl(X_CP_TIME, cur.cp_time, sizeof(cur.cp_time));
|
||||
deref_nl(X_TK_NIN, &cur.tk_nin, sizeof(cur.tk_nin));
|
||||
deref_nl(X_TK_NOUT, &cur.tk_nout, sizeof(cur.tk_nout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform all of the initialization and memory allocation needed to
|
||||
* track disk statistics.
|
||||
*/
|
||||
int
|
||||
dkinit(select)
|
||||
int select;
|
||||
{
|
||||
struct disklist_head disk_head;
|
||||
struct disk cur_disk, *p;
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
static int once = 0;
|
||||
extern int hz;
|
||||
int i;
|
||||
|
||||
if (once)
|
||||
return(1);
|
||||
|
||||
/* Open the kernel. */
|
||||
if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
|
||||
errx(1, "kvm_openfiles: %s", errbuf);
|
||||
|
||||
/* Obtain the namelist symbols from the kernel. */
|
||||
if (kvm_nlist(kd, namelist))
|
||||
KVM_ERROR("kvm_nlist failed to read symbols.");
|
||||
|
||||
/* Get the number of attached drives. */
|
||||
deref_nl(X_DISK_COUNT, &dk_ndrive, sizeof(dk_ndrive));
|
||||
|
||||
if (dk_ndrive < 0)
|
||||
errx(1, "invalid _disk_count %d.", dk_ndrive);
|
||||
else if (dk_ndrive == 0) {
|
||||
warnx("No drives attached.");
|
||||
}
|
||||
else {
|
||||
/* Get a pointer to the first disk. */
|
||||
deref_nl(X_DISKLIST, &disk_head, sizeof(disk_head));
|
||||
dk_drivehead = disk_head.tqh_first;
|
||||
}
|
||||
|
||||
/* Get ticks per second. */
|
||||
deref_nl(X_STATHZ, &hz, sizeof(hz));
|
||||
if (!hz)
|
||||
deref_nl(X_HZ, &hz, sizeof(hz));
|
||||
|
||||
/* allocate space for the statistics */
|
||||
cur.dk_time = calloc(dk_ndrive, sizeof(struct timeval));
|
||||
cur.dk_xfer = calloc(dk_ndrive, sizeof(u_int64_t));
|
||||
cur.dk_seek = calloc(dk_ndrive, sizeof(u_int64_t));
|
||||
cur.dk_bytes = calloc(dk_ndrive, sizeof(u_int64_t));
|
||||
last.dk_time = calloc(dk_ndrive, sizeof(struct timeval));
|
||||
last.dk_xfer = calloc(dk_ndrive, sizeof(u_int64_t));
|
||||
last.dk_seek = calloc(dk_ndrive, sizeof(u_int64_t));
|
||||
last.dk_bytes = calloc(dk_ndrive, sizeof(u_int64_t));
|
||||
cur.dk_select = calloc(dk_ndrive, sizeof(int));
|
||||
cur.dk_name = calloc(dk_ndrive, sizeof(char *));
|
||||
|
||||
if (!cur.dk_time || !cur.dk_xfer || !cur.dk_seek || !cur.dk_bytes
|
||||
|| !last.dk_time || !last.dk_xfer || !last.dk_seek || !last.dk_bytes
|
||||
|| !cur.dk_select || !cur.dk_name)
|
||||
errx(1, "Memory allocation failure.");
|
||||
|
||||
/* Set up the compatibility interfaces. */
|
||||
dk_select = cur.dk_select;
|
||||
dr_name = cur.dk_name;
|
||||
|
||||
/* Read the disk names and set intial selection. */
|
||||
p = dk_drivehead;
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
char buf[10];
|
||||
deref_kptr(p, &cur_disk, sizeof(cur_disk));
|
||||
deref_kptr(cur_disk.dk_name, buf, sizeof(buf));
|
||||
cur.dk_name[i] = strdup(buf);
|
||||
cur.dk_select[i] = select;
|
||||
|
||||
p = cur_disk.dk_link.tqe_next;
|
||||
}
|
||||
|
||||
/* Never do this initalization again. */
|
||||
once = 1;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dereference the kernel pointer `kptr' and fill in the local copy
|
||||
* pointed to by `ptr'. The storage space must be pre-allocated,
|
||||
* and the size of the copy passed in `len'.
|
||||
*/
|
||||
static void
|
||||
deref_kptr(kptr, ptr, len)
|
||||
void *kptr, *ptr;
|
||||
size_t len;
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
if (kvm_read(kd, (u_long)kptr, (char *)ptr, len) != len) {
|
||||
bzero(buf, sizeof(buf));
|
||||
snprintf(buf, (sizeof(buf) - 1),
|
||||
"can't dereference kptr 0x%lx", (u_long)kptr);
|
||||
KVM_ERROR(buf);
|
||||
}
|
||||
}
|
49
usr.bin/vmstat/dkstats.h
Normal file
49
usr.bin/vmstat/dkstats.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* $NetBSD: dkstats.h,v 1.1 1996/05/10 23:19:28 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 John M. Vinopal
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project
|
||||
* by John M. Vinopal.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 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.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* poseur disk entry to hold the information we're interested in. */
|
||||
struct _disk {
|
||||
int *dk_select; /* Display stats for selected disks. */
|
||||
char **dk_name; /* Disk names (sd0, wd1, etc). */
|
||||
u_int64_t *dk_xfer; /* # of transfers. */
|
||||
u_int64_t *dk_seek; /* # of seeks (currently unused). */
|
||||
u_int64_t *dk_bytes; /* # of bytes transfered. */
|
||||
struct timeval *dk_time; /* Time spent in disk i/o. */
|
||||
long tk_nin; /* TTY Chars in. */
|
||||
long tk_nout; /* TTY Chars out. */
|
||||
long cp_time[CPUSTATES]; /* System timer ticks. */
|
||||
};
|
@ -1,245 +0,0 @@
|
||||
/* $NetBSD: names.c,v 1.19 1996/04/01 21:45:25 mark Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* 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.
|
||||
*
|
||||
* @(#)names.c 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#if !defined(hp300) && !defined(tahoe) && !defined(luna68k) && !defined(mips)
|
||||
char *defdrives[] = { 0 };
|
||||
#endif
|
||||
|
||||
#if defined(i386)
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(arm32)
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(pc532)
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(sparc)
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(m68k) && !defined(hp300)
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__alpha__)
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(vax)
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(hp300) || defined(luna68k)
|
||||
#if defined(hp300)
|
||||
#include <hp300/dev/device.h>
|
||||
#else
|
||||
#include <luna68k/dev/device.h>
|
||||
#endif
|
||||
|
||||
char *defdrives[] = { "sd0", "sd1", "sd2", "rd0", "rd1", "rd2", 0 };
|
||||
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
register char *p;
|
||||
register u_long hp;
|
||||
static char buf[BUFSIZ];
|
||||
struct hp_device hdev;
|
||||
struct driver hdrv;
|
||||
char name[10];
|
||||
|
||||
hp = namelist[X_HPDINIT].n_value;
|
||||
if (hp == 0) {
|
||||
(void)fprintf(stderr,
|
||||
"disk init info not in namelist\n");
|
||||
return (0);
|
||||
}
|
||||
p = buf;
|
||||
for (;; hp += sizeof hdev) {
|
||||
(void)kvm_read(kd, hp, &hdev, sizeof hdev);
|
||||
if (hdev.hp_driver == 0)
|
||||
break;
|
||||
if (hdev.hp_dk < 0 || hdev.hp_alive == 0 ||
|
||||
hdev.hp_cdriver == 0)
|
||||
continue;
|
||||
(void)kvm_read(kd, (u_long)hdev.hp_driver, &hdrv, sizeof hdrv);
|
||||
(void)kvm_read(kd, (u_long)hdrv.d_name, name, sizeof name);
|
||||
dr_name[hdev.hp_dk] = p;
|
||||
p += sprintf(p, "%s%d", name, hdev.hp_unit) + 1;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
#endif /* hp300 || luna68k */
|
||||
|
||||
#ifdef tahoe
|
||||
#include <tahoe/vba/vbavar.h>
|
||||
|
||||
char *defdrives[] = { "dk0", "dk1", "dk2", 0 };
|
||||
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
register char *p;
|
||||
struct vba_device udev, *up;
|
||||
struct vba_driver udrv;
|
||||
char name[10];
|
||||
static char buf[BUFSIZ];
|
||||
|
||||
up = (struct vba_device *)namelist[X_VBDINIT].n_value;
|
||||
if (up == 0) {
|
||||
(void) fprintf(stderr,
|
||||
"disk init info not in namelist\n");
|
||||
return (0);
|
||||
}
|
||||
p = buf;
|
||||
for (;; up += sizeof udev) {
|
||||
(void)kvm_read(kd, up, &udev, sizeof udev);
|
||||
if (udev.ui_driver == 0)
|
||||
break;
|
||||
if (udev.ui_dk < 0 || udev.ui_alive == 0)
|
||||
continue;
|
||||
(void)kvm_read(kd, udev.ui_driver, &udrv, sizeof udrv);
|
||||
(void)kvm_read(kd, udrv.ud_dname, name, sizeof name);
|
||||
dr_name[udev.ui_dk] = p;
|
||||
p += sprintf(p, "%s%d", name, udev.ui_unit);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
#endif /* tahoe */
|
||||
|
||||
#ifdef sun
|
||||
#include <sundev/mbvar.h>
|
||||
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
static int once = 0;
|
||||
struct mb_device mdev;
|
||||
struct mb_driver mdrv;
|
||||
short two_char;
|
||||
char *cp = (char *) &two_char;
|
||||
register struct mb_device *mp;
|
||||
|
||||
mp = (struct mb_device *)namelist[X_MBDINIT].n_value;
|
||||
if (mp == 0) {
|
||||
(void)fprintf(stderr,
|
||||
"disk init info not in namelist\n");
|
||||
return (0);
|
||||
}
|
||||
for (;; ++mp) {
|
||||
(void)kvm_read(kd, mp++, &mdev, sizeof(mdev));
|
||||
if (mdev.md_driver == 0)
|
||||
break;
|
||||
if (mdev.md_dk < 0 || mdev.md_alive == 0)
|
||||
continue;
|
||||
(void)kvm_read(kd, mdev.md_driver, &mdrv, sizeof(mdrv));
|
||||
(void)kvm_read(kd, mdrv.mdr_dname, &two_char, sizeof(two_char));
|
||||
(void)sprintf(dr_name[mdev.md_dk],
|
||||
"%c%c%d", cp[0], cp[1], mdev.md_unit);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
#endif /* sun */
|
||||
|
||||
#if defined(mips)
|
||||
#include <pmax/dev/device.h>
|
||||
|
||||
char *defdrives[] = { "rz0", "rz1", "rz2", "rz3", "rz4", "rz5", "rz6", 0 };
|
||||
|
||||
int
|
||||
read_names()
|
||||
{
|
||||
register char *p;
|
||||
register u_long sp;
|
||||
static char buf[BUFSIZ];
|
||||
struct pmax_scsi_device sdev;
|
||||
struct pmax_driver hdrv;
|
||||
char name[10];
|
||||
|
||||
sp = namelist[X_SCSI_DINIT].n_value;
|
||||
if (sp == 0) {
|
||||
(void)fprintf(stderr, "disk init info not in namelist\n");
|
||||
return (0);
|
||||
}
|
||||
p = buf;
|
||||
for (;; sp += sizeof sdev) {
|
||||
(void)kvm_read(kd, sp, &sdev, sizeof sdev);
|
||||
if (sdev.sd_driver == 0)
|
||||
break;
|
||||
if (sdev.sd_dk < 0 || sdev.sd_alive == 0 ||
|
||||
sdev.sd_cdriver == 0)
|
||||
continue;
|
||||
(void)kvm_read(kd, (u_long)sdev.sd_driver, &hdrv, sizeof hdrv);
|
||||
(void)kvm_read(kd, (u_long)hdrv.d_name, name, sizeof name);
|
||||
dr_name[sdev.sd_dk] = p;
|
||||
p += sprintf(p, "%s%d", name, sdev.sd_unit) + 1;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
#endif /* mips */
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: vmstat.8,v 1.11 1995/08/10 23:29:47 jtc Exp $
|
||||
.\" $NetBSD: vmstat.8,v 1.12 1996/05/10 23:19:30 thorpej Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1986, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@ -76,7 +76,7 @@ startup.
|
||||
.TP
|
||||
\-M
|
||||
Extract values associated with the name list from the specified core
|
||||
instead of the default ``/dev/kmem''.
|
||||
instead of the default ``/dev/mem''.
|
||||
.TP
|
||||
\-N
|
||||
Extract the name list from the specified system instead of the default
|
||||
@ -150,7 +150,7 @@ sr pages scanned by clock algorithm, per-second
|
||||
.RE
|
||||
.TP
|
||||
disks
|
||||
Disk operations per second (this field is system dependent).
|
||||
Disk transfers per second.
|
||||
Typically paging will be split across the available drives.
|
||||
The header of the field is the first character of the disk name and
|
||||
the unit number.
|
||||
@ -189,10 +189,10 @@ some of the statistics are sampled in the system.
|
||||
Others vary every second and running the output for a while will make it
|
||||
apparent which are recomputed every second.
|
||||
.SH FILES
|
||||
.ta \w'/dev/kmem 'u
|
||||
.ta \w'/dev/mem 'u
|
||||
/netbsd default kernel namelist
|
||||
.br
|
||||
/dev/kmem default memory file
|
||||
/dev/mem default memory file
|
||||
.SH SEE ALSO
|
||||
.IR fstat (1),
|
||||
.IR netstat (1),
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vmstat.c,v 1.28 1996/04/04 00:27:50 cgd Exp $ */
|
||||
/* $NetBSD: vmstat.c,v 1.29 1996/05/10 23:19:32 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1991, 1993
|
||||
@ -43,7 +43,7 @@ static char copyright[] =
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: vmstat.c,v 1.28 1996/04/04 00:27:50 cgd Exp $";
|
||||
static char rcsid[] = "$NetBSD: vmstat.c,v 1.29 1996/05/10 23:19:32 thorpej Exp $";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -72,6 +72,7 @@ static char rcsid[] = "$NetBSD: vmstat.c,v 1.28 1996/04/04 00:27:50 cgd Exp $";
|
||||
#include <string.h>
|
||||
#include <paths.h>
|
||||
#include <limits.h>
|
||||
#include "dkstats.h"
|
||||
|
||||
#define NEWVM /* XXX till old has been updated or purged */
|
||||
struct nlist namelist[] = {
|
||||
@ -120,14 +121,6 @@ struct nlist namelist[] = {
|
||||
#else
|
||||
#define X_END 15
|
||||
#endif
|
||||
#if defined(hp300) || defined(luna68k)
|
||||
#define X_HPDINIT (X_END)
|
||||
{ "_hp_dinit" },
|
||||
#endif
|
||||
#ifdef mips
|
||||
#define X_SCSI_DINIT (X_END)
|
||||
{ "_scsi_dinit" },
|
||||
#endif
|
||||
#ifdef tahoe
|
||||
#define X_VBDINIT (X_END)
|
||||
{ "_vbdinit" },
|
||||
@ -143,14 +136,13 @@ struct nlist namelist[] = {
|
||||
{ "" },
|
||||
};
|
||||
|
||||
struct _disk {
|
||||
long time[CPUSTATES];
|
||||
long *xfer;
|
||||
} cur, last;
|
||||
/* Objects defined in dkstats.c */
|
||||
extern struct _disk cur;
|
||||
extern char **dr_name;
|
||||
extern int *dk_select, dk_ndrive;
|
||||
|
||||
struct vmmeter sum, osum;
|
||||
char **dr_name;
|
||||
int *dr_select, dk_ndrive, ndrives;
|
||||
int ndrives;
|
||||
|
||||
int winlines = 20;
|
||||
|
||||
@ -163,14 +155,24 @@ kvm_t *kd;
|
||||
#define TIMESTAT 0x10
|
||||
#define VMSTAT 0x20
|
||||
|
||||
#include "names.c" /* disk names -- machine dependent */
|
||||
|
||||
void cpustats(), dkstats(), dointr(), domem(), dosum();
|
||||
void dovmstat(), kread(), usage();
|
||||
void cpustats __P((void));
|
||||
void dkstats __P((void));
|
||||
void dointr __P((void));
|
||||
void domem __P((void));
|
||||
void dosum __P((void));
|
||||
void dovmstat __P((u_int, int));
|
||||
void kread __P((int, void *, size_t));
|
||||
void usage __P((void));
|
||||
#ifdef notdef
|
||||
void dotimes(), doforkst();
|
||||
void dotimes __P((void));
|
||||
void doforkst __P((void));
|
||||
#endif
|
||||
|
||||
char **choosedrives __P((char **));
|
||||
|
||||
/* Namelist and memory file names. */
|
||||
char *nlistf, *memf;
|
||||
|
||||
main(argc, argv)
|
||||
register int argc;
|
||||
register char **argv;
|
||||
@ -180,7 +182,6 @@ main(argc, argv)
|
||||
register int c, todo;
|
||||
u_int interval;
|
||||
int reps;
|
||||
char *memf, *nlistf;
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
|
||||
memf = nlistf = NULL;
|
||||
@ -260,10 +261,10 @@ main(argc, argv)
|
||||
}
|
||||
|
||||
if (todo & VMSTAT) {
|
||||
char **getdrivedata();
|
||||
struct winsize winsize;
|
||||
|
||||
argv = getdrivedata(argv);
|
||||
dkinit(0); /* Initialize disk stats, no disks selected. */
|
||||
argv = choosedrives(argv); /* Select disks. */
|
||||
winsize.ws_row = 0;
|
||||
(void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
|
||||
if (winsize.ws_row > 0)
|
||||
@ -306,32 +307,13 @@ main(argc, argv)
|
||||
}
|
||||
|
||||
char **
|
||||
getdrivedata(argv)
|
||||
choosedrives(argv)
|
||||
char **argv;
|
||||
{
|
||||
register int i;
|
||||
register char **cp;
|
||||
char buf[30];
|
||||
|
||||
kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive));
|
||||
if (dk_ndrive <= 0) {
|
||||
(void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive);
|
||||
exit(1);
|
||||
}
|
||||
dr_select = calloc((size_t)dk_ndrive, sizeof(int));
|
||||
dr_name = calloc((size_t)dk_ndrive, sizeof(char *));
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
dr_name[i] = NULL;
|
||||
cur.xfer = calloc((size_t)dk_ndrive, sizeof(long));
|
||||
last.xfer = calloc((size_t)dk_ndrive, sizeof(long));
|
||||
if (!read_names())
|
||||
exit (1);
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dr_name[i] == NULL) {
|
||||
(void)sprintf(buf, "??%d", i);
|
||||
dr_name[i] = strdup(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose drives to be displayed. Priority goes to (in order) drives
|
||||
* supplied as arguments, default drives. If everything isn't filled
|
||||
@ -347,25 +329,15 @@ getdrivedata(argv)
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
if (strcmp(dr_name[i], *argv))
|
||||
continue;
|
||||
dr_select[i] = 1;
|
||||
dk_select[i] = 1;
|
||||
++ndrives;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
|
||||
if (dr_select[i])
|
||||
if (dk_select[i])
|
||||
continue;
|
||||
for (cp = defdrives; *cp; cp++)
|
||||
if (strcmp(dr_name[i], *cp) == 0) {
|
||||
dr_select[i] = 1;
|
||||
++ndrives;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
|
||||
if (dr_select[i])
|
||||
continue;
|
||||
dr_select[i] = 1;
|
||||
dk_select[i] = 1;
|
||||
++ndrives;
|
||||
}
|
||||
return(argv);
|
||||
@ -414,8 +386,8 @@ dovmstat(interval, reps)
|
||||
for (hdrcnt = 1;;) {
|
||||
if (!--hdrcnt)
|
||||
printhdr();
|
||||
kread(X_CPTIME, cur.time, sizeof(cur.time));
|
||||
kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer) * dk_ndrive);
|
||||
/* Read new disk statistics */
|
||||
dkreadstats();
|
||||
kread(X_SUM, &sum, sizeof(sum));
|
||||
size = sizeof(total);
|
||||
mib[0] = CTL_VM;
|
||||
@ -426,7 +398,7 @@ dovmstat(interval, reps)
|
||||
}
|
||||
(void)printf("%2d%2d%2d",
|
||||
total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
|
||||
#define pgtok(a) ((a) * sum.v_page_size >> 10)
|
||||
#define pgtok(a) ((a) * (sum.v_page_size >> 10))
|
||||
#define rate(x) (((x) + halfuptime) / uptime) /* round */
|
||||
(void)printf("%6ld%6ld ",
|
||||
pgtok(total.t_avm), pgtok(total.t_free));
|
||||
@ -477,18 +449,29 @@ printhdr()
|
||||
register int i;
|
||||
|
||||
(void)printf(" procs memory page%*s", 20, "");
|
||||
if (ndrives > 1)
|
||||
(void)printf("disks %*s faults cpu\n",
|
||||
ndrives * 3 - 6, "");
|
||||
else
|
||||
(void)printf("%*s faults cpu\n", ndrives * 3, "");
|
||||
#ifndef NEWVM
|
||||
(void)printf(" r b w avm fre re at pi po fr de sr ");
|
||||
if (ndrives > 0)
|
||||
#ifdef NEWVM
|
||||
(void)printf("%s %*sfaults cpu\n",
|
||||
((ndrives > 1) ? "disks" : "disk"),
|
||||
#else
|
||||
(void)printf("disks %*sfaults cpu\n",
|
||||
#endif
|
||||
((ndrives > 1) ? ndrives * 3 - 4 : 0), "");
|
||||
else
|
||||
#ifdef NEWVM
|
||||
(void)printf("%*s faults cpu\n",
|
||||
#else
|
||||
(void)printf("%*s faults cpu\n",
|
||||
#endif
|
||||
ndrives * 3, "");
|
||||
|
||||
#ifdef NEWVM
|
||||
(void)printf(" r b w avm fre flt re pi po fr sr ");
|
||||
#else
|
||||
(void)printf(" r b w avm fre re at pi po fr de sr ");
|
||||
#endif
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dr_select[i])
|
||||
if (dk_select[i])
|
||||
(void)printf("%c%c ", dr_name[i][0],
|
||||
dr_name[i][strlen(dr_name[i]) - 1]);
|
||||
(void)printf(" in sy cs us sy id\n");
|
||||
@ -668,25 +651,19 @@ dkstats()
|
||||
double etime;
|
||||
long tmp;
|
||||
|
||||
for (dn = 0; dn < dk_ndrive; ++dn) {
|
||||
tmp = cur.xfer[dn];
|
||||
cur.xfer[dn] -= last.xfer[dn];
|
||||
last.xfer[dn] = tmp;
|
||||
}
|
||||
/* Calculate disk stat deltas. */
|
||||
dkswap();
|
||||
etime = 0;
|
||||
for (state = 0; state < CPUSTATES; ++state) {
|
||||
tmp = cur.time[state];
|
||||
cur.time[state] -= last.time[state];
|
||||
last.time[state] = tmp;
|
||||
etime += cur.time[state];
|
||||
etime += cur.cp_time[state];
|
||||
}
|
||||
if (etime == 0)
|
||||
etime = 1;
|
||||
etime /= hz;
|
||||
for (dn = 0; dn < dk_ndrive; ++dn) {
|
||||
if (!dr_select[dn])
|
||||
if (!dk_select[dn])
|
||||
continue;
|
||||
(void)printf("%2.0f ", cur.xfer[dn] / etime);
|
||||
(void)printf("%2.0f ", cur.dk_xfer[dn] / etime);
|
||||
}
|
||||
}
|
||||
|
||||
@ -698,14 +675,14 @@ cpustats()
|
||||
|
||||
total = 0;
|
||||
for (state = 0; state < CPUSTATES; ++state)
|
||||
total += cur.time[state];
|
||||
total += cur.cp_time[state];
|
||||
if (total)
|
||||
pct = 100 / total;
|
||||
else
|
||||
pct = 0;
|
||||
(void)printf("%2.0f ", (cur.time[CP_USER] + cur.time[CP_NICE]) * pct);
|
||||
(void)printf("%2.0f ", (cur.time[CP_SYS] + cur.time[CP_INTR]) * pct);
|
||||
(void)printf("%2.0f", cur.time[CP_IDLE] * pct);
|
||||
(void)printf("%2.0f ", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pct);
|
||||
(void)printf("%2.0f ", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pct);
|
||||
(void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct);
|
||||
}
|
||||
|
||||
#if defined(pc532)
|
||||
|
@ -1,13 +1,16 @@
|
||||
# $NetBSD: Makefile,v 1.12 1995/12/22 08:04:27 jonathan Exp $
|
||||
# $NetBSD: Makefile,v 1.13 1996/05/10 23:20:26 thorpej Exp $
|
||||
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= iostat
|
||||
.if (${MACHINE_ARCH} == "m68k")
|
||||
CFLAGS+=-D${MACHINE}
|
||||
.endif
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../sys/arch -I${.CURDIR}/../../usr.bin/vmstat
|
||||
MAN= iostat.8
|
||||
|
||||
.PATH: ${.CURDIR}/../../usr.bin/vmstat
|
||||
|
||||
CFLAGS+=-I${.CURDIR}/../../usr.bin/vmstat
|
||||
|
||||
# dkstats.c pulled in from ../../usr.bin/vmstat
|
||||
SRCS= dkstats.c iostat.c
|
||||
|
||||
DPADD= ${LIBKVM}
|
||||
LDADD= -lkvm
|
||||
BINGRP= kmem
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: iostat.8,v 1.8 1995/11/28 20:16:30 thorpej Exp $
|
||||
.\" $NetBSD: iostat.8,v 1.9 1996/05/10 23:20:28 thorpej Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1985, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@ -33,9 +33,9 @@
|
||||
.\"
|
||||
.\" from: @(#)iostat.8 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dd Jan 18, 1996
|
||||
.Dt IOSTAT 8
|
||||
.Os BSD 4
|
||||
.Os NetBSD 1.1
|
||||
.Sh NAME
|
||||
.Nm iostat
|
||||
.Nd report
|
||||
@ -43,6 +43,7 @@
|
||||
statistics
|
||||
.Sh SYNOPSIS
|
||||
.Nm iostat
|
||||
.Op Fl CdDIT
|
||||
.Op Fl c Ar count
|
||||
.Op Fl M Ar core
|
||||
.Op Fl N Ar system
|
||||
@ -52,8 +53,19 @@ statistics
|
||||
.Nm Iostat
|
||||
displays kernel
|
||||
.Tn I/O
|
||||
statistics on terminal, disk and cpu
|
||||
operations.
|
||||
statistics on terminal, disk and cpu operations. By default,
|
||||
.Nm iostat
|
||||
displays one line of statistics averaged over the machine's run time.
|
||||
The use of
|
||||
.Fl c
|
||||
presents successive lines averaged over the
|
||||
.Ar wait
|
||||
period.
|
||||
The
|
||||
.Fl I
|
||||
option causes
|
||||
.Nm iostat
|
||||
to print raw, unaveraged values.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width flag
|
||||
@ -61,18 +73,44 @@ The options are as follows:
|
||||
Repeat the display
|
||||
.Ar count
|
||||
times.
|
||||
The first display is for the time since a reboot and each subsequent
|
||||
report is for the time period since the last display.
|
||||
Unless the
|
||||
.Fl I
|
||||
flag is in effect, the first display is for the time since a reboot and
|
||||
each subsequent report is for the time period since the last display.
|
||||
If no
|
||||
.Ar wait
|
||||
interval is specified, the default is 1 second.
|
||||
.It Fl C
|
||||
Show cpu statistics. This is enabled by default unless the
|
||||
.Fl d,
|
||||
.Fl D,
|
||||
or
|
||||
.Fl T
|
||||
flags are used.
|
||||
.It Fl d
|
||||
Show disk statistics. This is the default. Displays kilobytes per
|
||||
transfer, number of transfers, and megabytes transfered. Use of this
|
||||
flag disables display of cpu and tty statistics.
|
||||
.It Fl D
|
||||
Show alternate disk statistics. Displays kilobytes transfered, number of
|
||||
transfers, and time spent in transfers. Use of this flag disables the
|
||||
default display.
|
||||
.It Fl I
|
||||
Show the running total values, rather than an average.
|
||||
.It Fl M
|
||||
Extract values associated with the name list from the specified core
|
||||
instead of the default
|
||||
.Dq Pa /dev/kmem .
|
||||
.Dq Pa /dev/mem .
|
||||
.It Fl N
|
||||
Extract the name list from the specified system instead of the default
|
||||
.Dq Pa /netbsd .
|
||||
.It Fl T
|
||||
Show tty statistics. This is enabled by default unless the
|
||||
.Fl C,
|
||||
.Fl d,
|
||||
or
|
||||
.Fl D
|
||||
flags are used.
|
||||
.It Fl w
|
||||
Pause
|
||||
.Ar wait
|
||||
@ -93,7 +131,7 @@ characters read from terminals
|
||||
characters written to terminals
|
||||
.El
|
||||
.It disks
|
||||
Disk operations (this field is system dependent).
|
||||
Disk operations.
|
||||
The header of the field is the disk name and unit number.
|
||||
If more than four disk drives are configured in the system,
|
||||
.Nm iostat
|
||||
@ -104,13 +142,24 @@ to display specific drives, their names may be supplied on the command
|
||||
line.
|
||||
.Pp
|
||||
.Bl -tag -width indent -compact
|
||||
.It sps
|
||||
sectors transferred per second
|
||||
.It tps
|
||||
.It K/t
|
||||
Kilobytes transferred per disk transfer
|
||||
.It t/s
|
||||
transfers per second
|
||||
.It msps
|
||||
milliseconds per average seek (including implied
|
||||
seeks and rotational latency)
|
||||
.It Mb/s
|
||||
Megabytes transferred per second
|
||||
.Pp
|
||||
.El
|
||||
The alternate display format, (selected with
|
||||
.Fl D
|
||||
), presents the following values.
|
||||
.Bl -tag -width indent -compact
|
||||
.It Kb
|
||||
Kilobytes transferred
|
||||
.It xfr
|
||||
Disk transfers
|
||||
.It time
|
||||
Seconds spent in disk activity
|
||||
.El
|
||||
.It cpu
|
||||
.Bl -tag -width indent -compact
|
||||
@ -125,10 +174,10 @@ seeks and rotational latency)
|
||||
.El
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /dev/kmem -compact
|
||||
.Bl -tag -width /dev/mem -compact
|
||||
.It Pa /netbsd
|
||||
Default kernel namelist.
|
||||
.It Pa /dev/kmem
|
||||
.It Pa /dev/mem
|
||||
Default memory file.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
|
@ -1,4 +1,36 @@
|
||||
/* $NetBSD: iostat.c,v 1.8 1995/11/28 20:16:31 thorpej Exp $ */
|
||||
/* $NetBSD: iostat.c,v 1.9 1996/05/10 23:20:29 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 John M. Vinopal
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project
|
||||
* by John M. Vinopal.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 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.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1986, 1991, 1993
|
||||
@ -43,123 +75,88 @@ static char copyright[] =
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)iostat.c 8.2 (Berkeley) 1/26/94";
|
||||
#else
|
||||
static char *rcsid = "$NetBSD: iostat.c,v 1.8 1995/11/28 20:16:31 thorpej Exp $";
|
||||
static char *rcsid = "$NetBSD: iostat.c,v 1.9 1996/05/10 23:20:29 thorpej Exp $"
|
||||
;
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/dkstat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <kvm.h>
|
||||
#include <limits.h>
|
||||
#include <nlist.h>
|
||||
#include <paths.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct nlist namelist[] = {
|
||||
#define X_DK_TIME 0
|
||||
{ "_dk_time" },
|
||||
#define X_DK_XFER 1
|
||||
{ "_dk_xfer" },
|
||||
#define X_DK_WDS 2
|
||||
{ "_dk_wds" },
|
||||
#define X_TK_NIN 3
|
||||
{ "_tk_nin" },
|
||||
#define X_TK_NOUT 4
|
||||
{ "_tk_nout" },
|
||||
#define X_DK_SEEK 5
|
||||
{ "_dk_seek" },
|
||||
#define X_CP_TIME 6
|
||||
{ "_cp_time" },
|
||||
#define X_DK_WPMS 7
|
||||
{ "_dk_wpms" },
|
||||
#define X_HZ 8
|
||||
{ "_hz" },
|
||||
#define X_STATHZ 9
|
||||
{ "_stathz" },
|
||||
#define X_DK_NDRIVE 10
|
||||
{ "_dk_ndrive" },
|
||||
#define X_END 10
|
||||
#if defined(hp300) || defined(luna68k)
|
||||
#define X_HPDINIT (X_END+1)
|
||||
{ "_hp_dinit" },
|
||||
#endif
|
||||
#ifdef mips
|
||||
#define X_SCSI_DINIT (X_END+1)
|
||||
{ "_scsi_dinit" },
|
||||
#endif
|
||||
#ifdef tahoe
|
||||
#define X_VBDINIT (X_END+1)
|
||||
{ "_vbdinit" },
|
||||
#endif
|
||||
#ifdef vax
|
||||
{ "_mbdinit" },
|
||||
#define X_MBDINIT (X_END+1)
|
||||
{ "_ubdinit" },
|
||||
#define X_UBDINIT (X_END+2)
|
||||
#endif
|
||||
{ NULL },
|
||||
};
|
||||
#include "dkstats.h"
|
||||
|
||||
struct _disk {
|
||||
long cp_time[CPUSTATES];
|
||||
long *dk_time;
|
||||
long *dk_wds;
|
||||
long *dk_seek;
|
||||
long *dk_xfer;
|
||||
long tk_nin;
|
||||
long tk_nout;
|
||||
} cur, last;
|
||||
/* Defined in dkstats.c */
|
||||
extern struct _disk cur;
|
||||
extern int dk_ndrive;
|
||||
|
||||
kvm_t *kd;
|
||||
double etime;
|
||||
long *dk_wpms;
|
||||
int dk_ndrive, *dr_select, hz, kmemfd, ndrives;
|
||||
char **dr_name;
|
||||
/* Namelist and memory files. */
|
||||
char *nlistf, *memf;
|
||||
|
||||
#define nlread(x, v) \
|
||||
kvm_read(kd, namelist[x].n_value, &(v), sizeof(v))
|
||||
int hz, reps, interval;
|
||||
static int todo = 0;
|
||||
|
||||
#include "names.c" /* XXX */
|
||||
#define ISSET(x, a) ((x) & (a))
|
||||
#define SHOW_CPU 0x0001
|
||||
#define SHOW_TTY 0x0002
|
||||
#define SHOW_STATS_1 0x0004
|
||||
#define SHOW_STATS_2 0x0008
|
||||
#define SHOW_TOTALS 0x0080
|
||||
|
||||
void cpustats __P((void));
|
||||
void dkstats __P((void));
|
||||
void phdr __P((int));
|
||||
void usage __P((void));
|
||||
static void cpustats __P((void));
|
||||
static void disk_stats __P((double));
|
||||
static void disk_stats2 __P((double));
|
||||
static void header __P((int));
|
||||
static void usage __P((void));
|
||||
static void display __P((void));
|
||||
static void selectdrives __P((int, char **));
|
||||
|
||||
void dkswap __P((void));
|
||||
void dkreadstats __P((void));
|
||||
int dkinit __P((int));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register int i;
|
||||
long tmp;
|
||||
int ch, hdrcnt, reps, interval, stathz, ndrives;
|
||||
char **cp, *memf, *nlistf, buf[30];
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
int ch, hdrcnt;
|
||||
struct timeval tv;
|
||||
|
||||
interval = reps = 0;
|
||||
nlistf = memf = NULL;
|
||||
while ((ch = getopt(argc, argv, "c:M:N:w:")) != EOF)
|
||||
while ((ch = getopt(argc, argv, "Cc:dDIM:N:Tw:")) != EOF)
|
||||
switch(ch) {
|
||||
case 'c':
|
||||
if ((reps = atoi(optarg)) <= 0)
|
||||
errx(1, "repetition count <= 0.");
|
||||
break;
|
||||
case 'C':
|
||||
todo |= SHOW_CPU;
|
||||
break;
|
||||
case 'd':
|
||||
todo |= SHOW_STATS_1;
|
||||
break;
|
||||
case 'D':
|
||||
todo |= SHOW_STATS_2;
|
||||
break;
|
||||
case 'I':
|
||||
todo |= SHOW_TOTALS;
|
||||
break;
|
||||
case 'M':
|
||||
memf = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
nlistf = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
todo |= SHOW_TTY;
|
||||
break;
|
||||
case 'w':
|
||||
if ((interval = atoi(optarg)) <= 0)
|
||||
errx(1, "interval <= 0.");
|
||||
@ -171,6 +168,9 @@ main(argc, argv)
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!ISSET(todo, SHOW_CPU | SHOW_TTY | SHOW_STATS_1 | SHOW_STATS_2))
|
||||
todo |= SHOW_CPU | SHOW_TTY | SHOW_STATS_1;
|
||||
|
||||
/*
|
||||
* Discard setgid privileges if not the running kernel so that bad
|
||||
* guys can't print interesting stuff from kernel memory.
|
||||
@ -178,41 +178,206 @@ main(argc, argv)
|
||||
if (nlistf != NULL || memf != NULL)
|
||||
setgid(getgid());
|
||||
|
||||
kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
|
||||
if (kd == 0)
|
||||
errx(1, "kvm_openfiles: %s", errbuf);
|
||||
if (kvm_nlist(kd, namelist) == -1)
|
||||
errx(1, "kvm_nlist: %s", kvm_geterr(kd));
|
||||
if (namelist[X_DK_NDRIVE].n_type == 0)
|
||||
errx(1, "dk_ndrive not found in namelist");
|
||||
(void)nlread(X_DK_NDRIVE, dk_ndrive);
|
||||
if (dk_ndrive <= 0)
|
||||
errx(1, "invalid dk_ndrive %d\n", dk_ndrive);
|
||||
dkinit(0);
|
||||
dkreadstats();
|
||||
selectdrives(argc, argv);
|
||||
|
||||
cur.dk_time = calloc(dk_ndrive, sizeof(long));
|
||||
cur.dk_wds = calloc(dk_ndrive, sizeof(long));
|
||||
cur.dk_seek = calloc(dk_ndrive, sizeof(long));
|
||||
cur.dk_xfer = calloc(dk_ndrive, sizeof(long));
|
||||
last.dk_time = calloc(dk_ndrive, sizeof(long));
|
||||
last.dk_wds = calloc(dk_ndrive, sizeof(long));
|
||||
last.dk_seek = calloc(dk_ndrive, sizeof(long));
|
||||
last.dk_xfer = calloc(dk_ndrive, sizeof(long));
|
||||
dr_select = calloc(dk_ndrive, sizeof(int));
|
||||
dr_name = calloc(dk_ndrive, sizeof(char *));
|
||||
dk_wpms = calloc(dk_ndrive, sizeof(long));
|
||||
tv.tv_sec = interval;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
(void)sprintf(buf, "dk%d", i);
|
||||
dr_name[i] = strdup(buf);
|
||||
/* print a new header on sigcont */
|
||||
(void)signal(SIGCONT, header);
|
||||
|
||||
for (hdrcnt = 1;;) {
|
||||
if (!--hdrcnt) {
|
||||
header(0);
|
||||
hdrcnt = 20;
|
||||
}
|
||||
if (!read_names())
|
||||
|
||||
if (!ISSET(todo, SHOW_TOTALS))
|
||||
dkswap();
|
||||
display();
|
||||
|
||||
if (reps >= 0 && --reps <= 0)
|
||||
break;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
dkreadstats();
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
header(signo)
|
||||
int signo;
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* Main Headers. */
|
||||
if (ISSET(todo, SHOW_TTY))
|
||||
(void)printf(" tty");
|
||||
|
||||
if (ISSET(todo, SHOW_STATS_1))
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (cur.dk_select[i])
|
||||
(void)printf(" %3.3s ", cur.dk_name[i]);
|
||||
|
||||
if (ISSET(todo, SHOW_STATS_2))
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (cur.dk_select[i])
|
||||
(void)printf(" %3.3s ", cur.dk_name[i]);
|
||||
|
||||
if (ISSET(todo, SHOW_CPU))
|
||||
(void)printf(" cpu");
|
||||
printf("\n");
|
||||
|
||||
/* Sub-Headers. */
|
||||
if (ISSET(todo, SHOW_TTY))
|
||||
printf(" tin tout");
|
||||
|
||||
if (ISSET(todo, SHOW_STATS_1))
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (cur.dk_select[i])
|
||||
if (ISSET(todo, SHOW_TOTALS))
|
||||
(void)printf(" K/t xfr Mb ");
|
||||
else
|
||||
(void)printf(" K/t t/s Mb/s ");
|
||||
|
||||
if (ISSET(todo, SHOW_STATS_2))
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (cur.dk_select[i])
|
||||
(void)printf(" Kb xfr time ");
|
||||
|
||||
if (ISSET(todo, SHOW_CPU))
|
||||
(void)printf(" us ni sy in id");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
disk_stats(etime)
|
||||
double etime;
|
||||
{
|
||||
register int dn;
|
||||
double atime, mbps;
|
||||
|
||||
for (dn = 0; dn < dk_ndrive; ++dn) {
|
||||
if (!cur.dk_select[dn])
|
||||
continue;
|
||||
|
||||
/* average Kbytes per transfer. */
|
||||
if (cur.dk_xfer[dn])
|
||||
mbps = (cur.dk_bytes[dn] / (1024.0)) / cur.dk_xfer[dn];
|
||||
else
|
||||
mbps = 0.0;
|
||||
(void)printf(" %5.2f", mbps);
|
||||
|
||||
/* average transfers per second. */
|
||||
(void)printf(" %3.0f", cur.dk_xfer[dn] / etime);
|
||||
|
||||
/* time busy in disk activity */
|
||||
atime = (double)cur.dk_time[dn].tv_sec +
|
||||
((double)cur.dk_time[dn].tv_usec / (double)1000000);
|
||||
|
||||
/* Megabytes per second. */
|
||||
if (atime != 0.0)
|
||||
mbps = cur.dk_bytes[dn] / (double)(1024 * 1024);
|
||||
else
|
||||
mbps = 0;
|
||||
(void)printf(" %4.2f ", mbps / etime);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
disk_stats2(etime)
|
||||
double etime;
|
||||
{
|
||||
register int dn;
|
||||
double atime;
|
||||
|
||||
for (dn = 0; dn < dk_ndrive; ++dn) {
|
||||
if (!cur.dk_select[dn])
|
||||
continue;
|
||||
|
||||
/* average kbytes per second. */
|
||||
(void)printf(" %4.0f", cur.dk_bytes[dn] / (1024.0) / etime);
|
||||
|
||||
/* average transfers per second. */
|
||||
(void)printf(" %3.0f", cur.dk_xfer[dn] / etime);
|
||||
|
||||
/* average time busy in disk activity. */
|
||||
atime = (double)cur.dk_time[dn].tv_sec +
|
||||
((double)cur.dk_time[dn].tv_usec / (double)1000000);
|
||||
(void)printf(" %4.2f ", atime / etime);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cpustats()
|
||||
{
|
||||
register int state;
|
||||
double time;
|
||||
|
||||
time = 0;
|
||||
for (state = 0; state < CPUSTATES; ++state)
|
||||
time += cur.cp_time[state];
|
||||
if (!time)
|
||||
time = 1.0;
|
||||
/* States are generally never 100% and can use %3.0f. */
|
||||
for (state = 0; state < CPUSTATES; ++state)
|
||||
printf("%3.0f", 100. * cur.cp_time[state] / time);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: iostat [-CdDIT] [-c count] [-M core] [-N system] [-w wait] [drives]\n");
|
||||
exit(1);
|
||||
(void)nlread(X_HZ, hz);
|
||||
(void)nlread(X_STATHZ, stathz);
|
||||
if (stathz)
|
||||
hz = stathz;
|
||||
(void)kvm_read(kd, namelist[X_DK_WPMS].n_value, dk_wpms,
|
||||
dk_ndrive * sizeof(dk_wpms));
|
||||
}
|
||||
|
||||
static void
|
||||
display()
|
||||
{
|
||||
int i;
|
||||
double etime;
|
||||
|
||||
/* Sum up the elapsed ticks. */
|
||||
etime = 0.0;
|
||||
for (i = 0; i < CPUSTATES; i++) {
|
||||
etime += cur.cp_time[i];
|
||||
}
|
||||
if (etime == 0.0)
|
||||
etime = 1.0;
|
||||
/* Convert to seconds. */
|
||||
etime /= (float)hz;
|
||||
|
||||
/* If we're showing totals only, then don't divide by the
|
||||
* system time.
|
||||
*/
|
||||
if (ISSET(todo, SHOW_TOTALS))
|
||||
etime = 1.0;
|
||||
|
||||
if (ISSET(todo, SHOW_TTY))
|
||||
printf("%4.0f %4.0f", cur.tk_nin / etime, cur.tk_nout / etime);
|
||||
|
||||
if (ISSET(todo, SHOW_STATS_1))
|
||||
disk_stats(etime);
|
||||
|
||||
if (ISSET(todo, SHOW_STATS_2))
|
||||
disk_stats2(etime);
|
||||
|
||||
if (ISSET(todo, SHOW_CPU))
|
||||
cpustats();
|
||||
|
||||
(void)printf("\n");
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
selectdrives(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i, ndrives;
|
||||
|
||||
/*
|
||||
* Choose drives to be displayed. Priority goes to (in order) drives
|
||||
@ -230,9 +395,9 @@ main(argc, argv)
|
||||
break;
|
||||
#endif
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
if (strcmp(dr_name[i], *argv))
|
||||
if (strcmp(cur.dk_name[i], *argv))
|
||||
continue;
|
||||
dr_select[i] = 1;
|
||||
cur.dk_select[i] = 1;
|
||||
++ndrives;
|
||||
}
|
||||
}
|
||||
@ -251,147 +416,12 @@ main(argc, argv)
|
||||
if (reps)
|
||||
interval = 1;
|
||||
|
||||
/* Pick up to 4 drives if none specified. */
|
||||
if (ndrives == 0)
|
||||
for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
|
||||
if (dr_select[i] || dk_wpms[i] == 0)
|
||||
if (cur.dk_select[i])
|
||||
continue;
|
||||
for (cp = defdrives; *cp; cp++)
|
||||
if (strcmp(dr_name[i], *cp) == 0) {
|
||||
dr_select[i] = 1;
|
||||
++ndrives;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
|
||||
if (dr_select[i])
|
||||
continue;
|
||||
dr_select[i] = 1;
|
||||
cur.dk_select[i] = 1;
|
||||
++ndrives;
|
||||
}
|
||||
|
||||
(void)signal(SIGCONT, phdr);
|
||||
|
||||
for (hdrcnt = 1;;) {
|
||||
if (!--hdrcnt) {
|
||||
phdr(0);
|
||||
hdrcnt = 20;
|
||||
}
|
||||
(void)kvm_read(kd, namelist[X_DK_TIME].n_value,
|
||||
cur.dk_time, dk_ndrive * sizeof(long));
|
||||
(void)kvm_read(kd, namelist[X_DK_XFER].n_value,
|
||||
cur.dk_xfer, dk_ndrive * sizeof(long));
|
||||
(void)kvm_read(kd, namelist[X_DK_WDS].n_value,
|
||||
cur.dk_wds, dk_ndrive * sizeof(long));
|
||||
(void)kvm_read(kd, namelist[X_DK_SEEK].n_value,
|
||||
cur.dk_seek, dk_ndrive * sizeof(long));
|
||||
(void)kvm_read(kd, namelist[X_TK_NIN].n_value,
|
||||
&cur.tk_nin, sizeof(cur.tk_nin));
|
||||
(void)kvm_read(kd, namelist[X_TK_NOUT].n_value,
|
||||
&cur.tk_nout, sizeof(cur.tk_nout));
|
||||
(void)kvm_read(kd, namelist[X_CP_TIME].n_value,
|
||||
cur.cp_time, sizeof(cur.cp_time));
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
if (!dr_select[i])
|
||||
continue;
|
||||
#define X(fld) tmp = cur.fld[i]; cur.fld[i] -= last.fld[i]; last.fld[i] = tmp
|
||||
X(dk_xfer);
|
||||
X(dk_seek);
|
||||
X(dk_wds);
|
||||
X(dk_time);
|
||||
}
|
||||
tmp = cur.tk_nin;
|
||||
cur.tk_nin -= last.tk_nin;
|
||||
last.tk_nin = tmp;
|
||||
tmp = cur.tk_nout;
|
||||
cur.tk_nout -= last.tk_nout;
|
||||
last.tk_nout = tmp;
|
||||
etime = 0;
|
||||
for (i = 0; i < CPUSTATES; i++) {
|
||||
X(cp_time);
|
||||
etime += cur.cp_time[i];
|
||||
}
|
||||
if (etime == 0.0)
|
||||
etime = 1.0;
|
||||
etime /= (float)hz;
|
||||
(void)printf("%4.0f%5.0f",
|
||||
cur.tk_nin / etime, cur.tk_nout / etime);
|
||||
dkstats();
|
||||
cpustats();
|
||||
(void)printf("\n");
|
||||
(void)fflush(stdout);
|
||||
|
||||
if (reps >= 0 && --reps <= 0)
|
||||
break;
|
||||
(void)sleep(interval);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* ARGUSED */
|
||||
void
|
||||
phdr(signo)
|
||||
int signo;
|
||||
{
|
||||
register int i;
|
||||
|
||||
(void)printf(" tty");
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dr_select[i])
|
||||
(void)printf(" %3.3s ", dr_name[i]);
|
||||
(void)printf(" cpu\n tin tout");
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dr_select[i])
|
||||
(void)printf(" sps tps msps ");
|
||||
(void)printf(" us ni sy in id\n");
|
||||
}
|
||||
|
||||
void
|
||||
dkstats()
|
||||
{
|
||||
register int dn;
|
||||
double atime, itime, msps, words, xtime;
|
||||
|
||||
for (dn = 0; dn < dk_ndrive; ++dn) {
|
||||
if (!dr_select[dn])
|
||||
continue;
|
||||
words = cur.dk_wds[dn] * 32; /* words xfer'd */
|
||||
(void)printf("%4.0f", /* sectors */
|
||||
words / (DEV_BSIZE / 2) / etime);
|
||||
|
||||
(void)printf("%4.0f", cur.dk_xfer[dn] / etime);
|
||||
|
||||
if (dk_wpms[dn] && cur.dk_xfer[dn]) {
|
||||
atime = cur.dk_time[dn]; /* ticks disk busy */
|
||||
atime /= (float)hz; /* ticks to seconds */
|
||||
xtime = words / dk_wpms[dn]; /* transfer time */
|
||||
itime = atime - xtime; /* time not xfer'ing */
|
||||
if (itime < 0)
|
||||
msps = 0;
|
||||
else
|
||||
msps = itime * 1000 / cur.dk_xfer[dn];
|
||||
} else
|
||||
msps = 0;
|
||||
(void)printf("%5.1f ", msps);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cpustats()
|
||||
{
|
||||
register int state;
|
||||
double time;
|
||||
|
||||
time = 0;
|
||||
for (state = 0; state < CPUSTATES; ++state)
|
||||
time += cur.cp_time[state];
|
||||
for (state = 0; state < CPUSTATES; ++state)
|
||||
(void)printf("%3.0f",
|
||||
100. * cur.cp_time[state] / (time ? time : 1));
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: iostat [-c count] [-M core] [-N system] [-w wait] [drives]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user