summaryrefslogtreecommitdiff
path: root/usr.bin/vmstat
diff options
context:
space:
mode:
authorThierry Deval <tdeval@cvs.openbsd.org>2002-12-16 01:57:06 +0000
committerThierry Deval <tdeval@cvs.openbsd.org>2002-12-16 01:57:06 +0000
commitda3a34e76ccd83612ffbc890187c29ee4b2960c9 (patch)
tree5e7c9b8bb5df4f4ec21ea8156ecd837aee78b2e9 /usr.bin/vmstat
parent8d617ca6e54dc39ece5af3b3a927e2dbbe2d3f1f (diff)
Make systat(1), iostat(8) and vmstat(8) automatically update their disk
statistics when a device is added/removed. ok deraadt@
Diffstat (limited to 'usr.bin/vmstat')
-rw-r--r--usr.bin/vmstat/dkstats.c187
-rw-r--r--usr.bin/vmstat/dkstats.h3
-rw-r--r--usr.bin/vmstat/vmstat.c8
3 files changed, 168 insertions, 30 deletions
diff --git a/usr.bin/vmstat/dkstats.c b/usr.bin/vmstat/dkstats.c
index 0c5d34e6051..fccd1b58b92 100644
--- a/usr.bin/vmstat/dkstats.c
+++ b/usr.bin/vmstat/dkstats.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dkstats.c,v 1.21 2002/09/17 19:37:40 deraadt Exp $ */
+/* $OpenBSD: dkstats.c,v 1.22 2002/12/16 01:57:04 tdeval Exp $ */
/* $NetBSD: dkstats.c,v 1.1 1996/05/10 23:19:27 thorpej Exp $ */
/*
@@ -122,7 +122,7 @@ dkswap(void)
u_int64_t tmp;
int i;
- for (i = 0; i < dk_ndrive; i++) {
+ for (i = 0; i < cur.dk_ndrive; i++) {
struct timeval tmp_timer;
if (!cur.dk_select[i])
@@ -159,23 +159,159 @@ dkreadstats(void)
#if !defined(NOKVM)
struct disk cur_disk, *p;
#endif
- int i, mib[3];
+ int i, j, mib[3];
size_t size;
+ char *disknames, *name, *bufpp, **dk_name;
struct diskstats *q;
+ last.dk_ndrive = cur.dk_ndrive;
+
if (nlistf == NULL && memf == NULL) {
- size = dk_ndrive * sizeof(struct diskstats);
+ /* Get the number of attached drives. */
+ mib[0] = CTL_HW;
+ mib[1] = HW_DISKCOUNT;
+ size = sizeof(dk_ndrive);
+ if (sysctl(mib, 2, &dk_ndrive, &size, NULL, 0) < 0 ) {
+ warn("could not read hw.diskcount");
+ dk_ndrive = 0;
+ }
+
+ if (cur.dk_ndrive != dk_ndrive) {
+ /* Re-read the disk names. */
+ dk_name = calloc(dk_ndrive, sizeof(char *));
+ if (dk_name == NULL)
+ err(1, NULL);
+ mib[0] = CTL_HW;
+ mib[1] = HW_DISKNAMES;
+ size = 0;
+ if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
+ err(1, "can't get hw.disknames");
+ disknames = malloc(size);
+ if (disknames == NULL)
+ err(1, NULL);
+ if (sysctl(mib, 2, disknames, &size, NULL, 0) < 0)
+ err(1, "can't get hw.disknames");
+ bufpp = disknames;
+ i = 0;
+ while ((name = strsep(&bufpp, ",")) != NULL) {
+ dk_name[i++] = name;
+ }
+ disknames = cur.dk_name[0]; /* To free old names. */
+
+ if (dk_ndrive < cur.dk_ndrive) {
+ for (i = 0, j = 0; i < dk_ndrive; i++, j++) {
+ while (j < cur.dk_ndrive &&
+ strcmp(cur.dk_name[j], dk_name[i]))
+ j++;
+ if (i == j) continue;
+
+ if (j >= cur.dk_ndrive) {
+ cur.dk_select[i] = 1;
+ last.dk_xfer[i] = 0;
+ last.dk_seek[i] = 0;
+ last.dk_bytes[i] = 0;
+ bzero(&last.dk_time[i],
+ sizeof(struct timeval));
+ continue;
+ }
+
+ cur.dk_select[i] = cur.dk_select[j];
+ last.dk_xfer[i] = last.dk_xfer[j];
+ last.dk_seek[i] = last.dk_seek[j];
+ last.dk_bytes[i] = last.dk_bytes[j];
+ last.dk_time[i] = last.dk_time[j];
+ }
+
+ cur.dk_select = realloc(cur.dk_select,
+ dk_ndrive * sizeof(*cur.dk_select));
+ cur.dk_xfer = realloc(cur.dk_xfer,
+ dk_ndrive * sizeof(*cur.dk_xfer));
+ cur.dk_seek = realloc(cur.dk_seek,
+ dk_ndrive * sizeof(*cur.dk_seek));
+ cur.dk_bytes = realloc(cur.dk_bytes,
+ dk_ndrive * sizeof(*cur.dk_bytes));
+ cur.dk_time = realloc(cur.dk_time,
+ dk_ndrive * sizeof(*cur.dk_time));
+ last.dk_xfer = realloc(last.dk_xfer,
+ dk_ndrive * sizeof(*last.dk_xfer));
+ last.dk_seek = realloc(last.dk_seek,
+ dk_ndrive * sizeof(*last.dk_seek));
+ last.dk_bytes = realloc(last.dk_bytes,
+ dk_ndrive * sizeof(*last.dk_bytes));
+ last.dk_time = realloc(last.dk_time,
+ dk_ndrive * sizeof(*last.dk_time));
+ } else {
+ cur.dk_select = realloc(cur.dk_select,
+ dk_ndrive * sizeof(*cur.dk_select));
+ cur.dk_xfer = realloc(cur.dk_xfer,
+ dk_ndrive * sizeof(*cur.dk_xfer));
+ cur.dk_seek = realloc(cur.dk_seek,
+ dk_ndrive * sizeof(*cur.dk_seek));
+ cur.dk_bytes = realloc(cur.dk_bytes,
+ dk_ndrive * sizeof(*cur.dk_bytes));
+ cur.dk_time = realloc(cur.dk_time,
+ dk_ndrive * sizeof(*cur.dk_time));
+ last.dk_xfer = realloc(last.dk_xfer,
+ dk_ndrive * sizeof(*last.dk_xfer));
+ last.dk_seek = realloc(last.dk_seek,
+ dk_ndrive * sizeof(*last.dk_seek));
+ last.dk_bytes = realloc(last.dk_bytes,
+ dk_ndrive * sizeof(*last.dk_bytes));
+ last.dk_time = realloc(last.dk_time,
+ dk_ndrive * sizeof(*last.dk_time));
+
+ for (i = dk_ndrive - 1, j = cur.dk_ndrive - 1;
+ i >= 0; i--) {
+
+ if (j < 0 ||
+ strcmp(cur.dk_name[j], dk_name[i]))
+ {
+ cur.dk_select[i] = 1;
+ last.dk_xfer[i] = 0;
+ last.dk_seek[i] = 0;
+ last.dk_bytes[i] = 0;
+ bzero(&last.dk_time[i],
+ sizeof(struct timeval));
+ continue;
+ }
+
+ if (i > j) {
+ cur.dk_select[i] =
+ cur.dk_select[j];
+ last.dk_xfer[i] =
+ last.dk_xfer[j];
+ last.dk_seek[i] =
+ last.dk_seek[j];
+ last.dk_bytes[i] =
+ last.dk_bytes[j];
+ last.dk_time[i] =
+ last.dk_time[j];
+ }
+ j--;
+ }
+ }
+
+ cur.dk_ndrive = dk_ndrive;
+ free(disknames);
+ cur.dk_name = dk_name;
+ dr_name = cur.dk_name;
+ dk_select = cur.dk_select;
+ }
+
+ size = cur.dk_ndrive * sizeof(struct diskstats);
mib[0] = CTL_HW;
mib[1] = HW_DISKSTATS;
q = malloc(size);
if (q == NULL)
err(1, NULL);
if (sysctl(mib, 2, q, &size, NULL, 0) < 0) {
+#ifdef DEBUG
warn("could not read hw.diskstats");
- bzero(q, dk_ndrive * sizeof(struct diskstats));
+#endif /* DEBUG */
+ bzero(q, cur.dk_ndrive * sizeof(struct diskstats));
}
- for (i = 0; i < dk_ndrive; i++) {
+ for (i = 0; i < cur.dk_ndrive; i++) {
cur.dk_xfer[i] = q[i].ds_xfer;
cur.dk_seek[i] = q[i].ds_seek;
cur.dk_bytes[i] = q[i].ds_bytes;
@@ -210,7 +346,7 @@ dkreadstats(void)
#if !defined(NOKVM)
p = dk_drivehead;
- for (i = 0; i < dk_ndrive; i++) {
+ for (i = 0; i < cur.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;
@@ -268,10 +404,10 @@ dkinit(int select)
KVM_ERROR("kvm_nlist failed to read symbols.");
/* Get the number of attached drives. */
- deref_nl(X_DISK_COUNT, &dk_ndrive, sizeof(dk_ndrive));
+ deref_nl(X_DISK_COUNT, &cur.dk_ndrive, sizeof(cur.dk_ndrive));
- if (dk_ndrive < 0)
- errx(1, "invalid _disk_count %d.", dk_ndrive);
+ if (cur.dk_ndrive < 0)
+ errx(1, "invalid _disk_count %d.", cur.dk_ndrive);
/* Get a pointer to the first disk. */
deref_nl(X_DISKLIST, &disk_head, sizeof(disk_head));
@@ -286,10 +422,10 @@ dkinit(int select)
/* Get the number of attached drives. */
mib[0] = CTL_HW;
mib[1] = HW_DISKCOUNT;
- size = sizeof(dk_ndrive);
- if (sysctl(mib, 2, &dk_ndrive, &size, NULL, 0) < 0 ) {
+ size = sizeof(cur.dk_ndrive);
+ if (sysctl(mib, 2, &cur.dk_ndrive, &size, NULL, 0) < 0 ) {
warn("could not read hw.diskcount");
- dk_ndrive = 0;
+ cur.dk_ndrive = 0;
}
/* Get ticks per second. */
@@ -304,16 +440,16 @@ dkinit(int select)
}
/* 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 *));
+ cur.dk_time = calloc(cur.dk_ndrive, sizeof(struct timeval));
+ cur.dk_xfer = calloc(cur.dk_ndrive, sizeof(u_int64_t));
+ cur.dk_seek = calloc(cur.dk_ndrive, sizeof(u_int64_t));
+ cur.dk_bytes = calloc(cur.dk_ndrive, sizeof(u_int64_t));
+ last.dk_time = calloc(cur.dk_ndrive, sizeof(struct timeval));
+ last.dk_xfer = calloc(cur.dk_ndrive, sizeof(u_int64_t));
+ last.dk_seek = calloc(cur.dk_ndrive, sizeof(u_int64_t));
+ last.dk_bytes = calloc(cur.dk_ndrive, sizeof(u_int64_t));
+ cur.dk_select = calloc(cur.dk_ndrive, sizeof(int));
+ cur.dk_name = calloc(cur.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 ||
@@ -321,10 +457,11 @@ dkinit(int select)
errx(1, "Memory allocation failure.");
/* Set up the compatibility interfaces. */
+ dk_ndrive = cur.dk_ndrive;
dk_select = cur.dk_select;
dr_name = cur.dk_name;
- /* Read the disk names and set intial selection. */
+ /* Read the disk names and set initial selection. */
if (nlistf == NULL && memf == NULL) {
mib[0] = CTL_HW;
mib[1] = HW_DISKNAMES;
@@ -345,7 +482,7 @@ dkinit(int select)
} else {
#if !defined(NOKVM)
p = dk_drivehead;
- for (i = 0; i < dk_ndrive; i++) {
+ for (i = 0; i < cur.dk_ndrive; i++) {
char buf[10];
deref_kptr(p, &cur_disk, sizeof(cur_disk));
diff --git a/usr.bin/vmstat/dkstats.h b/usr.bin/vmstat/dkstats.h
index 231b7aa9240..5080d7f5d2f 100644
--- a/usr.bin/vmstat/dkstats.h
+++ b/usr.bin/vmstat/dkstats.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dkstats.h,v 1.7 2002/02/16 21:27:58 millert Exp $ */
+/* $OpenBSD: dkstats.h,v 1.8 2002/12/16 01:57:04 tdeval Exp $ */
/* $NetBSD: dkstats.h,v 1.1 1996/05/10 23:19:28 thorpej Exp $ */
/*
@@ -38,6 +38,7 @@
/* poseur disk entry to hold the information we're interested in. */
struct _disk {
+ int dk_ndrive; /* # of drives. */
int *dk_select; /* Display stats for selected disks. */
char **dk_name; /* Disk names (sd0, wd1, etc). */
u_int64_t *dk_xfer; /* # of transfers. */
diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c
index 0ae8ee4cbb3..d341878c388 100644
--- a/usr.bin/vmstat/vmstat.c
+++ b/usr.bin/vmstat/vmstat.c
@@ -1,5 +1,5 @@
/* $NetBSD: vmstat.c,v 1.29.4.1 1996/06/05 00:21:05 cgd Exp $ */
-/* $OpenBSD: vmstat.c,v 1.72 2002/09/17 19:37:40 deraadt Exp $ */
+/* $OpenBSD: vmstat.c,v 1.73 2002/12/16 01:57:04 tdeval Exp $ */
/*
* Copyright (c) 1980, 1986, 1991, 1993
@@ -117,7 +117,7 @@ struct nlist namelist[] = {
};
/* Objects defined in dkstats.c */
-extern struct _disk cur;
+extern struct _disk cur, last;
extern char **dr_name;
extern int *dk_select, dk_ndrive;
@@ -386,10 +386,10 @@ dovmstat(u_int interval, int reps)
hz = clkinfo.stathz;
for (hdrcnt = 1;;) {
- if (!--hdrcnt)
- printhdr();
/* Read new disk statistics */
dkreadstats();
+ if (!--hdrcnt || last.dk_ndrive != cur.dk_ndrive)
+ printhdr();
if (nlistf == NULL && memf == NULL) {
size = sizeof(struct uvmexp);
mib[0] = CTL_VM;