From f06ef22e8edd02ba79946707dea04a4804bb1cd9 Mon Sep 17 00:00:00 2001 From: tholo Date: Sun, 3 Mar 1996 02:51:20 +0000 Subject: [PATCH] Working disk statistics; NetBSD PR 2160 --- usr.bin/vmstat/Makefile | 7 +- usr.bin/vmstat/dkstats.c | 271 +++++++++++++++++++++++++++++++++++++++ usr.bin/vmstat/dkstats.h | 50 ++++++++ usr.bin/vmstat/names.c | 237 ---------------------------------- usr.bin/vmstat/vmstat.8 | 10 +- usr.bin/vmstat/vmstat.c | 118 +++++++---------- 6 files changed, 378 insertions(+), 315 deletions(-) create mode 100644 usr.bin/vmstat/dkstats.c create mode 100644 usr.bin/vmstat/dkstats.h delete mode 100644 usr.bin/vmstat/names.c diff --git a/usr.bin/vmstat/Makefile b/usr.bin/vmstat/Makefile index ba168772d1f..9718e67d6f0 100644 --- a/usr.bin/vmstat/Makefile +++ b/usr.bin/vmstat/Makefile @@ -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 diff --git a/usr.bin/vmstat/dkstats.c b/usr.bin/vmstat/dkstats.c new file mode 100644 index 00000000000..f7cc56f9a91 --- /dev/null +++ b/usr.bin/vmstat/dkstats.c @@ -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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 */ +#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 index 00000000000..d22e84bf37e --- /dev/null +++ b/usr.bin/vmstat/dkstats.h @@ -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 +#include + +/* 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 index 9fc46637315..00000000000 --- a/usr.bin/vmstat/names.c +++ /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 -#else -#include -#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 - -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 - -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 - -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 */ diff --git a/usr.bin/vmstat/vmstat.8 b/usr.bin/vmstat/vmstat.8 index 5182703ba10..119916d11b8 100644 --- a/usr.bin/vmstat/vmstat.8 +++ b/usr.bin/vmstat/vmstat.8 @@ -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), diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index e38fa9763fc..ad62eebd330 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -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 #include #include +#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) -- 2.20.1