Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 Jul 2001 20:43:36 -0600
From:      "Kenneth D. Merry" <ken@kdm.org>
To:        audit@FreeBSD.org
Subject:   new devstat statistics function
Message-ID:  <20010715204336.A60429@panzer.kdm.org>

next in thread | raw e-mail | index | archive | help

--h31gzZEtNLTqOjlF
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline


Attached is a patch to add a new devstat(3) statistics calculation
function.  The code was developed by Sergey Osokin <osa@freebsd.org.ru>
and myself.

It includes a patch to iostat(8) to change over to the new statistics
calculation function.

Anyway, comments would be appreciated.

This is likely a portion of the devstat changes that will be coming down
the pipe in the near term.  Thomas Moestl <tmm@FreeBSD.org> has some
patches to allow devstat use on core files/kernels, and we're talking about
some more changes besides.

Ken
-- 
Kenneth Merry
ken@kdm.org

--h31gzZEtNLTqOjlF
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="devstat.stats.20010715"

==== //depot/FreeBSD-ken/src/lib/libdevstat/devstat.3#5 - /usr/home/ken/perforce/FreeBSD-ken/src/lib/libdevstat/devstat.3 ====
*** /tmp/tmp.1875.0	Sun Jul 15 20:36:42 2001
--- /usr/home/ken/perforce/FreeBSD-ken/src/lib/libdevstat/devstat.3	Sun Jul 15 20:33:42 2001
***************
*** 1,5 ****
  .\"
! .\" Copyright (c) 1998, 1999 Kenneth D. Merry.
  .\" All rights reserved.
  .\"
  .\" Redistribution and use in source and binary forms, with or without
--- 1,5 ----
  .\"
! .\" Copyright (c) 1998, 1999, 2001 Kenneth D. Merry.
  .\" All rights reserved.
  .\"
  .\" Redistribution and use in source and binary forms, with or without
***************
*** 27,33 ****
  .\"
  .\" $FreeBSD: src/lib/libdevstat/devstat.3,v 1.13 2001/07/10 13:41:33 ru Exp $
  .\"
! .Dd May 21, 1998
  .Dt DEVSTAT 3
  .Os
  .Sh NAME
--- 27,33 ----
  .\"
  .\" $FreeBSD: src/lib/libdevstat/devstat.3,v 1.13 2001/07/10 13:41:33 ru Exp $
  .\"
! .Dd July 15, 2001
  .Dt DEVSTAT 3
  .Os
  .Sh NAME
***************
*** 99,104 ****
--- 99,111 ----
  .Fa "struct timeval cur_time"
  .Fa "struct timeval prev_time"
  .Fc
+ .Ft int
+ .Fo devstat_compute_statistics
+ .Fa "struct devstat *current"
+ .Fa "struct devstat *previous"
+ .Fa "long double *etime"
+ .Fa "..."
+ .Fc
  .Sh DESCRIPTION
  The
  .Nm
***************
*** 466,471 ****
--- 473,728 ----
  each time it fetches the current
  .Nm
  list.
