Working disk statistics; NetBSD PR 2160
authortholo <tholo@openbsd.org>
Sun, 3 Mar 1996 02:51:20 +0000 (02:51 +0000)
committertholo <tholo@openbsd.org>
Sun, 3 Mar 1996 02:51:20 +0000 (02:51 +0000)
usr.bin/vmstat/Makefile
usr.bin/vmstat/dkstats.c [new file with mode: 0644]
usr.bin/vmstat/dkstats.h [new file with mode: 0644]
usr.bin/vmstat/names.c [deleted file]
usr.bin/vmstat/vmstat.8
usr.bin/vmstat/vmstat.c

index ba16877..9718e67 100644 (file)
@@ -1,3 +1,4 @@
+#      $OpenBSD: Makefile,v 1.2 1996/03/03 02:51:20 tholo Exp $
 #      $NetBSD: Makefile,v 1.14 1995/05/07 22:15:57 cgd Exp $
 #      @(#)Makefile    8.1 (Berkeley) 6/6/93
 
@@ -5,11 +6,13 @@ PROG= vmstat
 .if (${MACHINE_ARCH} == "m68k")
 CFLAGS+=-D${MACHINE}
 .endif
+
 CFLAGS+=-I${.CURDIR}/../../sys/arch
+SRCS=  dkstats.c vmstat.c
 MAN=   vmstat.8
+DPADD= ${LIBKVM}
+LDADD= -lkvm
 BINGRP=        kmem
 BINMODE=2555
-DPADD= names.c ${LIBKVM}
-LDADD= -lkvm
 
 .include <bsd.prog.mk>
