2.9BSD/usr/src/cmd/iostat.c

Compare this file to the similar file:
Show the results in this format:

/*
 *	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;
}