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.Fn devstat_compute_etime "struct bintime cur_time" "struct bintime prev_time" 91.Sh DESCRIPTION 92The 93.Nm 94library is a library of helper functions for dealing with the kernel 95.Xr devstat 9 96interface, which is accessible to users via 97.Xr sysctl 3 98and 99.Xr kvm 3 . 100All functions that take a 101.Vt "kvm_t *" 102as first argument can be passed 103.Dv NULL 104instead of a kvm handle as this argument, 105which causes the data to be read via 106.Xr sysctl 3 . 107Otherwise, it is read via 108.Xr kvm 3 109using the supplied handle. 110The 111.Fn devstat_checkversion 112function 113should be called with each kvm handle that is going to be used (or with 114.Dv NULL 115if 116.Xr sysctl 3 117is going to be used). 118.Pp 119The 120.Fn devstat_getnumdevs 121function 122returns the number of devices registered with the 123.Nm 124subsystem in the kernel. 125.Pp 126The 127.Fn devstat_getgeneration 128function 129returns the current generation of the 130.Nm 131list of devices in the kernel. 132.Pp 133The 134.Fn devstat_getversion 135function 136returns the current kernel 137.Nm 138version. 139.Pp 140The 141.Fn devstat_checkversion 142function 143checks the userland 144.Nm 145version against the kernel 146.Nm 147version. 148If the two are identical, it returns zero. 149Otherwise, it prints an appropriate error in 150.Va devstat_errbuf 151and returns \-1. 152.Pp 153The 154.Fn devstat_getdevs 155function 156fetches the current list of devices and statistics into the supplied 157.Vt statinfo 158structure. 159The 160.Vt statinfo 161structure can be found in 162.In devstat.h : 163.Bd -literal -offset indent 164struct statinfo { 165 long cp_time[CPUSTATES]; 166 long tk_nin; 167 long tk_nout; 168 struct devinfo *dinfo; 169 long double snap_time; 170}; 171.Ed 172.Pp 173The 174.Fn devstat_getdevs 175function 176expects the 177.Vt statinfo 178structure to be allocated, and it also expects the 179.Va dinfo 180subelement to be allocated and zeroed prior to the first invocation of 181.Fn devstat_getdevs . 182The 183.Va dinfo 184subelement is used to store state between calls, and should not be modified 185after the first call to 186.Fn devstat_getdevs . 187The 188.Va dinfo 189subelement contains the following elements: 190.Bd -literal -offset indent 191struct devinfo { 192 struct devstat *devices; 193 u_int8_t *mem_ptr; 194 long generation; 195 int numdevs; 196}; 197.Ed 198.Pp 199The 200.Va kern.devstat.all 201.Xr sysctl 8 202variable contains an array of 203.Nm 204structures, but at the head of the array is the current 205.Nm 206generation. 207The reason the generation is at the head of the buffer is so that userland 208software accessing the 209.Nm 210statistics information can atomically get 211both the statistics information and the corresponding generation number. 212If client software were forced to get the generation number via a separate 213.Xr sysctl 8 214variable (which is available for convenience), the list of devices could 215change between the time the client gets the generation and the time the 216client gets the device list. 217.Pp 218The 219.Va mem_ptr 220subelement of the 221.Vt devinfo 222structure is a pointer to memory that is allocated, and resized if 223necessary, by 224.Fn devstat_getdevs . 225The devices subelement of the 226.Vt devinfo 227structure is basically a pointer to the beginning of the array of devstat 228structures from the 229.Va kern.devstat.all 230.Xr sysctl 8 231variable (or the corresponding values read via 232.Xr kvm 3 ) . 233The generation subelement of the 234.Vt devinfo 235structure contains the corresponding generation number. 236The 237.Va numdevs 238subelement of the 239.Vt devinfo 240structure contains the current 241number of devices registered with the kernel 242.Nm 243subsystem. 244.Pp 245The 246.Fn devstat_selectdevs 247function 248selects devices to display based upon a number of criteria: 249.Bl -tag -width indent 250.It specified devices 251Specified devices are the first selection priority. 252These are generally devices specified by name by the user e.g.\& 253.Li da0 , da1 , cd0 . 254.It match patterns 255These are pattern matching expressions generated by 256.Fn devstat_buildmatch 257from user input. 258.It performance 259If performance mode is enabled, devices will be sorted based on the 260.Va bytes 261field in the 262.Vt device_selection 263structure passed in to 264.Fn devstat_selectdevs . 265The 266.Va bytes 267value currently must be maintained by the user. 268In the future, this may be done for him in a 269.Nm 270library routine. 271If no devices have been selected by name or by pattern, the performance 272tracking code will select every device in the system, and sort them by 273performance. 274If devices have been selected by name or pattern, the performance tracking 275code will honor those selections and will only sort among the selected 276devices. 277.It order in the devstat list 278If the selection mode is set to 279.Dv DS_SELECT_ADD , 280and if there are still less 281than 282.Fa maxshowdevs 283devices selected, 284.Fn devstat_selectdevs 285will automatically select up to 286.Fa maxshowdevs 287devices. 288.El 289.Pp 290The 291.Fn devstat_selectdevs 292function 293performs selections in four different modes: 294.Bl -tag -width ".Dv DS_SELECT_ADDONLY" 295.It Dv DS_SELECT_ADD 296In 297.Dq add 298mode, 299.Fn devstat_selectdevs 300will select any unselected devices specified by name or matching pattern. 301It will also select more devices, in devstat list order, until the number 302of selected devices is equal to 303.Fa maxshowdevs 304or until all devices are 305selected. 306.It Dv DS_SELECT_ONLY 307In 308.Dq only 309mode, 310.Fn devstat_selectdevs 311will clear all current selections, and will only select devices specified 312by name or by matching pattern. 313.It Dv DS_SELECT_REMOVE 314In 315.Dq remove 316mode, 317.Fn devstat_selectdevs 318will remove devices specified by name or by matching pattern. 319It will not select any additional devices. 320.It Dv DS_SELECT_ADDONLY 321In 322.Dq "add only" 323mode, 324.Fn devstat_selectdevs 325will select any unselected devices specified by name or matching pattern. 326In this respect it is identical to 327.Dq add 328mode. 329It will not, however, select any devices other than those specified. 330.El 331.Pp 332In all selection modes, 333.Fn devstat_selectdevs 334will not select any more than 335.Fa maxshowdevs 336devices. 337One exception to this is when you are in 338.Dq top 339mode and no devices have been selected. 340In this case, 341.Fn devstat_selectdevs 342will select every device in the system. 343Client programs must pay attention to selection order when deciding whether 344to pay attention to a particular device. 345This may be the wrong behavior, and probably requires additional thought. 346.Pp 347The 348.Fn devstat_selectdevs 349function 350handles allocation and resizing of the 351.Fa dev_select 352structure passed in 353by the client. 354The 355.Fn devstat_selectdevs 356function 357uses the 358.Fa numdevs 359and 360.Fa current_generation 361fields to track the 362current 363.Nm 364generation and number of devices. 365If 366.Fa num_selections 367is not the same 368as 369.Fa numdevs 370or if 371.Fa select_generation 372is not the same as 373.Fa current_generation , 374.Fn devstat_selectdevs 375will resize the selection list as necessary, and re-initialize the 376selection array. 377.Pp 378The 379.Fn devstat_buildmatch 380function 381takes a comma separated match string and compiles it into a 382.Vt devstat_match 383structure that is understood by 384.Fn devstat_selectdevs . 385Match strings have the following format: 386.Pp 387.D1 Ar device , Ns Ar type , Ns Ar if 388.Pp 389The 390.Fn devstat_buildmatch 391function 392takes care of allocating and reallocating the match list as necessary. 393Currently known match types include: 394.Bl -tag -width indent 395.It device type: 396.Bl -tag -width ".Li enclosure" -compact 397.It Li da 398Direct Access devices 399.It Li sa 400Sequential Access devices 401.It Li printer 402Printers 403.It Li proc 404Processor devices 405.It Li worm 406Write Once Read Multiple devices 407.It Li cd 408CD devices 409.It Li scanner 410Scanner devices 411.It Li optical 412Optical Memory devices 413.It Li changer 414Medium Changer devices 415.It Li comm 416Communication devices 417.It Li array 418Storage Array devices 419.It Li enclosure 420Enclosure Services devices 421.It Li floppy 422Floppy devices 423.El 424.It interface: 425.Bl -tag -width ".Li enclosure" -compact 426.It Li IDE 427Integrated Drive Electronics devices 428.It Li SCSI 429Small Computer System Interface devices 430.It Li other 431Any other device interface 432.El 433.It passthrough: 434.Bl -tag -width ".Li enclosure" -compact 435.It Li pass 436Passthrough devices 437.El 438.El 439.Pp 440The 441.Fn devstat_compute_statistics 442function 443is an updated version of 444.Fn compute_stats 445that provides more 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 687.Fn devstat_compute_etime 688provides an easy way to find the difference in seconds between two 689.Vt bintime 690structures. 691This is most commonly used in conjunction with the time recorded by the 692.Fn devstat_getdevs 693function (in 694.Vt "struct statinfo" ) 695each time it fetches the current 696.Nm 697list. 698.Sh RETURN VALUES 699The 700.Fn devstat_getnumdevs , 701.Fn devstat_getgeneration , 702and 703.Fn devstat_getversion 704function 705return the indicated sysctl variable, or \-1 if there is an error 706fetching the variable. 707.Pp 708The 709.Fn devstat_checkversion 710function 711returns 0 if the kernel and userland 712.Nm 713versions match. 714If they do not match, it returns \-1. 715.Pp 716The 717.Fn devstat_getdevs 718and 719.Fn devstat_selectdevs 720functions 721return \-1 in case of an error, 0 if there is no error, and 1 if the device 722list or selected devices have changed. 723A return value of 1 from 724.Fn devstat_getdevs 725is usually a hint to re-run 726.Fn devstat_selectdevs 727because the device list has changed. 728.Pp 729The 730.Fn devstat_buildmatch 731function returns \-1 for error, and 0 if there is no error. 732.Pp 733The 734.Fn devstat_compute_etime 735function 736returns the computed elapsed time. 737.Pp 738The 739.Fn devstat_compute_statistics 740function returns \-1 for error, and 0 for success. 741.Pp 742If an error is returned from one of the 743.Nm 744library functions, the reason for the error is generally printed in 745the global string 746.Va devstat_errbuf 747which is 748.Dv DEVSTAT_ERRBUF_SIZE 749characters long. 750.Sh SEE ALSO 751.Xr systat 1 , 752.Xr kvm 3 , 753.Xr sysctl 3 , 754.Xr iostat 8 , 755.Xr rpc.rstatd 8 , 756.Xr sysctl 8 , 757.Xr vmstat 8 , 758.Xr devstat 9 759.Sh HISTORY 760The 761.Nm 762statistics system first appeared in 763.Fx 3.0 . 764The new interface (the functions prefixed with 765.Li devstat_ ) 766first appeared in 767.Fx 5.0 . 768.Sh AUTHORS 769.An Kenneth Merry Aq [email protected] 770.Sh BUGS 771There should probably be an interface to de-allocate memory allocated by 772.Fn devstat_getdevs , 773.Fn devstat_selectdevs , 774and 775.Fn devstat_buildmatch . 776.Pp 777The 778.Fn devstat_selectdevs 779function 780should probably not select more than 781.Fa maxshowdevs 782devices in 783.Dq top 784mode when no devices have been selected previously. 785.Pp 786There should probably be functions to perform the statistics buffer 787swapping that goes on in most of the clients of this library. 788.Pp 789The 790.Vt statinfo 791and 792.Vt devinfo 793structures should probably be cleaned up and thought out a little more. 794