Subject: tape drive instrumentation, again
To: None <tech-kern@netbsd.org>
From: Brett Lymn <blymn@baesystems.com.au>
List: tech-kern
Date: 03/12/2006 21:48:25
Folks,

This is the next iteration of the tape/nfs statistics.  I have made
the disk_* functions wrappers around the iostat_* equivalents.  This
minimises the code changes.  I have also done the same with
disk_find(), this is a wrapper around the iostat_find() function but
it returns the struct disk *.  I also change the sysctl name from
drivenames to iostatnames, I have left the nfs names in the list
because I do think they could be useful.

As before, a tar file containing the extra files plus the patch are on
ftp.netbsd.org in /pub/NetBSD/misc/blymn/iostat_patch.tar.gz.  Below
is the patch from the tar ball so people can review it.

========================================================================

Index: sys/arch/acorn32/mainbus/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/acorn32/mainbus/fd.c,v
retrieving revision 1.24
diff -u -r1.24 fd.c
--- sys/arch/acorn32/mainbus/fd.c	23 Feb 2006 05:37:46 -0000	1.24
+++ sys/arch/acorn32/mainbus/fd.c	12 Mar 2006 10:19:40 -0000
@@ -399,7 +399,7 @@
 
 	printf("\n");
 
-	callout_init(&fdc->sc_timo_ch); 
+	callout_init(&fdc->sc_timo_ch);
 	callout_init(&fdc->sc_intr_ch);
 
 	fdc->sc_ih = intr_claim(pa->pa_irq, IPL_BIO, "fdc",
@@ -1030,7 +1030,7 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
+		fd->sc_dk.dk_stats->seek++;
 		disk_busy(&fd->sc_dk);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
@@ -1055,7 +1055,7 @@
 		 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
 		 if (block != fd->sc_blkno) {
 			 printf("fdcintr: block %" PRId64
-			     " != blkno %" PRId64 "\n",	
+			     " != blkno %" PRId64 "\n",
 				block, fd->sc_blkno);
 #ifdef DDB
 			 Debugger();
@@ -1455,11 +1455,11 @@
 			return EINVAL;
 		}
 
-		fd_formb = malloc(sizeof(struct ne7_fd_formb), 
+		fd_formb = malloc(sizeof(struct ne7_fd_formb),
 		    M_TEMP, M_NOWAIT);
 		if(fd_formb == 0)
 			return ENOMEM;
-		    
+
 
 		fd_formb->head = form_cmd->head;
 		fd_formb->cyl = form_cmd->cylinder;
@@ -1550,7 +1550,7 @@
 			break;
 	}
 	splx(s);
-       
+
 	if (rv == EWOULDBLOCK) {
 		/* timed out */
 		rv = EIO;
@@ -1590,7 +1590,7 @@
 	type = FDTYPE(dev) - 1;
 	if (type < 0) type = 0;
 	floppysize = fd_types[type].size << (fd_types[type].secsize + 7);
-        
+
 	if (md->md_size < floppysize) {
 		printf("Memory disc is not big enough for floppy image\n");
 		return(EINVAL);
@@ -1603,7 +1603,7 @@
 /* obtain a buffer */
 
 	bp = geteblk(fd_types[type].sectrac * DEV_BSIZE);
-    
+
 /* request no partition relocation by driver on I/O operations */
 
 	bp->b_dev = dev;
@@ -1611,7 +1611,7 @@
 	s = spl0();
 
 	if (fdopen(bp->b_dev, 0, 0, curlwp) != 0) {
-		brelse(bp);		
+		brelse(bp);
 		printf("Cannot open floppy device\n");
 			return(EINVAL);
 	}
@@ -1630,14 +1630,14 @@
 
 		if (biowait(bp))
 			panic("Cannot load floppy image");
-                                                 
+
 		memcpy((caddr_t)md->md_addr + loop * fd_types[type].sectrac
 		    * DEV_BSIZE, (caddr_t)bp->b_data,
 		    fd_types[type].sectrac * DEV_BSIZE);
 	}
 	printf("\x08\x08\x08\x08\x08\x08%4dK done\n",
 	    loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
-        
+
 	fdclose(bp->b_dev, 0, 0, curlwp);
 
 	brelse(bp);
Index: sys/arch/arc/jazz/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/jazz/fd.c,v
retrieving revision 1.25
diff -u -r1.25 fd.c
--- sys/arch/arc/jazz/fd.c	23 Feb 2006 05:37:46 -0000	1.25
+++ sys/arch/arc/jazz/fd.c	12 Mar 2006 10:19:41 -0000
@@ -831,7 +831,7 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
+		fd->sc_dk.stats->seek++;
 		disk_busy(&fd->sc_dk);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
Index: sys/arch/atari/dev/hdfd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/atari/dev/hdfd.c,v
retrieving revision 1.49
diff -u -r1.49 hdfd.c
--- sys/arch/atari/dev/hdfd.c	23 Feb 2006 05:37:46 -0000	1.49
+++ sys/arch/atari/dev/hdfd.c	12 Mar 2006 10:19:41 -0000
@@ -1050,7 +1050,7 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
+		fd->sc_dk.dk_stats->seek++;
 		disk_busy(&fd->sc_dk);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
@@ -1501,7 +1501,7 @@
 			fd_formb->fd_formb_secno(i) = il[i+1];
 			fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize;
 		}
-		
+
 		error = fdformat(dev, fd_formb, l->l_proc);
 		free(fd_formb, M_TEMP);
 		return error;
@@ -1569,7 +1569,7 @@
 			break;
 	}
 	splx(s);
-       
+
 	if (rv == EWOULDBLOCK) {
 		/* timed out */
 		rv = EIO;
Index: sys/arch/hp300/dev/rd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hp300/dev/rd.c,v
retrieving revision 1.71
diff -u -r1.71 rd.c
--- sys/arch/hp300/dev/rd.c	25 Feb 2006 02:28:56 -0000	1.71
+++ sys/arch/hp300/dev/rd.c	12 Mar 2006 10:19:41 -0000
@@ -836,7 +836,7 @@
 
 		/* Instrumentation. */
 		disk_busy(&rs->sc_dkdev);
-		rs->sc_dkdev.dk_seek++;
+		rs->sc_dkdev->dk_stats->seek++;
 
 #ifdef DEBUG
 		if (rddebug & RDB_IO)
Index: sys/arch/pdp10/dev/hp.c
===================================================================
RCS file: /cvsroot/src/sys/arch/pdp10/dev/hp.c,v
retrieving revision 1.4
diff -u -r1.4 hp.c
--- sys/arch/pdp10/dev/hp.c	11 Dec 2005 12:18:34 -0000	1.4
+++ sys/arch/pdp10/dev/hp.c	12 Mar 2006 10:19:41 -0000
@@ -13,7 +13,7 @@
  *    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 at Ludd, University of 
+ *      This product includes software developed at Ludd, University of
  *      Lule}, Sweden and its contributors.
  * 4. The name of the author may not be used to endorse or promote products
  *    derived from this software without specific prior written permission
@@ -265,7 +265,7 @@
 	 * Collect statistics.
 	 */
 	disk_busy(&sc->sc_disk);
-	sc->sc_disk.dk_seek++;
+	sc->sc_disk.dk_stats->seek++;
 
 	bn = bp->b_rawblkno;
 	if (bn) {
@@ -417,7 +417,7 @@
 	case -1:
 		HP_WCSR(HP_ER1, 0);
 		goto hper2;
-		
+
 	case HPER1_DCK: /* Corrected? data read. Just notice. */
 panic("hpfinish");
 #if 0
Index: sys/arch/sparc/dev/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/dev/fd.c,v
retrieving revision 1.125
diff -u -r1.125 fd.c
--- sys/arch/sparc/dev/fd.c	23 Feb 2006 05:37:48 -0000	1.125
+++ sys/arch/sparc/dev/fd.c	12 Mar 2006 10:19:42 -0000
@@ -1490,7 +1490,7 @@
 		fdc->sc_state = SEEKWAIT;
 		fdc->sc_nstat = 0;
 
-		fd->sc_dk.dk_seek++;
+		fd->sc_dk.dk_stats->seek++;
 
 		disk_busy(&fd->sc_dk);
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
Index: sys/arch/vax/mba/hp.c
===================================================================
RCS file: /cvsroot/src/sys/arch/vax/mba/hp.c,v
retrieving revision 1.39
diff -u -r1.39 hp.c
--- sys/arch/vax/mba/hp.c	11 Dec 2005 12:19:35 -0000	1.39
+++ sys/arch/vax/mba/hp.c	12 Mar 2006 10:19:42 -0000
@@ -13,7 +13,7 @@
  *    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 at Ludd, University of 
+ *      This product includes software developed at Ludd, University of
  *      Lule}, Sweden and its contributors.
  * 4. The name of the author may not be used to endorse or promote products
  *    derived from this software without specific prior written permission
@@ -235,7 +235,7 @@
 	 * Collect statistics.
 	 */
 	disk_busy(&sc->sc_disk);
-	sc->sc_disk.dk_seek++;
+	sc->sc_disk->dk_stats.seek++;
 
 	bn = bp->b_rawblkno;
 	if (bn) {
@@ -380,7 +380,7 @@
 	case -1:
 		HP_WCSR(HP_ER1, 0);
 		goto hper2;
-		
+
 	case HPER1_DCK: /* Corrected? data read. Just notice. */
 		bc = bus_space_read_4(md->md_mba->sc_iot,
 		    md->md_mba->sc_ioh, MBA_BC);
Index: sys/arch/x68k/dev/fd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/dev/fd.c,v
retrieving revision 1.68
diff -u -r1.68 fd.c
--- sys/arch/x68k/dev/fd.c	23 Feb 2006 05:37:48 -0000	1.68
+++ sys/arch/x68k/dev/fd.c	12 Mar 2006 10:19:42 -0000
@@ -420,7 +420,7 @@
 
 	printf("\n");
 
-	callout_init(&fdc->sc_timo_ch); 
+	callout_init(&fdc->sc_timo_ch);
 	callout_init(&fdc->sc_intr_ch);
 
 	/* Re-map the I/O space. */
@@ -1109,7 +1109,7 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
+		fd->sc_dk.dk_stats->seek++;
 		disk_busy(&fd->sc_dk);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
@@ -1183,7 +1183,7 @@
 			 head, sec, nblks, fd->sc_skip));
 		DPRINTF(("C H R N: %d %d %d %d\n", fd->sc_cylin, head, sec,
 			 type->secsize));
-			 
+
 		if (fd->sc_part != SEC_P11)
 			goto docopy;
 
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.763
diff -u -r1.763 files
--- sys/conf/files	1 Mar 2006 22:12:09 -0000	1.763
+++ sys/conf/files	12 Mar 2006 10:19:43 -0000
@@ -1242,6 +1242,7 @@
 file	kern/subr_bufq.c
 file	kern/subr_devsw.c
 file	kern/subr_disk.c
+file	kern/subr_iostat.c
 file	kern/subr_evcnt.c
 file	kern/subr_extent.c
 file	kern/subr_log.c