diff --git a/usr.bin/vmstat/dkstats.c b/usr.bin/vmstat/dkstats.c
new file mode 100644 (file)
index 0000000..f7cc56f
--- /dev/null
@@ -0,0 +1,271 @@
+/*     $OpenBSD: dkstats.c,v 1.1 1996/03/03 02:51:20 tholo Exp $       */
+
+/*
+ * Copyright (c) 1996 John M. Vinopal (banshee@resort.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    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 for the NetBSD Project
+ *      by John M. Vinopal.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/dkstat.h>
+#include <sys/time.h>
+#include <sys/disk.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <limits.h>
+#include <nlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "dkstats.h"
+
+static struct nlist namelist[] = {
+#define        X_TK_NIN        0
+       { "_tk_nin" },          /* tty characters in */
+#define        X_TK_NOUT       1
+       { "_tk_nout" },         /* tty characters out */
+#define        X_CP_TIME       2
+       { "_cp_time" },         /* system timer ticks */
+#define        X_HZ            3
+       { "_hz" },              /* ticks per second */
+#define        X_STATHZ        4
+       { "_stathz" },
+#define X_DISK_COUNT   5
+       { "_disk_count" },      /* number of disks */
+#define X_DISKLIST     6
+       { "_disklist" },        /* TAILQ of disks */
+       { NULL },
+};
+
+/* Structures to hold the statistics. */
+struct _disk   cur, last;
+
+/* Kernel pointers: nlistf and memf defined in calling program. */
+static kvm_t   *kd = NULL;
+extern char    *nlistf;
+extern char    *memf;
+
+/* Pointer to list of disks. */
+static struct disk     *dk_drivehead = NULL;
+
+/* Backward compatibility references. */
+int            dk_ndrive = 0;
+int            *dk_select;
+char           **dr_name;
+
+#define        KVM_ERROR(_string) {                                            \
+       warnx((_string));                                               \
+       errx(1, kvm_geterr(kd));                                        \
+}
+
+/*
+ * Dereference the namelist pointer `v' and fill in the local copy 
+ * 'p' which is of size 's'.
+ */
+#define deref_nl(v, p, s) deref_kptr((void *)namelist[(v)].n_value, (p), (s));
+
+/* Missing from <sys/time.h> */
+#define timerset(tvp, uvp) ((uvp)->tv_sec = (tvp)->tv_sec);            \
+                          ((uvp)->tv_usec = (tvp)->tv_usec)
+
+void dkswap __P((void));
+void dkreadstats __P((void));
+int dkinit __P((int));
+static void deref_kptr __P(( void *, void *, size_t));
+
+/*
+ * Take the delta between the present values and the last recorded
+ * values, storing the present values in the 'last' structure, and
+ * the delta values in the 'cur' structure.
+ */
+void
+dkswap()
+{
+#define SWAP(fld)              tmp = cur.fld;                          \
+                               cur.fld -= last.fld;                    \
+                               last.fld = tmp
+       u_int64_t tmp;
+       int     i;
+
+       for (i = 0; i < dk_ndrive; i++) {
+               struct timeval  tmp_timer;
+
+               if (!cur.dk_select[i])
+                       continue;
+
+               /* Delta Values. */
+               SWAP(dk_xfer[i]);
+               SWAP(dk_seek[i]);
+               SWAP(dk_bytes[i]);
+
+               /* Delta Time. */
+               timerclear(&tmp_timer);
+               timerset(&(cur.dk_time[i]), &tmp_timer);
+               timersub(&tmp_timer, &(last.dk_time[i]), &(cur.dk_time[i]));
+               timerclear(&(last.dk_time[i]));
+               timerset(&tmp_timer, &(last.dk_time[i]));
+       }
+       for (i = 0; i < CPUSTATES; i++) {
+               SWAP(cp_time[i]);
+       }
+       SWAP(tk_nin);
+       SWAP(tk_nout);
+
+#undef SWAP
+}
+
+/*
+ * Read the disk statistics for each disk in the disk list. 
+ * Also collect statistics for tty i/o and cpu ticks.
+ */
+void
+dkreadstats()
+{
+       struct disk     cur_disk, *p;
+       int             i;
+
+       p = dk_drivehead;
+
+       for (i = 0; i < dk_ndrive; i++) {
+               deref_kptr(p, &cur_disk, sizeof(cur_disk));
+               cur.dk_xfer[i] = cur_disk.dk_xfer;
+               cur.dk_seek[i] = cur_disk.dk_seek;
+               cur.dk_bytes[i] = cur_disk.dk_bytes;
+               timerset(&(cur_disk.dk_time), &(cur.dk_time[i]));
+               p = cur_disk.dk_link.tqe_next;
+       }
+       deref_nl(X_CP_TIME, cur.cp_time, sizeof(cur.cp_time));
+       deref_nl(X_TK_NIN, &cur.tk_nin, sizeof(cur.tk_nin));
+       deref_nl(X_TK_NOUT, &cur.tk_nout, sizeof(cur.tk_nout));
+}
+
+/*
+ * Perform all of the initialization and memory allocation needed to
+ * track disk statistics.
+ */
+int
+dkinit(select)
+int    select;
+{
+       struct disklist_head disk_head;
+       struct disk     cur_disk, *p;
+        char           errbuf[_POSIX2_LINE_MAX];
+       static int      once = 0;
+       extern int      hz;
+       int             i;
+
+       if (once)
+               return(1);
+
+       /* Open the kernel. */
+        if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
+               errx(1, "kvm_openfiles: %s", errbuf);
+
+       /* Obtain the namelist symbols from the kernel. */
+       if (kvm_nlist(kd, namelist))
+               KVM_ERROR("kvm_nlist failed to read symbols.");
+
+       /* Get the number of attached drives. */
+       deref_nl(X_DISK_COUNT, &dk_ndrive, sizeof(dk_ndrive));
+
+       if (dk_ndrive < 0)
+               errx(1, "invalid _disk_count %d.", dk_ndrive);
+       else if (dk_ndrive == 0) {
+               warnx("No drives attached.");
+       }
+       else {
+               /* Get a pointer to the first disk. */
+               deref_nl(X_DISKLIST, &disk_head, sizeof(disk_head));
+               dk_drivehead = disk_head.tqh_first;
+       }
+
+       /* Get ticks per second. */
+       deref_nl(X_STATHZ, &hz, sizeof(hz));
+       if (!hz)
+               deref_nl(X_HZ, &hz, sizeof(hz));
+
+       /* allocate space for the statistics */
+       cur.dk_time = calloc(dk_ndrive, sizeof(struct timeval));
+       cur.dk_xfer = calloc(dk_ndrive, sizeof(u_int64_t));
+       cur.dk_seek = calloc(dk_ndrive, sizeof(u_int64_t));
+       cur.dk_bytes = calloc(dk_ndrive, sizeof(u_int64_t));
+       last.dk_time = calloc(dk_ndrive, sizeof(struct timeval));
+       last.dk_xfer = calloc(dk_ndrive, sizeof(u_int64_t));
+       last.dk_seek = calloc(dk_ndrive, sizeof(u_int64_t));
+       last.dk_bytes = calloc(dk_ndrive, sizeof(u_int64_t));
+       cur.dk_select = calloc(dk_ndrive, sizeof(int));
+       cur.dk_name = calloc(dk_ndrive, sizeof(char *));
+       
+       if (!cur.dk_time || !cur.dk_xfer || !cur.dk_seek || !cur.dk_bytes
+           || !last.dk_time || !last.dk_xfer || !last.dk_seek || !last.dk_bytes
+           || !cur.dk_select || !cur.dk_name)
+               errx(1, "Memory allocation failure.");
+
+       /* Set up the compatibility interfaces. */
+       dk_select = cur.dk_select;
+       dr_name = cur.dk_name;
+
+       /* Read the disk names and set intial selection. */
+       p = dk_drivehead;
+       for (i = 0; i < dk_ndrive; i++) {
+               char    buf[10];
+               deref_kptr(p, &cur_disk, sizeof(cur_disk));
+               deref_kptr(cur_disk.dk_name, buf, sizeof(buf));
+               cur.dk_name[i] = strdup(buf);
+               cur.dk_select[i] = select;
+
+               p = cur_disk.dk_link.tqe_next;
+       }
+
+       /* Never do this initalization again. */
+       once = 1;
+       return(1);
+}
+
+/*
+ * Dereference the kernel pointer `kptr' and fill in the local copy 
+ * pointed to by `ptr'.  The storage space must be pre-allocated,
+ * and the size of the copy passed in `len'.
+ */
+static void
+deref_kptr(kptr, ptr, len)
+       void *kptr, *ptr;
+       size_t len;
+{
+       char buf[128];
+
+       if (kvm_read(kd, (u_long)kptr, (char *)ptr, len) != len) {
+               bzero(buf, sizeof(buf));
+               snprintf(buf, (sizeof(buf) - 1),
+                    "can't dereference kptr 0x%x", (uint)kptr);
+               KVM_ERROR(buf);
+       }
+}
diff --git a/usr.bin/vmstat/dkstats.h b/usr.bin/vmstat/dkstats.h
new file mode 100644 (file)
index 0000000..d22e84b
--- /dev/null
@@ -0,0 +1,50 @@
+/*     $OpenBSD: dkstats.h,v 1.1 1996/03/03 02:51:21 tholo Exp $       */
+
+/*
+ * Copyright (c) 1996 John M. Vinopal (banshee@resort.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    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 for the NetBSD Project
+ *      by John M. Vinopal.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/time.h>
+#include <unistd.h>
+
+/* poseur disk entry to hold the information we're interested in. */
+struct _disk {
+       int              *dk_select;    /* Display stats for selected disks. */
+       char            **dk_name;      /* Disk names (sd0, wd1, etc). */
+       u_int64_t        *dk_xfer;      /* # of transfers. */
+       u_int64_t        *dk_seek;      /* # of seeks (currently unused). */
+       u_int64_t        *dk_bytes;     /* # of bytes transfered. */
+       struct timeval   *dk_time;      /* Time spent in disk i/o. */
+       long    tk_nin;                 /* TTY Chars in. */
+       long    tk_nout;                /* TTY Chars out. */
+       long    cp_time[CPUSTATES];     /* System timer ticks. */
+};
+
diff --git a/usr.bin/vmstat/names.c b/usr.bin/vmstat/names.c
deleted file mode 100644 (file)
index 9fc4663..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*     $NetBSD: names.c,v 1.18 1995/12/17 05:30:05 jonathan Exp $      */
-
-/*-
- * Copyright (c) 1991, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    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 by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)names.c     8.1 (Berkeley) 6/6/93
- */
-
-#if !defined(hp300) && !defined(tahoe) && !defined(luna68k) && !defined(mips)
-char *defdrives[] = { 0 };
-#endif
-
-#if defined(i386)
-int
-read_names()
-{
-       return 1;
-}
-#endif
-
-#if defined(pc532)
-int
-read_names()
-{
-       return 1;
-}
-#endif
-
-#if defined(sparc)
-int
-read_names()
-{
-       return 1;
-}
-#endif
-
-#if defined(m68k) && !defined(hp300)
-int
-read_names()
-{
-       return(1);
-}
-#endif
-
-#if defined(__alpha__)
-int
-read_names()
-{
-       return 1;
-}
-#endif
-
-#if defined(vax)
-int
-read_names()
-{
-       return 1;
-}
-#endif
-
-#if defined(hp300) || defined(luna68k)
-#if defined(hp300)
-#include <hp300/dev/device.h>
-#else
-#include <luna68k/dev/device.h>
-#endif
-
-char *defdrives[] = { "sd0", "sd1", "sd2", "rd0", "rd1", "rd2", 0 };
-
-int
-read_names()
-{
-       register char *p;
-       register u_long hp;
-       static char buf[BUFSIZ];
-       struct hp_device hdev;
-       struct driver hdrv;
-       char name[10];
-
-       hp = namelist[X_HPDINIT].n_value;
-       if (hp == 0) {
-               (void)fprintf(stderr,
-                   "disk init info not in namelist\n");
-               return (0);
-       }
-       p = buf;
-       for (;; hp += sizeof hdev) {
-               (void)kvm_read(kd, hp, &hdev, sizeof hdev);
-               if (hdev.hp_driver == 0)
-                       break;
-               if (hdev.hp_dk < 0 || hdev.hp_alive == 0 ||
-                   hdev.hp_cdriver == 0)
-                       continue;
-               (void)kvm_read(kd, (u_long)hdev.hp_driver, &hdrv, sizeof hdrv);
-               (void)kvm_read(kd, (u_long)hdrv.d_name, name, sizeof name);
-               dr_name[hdev.hp_dk] = p;
-               p += sprintf(p, "%s%d", name, hdev.hp_unit) + 1;
-       }
-       return (1);
-}
-#endif /* hp300 || luna68k */
-
-#ifdef tahoe
-#include <tahoe/vba/vbavar.h>
-
-char *defdrives[] = { "dk0", "dk1", "dk2", 0 };
-
-int
-read_names()
-{
-       register char *p;
-       struct vba_device udev, *up;
-       struct vba_driver udrv;
-       char name[10];
-       static char buf[BUFSIZ];
-
-       up = (struct vba_device *)namelist[X_VBDINIT].n_value;
-       if (up == 0) {
-               (void) fprintf(stderr,
-                   "disk init info not in namelist\n");
-               return (0);
-       }
-       p = buf;
-       for (;; up += sizeof udev) {
-               (void)kvm_read(kd, up, &udev, sizeof udev);
-               if (udev.ui_driver == 0)
-                       break;
-               if (udev.ui_dk < 0 || udev.ui_alive == 0)
-                       continue;
-               (void)kvm_read(kd, udev.ui_driver, &udrv, sizeof udrv);
-               (void)kvm_read(kd, udrv.ud_dname, name, sizeof name);
-               dr_name[udev.ui_dk] = p;
-               p += sprintf(p, "%s%d", name, udev.ui_unit);
-       }
-       return (1);
-}
-#endif /* tahoe */
-
-#ifdef sun
-#include <sundev/mbvar.h>
-
-int
-read_names()
-{
-       static int once = 0;
-       struct mb_device mdev;
-       struct mb_driver mdrv;
-       short two_char;
-       char *cp = (char *) &two_char;
-       register struct mb_device *mp;
-
-       mp = (struct mb_device *)namelist[X_MBDINIT].n_value;
-       if (mp == 0) {
-               (void)fprintf(stderr,
-                   "disk init info not in namelist\n");
-               return (0);
-       }
-       for (;; ++mp) {
-               (void)kvm_read(kd, mp++, &mdev, sizeof(mdev));
-               if (mdev.md_driver == 0)
-                       break;
-               if (mdev.md_dk < 0 || mdev.md_alive == 0)
-                       continue;
-               (void)kvm_read(kd, mdev.md_driver, &mdrv, sizeof(mdrv));
-               (void)kvm_read(kd, mdrv.mdr_dname, &two_char, sizeof(two_char));
-               (void)sprintf(dr_name[mdev.md_dk],
-                   "%c%c%d", cp[0], cp[1], mdev.md_unit);
-       }
-       return(1);
-}
-#endif /* sun */
-
-#if defined(mips)
-#include <pmax/dev/device.h>
-
-char *defdrives[] = { "rz0", "rz1", "rz2", "rz3", "rz4", "rz5", "rz6", 0 };
-
-int
-read_names()
-{
-       register char *p;
-       register u_long sp;
-       static char buf[BUFSIZ];
-       struct pmax_scsi_device sdev;
-       struct pmax_driver hdrv;
-       char name[10];
-
-       sp = namelist[X_SCSI_DINIT].n_value;
-       if (sp == 0) {
-               (void)fprintf(stderr, "disk init info not in namelist\n");
-               return (0);
-       }
-       p = buf;
-       for (;; sp += sizeof sdev) {
-               (void)kvm_read(kd, sp, &sdev, sizeof sdev);
-               if (sdev.sd_driver == 0)
-                       break;
-               if (sdev.sd_dk < 0 || sdev.sd_alive == 0 ||
-                   sdev.sd_cdriver == 0)
-                       continue;
-               (void)kvm_read(kd, (u_long)sdev.sd_driver, &hdrv, sizeof hdrv);
-               (void)kvm_read(kd, (u_long)hdrv.d_name, name, sizeof name);
-               dr_name[sdev.sd_dk] = p;
-               p += sprintf(p, "%s%d", name, sdev.sd_unit) + 1;
-       }
-       return (1);
-}
-#endif /* mips */
index 5182703..119916d 100644 (file)
@@ -76,7 +76,7 @@ startup.
 .TP
 \-M
 Extract values associated with the name list from the specified core 
