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