Index: sys/dev/cgd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/cgd.c,v
retrieving revision 1.34
diff -u -r1.34 cgd.c
--- sys/dev/cgd.c	4 Jan 2006 17:16:35 -0000	1.34
+++ sys/dev/cgd.c	12 Mar 2006 10:19:43 -0000
@@ -323,7 +323,8 @@
 		newaddr = cgd_getdata(dksc, bp->b_bcount);
 		if (!newaddr) {
 			putiobuf(nbp);
-			disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
+			disk_unbusy(&dksc->sc_dkdev, 0,
+				    (bp->b_flags & B_READ));
 			return -1;
 		}
 		cgd_cipher(cs, newaddr, addr, bp->b_bcount, bn,
Index: sys/dev/gpib/rd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/gpib/rd.c,v
retrieving revision 1.8
diff -u -r1.8 rd.c
--- sys/dev/gpib/rd.c	25 Feb 2006 02:28:58 -0000	1.8
+++ sys/dev/gpib/rd.c	12 Mar 2006 10:19:43 -0000
@@ -785,7 +785,7 @@
 	    sizeof(sc->sc_ioc)-1) == sizeof(sc->sc_ioc)-1) {
 		/* Instrumentation. */
 		disk_busy(&sc->sc_dk);
-		sc->sc_dk.dk_seek++;
+		sc->sc_dk.dk_stats->seek++;
 		gpibawait(sc->sc_ic);
 		return;
 	}
Index: sys/dev/isa/fd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/fd.c,v
retrieving revision 1.64
diff -u -r1.64 fd.c
--- sys/dev/isa/fd.c	6 Jan 2006 09:21:44 -0000	1.64
+++ sys/dev/isa/fd.c	12 Mar 2006 10:19:44 -0000
@@ -1042,7 +1042,7 @@
 		fd->sc_cylin = -1;
 		fdc->sc_state = SEEKWAIT;
 
-		fd->sc_dk.dk_seek++;
+		fd->sc_dk.dk_stats->seek++;
 		disk_busy(&fd->sc_dk);
 
 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
Index: sys/dev/scsipi/st.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/st.c,v
retrieving revision 1.186
diff -u -r1.186 st.c
--- sys/dev/scsipi/st.c	11 Dec 2005 12:23:51 -0000	1.186
+++ sys/dev/scsipi/st.c	12 Mar 2006 10:19:44 -0000
@@ -76,7 +76,7 @@
 #include <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/vnode.h>
-#include <sys/tape.h>
+#include <sys/iostat.h>
 #include <sys/sysctl.h>
 
 #include <dev/scsipi/scsi_spc.h>
@@ -107,9 +107,6 @@
 #define		ST_MOUNT_DELAY		0
 #endif
 
-struct tape *
-drive_attach(char *name);
-
 static dev_type_open(stopen);
 static dev_type_close(stclose);
 static dev_type_read(stread);
@@ -352,14 +349,6 @@
 	stdone
 };
 
-/*
- * A global list of all tape drives attached to the system.  May grow or
- * shrink over time.
- */
-struct  tapelist_head tapelist = TAILQ_HEAD_INITIALIZER(tapelist);
-int     tape_count = 0;             /* number of drives in global tapelist */
-struct simplelock tapelist_slock = SIMPLELOCK_INITIALIZER;
-
 #if	defined(ST_ENABLE_EARLYWARN)
 #define	ST_INIT_FLAGS	ST_EARLYWARN
 #else
@@ -423,8 +412,9 @@
 		    (st->flags & ST_READONLY) ? "protected" : "enabled");
 	}
 
-	st->stats = drive_attach(st->sc_dev.dv_xname);
-	
+	st->stats = iostat_alloc(IOSTAT_TAPE);
+	st->stats->name = st->sc_dev.dv_xname;
+
 #if NRND > 0
 	rnd_attach_source(&st->rnd_source, st->sc_dev.dv_xname,
 			  RND_TYPE_TAPE, 0);
@@ -480,16 +470,7 @@
 	vdevgone(bmaj, mn, mn+STNMINOR-1, VBLK);
 	vdevgone(cmaj, mn, mn+STNMINOR-1, VCHR);
 
-	if (tape_count == 0) {
-		printf("%s detach: tape_count already zero\n",
-		       st->sc_dev.dv_xname);
-	} else {
-		simple_lock(&tapelist_slock);
-		TAILQ_REMOVE(&tapelist, st->stats, link);
-		tape_count--;
-		simple_unlock(&tapelist_slock);
-		free(st->stats, M_DEVBUF);
-	}
+	iostat_free(st->stats);
 
 #if NRND > 0
 	/* Unhook the entropy source. */
@@ -1187,7 +1168,7 @@
 	struct buf *bp;
 	struct scsi_rw_tape cmd;
 	struct scsipi_xfer *xs;
-	int flags, error, s;
+	int flags, error;
 
 	SC_DEBUG(periph, SCSIPI_DB2, ("ststart "));
 	/*
@@ -1224,12 +1205,8 @@
 		if ((bp = BUFQ_PEEK(st->buf_queue)) == NULL)
 			return;
 
-		if (st->stats->busy++ == 0) {
-			s = splclock();
-			st->stats->timestamp = mono_time;
-			splx(s);
-		}
-		
+		iostat_busy(st->stats);
+
 		/*
 		 * only FIXEDBLOCK devices have pending I/O or space operations.
 		 */
@@ -1356,8 +1333,6 @@
 {
 	struct st_softc *st = (void *)xs->xs_periph->periph_dev;
 	struct buf *bp = xs->bp;
-	int s;
-	struct timeval st_time, diff_time;
 
 	if (bp) {
 		bp->b_error = error;
@@ -1370,32 +1345,10 @@
 		else
 			st->flags &= ~ST_WRITTEN;
 
-		if (st->stats->busy-- == 0) {
-			  /* this is not really fatal so we don't panic */
-			printf("%s: busy < 0, Oops.\n", st->stats->name);
-			st->stats->busy = 0;
-		} else {
-			s = splclock();
-			st_time = mono_time;
-			splx(s);
-
-			timersub(&st_time, &st->stats->timestamp, &diff_time);
-			timeradd(&st->stats->time, &diff_time,
-				 &st->stats->time);
+		iostat_unbusy(st->stats, bp->b_bcount,
+			     ((bp->b_flags & B_READ) == B_READ));
+
 
-			st->stats->timestamp = st_time;
-			if (bp->b_bcount > 0) {
-				if ((bp->b_flags & B_READ) == B_WRITE) {
-					st->stats->wbytes += bp->b_bcount;
-					st->stats->wxfer++;
-				} else {
-					st->stats->rbytes += bp->b_bcount;
-					st->stats->rxfer++;
-				}
-			}
-		}
-		
-			
 #if NRND > 0
 		rnd_add_uint32(&st->rnd_source, bp->b_blkno);
 #endif
@@ -2453,156 +2406,3 @@
 	/* Not implemented. */
 	return (ENXIO);
 }
-
-int
-sysctl_hw_tapenames(SYSCTLFN_ARGS)
-{
-	char bf[TAPENAMELEN + 1];
-	char *where = oldp;
-	struct tape *tapep;
-	size_t needed, left, slen;
-	int error, first;
-
-	if (newp != NULL)
-		return (EPERM);
-	if (namelen != 0)
-		return (EINVAL);
-
-	first = 1;
-	error = 0;
-	needed = 0;
-	left = *oldlenp;
-
-	simple_lock(&tapelist_slock);
-	for (tapep = TAILQ_FIRST(&tapelist); tapep != NULL;
-	    tapep = TAILQ_NEXT(tapep, link)) {
-		if (where == NULL)
-			needed += strlen(tapep->name) + 1;
-		else {
-			memset(bf, 0, sizeof(bf));
-			if (first) {
-				strncpy(bf, tapep->name, sizeof(bf));
-				first = 0;
-			} else {
-				bf[0] = ' ';
-				strncpy(bf + 1, tapep->name, sizeof(bf) - 1);
-			}
-			bf[TAPENAMELEN] = '\0';
-			slen = strlen(bf);
-			if (left < slen + 1)
-				break;
-			/* +1 to copy out the trailing NUL byte */
-			error = copyout(bf, where, slen + 1);
-			if (error)
-				break;
-			where += slen;
-			needed += slen;
-			left -= slen;
-		}
-	}
-	simple_unlock(&tapelist_slock);
-	*oldlenp = needed;
-	return (error);
-}
-
-int
-sysctl_hw_tapestats(SYSCTLFN_ARGS)
-{
-	struct tape_sysctl stape;
-	struct tape *tapep;
-	char *where = oldp;
-	size_t tocopy, left;
-	int error;
-
-	if (newp != NULL)
-		return (EPERM);
-
-	tocopy = name[0];
-
-	if (where == NULL) {
-		*oldlenp = tape_count * tocopy;
-		return (0);
-	}
-
-	error = 0;
-	left = *oldlenp;
-	memset(&stape, 0, sizeof(stape));
-	*oldlenp = 0;
-
-	simple_lock(&tapelist_slock);
-	TAILQ_FOREACH(tapep, &tapelist, link) {
-		if (left < tocopy)
-			break;
-		strncpy(stape.name, tapep->name, sizeof(stape.name));
-		stape.xfer = tapep->rxfer + tapep->wxfer;
-		stape.rxfer = tapep->rxfer;
-		stape.wxfer = tapep->wxfer;
-		stape.bytes = tapep->rbytes + tapep->wbytes;
-		stape.rbytes = tapep->rbytes;
-		stape.wbytes = tapep->wbytes;
-		stape.attachtime_sec = tapep->attachtime.tv_sec;
-		stape.attachtime_usec = tapep->attachtime.tv_usec;
-		stape.timestamp_sec = tapep->timestamp.tv_sec;
-		stape.timestamp_usec = tapep->timestamp.tv_usec;
-		stape.time_sec = tapep->time.tv_sec;
-		stape.time_usec = tapep->time.tv_usec;
-		stape.busy = tapep->busy;
-
-		error = copyout(&stape, where, min(tocopy, sizeof(stape)));
-		if (error)
-			break;
-		where += tocopy;
-		*oldlenp += tocopy;
-		left -= tocopy;
-	}
-	simple_unlock(&tapelist_slock);
-	return (error);
-}
-
-struct tape *
-drive_attach(char *name) 
-{
-	struct tape *stats;
-	int s;
-	
-	/* Allocate and initialise statistics */
-	stats = (struct tape *) malloc(sizeof(struct tape), M_DEVBUF,
-					   M_WAITOK);
-	stats->rxfer = stats->wxfer = stats->rbytes = 0;
-	stats->wbytes = stats->busy = 0;
-
-	/*
-	 * Set the attached timestamp.
-	 */
-	s = splclock();
-	stats->attachtime = mono_time;
-	splx(s);
-
-	  /* and clear the utilisation time */
-	timerclear(&stats->time);
-
-	  /* link the tape drive to the tapelist */
-	simple_lock(&tapelist_slock);
-	TAILQ_INSERT_TAIL(&tapelist, stats, link);
-	tape_count++;
-	simple_unlock(&tapelist_slock);
-	stats->name = name;
-
-	return stats;
-}
-
-SYSCTL_SETUP(sysctl_tape_stats_setup, "sysctl tape stats setup")
-{
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_STRING, "tapenames",
-		       SYSCTL_DESCR("List of tape devices present"),
-		       sysctl_hw_tapenames, 0, NULL, 0,
-		       CTL_HW, HW_TAPENAMES, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_STRUCT, "tapestats",
-		       SYSCTL_DESCR("Statistics on tape drive operation"),
-		       sysctl_hw_tapestats, 0, NULL, 0,
-		       CTL_HW, HW_TAPESTATS, CTL_EOL);
-}
Index: sys/dev/scsipi/stvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/stvar.h,v
retrieving revision 1.16
diff -u -r1.16 stvar.h
--- sys/dev/scsipi/stvar.h	11 Dec 2005 12:23:51 -0000	1.16
+++ sys/dev/scsipi/stvar.h	12 Mar 2006 10:19:44 -0000
@@ -150,9 +150,9 @@
 					/* operations */
 	struct callout sc_callout;	/* restarting the queue after */
 					/* transient error */
