1.\" 2.\" Copyright (c) 1998, 1999 Kenneth D. Merry. 3.\" All rights reserved. 4.\" 5.\" Redistribution and use in source and binary forms, with or without 6.\" modification, are permitted provided that the following conditions 7.\" are met: 8.\" 1. Redistributions of source code must retain the above copyright 9.\" notice, this list of conditions and the following disclaimer. 10.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" notice, this list of conditions and the following disclaimer in the 12.\" documentation and/or other materials provided with the distribution. 13.\" 3. The name of the author may not be used to endorse or promote products 14.\" derived from this software without specific prior written permission. 15.\" 16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26.\" SUCH DAMAGE. 27.\" 28.\" $FreeBSD$ 29.\" 30.Dd May 21, 1998 31.Dt DEVSTAT 3 32.Os FreeBSD 3.0 33.Sh NAME 34.Nm devstat , 35.Nm getnumdevs , 36.Nm getgeneration , 37.Nm getversion , 38.Nm checkversion , 39.Nm getdevs , 40.Nm selectdevs , 41.Nm buildmatch , 42.Nm compute_stats , 43.Nm compute_etime 44.Nd device statistics utility library 45.Sh LIBRARY 46.Lb libdevstat 47.Sh SYNOPSIS 48.Fd #include <sys/dkstat.h> 49.Fd #include <devstat.h> 50.Ft int 51.Fn getnumdevs "void" 52.Ft long 53.Fn getgeneration "void" 54.Ft int 55.Fn getversion "void" 56.Ft int 57.Fn checkversion "void" 58.Ft int 59.Fn getdevs "struct statinfo *stats" 60.Ft int 61.Fo selectdevs 62.Fa "struct device_selection **dev_select" 63.Fa "int *num_selected" 64.Fa "int *num_selections" 65.Fa "long *select_generation" 66.Fa "long current_generation" 67.Fa "struct devstat *devices" 68.Fa "int numdevs" 69.Fa "struct devstat_match *matches" 70.Fa "int num_matches" 71.Fa "char **dev_selections" 72.Fa "int num_dev_selections" 73.Fa "devstat_select_mode select_mode" 74.Fa "int maxshowdevs" 75.Fa "int perf_select" 76.Fc 77.Ft int 78.Fo buildmatch 79.Fa "char *match_str" 80.Fa "struct devstat_match **matches" 81.Fa "int *num_matches" 82.Fc 83.Ft int 84.Fo compute_stats 85.Fa "struct devstat *current" 86.Fa "struct devstat *previous" 87.Fa "long double etime" 88.Fa "u_int64_t *total_bytes" 89.Fa "u_int64_t *total_transfers" 90.Fa "u_int64_t *total_blocks" 91.Fa "long double *kb_per_transfer" 92.Fa "long double *transfers_per_second" 93.Fa "long double *mb_per_second" 94.Fa "long double *blocks_per_second" 95.Fa "long double *ms_per_transaction" 96.Fc 97.Ft long double 98.Fo compute_etime 99.Fa "struct timeval cur_time" 100.Fa "struct timeval prev_time" 101.Fc 102.Sh DESCRIPTION 103The 104.Nm 105library is a library of helper functions for dealing with the kernel 106.Xr devstat 9 107interface, which is accessible to users via 108.Xr sysctl 3 . 109.Pp 110.Fn getnumdevs 111returns the number of devices registered with the 112.Nm devstat 113subsystem in the kernel. 114.Pp 115.Fn getgeneration 116returns the current generation of the 117.Nm devstat 118list of devices in the kernel. 119.Pp 120.Fn getversion 121returns the current kernel 122.Nm devstat 123version. 124.Pp 125.Fn checkversion 126checks the userland devstat version against the kernel devstat version. If 127the two are identical, it returns zero. Otherwise, it prints an 128appropriate error in 129.Va devstat_errbuf 130and returns -1. 131.Pp 132.Fn getdevs 133fetches the current list of devices and statistics into the supplied 134.Va statinfo 135structure. The 136.Va statinfo 137structure can be found in 138.Aq Pa devstat.h : 139.Bd -literal -offset indent 140struct statinfo { 141 long cp_time[CPUSTATES]; 142 long tk_nin; 143 long tk_nout; 144 struct devinfo *dinfo; 145 struct timeval busy_time; 146}; 147.Ed 148.Pp 149.Fn getdevs 150expects the 151.Va statinfo 152structure to be allocated, and it also expects the 153.Va dinfo 154subelement to be allocated and zeroed prior to the first invocation of 155.Fn getdevs . 156The 157.Va dinfo 158subelement is used to store state between calls, and should not be modified 159after the first call to 160.Fn getdevs . 161The 162.Va dinfo 163subelement contains the following elements: 164.Bd -literal -offset indent 165struct devinfo { 166 struct devstat *devices; 167 u_int8_t *mem_ptr; 168 long generation; 169 int numdevs; 170}; 171.Ed 172.Pp 173The 174.Va kern.devstat.all 175.Nm sysctl 176variable contains an array of 177.Nm devstat 178structures, but at the head of the array is the current 179.Nm devstat 180generation. The reason the generation is at the head of the buffer is so 181that userland software accessing the devstat statistics information can 182atomically get both the statistics information and the corresponding 183generation number. If client software were forced to get the generation 184number via a separate 185.Nm sysctl 186variable (which is available for convenience), the list of devices could 187change between the time the client gets the generation and the time the 188client gets the device list. 189.Pp 190The 191.Va mem_ptr 192subelement of the 193.Va devinfo 194structure is a pointer to memory that is allocated, and resized if 195necessary, by 196.Fn getdevs . 197The devices subelement of the 198.Va devinfo 199structure is basically a pointer to the beginning of the array of devstat 200structures from the 201.Va kern.devstat.all 202.Nm sysctl 203variable. The generation subelement of the 204.Nm devinfo 205structure contains the generation number from the 206.Va kern.devstat.all 207.Nm sysctl 208variable. 209The 210.Va numdevs 211subelement of the 212.Va devinfo 213structure contains the current 214number of devices registered with the kernel 215.Nm devstat 216subsystem. 217.Pp 218.Fn selectdevs 219selects devices to display based upon a number of criteria: 220.Bl -tag -width flag 221.It specified devices 222Specified devices are the first selection priority. These are generally 223devices specified by name by the user. e.g. da0, da1, cd0. 224.It match patterns 225These are pattern matching expressions generated by 226.Fn buildmatch 227from user input. 228.It performance 229If performance mode is enabled, devices will be sorted based on the 230.Va bytes 231field in the 232.Va device_selection 233structure passed in to 234.Fn selectdevs . 235The 236.Va bytes 237value currently must be maintained by the user. In the future, 238this may be done for him in a 239.Nm 240library routine. 241If no devices have been selected by name or by pattern, the performance 242tracking code will select every device in the system, and sort them by 243performance. If devices have been selected by name or pattern, the 244performance tracking code will honor those selections and will only sort 245among the selected devices. 246.It order in the devstat list 247If the selection mode is set to DS_SELECT_ADD, and if there are still less 248than 249.Va maxshowdevs 250devices selected, 251.Fn selectdevs 252will automatically select up to 253.Va maxshowdevs 254devices. 255.El 256.Pp 257.Fn selectdevs 258performs selections in four different modes: 259.Bl -tag -width DS_SELECT_ADDONLY 260.It DS_SELECT_ADD 261In add mode, 262.Fn selectdevs 263will select any unselected devices specified by name or matching pattern. 264It will also select more devices, in devstat list order, until the number 265of selected devices is equal to 266.Va maxshowdevs 267or until all devices are 268selected. 269.It DS_SELECT_ONLY 270In only mode, 271.Fn selectdevs 272will clear all current selections, and will only select devices specified 273by name or by matching pattern. 274.It DS_SELECT_REMOVE 275In remove mode, 276.Fn selectdevs 277will remove devices specified by name or by matching pattern. It will not 278select any additional devices. 279.It DS_SELECT_ADDONLY 280In add only mode, 281.Fn selectdevs 282will select any unselected devices specified by name or matching pattern. 283In this respect it is identical to add mode. It will not, however, select 284any devices other than those specified. 285.El 286.Pp 287In all selection modes, 288.Fn selectdevs 289will not select any more than 290.Va maxshowdevs 291devices. One exception to 292this is when you are in 293.Dq top 294mode and no devices have been selected. In 295this case, 296.Fn selectdevs 297will select every device in the system. Client programs must pay attention 298to selection order when deciding whether to pay attention to a particular 299device. This may be the wrong behavior, and probably requires additional 300thought. 301.Pp 302.Fn selectdevs 303handles allocation and resizing of the 304.Va dev_select 305structure passed in 306by the client. 307.Fn selectdevs 308uses the 309.Va numdevs 310and 311.Va current_generation 312fields to track the 313current 314.Nm 315generation and number of devices. If 316.Va num_selections 317is not the same 318as 319.Va numdevs 320or if 321.Va select_generation 322is not the same as 323.Va current_generation , 324.Fn selectdevs 325will resize the selection list as necessary, and re-initialize the 326selection array. 327.Pp 328.Fn buildmatch 329takes a comma separated match string and compiles it into a 330\fBdevstat_match\fR structure that is understood by 331.Fn selectdevs . 332Match strings have the following format: 333.Pp 334.Bd -literal -offset indent 335device,type,if 336.Ed 337.Pp 338.Fn buildmatch 339takes care of allocating and reallocating the match list as necessary. 340Currently known match types include: 341.Pp 342.Bl -tag -width indent -compact 343.It device type: 344.Bl -tag -width 123456789 -compact 345.It da 346Direct Access devices 347.It sa 348Sequential Access devices 349.It printer 350Printers 351.It proc 352Processor devices 353.It worm 354Write Once Read Multiple devices 355.It cd 356CD devices 357.It scanner 358Scanner devices 359.It optical 360Optical Memory devices 361.It changer 362Medium Changer devices 363.It comm 364Communication devices 365.It array 366Storage Array devices 367.It enclosure 368Enclosure Services devices 369.It floppy 370Floppy devices 371.El 372.Pp 373.It interface: 374.Bl -tag -width 123456789 -compact 375.It IDE 376Integrated Drive Electronics devices 377.It SCSI 378Small Computer System Interface devices 379.It other 380Any other device interface 381.El 382.Pp 383.It passthrough: 384.Bl -tag -width 123456789 -compact 385.It pass 386Passthrough devices 387.El 388.El 389.Pp 390.Fn compute_stats 391provides an easy way to obtain various device statistics. Only two 392arguments are mandatory: 393.Va current 394and 395.Va etime . 396Every other argument is optional. For most applications, the user will 397want to supply both 398.Va current 399and 400.Va previous 401devstat structures so that statistics may be calculated over a given period 402of time. In some instances, for instance when calculating statistics since 403system boot, the user may pass in a NULL pointer for the 404.Va previous 405argument. In that case, 406.Fn compute_stats 407will use the total stats in the 408.Va current 409structure to calculate statistics over 410.Va etime . 411The various statistics that may be calculated by 412.Fn compute_stats 413should be mostly explained by the function declaration itself, but for 414completeness here is a list of variable names and the statistics that will 415be put in them: 416.Bl -tag -width transfers_per_second 417.It total_bytes 418This is the total number of bytes transferred on the given device, both 419reads and writes, between the acquisition of 420.Va previous 421and the acquisition of 422.Va current . 423If 424.Va previous 425is NULL, the result will be the total reads and writes given in 426.Va current . 427.It total_transfers 428This is the total number of transfers completed between the 429acquisition of 430.Va previous 431and the acquisition of 432.Va current . 433If 434.Va previous 435is NULL, the result will be the total number of transactions listed in 436.Va current . 437.It total_blocks 438This is basically 439.Va total_bytes 440divided by the device blocksize. If the device blocksize is listed as 441.Sq 0 , 442the device blocksize will default to 512 bytes. 443.It kb_per_transfer 444This is the average number of kilobytes per transfer during the measurement 445period. 446.It transfers_per_second 447This is the average number of transfers per second. 448.It mb_per_second 449This is average megabytes per second. 450.It blocks_per_second 451This is average blocks per second. If the device blocksize is 452.Sq 0 , 453a default blocksize of 512 bytes will be used instead. 454.It ms_per_transaction 455The average number of milliseconds per transaction. 456.El 457.Pp 458.Fn compute_etime 459provides an easy way to find the difference in seconds between two 460.Va timeval 461structures. This is most commonly used in conjunction with the time 462recorded by the 463.Fn getdevs 464function (in struct 465.Va statinfo ) 466each time it fetches the current 467.Nm 468list. 469.Sh RETURN VALUES 470.Fn getnumdevs , 471.Fn getgeneration , 472and 473.Fn getversion 474return the indicated \fBsysctl\fR variable, or -1 if there is an error 475fetching the variable. 476.Pp 477.Fn checkversion 478returns 0 if the kernel and userland 479.Nm devstat 480versions match. If they do not match, it returns -1. 481.Pp 482.Fn getdevs 483and 484.Fn selectdevs 485return -1 in case of an error, 0 if there is no error and 1 if the device 486list or selected devices have changed. A return value of 1 from 487.Fn getdevs 488is usually a hint to re-run 489.Fn selectdevs 490because the device list has changed. 491.Pp 492.Fn buildmatch 493returns -1 for error, and 0 if there is no error. 494.Pp 495.Fn compute_stats 496returns -1 for error, and 0 for success. 497.Pp 498.Fn compute_etime 499returns the computed elapsed time. 500.Pp 501If an error is returned from one of the 502.Nm 503library functions, the reason for the error is generally printed in 504the global string 505.Va devstat_errbuf 506which is 507.Dv DEVSTAT_ERRBUF_SIZE 508characters long. 509.Sh SEE ALSO 510.Xr systat 1 , 511.Xr iostat 8 , 512.Xr rpc.rstatd 8 , 513.Xr vmstat 8 , 514.Xr devstat 9 515.Sh HISTORY 516The 517.Nm 518statistics system first appeared in 519.Fx 3.0 . 520.Sh AUTHORS 521.An Kenneth Merry Aq ken@FreeBSD.ORG 522.Sh BUGS 523There should probably be an interface to de-allocate memory allocated by 524.Fn getdevs , 525.Fn selectdevs , 526and 527.Fn buildmatch . 528.Pp 529.Fn selectdevs 530should probably not select more than 531.Va maxshowdevs 532devices in 533.Dq top 534mode when no devices have been selected previously. 535.Pp 536There should probably be functions to perform the statistics buffer 537swapping that goes on in most of the clients of this library. 538.Pp 539The 540.Va statinfo 541and 542.Va devinfo 543structures should probably be cleaned up and thought out a little more. 544