2.9BSD/usr/src/cmd/iostat.c
/*
* IOSTAT
*
* For use with the 2.9 BSD (Berkeley PDP11) system.
*/
#include <sys/param.h>
#ifndef DISKMON
#define DISKMON /* force definition for systm.h */
#endif
#include <sys/systm.h>
#include <stdio.h>
#include <a.out.h>
#define MAXDISK 6 /* max disks that can be monitored */
#define LSTDRV 0 /* last bit for drives (seek only) */
/* usec per word for the various disks */
double xf[MAXDISK] = {
2.48, /* RM02 */
2.48, /* RM02 */
11.1 /* RK05 */
/* 1.95, Ampex 9300/Diva Comp 5 (33 sect.) */
/* 2.05, RS04 */
};
int bflg;
int dflg;
int iflg;
int aflg;
int sflg;
int oflg; /* Data only, no summary line, no headers */
int uflg;
struct nlist nl[] = {
#define X_DKBUSY 0
"_dk_busy", 0, 0,
#define X_SYTIME 1
"_sy_time", 0, 0,
#define X_DKTIME 2
"_dk_time", 0, 0,
#define X_DKNUMB 3
"_dk_numb", 0, 0,
#define X_DKWDS 4
"_dk_wds", 0, 0,
#define X_NDISK 5
"_ndisk", 0, 0,
#define X_TIN 6
"_tk_nin", 0, 0,
#define X_TOUT 7
"_tk_nout", 0, 0,
#define X_IOINFO 8
"_io_info", 0, 0,
#define X_UBMETER 9
"_ub_meter", 0, 0,
"\0\0\0\0\0\0\0\0", 0, 0
};
struct
{
int busy;
long sy_time[8];
long dk_time[1<<MAXDISK];
long numb[MAXDISK];
long wds[MAXDISK];
long tin;
long tout;
} s, s1;
struct ubmeter {
long ub_requests; /* total # of calls to mapalloc */
long ub_remaps; /* total # of buffer remappings */
long ub_failures; /* total # of allocation failures */
long ub_pages; /* total # of pages allocated */
};
int ndisk;
struct ioinfo io_info, io_delta;
struct ubmeter ub_meter, ub_delta;
double etime;
int skip=1;
int mf;
main(argc, argv)
char *argv[];
{
extern char *ctime();
register i;
int iter;
double f1, f2;
long t;
if ((nlist("/unix", nl) == -1) || (nl[0].n_type == 0)) {
printf("no /unix namelist\n");
exit(1);
}
if(nl[X_SYTIME].n_type == 0) {
printf("sy_time not in namelist-- wrong iostat\n");
exit(1);
}
mf = open("/dev/kmem", 0);
if(mf < 0) {
printf("cannot open /dev/kmem\n");
exit(1);
}
iter = 0;
while (argc>1&&argv[1][0]=='-') {
if (argv[1][1]=='d')
dflg++;
else if (argv[1][1]=='s')
sflg++;
else if (argv[1][1]=='a')
aflg++;
else if (argv[1][1]=='i')
iflg++;
else if (argv[1][1]=='b')
bflg++;
else if (argv[1][1]=='o')
oflg++;
else if (argv[1][1]=='u')
uflg++;
argc--;
argv++;
}
if(argc > 2)
iter = atoi(argv[2]);
if(oflg && (iter != 0)) iter+=1;
lseek(mf, (long)nl[X_NDISK].n_value, 0);
read(mf, (char *)&ndisk, sizeof ndisk);
if (ndisk <=0 || ndisk > MAXDISK || ndisk <= LSTDRV) {
fprintf(stderr, "Too many disks monitored (or system mismatch)\n");
exit(1);
}
if (!(sflg|iflg|oflg|bflg|uflg)) {
printf(" TTY ");
for (i=0; i <= LSTDRV; i++)
printf(" DK%d SEEK",i);
for ( ; i < ndisk; i++)
printf(" DK%d TRANSFER ",i);
printf(" PERCENT\n");
printf("tin tout");
for (i=0; i <= LSTDRV; i++)
printf(" sps msps");
for ( ; i < ndisk; i++)
printf(" tps msps mspt");
printf(" usr nic sys idle\n");
}
if(iflg&&!oflg)
{
printf(" RESOURCE USAGE (in percent)\n");
printf(" user nice sys idle iowt iact");
for (i=0; i <= LSTDRV; i++)
printf(" dk%ds",i);
for ( ; i < ndisk; i++)
printf(" dk%dx",i);
printf("\n");
}
if (bflg && !oflg) {
printf(" BUFFER CACHE USAGE\n");
printf("read reada cache write\n");
}
if (uflg && !oflg) {
printf(" UNIBUS MAP USAGE\n");
printf("requests buffer remaps raw i/o pages allocation failures\n");
}
loop:
if (bflg) {
biostats();
goto contin;
}
if (uflg) {
unibusstats();
goto contin;
}
lseek(mf, (long)nl[X_DKBUSY].n_value, 0);
read(mf, (char *)&(s.busy), sizeof (s.busy));
lseek(mf, (long)nl[X_SYTIME].n_value, 0);
read(mf, (char *)&(s.sy_time), sizeof (s.sy_time));
lseek(mf, (long)nl[X_DKTIME].n_value, 0);
read(mf, (char *)&(s.dk_time), (1 << ndisk) * sizeof (s.dk_time[0]));
lseek(mf, (long)nl[X_DKNUMB].n_value, 0);
read(mf, (char *)&(s.numb), ndisk * sizeof (s.numb[0]));
lseek(mf, (long)nl[X_DKWDS].n_value, 0);
read(mf, (char *)&(s.wds), ndisk * sizeof (s.wds[0]));
lseek(mf, (long)nl[X_TIN].n_value, 0);
read(mf, (char *)&(s.tin), sizeof (s.tin));
lseek(mf, (long)nl[X_TOUT].n_value, 0);
read(mf, (char *)&(s.tout), sizeof (s.tout));
etime = 0;
for(i=0; i < 8; i++) {
t = s.sy_time[i];
s.sy_time[i] -= s1.sy_time[i];
s1.sy_time[i] = t;
etime += s.sy_time[i];
}
if(etime == 0.)
etime = 1.;
for(i=0; i < (1 << ndisk); i++) {
t = s.dk_time[i];
s.dk_time[i] -= s1.dk_time[i];
s1.dk_time[i] = t;
}
for(i=0; i < ndisk; i++) {
t = s.numb[i];
s.numb[i] -= s1.numb[i];
s1.numb[i] = t;
t = s.wds[i];
s.wds[i] -= s1.wds[i];
s1.wds[i] = t;
}
t = s.tin;
s.tin -= s1.tin;
s1.tin = t;
t = s.tout;
s.tout -= s1.tout;
s1.tout = t;
if(oflg && skip)
{
skip =0;
goto contin;
}
if (dflg) {
long tm;
time(&tm);
printf("%s", ctime(&tm));
}
if (aflg)
printf("%.2f minutes total\n", etime/3600);
if (sflg) {
stats2(etime);
goto contin;
}
if (iflg) {
stats3(etime);
goto contin;
}
etime /= 60.;
f1 = s.tin;
f2 = s.tout;
printf(" %3.0f", f1/etime);
printf(" %3.0f", f2/etime);
for(i=0; i<ndisk; i++)
stats(i);
for(i=0; i<4; i++)
stat1(i);
printf("\n");
contin:
--iter;
if(iter)
if(argc > 1) {
sleep(atoi(argv[1]));
goto loop;
}
}
stats(dn)
{
register i;
double f1, f2, f3;
double f4, f5, f6;
long t;
t = 0;
for(i=0; i < (1<<ndisk); i++)
if(i & (1<<dn))
t += s.dk_time[i];
f1 = t;
f1 = f1/60.;
f2 = s.numb[dn];
if(f2 == 0.) {
if(dn>LSTDRV)
printf(" %4.0f %4.1f %4.1f", 0.0, 0.0, 0.0);
else
printf(" %4.0f %4.1f", 0.0, 0.0);
return;
}
f3 = s.wds[dn];
f3 = f3*32.;
f4 = xf[dn];
f4 = f4*1.0e-6;
f5 = f1 - f4*f3;
f6 = f1 - f5;
printf(" %4.0f", f2/etime);
printf(" %4.1f", f5*1000./f2);
if(dn >LSTDRV)
printf(" %4.1f", f6*1000./f2); /* no xfer time for seeks */
}
stat1(o)
{
double f;
f = s.sy_time[2*o] +s.sy_time[2*o+1];
printf(" %3.0f", f*(100./60.)/etime);
}
stats2(t)
double t;
{
register i, j;
t /= 100.;
printf("sy_time: ");
for (j=0; j<8; j++)
printf("%6.2f ", s.sy_time[j]/t);
printf("\ndk_time: ");
for (j=0; j < (1<<ndisk); j++) {
printf("%6.2f ", s.dk_time[j]);
if (j%8 == 7)
printf("\n ");
}
printf("\ndk_numb: ");
for(i=0; i<ndisk; i++)
printf("%12D",s.numb[i]);
printf("\ndk_wds: ");
for(i=0; i<ndisk; i++)
printf("%12D",s.wds[i]);
printf("\n\n");
}
stats3(t)
double t;
{
register i, j;
double sum;
t /= 100;
sum = s.sy_time[0] + s.sy_time[1];
printf(" %4.0f", sum/t);
sum = s.sy_time[2] + s.sy_time[3];
printf(" %4.0f", sum/t);
sum = s.sy_time[4] + s.sy_time[5];
printf(" %4.0f", sum/t);
sum = s.sy_time[6] + s.sy_time[7];
printf(" %4.0f", sum/t);
printf(" %4.0f", s.sy_time[7]/t);
sum = s.sy_time[1] + s.sy_time[3] + s.sy_time[5] + s.sy_time[7];
printf(" %4.0f", sum/t);
for (j=0; j < ndisk; j++) {
sum = 0;
for(i=0; i < (1<<ndisk); i++)
if(i & (01<<j))
sum += s.dk_time[i];
printf(" %4.0f", sum/t);
}
printf("\n");
}
biostats()
{
if (nl[X_IOINFO].n_type == 0) {
printf("io_info not found in /unix namelist\n");
exit(1);
}
lseek(mf,(long)nl[X_IOINFO].n_value, 0);
read(mf, (char *)&io_info, sizeof(io_info));
printf("%D\t%D\t%D\t%D\n",
io_info.nread-io_delta.nread, io_info.nreada-io_delta.nreada,
io_info.ncache-io_delta.ncache, io_info.nwrite-io_delta.nwrite);
io_delta = io_info;
}
unibusstats()
{
if (nl[X_UBMETER].n_type == 0) {
printf("ub_meter not found in /unix name list\n");
exit(1);
}
lseek(mf, (long)nl[X_UBMETER].n_value, 0);
read(mf, (char *) &ub_meter, sizeof(ub_meter));
printf("%D\t\t%D\t\t%D\t\t%D\n",
ub_meter.ub_requests - ub_delta.ub_requests,
ub_meter.ub_remaps - ub_delta.ub_remaps,
ub_meter.ub_pages - ub_delta.ub_pages,
ub_meter.ub_failures - ub_delta.ub_failures
);
ub_delta = ub_meter;
}