-	
-	struct tape *stats;		/* statistics for the drive */
-	
+
+	struct io_stats *stats;		/* statistics for the drive */
+
 #if NRND > 0
 	rndsource_element_t	rnd_source;
 #endif
Index: sys/kern/init_sysctl.c
===================================================================
RCS file: /cvsroot/src/sys/kern/init_sysctl.c,v
retrieving revision 1.63
diff -u -r1.63 init_sysctl.c
--- sys/kern/init_sysctl.c	1 Mar 2006 12:38:21 -0000	1.63
+++ sys/kern/init_sysctl.c	12 Mar 2006 10:19:45 -0000
@@ -904,18 +904,6 @@
 		       CTL_HW, HW_PAGESIZE, CTL_EOL);
 	sysctl_createv(clog, 0, NULL, NULL,
 		       CTLFLAG_PERMANENT,
-		       CTLTYPE_STRING, "disknames",
-		       SYSCTL_DESCR("List of disk devices present"),
-		       sysctl_hw_disknames, 0, NULL, 0,
-		       CTL_HW, HW_DISKNAMES, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_STRUCT, "diskstats",
-		       SYSCTL_DESCR("Statistics on disk operation"),
-		       sysctl_hw_diskstats, 0, NULL, 0,
-		       CTL_HW, HW_DISKSTATS, CTL_EOL);
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
 		       CTLTYPE_STRING, "machine_arch",
 		       SYSCTL_DESCR("Machine CPU class"),
 		       NULL, 0, machine_arch, 0,
Index: sys/kern/subr_disk.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_disk.c,v
retrieving revision 1.73
diff -u -r1.73 subr_disk.c
--- sys/kern/subr_disk.c	26 Dec 2005 18:45:27 -0000	1.73
+++ sys/kern/subr_disk.c	12 Mar 2006 10:19:45 -0000
@@ -89,14 +89,6 @@
 #include <lib/libkern/libkern.h>
 
 /*
- * A global list of all disks attached to the system.  May grow or
- * shrink over time.
- */
-struct	disklist_head disklist = TAILQ_HEAD_INITIALIZER(disklist);
-int	disk_count;		/* number of drives in global disklist */
-struct simplelock disklist_slock = SIMPLELOCK_INITIALIZER;
-
-/*
  * Compute checksum for disk label.
  */
 u_int
@@ -172,27 +164,20 @@
 }
 
 /*
- * Searches the disklist for the disk corresponding to the
+ * Searches the iostatlist for the disk corresponding to the
  * name provided.
  */
 struct disk *
 disk_find(char *name)
 {
-	struct disk *diskp;
+	struct io_stats *stat;
 
-	if ((name == NULL) || (disk_count <= 0))
-		return (NULL);
+	stat = iostat_find(name);
 
-	simple_lock(&disklist_slock);
-	for (diskp = TAILQ_FIRST(&disklist); diskp != NULL;
-	    diskp = TAILQ_NEXT(diskp, dk_link))
-		if (strcmp(diskp->dk_name, name) == 0) {
-			simple_unlock(&disklist_slock);
-			return (diskp);
-		}
-	simple_unlock(&disklist_slock);
+	if ((stat != NULL) && (stat->type == IOSTAT_DISK))
+		return stat->parent;
 
-	return (NULL);
+        return (NULL);
 }
 
 static void
@@ -211,8 +196,6 @@
 static void
 disk_attach0(struct disk *diskp)
 {
-	int s;
-
 	/*
 	 * Allocate and initialize the disklabel structures.  Note that
 	 * it's not safe to sleep here, since we're probably going to be
@@ -228,19 +211,12 @@
 	memset(diskp->dk_cpulabel, 0, sizeof(struct cpu_disklabel));
 
 	/*
-	 * Set the attached timestamp.
+	 * Set up the stats collection.
 	 */
-	s = splclock();
-	diskp->dk_attachtime = mono_time;
-	splx(s);
+	diskp->dk_stats = iostat_alloc(IOSTAT_DISK);
+        diskp->dk_stats->parent = (void *) diskp;
+        diskp->dk_stats->name = diskp->dk_name;
 
-	/*
-	 * Link into the disklist.
-	 */
-	simple_lock(&disklist_slock);
-	TAILQ_INSERT_TAIL(&disklist, diskp, dk_link);
-	disk_count++;
-	simple_unlock(&disklist_slock);
 }
 
 static void