+ .Pp
+ .Fn devstat_compute_statistics
+ is an updated version of
+ .Fn compute_stats
+ that provides more complete statistics calculation.  There are four
+ arguments for which values \fBmust\fR be supplied:
+ .Va current ,
+ .Va previous ,
+ .Va etime ,
+ and the terminating argument for the varargs list,
+ .Va DSM_NONE .
+ For most applications, the user will want to supply valid devstat
+ structures for both
+ .Va current
+ and
+ .Va previous .
+ In some instances, for instance when calculating statistics since system
+ boot, the user may pass in a NULL pointer for the
+ .Va previous
+ argument.  In that case,
+ .Fn devstat_compute_statistics
+ will use the total stats in the
+ .Va current
+ structure to calculate statistics over
+ .Va etime .
+ For each statistic to be calculated, the user should supply the proper
+ enumerated type (listed below), and a variable of the indicated type.  All
+ statistics are either integer values, for which a u_int64_t is used, or
+ floating point, for which a long double is used.
+ The statistics that may be calculated are:
+ .Bl -tag -width DSM_TRANSFERS_PER_SECOND_OTHER
+ .It DSM_NONE
+ type: N/A
+ .Pp
+ This \fBmust\fR
+ be the last argument passed to
+ .Fn devstat_compute_statistics .
+ It is an argument list terminator.
+ .It DSM_TOTAL_BYTES
+ type: u_int64_t *
+ .Pp
+ The total number of bytes transferred between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TOTAL_BYTES_READ
+ type: u_int64_t *
+ .Pp
+ The total number of bytes read between the acquisition of
+ .Va previous 
+ and
+ .Va current .
+ .It DSM_TOTAL_BYTES_WRITE
+ type: u_int64_t *
+ .Pp
+ The total number of bytes written between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TOTAL_TRANSFERS
+ type: u_int64_t *
+ .Pp
+ The total number of transfers between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TOTAL_TRANSFERS_READ
+ type: u_int64_t *
+ .Pp
+ The total number of reads between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TOTAL_TRANSFERS_WRITE
+ type: u_int64_t *
+ .Pp
+ The total number of writes between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TOTAL_TRANSFERS_OTHER
+ type: u_int64_t *
+ .Pp
+ The total number of transactions that are not reads or writes that occurred
+ between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TOTAL_BLOCKS
+ type: u_int64_t *
+ .Pp
+ The total number of blocks transferred between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ This number is in terms of the blocksize reported by the device.  If no
+ blocksize has been reported (i.e. the block size is 0), a default
+ blocksize of 512 bytes will be used in the calculation.
+ .It DSM_TOTAL_BLOCKS_READ
+ type: u_int64_t *
+ .Pp
+ The total number of blocks read between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ This number is in terms of the blocksize reported by the device.  If no
+ blocksize has been reported (i.e. the block size is 0), a default
+ blocksize of 512 bytes will be used in the calculation.
+ .It DSM_TOTAL_BLOCKS_WRITE
+ type: u_int64_t *
+ .Pp
+ The total number of blocks written between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ This number is in terms of the blocksize reported by the device.  If no
+ blocksize has been reported (i.e. the block size is 0), a default
+ blocksize of 512 bytes will be used in the calculation.
+ .It DSM_KB_PER_TRANSFER
+ type: long double *
+ .Pp
+ The average number of kilobytes per transfer between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_KB_PER_TRANSFER_READ
+ type: long double *
+ .Pp
+ The average number of kilobytes per read transaction between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_KB_PER_TRANSFER_WRITE
+ type: long double *
+ .Pp
+ The average number of kilobytes per write transaction between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TRANSFERS_PER_SECOND
+ type: long double *
+ .Pp
+ The average number of transfers per second between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TRANSFERS_PER_SECOND_READ
+ type: long double *
+ .Pp
+ The average number of reads per second between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TRANSFERS_PER_SECOND_WRITE
+ type: long double *
+ .Pp
+ The average number of writes per second between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_TRANSFERS_PER_SECOND_OTHER
+ type: long double *
+ .Pp
+ The average number of non-read, non-write transactions per second between
+ the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_MB_PER_SECOND
+ type: long double *
+ .Pp
+ The average number of megabytes transferred per second between the
+ acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_MB_PER_SECOND_READ
+ type: long double *
+ .Pp
+ The average number of megabytes read per second between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_MB_PER_SECOND_WRITE
+ type: long double *
+ .Pp
+ The average number of megabytes written per second between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ .It DSM_BLOCKS_PER_SECOND
+ type: long double *
+ .Pp
+ The average number of blocks transferred per second between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ This number is in terms of the blocksize reported by the device.  If no
+ blocksize has been reported (i.e. the block size is 0), a default
+ blocksize of 512 bytes will be used in the calculation.
+ .It DSM_BLOCKS_PER_SECOND_READ
+ type: long double *
+ .Pp
+ The average number of blocks read per second between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ This number is in terms of the blocksize reported by the device.  If no
+ blocksize has been reported (i.e. the block size is 0), a default
+ blocksize of 512 bytes will be used in the calculation.
+ .It DSM_BLOCKS_PER_SECOND_WRITE
+ type: long double *
+ .Pp
+ The average number of blocks written per second between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ This number is in terms of the blocksize reported by the device.  If no
+ blocksize has been reported (i.e. the block size is 0), a default
+ blocksize of 512 bytes will be used in the calculation.
+ .It DSM_MS_PER_TRANSACTION
+ type: long double *
+ .Pp
+ The average rate of transaction completion between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ Note that this isn't a true reflection of the average number of
+ milliseconds per transaction, but rather is the average rate of transaction
+ completion.  The number is derived by dividing the time elapsed by
+ the number of transactions completed.
+ .It DSM_MS_PER_TRANSACTION_READ
+ type: long double *
+ .Pp
+ The average rate of read completions between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ As above, this is not the true number of milliseconds per transaction, but
+ rather the average rate of read transaction completion.
+ .It DSM_MS_PER_TRANSACTION_WRITE
+ type: long double *
+ .Pp
+ The average rate of write transaction completion between the acquisition of
+ .Va previous
+ and
+ .Va current .
+ As above, this is not the true number of milliseconds per transaction, but
+ rather the average rate of write transaction completion.
+ .El
  .Sh RETURN VALUES
  .Fn getnumdevs ,
  .Fn getgeneration ,
***************
*** 497,502 ****
--- 754,762 ----
  .Pp
  .Fn compute_etime
  returns the computed elapsed time.
+ .Pp
+ .Fn devstat_compute_statistics
+ returns -1 for error, and 0 for success.
  .Pp
  If an error is returned from one of the
  .Nm
==== //depot/FreeBSD-ken/src/lib/libdevstat/devstat.c#1 - /usr/home/ken/perforce/FreeBSD-ken/src/lib/libdevstat/devstat.c ====
*** /tmp/tmp.1875.1	Sun Jul 15 20:36:42 2001
--- /usr/home/ken/perforce/FreeBSD-ken/src/lib/libdevstat/devstat.c	Mon May 28 15:33:57 2001
***************
*** 38,46 ****
--- 38,53 ----
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
+ #include <stdarg.h>
  
  #include "devstat.h"
  
+ typedef enum {
+ 	DEVSTAT_ARG_NOTYPE,
+ 	DEVSTAT_ARG_UINT64,
+ 	DEVSTAT_ARG_LD
+ } devstat_arg_type;
+ 
  char devstat_errbuf[DEVSTAT_ERRBUF_SIZE];
  
  /*
***************
*** 68,73 ****
--- 75,113 ----
  	{NULL,		0,			0}
  };
  
+ struct devstat_args {
+ 	devstat_metric 		metric;
+ 	devstat_arg_type	argtype;
+ } devstat_arg_list[] = {
+ 	{ DSM_NONE, DEVSTAT_ARG_NOTYPE },
+ 	{ DSM_TOTAL_BYTES, DEVSTAT_ARG_UINT64 },
+ 	{ DSM_TOTAL_BYTES_READ, DEVSTAT_ARG_UINT64 },
+ 	{ DSM_TOTAL_BYTES_WRITE, DEVSTAT_ARG_UINT64 },
+ 	{ DSM_TOTAL_TRANSFERS, 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_BLOCKS, DEVSTAT_ARG_UINT64 },
+ 	{ DSM_TOTAL_BLOCKS_READ, DEVSTAT_ARG_UINT64 },
+ 	{ DSM_TOTAL_BLOCKS_WRITE, 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_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_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_BLOCKS_PER_SECOND, DEVSTAT_ARG_LD },
+ 	{ DSM_BLOCKS_PER_SECOND_READ, DEVSTAT_ARG_LD },
+ 	{ DSM_BLOCKS_PER_SECOND_WRITE, 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 }
+ };
+ 
  /*
   * Local function declarations.
   */
***************
*** 1125,1128 ****
--- 1165,1467 ----
          etime /= 1000000;
  
  	return(etime);
+ }
+ 
+ int
+ devstat_compute_statistics(struct devstat *current, struct devstat *previous,
+ 			   long double etime, ...)
+ {
+ 	char *func_name = "devstat_compute_statistics";
+ 	u_int64_t totalbytes, totalbytesread, totalbyteswrite;
+ 	u_int64_t totaltransfers, totaltransfersread, totaltransferswrite;
+ 	u_int64_t totaltransfersother, totalblocks, totalblocksread;
+ 	u_int64_t totalblockswrite;
+ 	va_list ap;
+ 	devstat_metric metric;
+ 	u_int64_t *destu64;
+ 	long double *destld;
+ 	int retval;
+ 
+ 	retval = 0;
+ 
+ 	/*
+ 	 * current is the only mandatory field.
+ 	 */
+ 	if (current == NULL) {
+ 		sprintf(devstat_errbuf, "%s: current stats structure was NULL",
+ 			func_name);
+ 		return(-1);
+ 	}
+ 
+ 	totalbytesread = current->bytes_read -
+ 			 ((previous) ? previous->bytes_read : 0);
+ 	totalbyteswrite = current->bytes_written -
+ 			    ((previous) ? previous->bytes_written : 0);
+ 
+ 	totalbytes = totalbytesread + totalbyteswrite;
+ 
+ 	totaltransfersread = current->num_reads -
+ 			     ((previous) ? previous->num_reads : 0);
+ 
+ 	totaltransferswrite = current->num_writes -
+ 			      ((previous) ? previous->num_writes : 0);
+ 
+ 	totaltransfersother = current->num_other -
+ 			      ((previous) ? previous->num_other : 0);
+ 
+ 	totaltransfers = totaltransfersread + totaltransferswrite +
+ 			 totaltransfersother;
+ 
+ 	totalblocks = totalbytes;
+ 	totalblocksread = totalbytesread;
+ 	totalblockswrite = totalbyteswrite;
+ 
+ 	if (current->block_size > 0) {
+ 		totalblocks /= current->block_size;
+ 		totalblocksread /= current->block_size;
+ 		totalblockswrite /= current->block_size;
+ 	} else {
+ 		totalblocks /= 512;
+ 		totalblocksread /= 512;
+ 		totalblockswrite /= 512;
+ 	}
+ 
+ 	va_start(ap, etime);
+ 
+ 	while ((metric = (devstat_metric)va_arg(ap, devstat_metric)) != 0) {
+ 
+ 		if (metric == DSM_NONE)
+ 			break;
+ 
+ 		if (metric >= DSM_MAX) {
+ 			sprintf(devstat_errbuf, "%s: metric %d is out of "
+ 				"range", func_name, metric);
+ 			retval = -1;
+ 			goto bailout;
+ 		}
+ 
+ 		switch (devstat_arg_list[metric].argtype) {
+ 		case DEVSTAT_ARG_UINT64:
+ 			destu64 = (u_int64_t *)va_arg(ap, u_int64_t *);
+ 			if (destu64 == NULL) {
+ 				sprintf(devstat_errbuf, "%s: argument type not"
+ 					" u_int64_t * or argument type missing",
+ 				        func_name);
+ 				retval = -1;
+ 				goto bailout;
+ 				break; /* NOTREACHED */
+ 			}
+ 			break;
+ 		case DEVSTAT_ARG_LD:
+ 			destld = (long double *)va_arg(ap, long double *);
+ 			if (destld == NULL) {
+ 				sprintf(devstat_errbuf, "%s: argument type not"
+ 					" long double * or argument type "
+ 					"missing", func_name);
+ 				retval = -1;
+ 				goto bailout;
+ 				break; /* NOTREACHED */
+ 			}
+ 			break;
+ 		default:
+ 			sprintf(devstat_errbuf, "%s: unknown argument type %d",
+ 				func_name, devstat_arg_list[metric].argtype);
+ 			retval = -1;
+ 			goto bailout;
+ 			break; /* NOTREACHED */
+ 		}
+ 
+ 		switch (metric) {
+ 		case DSM_TOTAL_BYTES:
+ 			*destu64 = totalbytes;
+ 			break;
+ 		case DSM_TOTAL_BYTES_READ:
+ 			*destu64 = totalbytesread;
+ 			break;
+ 		case DSM_TOTAL_BYTES_WRITE:
+ 			*destu64 = totalbyteswrite;
+ 			break;
+ 		case DSM_TOTAL_TRANSFERS:
+ 			*destu64 = totaltransfers;
+ 			break;
+ 		case DSM_TOTAL_TRANSFERS_READ:
+ 			*destu64 = totaltransfersread;
+ 			break;
+ 		case DSM_TOTAL_TRANSFERS_WRITE:
+ 			*destu64 = totaltransferswrite;
+ 			break;
+ 		case DSM_TOTAL_TRANSFERS_OTHER:
+ 			*destu64 = totaltransfersother;
+ 			break;
+ 		case DSM_TOTAL_BLOCKS:
+ 			*destu64 = totalblocks;
+ 			break;
+ 		case DSM_TOTAL_BLOCKS_READ:
+ 			*destu64 = totalblocksread;
+ 			break;
+ 		case DSM_TOTAL_BLOCKS_WRITE:
+ 			*destu64 = totalblockswrite;
+ 			break;
+ 		case DSM_KB_PER_TRANSFER:
+ 			*destld = totalbytes;
+ 			*destld /= 1024;
+ 			if (totaltransfers > 0)
+ 				*destld /= totaltransfers;
+ 			else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_KB_PER_TRANSFER_READ:
+ 			*destld = totalbytesread;
+ 			*destld /= 1024;
+ 			if (totaltransfersread > 0)
+ 				*destld /= totaltransfersread;
+ 			else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_KB_PER_TRANSFER_WRITE:
+ 			*destld = totalbyteswrite;
+ 			*destld /= 1024;
+ 			if (totaltransferswrite > 0)
+ 				*destld /= totaltransferswrite;
+ 			else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_TRANSFERS_PER_SECOND:
+ 			if (etime > 0.0) {
+ 				*destld = totaltransfers;
+ 				*destld /= etime;
+ 			} else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_TRANSFERS_PER_SECOND_READ:
+ 			if (etime > 0.0) {
+ 				*destld = totaltransfersread;
+ 				*destld /= etime;
+ 			} else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_TRANSFERS_PER_SECOND_WRITE:
+ 			if (etime > 0.0) {
+ 				*destld = totaltransferswrite;
+ 				*destld /= etime;
+ 			} else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_TRANSFERS_PER_SECOND_OTHER:
+ 			if (etime > 0.0) {
+ 				*destld = totaltransfersother;
+ 				*destld /= etime;
+ 			} else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_MB_PER_SECOND:
+ 			*destld = totalbytes;
+ 			*destld /= 1024 * 1024;
+ 			if (etime > 0.0)
+ 				*destld /= etime;
+ 			else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_MB_PER_SECOND_READ:
+ 			*destld = totalbytesread;
+ 			*destld /= 1024 * 1024;
+ 			if (etime > 0.0)
+ 				*destld /= etime;
+ 			else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_MB_PER_SECOND_WRITE:
+ 			*destld = totalbyteswrite;
+ 			*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)
+ 				*destld /= etime;
+ 			else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_BLOCKS_PER_SECOND_READ:
+ 			*destld = totalblocksread;
+ 			if (etime > 0.0)
+ 				*destld /= etime;
+ 			else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_BLOCKS_PER_SECOND_WRITE:
+ 			*destld = totalblockswrite;
+ 			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
+ 		 * completed.  While that does give the caller a good
+ 		 * picture of the average rate of transaction completion,
+ 		 * it doesn't necessarily give the caller a good view of
+ 		 * how long transactions took to complete on average.
+ 		 * Those two numbers will be different for a device that
+ 		 * can handle more than one transaction at a time.  e.g.
+ 		 * SCSI disks doing tagged queueing.
+ 		 *
+ 		 * The only way to accurately determine the real average
+ 		 * time per transaction would be to compute and store the
+ 		 * time on a per-transaction basis.  That currently isn't
+ 		 * done in the kernel, and would only be desireable if it
+ 		 * could be implemented in a somewhat non-intrusive and high
+ 		 * performance way.
+ 		 */
+ 		case DSM_MS_PER_TRANSACTION:
+ 			if (totaltransfers > 0) {
+ 				*destld = etime;
+ 				*destld /= totaltransfers;
+ 				*destld *= 1000;
+ 			} else
+ 				*destld = 0.0;
+ 			break;
+ 		/*
+ 		 * As above, these next two really only give the average
+ 		 * rate of completion for read and write transactions, not
+ 		 * the average time the transaction took to complete.
+ 		 */
+ 		case DSM_MS_PER_TRANSACTION_READ:
+ 			if (totaltransfersread > 0) {
+ 				*destld = etime;
+ 				*destld /= totaltransfersread;
+ 				*destld *= 1000;
+ 			} else
+ 				*destld = 0.0;
+ 			break;
+ 		case DSM_MS_PER_TRANSACTION_WRITE:
+ 			if (totaltransferswrite > 0) {
+ 				*destld = etime;
+ 				*destld /= totaltransferswrite;
+ 				*destld *= 1000;
+ 			} else
+ 				*destld = 0.0;
+ 			break;
+ 		default:
+ 			/*
+ 			 * This shouldn't happen, since we should have
+ 			 * caught any out of range metrics at the top of
+ 			 * the loop.
+ 			 */
+ 			sprintf(devstat_errbuf, "%s: unknown metric %d",
+ 				func_name, metric);
+ 			retval = -1;
+ 			goto bailout;
+ 			break; /* NOTREACHED */
+ 		}
+ 	}
+ 
+ bailout:
+ 
+ 	va_end(ap);
+ 	return(retval);
  }
