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
This commit is contained in:
phk 2003-03-18 09:57:54 +00:00
parent 88560bfa93
commit f4bf9dc635
2 changed files with 130 additions and 27 deletions

View File

@ -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(&current->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
}
}

View File

@ -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;