@@ -248,14 +224,9 @@
 {
 
 	/*
-	 * Remove from the disklist.
+	 * Remove from the drivelist.
 	 */
-	if (disk_count == 0)
-		panic("disk_detach: disk_count == 0");
-	simple_lock(&disklist_slock);
-	TAILQ_REMOVE(&disklist, diskp, dk_link);
-	disk_count--;
-	simple_unlock(&disklist_slock);
+        iostat_free(diskp->dk_stats);
 
 	/*
 	 * Free the space used by the disklabel structures.
@@ -316,205 +287,31 @@
 	disk_detach0(diskp);
 }
 
-
 /*
- * Increment a disk's busy counter.  If the counter is going from
- * 0 to 1, set the timestamp.
+ * Mark the disk as busy for metrics collection.
  */
 void
 disk_busy(struct disk *diskp)
 {
-	int s;
-
-	/*
-	 * XXX We'd like to use something as accurate as microtime(),
-	 * but that doesn't depend on the system TOD clock.
-	 */
-	if (diskp->dk_busy++ == 0) {
-		s = splclock();
-		diskp->dk_timestamp = mono_time;
-		splx(s);
-	}
+	iostat_busy(diskp->dk_stats);
 }
 
 /*
- * Decrement a disk's busy counter, increment the byte count, total busy
- * time, and reset the timestamp.
+ * Finished disk operations, gather metrics.
  */
 void
 disk_unbusy(struct disk *diskp, long bcount, int read)
 {
-	int s;
-	struct timeval dv_time, diff_time;
-
-	if (diskp->dk_busy-- == 0) {
-		printf("%s: dk_busy < 0\n", diskp->dk_name);
-		panic("disk_unbusy");
-	}
-
-	s = splclock();
-	dv_time = mono_time;
-	splx(s);
-
-	timersub(&dv_time, &diskp->dk_timestamp, &diff_time);
-	timeradd(&diskp->dk_time, &diff_time, &diskp->dk_time);
-
-	diskp->dk_timestamp = dv_time;
-	if (bcount > 0) {
-		if (read) {
-			diskp->dk_rbytes += bcount;
-			diskp->dk_rxfer++;
-		} else {
-			diskp->dk_wbytes += bcount;
-			diskp->dk_wxfer++;
-		}
-	}
+	iostat_unbusy(diskp->dk_stats, bcount, read);
 }
 
 /*
- * Reset the metrics counters on the given disk.  Note that we cannot
- * reset the busy counter, as it may case a panic in disk_unbusy().
- * We also must avoid playing with the timestamp information, as it
- * may skew any pending transfer results.
+ * Reset the metrics counters on the given disk.
  */
 void
 disk_resetstat(struct disk *diskp)
 {
-	int s = splbio(), t;
-
-	diskp->dk_rxfer = 0;
-	diskp->dk_rbytes = 0;
-	diskp->dk_wxfer = 0;
-	diskp->dk_wbytes = 0;
-
-	t = splclock();
-	diskp->dk_attachtime = mono_time;
-	splx(t);
-
-	timerclear(&diskp->dk_time);
-
-	splx(s);
-}
-
-int
-sysctl_hw_disknames(SYSCTLFN_ARGS)
-{
-	char bf[DK_DISKNAMELEN + 1];
-	char *where = oldp;
-	struct disk *diskp;
-	size_t needed, left, slen;
-	int error, first;
-
-	if (newp != NULL)
-		return (EPERM);
-	if (namelen != 0)
-		return (EINVAL);
-
-	first = 1;
-	error = 0;
-	needed = 0;
-	left = *oldlenp;
-
-	simple_lock(&disklist_slock);
-	for (diskp = TAILQ_FIRST(&disklist); diskp != NULL;
-	    diskp = TAILQ_NEXT(diskp, dk_link)) {
-		if (where == NULL)
-			needed += strlen(diskp->dk_name) + 1;
-		else {
-			memset(bf, 0, sizeof(bf));
-			if (first) {
-				strncpy(bf, diskp->dk_name, sizeof(bf));
-				first = 0;
-			} else {
-				bf[0] = ' ';
-				strncpy(bf + 1, diskp->dk_name,
-				    sizeof(bf) - 1);
-			}
-			bf[DK_DISKNAMELEN] = '\0';
-			slen = strlen(bf);
-			if (left < slen + 1)
-				break;
-			/* +1 to copy out the trailing NUL byte */
-			error = copyout(bf, where, slen + 1);
-			if (error)
-				break;
-			where += slen;
-			needed += slen;
-			left -= slen;
-		}
-	}
-	simple_unlock(&disklist_slock);
-	*oldlenp = needed;
-	return (error);
-}
-
-int
-sysctl_hw_diskstats(SYSCTLFN_ARGS)
-{
-	struct disk_sysctl sdisk;
-	struct disk *diskp;
-	char *where = oldp;
-	size_t tocopy, left;
-	int error;
-
-	if (newp != NULL)
-		return (EPERM);
-
-	/*
-	 * The original hw.diskstats call was broken and did not require
-	 * the userland to pass in it's size of struct disk_sysctl.  This
-	 * was fixed after NetBSD 1.6 was released, and any applications
-	 * that do not pass in the size are given an error only, unless
-	 * we care about 1.6 compatibility.
-	 */
-	if (namelen == 0)
-#ifdef COMPAT_16
-		tocopy = offsetof(struct disk_sysctl, dk_rxfer);
-#else
-		return (EINVAL);
-#endif
-	else
-		tocopy = name[0];
-
-	if (where == NULL) {
-		*oldlenp = disk_count * tocopy;
-		return (0);
-	}
-
-	error = 0;
-	left = *oldlenp;
-	memset(&sdisk, 0, sizeof(sdisk));
-	*oldlenp = 0;
-
-	simple_lock(&disklist_slock);
-	TAILQ_FOREACH(diskp, &disklist, dk_link) {
-		if (left < tocopy)
-			break;
-		strncpy(sdisk.dk_name, diskp->dk_name, sizeof(sdisk.dk_name));
-		sdisk.dk_xfer = diskp->dk_rxfer + diskp->dk_wxfer;
-		sdisk.dk_rxfer = diskp->dk_rxfer;
-		sdisk.dk_wxfer = diskp->dk_wxfer;
-		sdisk.dk_seek = diskp->dk_seek;
-		sdisk.dk_bytes = diskp->dk_rbytes + diskp->dk_wbytes;
-		sdisk.dk_rbytes = diskp->dk_rbytes;
-		sdisk.dk_wbytes = diskp->dk_wbytes;
-		sdisk.dk_attachtime_sec = diskp->dk_attachtime.tv_sec;
-		sdisk.dk_attachtime_usec = diskp->dk_attachtime.tv_usec;
-		sdisk.dk_timestamp_sec = diskp->dk_timestamp.tv_sec;
-		sdisk.dk_timestamp_usec = diskp->dk_timestamp.tv_usec;
-		sdisk.dk_time_sec = diskp->dk_time.tv_sec;
-		sdisk.dk_time_usec = diskp->dk_time.tv_usec;
-		sdisk.dk_busy = diskp->dk_busy;
-
-		error = copyout(&sdisk, where, min(tocopy, sizeof(sdisk)));
-		if (error)
-			break;
-		where += tocopy;
-		*oldlenp += tocopy;
-		left -= tocopy;
-	}
-	simple_unlock(&disklist_slock);
-	return (error);
+	iostat_resetstat(diskp->dk_stats);
 }
 
 /*
Index: sys/nfs/nfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_vfsops.c,v
retrieving revision 1.152
diff -u -r1.152 nfs_vfsops.c
--- sys/nfs/nfs_vfsops.c	21 Feb 2006 04:32:39 -0000	1.152
+++ sys/nfs/nfs_vfsops.c	12 Mar 2006 10:19:45 -0000
@@ -77,6 +77,12 @@
 extern struct nfsstats nfsstats;
 extern int nfs_ticks;
 
+/*
+ * keep a count of the nfs mounts to generate ficticious drive names
+ * for the per drive stats.
+ */
+unsigned int nfs_mount_count = 0;
+
 MALLOC_DEFINE(M_NFSMNT, "NFS mount", "NFS mount structure");
 
 /*
@@ -800,6 +806,13 @@
 	nmp->nm_vnode = *vpp;
 	VOP_UNLOCK(*vpp, 0);
 
+	nmp->stats = iostat_alloc(IOSTAT_NFS);
+	nmp->stats->parent = nmp;
+	  /* generate a ficticious drive name for the nfs mount */
+	MALLOC(nmp->stats->name, char *, IOSTATNAMELEN, M_NFSMNT, M_WAITOK);
+	snprintf(nmp->stats->name, IOSTATNAMELEN, "nfs%u", nfs_mount_count);
+	nfs_mount_count++;
+
 	return (0);
 bad:
 	nfs_disconnect(nmp);
@@ -869,6 +882,14 @@
 	nmp->nm_iflag |= NFSMNT_DISMNT;
 
 	/*
+	 * Clean up the stats... note that we carefully avoid decrementing
+	 * nfs_mount_count here for good reason - we may not be unmounting
+	 * the last thing mounted.
+	 */
+	FREE(nmp->stats->name, M_NFSMNT);
+	iostat_free(nmp->stats);
+
+	/*
 	 * There are two reference counts to get rid of here
 	 * (see comment in mountnfs()).
 	 */
Index: sys/nfs/nfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_vnops.c,v
retrieving revision 1.231
diff -u -r1.231 nfs_vnops.c
--- sys/nfs/nfs_vnops.c	1 Mar 2006 12:38:32 -0000	1.231
+++ sys/nfs/nfs_vnops.c	12 Mar 2006 10:19:46 -0000
@@ -53,6 +53,7 @@
 #include <sys/proc.h>
 #include <sys/mount.h>
 #include <sys/buf.h>
+#include <sys/disk.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/namei.h>
@@ -1240,7 +1241,7 @@
 	caddr_t bpos, dpos, cp2;
 	struct mbuf *mreq, *mrep, *md, *mb;
 	struct nfsmount *nmp;
-	int error = 0, len, retlen, tsiz, eof;
+	int error = 0, len, retlen, tsiz, eof, byte_count;
 	const int v3 = NFS_ISV3(vp);
 	struct nfsnode *np = VTONFS(vp);
 #ifndef NFS_V2_ONLY
@@ -1254,6 +1255,8 @@
 	tsiz = uiop->uio_resid;
 	if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
 		return (EFBIG);
+	iostat_busy(nmp->stats);
+	byte_count = 0; /* count bytes actually transferred */
 	while (tsiz > 0) {
 		nfsstats.rpccnt[NFSPROC_READ]++;
 		len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
@@ -1288,6 +1291,7 @@
 		nfsm_mtouio(uiop, retlen);
 		m_freem(mrep);
 		tsiz -= retlen;
+		byte_count += retlen;
 #ifndef NFS_V2_ONLY
 		if (v3) {
 			if (eof || retlen == 0)
@@ -1298,6 +1302,7 @@
 			tsiz = 0;
 	}
 nfsmout:
+	iostat_unbusy(nmp->stats, byte_count, 1);
 	return (error);
 }
 
@@ -1347,7 +1352,7 @@
 	int committed = NFSV3WRITE_FILESYNC;
 	struct nfsnode *np = VTONFS(vp);
 	struct nfs_writerpc_context ctx;
-	int s;
+	int s, byte_count;
 	struct lwp *l = NULL;
 	size_t origresid;
 #ifndef NFS_V2_ONLY
@@ -1376,6 +1381,8 @@
 retry:
 	origresid = uiop->uio_resid;
 	KASSERT(origresid == uiop->uio_iov->iov_len);
+	iostat_busy(nmp->stats);
+	byte_count = 0; /* count of bytes actually written */
 	while (tsiz > 0) {
 		uint32_t datalen; /* data bytes need to be allocated in mbuf */
 		uint32_t backup;
@@ -1508,6 +1515,7 @@
 		if (error)
 			break;
 		tsiz -= len;
+		byte_count += len;
 		if (stalewriteverf) {
 			*stalewriteverfp = TRUE;
 			stalewriteverf = FALSE;
@@ -1528,6 +1536,7 @@
 		}
 	}
 nfsmout:
+	iostat_unbusy(nmp->stats, byte_count, 0);
 	if (pageprotected) {
 		/*
 		 * wait until mbufs go away.
Index: sys/nfs/nfsmount.h
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfsmount.h,v
retrieving revision 1.37
diff -u -r1.37 nfsmount.h
--- sys/nfs/nfsmount.h	11 Dec 2005 12:25:17 -0000	1.37
+++ sys/nfs/nfsmount.h	12 Mar 2006 10:19:46 -0000
@@ -37,6 +37,9 @@
 
 #ifndef _NFS_NFSMOUNT_H_
 #define _NFS_NFSMOUNT_H_
+#ifdef _KERNEL
+#include <sys/disk.h>
+#endif
 
 /*
  * Arguments to mount NFS
@@ -167,6 +170,7 @@
 	int	nm_iflag;		/* internal flags */
 	int	nm_waiters;		/* number of waiting listeners.. */
 	long	nm_wcckludgetime;	/* see nfs_check_wccdata() */
+	struct io_stats *stats;		/* per nfs mount statistics */
 };
 
 /*
Index: sys/sys/Makefile
===================================================================
RCS file: /cvsroot/src/sys/sys/Makefile,v
retrieving revision 1.82
diff -u -r1.82 Makefile
--- sys/sys/Makefile	11 Feb 2006 17:36:41 -0000	1.82
+++ sys/sys/Makefile	12 Mar 2006 10:19:47 -0000
@@ -12,7 +12,7 @@
 	exec_coff.h exec_ecoff.h exec_elf.h exec_script.h extattr.h extent.h \
 	fcntl.h fd_set.h fdio.h featuretest.h file.h filedesc.h filio.h \
 	float_ieee754.h fstypes.h gmon.h gpio.h hash.h \
-	ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h ipc.h \
+	ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h iostat.h ipc.h \
 	joystick.h \
 	kcore.h kgdb.h ksem.h ksyms.h ktrace.h \
 	lkm.h localedef.h lock.h lockf.h lwp.h \
Index: sys/sys/disk.h
===================================================================
RCS file: /cvsroot/src/sys/sys/disk.h,v
retrieving revision 1.33
diff -u -r1.33 disk.h
--- sys/sys/disk.h	26 Dec 2005 18:41:36 -0000	1.33
+++ sys/sys/disk.h	12 Mar 2006 10:19:47 -0000
@@ -90,6 +90,7 @@
 #include <sys/time.h>
 #include <sys/queue.h>
 #include <sys/lock.h>
+#include <sys/iostat.h>
 
 struct buf;
 struct disk;
@@ -209,15 +210,7 @@
 	 * Metrics data; note that some metrics may have no meaning
 	 * on certain types of disks.
 	 */
-	int		dk_busy;	/* busy counter */
-	uint64_t	dk_rxfer;	/* total number of read transfers */
-	uint64_t	dk_wxfer;	/* total number of write transfers */
-	uint64_t	dk_seek;	/* total independent seek operations */
-	uint64_t	dk_rbytes;	/* total bytes read */
-	uint64_t	dk_wbytes;	/* total bytes written */
-	struct timeval	dk_attachtime;	/* time disk was attached */
-	struct timeval	dk_timestamp;	/* timestamp of last unbusy */
-	struct timeval	dk_time;	/* total time spent busy */
+	struct io_stats	*dk_stats;
 
 	struct	dkdriver *dk_driver;	/* pointer to driver */
 
@@ -243,29 +236,6 @@
 	struct cpu_disklabel *dk_cpulabel;
 };
 
