1.\" 2.\" Copyright (c) 1998, 1999, 2001 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 March 18, 2003 31.Dt DEVSTAT 3 32.Os 33.Sh NAME 34.Nm devstat , 35.Nm devstat_getnumdevs , 36.Nm devstat_getgeneration , 37.Nm devstat_getversion , 38.Nm devstat_checkversion , 39.Nm devstat_getdevs , 40.Nm devstat_selectdevs , 41.Nm devstat_buildmatch , 42.Nm devstat_compute_statistics , 43.Nm devstat_compute_etime 44.Nd device statistics utility library 45.Sh LIBRARY 46.Lb libdevstat 47.Sh SYNOPSIS 48.In devstat.h 49.Ft int 50.Fn devstat_getnumdevs "kvm_t *kd" 51.Ft long 52.Fn devstat_getgeneration "kvm_t *kd" 53.Ft int 54.Fn devstat_getversion "kvm_t *kd" 55.Ft int 56.Fn devstat_checkversion "kvm_t *kd" 57.Ft int 58.Fn devstat_getdevs "kvm_t *kd" "struct statinfo *stats" 59.Ft int 60.Fo devstat_selectdevs 61.Fa "struct device_selection **dev_select" 62.Fa "int *num_selected" 63.Fa "int *num_selections" 64.Fa "long *select_generation" 65.Fa "long current_generation" 66.Fa "struct devstat *devices" 67.Fa "int numdevs" 68.Fa "struct devstat_match *matches" 69.Fa "int num_matches" 70.Fa "char **dev_selections" 71.Fa "int num_dev_selections" 72.Fa "devstat_select_mode select_mode" 73.Fa "int maxshowdevs" 74.Fa "int perf_select" 75.Fc 76.Ft int 77.Fo devstat_buildmatch 78.Fa "char *match_str" 79.Fa "struct devstat_match **matches" 80.Fa "int *num_matches" 81.Fc 82.Ft int 83.Fo devstat_compute_statistics 84.Fa "struct devstat *current" 85.Fa "struct devstat *previous" 86.Fa "long double etime" 87.Fa "..." 88.Fc 89.Ft "long double" 90.Fo devstat_compute_etime 91.Fa "struct bintime *cur_time" 92.Fa "struct bintime *prev_time" 93.Fc 94.Sh DESCRIPTION 95The 96.Nm 97library is a library of helper functions for dealing with the kernel 98.Xr devstat 9 99interface, which is accessible to users via 100.Xr sysctl 3 101and 102.Xr kvm 3 . 103All functions that take a 104.Vt "kvm_t *" 105as first argument can be passed 106.Dv NULL 107instead of a kvm handle as this argument, 108which causes the data to be read via 109.Xr sysctl 3 . 110Otherwise, it is read via 111.Xr kvm 3 112using the supplied handle. 113The 114.Fn devstat_checkversion 115function 116should be called with each kvm handle that is going to be used (or with 117.Dv NULL 118if 119.Xr sysctl 3 120is going to be used). 121.Pp 122The 123.Fn devstat_getnumdevs 124function 125returns the number of devices registered with the 126.Nm 127subsystem in the kernel. 128.Pp 129The 130.Fn devstat_getgeneration 131function 132returns the current generation of the 133.Nm 134list of devices in the kernel. 135.Pp 136The 137.Fn devstat_getversion 138function 139returns the current kernel 140.Nm 141version. 142.Pp 143The 144.Fn devstat_checkversion 145function 146checks the userland 147.Nm 148version against the kernel 149.Nm 150version. 151If the two are identical, it returns zero. 152Otherwise, it prints an appropriate error in 153.Va devstat_errbuf 154and returns \-1. 155.Pp 156The 157.Fn devstat_getdevs 158function 159fetches the current list of devices and statistics into the supplied 160.Vt statinfo 161structure. 162The 163.Vt statinfo 164structure can be found in 165.In devstat.h : 166.Bd -literal -offset indent 167struct statinfo { 168 long cp_time[CPUSTATES]; 169 long tk_nin; 170 long tk_nout; 171 struct devinfo *dinfo; 172 long double snap_time; 173}; 174.Ed 175.Pp 176The 177.Fn devstat_getdevs 178function 179expects the 180.Vt statinfo 181structure to be allocated, and it also expects the 182.Va dinfo 183subelement to be allocated and zeroed prior to the first invocation of 184.Fn devstat_getdevs . 185The 186.Va dinfo 187subelement is used to store state between calls, and should not be modified 188after the first call to 189.Fn devstat_getdevs . 190The 191.Va dinfo 192subelement contains the following elements: 193.Bd -literal -offset indent 194struct devinfo { 195 struct devstat *devices; 196 u_int8_t *mem_ptr; 197 long generation; 198 int numdevs; 199}; 200.Ed 201.Pp 202The 203.Va kern.devstat.all 204.Xr sysctl 8 205variable contains an array of 206.Nm 207structures, but at the head of the array is the current 208.Nm 209generation. 210The reason the generation is at the head of the buffer is so that userland 211software accessing the 212.Nm 213statistics information can atomically get 214both the statistics information and the corresponding generation number. 215If client software were forced to get the generation number via a separate 216.Xr sysctl 8 217variable (which is available for convenience), the list of devices could 218change between the time the client gets the generation and the time the 219client gets the device list. 220.Pp 221The 222.Va mem_ptr 223subelement of the 224.Vt devinfo 225structure is a pointer to memory that is allocated, and resized if 226necessary, by 227.Fn devstat_getdevs . 228The devices subelement of the 229.Vt devinfo 230structure is basically a pointer to the beginning of the array of devstat 231structures from the 232.Va kern.devstat.all 233.Xr sysctl 8 234variable (or the corresponding values read via 235.Xr kvm 3 ) . 236The generation subelement of the 237.Vt devinfo 238structure contains the corresponding generation number. 239The 240.Va numdevs 241subelement of the 242.Vt devinfo 243structure contains the current 244number of devices registered with the kernel 245.Nm 246subsystem. 247.Pp 248The 249.Fn devstat_selectdevs 250function 251selects devices to display based upon a number of criteria: 252.Bl -tag -width indent 253.It specified devices 254Specified devices are the first selection priority. 255These are generally devices specified by name by the user e.g.\& 256.Li da0 , da1 , cd0 . 257.It match patterns 258These are pattern matching expressions generated by 259.Fn devstat_buildmatch 260from user input. 261.It performance 262If performance mode is enabled, devices will be sorted based on the 263.Va bytes 264field in the 265.Vt device_selection 266structure passed in to 267.Fn devstat_selectdevs . 268The 269.Va bytes 270value currently must be maintained by the user. 271In the future, this may be done for him in a 272.Nm 273library routine. 274If no devices have been selected by name or by pattern, the performance 275tracking code will select every device in the system, and sort them by 276performance. 277If devices have been selected by name or pattern, the performance tracking 278code will honor those selections and will only sort among the selected 279devices. 280.It order in the devstat list 281If the selection mode is set to 282.Dv DS_SELECT_ADD , 283and if there are still less 284than 285.Fa maxshowdevs 286devices selected, 287.Fn devstat_selectdevs 288will automatically select up to 289.Fa maxshowdevs 290devices. 291.El 292.Pp 293The 294.Fn devstat_selectdevs 295function 296performs selections in four different modes: 297.Bl -tag -width ".Dv DS_SELECT_ADDONLY" 298.It Dv DS_SELECT_ADD 299In 300.Dq add 301mode, 302.Fn devstat_selectdevs 303will select any unselected devices specified by name or matching pattern. 304It will also select more devices, in devstat list order, until the number 305of selected devices is equal to 306.Fa maxshowdevs 307or until all devices are 308selected. 309.It Dv DS_SELECT_ONLY 310In 311.Dq only 312mode, 313.Fn devstat_selectdevs 314will clear all current selections, and will only select devices specified 315by name or by matching pattern. 316.It Dv DS_SELECT_REMOVE 317In 318.Dq remove 319mode, 320.Fn devstat_selectdevs 321will remove devices specified by name or by matching pattern. 322It will not select any additional devices. 323.It Dv DS_SELECT_ADDONLY 324In 325.Dq "add only" 326mode, 327.Fn devstat_selectdevs 328will select any unselected devices specified by name or matching pattern. 329In this respect it is identical to 330.Dq add 331mode. 332It will not, however, select any devices other than those specified. 333.El 334.Pp 335In all selection modes, 336.Fn devstat_selectdevs 337will not select any more than 338.Fa maxshowdevs 339devices. 340One exception to this is when you are in 341.Dq top 342mode and no devices have been selected. 343In this case, 344.Fn devstat_selectdevs 345will select every device in the system. 346Client programs must pay attention to selection order when deciding whether 347to pay attention to a particular device. 348This may be the wrong behavior, and probably requires additional thought. 349.Pp 350The 351.Fn devstat_selectdevs 352function 353handles allocation and resizing of the 354.Fa dev_select 355structure passed in 356by the client. 357The 358.Fn devstat_selectdevs 359function 360uses the 361.Fa numdevs 362and 363.Fa current_generation 364fields to track the 365current 366.Nm 367generation and number of devices. 368If 369.Fa num_selections 370is not the same 371as 372.Fa numdevs 373or if 374.Fa select_generation 375is not the same as 376.Fa current_generation , 377.Fn devstat_selectdevs 378will resize the selection list as necessary, and re-initialize the 379selection array. 380.Pp 381The 382.Fn devstat_buildmatch 383function 384takes a comma separated match string and compiles it into a 385.Vt devstat_match 386structure that is understood by 387.Fn devstat_selectdevs . 388Match strings have the following format: 389.Pp 390.D1 Ar device , Ns Ar type , Ns Ar if 391.Pp 392The 393.Fn devstat_buildmatch 394function 395takes care of allocating and reallocating the match list as necessary. 396Currently known match types include: 397.Bl -tag -width indent 398.It device type: 399.Bl -tag -width ".Li enclosure" -compact 400.It Li da 401Direct Access devices 402.It Li sa 403Sequential Access devices 404.It Li printer 405Printers 406.It Li proc 407Processor devices 408.It Li worm 409Write Once Read Multiple devices 410.It Li cd 411CD devices 412.It Li scanner 413Scanner devices 414.It Li optical 415Optical Memory devices 416.It Li changer 417Medium Changer devices 418.It Li comm 419Communication devices 420.It Li array 421Storage Array devices 422.It Li enclosure 423Enclosure Services devices 424.It Li floppy 425Floppy devices 426.El 427.It interface: 428.Bl -tag -width ".Li enclosure" -compact 429.It Li IDE 430Integrated Drive Electronics devices 431.It Li SCSI 432Small Computer System Interface devices 433.It Li other 434Any other device interface 435.El 436.It passthrough: 437.Bl -tag -width ".Li enclosure" -compact 438.It Li pass 439Passthrough devices 440.El 441.El 442.Pp 443The 444.Fn devstat_compute_statistics 445function 446is an updated version of 447.Fn compute_stats 448that provides more complete statistics calculation. 449There are four arguments for which values 450.Em must 451be supplied: 452.Fa current , 453.Fa previous , 454.Fa etime , 455and the terminating argument for the varargs list, 456.Dv DSM_NONE . 457For most applications, the user will want to supply valid 458.Vt devstat 459structures for both 460.Fa current 461and 462.Fa previous . 463In some instances, for instance when calculating statistics since system 464boot, the user may pass in a 465.Dv NULL 466pointer for the 467.Fa previous 468argument. 469In that case, 470.Fn devstat_compute_statistics 471will use the total stats in the 472.Fa current 473structure to calculate statistics over 474.Fa etime . 475For each statistics to be calculated, the user should supply the proper 476enumerated type (listed below), and a variable of the indicated type. 477All statistics are either integer values, for which a 478.Vt u_int64_t 479is used, 480or floating point, for which a 481.Vt "long double" 482is used. 483The statistics that may be calculated are: 484.Bl -tag -width ".Dv DSM_TRANSFERS_PER_SECOND_OTHER" 485.It Dv DSM_NONE 486type: N/A 487.Pp 488This 489.Em must 490be the last argument passed to 491.Fn devstat_compute_statistics . 492It is an argument list terminator. 493.It Dv DSM_TOTAL_BYTES 494type: 495.Vt "u_int64_t *" 496.Pp 497The total number of bytes transferred between the acquisition of 498.Fa previous 499and 500.Fa current . 501.It Dv DSM_TOTAL_BYTES_READ 502.It Dv DSM_TOTAL_BYTES_WRITE 503.It Dv DSM_TOTAL_BYTES_FREE 504type: 505.Vt "u_int64_t *" 506.Pp 507The total number of bytes in transactions of the specified type 508between the acquisition of 509.Fa previous 510and 511.Fa current . 512.It Dv DSM_TOTAL_TRANSFERS 513type: 514.Vt "u_int64_t *" 515.Pp 516The total number of transfers between the acquisition of 517.Fa previous 518and 519.Fa current . 520.It Dv DSM_TOTAL_TRANSFERS_OTHER 521.It Dv DSM_TOTAL_TRANSFERS_READ 522.It Dv DSM_TOTAL_TRANSFERS_WRITE 523.It Dv DSM_TOTAL_TRANSFERS_FREE 524type: 525.Vt "u_int64_t *" 526.Pp 527The total number of transactions of the specified type between 528the acquisition of 529.Fa previous 530and 531.Fa current . 532.It Dv DSM_TOTAL_BLOCKS 533type: 534.Vt "u_int64_t *" 535.Pp 536The total number of blocks transferred between the acquisition of 537.Fa previous 538and 539.Fa current . 540This number is in terms of the blocksize reported by the device. 541If no blocksize has been reported (i.e., the block size is 0), a default 542blocksize of 512 bytes will be used in the calculation. 543.It Dv DSM_TOTAL_BLOCKS_READ 544.It Dv DSM_TOTAL_BLOCKS_WRITE 545.It Dv DSM_TOTAL_BLOCKS_FREE 546type: 547.Vt "u_int64_t *" 548.Pp 549The total number of blocks of the specified type between the acquisition of 550.Fa previous 551and 552.Fa current . 553This number is in terms of the blocksize reported by the device. 554If no blocksize has been reported (i.e., the block size is 0), a default 555blocksize of 512 bytes will be used in the calculation. 556.It Dv DSM_KB_PER_TRANSFER 557type: 558.Vt "long double *" 559.Pp 560The average number of kilobytes per transfer between the acquisition of 561.Fa previous 562and 563.Fa current . 564.It Dv DSM_KB_PER_TRANSFER_READ 565.It Dv DSM_KB_PER_TRANSFER_WRITE 566.It Dv DSM_KB_PER_TRANSFER_FREE 567type: 568.Vt "long double *" 569.Pp 570The average number of kilobytes in the specified type transaction between 571the acquisition of 572.Fa previous 573and 574.Fa current . 575.It Dv DSM_TRANSFERS_PER_SECOND 576type: 577.Vt "long double *" 578.Pp 579The average number of transfers per second between the acquisition of 580.Fa previous 581and 582.Fa current . 583.It Dv DSM_TRANSFERS_PER_SECOND_OTHER 584.It Dv DSM_TRANSFERS_PER_SECOND_READ 585.It Dv DSM_TRANSFERS_PER_SECOND_WRITE 586.It Dv DSM_TRANSFERS_PER_SECOND_FREE 587type: 588.Vt "long double *" 589.Pp 590The average number of transactions of the specified type per second 591between the acquisition of 592.Fa previous 593and 594.Fa current . 595.It Dv DSM_MB_PER_SECOND 596type: 597.Vt "long double *" 598.Pp 599The average number of megabytes transferred per second between the 600acquisition of 601.Fa previous 602and 603.Fa current . 604.It Dv DSM_MB_PER_SECOND_READ 605.It Dv DSM_MB_PER_SECOND_WRITE 606.It Dv DSM_MB_PER_SECOND_FREE 607type: 608.Vt "long double *" 609.Pp 610The average number of megabytes per second in the specified type of 611transaction between the acquisition of 612.Fa previous 613and 614.Fa current . 615.It Dv DSM_BLOCKS_PER_SECOND 616type: 617.Vt "long double *" 618.Pp 619The average number of blocks transferred per second between the acquisition of 620.Fa previous 621and 622.Fa current . 623This number is in terms of the blocksize reported by the device. 624If no blocksize has been reported (i.e., the block size is 0), a default 625blocksize of 512 bytes will be used in the calculation. 626.It Dv DSM_BLOCKS_PER_SECOND_READ 627.It Dv DSM_BLOCKS_PER_SECOND_WRITE 628.It Dv DSM_BLOCKS_PER_SECOND_FREE 629type: 630.Vt "long double *" 631.Pp 632The average number of blocks per second in the specificed type of transaction 633between the acquisition of 634.Fa previous 635and 636.Fa current . 637This number is in terms of the blocksize reported by the device. 638If no blocksize has been reported (i.e., the block size is 0), a default 639blocksize of 512 bytes will be used in the calculation. 640.It Dv DSM_MS_PER_TRANSACTION 641type: 642.Vt "long double *" 643.Pp 644The average duration of transactions between the acquisition of 645.Fa previous 646and 647.Fa current . 648.It Dv DSM_MS_PER_TRANSACTION_OTHER 649.It Dv DSM_MS_PER_TRANSACTION_READ 650.It Dv DSM_MS_PER_TRANSACTION_WRITE 651.It Dv DSM_MS_PER_TRANSACTION_FREE 652type: 653.Vt "long double *" 654.Pp 655The average duration of transactions of the specified type between the 656acquisition of 657.Fa previous 658and 659.Fa current . 660.It Dv DSM_BUSY_PCT 661type: 662.Vt "long double *" 663.Pp 664The percentage of time the device had one or more transactions outstanding 665between the acquisition of 666.Fa previous 667and 668.Fa current . 669.It Dv DSM_QUEUE_LENGTH 670type: 671.Vt "u_int64_t *" 672.Pp 673The number of not yet completed transactions at the time when 674.Fa current 675was acquired. 676.It Dv DSM_SKIP 677type: N/A 678.Pp 679If you do not need a result from 680.Fn devstat_compute_statistics , 681just put 682.Dv DSM_SKIP 683as first (type) parameter and 684.Dv NULL 685as second parameter. 686This can be useful in scenarios where the statistics to be calculated 687are determined at run time. 688.El 689.Pp 690The 691.Fn devstat_compute_etime 692function 693provides an easy way to find the difference in seconds between two 694.Vt bintime 695structures. 696This is most commonly used in conjunction with the time recorded by the 697.Fn devstat_getdevs 698function (in 699.Vt "struct statinfo" ) 700each time it fetches the current 701.Nm 702list. 703.Sh RETURN VALUES 704The 705.Fn devstat_getnumdevs , 706.Fn devstat_getgeneration , 707and 708.Fn devstat_getversion 709function 710return the indicated sysctl variable, or \-1 if there is an error 711fetching the variable. 712.Pp 713The 714.Fn devstat_checkversion 715function 716returns 0 if the kernel and userland 717.Nm 718versions match. 719If they do not match, it returns \-1. 720.Pp 721The 722.Fn devstat_getdevs 723and 724.Fn devstat_selectdevs 725functions 726return \-1 in case of an error, 0 if there is no error, and 1 if the device 727list or selected devices have changed. 728A return value of 1 from 729.Fn devstat_getdevs 730is usually a hint to re-run 731.Fn devstat_selectdevs 732because the device list has changed. 733.Pp 734The 735.Fn devstat_buildmatch 736function returns \-1 for error, and 0 if there is no error. 737.Pp 738The 739.Fn devstat_compute_etime 740function 741returns the computed elapsed time. 742.Pp 743The 744.Fn devstat_compute_statistics 745function returns \-1 for error, and 0 for success. 746.Pp 747If an error is returned from one of the 748.Nm 749library functions, the reason for the error is generally printed in 750the global string 751.Va devstat_errbuf 752which is 753.Dv DEVSTAT_ERRBUF_SIZE 754characters long. 755.Sh SEE ALSO 756.Xr systat 1 , 757.Xr kvm 3 , 758.Xr sysctl 3 , 759.Xr iostat 8 , 760.Xr rpc.rstatd 8 , 761.Xr sysctl 8 , 762.Xr vmstat 8 , 763.Xr devstat 9 764.Sh HISTORY 765The 766.Nm 767statistics system first appeared in 768.Fx 3.0 . 769The new interface (the functions prefixed with 770.Li devstat_ ) 771first appeared in 772.Fx 5.0 . 773.Sh AUTHORS 774.An Kenneth Merry Aq ken@FreeBSD.org 775.Sh BUGS 776There should probably be an interface to de-allocate memory allocated by 777.Fn devstat_getdevs , 778.Fn devstat_selectdevs , 779and 780.Fn devstat_buildmatch . 781.Pp 782The 783.Fn devstat_selectdevs 784function 785should probably not select more than 786.Fa maxshowdevs 787devices in 788.Dq top 789mode when no devices have been selected previously. 790.Pp 791There should probably be functions to perform the statistics buffer 792swapping that goes on in most of the clients of this library. 793.Pp 794The 795.Vt statinfo 796and 797.Vt devinfo 798structures should probably be cleaned up and thought out a little more. 799