-instead of the default ``/dev/kmem''.
+instead of the default ``/dev/mem''.
 .TP
 \-N
 Extract the name list from the specified system instead of the default
@@ -150,7 +150,7 @@ sr  pages scanned by clock algorithm, per-second
 .RE
 .TP
 disks
-Disk operations per second (this field is system dependent).
+Disk transfers per second.
 Typically paging will be split across the available drives.
 The header of the field is the first character of the disk name and
 the unit number.
@@ -189,10 +189,10 @@ some of the statistics are sampled in the system.
 Others vary every second and running the output for a while will make it
 apparent which are recomputed every second.
 .SH FILES
-.ta \w'/dev/kmem  'u
-/netbsd        default kernel namelist
+.ta \w'/dev/mem  'u
+/bsd   default kernel namelist
 .br
-/dev/kmem      default memory file
+/dev/mem       default memory file
 .SH SEE ALSO
 .IR fstat (1),
 .IR netstat (1),
index e38fa97..ad62eeb 100644 (file)
@@ -1,5 +1,5 @@
 /*     $NetBSD: vmstat.c,v 1.27 1995/10/10 01:17:35 cgd Exp $  */
-/*     $OpenBSD: vmstat.c,v 1.5 1996/03/01 07:35:40 tholo Exp $        */
+/*     $OpenBSD: vmstat.c,v 1.6 1996/03/03 02:51:24 tholo Exp $        */
 
 /*
  * Copyright (c) 1980, 1986, 1991, 1993
@@ -73,6 +73,7 @@ static char rcsid[] = "$NetBSD: vmstat.c,v 1.27 1995/10/10 01:17:35 cgd Exp $";
 #include <string.h>
 #include <paths.h>
 #include <limits.h>
+#include "dkstats.h"
 
 #define NEWVM                  /* XXX till old has been updated or purged */
 struct nlist namelist[] = {
@@ -150,14 +151,13 @@ struct nlist namelist[] = {
        { "" },
 };
 
-struct _disk {
-       long time[CPUSTATES];
-       long *xfer;
-} cur, last;
+/* Objects defined in dkstats.c */
+extern struct _disk    cur;
+extern char            **dr_name;
+extern int             *dk_select, dk_ndrive;
 
 struct vmmeter sum, osum;
-char   **dr_name;
-int    *dr_select, dk_ndrive, ndrives;
+int            ndrives;
 
 int    winlines = 20;
 
@@ -170,12 +170,13 @@ kvm_t *kd;
 #define        TIMESTAT        0x10
 #define        VMSTAT          0x20
 
-#include "names.c"                     /* disk names -- machine dependent */
-
 void   cpustats(), dkstats(), dointr(), domem(), dosum();
 void   dovmstat(), kread(), usage();
 void   dotimes(), doforkst();
 
+char *nlistf = NULL;
+char *memf = NULL;
+
 main(argc, argv)
        register int argc;
        register char **argv;
@@ -195,11 +196,9 @@ main(argc, argv)
                case 'c':
                        reps = atoi(optarg);
                        break;
-#ifndef notdef
                case 'f':
                        todo |= FORKSTAT;
                        break;
-#endif
                case 'i':
                        todo |= INTRSTAT;
                        break;
@@ -263,10 +262,11 @@ main(argc, argv)
        }
 
        if (todo & VMSTAT) {
-               char **getdrivedata();
+               char **choosedrives();
                struct winsize winsize;
 
-               argv = getdrivedata(argv);
+               dkinit(0);      /* Initialize disk stats, no disks selected. */
+               argv = choosedrives(argv);      /* Select disks. */
                winsize.ws_row = 0;
                (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
                if (winsize.ws_row > 0)
@@ -305,32 +305,13 @@ main(argc, argv)
 }
 
 char **
-getdrivedata(argv)
+choosedrives(argv)
        char **argv;
 {
        register int i;
        register char **cp;
        char buf[30];
 
-       kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive));
-       if (dk_ndrive <= 0) {
-               (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive);
-               exit(1);
-       }
-       dr_select = calloc((size_t)dk_ndrive, sizeof(int));
-       dr_name = calloc((size_t)dk_ndrive, sizeof(char *));
-       for (i = 0; i < dk_ndrive; i++)
-               dr_name[i] = NULL;
-       cur.xfer = calloc((size_t)dk_ndrive, sizeof(long));
-       last.xfer = calloc((size_t)dk_ndrive, sizeof(long));
-       if (!read_names())
-               exit (1);
-       for (i = 0; i < dk_ndrive; i++)
-               if (dr_name[i] == NULL) {
-                       (void)sprintf(buf, "??%d", i);
-                       dr_name[i] = strdup(buf);
-               }
-
        /*
         * Choose drives to be displayed.  Priority goes to (in order) drives
         * supplied as arguments, default drives.  If everything isn't filled
@@ -346,25 +327,15 @@ getdrivedata(argv)
                for (i = 0; i < dk_ndrive; i++) {
                        if (strcmp(dr_name[i], *argv))
                                continue;
-                       dr_select[i] = 1;
+                       dk_select[i] = 1;
                        ++ndrives;
                        break;
                }
        }
        for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
-               if (dr_select[i])
-                       continue;
-               for (cp = defdrives; *cp; cp++)
-                       if (strcmp(dr_name[i], *cp) == 0) {
-                               dr_select[i] = 1;
-                               ++ndrives;
-                               break;
-                       }
-       }
-       for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
-               if (dr_select[i])
+               if (dk_select[i])
                        continue;
-               dr_select[i] = 1;
+               dk_select[i] = 1;
                ++ndrives;
        }
        return(argv);
@@ -413,8 +384,8 @@ dovmstat(interval, reps)
        for (hdrcnt = 1;;) {
                if (!--hdrcnt)
                        printhdr();
-               kread(X_CPTIME, cur.time, sizeof(cur.time));
-               kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer) * dk_ndrive);
+               /* Read new disk statistics */
+               dkreadstats();
                kread(X_SUM, &sum, sizeof(sum));
                size = sizeof(total);
                mib[0] = CTL_VM;