-#define	DK_DISKNAMELEN	16
-
-/* The following structure is 64-bit alignment safe */
-struct disk_sysctl {
-	char		dk_name[DK_DISKNAMELEN];
-	int32_t		dk_busy;
-	int32_t		pad;
-	uint64_t	dk_xfer;
-	uint64_t	dk_seek;
-	uint64_t	dk_bytes;
-	uint32_t	dk_attachtime_sec;
-	uint32_t	dk_attachtime_usec;
-	uint32_t	dk_timestamp_sec;
-	uint32_t	dk_timestamp_usec;
-	uint32_t	dk_time_sec;
-	uint32_t	dk_time_usec;
-	/* New separate read/write stats */
-	uint64_t	dk_rxfer;
-	uint64_t	dk_rbytes;
-	uint64_t	dk_wxfer;
-	uint64_t	dk_wbytes;
-};
-
 struct dkdriver {
 	void	(*d_strategy)(struct buf *);
 	void	(*d_minphys)(struct buf *);
@@ -288,11 +258,6 @@
 #define	DK_OPENRAW	5		/* open without label */
 
 /*
- * disklist_head is defined here so that user-land has access to it.
- */
-TAILQ_HEAD(disklist_head, disk);	/* the disklist is a TAILQ */
-
-/*
  * Bad sector lists per fixed disk
  */
 struct disk_badsectors {
@@ -328,10 +293,10 @@
 void	pseudo_disk_init(struct disk *);
 void	pseudo_disk_attach(struct disk *);
 void	pseudo_disk_detach(struct disk *);
-void	disk_busy(struct disk *);
-void	disk_unbusy(struct disk *, long, int);
-void	disk_resetstat(struct disk *);
-struct	disk *disk_find(char *);
+void    disk_busy(struct disk *);
+void    disk_unbusy(struct disk *, long, int);
+void    disk_resetstat(struct disk *);
+struct  disk *disk_find(char *);
 
 int	dkwedge_add(struct dkwedge_info *);
 int	dkwedge_del(struct dkwedge_info *);
Index: sys/sys/sysctl.h
===================================================================
RCS file: /cvsroot/src/sys/sys/sysctl.h,v
retrieving revision 1.152
diff -u -r1.152 sysctl.h
--- sys/sys/sysctl.h	25 Feb 2006 00:58:36 -0000	1.152
+++ sys/sys/sysctl.h	12 Mar 2006 10:19:47 -0000
@@ -703,15 +703,14 @@
 #define	HW_USERMEM	 6		/* int: non-kernel memory (bytes) */
 #define	HW_PAGESIZE	 7		/* int: software page size */
 #define	HW_DISKNAMES	 8		/* string: disk drive names */
-#define	HW_DISKSTATS	 9		/* struct: diskstats[] */
+#define	HW_IOSTATS	 9		/* struct: iostats[] */
 #define	HW_MACHINE_ARCH	10		/* string: machine architecture */
 #define	HW_ALIGNBYTES	11		/* int: ALIGNBYTES for the kernel */
 #define	HW_CNMAGIC	12		/* string: console magic sequence(s) */
 #define	HW_PHYSMEM64	13		/* quad: total memory (bytes) */
 #define	HW_USERMEM64	14		/* quad: non-kernel memory (bytes) */
-#define	HW_TAPENAMES	15		/* string: tape drive names */
-#define	HW_TAPESTATS	16		/* struct: tapestats[] */
-#define	HW_MAXID	16		/* number of valid hw ids */
+#define	HW_IOSTATNAMES	15		/* string: iostat names */
+#define	HW_MAXID	15		/* number of valid hw ids */
 
 #define	CTL_HW_NAMES { \
 	{ 0, 0 }, \
@@ -722,8 +721,8 @@
 	{ "physmem", CTLTYPE_INT }, \
 	{ "usermem", CTLTYPE_INT }, \
 	{ "pagesize", CTLTYPE_INT }, \
-	{ "disknames", CTLTYPE_STRING }, \
-	{ "diskstats", CTLTYPE_STRUCT }, \
+	{ "drivenames", CTLTYPE_STRING }, \
+	{ "drivestats", CTLTYPE_STRUCT }, \
 	{ "machine_arch", CTLTYPE_STRING }, \
 	{ "alignbytes", CTLTYPE_INT }, \
 	{ "cnmagic", CTLTYPE_STRING }, \
@@ -1074,8 +1073,6 @@
  * these helpers are in other files (XXX so should the nodes be) or
  * are used by more than one node
  */
-int	sysctl_hw_disknames(SYSCTLFN_PROTO);
-int	sysctl_hw_diskstats(SYSCTLFN_PROTO);
 int	sysctl_hw_tapenames(SYSCTLFN_PROTO);
 int	sysctl_hw_tapestats(SYSCTLFN_PROTO);
 int	sysctl_kern_vnode(SYSCTLFN_PROTO);
Index: usr.bin/systat/Makefile
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/Makefile,v
retrieving revision 1.31
diff -u -r1.31 Makefile
--- usr.bin/systat/Makefile	7 Aug 2005 12:32:38 -0000	1.31
+++ usr.bin/systat/Makefile	12 Mar 2006 10:19:47 -0000
@@ -11,7 +11,7 @@
 CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/vmstat -DSUPPORT_UTMP -DSUPPORT_UTMPX \
 	-I${NETBSDSRCDIR}/usr.bin/who
 CWARNFLAGS+=    -Wno-format-y2k
-SRCS=	bufcache.c cmds.c cmdtab.c disks.c df.c dkstats.c tpstats.c fetch.c \
+SRCS=	bufcache.c cmds.c cmdtab.c disks.c df.c drvstats.c fetch.c \
 	globalcmds.c icmp.c iostat.c ip.c keyboard.c main.c mbufs.c \
 	netcmds.c netstat.c pigs.c ps.c swap.c tcp.c vmstat.c utmpentry.c
 DPADD=	${LIBCURSES} ${LIBM} ${LIBKVM}
Index: usr.bin/systat/disks.c
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/disks.c,v
retrieving revision 1.15
diff -u -r1.15 disks.c
--- usr.bin/systat/disks.c	26 Feb 2005 18:58:45 -0000	1.15
+++ usr.bin/systat/disks.c	12 Mar 2006 10:19:47 -0000
@@ -42,16 +42,16 @@
 
 #include "systat.h"
 #include "extern.h"
-#include "dkstats.h"
+#include "drvstats.h"
 
-static void dkselect(char *args, int truefalse, int selections[]);
+static void drvselect(char *args, int truefalse, int selections[]);
 
 void
 disks_add(char *args)
 {
 
 	if (args)
-		dkselect(args, 1, dk_select);
+		drvselect(args, 1, drv_select);
 }
 
 void
@@ -59,7 +59,7 @@
 {
 
 	if (args)
-		dkselect(args, 0, dk_select);
+		drvselect(args, 0, drv_select);
 }
 
 void
@@ -68,19 +68,19 @@
 	int i;
 
 	if (args) {
-		for (i = 0; i < dk_ndrive; i++)
-			dk_select[i] = 0;
+		for (i = 0; i < ndrive; i++)
+			drv_select[i] = 0;
 		disks_add(args);
 	} else {
 		move(CMDLINE, 0);
 		clrtoeol();
-		for (i = 0; i < dk_ndrive; i++)
+		for (i = 0; i < ndrive; i++)
 			printw("%s ", dr_name[i]);
 	}
 }
 
 static void
-dkselect(char *args, int truefalse, int selections[])
+drvselect(char *args, int truefalse, int selections[])
 {
 	char *cp;
 	int i;
@@ -98,12 +98,12 @@
 			*cp++ = '\0';
 		if (cp - args == 0)
 			break;
-		for (i = 0; i < dk_ndrive; i++)
+		for (i = 0; i < ndrive; i++)
 			if (strcmp(args, dr_name[i]) == 0) {
 				selections[i] = truefalse;
 				break;
 			}
-		if (i >= dk_ndrive)
+		if (i >= ndrive)
 			error("%s: unknown drive", args);
 		args = cp;
 	}
Index: usr.bin/systat/iostat.c
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/iostat.c,v
retrieving revision 1.34
diff -u -r1.34 iostat.c
--- usr.bin/systat/iostat.c	5 Feb 2006 09:58:39 -0000	1.34
+++ usr.bin/systat/iostat.c	12 Mar 2006 10:19:47 -0000
@@ -43,8 +43,7 @@
 
 #include "systat.h"
 #include "extern.h"
-#include "dkstats.h"
-#include "tpstats.h"
+#include "drvstats.h"
 
 static  int linesperregion;
 static  double etime;
@@ -56,7 +55,6 @@
 static void histogram(double, int, double);
 static int numlabels(int);
 static int stats(int, int, int);
-static int tpstats(int, int, int);
 static void stat1(int, int);
 
 
@@ -82,11 +80,9 @@
 initiostat(void)
 {
 
-	dkinit(1);
-	tpinit(1);
+	drvinit(1);
 	cpureadstats();
-	dkreadstats();
-	tpreadstats();
+	drvreadstats();
 	return(1);
 }
 
@@ -96,11 +92,8 @@
 
 	cpureadstats();
 
-	if (dk_ndrive != 0)
-		dkreadstats();
-
-	if (tp_ndrive != 0)
-		tpreadstats();
+	if (ndrive != 0)
+		drvreadstats();
 }
 
 #define	INSET	14
