diff options
-rw-r--r-- | lib/libdevstat/Makefile | 3 | ||||
-rw-r--r-- | lib/libdevstat/devstat.c | 126 | ||||
-rw-r--r-- | lib/libdevstat/devstat.h | 42 | ||||
-rw-r--r-- | libexec/rpc.rstatd/rstat_proc.c | 9 | ||||
-rw-r--r-- | sys/cam/cam_periph.c | 4 | ||||
-rw-r--r-- | sys/kern/subr_devstat.c | 97 | ||||
-rw-r--r-- | sys/sys/devicestat.h | 101 | ||||
-rw-r--r-- | sys/sys/param.h | 2 | ||||
-rw-r--r-- | usr.bin/systat/iostat.c | 4 | ||||
-rw-r--r-- | usr.bin/systat/vmstat.c | 26 | ||||
-rw-r--r-- | usr.bin/vmstat/vmstat.c | 4 | ||||
-rw-r--r-- | usr.sbin/iostat/iostat.c | 12 |
12 files changed, 165 insertions, 265 deletions
diff --git a/lib/libdevstat/Makefile b/lib/libdevstat/Makefile index 5d484bf..3c7454e 100644 --- a/lib/libdevstat/Makefile +++ b/lib/libdevstat/Makefile @@ -3,7 +3,8 @@ MAINTAINER=ken@FreeBSD.ORG LIB= devstat -SHLIB_MAJOR= 3 +# Bump DEVSTAT_USER_API_VER in devstat.h every time this is incremented. +SHLIB_MAJOR= 4 SRCS= devstat.c INCS= devstat.h diff --git a/lib/libdevstat/devstat.c b/lib/libdevstat/devstat.c index 9c715d8..e5047be 100644 --- a/lib/libdevstat/devstat.c +++ b/lib/libdevstat/devstat.c @@ -315,6 +315,7 @@ devstat_getdevs(kvm_t *kd, struct statinfo *stats) int retval = 0; struct devinfo *dinfo; const char *func_name = "devstat_getdevs"; + struct timespec ts; dinfo = stats->dinfo; @@ -327,8 +328,8 @@ devstat_getdevs(kvm_t *kd, struct statinfo *stats) oldnumdevs = dinfo->numdevs; oldgeneration = dinfo->generation; - /* Get the current time when we get the stats */ - gettimeofday(&stats->busy_time, NULL); + clock_gettime(CLOCK_MONOTONIC, &ts); + stats->snap_time = ts.tv_sec + ts.tv_nsec * 1e-9; if (kd == NULL) { /* If this is our first time through, mem_ptr will be null. */ @@ -338,7 +339,7 @@ devstat_getdevs(kvm_t *kd, struct statinfo *stats) * error. Don't bother setting the error string, since * getnumdevs() has already done that for us. */ - if ((dinfo->numdevs = getnumdevs()) < 0) + if ((dinfo->numdevs = devstat_getnumdevs(NULL)) < 0) return(-1); /* @@ -371,9 +372,9 @@ devstat_getdevs(kvm_t *kd, struct statinfo *stats) if (errno == ENOMEM) { /* * No need to set the error string here, - * getnumdevs() will do that if it fails. + * devstat_getnumdevs() will do that if it fails. */ - if ((dinfo->numdevs = getnumdevs()) < 0) + if ((dinfo->numdevs = devstat_getnumdevs(NULL)) < 0) return(-1); dssize = (dinfo->numdevs * @@ -403,7 +404,7 @@ devstat_getdevs(kvm_t *kd, struct statinfo *stats) * This is of course non-atomic, but since we are working * on a core dump, the generation is unlikely to change */ - if ((dinfo->numdevs = getnumdevs()) == -1) + if ((dinfo->numdevs = devstat_getnumdevs(NULL)) == -1) return(-1); if ((dinfo->mem_ptr = get_devstat_kvm(kd)) == NULL) return(-1); @@ -430,8 +431,8 @@ devstat_getdevs(kvm_t *kd, struct statinfo *stats) * necessary. */ if (oldgeneration != dinfo->generation) { - if (getnumdevs() != dinfo->numdevs) { - if ((dinfo->numdevs = getnumdevs()) < 0) + if (devstat_getnumdevs(NULL) != dinfo->numdevs) { + if ((dinfo->numdevs = devstat_getnumdevs(NULL)) < 0) return(-1); dssize = (dinfo->numdevs * sizeof(struct devstat)) + sizeof(long); @@ -1142,21 +1143,21 @@ compute_stats(struct devstat *current, struct devstat *previous, DSM_NONE)); } + +/* This is 1/2^64 */ +#define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-20 + long double -devstat_compute_etime(struct timeval cur_time, struct timeval prev_time) +devstat_compute_etime(struct bintime *cur_time, struct bintime *prev_time) { - struct timeval busy_time; - u_int64_t busy_usec; long double etime; - timersub(&cur_time, &prev_time, &busy_time); - - busy_usec = busy_time.tv_sec; - busy_usec *= 1000000; - busy_usec += busy_time.tv_usec; - etime = busy_usec; - etime /= 1000000; - + etime = cur_time->sec; + etime += cur_time->frac * BINTIME_SCALE; + if (prev_time != NULL) { + etime -= prev_time->sec; + etime -= prev_time->frac * BINTIME_SCALE; + } return(etime); } @@ -1186,21 +1187,21 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, return(-1); } - totalbytesread = current->bytes_read - - ((previous) ? previous->bytes_read : 0); - totalbyteswrite = current->bytes_written - - ((previous) ? previous->bytes_written : 0); + totalbytesread = current->bytes[DEVSTAT_READ] - + ((previous) ? previous->bytes[DEVSTAT_READ] : 0); + totalbyteswrite = current->bytes[DEVSTAT_WRITE] - + ((previous) ? previous->bytes[DEVSTAT_WRITE] : 0); totalbytes = totalbytesread + totalbyteswrite; - totaltransfersread = current->num_reads - - ((previous) ? previous->num_reads : 0); + totaltransfersread = current->operations[DEVSTAT_READ] - + ((previous) ? previous->operations[DEVSTAT_READ] : 0); - totaltransferswrite = current->num_writes - - ((previous) ? previous->num_writes : 0); + totaltransferswrite = current->operations[DEVSTAT_WRITE] - + ((previous) ? previous->operations[DEVSTAT_WRITE] : 0); - totaltransfersother = current->num_other - - ((previous) ? previous->num_other : 0); + totaltransfersother = current->operations[DEVSTAT_NO_DATA] - + ((previous) ? previous->operations[DEVSTAT_NO_DATA] : 0); totaltransfers = totaltransfersread + totaltransferswrite + totaltransfersother; @@ -1496,7 +1497,7 @@ get_devstat_kvm(kvm_t *kd) char *rv = NULL; const char *func_name = "get_devstat_kvm"; - if ((num_devs = getnumdevs()) <= 0) + if ((num_devs = devstat_getnumdevs(kd)) <= 0) return(NULL); error = 0; if (KREADNL(kd, X_DEVICE_STATQ, dhead) == -1) @@ -1510,7 +1511,7 @@ get_devstat_kvm(kvm_t *kd) func_name); return(NULL); } - gen = getgeneration(); + gen = devstat_getgeneration(kd); memcpy(rv, &gen, sizeof(gen)); wp = sizeof(gen); /* @@ -1536,66 +1537,3 @@ get_devstat_kvm(kvm_t *kd) } return(rv); } - -/* - * Compatability functions for libdevstat 2. These are deprecated and may - * eventually be removed. - */ -int -getnumdevs(void) -{ - return(devstat_getnumdevs(NULL)); -} - -long -getgeneration(void) -{ - return(devstat_getgeneration(NULL)); -} - -int -getversion(void) -{ - return(devstat_getversion(NULL)); -} - -int -checkversion(void) -{ - return(devstat_checkversion(NULL)); -} - -int -getdevs(struct statinfo *stats) -{ - return(devstat_getdevs(NULL, stats)); -} - -int -selectdevs(struct device_selection **dev_select, int *num_selected, - int *num_selections, long *select_generation, - long current_generation, struct devstat *devices, int numdevs, - struct devstat_match *matches, int num_matches, - char **dev_selections, int num_dev_selections, - devstat_select_mode select_mode, int maxshowdevs, - int perf_select) -{ - - return(devstat_selectdevs(dev_select, num_selected, num_selections, - select_generation, current_generation, devices, numdevs, - matches, num_matches, dev_selections, num_dev_selections, - select_mode, maxshowdevs, perf_select)); -} - -int -buildmatch(char *match_str, struct devstat_match **matches, - int *num_matches) -{ - return(devstat_buildmatch(match_str, matches, num_matches)); -} - -long double -compute_etime(struct timeval cur_time, struct timeval prev_time) -{ - return(devstat_compute_etime(cur_time, prev_time)); -} diff --git a/lib/libdevstat/devstat.h b/lib/libdevstat/devstat.h index c1ae355..09af217 100644 --- a/lib/libdevstat/devstat.h +++ b/lib/libdevstat/devstat.h @@ -35,6 +35,16 @@ #include <kvm.h> +/* + * Bumped every time we change the userland API. Hopefully this doesn't + * happen very often! This should be bumped every time we have to + * increment SHLIB_MAJOR in the libdevstat Makefile (for non-backwards + * compatible API changes) and should also be bumped every time we make + * backwards-compatible API changes, so application writers have a way to + * determine when a particular feature is available. + */ +#define DEVSTAT_USER_API_VER 4 + #define DEVSTAT_ERRBUF_SIZE 2048 /* size of the devstat library error string */ extern char devstat_errbuf[]; @@ -111,7 +121,7 @@ struct statinfo { long tk_nin; long tk_nout; struct devinfo *dinfo; - struct timeval busy_time; + long double snap_time; }; typedef enum { @@ -122,31 +132,7 @@ typedef enum { } devstat_select_mode; __BEGIN_DECLS -/* Legacy interfaces. */ -int getnumdevs(void); -long getgeneration(void); -int getversion(void); -int checkversion(void); -int getdevs(struct statinfo *stats); -int selectdevs(struct device_selection **dev_select, int *num_selected, - int *num_selections, long *select_generation, - long current_generation, struct devstat *devices, int numdevs, - struct devstat_match *matches, int num_matches, - char **dev_selections, int num_dev_selections, - devstat_select_mode select_mode, int maxshowdevs, - int perf_select); -int buildmatch(char *match_str, struct devstat_match **matches, - int *num_matches); -int compute_stats(struct devstat *current, struct devstat *previous, - long double etime, u_int64_t *total_bytes, - u_int64_t *total_transfers, u_int64_t *total_blocks, - long double *kb_per_transfer, - long double *transfers_per_second, long double *mb_per_second, - long double *blocks_per_second, - long double *ms_per_transaction); -long double compute_etime(struct timeval cur_time, struct timeval prev_time); - -/* New interfaces. */ + int devstat_getnumdevs(kvm_t *kd); long devstat_getgeneration(kvm_t *kd); int devstat_getversion(kvm_t *kd); @@ -164,8 +150,8 @@ int devstat_buildmatch(char *match_str, struct devstat_match **matches, int devstat_compute_statistics(struct devstat *current, struct devstat *previous, long double etime, ...); -long double devstat_compute_etime(struct timeval cur_time, - struct timeval prev_time); +long double devstat_compute_etime(struct bintime *cur_time, + struct bintime *prev_time); __END_DECLS #endif /* _DEVSTAT_H */ diff --git a/libexec/rpc.rstatd/rstat_proc.c b/libexec/rpc.rstatd/rstat_proc.c index bb04c16..440bdb6 100644 --- a/libexec/rpc.rstatd/rstat_proc.c +++ b/libexec/rpc.rstatd/rstat_proc.c @@ -370,7 +370,7 @@ haveadisk(void) void updatexfers(int numdevs, int *devs) { - register int i, j, t; + register int i, j, k, t; struct statinfo stats; int num_devices = 0; u_int64_t total_transfers; @@ -400,9 +400,10 @@ updatexfers(int numdevs, int *devs) & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) && ((stats.dinfo->devices[i].device_type & DEVSTAT_TYPE_PASS) == 0)) { - total_transfers = stats.dinfo->devices[i].num_reads + - stats.dinfo->devices[i].num_writes + - stats.dinfo->devices[i].num_other; + total_transfers = 0; + for (k = 0; k < DEVSTAT_N_TRANS_FLAGS; k++) + total_transfers += + stats.dinfo->devices[i].operations[k]; /* * XXX KDM If the total transfers for this device * are greater than the amount we can fit in a diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 247ebb8..09126e6 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -866,7 +866,7 @@ cam_periph_runccb(union ccb *ccb, * this particular type of ccb, record the transaction start. */ if ((ds != NULL) && (ccb->ccb_h.func_code == XPT_SCSI_IO)) - devstat_start_transaction(ds); + devstat_start_transaction(ds, NULL); xpt_action(ccb); @@ -896,7 +896,7 @@ cam_periph_runccb(union ccb *ccb, CAM_DIR_NONE) ? DEVSTAT_NO_DATA : (ccb->ccb_h.flags & CAM_DIR_OUT) ? DEVSTAT_WRITE : - DEVSTAT_READ); + DEVSTAT_READ, NULL, NULL); return(error); } diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c index 01322e0..26fc062 100644 --- a/sys/kern/subr_devstat.c +++ b/sys/kern/subr_devstat.c @@ -156,7 +156,7 @@ devstat_add_entry(struct devstat *ds, const char *dev_name, ds->flags = flags; ds->device_type = device_type; ds->priority = priority; - getmicrotime(&ds->dev_creation_time); + binuptime(&ds->creation_time); } /* @@ -183,9 +183,12 @@ devstat_remove_entry(struct devstat *ds) /* * Record a transaction start. + * + * See comments for devstat_end_transaction(). Ordering is very important + * here. */ void -devstat_start_transaction(struct devstat *ds) +devstat_start_transaction(struct devstat *ds, struct bintime *now) { /* sanity check */ if (ds == NULL) @@ -196,9 +199,21 @@ devstat_start_transaction(struct devstat *ds) * to busy. The start time is really the start of the latest busy * period. */ - if (ds->busy_count == 0) - getmicrouptime(&ds->start_time); - ds->busy_count++; + if (ds->start_count == ds->end_count) { + if (now != NULL) + ds->busy_from = *now; + else + binuptime(&ds->busy_from); + } + ds->start_count++; +} + +void +devstat_start_transaction_bio(struct devstat *ds, struct bio *bp) +{ + + binuptime(&bp->bio_t0); + devstat_start_transaction(ds, &bp->bio_t0); } void @@ -210,35 +225,35 @@ devstat_start_transaction_bio(struct devstat *ds, struct bio *bp) /* * Record the ending of a transaction, and incrment the various counters. + * + * Ordering in this function, and in devstat_start_transaction() is VERY + * important. The idea here is to run without locks, so we are very + * careful to only modify some fields on the way "down" (i.e. at + * transaction start) and some fields on the way "up" (i.e. at transaction + * completion). One exception is busy_from, which we only modify in + * devstat_start_transaction() when there are no outstanding transactions, + * and thus it can't be modified in devstat_end_transaction() + * simultaneously. */ void devstat_end_transaction(struct devstat *ds, u_int32_t bytes, - devstat_tag_type tag_type, devstat_trans_flags flags) + devstat_tag_type tag_type, devstat_trans_flags flags, + struct bintime *now, struct bintime *then) { - struct timeval busy_time; + struct bintime dt, lnow; /* sanity check */ if (ds == NULL) return; - getmicrouptime(&ds->last_comp_time); - ds->busy_count--; + if (now == NULL) { + now = &lnow; + binuptime(now); + } - /* - * There might be some transactions (DEVSTAT_NO_DATA) that don't - * transfer any data. - */ - if (flags == DEVSTAT_READ) { - ds->bytes_read += bytes; - ds->num_reads++; - } else if (flags == DEVSTAT_WRITE) { - ds->bytes_written += bytes; - ds->num_writes++; - } else if (flags == DEVSTAT_FREE) { - ds->bytes_freed += bytes; - ds->num_frees++; - } else - ds->num_other++; + /* Update byte and operations counts */ + ds->bytes[flags] += bytes; + ds->operations[flags]++; /* * Keep a count of the various tag types sent. @@ -247,21 +262,20 @@ devstat_end_transaction(struct devstat *ds, u_int32_t bytes, tag_type != DEVSTAT_TAG_NONE) ds->tag_types[tag_type]++; - /* - * We only update the busy time when we go idle. Otherwise, this - * calculation would require many more clock cycles. - */ - if (ds->busy_count == 0) { - /* Calculate how long we were busy */ - busy_time = ds->last_comp_time; - timevalsub(&busy_time, &ds->start_time); - - /* Add our busy time to the total busy time. */ - timevaladd(&ds->busy_time, &busy_time); - } else if (ds->busy_count < 0) - printf("devstat_end_transaction: HELP!! busy_count " - "for %s%d is < 0 (%d)!\n", ds->device_name, - ds->unit_number, ds->busy_count); + if (then != NULL) { + /* Update duration of operations */ + dt = *now; + bintime_sub(&dt, then); + bintime_add(&ds->duration[flags], &dt); + } + + /* Accumulate busy time */ + dt = *now; + bintime_sub(&dt, &ds->busy_from); + bintime_add(&ds->busy_time, &dt); + ds->busy_from = *now; + + ds->end_count++; } void @@ -277,7 +291,7 @@ devstat_end_transaction_bio(struct devstat *ds, struct bio *bp) flg = DEVSTAT_WRITE; devstat_end_transaction(ds, bp->bio_bcount - bp->bio_resid, - DEVSTAT_TAG_SIMPLE, flg); + DEVSTAT_TAG_SIMPLE, flg, NULL, &bp->bio_t0); } /* @@ -427,3 +441,6 @@ devstat_free(struct devstat *dsp) } } } + +SYSCTL_INT(_debug_sizeof, OID_AUTO, devstat, CTLFLAG_RD, + 0, sizeof(struct devstat), "sizeof(struct devstat)"); diff --git a/sys/sys/devicestat.h b/sys/sys/devicestat.h index 872f3f8..c06df37 100644 --- a/sys/sys/devicestat.h +++ b/sys/sys/devicestat.h @@ -48,7 +48,7 @@ * userland utilities to determine whether or not they are in sync with the * kernel. */ -#define DEVSTAT_VERSION 5 +#define DEVSTAT_VERSION 6 /* * These flags specify which statistics features are supported or not @@ -68,6 +68,7 @@ typedef enum { DEVSTAT_WRITE = 0x02, DEVSTAT_FREE = 0x03 } devstat_trans_flags; +#define DEVSTAT_N_TRANS_FLAGS 4 typedef enum { DEVSTAT_TAG_SIMPLE = 0x00, @@ -124,8 +125,15 @@ typedef enum { } devstat_type_flags; struct devstat { - int sequence0; /* Update sequence# */ + /* Internal house-keeping fields */ + u_int sequence0; /* Update sequence# */ int allocated; /* Allocated entry */ + u_int start_count; /* started ops */ + u_int end_count; /* completed ops */ + struct bintime busy_from; /* + * busy time unaccounted + * for since this time + */ STAILQ_ENTRY(devstat) dev_links; u_int32_t device_number; /* * Devstat device @@ -133,44 +141,13 @@ struct devstat { */ char device_name[DEVSTAT_NAME_LEN]; int unit_number; - u_int64_t bytes_read; /* - * Total bytes read - * from a device. - */ - u_int64_t bytes_written; /* - * Total bytes written - * to a device. - */ - u_int64_t bytes_freed; /* - * Total bytes freed - * from a device. - */ - u_int64_t num_reads; /* - * Total number of - * read requests to - * the device. - */ - u_int64_t num_writes; /* - * Total number of - * write requests to - * the device. - */ - u_int64_t num_frees; /* - * Total number of - * free requests to - * the device. - */ - u_int64_t num_other; /* - * Total number of - * transactions that - * don't read or write - * data. - */ - int32_t busy_count; /* - * Total number of - * transactions - * outstanding for - * the device. + u_int64_t bytes[DEVSTAT_N_TRANS_FLAGS]; + u_int64_t operations[DEVSTAT_N_TRANS_FLAGS]; + struct bintime duration[DEVSTAT_N_TRANS_FLAGS]; + struct bintime busy_time; + struct bintime creation_time; /* + * Time the device was + * created. */ u_int32_t block_size; /* Block size, bytes */ u_int64_t tag_types[3]; /* @@ -179,28 +156,6 @@ struct devstat { * and head of queue * tags sent. */ - struct timeval dev_creation_time; /* - * Time the device was - * created. - */ - struct timeval busy_time; /* - * Total amount of - * time drive has spent - * processing requests. - */ - struct timeval start_time; /* - * The time when - * busy_count was - * last == 0. Or, the - * start of the latest - * busy period. - */ - struct timeval last_comp_time; /* - * Last time a - * transaction was - * completed. - */ - devstat_support_flags flags; /* * Which statistics * are supported by a @@ -208,8 +163,11 @@ struct devstat { */ devstat_type_flags device_type; /* Device type */ devstat_priority priority; /* Controls list pos. */ - - int sequence1; /* Update sequence# */ + void *id; /* + * Identification for + * GEOM nodes + */ + u_int sequence1; /* Update sequence# */ }; STAILQ_HEAD(devstatlist, devstat); @@ -217,18 +175,19 @@ STAILQ_HEAD(devstatlist, devstat); #ifdef _KERNEL struct bio; -struct devstat *devstat_new_entry(const char *dev_name, - int unit_number, u_int32_t block_size, - devstat_support_flags flags, - devstat_type_flags device_type, - devstat_priority priority); +struct devstat *devstat_new_entry(const char *dev_name, int unit_number, + u_int32_t block_size, + devstat_support_flags flags, + devstat_type_flags device_type, + devstat_priority priority); void devstat_remove_entry(struct devstat *ds); -void devstat_start_transaction(struct devstat *ds); +void devstat_start_transaction(struct devstat *ds, struct bintime *now); void devstat_start_transaction_bio(struct devstat *ds, struct bio *bp); void devstat_end_transaction(struct devstat *ds, u_int32_t bytes, devstat_tag_type tag_type, - devstat_trans_flags flags); + devstat_trans_flags flags, + struct bintime *now, struct bintime *then); void devstat_end_transaction_bio(struct devstat *ds, struct bio *bp); #endif diff --git a/sys/sys/param.h b/sys/sys/param.h index f78e76e..c737e83 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -55,7 +55,7 @@ * doc/en_US.ISO8859-1/books/porters-handbook/book.sgml */ #undef __FreeBSD_version -#define __FreeBSD_version 500106 /* Master, propagated to newvers */ +#define __FreeBSD_version 500107 /* Master, propagated to newvers */ #ifndef NULL #define NULL 0 diff --git a/usr.bin/systat/iostat.c b/usr.bin/systat/iostat.c index ba39f3e..a54bb6d 100644 --- a/usr.bin/systat/iostat.c +++ b/usr.bin/systat/iostat.c @@ -148,8 +148,6 @@ fetchiostat() last.dinfo = cur.dinfo; cur.dinfo = tmp_dinfo; - last.busy_time = cur.busy_time; - /* * Here what we want to do is refresh our device stats. * getdevs() returns 1 when the device list has changed. @@ -322,7 +320,7 @@ devstats(row, _col, dn) di = dev_select[dn].position; - busy_seconds = devstat_compute_etime(cur.busy_time, last.busy_time); + busy_seconds = cur.snap_time - last.snap_time; if (devstat_compute_statistics(&cur.dinfo->devices[di], &last.dinfo->devices[di], busy_seconds, diff --git a/usr.bin/systat/vmstat.c b/usr.bin/systat/vmstat.c index 5fc1985..ff7a37b 100644 --- a/usr.bin/systat/vmstat.c +++ b/usr.bin/systat/vmstat.c @@ -798,7 +798,7 @@ getinfo(ls) last.dinfo = cur.dinfo; cur.dinfo = tmp_dinfo; - last.busy_time = cur.busy_time; + last.snap_time = cur.snap_time; switch (devstat_getdevs(NULL, &cur)) { case -1: errx(1, "%s", devstat_errbuf); @@ -852,12 +852,19 @@ dinfo(dn, lc, now, then) di = dev_select[dn].position; - elapsed_time = devstat_compute_etime(now->busy_time, - then ? then->busy_time : now->dinfo->devices[di].dev_creation_time); - - device_busy = devstat_compute_etime(now->dinfo->devices[di].busy_time, - then ? then->dinfo->devices[di].busy_time : - now->dinfo->devices[di].dev_creation_time); + if (then != NULL) { + /* Calculate relative to previous sample */ + elapsed_time = now->snap_time - then->snap_time; + device_busy = devstat_compute_etime( + &now->dinfo->devices[di].busy_time, + &then->dinfo->devices[di].busy_time); + } else { + /* Calculate relative to device creation */ + elapsed_time = now->snap_time - devstat_compute_etime( + &now->dinfo->devices[di].creation_time, NULL); + device_busy = devstat_compute_etime( + &now->dinfo->devices[di].busy_time, NULL); + } if (devstat_compute_statistics(&now->dinfo->devices[di], then ? &then->dinfo->devices[di] : NULL, elapsed_time, @@ -866,11 +873,6 @@ dinfo(dn, lc, now, then) DSM_NONE) != 0) errx(1, "%s", devstat_errbuf); - if ((device_busy == 0) && (transfers_per_second > 5)) - /* the device has been 100% busy, fake it because - * as long as the device is 100% busy the busy_time - * field in the devstat struct is not updated */ - device_busy = elapsed_time; if (device_busy > elapsed_time) /* this normally happens after one or more periods * where the device has been 100% busy, correct it */ diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index fb99b2c..88c1d21 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -428,7 +428,7 @@ dovmstat(interval, reps) tmp_dinfo = last.dinfo; last.dinfo = cur.dinfo; cur.dinfo = tmp_dinfo; - last.busy_time = cur.busy_time; + last.snap_time = cur.snap_time; /* * Here what we want to do is refresh our device stats. @@ -680,7 +680,7 @@ devstats() last.cp_time[state] = tmp; } - busy_seconds = devstat_compute_etime(cur.busy_time, last.busy_time); + busy_seconds = cur.snap_time - last.snap_time; for (dn = 0; dn < num_devices; dn++) { int di; diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c index 3370df2..724756e 100644 --- a/usr.sbin/iostat/iostat.c +++ b/usr.sbin/iostat/iostat.c @@ -407,12 +407,10 @@ main(int argc, char **argv) cur.tk_nin = 0; /* - * Set the busy time to the system boot time, so the stats are - * calculated since system boot. + * Set the snap time to the system boot time (ie: zero), so the + * stats are calculated since system boot. */ - if (readvar(kd, "kern.boottime", X_BOOTTIME, &cur.busy_time, - sizeof(cur.busy_time)) != 0) - exit(1); + cur.snap_time = 0; /* * If the user stops the program (control-Z) and then resumes it, @@ -452,7 +450,7 @@ main(int argc, char **argv) last.dinfo = cur.dinfo; cur.dinfo = tmp_dinfo; - last.busy_time = cur.busy_time; + last.snap_time = cur.snap_time; /* * Here what we want to do is refresh our device stats. @@ -538,7 +536,7 @@ main(int argc, char **argv) last.tk_nout = tmp; } - etime = devstat_compute_etime(cur.busy_time, last.busy_time); + etime = cur.snap_time - last.snap_time; if (etime == 0.0) etime = 1.0; |