@@ -425,7 +396,7 @@ dovmstat(interval, reps)
                }
                (void)printf("%2d%2d%2d",
                    total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
-#define pgtok(a) ((a) * sum.v_page_size >> 10)
+#define pgtok(a) ((a) * (sum.v_page_size >> 10))
 #define        rate(x) (((x) + halfuptime) / uptime)   /* round */
                (void)printf("%6ld%6ld ",
                    pgtok(total.t_avm), pgtok(total.t_free));
@@ -476,18 +447,29 @@ printhdr()
        register int i;
 
        (void)printf(" procs   memory     page%*s", 20, "");
-       if (ndrives > 1)
-               (void)printf("disks %*s  faults      cpu\n",
-                  ndrives * 3 - 6, "");
+       if (ndrives > 0)
+#ifdef NEWVM
+               (void)printf("%s %*sfaults   cpu\n",
+                  ((ndrives > 1) ? "disks" : "disk"),
+#else
+               (void)printf("disks %*sfaults      cpu\n",
+#endif
+                  ((ndrives > 1) ? ndrives * 3 - 4 : 0), "");
        else
-               (void)printf("%*s  faults      cpu\n", ndrives * 3, "");
-#ifndef NEWVM
-       (void)printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
+#ifdef NEWVM
+               (void)printf("%*s  faults   cpu\n",
 #else
+               (void)printf("%*s  faults      cpu\n",
+#endif
+                  ndrives * 3, "");
+
+#ifdef NEWVM
        (void)printf(" r b w   avm   fre  flt  re  pi  po  fr  sr ");
+#else
+       (void)printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
 #endif
        for (i = 0; i < dk_ndrive; i++)
-               if (dr_select[i])
+               if (dk_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");
@@ -670,25 +652,19 @@ dkstats()
        double etime;
        long tmp;
 
-       for (dn = 0; dn < dk_ndrive; ++dn) {
-               tmp = cur.xfer[dn];
-               cur.xfer[dn] -= last.xfer[dn];
-               last.xfer[dn] = tmp;
-       }
+       /* Calculate disk stat deltas. */
+       dkswap();
        etime = 0;
        for (state = 0; state < CPUSTATES; ++state) {
-               tmp = cur.time[state];
-               cur.time[state] -= last.time[state];
-               last.time[state] = tmp;
-               etime += cur.time[state];
+               etime += cur.cp_time[state];
        }
        if (etime == 0)
                etime = 1;
        etime /= hz;
        for (dn = 0; dn < dk_ndrive; ++dn) {
-               if (!dr_select[dn])
+               if (!dk_select[dn])
                        continue;
-               (void)printf("%2.0f ", cur.xfer[dn] / etime);
+               (void)printf("%2.0f ", cur.dk_xfer[dn] / etime);
        }
 }
 
@@ -700,14 +676,14 @@ cpustats()
 
        total = 0;
        for (state = 0; state < CPUSTATES; ++state)
-               total += cur.time[state];
+               total += cur.cp_time[state];
        if (total)
                pct = 100 / total;
        else
                pct = 0;
-       (void)printf("%2.0f ", (cur.time[CP_USER] + cur.time[CP_NICE]) * pct);
-       (void)printf("%2.0f ", (cur.time[CP_SYS] + cur.time[CP_INTR]) * pct);
-       (void)printf("%2.0f", cur.time[CP_IDLE] * pct);
+       (void)printf("%2.0f ", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pct);
+       (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pct);
+       (void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct);
 }
 
 #if defined(pc532)