From 36eab1f55ace4b4529f568b4d9f0406ac6cc16a6 Mon Sep 17 00:00:00 2001 From: Poul-Henning Kamp Date: Tue, 18 Mar 2003 09:57:54 +0000 Subject: [PATCH] Add more devstat calculations, mostly filling in holes, but also adding a couple of reqests: DSM_BUSY_PCT and DSM_QUEUE_LENGTH. I have no further plans for mutilating this API at this point in time, and will update the man-page to reflect current reality as the next thing. Reviewed by: ken --- lib/libdevstat/devstat.c | 142 ++++++++++++++++++++++++++++++++------- lib/libdevstat/devstat.h | 15 ++++- 2 files changed, 130 insertions(+), 27 deletions(-) diff --git a/lib/libdevstat/devstat.c b/lib/libdevstat/devstat.c index 33f961888867..a120b4f76228 100644 --- a/lib/libdevstat/devstat.c +++ b/lib/libdevstat/devstat.c @@ -89,29 +89,40 @@ struct devstat_args { { DSM_TOTAL_BYTES, DEVSTAT_ARG_UINT64 }, { DSM_TOTAL_BYTES_READ, DEVSTAT_ARG_UINT64 }, { DSM_TOTAL_BYTES_WRITE, DEVSTAT_ARG_UINT64 }, + { DSM_TOTAL_BYTES_FREE, DEVSTAT_ARG_UINT64 }, { DSM_TOTAL_TRANSFERS, DEVSTAT_ARG_UINT64 }, + { DSM_TOTAL_TRANSFERS_OTHER, DEVSTAT_ARG_UINT64 }, { DSM_TOTAL_TRANSFERS_READ, DEVSTAT_ARG_UINT64 }, { DSM_TOTAL_TRANSFERS_WRITE, DEVSTAT_ARG_UINT64 }, - { DSM_TOTAL_TRANSFERS_OTHER, DEVSTAT_ARG_UINT64 }, + { DSM_TOTAL_TRANSFERS_FREE, DEVSTAT_ARG_UINT64 }, { DSM_TOTAL_BLOCKS, DEVSTAT_ARG_UINT64 }, { DSM_TOTAL_BLOCKS_READ, DEVSTAT_ARG_UINT64 }, { DSM_TOTAL_BLOCKS_WRITE, DEVSTAT_ARG_UINT64 }, + { DSM_TOTAL_BLOCKS_FREE, DEVSTAT_ARG_UINT64 }, { DSM_KB_PER_TRANSFER, DEVSTAT_ARG_LD }, { DSM_KB_PER_TRANSFER_READ, DEVSTAT_ARG_LD }, { DSM_KB_PER_TRANSFER_WRITE, DEVSTAT_ARG_LD }, + { DSM_KB_PER_TRANSFER_FREE, DEVSTAT_ARG_LD }, { DSM_TRANSFERS_PER_SECOND, DEVSTAT_ARG_LD }, { DSM_TRANSFERS_PER_SECOND_READ, DEVSTAT_ARG_LD }, { DSM_TRANSFERS_PER_SECOND_WRITE, DEVSTAT_ARG_LD }, + { DSM_TRANSFERS_PER_SECOND_FREE, DEVSTAT_ARG_LD }, { DSM_TRANSFERS_PER_SECOND_OTHER, DEVSTAT_ARG_LD }, { DSM_MB_PER_SECOND, DEVSTAT_ARG_LD }, { DSM_MB_PER_SECOND_READ, DEVSTAT_ARG_LD }, { DSM_MB_PER_SECOND_WRITE, DEVSTAT_ARG_LD }, + { DSM_MB_PER_SECOND_FREE, DEVSTAT_ARG_LD }, { DSM_BLOCKS_PER_SECOND, DEVSTAT_ARG_LD }, { DSM_BLOCKS_PER_SECOND_READ, DEVSTAT_ARG_LD }, { DSM_BLOCKS_PER_SECOND_WRITE, DEVSTAT_ARG_LD }, + { DSM_BLOCKS_PER_SECOND_FREE, DEVSTAT_ARG_LD }, { DSM_MS_PER_TRANSACTION, DEVSTAT_ARG_LD }, { DSM_MS_PER_TRANSACTION_READ, DEVSTAT_ARG_LD }, { DSM_MS_PER_TRANSACTION_WRITE, DEVSTAT_ARG_LD }, + { DSM_MS_PER_TRANSACTION_FREE, DEVSTAT_ARG_LD }, + { DSM_MS_PER_TRANSACTION_OTHER, DEVSTAT_ARG_LD }, + { DSM_BUSY_PCT, DEVSTAT_ARG_LD }, + { DSM_QUEUE_LENGTH, DEVSTAT_ARG_UINT64 }, { DSM_SKIP, DEVSTAT_ARG_SKIP } }; @@ -362,8 +373,14 @@ devstat_getdevs(kvm_t *kd, struct statinfo *stats) * If devices are being added to the system that quickly, maybe * the user can just wait until all devices are added. */ - if ((error = sysctlbyname("kern.devstat.all", dinfo->mem_ptr, - &dssize, NULL, 0)) == -1) { + for (;;) { + error = sysctlbyname("kern.devstat.all", + dinfo->mem_ptr, + &dssize, NULL, 0); + if (error != -1 || errno != EBUSY) + break; + } + if (error == -1) { /* * If we get ENOMEM back, that means that there are * more devices now, so we need to allocate more @@ -1161,20 +1178,27 @@ devstat_compute_etime(struct bintime *cur_time, struct bintime *prev_time) return(etime); } +#define DELTA(field, index) \ + (current->field[(index)] - (previous ? previous->field[(index)] : 0)) + +#define DELTA_T(field) \ + devstat_compute_etime(¤t->field, \ + (previous ? &previous->field : NULL)) + int devstat_compute_statistics(struct devstat *current, struct devstat *previous, long double etime, ...) { const char *func_name = "devstat_compute_statistics"; - u_int64_t totalbytes, totalbytesread, totalbyteswrite; + u_int64_t totalbytes, totalbytesread, totalbyteswrite, totalbytesfree; u_int64_t totaltransfers, totaltransfersread, totaltransferswrite; u_int64_t totaltransfersother, totalblocks, totalblocksread; - u_int64_t totalblockswrite; + u_int64_t totalblockswrite, totaltransfersfree, totalblocksfree; va_list ap; devstat_metric metric; u_int64_t *destu64; long double *destld; - int retval; + int retval, i; retval = 0; @@ -1187,37 +1211,33 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, return(-1); } - 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->operations[DEVSTAT_READ] - - ((previous) ? previous->operations[DEVSTAT_READ] : 0); - - totaltransferswrite = current->operations[DEVSTAT_WRITE] - - ((previous) ? previous->operations[DEVSTAT_WRITE] : 0); - - totaltransfersother = current->operations[DEVSTAT_NO_DATA] - - ((previous) ? previous->operations[DEVSTAT_NO_DATA] : 0); + totalbytesread = DELTA(bytes, DEVSTAT_READ); + totalbyteswrite = DELTA(bytes, DEVSTAT_WRITE); + totalbytesfree = DELTA(bytes, DEVSTAT_FREE); + totalbytes = totalbytesread + totalbyteswrite + totalbytesfree; + totaltransfersread = DELTA(operations, DEVSTAT_READ); + totaltransferswrite = DELTA(operations, DEVSTAT_WRITE); + totaltransfersother = DELTA(operations, DEVSTAT_NO_DATA); + totaltransfersfree = DELTA(operations, DEVSTAT_FREE); totaltransfers = totaltransfersread + totaltransferswrite + - totaltransfersother; + totaltransfersother + totaltransfersfree; totalblocks = totalbytes; totalblocksread = totalbytesread; totalblockswrite = totalbyteswrite; + totalblocksfree = totalbytesfree; if (current->block_size > 0) { totalblocks /= current->block_size; totalblocksread /= current->block_size; totalblockswrite /= current->block_size; + totalblocksfree /= current->block_size; } else { totalblocks /= 512; totalblocksread /= 512; totalblockswrite /= 512; + totalblocksfree /= 512; } va_start(ap, etime); @@ -1264,6 +1284,9 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, case DSM_TOTAL_BYTES_WRITE: *destu64 = totalbyteswrite; break; + case DSM_TOTAL_BYTES_FREE: + *destu64 = totalbytesfree; + break; case DSM_TOTAL_TRANSFERS: *destu64 = totaltransfers; break; @@ -1273,6 +1296,9 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, case DSM_TOTAL_TRANSFERS_WRITE: *destu64 = totaltransferswrite; break; + case DSM_TOTAL_TRANSFERS_FREE: + *destu64 = totaltransfersfree; + break; case DSM_TOTAL_TRANSFERS_OTHER: *destu64 = totaltransfersother; break; @@ -1285,6 +1311,9 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, case DSM_TOTAL_BLOCKS_WRITE: *destu64 = totalblockswrite; break; + case DSM_TOTAL_BLOCKS_FREE: + *destu64 = totalblocksfree; + break; case DSM_KB_PER_TRANSFER: *destld = totalbytes; *destld /= 1024; @@ -1309,6 +1338,14 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, else *destld = 0.0; break; + case DSM_KB_PER_TRANSFER_FREE: + *destld = totalbytesfree; + *destld /= 1024; + if (totaltransfersfree > 0) + *destld /= totaltransfersfree; + else + *destld = 0.0; + break; case DSM_TRANSFERS_PER_SECOND: if (etime > 0.0) { *destld = totaltransfers; @@ -1330,6 +1367,13 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, } else *destld = 0.0; break; + case DSM_TRANSFERS_PER_SECOND_FREE: + if (etime > 0.0) { + *destld = totaltransfersfree; + *destld /= etime; + } else + *destld = 0.0; + break; case DSM_TRANSFERS_PER_SECOND_OTHER: if (etime > 0.0) { *destld = totaltransfersother; @@ -1361,6 +1405,14 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, else *destld = 0.0; break; + case DSM_MB_PER_SECOND_FREE: + *destld = totalbytesfree; + *destld /= 1024 * 1024; + if (etime > 0.0) + *destld /= etime; + else + *destld = 0.0; + break; case DSM_BLOCKS_PER_SECOND: *destld = totalblocks; if (etime > 0.0) @@ -1382,6 +1434,13 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, else *destld = 0.0; break; + case DSM_BLOCKS_PER_SECOND_FREE: + *destld = totalblocksfree; + if (etime > 0.0) + *destld /= etime; + else + *destld = 0.0; + break; /* * This calculation is somewhat bogus. It simply divides * the elapsed time by the total number of transactions @@ -1402,7 +1461,9 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, */ case DSM_MS_PER_TRANSACTION: if (totaltransfers > 0) { - *destld = etime; + *destld = 0; + for (i = 0; i < DEVSTAT_N_TRANS_FLAGS; i++) + *destld += DELTA_T(duration[i]); *destld /= totaltransfers; *destld *= 1000; } else @@ -1415,7 +1476,7 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, */ case DSM_MS_PER_TRANSACTION_READ: if (totaltransfersread > 0) { - *destld = etime; + *destld = DELTA_T(duration[DEVSTAT_READ]); *destld /= totaltransfersread; *destld *= 1000; } else @@ -1423,12 +1484,42 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, break; case DSM_MS_PER_TRANSACTION_WRITE: if (totaltransferswrite > 0) { - *destld = etime; + *destld = DELTA_T(duration[DEVSTAT_WRITE]); *destld /= totaltransferswrite; *destld *= 1000; } else *destld = 0.0; break; + case DSM_MS_PER_TRANSACTION_FREE: + if (totaltransfersfree > 0) { + *destld = DELTA_T(duration[DEVSTAT_FREE]); + *destld /= totaltransfersfree; + *destld *= 1000; + } else + *destld = 0.0; + break; + case DSM_MS_PER_TRANSACTION_OTHER: + if (totaltransfersother > 0) { + *destld = DELTA_T(duration[DEVSTAT_NO_DATA]); + *destld /= totaltransfersother; + *destld *= 1000; + } else + *destld = 0.0; + break; + case DSM_BUSY_PCT: + *destld = DELTA_T(busy_time); + if (*destld < 0) + *destld = 0; + *destld /= etime; + *destld *= 100; + break; + case DSM_QUEUE_LENGTH: + *destu64 = current->start_count - current->end_count; + break; +/* + * XXX: comment out the default block to see if any case's are missing. + */ +#if 1 default: /* * This shouldn't happen, since we should have @@ -1440,6 +1531,7 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, retval = -1; goto bailout; break; /* NOTREACHED */ +#endif } } diff --git a/lib/libdevstat/devstat.h b/lib/libdevstat/devstat.h index 09af2170ee2d..9c6a9511a14c 100644 --- a/lib/libdevstat/devstat.h +++ b/lib/libdevstat/devstat.h @@ -61,29 +61,40 @@ typedef enum { DSM_TOTAL_BYTES, DSM_TOTAL_BYTES_READ, DSM_TOTAL_BYTES_WRITE, + DSM_TOTAL_BYTES_FREE, DSM_TOTAL_TRANSFERS, + DSM_TOTAL_TRANSFERS_OTHER, DSM_TOTAL_TRANSFERS_READ, DSM_TOTAL_TRANSFERS_WRITE, - DSM_TOTAL_TRANSFERS_OTHER, + DSM_TOTAL_TRANSFERS_FREE, DSM_TOTAL_BLOCKS, DSM_TOTAL_BLOCKS_READ, DSM_TOTAL_BLOCKS_WRITE, + DSM_TOTAL_BLOCKS_FREE, DSM_KB_PER_TRANSFER, DSM_KB_PER_TRANSFER_READ, DSM_KB_PER_TRANSFER_WRITE, + DSM_KB_PER_TRANSFER_FREE, DSM_TRANSFERS_PER_SECOND, + DSM_TRANSFERS_PER_SECOND_OTHER, DSM_TRANSFERS_PER_SECOND_READ, DSM_TRANSFERS_PER_SECOND_WRITE, - DSM_TRANSFERS_PER_SECOND_OTHER, + DSM_TRANSFERS_PER_SECOND_FREE, DSM_MB_PER_SECOND, DSM_MB_PER_SECOND_READ, DSM_MB_PER_SECOND_WRITE, + DSM_MB_PER_SECOND_FREE, DSM_BLOCKS_PER_SECOND, DSM_BLOCKS_PER_SECOND_READ, DSM_BLOCKS_PER_SECOND_WRITE, + DSM_BLOCKS_PER_SECOND_FREE, DSM_MS_PER_TRANSACTION, + DSM_MS_PER_TRANSACTION_OTHER, DSM_MS_PER_TRANSACTION_READ, DSM_MS_PER_TRANSACTION_WRITE, + DSM_MS_PER_TRANSACTION_FREE, + DSM_BUSY_PCT, + DSM_QUEUE_LENGTH, DSM_SKIP, DSM_MAX } devstat_metric;