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