version 1.2, 1996/03/27 19:32:54 |
version 1.3, 1996/05/22 11:35:34 |
|
|
/* $OpenBSD$ */ |
/* $NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $ */ |
/* $NetBSD: iostat.c,v 1.4 1996/03/15 22:19:25 ragge Exp $ */ |
|
|
|
/* |
/* |
* Copyright (c) 1980, 1992, 1993 |
* Copyright (c) 1980, 1992, 1993 |
|
|
#ifndef lint |
#ifndef lint |
#if 0 |
#if 0 |
static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93"; |
static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93"; |
static char rcsid[] = "$NetBSD: iostat.c,v 1.4 1996/03/15 22:19:25 ragge Exp $"; |
|
#endif |
#endif |
static char rcsid[] = "$OpenBSD$"; |
static char rcsid[] = "$NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $"; |
#endif not lint |
#endif not lint |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/dkstat.h> |
#include <sys/dkstat.h> |
#include <sys/buf.h> |
#include <sys/buf.h> |
|
#include <sys/time.h> |
|
|
#include <string.h> |
#include <string.h> |
#include <stdlib.h> |
#include <stdlib.h> |
|
|
#include "systat.h" |
#include "systat.h" |
#include "extern.h" |
#include "extern.h" |
|
|
static struct nlist namelist[] = { |
#include "dkstats.h" |
#define X_DK_BUSY 0 |
extern struct _disk cur; |
{ "_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; |
|
|
|
static int linesperregion; |
static int linesperregion; |
static double etime; |
static double etime; |
static int numbers = 0; /* default display bar graphs */ |
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 int barlabels __P((int)); |
static void histogram __P((double, int, double)); |
static void histogram __P((double, int, double)); |
|
|
int |
int |
initiostat() |
initiostat() |
{ |
{ |
if (namelist[X_DK_BUSY].n_type == 0) { |
dkinit(1); |
if (kvm_nlist(kd, namelist)) { |
dkreadstats(); |
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); |
|
} |
} |
|
|
void |
void |
fetchiostat() |
fetchiostat() |
{ |
{ |
if (namelist[X_DK_BUSY].n_type == 0) |
if (dk_ndrive == 0) |
return; |
return; |
NREAD(X_DK_BUSY, &s.dk_busy, LONG); |
dkreadstats(); |
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); |
|
} |
} |
|
|
#define INSET 10 |
#define INSET 10 |
|
|
{ |
{ |
int row; |
int row; |
|
|
if (namelist[X_DK_BUSY].n_type == 0) { |
if (dk_ndrive == 0) { |
error("No dk_busy defined."); |
error("No drives defined."); |
return; |
return; |
} |
} |
row = 0; |
row = 0; |
|
|
#define COLWIDTH 14 |
#define COLWIDTH 14 |
#define DRIVESPERLINE ((wnd->maxx - INSET) / COLWIDTH) |
#define DRIVESPERLINE ((wnd->maxx - INSET) / COLWIDTH) |
for (ndrives = 0, i = 0; i < dk_ndrive; i++) |
for (ndrives = 0, i = 0; i < dk_ndrive; i++) |
if (dk_select[i]) |
if (cur.dk_select[i]) |
ndrives++; |
ndrives++; |
regions = howmany(ndrives, DRIVESPERLINE); |
regions = howmany(ndrives, DRIVESPERLINE); |
/* |
/* |
|
|
linesperregion = 3; |
linesperregion = 3; |
col = 0; |
col = 0; |
for (i = 0; i < dk_ndrive; i++) |
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) { |
if (col + COLWIDTH >= wnd->maxx - INSET) { |
col = 0, row += linesperregion + 1; |
col = 0, row += linesperregion + 1; |
if (row > wnd->maxy - (linesperregion + 1)) |
if (row > wnd->maxy - (linesperregion + 1)) |
break; |
break; |
} |
} |
mvwaddstr(wnd, row, col + 4, dr_name[i]); |
mvwaddstr(wnd, row, col + 4, cur.dk_name[i]); |
mvwaddstr(wnd, row + 1, col, "bps tps msps"); |
mvwaddstr(wnd, row + 1, col, "Kps tps sec"); |
col += COLWIDTH; |
col += COLWIDTH; |
} |
} |
if (col) |
if (col) |
|
|
int i; |
int i; |
|
|
mvwaddstr(wnd, row++, INSET, |
mvwaddstr(wnd, row++, INSET, |
"/0 /5 /10 /15 /20 /25 /30 /35 /40 /45 /50"); |
"/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); |
linesperregion = 2 + msps; |
linesperregion = 2 + secs; |
for (i = 0; i < dk_ndrive; i++) |
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) |
if (row > wnd->maxy - linesperregion) |
break; |
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|"); |
mvwaddstr(wnd, row++, 0, " tps|"); |
if (msps) |
if (secs) |
mvwaddstr(wnd, row++, 0, " msps|"); |
mvwaddstr(wnd, row++, 0, " msec|"); |
} |
} |
return (row); |
return (row); |
} |
} |
|
|
void |
void |
showiostat() |
showiostat() |
{ |
{ |
register long t; |
register u_int64_t t; |
register int i, row, col; |
register int i, row, col; |
|
|
if (namelist[X_DK_BUSY].n_type == 0) |
if (dk_ndrive == 0) |
return; |
return; |
for (i = 0; i < dk_ndrive; i++) { |
dkswap(); |
#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); |
|
} |
|
etime = 0; |
etime = 0; |
for(i = 0; i < CPUSTATES; i++) { |
for(i = 0; i < CPUSTATES; i++) { |
X(cp_time); |
etime += cur.cp_time[i]; |
etime += s.cp_time[i]; |
|
} |
} |
if (etime == 0.0) |
if (etime == 0.0) |
etime = 1.0; |
etime = 1.0; |
|
|
if (!numbers) { |
if (!numbers) { |
row += 2; |
row += 2; |
for (i = 0; i < dk_ndrive; i++) |
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) |
if (row > wnd->maxy - linesperregion) |
break; |
break; |
row = stats(row, INSET, i); |
row = stats(row, INSET, i); |
|
|
wmove(wnd, row + 3, 0); |
wmove(wnd, row + 3, 0); |
winsertln(wnd); |
winsertln(wnd); |
for (i = 0; i < dk_ndrive; i++) |
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) { |
if (col + COLWIDTH >= wnd->maxx) { |
col = 0, row += linesperregion + 1; |
col = 0, row += linesperregion + 1; |
if (row > wnd->maxy - (linesperregion + 1)) |
if (row > wnd->maxy - (linesperregion + 1)) |
|
|
stats(row, col, dn) |
stats(row, col, dn) |
int row, col, dn; |
int row, col, dn; |
{ |
{ |
double atime, words, xtime, itime; |
double atime, words; |
|
|
atime = s.dk_time[dn]; |
/* time busy in disk activity */ |
atime /= (float) hz; |
atime = (double)cur.dk_time[dn].tv_sec + |
words = s.dk_wds[dn]*32.0; /* number of words transferred */ |
((double)cur.dk_time[dn].tv_usec / (double)1000000); |
xtime = dk_mspw[dn]*words; /* transfer time */ |
|
itime = atime - xtime; /* time not transferring */ |
words = cur.dk_bytes[dn] / 1024.0; /* # of K transferred */ |
if (xtime < 0) |
|
itime += xtime, xtime = 0; |
|
if (itime < 0) |
|
xtime += itime, itime = 0; |
|
if (numbers) { |
if (numbers) { |
mvwprintw(wnd, row, col, "%3.0f%4.0f%5.1f", |
mvwprintw(wnd, row, col, "%3.0f%4.0f%5.1f", |
words / 512 / etime, s.dk_xfer[dn] / etime, |
words / etime, cur.dk_xfer[dn] / etime, atime / etime); |
s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0.0); |
|
return (row); |
return (row); |
} |
} |
wmove(wnd, row++, col); |
wmove(wnd, row++, col); |
histogram(words / 512 / etime, 50, 1.0); |
histogram(words / etime, 50, 0.5); |
wmove(wnd, row++, col); |
wmove(wnd, row++, col); |
histogram(s.dk_xfer[dn] / etime, 50, 1.0); |
histogram(cur.dk_xfer[dn] / etime, 50, 0.5); |
if (msps) { |
if (secs) { |
wmove(wnd, row++, col); |
wmove(wnd, row++, col); |
histogram(s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0, |
atime *= 1000; /* In milliseconds */ |
50, 1.0); |
histogram(atime / etime, 50, 0.5); |
} |
} |
return (row); |
return (row); |
} |
} |
|
|
|
|
time = 0; |
time = 0; |
for (i = 0; i < CPUSTATES; i++) |
for (i = 0; i < CPUSTATES; i++) |
time += s.cp_time[i]; |
time += cur.cp_time[i]; |
if (time == 0.0) |
if (time == 0.0) |
time = 1.0; |
time = 1.0; |
wmove(wnd, row, INSET); |
wmove(wnd, row, INSET); |
#define CPUSCALE 0.5 |
#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 |
static void |
|
|
while (k--) |
while (k--) |
waddch(wnd, 'X'); |
waddch(wnd, 'X'); |
waddstr(wnd, buf); |
waddstr(wnd, buf); |
|
wclrtoeol(wnd); |
return; |
return; |
} |
} |
while (k--) |
while (k--) |
|
|
char *cmd, *args; |
char *cmd, *args; |
{ |
{ |
|
|
if (prefix(cmd, "msps")) |
if (prefix(cmd, "secs")) |
msps = !msps; |
secs = !secs; |
else if (prefix(cmd, "numbers")) |
else if (prefix(cmd, "numbers")) |
numbers = 1; |
numbers = 1; |
else if (prefix(cmd, "bars")) |
else if (prefix(cmd, "bars")) |