Subject: bin/2161: iostat fails to print disk statistics
To: None <gnats-bugs@NetBSD.ORG>
From: John M Vinopal <banshee@gabriella.resort.com>
List: netbsd-bugs
Date: 03/02/1996 14:02:26
>Number:         2161
>Category:       bin
>Synopsis:       iostat fails to print disk statistics
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Mar  2 17:20:04 1996
>Last-Modified:
>Originator:     John M Vinopal
>Organization:
Resort 'O' Matic
>Release:        1.1
>Environment:
System: NetBSD gabriella.resort.com 1.1A NetBSD 1.1A (GABRIELLA-NCR) #0: Sun Feb
 4 16:16:19 PST 1996 banshee@gabriella.resort.com:/usr/local/NetBSD/src/sys/arch
/i386/compile/GABRIELLA-NCR i386


>Description:
        Kernel alterations have made all disk statistics fail to work
        with userland utilities.
>How-To-Repeat:
>Fix:
        The following shar file contains a full replacement for the
        iostat utility.  The dkstats.[c,h] files are read from the
	vmstat(8) directory.

        This code has been tested ONLY on an i386 with one/two floppies
        and one/two hard drives.  It _should_ work on diskless and
        many disk systems.  Bugs/comments should be forwarded to
        banshee@resort.com 

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	Makefile
#	iostat.8
#	iostat.c
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
X#	$NetBSD: Makefile,v 1.12 1995/12/22 08:04:27 jonathan Exp $
X#	from: @(#)Makefile	8.1 (Berkeley) 6/6/93
X
XPROG=	iostat
X.if (${MACHINE_ARCH} == "m68k")
XCFLAGS+=-D${MACHINE}
X.endif
X
X.PATH:	${.CURDIR}/../../usr.bin/vmstat
X
XCFLAGS+=-I${.CURDIR}/../../sys/arch -I${.CURDIR}/../../usr.bin/vmstat
XSRCS=	dkstats.c iostat.c
XMAN=	iostat.8
XDPADD=	${LIBKVM}
XLDADD=	-lkvm
XBINGRP=	kmem
XBINMODE=2555
X
X.include <bsd.prog.mk>
END-of-Makefile
echo x - iostat.8
sed 's/^X//' >iostat.8 << 'END-of-iostat.8'
X.\"	$NetBSD: iostat.8,v 1.8 1995/11/28 20:16:30 thorpej Exp $
X.\"
X.\" Copyright (c) 1985, 1991, 1993
X.\"	The Regents of the University of California.  All rights reserved.
X.\"
X.\" Redistribution and use in source and binary forms, with or without
X.\" modification, are permitted provided that the following conditions
X.\" are met:
X.\" 1. Redistributions of source code must retain the above copyright
X.\"    notice, this list of conditions and the following disclaimer.
X.\" 2. Redistributions in binary form must reproduce the above copyright
X.\"    notice, this list of conditions and the following disclaimer in the
X.\"    documentation and/or other materials provided with the distribution.
X.\" 3. All advertising materials mentioning features or use of this software
X.\"    must display the following acknowledgement:
X.\"	This product includes software developed by the University of
X.\"	California, Berkeley and its contributors.
X.\" 4. Neither the name of the University nor the names of its contributors
X.\"    may be used to endorse or promote products derived from this software
X.\"    without specific prior written permission.
X.\"
X.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X.\" SUCH DAMAGE.
X.\"
X.\"	from: @(#)iostat.8	8.1 (Berkeley) 6/6/93
X.\"
X.Dd Jan 18, 1996
X.Dt IOSTAT 8
X.Os NetBSD 1.1
X.Sh NAME
X.Nm iostat
X.Nd report
X.Tn I/O
Xstatistics
X.Sh SYNOPSIS
X.Nm iostat
X.Op Fl CdDIT
X.Op Fl c Ar count
X.Op Fl M Ar core
X.Op Fl N Ar system
X.Op Fl w Ar wait
X.Op Ar drives
X.Sh DESCRIPTION
X.Nm Iostat
Xdisplays kernel
X.Tn I/O
Xstatistics on terminal, disk and cpu operations.  By default,
X.Nm iostat
Xdisplays one line of statistics averaged over the machine's run time.
XThe use of 
X.Fl c
Xpresents successive lines averaged over the
X.Ar wait
Xperiod.
XThe
X.Fl I
Xoption causes
X.Nm iostat
Xto print raw, unaveraged values.
X.Pp
XThe options are as follows:
X.Bl -tag -width flag
X.It Fl c
XRepeat the display
X.Ar count
Xtimes.
XUnless the
X.Fl I
Xflag is in effect, the first display is for the time since a reboot and
Xeach subsequent report is for the time period since the last display.
XIf no
X.Ar wait
Xinterval is specified, the default is 1 second.
X.It Fl C
XShow cpu statistics.  This is enabled by default unless the
X.Fl d, 
X.Fl D,
Xor 
X.Fl T
Xflags are used.
X.It Fl d
XShow disk statistics.  This is the default.  Displays kilobytes per
Xtransfer, number of transfers, and megabytes transfered.  Use of this
Xflag disables display of cpu and tty statistics.
X.It Fl D
XShow alternate disk statistics.  Displays kilobytes transfered, number of 
Xtransfers, and time spent in transfers.  Use of this flag disables the
Xdefault display.
X.It Fl I
XShow the running total values, rather than an average.
X.It Fl M
XExtract values associated with the name list from the specified core
Xinstead of the default
X.Dq Pa /dev/mem .
X.It Fl N
XExtract the name list from the specified system instead of the default
X.Dq Pa /netbsd .
X.It Fl T
XShow tty statistics.  This is enabled by default unless the
X.Fl C, 
X.Fl d,
Xor 
X.Fl D
Xflags are used.
X.It Fl w
XPause
X.Ar wait
Xseconds between each display.
XIf no repeat
X.Ar count
Xis specified, the default is infinity.
X.El
X.Pp
X.Nm Iostat
Xdisplays its information in the following format:
X.Bl -tag -width flag
X.It tty
X.Bl -tag -width indent -compact
X.It tin
Xcharacters read from terminals
X.It tout
Xcharacters written to terminals
X.El
X.It disks
XDisk operations. 
XThe header of the field is the disk name and unit number.
XIf more than four disk drives are configured in the system,
X.Nm iostat
Xdisplays only the first four drives.
XTo force
X.Nm iostat
Xto display specific drives, their names may be supplied on the command
Xline.
X.Pp
X.Bl -tag -width indent -compact
X.It K/t
XKilobytes transferred per disk transfer
X.It t/s
Xtransfers per second
X.It Mb/s
XMegabytes transferred per second
X.Pp
X.El
XThe alternate display format, (selected with
X.Fl D
X), presents the following values.
X.Bl -tag -width indent -compact
X.It Kb
XKilobytes transferred
X.It xfr
XDisk transfers
X.It time
XSeconds spent in disk activity
X.El
X.It cpu
X.Bl -tag -width indent -compact
X.It \&us
X% of cpu time in user mode
X.It \&ni
X% of cpu time in user mode running niced processes
X.It \&sy
X% of cpu time in system mode
X.It \&id
X% of cpu time in idle mode
X.El
X.El
X.Sh FILES
X.Bl -tag -width /dev/mem -compact
X.It Pa /netbsd
XDefault kernel namelist.
X.It Pa /dev/mem
XDefault memory file.
X.El
X.Sh SEE ALSO
X.Xr fstat 1 ,
X.Xr netstat 1 ,
X.Xr nfsstat 1 ,
X.Xr \&ps 1 ,
X.Xr systat 1 ,
X.Xr pstat 8 ,
X.Xr vmstat 8
X.Pp
XThe sections starting with ``Interpreting system activity'' in
X.%T "Installing and Operating 4.3BSD" .
END-of-iostat.8
echo x - iostat.c
sed 's/^X//' >iostat.c << 'END-of-iostat.c'
X/*	$NetBSD: iostat.c,v 1.8 1995/11/28 20:16:31 thorpej Exp $	*/
X
X/*
X * Copyright (c) 1996 John M. Vinopal (banshee@resort.com)
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *      This product includes software developed for the NetBSD Project
X *      by John M. Vinopal.
X * 4. The name of the author may not be used to endorse or promote products
X *    derived from this software without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
X * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
X * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
X * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
X * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
X * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X/*-
X * Copyright (c) 1986, 1991, 1993
X *      The Regents of the University of California.  All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *      This product includes software developed by the University of
X *      California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#ifndef lint
Xstatic char copyright[] =
X"@(#) Copyright (c) 1986, 1991, 1993\n\
X        The Regents of the University of California.  All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
X#if 0
Xstatic char sccsid[] = "@(#)iostat.c    8.2 (Berkeley) 1/26/94";
X#else
Xstatic char *rcsid = "$NetBSD: iostat.c,v 1.8 1995/11/28 20:16:31 thorpej Exp $"
X;
X#endif
X#endif /* not lint */
X
X#include <sys/dkstat.h>
X#include <sys/time.h>
X
X#include <err.h>
X#include <ctype.h>
X#include <signal.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X
X#include "dkstats.h"
X
X/* Defined in dkstats.c */
Xextern struct _disk cur;
Xextern int  	dk_ndrive;
X
Xchar	*nlistf = NULL;
Xchar	*memf = NULL;
X
Xint		hz, reps, interval;
Xstatic int	todo = 0;
X
X#define ISSET(x, a)	((x) & (a))
X#define SHOW_CPU	0x0001
X#define SHOW_TTY	0x0002
X#define SHOW_STATS_1	0x0004
X#define SHOW_STATS_2	0x0008
X#define SHOW_TOTALS	0x0080
X
Xstatic void cpustats __P((void));
Xstatic void disk_stats __P((double));
Xstatic void disk_stats2 __P((double));
Xstatic void header __P((int));
Xstatic void usage __P((void));
Xstatic void display __P((void));
Xstatic void selectdrives __P((int, char **));
X
Xvoid dkswap __P((void));
Xvoid dkreadstats __P((void));
Xint dkinit __P((int));
X
Xint
Xmain(argc, argv)
X	int argc;
X	char *argv[];
X{
X	int ch, hdrcnt;
X	struct timeval	tv;
X
X	while ((ch = getopt(argc, argv, "Cc:dDIM:N:Tw:")) != EOF)
X		switch(ch) {
X		case 'c':
X			if ((reps = atoi(optarg)) <= 0)
X				errx(1, "repetition count <= 0.");
X			break;
X		case 'C':
X			todo |= SHOW_CPU;
X			break;
X		case 'd':
X			todo |= SHOW_STATS_1;
X			break;
X		case 'D':
X			todo |= SHOW_STATS_2;
X			break;
X		case 'I':
X			todo |= SHOW_TOTALS;
X			break;
X		case 'M':
X			memf = optarg;
X			break;
X		case 'N':
X			nlistf = optarg;
X			break;
X		case 'T':
X			todo |= SHOW_TTY;
X			break;
X		case 'w':
X			if ((interval = atoi(optarg)) <= 0)
X				errx(1, "interval <= 0.");
X			break;
X		case '?':
X		default:
X			usage();
X		}
X	argc -= optind;
X	argv += optind;
X
X	if (!ISSET(todo, SHOW_CPU | SHOW_TTY | SHOW_STATS_1 | SHOW_STATS_2))
X		todo |= SHOW_CPU | SHOW_TTY | SHOW_STATS_1;
X
X	/*
X	 * Discard setgid privileges if not the running kernel so that bad
X	 * guys can't print interesting stuff from kernel memory.
X	 */
X	if (nlistf != NULL || memf != NULL)
X		setgid(getgid());
X
X	dkinit(0);
X	dkreadstats();
X	selectdrives(argc, argv);
X
X	tv.tv_sec = interval;
X	tv.tv_usec = 0;
X
X	/* print a new header on sigcont */
X	(void)signal(SIGCONT, header);
X
X	for (hdrcnt = 1;;) {
X		if (!--hdrcnt) {
X			header(0);
X			hdrcnt = 20;
X		}
X
X		if (!ISSET(todo, SHOW_TOTALS))
X			dkswap();
X		display();
X
X		if (reps >= 0 && --reps <= 0)
X			break;
X		select(0, NULL, NULL, NULL, &tv);
X		dkreadstats();
X	}
X	exit(0);
X}
X
Xstatic void
Xheader(signo)
X	int signo;
X{
X	register int i;
X
X	/* Main Headers. */
X	if (ISSET(todo, SHOW_TTY))
X		(void)printf("      tty");
X
X	if (ISSET(todo, SHOW_STATS_1))
X	for (i = 0; i < dk_ndrive; i++)
X		if (cur.dk_select[i])
X			(void)printf("            %3.3s ", cur.dk_name[i]);
X
X	if (ISSET(todo, SHOW_STATS_2))
X	for (i = 0; i < dk_ndrive; i++)
X		if (cur.dk_select[i])
X			(void)printf("           %3.3s ", cur.dk_name[i]);
X
X	if (ISSET(todo, SHOW_CPU))
X		(void)printf("            cpu");
X	printf("\n");
X
X	/* Sub-Headers. */
X	if (ISSET(todo, SHOW_TTY))
X		printf(" tin tout");
X
X	if (ISSET(todo, SHOW_STATS_1))
X	for (i = 0; i < dk_ndrive; i++)
X		if (cur.dk_select[i])
X			if (ISSET(todo, SHOW_TOTALS))
X				(void)printf("   K/t xfr Mb   ");
X			else
X				(void)printf("   K/t t/s Mb/s ");
X
X	if (ISSET(todo, SHOW_STATS_2))
X	for (i = 0; i < dk_ndrive; i++)
X		if (cur.dk_select[i])
X			(void)printf("   Kb xfr time ");
X
X	if (ISSET(todo, SHOW_CPU))
X		(void)printf(" us ni sy in id");
X	printf("\n");
X}
X
Xstatic void
Xdisk_stats(etime)
Xdouble etime;
X{
X	register int dn;
X	double atime, mbps;
X
X	for (dn = 0; dn < dk_ndrive; ++dn) {
X		if (!cur.dk_select[dn])
X			continue;
X
X		/* average Kbytes per transfer. */
X		if (cur.dk_xfer[dn])
X			mbps = (cur.dk_bytes[dn] / (1024.0)) / cur.dk_xfer[dn];
X		else
X			mbps = 0.0;
X		(void)printf(" %5.2f", mbps); 
X
X		/* average transfers per second. */
X		(void)printf(" %3.0f", cur.dk_xfer[dn] / etime);
X
X		/* time busy in disk activity */
X		atime = (double)cur.dk_time[dn].tv_sec +
X			((double)cur.dk_time[dn].tv_usec / (double)1000000);
X
X		/* Megabytes per second. */
X		if (atime != 0.0)
X			mbps = cur.dk_bytes[dn] / (double)(1024 * 1024);
X		else 
X			mbps = 0;
X		(void)printf(" %4.2f ", mbps / etime);
X	}
X}
X
Xstatic void
Xdisk_stats2(etime)
Xdouble etime;
X{
X	register int dn;
X	double atime;
X
X	for (dn = 0; dn < dk_ndrive; ++dn) {
X		if (!cur.dk_select[dn])
X			continue;
X
X		/* average kbytes per second. */
X		(void)printf(" %4.0f", cur.dk_bytes[dn] / (1024.0) / etime);
X
X		/* average transfers per second. */
X		(void)printf(" %3.0f", cur.dk_xfer[dn] / etime);
X
X		/* average time busy in disk activity. */
X		atime = (double)cur.dk_time[dn].tv_sec +
X			((double)cur.dk_time[dn].tv_usec / (double)1000000);
X		(void)printf(" %4.2f ", atime / etime);
X	}
X}
X
Xstatic void
Xcpustats()
X{
X	register int state;
X	double time;
X
X	time = 0;
X	for (state = 0; state < CPUSTATES; ++state)
X		time += cur.cp_time[state];
X	if (!time)
X		time = 1.0;
X	/* States are generally never 100% and can use %3.0f. */
X	for (state = 0; state < CPUSTATES; ++state)
X		printf("%3.0f", 100. * cur.cp_time[state] / time);
X}
X
Xstatic void
Xusage()
X{
X	(void)fprintf(stderr,
X"usage: iostat [-CdDIT] [-c count] [-M core] [-N system] [-w wait] [drives]\n");
X	exit(1);
X}
X
Xstatic void
Xdisplay()
X{
X	int	i;
X	double	etime;
X
X	/* Sum up the elapsed ticks. */
X	etime = 0.0;
X	for (i = 0; i < CPUSTATES; i++) {
X		etime += cur.cp_time[i];
X	}
X	if (etime == 0.0)
X		etime = 1.0;
X	/* Convert to seconds. */
X	etime /= (float)hz;
X
X	/* If we're showing totals only, then don't divide by the
X	 * system time.
X	 */
X	if (ISSET(todo, SHOW_TOTALS))
X		etime = 1.0;
X
X	if (ISSET(todo, SHOW_TTY))
X		printf("%4.0f %4.0f", cur.tk_nin / etime, cur.tk_nout / etime);
X	
X	if (ISSET(todo, SHOW_STATS_1))
X		disk_stats(etime);
X
X	if (ISSET(todo, SHOW_STATS_2))
X		disk_stats2(etime);
X
X	if (ISSET(todo, SHOW_CPU))
X		cpustats();
X
X	(void)printf("\n");
X	(void)fflush(stdout);
X}
X
Xstatic void
Xselectdrives(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	int	i, ndrives;
X
X	/*
X	 * Choose drives to be displayed.  Priority goes to (in order) drives
X	 * supplied as arguments and default drives.  If everything isn't
X	 * filled in and there are drives not taken care of, display the first
X	 * few that fit.
X	 *
X	 * The backward compatibility #ifdefs permit the syntax:
X	 *	iostat [ drives ] [ interval [ count ] ]
X	 */
X#define	BACKWARD_COMPATIBILITY
X	for (ndrives = 0; *argv; ++argv) {
X#ifdef	BACKWARD_COMPATIBILITY
X		if (isdigit(**argv))
X			break;
X#endif
X		for (i = 0; i < dk_ndrive; i++) {
X			if (strcmp(cur.dk_name[i], *argv))
X				continue;
X			cur.dk_select[i] = 1;
X			++ndrives;
X		}
X	}
X#ifdef	BACKWARD_COMPATIBILITY
X	if (*argv) {
X		interval = atoi(*argv);
X		if (*++argv)
X			reps = atoi(*argv);
X	}
X#endif
X
X	if (interval) {
X		if (!reps)
X			reps = -1;
X	} else
X		if (reps)
X			interval = 1;
X
X	/* Pick up to 4 drives if none specified. */
X	if (ndrives == 0)
X		for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
X			if (cur.dk_select[i])
X				continue;
X			cur.dk_select[i] = 1;
X			++ndrives;
X		}
X}
END-of-iostat.c
exit

>Audit-Trail:
>Unformatted: