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 December 15, 2012 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 uint8_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 uint64_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 "uint64_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 "uint64_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 "uint64_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 "uint64_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_DURATION 530type: 531.Vt "long double *" 532.Pp 533The total duration of transactions, in seconds, between the acquisition of 534.Fa previous 535and 536.Fa current . 537.It Dv DSM_TOTAL_DURATION_OTHER 538.It Dv DSM_TOTAL_DURATION_READ 539.It Dv DSM_TOTAL_DURATION_WRITE 540.It Dv DSM_TOTAL_DURATION_FREE 541type: 542.Vt "long double *" 543.Pp 544The total duration of transactions of the specified type between 545the acquisition of 546.Fa previous 547and 548.Fa current . 549.It Dv DSM_TOTAL_BUSY_TIME 550type: 551.Vt "long double *" 552.Pp 553Total time the device had one or more transactions outstanding 554between the acquisition of 555.Fa previous 556and 557.Fa current . 558.It Dv DSM_TOTAL_BLOCKS 559type: 560.Vt "uint64_t *" 561.Pp 562The total number of blocks transferred between the acquisition of 563.Fa previous 564and 565.Fa current . 566This number is in terms of the blocksize reported by the device. 567If no blocksize has been reported (i.e., the block size is 0), a default 568blocksize of 512 bytes will be used in the calculation. 569.It Dv DSM_TOTAL_BLOCKS_READ 570.It Dv DSM_TOTAL_BLOCKS_WRITE 571.It Dv DSM_TOTAL_BLOCKS_FREE 572type: 573.Vt "uint64_t *" 574.Pp 575The total number of blocks of the specified type between the acquisition of 576.Fa previous 577and 578.Fa current . 579This number is in terms of the blocksize reported by the device. 580If no blocksize has been reported (i.e., the block size is 0), a default 581blocksize of 512 bytes will be used in the calculation. 582.It Dv DSM_KB_PER_TRANSFER 583type: 584.Vt "long double *" 585.Pp 586The average number of kilobytes per transfer between the acquisition of 587.Fa previous 588and 589.Fa current . 590.It Dv DSM_KB_PER_TRANSFER_READ 591.It Dv DSM_KB_PER_TRANSFER_WRITE 592.It Dv DSM_KB_PER_TRANSFER_FREE 593type: 594.Vt "long double *" 595.Pp 596The average number of kilobytes in the specified type transaction between 597the acquisition of 598.Fa previous 599and 600.Fa current . 601.It Dv DSM_TRANSFERS_PER_SECOND 602type: 603.Vt "long double *" 604.Pp 605The average number of transfers per second between the acquisition of 606.Fa previous 607and 608.Fa current . 609.It Dv DSM_TRANSFERS_PER_SECOND_OTHER 610.It Dv DSM_TRANSFERS_PER_SECOND_READ 611.It Dv DSM_TRANSFERS_PER_SECOND_WRITE 612.It Dv DSM_TRANSFERS_PER_SECOND_FREE 613type: 614.Vt "long double *" 615.Pp 616The average number of transactions of the specified type per second 617between the acquisition of 618.Fa previous 619and 620.Fa current . 621.It Dv DSM_MB_PER_SECOND 622type: 623.Vt "long double *" 624.Pp 625The average number of megabytes transferred per second between the 626acquisition of 627.Fa previous 628and 629.Fa current . 630.It Dv DSM_MB_PER_SECOND_READ 631.It Dv DSM_MB_PER_SECOND_WRITE 632.It Dv DSM_MB_PER_SECOND_FREE 633type: 634.Vt "long double *" 635.Pp 636The average number of megabytes per second in the specified type of 637transaction between the acquisition of 638.Fa previous 639and 640.Fa current . 641.It Dv DSM_BLOCKS_PER_SECOND 642type: 643.Vt "long double *" 644.Pp 645The average number of blocks transferred per second between the acquisition of 646.Fa previous 647and 648.Fa current . 649This number is in terms of the blocksize reported by the device. 650If no blocksize has been reported (i.e., the block size is 0), a default 651blocksize of 512 bytes will be used in the calculation. 652.It Dv DSM_BLOCKS_PER_SECOND_READ 653.It Dv DSM_BLOCKS_PER_SECOND_WRITE 654.It Dv DSM_BLOCKS_PER_SECOND_FREE 655type: 656.Vt "long double *" 657.Pp 658The average number of blocks per second in the specified type of transaction 659between the acquisition of 660.Fa previous 661and 662.Fa current . 663This number is in terms of the blocksize reported by the device. 664If no blocksize has been reported (i.e., the block size is 0), a default 665blocksize of 512 bytes will be used in the calculation. 666.It Dv DSM_MS_PER_TRANSACTION 667type: 668.Vt "long double *" 669.Pp 670The average duration of transactions between the acquisition of 671.Fa previous 672and 673.Fa current . 674.It Dv DSM_MS_PER_TRANSACTION_OTHER 675.It Dv DSM_MS_PER_TRANSACTION_READ 676.It Dv DSM_MS_PER_TRANSACTION_WRITE 677.It Dv DSM_MS_PER_TRANSACTION_FREE 678type: 679.Vt "long double *" 680.Pp 681The average duration of transactions of the specified type between the 682acquisition of 683.Fa previous 684and 685.Fa current . 686.It Dv DSM_BUSY_PCT 687type: 688.Vt "long double *" 689.Pp 690The percentage of time the device had one or more transactions outstanding 691between the acquisition of 692.Fa previous 693and 694.Fa current . 695.It Dv DSM_QUEUE_LENGTH 696type: 697.Vt "uint64_t *" 698.Pp 699The number of not yet completed transactions at the time when 700.Fa current 701was acquired. 702.It Dv DSM_SKIP 703type: N/A 704.Pp 705If you do not need a result from 706.Fn devstat_compute_statistics , 707just put 708.Dv DSM_SKIP 709as first (type) parameter and 710.Dv NULL 711as second parameter. 712This can be useful in scenarios where the statistics to be calculated 713are determined at run time. 714.El 715.Pp 716The 717.Fn devstat_compute_etime 718function 719provides an easy way to find the difference in seconds between two 720.Vt bintime 721structures. 722This is most commonly used in conjunction with the time recorded by the 723.Fn devstat_getdevs 724function (in 725.Vt "struct statinfo" ) 726each time it fetches the current 727.Nm 728list. 729.Sh RETURN VALUES 730The 731.Fn devstat_getnumdevs , 732.Fn devstat_getgeneration , 733and 734.Fn devstat_getversion 735function 736return the indicated sysctl variable, or \-1 if there is an error 737fetching the variable. 738.Pp 739The 740.Fn devstat_checkversion 741function 742returns 0 if the kernel and userland 743.Nm 744versions match. 745If they do not match, it returns \-1. 746.Pp 747The 748.Fn devstat_getdevs 749and 750.Fn devstat_selectdevs 751functions 752return \-1 in case of an error, 0 if there is no error, and 1 if the device 753list or selected devices have changed. 754A return value of 1 from 755.Fn devstat_getdevs 756is usually a hint to re-run 757.Fn devstat_selectdevs 758because the device list has changed. 759.Pp 760The 761.Fn devstat_buildmatch 762function returns \-1 for error, and 0 if there is no error. 763.Pp 764The 765.Fn devstat_compute_etime 766function 767returns the computed elapsed time. 768.Pp 769The 770.Fn devstat_compute_statistics 771function returns \-1 for error, and 0 for success. 772.Pp 773If an error is returned from one of the 774.Nm 775library functions, the reason for the error is generally printed in 776the global string 777.Va devstat_errbuf 778which is 779.Dv DEVSTAT_ERRBUF_SIZE 780characters long. 781.Sh SEE ALSO 782.Xr systat 1 , 783.Xr kvm 3 , 784.Xr sysctl 3 , 785.Xr iostat 8 , 786.Xr rpc.rstatd 8 , 787.Xr sysctl 8 , 788.Xr vmstat 8 , 789.Xr devstat 9 790.Sh HISTORY 791The 792.Nm 793statistics system first appeared in 794.Fx 3.0 . 795The new interface (the functions prefixed with 796.Li devstat_ ) 797first appeared in 798.Fx 5.0 . 799.Sh AUTHORS 800.An Kenneth Merry Aq ken@FreeBSD.org 801.Sh BUGS 802There should probably be an interface to de-allocate memory allocated by 803.Fn devstat_getdevs , 804.Fn devstat_selectdevs , 805and 806.Fn devstat_buildmatch . 807.Pp 808The 809.Fn devstat_selectdevs 810function 811should probably not select more than 812.Fa maxshowdevs 813devices in 814.Dq top 815mode when no devices have been selected previously. 816.Pp 817There should probably be functions to perform the statistics buffer 818swapping that goes on in most of the clients of this library. 819.Pp 820The 821.Vt statinfo 822and 823.Vt devinfo 824structures should probably be cleaned up and thought out a little more. 825