==== //depot/FreeBSD-ken/src/lib/libdevstat/devstat.h#1 - /usr/home/ken/perforce/FreeBSD-ken/src/lib/libdevstat/devstat.h ====
*** /tmp/tmp.1875.2	Sun Jul 15 20:36:42 2001
--- /usr/home/ken/perforce/FreeBSD-ken/src/lib/libdevstat/devstat.h	Mon May 28 15:31:45 2001
***************
*** 44,49 ****
--- 44,80 ----
  	DEVSTAT_MATCH_PASS	= 0x04
  } devstat_match_flags;
  
+ typedef enum {
+ 	DSM_NONE,
+ 	DSM_TOTAL_BYTES,
+ 	DSM_TOTAL_BYTES_READ,
+ 	DSM_TOTAL_BYTES_WRITE,
+ 	DSM_TOTAL_TRANSFERS,
+ 	DSM_TOTAL_TRANSFERS_READ,
+ 	DSM_TOTAL_TRANSFERS_WRITE,
+ 	DSM_TOTAL_TRANSFERS_OTHER,
+ 	DSM_TOTAL_BLOCKS,
+ 	DSM_TOTAL_BLOCKS_READ,
+ 	DSM_TOTAL_BLOCKS_WRITE,
+ 	DSM_KB_PER_TRANSFER,
+ 	DSM_KB_PER_TRANSFER_READ,
+ 	DSM_KB_PER_TRANSFER_WRITE,
+ 	DSM_TRANSFERS_PER_SECOND,
+ 	DSM_TRANSFERS_PER_SECOND_READ,
+ 	DSM_TRANSFERS_PER_SECOND_WRITE,
+ 	DSM_TRANSFERS_PER_SECOND_OTHER,
+ 	DSM_MB_PER_SECOND,
+ 	DSM_MB_PER_SECOND_READ,
+ 	DSM_MB_PER_SECOND_WRITE,
+ 	DSM_BLOCKS_PER_SECOND,
+ 	DSM_BLOCKS_PER_SECOND_READ,
+ 	DSM_BLOCKS_PER_SECOND_WRITE,
+ 	DSM_MS_PER_TRANSACTION,
+ 	DSM_MS_PER_TRANSACTION_READ,
+ 	DSM_MS_PER_TRANSACTION_WRITE,
+ 	DSM_MAX
+ } devstat_metric;
+ 
  struct devstat_match {
  	devstat_match_flags	match_fields;
  	devstat_type_flags	device_type;
***************
*** 110,115 ****
--- 141,149 ----
  		  long double *blocks_per_second,
  		  long double *ms_per_transaction);
  long double compute_etime(struct timeval cur_time, struct timeval prev_time);