@@ -110,7 +103,7 @@
 {
 	int row;
 
-	if ((dk_ndrive == 0) && (tp_ndrive == 0)) {
+	if (ndrive == 0) {
 		error("No drives defined.");
 		return;
 	}
@@ -136,13 +129,10 @@
 
 #define COLWIDTH	(9 + secs * 5 + 1 + read_write * 9 + 1)
 #define DRIVESPERLINE	((getmaxx(wnd) + 1) / COLWIDTH)
-	for (ndrives = 0, i = 0; i < dk_ndrive; i++)
-		if (cur.dk_select[i])
-			ndrives++;
-	for (i = 0; i < tp_ndrive; i++)
-		if (cur_tape.select[i])
+	for (ndrives = 0, i = 0; i < ndrive; i++)
+		if (cur.select[i])
 			ndrives++;
-	
+
 	regions = howmany(ndrives, DRIVESPERLINE);
 	/*
 	 * Deduct -regions for blank line after each scrolling region.
@@ -155,22 +145,16 @@
 	if (linesperregion < 3)
 		linesperregion = 3;
 	col = 0;
-	for (i = 0; i < (dk_ndrive + tp_ndrive); i++)
-		if (((i < dk_ndrive) && (cur.dk_select[i])) ||
-		    ((i >= dk_ndrive) && (cur_tape.select[i - dk_ndrive]))) {
+	for (i = 0; i < ndrive; i++)
+		if (cur.select[i]) {
 			if (col + COLWIDTH - 1 > getmaxx(wnd)) {
 				col = 0, row += linesperregion + 1;
 				if (row > getmaxy(wnd) - (linesperregion))
 					break;
 			}
 
-			if (i < dk_ndrive)
-				mvwprintw(wnd, row, col + 5, "%s",
-					  cur.dk_name[i]);
-			else
-				mvwprintw(wnd, row, col + 5, "%s",
-					  cur_tape.name[i - dk_ndrive]);
-			
+			mvwprintw(wnd, row, col + 5, "%s", cur.name[i]);
+
 			if (read_write)
 				mvwprintw(wnd, row, col + 11 + secs * 5,
 				    "(write)");
@@ -195,26 +179,12 @@
 	mvwaddstr(wnd, row++, INSET,
 	    "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
 	linesperregion = 2 + secs + (read_write ? 2 : 0);
-	for (i = 0; i < dk_ndrive; i++)
-		if (cur.dk_select[i]) {
-			if (row > getmaxy(wnd) - linesperregion)
-				break;
-			mvwprintw(wnd, row++, 0, "%7.7s  kBps|",
-			    cur.dk_name[i]);
-			mvwaddstr(wnd, row++, 0, "          tps|");
-			if (read_write) {
-				mvwprintw(wnd, row++, 0, " (write) kBps|");
-				mvwaddstr(wnd, row++, 0, "          tps|");
-			}
-			if (secs)
-				mvwaddstr(wnd, row++, 0, "         msec|");
-		}
-	for (i = 0; i < tp_ndrive; i++)
-		if (cur_tape.select[i]) {
+	for (i = 0; i < ndrive; i++) {
+		if (cur.select[i]) {
 			if (row > getmaxy(wnd) - linesperregion)
 				break;
 			mvwprintw(wnd, row++, 0, "%7.7s  kBps|",
-			    cur_tape.name[i]);
+			    cur.name[i]);
 			mvwaddstr(wnd, row++, 0, "          tps|");
 			if (read_write) {
 				mvwprintw(wnd, row++, 0, " (write) kBps|");
@@ -223,6 +193,8 @@
 			if (secs)
 				mvwaddstr(wnd, row++, 0, "         msec|");
 		}
+	}
+
 	return (row);
 }
 
@@ -231,11 +203,10 @@
 {
 	int i, row, col;
 
-	if (dk_ndrive == 0)
+	if (ndrive == 0)
 		return;
-	dkswap();
 	cpuswap();
-	tpswap();
+	drvswap();
 
 	etime = cur.cp_etime;
 	row = 1;
@@ -247,18 +218,12 @@
 		stat1(row++, i);
 	if (!numbers) {
 		row += 2;
-		for (i = 0; i < dk_ndrive; i++)
-			if (cur.dk_select[i]) {
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i]) {
 				if (row > getmaxy(wnd) - linesperregion)
 					break;
 				row = stats(row, INSET, i);
 			}
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i]) {
-				if (row > getmaxy(wnd) - linesperregion)
-					break;
-				row = tpstats(row, INSET, i);
-			}
 		return;
 	}
 	col = 0;
@@ -266,22 +231,8 @@
 	wdeleteln(wnd);
 	wmove(wnd, row + 3, 0);
 	winsertln(wnd);
-	for (i = 0; i < dk_ndrive; i++)
-		if (cur.dk_select[i]) {
-			if (col + COLWIDTH - 1 > getmaxx(wnd)) {
-				col = 0, row += linesperregion + 1;
-				if (row > getmaxy(wnd) - (linesperregion + 1))
-					break;
-				wmove(wnd, row + linesperregion, 0);
-				wdeleteln(wnd);
-				wmove(wnd, row + 3, 0);
-				winsertln(wnd);
-			}
-			(void) stats(row + 3, col, i);
-			col += COLWIDTH;
-		}
-	for (i = 0; i < tp_ndrive; i++)
-		if (cur_tape.select[i]) {
+	for (i = 0; i < ndrive; i++)
+		if (cur.select[i]) {
 			if (col + COLWIDTH - 1 > getmaxx(wnd)) {
 				col = 0, row += linesperregion + 1;
 				if (row > getmaxy(wnd) - (linesperregion + 1))
@@ -303,64 +254,16 @@
 	uint64_t rxfer;
 
 	/* time busy in disk activity */
-	atime = (double)cur.dk_time[dn].tv_sec +
-		((double)cur.dk_time[dn].tv_usec / (double)1000000);
-
-	/* # of k transferred */
-	rwords = cur.dk_rbytes[dn] / 1024.0;
-	wwords = cur.dk_wbytes[dn] / 1024.0;
-	rxfer = cur.dk_rxfer[dn];
-	if (!read_write) {
-		rwords = wwords;
-		rxfer += cur.dk_wxfer[dn];
-	}
-	if (numbers) {
-		mvwprintw(wnd, row, col, "%5.0f%4.0f",
-		    rwords / etime, rxfer / etime);
-		if (secs)
-			wprintw(wnd, "%5.1f", atime / etime);
-		if (read_write)
-			wprintw(wnd, " %5.0f%4.0f",
-			    wwords / etime, cur.dk_wxfer[dn] / etime);
-		return (row);
-	}
-
-	wmove(wnd, row++, col);
-	histogram(rwords / etime, 50, 0.5);
-	wmove(wnd, row++, col);
-	histogram(rxfer / etime, 50, 0.5);
-	if (read_write) {
-		wmove(wnd, row++, col);
-		histogram(wwords / etime, 50, 0.5);
-		wmove(wnd, row++, col);
-		histogram(cur.dk_wxfer[dn] / etime, 50, 0.5);
-	}
-
-	if (secs) {
-		wmove(wnd, row++, col);
-		atime *= 1000;	/* In milliseconds */
-		histogram(atime / etime, 50, 0.5);
-	}
-	return (row);
-}
-
-static int
-tpstats(int row, int col, int dn)
-{
-	double atime, rwords, wwords;
-	uint64_t rxfer;
-
-	/* time busy in disk activity */
-	atime = (double)cur_tape.time[dn].tv_sec +
-		((double)cur_tape.time[dn].tv_usec / (double)1000000);
+	atime = (double)cur.time[dn].tv_sec +
+		((double)cur.time[dn].tv_usec / (double)1000000);
 
 	/* # of k transferred */
-	rwords = cur_tape.rbytes[dn] / 1024.0;
-	wwords = cur_tape.wbytes[dn] / 1024.0;
-	rxfer = cur_tape.rxfer[dn];
+	rwords = cur.rbytes[dn] / 1024.0;
+	wwords = cur.wbytes[dn] / 1024.0;
+	rxfer = cur.rxfer[dn];
 	if (!read_write) {
 		rwords = wwords;
-		rxfer += cur_tape.wxfer[dn];
+		rxfer += cur.wxfer[dn];
 	}
 	if (numbers) {
 		mvwprintw(wnd, row, col, "%5.0f%4.0f",
@@ -369,7 +272,7 @@
 			wprintw(wnd, "%5.1f", atime / etime);
 		if (read_write)
 			wprintw(wnd, " %5.0f%4.0f",
-			    wwords / etime, cur_tape.wxfer[dn] / etime);
+			    wwords / etime, cur.wxfer[dn] / etime);
 		return (row);
 	}
 
@@ -381,7 +284,7 @@
 		wmove(wnd, row++, col);
 		histogram(wwords / etime, 50, 0.5);
 		wmove(wnd, row++, col);
-		histogram(cur_tape.wxfer[dn] / etime, 50, 0.5);
+		histogram(cur.wxfer[dn] / etime, 50, 0.5);
 	}
 
 	if (secs) {
Index: usr.bin/systat/vmstat.c
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/vmstat.c,v
retrieving revision 1.62
diff -u -r1.62 vmstat.c
--- usr.bin/systat/vmstat.c	5 Feb 2006 09:54:50 -0000	1.62
+++ usr.bin/systat/vmstat.c	12 Mar 2006 10:19:47 -0000
@@ -55,8 +55,7 @@
 
 #include "systat.h"
 #include "extern.h"
-#include "dkstats.h"
-#include "tpstats.h"
+#include "drvstats.h"
 #include "utmpentry.h"
 
 static struct Info {
@@ -80,7 +79,6 @@
 static void copyinfo(struct Info *, struct Info *);
 static float cputime(int);
 static void dinfo(int, int, int);
-static void tinfo(int, int, int);
 static void getinfo(struct Info *, enum state);
 static void putint(int, int, int, int);
 static void putfloat(double, int, int, int, int, int);
@@ -221,9 +219,7 @@
 		}
 	}
 	hertz = stathz ? stathz : hz;
-	if (!dkinit(1))
-		return(0);
-	if (!tpinit(1))
+	if (!drvinit(1))
 		return(0);
 
 	/* Old style interrupt counts - deprecated */
@@ -427,8 +423,7 @@
 
 	cpuswap();
 	if (state == TIME) {
-		dkswap();
-		tpswap();
+		drvswap();
 		etime = cur.cp_etime;
 		/* < 5 ticks - ignore this trash */
 		if ((etime * hertz) < 1.0) {
@@ -558,14 +553,9 @@
 	PUTRATE(uvmexp.softs, GENSTATROW + 1, GENSTATCOL + 22, 5);
 	PUTRATE(uvmexp.faults, GENSTATROW + 1, GENSTATCOL + 27, 6);
 	for (l = 0, i = 0, r = DISKROW, c = DISKCOL;
-	     i < (dk_ndrive + tp_ndrive); i++) {
-		if (i < dk_ndrive) {
-			if (!dk_select[i])
-				continue;
-		} else {
-			if (!tp_select[i - dk_ndrive])
-				continue;
-		}
+	     i < ndrive; i++) {
+		if (!drv_select[i])
+			continue;
 
 		if (disk_horiz)
 			c += DISKCOLWIDTH;
@@ -589,10 +579,7 @@
 		}
 		l++;
 
-		if (i < dk_ndrive)
-			dinfo(i, r, c);
-		else
-			tinfo(i - dk_ndrive, r, c);
+		dinfo(i, r, c);
 	}
 	/* blank out if we lost any disks */
 	for (i = l; i < last_disks; i++) {
@@ -751,8 +738,7 @@
 	int i;
 
 	cpureadstats();
-	dkreadstats();
-	tpreadstats();
+	drvreadstats();
 	NREAD(X_NCHSTATS, &stats->nchstats, sizeof stats->nchstats);
 	if (nintr)
 		NREAD(X_INTRCNT, stats->intrcnt, nintr * LONG);
@@ -812,48 +798,20 @@
 	mvprintw(r, c, "%*.*s", DISKCOLWIDTH, DISKCOLWIDTH, dr_name[dn]);
 	ADV;
 
-	putint((int)(cur.dk_seek[dn]/etime+0.5), r, c, DISKCOLWIDTH);
-	ADV;
-	putint((int)((cur.dk_rxfer[dn]+cur.dk_wxfer[dn])/etime+0.5),
-	    r, c, DISKCOLWIDTH);
-	ADV;
-	puthumanint((cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) / etime + 0.5,
-		    r, c, DISKCOLWIDTH);
-	ADV;
-
-	/* time busy in disk activity */
-	atime = cur.dk_time[dn].tv_sec + cur.dk_time[dn].tv_usec / 1000000.0;
-	atime = atime * 100.0 / etime;
-	if (atime >= 100)
-		putint(100, r, c, DISKCOLWIDTH);
-	else
-		putfloat(atime, r, c, DISKCOLWIDTH, 1, 1);
-}
-
-static void
-tinfo(int dn, int r, int c)
-{
-	double atime;
-
-	mvprintw(r, c, "%*.*s", DISKCOLWIDTH, DISKCOLWIDTH, tp_name[dn]);
+	putint((int)(cur.seek[dn]/etime+0.5), r, c, DISKCOLWIDTH);
 	ADV;
-	ADV; /* skip over the seeks column - not relevant for tape drives */
-
-	putint((int)((cur_tape.rxfer[dn]+cur_tape.wxfer[dn])/etime+0.5),
+	putint((int)((cur.rxfer[dn]+cur.wxfer[dn])/etime+0.5),
 	    r, c, DISKCOLWIDTH);
 	ADV;
-	puthumanint((cur_tape.rbytes[dn] + cur_tape.wbytes[dn]) / etime + 0.5,
+	puthumanint((cur.rbytes[dn] + cur.wbytes[dn]) / etime + 0.5,
 		    r, c, DISKCOLWIDTH);
 	ADV;
 
 	/* time busy in disk activity */
-	atime = cur_tape.time[dn].tv_sec + cur_tape.time[dn].tv_usec / 1000000.0;
+	atime = cur.time[dn].tv_sec + cur.time[dn].tv_usec / 1000000.0;
 	atime = atime * 100.0 / etime;
 	if (atime >= 100)
 		putint(100, r, c, DISKCOLWIDTH);
 	else
 		putfloat(atime, r, c, DISKCOLWIDTH, 1, 1);
-#undef ADV
 }
-
-
Index: usr.bin/vmstat/Makefile
===================================================================
RCS file: /cvsroot/src/usr.bin/vmstat/Makefile,v
retrieving revision 1.22
diff -u -r1.22 Makefile
--- usr.bin/vmstat/Makefile	7 Aug 2005 12:23:20 -0000	1.22
+++ usr.bin/vmstat/Makefile	12 Mar 2006 10:19:47 -0000
@@ -4,7 +4,7 @@
 PROG=	vmstat
 WARNS=3
 
-SRCS=	dkstats.c tpstats.c vmstat.c
+SRCS=	drvstats.c vmstat.c
 MAN=	vmstat.1
 DPADD=	${LIBKVM}
 LDADD=	-lkvm
Index: usr.bin/vmstat/vmstat.c
===================================================================
RCS file: /cvsroot/src/usr.bin/vmstat/vmstat.c,v
retrieving revision 1.139
diff -u -r1.139 vmstat.c
--- usr.bin/vmstat/vmstat.c	5 Feb 2006 09:54:50 -0000	1.139
+++ usr.bin/vmstat/vmstat.c	12 Mar 2006 10:19:48 -0000
@@ -132,8 +132,7 @@
 #include <unistd.h>
 #include <util.h>
 
-#include "dkstats.h"
-#include "tpstats.h"
+#include "drvstats.h"
 
 /*
  * General namelist
@@ -252,8 +251,7 @@
 
 void	cpustats(void);
 void	deref_kptr(const void *, void *, size_t, const char *);
-void	dkstats(void);
-void	tpstats(void);
+void	drvstats(void);
 void	doevcnt(int verbose);
 void	dohashstat(int, int, const char *);
 void	dointr(int verbose);
@@ -405,8 +403,7 @@
 	if (todo & VMSTAT) {
 		struct winsize winsize;
 
-		dkinit(0);	/* Initialize disk stats, no disks selected. */
-		tpinit(0);
+		drvinit(0);	/* Initialize disk stats, no disks selected. */
 
 		(void)setgid(getgid()); /* don't need privs anymore */
 
@@ -511,35 +508,21 @@
 		if (isdigit((unsigned char)**argv))
 			break;
 #endif
-		for (i = 0; i < dk_ndrive; i++) {
+		for (i = 0; i < ndrive; i++) {
 			if (strcmp(dr_name[i], *argv))
 				continue;
-			dk_select[i] = 1;
+			drv_select[i] = 1;
 			++ndrives;
 			break;
 		}
-		for (i = 0; i < tp_ndrive; i++) {
-			if (strcmp(tp_name[i], *argv))
-				continue;
-			tp_select[i] = 1;
-			++ndrives;
-			break;
-		}
-	}
-	for (i = 0; i < dk_ndrive && ndrives < 3; i++) {
-		if (dk_select[i])
-			continue;
-		dk_select[i] = 1;
-		++ndrives;
 	}
-	
-	for (i = 0; i < tp_ndrive && ndrives < 3; i++) {
-		if (tp_select[i])
+	for (i = 0; i < ndrive && ndrives < 3; i++) {
+		if (drv_select[i])
 			continue;
-		tp_select[i] = 1;
+		drv_select[i] = 1;
 		++ndrives;
 	}
-	
+
 	return (argv);
 }
 
@@ -645,8 +628,8 @@
 		if (!--hdrcnt)
 			printhdr();
 		/* Read new disk statistics */
-		dkreadstats();
 		cpureadstats();
+		drvreadstats();
 		tkreadstats();
 		kread(namelist, X_UVMEXP, &uvmexp, sizeof(uvmexp));
 		if (memf != NULL) {
@@ -679,8 +662,7 @@
 		    rate(uvmexp.pgswapout - ouvmexp.pgswapout));
 		(void)printf("%4lu ", rate(uvmexp.pdfreed - ouvmexp.pdfreed));
 		(void)printf("%4lu ", rate(uvmexp.pdscans - ouvmexp.pdscans));
-		dkstats();
-		tpstats();
+		drvstats();
 		(void)printf("%4lu %4lu %3lu ",
 		    rate(uvmexp.intrs - ouvmexp.intrs),
 		    rate(uvmexp.syscalls - ouvmexp.syscalls),
@@ -716,8 +698,8 @@
 		    ndrives * 3, "");
 
 	(void)printf(" r b w    avm    fre  flt  re  pi   po   fr   sr ");
-	for (i = 0; i < dk_ndrive; i++)
-		if (dk_select[i])
+	for (i = 0; i < ndrive; i++)
+		if (drv_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");
@@ -884,40 +866,22 @@
 }
 
 void
-dkstats(void)
+drvstats(void)
 {
 	int dn;
 	double etime;
 
 	/* Calculate disk stat deltas. */
-	dkswap();
 	cpuswap();
+	drvswap();
 	tkswap();
 	etime = cur.cp_etime;
 
-	for (dn = 0; dn < dk_ndrive; ++dn) {
-		if (!dk_select[dn])
-			continue;
-		(void)printf("%2.0f ",
-		    (cur.dk_rxfer[dn] + cur.dk_wxfer[dn]) / etime);
-	}
-}
-
-void
-tpstats(void)
-{
-	int dn;
-	double etime;
-
-	/* Calculate tape stat deltas. */
-	tpswap();
-	etime = cur.cp_etime;
-
-	for (dn = 0; dn < tp_ndrive; ++dn) {
-		if (!tp_select[dn])
+	for (dn = 0; dn < ndrive; ++dn) {
+		if (!drv_select[dn])
 			continue;
 		(void)printf("%2.0f ",
-		    (cur_tape.rxfer[dn] + cur_tape.wxfer[dn]) / etime);
+		    (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
 	}
 }
 
Index: usr.sbin/iostat/Makefile
===================================================================
RCS file: /cvsroot/src/usr.sbin/iostat/Makefile,v
retrieving revision 1.21
diff -u -r1.21 Makefile
--- usr.sbin/iostat/Makefile	7 Aug 2005 12:34:21 -0000	1.21
+++ usr.sbin/iostat/Makefile	12 Mar 2006 10:19:48 -0000
@@ -11,7 +11,7 @@
 CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/vmstat
 
 # dkstats.c pulled in from ../../usr.bin/vmstat
-SRCS=	dkstats.c tpstats.c iostat.c
+SRCS=	drvstats.c iostat.c
 
 DPADD=	${LIBKVM}
 LDADD=	-lkvm
Index: usr.sbin/iostat/iostat.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/iostat/iostat.c,v
retrieving revision 1.48
diff -u -r1.48 iostat.c
--- usr.sbin/iostat/iostat.c	12 Feb 2006 22:11:54 -0000	1.48
+++ usr.sbin/iostat/iostat.c	12 Mar 2006 10:19:48 -0000
@@ -88,8 +88,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "dkstats.h"
-#include "tpstats.h"
+#include "drvstats.h"
 
 /* Namelist and memory files. */
 char	*nlistf, *memf;
@@ -110,9 +109,9 @@
 #define	SHOW_STATS_ALL	(SHOW_STATS_1 | SHOW_STATS_2 | SHOW_STATS_X)
 
 static void cpustats(void);
-static void disk_stats(double);
-static void disk_stats2(double);
-static void disk_statsx(double);
+static void drive_stats(double);
+static void drive_stats2(double);
+static void drive_statsx(double);
 static void sig_header(int);
 static volatile int do_header;
 static void header(void);
@@ -194,14 +193,12 @@
 		defdrives -= 9;		/* XXX magic number */
 	defdrives /= 18;		/* XXX magic number */
 
-	dkinit(0);
-	tpinit(0);
+	drvinit(0);
 	cpureadstats();
-	dkreadstats();
-	tpreadstats();
+	drvreadstats();
 	ndrives = selectdrives(argc, argv);
 	if (ndrives == 0) {
-		/* No drives are selected.  No need to show disk stats. */
+		/* No drives are selected.  No need to show drive stats. */
 		todo &= ~SHOW_STATS_ALL;
 		if (todo == 0)
 			errx(1, "no drives");
@@ -226,18 +223,16 @@
 
 		if (!ISSET(todo, SHOW_TOTALS)) {
 			cpuswap();
-			dkswap();
-			tpswap();
+			drvswap();
 		}
-		
+
 		display();
 
 		if (reps >= 0 && --reps <= 0)
 			break;
 		nanosleep(&tv, NULL);
 		cpureadstats();
-		dkreadstats();
-		tpreadstats();
+		drvreadstats();
 	}
 	exit(0);
 }
@@ -271,25 +266,17 @@
 		(void)printf("      tty");
 
 	if (ISSET(todo, SHOW_STATS_1)) {
-		for (i = 0; i < dk_ndrive; i++)
-			if (cur.dk_select[i])
-				(void)printf("        %9.9s ", cur.dk_name[i]);
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i])
-				(void)printf("        %9.9s ",
-					     cur_tape.name[i]);
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i])
+				(void)printf("        %9.9s ", cur.name[i]);
 	}
 
 	if (ISSET(todo, SHOW_STATS_2)) {
-		for (i = 0; i < dk_ndrive; i++)
-			if (cur.dk_select[i])
-				(void)printf("        %9.9s ", cur.dk_name[i]);
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i])
-				(void)printf("        %9.9s ",
-					     cur_tape.name[i]);
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i])
+				(void)printf("        %9.9s ", cur.name[i]);
 	}
