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 provides complete statistics calculation. 446There are four arguments for which values 447.Em must 448be supplied: 449.Fa current , 450.Fa previous , 451.Fa etime , 452and the terminating argument for the varargs list, 453.Dv DSM_NONE . 454For most applications, the user will want to supply valid 455.Vt devstat 456structures for both 457.Fa current 458and 459.Fa previous . 460In some instances, for instance when calculating statistics since system 461boot, the user may pass in a 462.Dv NULL 463pointer for the 464.Fa previous 465argument. 466In that case, 467.Fn devstat_compute_statistics 468will use the total stats in the 469.Fa current 470structure to calculate statistics over 471.Fa etime . 472For each statistics to be calculated, the user should supply the proper 473enumerated type (listed below), and a variable of the indicated type. 474All statistics are either integer values, for which a 475.Vt u_int64_t 476is used, 477or floating point, for which a 478.Vt "long double" 479is used. 480The statistics that may be calculated are: 481.Bl -tag -width ".Dv DSM_TRANSFERS_PER_SECOND_OTHER" 482.It Dv DSM_NONE 483type: N/A 484.Pp 485This 486.Em must 487be the last argument passed to 488.Fn devstat_compute_statistics . 489It is an argument list terminator. 490.It Dv DSM_TOTAL_BYTES 491type: 492.Vt "u_int64_t *" 493.Pp 494The total number of bytes transferred between the acquisition of 495.Fa previous 496and 497.Fa current . 498.It Dv DSM_TOTAL_BYTES_READ 499.It Dv DSM_TOTAL_BYTES_WRITE 500.It Dv DSM_TOTAL_BYTES_FREE 501type: 502.Vt "u_int64_t *" 503.Pp 504The total number of bytes in transactions of the specified type 505between the acquisition of 506.Fa previous 507and 508.Fa current . 509.It Dv DSM_TOTAL_TRANSFERS 510type: 511.Vt "u_int64_t *" 512.Pp 513The total number of transfers between the acquisition of 514.Fa previous 515and 516.Fa current . 517.It Dv DSM_TOTAL_TRANSFERS_OTHER 518.It Dv DSM_TOTAL_TRANSFERS_READ 519.It Dv DSM_TOTAL_TRANSFERS_WRITE 520.It Dv DSM_TOTAL_TRANSFERS_FREE 521type: 522.Vt "u_int64_t *" 523.Pp 524The total number of transactions of the specified type between 525the acquisition of 526.Fa previous 527and 528.Fa current . 529.It Dv DSM_TOTAL_BLOCKS 530type: 531.Vt "u_int64_t *" 532.Pp 533The total number of blocks transferred between the acquisition of 534.Fa previous 535and 536.Fa current . 537This number is in terms of the blocksize reported by the device. 538If no blocksize has been reported (i.e., the block size is 0), a default 539blocksize of 512 bytes will be used in the calculation. 540.It Dv DSM_TOTAL_BLOCKS_READ 541.It Dv DSM_TOTAL_BLOCKS_WRITE 542.It Dv DSM_TOTAL_BLOCKS_FREE 543type: 544.Vt "u_int64_t *" 545.Pp 546The total number of blocks of the specified type between the acquisition of 547.Fa previous 548and 549.Fa current . 550This number is in terms of the blocksize reported by the device. 551If no blocksize has been reported (i.e., the block size is 0), a default 552blocksize of 512 bytes will be used in the calculation. 553.It Dv DSM_KB_PER_TRANSFER 554type: 555.Vt "long double *" 556.Pp 557The average number of kilobytes per transfer between the acquisition of 558.Fa previous 559and 560.Fa current . 561.It Dv DSM_KB_PER_TRANSFER_READ 562.It Dv DSM_KB_PER_TRANSFER_WRITE 563.It Dv DSM_KB_PER_TRANSFER_FREE 564type: 565.Vt "long double *" 566.Pp 567The average number of kilobytes in the specified type transaction between 568the acquisition of 569.Fa previous 570and 571.Fa current . 572.It Dv DSM_TRANSFERS_PER_SECOND 573type: 574.Vt "long double *" 575.Pp 576The average number of transfers per second between the acquisition of 577.Fa previous 578and 579.Fa current . 580.It Dv DSM_TRANSFERS_PER_SECOND_OTHER 581.It Dv DSM_TRANSFERS_PER_SECOND_READ 582.It Dv DSM_TRANSFERS_PER_SECOND_WRITE 583.It Dv DSM_TRANSFERS_PER_SECOND_FREE 584type: 585.Vt "long double *" 586.Pp 587The average number of transactions of the specified type per second 588between the acquisition of 589.Fa previous 590and 591.Fa current . 592.It Dv DSM_MB_PER_SECOND 593type: 594.Vt "long double *" 595.Pp 596The average number of megabytes transferred per second between the 597acquisition of 598.Fa previous 599and 600.Fa current . 601.It Dv DSM_MB_PER_SECOND_READ 602.It Dv DSM_MB_PER_SECOND_WRITE 603.It Dv DSM_MB_PER_SECOND_FREE 604type: 605.Vt "long double *" 606.Pp 607The average number of megabytes per second in the specified type of 608transaction between the acquisition of 609.Fa previous 610and 611.Fa current . 612.It Dv DSM_BLOCKS_PER_SECOND 613type: 614.Vt "long double *" 615.Pp 616The average number of blocks transferred per second between the acquisition of 617.Fa previous 618and 619.Fa current . 620This number is in terms of the blocksize reported by the device. 621If no blocksize has been reported (i.e., the block size is 0), a default 622blocksize of 512 bytes will be used in the calculation. 623.It Dv DSM_BLOCKS_PER_SECOND_READ 624.It Dv DSM_BLOCKS_PER_SECOND_WRITE 625.It Dv DSM_BLOCKS_PER_SECOND_FREE 626type: 627.Vt "long double *" 628.Pp 629The average number of blocks per second in the specificed type of transaction 630between the acquisition of 631.Fa previous 632and 633.Fa current . 634This number is in terms of the blocksize reported by the device. 635If no blocksize has been reported (i.e., the block size is 0), a default 636blocksize of 512 bytes will be used in the calculation. 637.It Dv DSM_MS_PER_TRANSACTION 638type: 639.Vt "long double *" 640.Pp 641The average duration of transactions between the acquisition of 642.Fa previous 643and 644.Fa current . 645.It Dv DSM_MS_PER_TRANSACTION_OTHER 646.It Dv DSM_MS_PER_TRANSACTION_READ 647.It Dv DSM_MS_PER_TRANSACTION_WRITE 648.It Dv DSM_MS_PER_TRANSACTION_FREE 649type: 650.Vt "long double *" 651.Pp 652The average duration of transactions of the specified type between the 653acquisition of 654.Fa previous 655and 656.Fa current . 657.It Dv DSM_BUSY_PCT 658type: 659.Vt "long double *" 660.Pp 661The percentage of time the device had one or more transactions outstanding 662between the acquisition of 663.Fa previous 664and 665.Fa current . 666.It Dv DSM_QUEUE_LENGTH 667type: 668.Vt "u_int64_t *" 669.Pp 670The number of not yet completed transactions at the time when 671.Fa current 672was acquired. 673.It Dv DSM_SKIP 674type: N/A 675.Pp 676If you do not need a result from 677.Fn devstat_compute_statistics , 678just put 679.Dv DSM_SKIP 680as first (type) parameter and 681.Dv NULL 682as second parameter. 683This can be useful in scenarios where the statistics to be calculated 684are determined at run time. 685.El 686.Pp 687The 688.Fn devstat_compute_etime 689function 690provides an easy way to find the difference in seconds between two 691.Vt bintime 692structures. 693This is most commonly used in conjunction with the time recorded by the 694.Fn devstat_getdevs 695function (in 696.Vt "struct statinfo" ) 697each time it fetches the current 698.Nm 699list. 700.Sh RETURN VALUES 701The 702.Fn devstat_getnumdevs , 703.Fn devstat_getgeneration , 704and 705.Fn devstat_getversion 706function 707return the indicated sysctl variable, or \-1 if there is an error 708fetching the variable. 709.Pp 710The 711.Fn devstat_checkversion 712function 713returns 0 if the kernel and userland 714.Nm 715versions match. 716If they do not match, it returns \-1. 717.Pp 718The 719.Fn devstat_getdevs 720and 721.Fn devstat_selectdevs 722functions 723return \-1 in case of an error, 0 if there is no error, and 1 if the device 724list or selected devices have changed. 725A return value of 1 from 726.Fn devstat_getdevs 727is usually a hint to re-run 728.Fn devstat_selectdevs 729because the device list has changed. 730.Pp 731The 732.Fn devstat_buildmatch 733function returns \-1 for error, and 0 if there is no error. 734.Pp 735The 736.Fn devstat_compute_etime 737function 738returns the computed elapsed time. 739.Pp 740The 741.Fn devstat_compute_statistics 742function returns \-1 for error, and 0 for success. 743.Pp 744If an error is returned from one of the 745.Nm 746library functions, the reason for the error is generally printed in 747the global string 748.Va devstat_errbuf 749which is 750.Dv DEVSTAT_ERRBUF_SIZE 751characters long. 752.Sh SEE ALSO 753.Xr systat 1 , 754.Xr kvm 3 , 755.Xr sysctl 3 , 756.Xr iostat 8 , 757.Xr rpc.rstatd 8 , 758.Xr sysctl 8 , 759.Xr vmstat 8 , 760.Xr devstat 9 761.Sh HISTORY 762The 763.Nm 764statistics system first appeared in 765.Fx 3.0 . 766The new interface (the functions prefixed with 767.Li devstat_ ) 768first appeared in 769.Fx 5.0 . 770.Sh AUTHORS 771.An Kenneth Merry Aq ken@FreeBSD.org 772.Sh BUGS 773There should probably be an interface to de-allocate memory allocated by 774.Fn devstat_getdevs , 775.Fn devstat_selectdevs , 776and 777.Fn devstat_buildmatch . 778.Pp 779The 780.Fn devstat_selectdevs 781function 782should probably not select more than 783.Fa maxshowdevs 784devices in 785.Dq top 786mode when no devices have been selected previously. 787.Pp 788There should probably be functions to perform the statistics buffer 789swapping that goes on in most of the clients of this library. 790.Pp 791The 792.Vt statinfo 793and 794.Vt devinfo 795structures should probably be cleaned up and thought out a little more. 796