+ int devstat_compute_statistics(struct devstat *current,
+ 			       struct devstat *previous,
+ 			       long double etime, ...);
  __END_DECLS
  
  #endif /* _DEVSTAT_H  */
==== //depot/FreeBSD-ken/src/usr.sbin/iostat/iostat.c#4 - /usr/home/ken/perforce/FreeBSD-ken/src/usr.sbin/iostat/iostat.c ====
*** /tmp/tmp.1875.4	Sun Jul 15 20:36:42 2001
--- /usr/home/ken/perforce/FreeBSD-ken/src/usr.sbin/iostat/iostat.c	Mon May 28 20:14:42 2001
***************
*** 608,619 ****
  
  		di = dev_select[dn].position;
  
! 		if (compute_stats(&cur.dinfo->devices[di],
! 				  &last.dinfo->devices[di], busy_seconds,
! 				  &total_bytes, &total_transfers,
! 				  &total_blocks, &kb_per_transfer,
! 				  &transfers_per_second, &mb_per_second, 
! 				  &blocks_per_second, &ms_per_transaction)!= 0)
  			errx(1, "%s", devstat_errbuf);
  
  		if (perf_select != 0) {
--- 608,624 ----
  
  		di = dev_select[dn].position;
  
! 		if (devstat_compute_statistics(&cur.dinfo->devices[di],
! 		    &last.dinfo->devices[di], busy_seconds,
! 		    DSM_TOTAL_BYTES, &total_bytes,
! 		    DSM_TOTAL_TRANSFERS, &total_transfers,
! 		    DSM_TOTAL_BLOCKS, &total_blocks,
! 		    DSM_KB_PER_TRANSFER, &kb_per_transfer,
! 		    DSM_TRANSFERS_PER_SECOND, &transfers_per_second,
! 		    DSM_MB_PER_SECOND, &mb_per_second, 
! 		    DSM_BLOCKS_PER_SECOND, &blocks_per_second,
! 		    DSM_MS_PER_TRANSACTION, &ms_per_transaction,
! 		    DSM_NONE) != 0)
  			errx(1, "%s", devstat_errbuf);
  
  		if (perf_select != 0) {

--h31gzZEtNLTqOjlF--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010715204336.A60429>