-	
+
 	if (ISSET(todo, SHOW_CPU))
 		(void)printf("            CPU");
 
@@ -300,15 +287,8 @@
 		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("  KB/t  xfr  MB   ");
-				else
-					(void)printf("  KB/t  t/s  MB/s ");
-			}
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i]) {
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i]) {
 				if (ISSET(todo, SHOW_TOTALS))
 					(void)printf("  KB/t  xfr  MB   ");
 				else
@@ -317,11 +297,8 @@
 	}
 
 	if (ISSET(todo, SHOW_STATS_2)) {
-		for (i = 0; i < dk_ndrive; i++)
-			if (cur.dk_select[i])
-				(void)printf("    KB   xfr time ");
-		for (i = 0; i < tp_ndrive; i++)
-			if (cur_tape.select[i])
+		for (i = 0; i < ndrive; i++)
+			if (cur.select[i])
 				(void)printf("    KB   xfr time ");
 	}
 
@@ -331,150 +308,33 @@
 }
 
 static void
-disk_stats(double etime)
-{
-	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_rxfer[dn] + cur.dk_wxfer[dn])
-			mbps = ((cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) /
-			    1024.0) / (cur.dk_rxfer[dn] + cur.dk_wxfer[dn]);
-		else
-			mbps = 0.0;
-		(void)printf(" %5.2f", mbps);
-
-					/* average transfers per second. */
-		(void)printf(" %4.0f",
-		    (cur.dk_rxfer[dn] + cur.dk_wxfer[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_rbytes[dn] + cur.dk_wbytes[dn]) /
-			    (double)(1024 * 1024);
-		else
-			mbps = 0;
-		(void)printf(" %5.2f ", mbps / etime);
-	}
-}
-
-static void
-disk_stats2(double etime)
-{
-	int dn;
-	double atime;
-
-	for (dn = 0; dn < dk_ndrive; ++dn) {
-		if (!cur.dk_select[dn])
-			continue;
-
-					/* average kbytes per second. */
-		(void)printf(" %5.0f",
-		    (cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) / 1024.0 / etime);
-
-					/* average transfers per second. */
-		(void)printf(" %5.0f",
-		    (cur.dk_rxfer[dn] + cur.dk_wxfer[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
-disk_statsx(double etime)
-{
-	int dn;
-	double atime, kbps;
-
-	for (dn = 0; dn < dk_ndrive; ++dn) {
-		if (!cur.dk_select[dn])
-			continue;
-
-		(void)printf("%-8.8s", cur.dk_name[dn]);
-
-					/* average read Kbytes per transfer */
-		if (cur.dk_rxfer[dn])
-			kbps = (cur.dk_rbytes[dn] / 1024.0) / cur.dk_rxfer[dn];
-		else
-			kbps = 0.0;
-		(void)printf(" %8.2f", kbps);
-
-					/* average read transfers
-					   (per second) */
-		(void)printf(" %6.0f", cur.dk_rxfer[dn] / etime);
-
-					/* time read busy in disk activity */
-		atime = (double)cur.dk_time[dn].tv_sec +
-		    ((double)cur.dk_time[dn].tv_usec / (double)1000000);
-		(void)printf(" %6.2f", atime / etime);
-
-					/* average read megabytes
-					   (per second) */
-		(void)printf(" %8.2f",
-		    cur.dk_rbytes[dn] / (1024.0 * 1024) / etime);
-
-
-					/* average write Kbytes per transfer */
-		if (cur.dk_wxfer[dn])
-			kbps = (cur.dk_wbytes[dn] / 1024.0) / cur.dk_wxfer[dn];
-		else
-			kbps = 0.0;
-		(void)printf("   %8.2f", kbps);
-
-					/* average write transfers
-					   (per second) */
-		(void)printf(" %6.0f", cur.dk_wxfer[dn] / etime);
-
-					/* time write busy in disk activity */
-		atime = (double)cur.dk_time[dn].tv_sec +
-		    ((double)cur.dk_time[dn].tv_usec / (double)1000000);
-		(void)printf(" %6.2f", atime / etime);
-
-					/* average write megabytes
-					   (per second) */
-		(void)printf(" %8.2f\n",
-		    cur.dk_wbytes[dn] / (1024.0 * 1024) / etime);
-	}
-}
-
-static void
-tape_stats(double etime)
+drive_stats(double etime)
 {
 	int dn;
 	double atime, mbps;
 
-	for (dn = 0; dn < tp_ndrive; ++dn) {
-		if (!cur_tape.select[dn])
+	for (dn = 0; dn < ndrive; ++dn) {
+		if (!cur.select[dn])
 			continue;
 					/* average Kbytes per transfer. */
-		if (cur_tape.rxfer[dn] + cur_tape.wxfer[dn])
-			mbps = ((cur_tape.rbytes[dn] + cur_tape.wbytes[dn]) /
-			    1024.0) / (cur_tape.rxfer[dn] + cur_tape.wxfer[dn]);
+		if (cur.rxfer[dn] + cur.wxfer[dn])
+			mbps = ((cur.rbytes[dn] + cur.wbytes[dn]) /
+			    1024.0) / (cur.rxfer[dn] + cur.wxfer[dn]);
 		else
 			mbps = 0.0;
 		(void)printf(" %5.2f", mbps);
 
 					/* average transfers per second. */
 		(void)printf(" %4.0f",
-		    (cur_tape.rxfer[dn] + cur_tape.wxfer[dn]) / etime);
+		    (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
 
-					/* time busy in disk activity */
-		atime = (double)cur_tape.time[dn].tv_sec +
-		    ((double)cur_tape.time[dn].tv_usec / (double)1000000);
+					/* time busy in drive activity */
+		atime = (double)cur.time[dn].tv_sec +
+		    ((double)cur.time[dn].tv_usec / (double)1000000);
 
 					/* Megabytes per second. */
 		if (atime != 0.0)
-			mbps = (cur_tape.rbytes[dn] + cur_tape.wbytes[dn]) /
+			mbps = (cur.rbytes[dn] + cur.wbytes[dn]) /
 			    (double)(1024 * 1024);
 		else
 			mbps = 0;
@@ -483,84 +343,84 @@
 }
 
 static void
-tape_stats2(double etime)
+drive_stats2(double etime)
 {
 	int dn;
 	double atime;
 
-	for (dn = 0; dn < tp_ndrive; ++dn) {
-		if (!cur_tape.select[dn])
+	for (dn = 0; dn < ndrive; ++dn) {
+		if (!cur.select[dn])
 			continue;
 
 					/* average kbytes per second. */
 		(void)printf(" %5.0f",
-		    (cur_tape.rbytes[dn] + cur_tape.wbytes[dn]) / 1024.0 / etime);
+		    (cur.rbytes[dn] + cur.wbytes[dn]) / 1024.0 / etime);
 
 					/* average transfers per second. */
 		(void)printf(" %5.0f",
-		    (cur_tape.rxfer[dn] + cur_tape.wxfer[dn]) / etime);
+		    (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
 
-					/* average time busy in disk activity */
-		atime = (double)cur_tape.time[dn].tv_sec +
-		    ((double)cur_tape.time[dn].tv_usec / (double)1000000);
+					/* average time busy in drive activity */
+		atime = (double)cur.time[dn].tv_sec +
+		    ((double)cur.time[dn].tv_usec / (double)1000000);
 		(void)printf(" %4.2f ", atime / etime);
 	}
 }
 
 static void
-tape_statsx(double etime)
+drive_statsx(double etime)
 {
 	int dn;
 	double atime, kbps;
 
-	for (dn = 0; dn < tp_ndrive; ++dn) {
-		if (!cur_tape.select[dn])
+	for (dn = 0; dn < ndrive; ++dn) {
+		if (!cur.select[dn])
 			continue;
 
-		(void)printf("%-8.8s", cur_tape.name[dn]);
+		(void)printf("%-8.8s", cur.name[dn]);
 
 					/* average read Kbytes per transfer */
-		if (cur.dk_rxfer[dn])
-			kbps = (cur_tape.rbytes[dn] / 1024.0) / cur_tape.rxfer[dn];
+		if (cur.rxfer[dn])
+			kbps = (cur.rbytes[dn] / 1024.0) / cur.rxfer[dn];
 		else
 			kbps = 0.0;
 		(void)printf(" %8.2f", kbps);
 
 					/* average read transfers
 					   (per second) */
-		(void)printf(" %6.0f", cur_tape.rxfer[dn] / etime);
+		(void)printf(" %6.0f", cur.rxfer[dn] / etime);
 
-					/* time read busy in disk activity */
-		atime = (double)cur_tape.time[dn].tv_sec +
-		    ((double)cur_tape.time[dn].tv_usec / (double)1000000);
+					/* time read busy in drive activity */
+		atime = (double)cur.time[dn].tv_sec +
+		    ((double)cur.time[dn].tv_usec / (double)1000000);
 		(void)printf(" %6.2f", atime / etime);
 
 					/* average read megabytes
 					   (per second) */
 		(void)printf(" %8.2f",
-		    cur_tape.rbytes[dn] / (1024.0 * 1024) / etime);
+		    cur.rbytes[dn] / (1024.0 * 1024) / etime);
 
 
 					/* average write Kbytes per transfer */
-		if (cur_tape.wxfer[dn])
-			kbps = (cur_tape.wbytes[dn] / 1024.0) / cur_tape.wxfer[dn];
+		if (cur.wxfer[dn])
+			kbps = (cur.wbytes[dn] / 1024.0) / cur.wxfer[dn];
 		else
 			kbps = 0.0;
 		(void)printf("   %8.2f", kbps);
 
 					/* average write transfers
 					   (per second) */
-		(void)printf(" %6.0f", cur_tape.wxfer[dn] / etime);
+		(void)printf(" %6.0f", cur.wxfer[dn] / etime);
 
-					/* time write busy in disk activity */
-		atime = (double)cur_tape.time[dn].tv_sec +
-		    ((double)cur_tape.time[dn].tv_usec / (double)1000000);
+					/* time write busy in drive activity */
+		atime = (double)cur.time[dn].tv_sec +
+		    ((double)cur.time[dn].tv_usec / (double)1000000);
 		(void)printf(" %6.2f", atime / etime);
 
 					/* average write megabytes
 					   (per second) */
 		(void)printf(" %8.2f\n",
-		    cur_tape.wbytes[dn] / (1024.0 * 1024) / etime);
+		    cur.wbytes[dn] / (1024.0 * 1024) / etime);
 	}
 }
 
@@ -605,8 +465,7 @@
 		etime = 1.0;
 
 	if (ISSET(todo, SHOW_STATS_X)) {
-		disk_statsx(etime);
-		tape_statsx(etime);
+		drive_statsx(etime);
 		goto out;
 	}
 
@@ -614,16 +473,14 @@
 		printf("%4.0f %4.0f", cur.tk_nin / etime, cur.tk_nout / etime);
 
 	if (ISSET(todo, SHOW_STATS_1)) {
-		disk_stats(etime);
-		tape_stats(etime);
+		drive_stats(etime);
 	}
-	
+
 
 	if (ISSET(todo, SHOW_STATS_2)) {
-		disk_stats2(etime);
-		tape_stats2(etime);
+		drive_stats2(etime);
 	}
-	
+
 
 	if (ISSET(todo, SHOW_CPU))
 		cpustats();
@@ -656,19 +513,13 @@
 			break;
 #endif
 		tried++;
-		for (i = 0; i < dk_ndrive; i++) {
-			if (strcmp(cur.dk_name[i], *argv))
+		for (i = 0; i < ndrive; i++) {
+			if (strcmp(cur.name[i], *argv))
 				continue;
-			cur.dk_select[i] = 1;
-			++ndrives;
-		}
-		
-		for (i = 0; i < tp_ndrive; i++) {
-			if (strcmp(cur_tape.name[i], *argv))
-				continue;
-			cur_tape.select[i] = 1;
+			cur.select[i] = 1;
 			++ndrives;
 		}
+
 	}
 
 	if (ndrives == 0 && tried == 0) {
@@ -677,15 +528,11 @@
 		 * if none specified.
 		 */
 		maxdrives = (ISSET(todo, SHOW_STATS_X) ||
-			     (dk_ndrive + tp_ndrive) < defdrives)
-			? (dk_ndrive + tp_ndrive) : defdrives;
+			     ndrive < defdrives)
+			? (ndrive) : defdrives;
 		for (i = 0; i < maxdrives; i++) {
-			if (i >= dk_ndrive) {
-				cur_tape.select[i - dk_ndrive] = 1;
-			} else {
-				cur.dk_select[i] = 1;
-			}
-			
+			cur.select[i] = 1;
+
 			++ndrives;
 			if (!ISSET(todo, SHOW_STATS_X) && ndrives == defdrives)
 				break;



-- 
Brett Lymn