diff options
author | Thierry Deval <tdeval@cvs.openbsd.org> | 2002-12-16 01:57:06 +0000 |
---|---|---|
committer | Thierry Deval <tdeval@cvs.openbsd.org> | 2002-12-16 01:57:06 +0000 |
commit | da3a34e76ccd83612ffbc890187c29ee4b2960c9 (patch) | |
tree | 5e7c9b8bb5df4f4ec21ea8156ecd837aee78b2e9 /usr.bin/vmstat | |
parent | 8d617ca6e54dc39ece5af3b3a927e2dbbe2d3f1f (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.c | 187 | ||||
-rw-r--r-- | usr.bin/vmstat/dkstats.h | 3 | ||||
-rw-r--r-- | usr.bin/vmstat/vmstat.c | 8 |
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; |