Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Use I/O timestamps to compute disk statistics for better pre...
details: https://anonhg.NetBSD.org/src/rev/845a1f421295
branches: trunk
changeset: 354932:845a1f421295
user: mlelstv <mlelstv%NetBSD.org@localhost>
date: Tue Jul 04 21:19:33 2017 +0000
description:
Use I/O timestamps to compute disk statistics for better precision.
Disk statistics are collected in a fixed size array, that got corrupted
when a disk was detached. Adapt by skipping entries of detached disks
and detect reused disknames at the array end.
diffstat:
usr.bin/vmstat/drvstats.c | 87 +++++++++++++++++++++++++++++++++++++---------
usr.bin/vmstat/drvstats.h | 9 ++--
usr.bin/vmstat/vmstat.c | 13 ++++--
usr.sbin/iostat/iostat.c | 64 +++++++++++++++++++++++----------
4 files changed, 127 insertions(+), 46 deletions(-)
diffs (truncated from 435 to 300 lines):
diff -r f2f2fcfa8bb7 -r 845a1f421295 usr.bin/vmstat/drvstats.c
--- a/usr.bin/vmstat/drvstats.c Tue Jul 04 10:25:45 2017 +0000
+++ b/usr.bin/vmstat/drvstats.c Tue Jul 04 21:19:33 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: drvstats.c,v 1.10 2017/03/05 23:07:12 mlelstv Exp $ */
+/* $NetBSD: drvstats.c,v 1.11 2017/07/04 21:19:33 mlelstv Exp $ */
/*
* Copyright (c) 1996 John M. Vinopal
@@ -97,6 +97,31 @@
if (!cur.select[i])
continue;
+ /*
+ * When a drive is replaced with one of the same
+ * name, the previous statistics are invalid. Try
+ * to detect this by validating counters and timestamp
+ */
+ if ((cur.rxfer[i] == 0 && cur.wxfer[i] == 0)
+ || cur.rxfer[i] - last.rxfer[i] > INT64_MAX
+ || cur.wxfer[i] - last.wxfer[i] > INT64_MAX
+ || cur.seek[i] - last.seek[i] > INT64_MAX
+ || (cur.timestamp[i].tv_sec == 0 &&
+ cur.timestamp[i].tv_usec == 0)) {
+
+ last.rxfer[i] = cur.rxfer[i];
+ last.wxfer[i] = cur.wxfer[i];
+ last.seek[i] = cur.seek[i];
+ last.rbytes[i] = cur.rbytes[i];
+ last.wbytes[i] = cur.wbytes[i];
+
+ timerclear(&last.wait[i]);
+ timerclear(&last.time[i]);
+ timerclear(&last.waitsum[i]);
+ timerclear(&last.busysum[i]);
+ timerclear(&last.timestamp[i]);
+ }
+
/* Delta Values. */
SWAP(rxfer[i]);
SWAP(wxfer[i]);
@@ -108,6 +133,7 @@
DELTA(time[i]);
DELTA(waitsum[i]);
DELTA(busysum[i]);
+ DELTA(timestamp[i]);
}
}
@@ -151,7 +177,7 @@
void
drvreadstats(void)
{
- size_t size, i;
+ size_t size, i, j, count;
int mib[3];
mib[0] = CTL_HW;
@@ -161,27 +187,46 @@
size = ndrive * sizeof(struct io_sysctl);
if (sysctl(mib, 3, drives, &size, NULL, 0) < 0)
err(1, "sysctl hw.iostats failed");
+ /* recalculate array length */
+ count = size / sizeof(struct io_sysctl);
-#define COPYF(x,k) cur.x[k] = drives[k].x
-#define COPYT(x,k) do { \
- cur.x[k].tv_sec = drives[k].x##_sec; \
- cur.x[k].tv_usec = drives[k].x##_usec; \
+#define COPYF(x,k,l) cur.x[k] = drives[l].x
+#define COPYT(x,k,l) do { \
+ cur.x[k].tv_sec = drives[l].x##_sec; \
+ cur.x[k].tv_usec = drives[l].x##_usec; \
} while (/* CONSTCOND */0)
- for (i = 0; i < ndrive; i++) {
+ for (i = 0, j = 0; i < ndrive && j < count; i++) {
+
+ /*
+ * skip removed entries
+ *
+ * we cannot detect entries replaced with
+ * devices of the same name (e.g. unplug/replug).
+ */
+ if (strcmp(cur.name[i], drives[j].name)) {
+ cur.select[i] = 0;
+ continue;
+ }
- COPYF(rxfer, i);
- COPYF(wxfer, i);
- COPYF(seek, i);
- COPYF(rbytes, i);
- COPYF(wbytes, i);
+ COPYF(rxfer, i, j);
+ COPYF(wxfer, i, j);
+ COPYF(seek, i, j);
+ COPYF(rbytes, i, j);
+ COPYF(wbytes, i, j);
- COPYT(wait, i);
- COPYT(time, i);
- COPYT(waitsum, i);
- COPYT(busysum, i);
+ COPYT(wait, i, j);
+ COPYT(time, i, j);
+ COPYT(waitsum, i, j);
+ COPYT(busysum, i, j);
+ COPYT(timestamp, i, j);
+
+ ++j;
}
+ /* shrink table to new size */
+ ndrive = j;
+
mib[0] = CTL_KERN;
mib[1] = KERN_TKSTAT;
mib[2] = KERN_TKSTAT_NIN;
@@ -295,6 +340,7 @@
cur.wait = calloc(ndrive, sizeof(struct timeval));
cur.waitsum = calloc(ndrive, sizeof(struct timeval));
cur.busysum = calloc(ndrive, sizeof(struct timeval));
+ cur.timestamp = calloc(ndrive, sizeof(struct timeval));
cur.rxfer = calloc(ndrive, sizeof(u_int64_t));
cur.wxfer = calloc(ndrive, sizeof(u_int64_t));
cur.seek = calloc(ndrive, sizeof(u_int64_t));
@@ -304,6 +350,7 @@
last.wait = calloc(ndrive, sizeof(struct timeval));
last.waitsum = calloc(ndrive, sizeof(struct timeval));
last.busysum = calloc(ndrive, sizeof(struct timeval));
+ last.timestamp = calloc(ndrive, sizeof(struct timeval));
last.rxfer = calloc(ndrive, sizeof(u_int64_t));
last.wxfer = calloc(ndrive, sizeof(u_int64_t));
last.seek = calloc(ndrive, sizeof(u_int64_t));
@@ -314,11 +361,13 @@
if (cur.time == NULL || cur.wait == NULL ||
cur.waitsum == NULL || cur.busysum == NULL ||
+ cur.timestamp == NULL ||
cur.rxfer == NULL || cur.wxfer == NULL ||
cur.seek == NULL || cur.rbytes == NULL ||
cur.wbytes == NULL ||
last.time == NULL || last.wait == NULL ||
last.waitsum == NULL || last.busysum == NULL ||
+ last.timestamp == NULL ||
last.rxfer == NULL || last.wxfer == NULL ||
last.seek == NULL || last.rbytes == NULL ||
last.wbytes == NULL ||
@@ -335,8 +384,12 @@
mib[2] = sizeof(struct io_sysctl);
if (sysctl(mib, 3, drives, &size, NULL, 0) == -1)
err(1, "sysctl hw.iostats failed");
+ /* Recalculate array length */
+ ndrive = size / sizeof(struct io_sysctl);
for (i = 0; i < ndrive; i++) {
- cur.name[i] = drives[i].name;
+ cur.name[i] = strndup(drives[i].name, sizeof(drives[i].name));
+ if (cur.name[i] == NULL)
+ errx(1, "Memory allocation failure");
cur.select[i] = selected;
}
diff -r f2f2fcfa8bb7 -r 845a1f421295 usr.bin/vmstat/drvstats.h
--- a/usr.bin/vmstat/drvstats.h Tue Jul 04 10:25:45 2017 +0000
+++ b/usr.bin/vmstat/drvstats.h Tue Jul 04 21:19:33 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: drvstats.h,v 1.4 2017/03/05 23:07:12 mlelstv Exp $ */
+/* $NetBSD: drvstats.h,v 1.5 2017/07/04 21:19:33 mlelstv Exp $ */
/*
* Copyright (c) 1996 John M. Vinopal
@@ -39,7 +39,7 @@
/* poseur disk entry to hold the information we're interested in. */
struct _drive {
int *select; /* Display stats for selected disks. */
- char **name; /* Disk names (sd0, wd1, etc). */
+ char **name; /* Disk names (sd0, wd1, etc). */
u_int64_t *rxfer; /* # of read transfers. */
u_int64_t *wxfer; /* # of write transfers. */
u_int64_t *seek; /* # of seeks (currently unused). */
@@ -47,8 +47,9 @@
u_int64_t *wbytes; /* # of bytes written. */
struct timeval *time; /* Time spent in disk i/o. */
struct timeval *wait; /* Time spent in queue waiting. */
- struct timeval *busysum; /* Time busy * queue length */
- struct timeval *waitsum; /* Time waiting * queue length */
+ struct timeval *busysum; /* Time busy * queue length */
+ struct timeval *waitsum; /* Time waiting * queue length */
+ struct timeval *timestamp; /* Disk sample time */
u_int64_t tk_nin; /* TTY Chars in. */
u_int64_t tk_nout; /* TTY Chars out. */
u_int64_t cp_time[CPUSTATES]; /* System timer ticks. */
diff -r f2f2fcfa8bb7 -r 845a1f421295 usr.bin/vmstat/vmstat.c
--- a/usr.bin/vmstat/vmstat.c Tue Jul 04 10:25:45 2017 +0000
+++ b/usr.bin/vmstat/vmstat.c Tue Jul 04 21:19:33 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vmstat.c,v 1.216 2017/01/05 07:53:20 ryo Exp $ */
+/* $NetBSD: vmstat.c,v 1.217 2017/07/04 21:19:33 mlelstv Exp $ */
/*-
* Copyright (c) 1998, 2000, 2001, 2007 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
#if 0
static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95";
#else
-__RCSID("$NetBSD: vmstat.c,v 1.216 2017/01/05 07:53:20 ryo Exp $");
+__RCSID("$NetBSD: vmstat.c,v 1.217 2017/07/04 21:19:33 mlelstv Exp $");
#endif
#endif /* not lint */
@@ -1113,20 +1113,23 @@
drvstats(int *ovflwp)
{
size_t dn;
- double etime;
+ double dtime;
int ovflw = *ovflwp;
/* Calculate disk stat deltas. */
cpuswap();
drvswap();
tkswap();
- etime = cur.cp_etime;
for (dn = 0; dn < ndrive; ++dn) {
+ /* elapsed time for disk stats */
+ dtime = (double)cur.timestamp[dn].tv_sec +
+ ((double)cur.timestamp[dn].tv_usec / (double)1000000);
+
if (!drv_select[dn])
continue;
PRWORD(ovflw, " %*.0f", 3, 1,
- (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
+ (cur.rxfer[dn] + cur.wxfer[dn]) / dtime);
}
*ovflwp = ovflw;
}
diff -r f2f2fcfa8bb7 -r 845a1f421295 usr.sbin/iostat/iostat.c
--- a/usr.sbin/iostat/iostat.c Tue Jul 04 10:25:45 2017 +0000
+++ b/usr.sbin/iostat/iostat.c Tue Jul 04 21:19:33 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: iostat.c,v 1.64 2017/03/05 23:07:12 mlelstv Exp $ */
+/* $NetBSD: iostat.c,v 1.65 2017/07/04 21:19:33 mlelstv Exp $ */
/*
* Copyright (c) 1996 John M. Vinopal
@@ -71,7 +71,7 @@
#if 0
static char sccsid[] = "@(#)iostat.c 8.3 (Berkeley) 4/28/95";
#else
-__RCSID("$NetBSD: iostat.c,v 1.64 2017/03/05 23:07:12 mlelstv Exp $");
+__RCSID("$NetBSD: iostat.c,v 1.65 2017/07/04 21:19:33 mlelstv Exp $");
#endif
#endif /* not lint */
@@ -112,6 +112,7 @@
#define SHOW_STATS_ALL (SHOW_STATS_1 | SHOW_STATS_2 | SHOW_STATS_X | SHOW_STATS_Y)
static void cpustats(void);
+static double drive_time(double, int);
static void drive_stats(double);
static void drive_stats2(double);
static void drive_statsx(double);
@@ -321,15 +322,32 @@
printf("\n");
}
+static double
+drive_time(double etime, int dn)
+{
+ if (ISSET(todo, SHOW_TOTALS))
+ return etime;
+
+ if (cur.timestamp[dn].tv_sec || cur.timestamp[dn].tv_usec) {
+ etime = (double)cur.timestamp[dn].tv_sec +
+ ((double)cur.timestamp[dn].tv_usec / (double)1000000);
+ }
+
+ return etime;
+}
+
static void
drive_stats(double etime)
{
size_t dn;
- double atime, mbps;
+ double atime, dtime, mbps;
for (dn = 0; dn < ndrive; ++dn) {
if (!cur.select[dn])
continue;
+
+ dtime = drive_time(etime, dn);
+
/* average Kbytes per transfer. */
if (cur.rxfer[dn] + cur.wxfer[dn])
mbps = ((cur.rbytes[dn] + cur.wbytes[dn]) /
@@ -341,7 +359,7 @@
Home |
Main Index |
Thread Index |
Old Index