xref: /freebsd/lib/libdevstat/devstat.3 (revision 525fe93dc7487a1e63a90f6a2b956abc601963c1)
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.Dd December 15, 2012
29.Dt DEVSTAT 3
30.Os
31.Sh NAME
32.Nm devstat ,
33.Nm devstat_getnumdevs ,
34.Nm devstat_getgeneration ,
35.Nm devstat_getversion ,
36.Nm devstat_checkversion ,
37.Nm devstat_getdevs ,
38.Nm devstat_selectdevs ,
39.Nm devstat_buildmatch ,
40.Nm devstat_compute_statistics ,
41.Nm devstat_compute_etime
42.Nd device statistics utility library
43.Sh LIBRARY
44.Lb libdevstat
45.Sh SYNOPSIS
46.In devstat.h
47.Ft int
48.Fn devstat_getnumdevs "kvm_t *kd"
49.Ft long
50.Fn devstat_getgeneration "kvm_t *kd"
51.Ft int
52.Fn devstat_getversion "kvm_t *kd"
53.Ft int
54.Fn devstat_checkversion "kvm_t *kd"
55.Ft int
56.Fn devstat_getdevs "kvm_t *kd" "struct statinfo *stats"
57.Ft int
58.Fo devstat_selectdevs
59.Fa "struct device_selection **dev_select"
60.Fa "int *num_selected"
61.Fa "int *num_selections"
62.Fa "long *select_generation"
63.Fa "long current_generation"
64.Fa "struct devstat *devices"
65.Fa "int numdevs"
66.Fa "struct devstat_match *matches"
67.Fa "int num_matches"
68.Fa "char **dev_selections"
69.Fa "int num_dev_selections"
70.Fa "devstat_select_mode select_mode"
71.Fa "int maxshowdevs"
72.Fa "int perf_select"
73.Fc
74.Ft int
75.Fo devstat_buildmatch
76.Fa "char *match_str"
77.Fa "struct devstat_match **matches"
78.Fa "int *num_matches"
79.Fc
80.Ft int
81.Fo devstat_compute_statistics
82.Fa "struct devstat *current"
83.Fa "struct devstat *previous"
84.Fa "long double etime"
85.Fa "..."
86.Fc
87.Ft "long double"
88.Fo devstat_compute_etime
89.Fa "struct bintime *cur_time"
90.Fa "struct bintime *prev_time"
91.Fc
92.Sh DESCRIPTION
93The
94.Nm
95library is a library of helper functions for dealing with the kernel
96.Xr devstat 9
97interface, which is accessible to users via
98.Xr sysctl 3
99and
100.Xr kvm 3 .
101All functions that take a
102.Vt "kvm_t *"
103as first argument can be passed
104.Dv NULL
105instead of a kvm handle as this argument,
106which causes the data to be read via
107.Xr sysctl 3 .
108Otherwise, it is read via
109.Xr kvm 3
110using the supplied handle.
111The
112.Fn devstat_checkversion
113function
114should be called with each kvm handle that is going to be used (or with
115.Dv NULL
116if
117.Xr sysctl 3
118is going to be used).
119.Pp
120The
121.Fn devstat_getnumdevs
122function
123returns the number of devices registered with the
124.Nm
125subsystem in the kernel.
126.Pp
127The
128.Fn devstat_getgeneration
129function
130returns the current generation of the
131.Nm
132list of devices in the kernel.
133.Pp
134The
135.Fn devstat_getversion
136function
137returns the current kernel
138.Nm
139version.
140.Pp
141The
142.Fn devstat_checkversion
143function
144checks the userland
145.Nm
146version against the kernel
147.Nm
148version.
149If the two are identical, it returns zero.
150Otherwise, it prints an appropriate error in
151.Va devstat_errbuf
152and returns \-1.
153.Pp
154The
155.Fn devstat_getdevs
156function
157fetches the current list of devices and statistics into the supplied
158.Vt statinfo
159structure.
160The
161.Vt statinfo
162structure can be found in
163.In devstat.h :
164.Bd -literal -offset indent
165struct statinfo {
166	long            cp_time[CPUSTATES];
167	long            tk_nin;
168	long            tk_nout;
169	struct devinfo  *dinfo;
170	long double     snap_time;
171};
172.Ed
173.Pp
174The
175.Fn devstat_getdevs
176function
177expects the
178.Vt statinfo
179structure to be allocated, and it also expects the
180.Va dinfo
181subelement to be allocated and zeroed prior to the first invocation of
182.Fn devstat_getdevs .
183The
184.Va dinfo
185subelement is used to store state between calls, and should not be modified
186after the first call to
187.Fn devstat_getdevs .
188The
189.Va dinfo
190subelement contains the following elements:
191.Bd -literal -offset indent
192struct devinfo {
193	struct devstat	*devices;
194	uint8_t		*mem_ptr;
195	long		generation;
196	int		numdevs;
197};
198.Ed
199.Pp
200The
201.Va kern.devstat.all
202.Xr sysctl 8
203variable contains an array of
204.Nm
205structures, but at the head of the array is the current
206.Nm
207generation.
208The reason the generation is at the head of the buffer is so that userland
209software accessing the
210.Nm
211statistics information can atomically get
212both the statistics information and the corresponding generation number.
213If client software were forced to get the generation number via a separate
214.Xr sysctl 8
215variable (which is available for convenience), the list of devices could
216change between the time the client gets the generation and the time the
217client gets the device list.
218.Pp
219The
220.Va mem_ptr
221subelement of the
222.Vt devinfo
223structure is a pointer to memory that is allocated, and resized if
224necessary, by
225.Fn devstat_getdevs .
226The devices subelement of the
227.Vt devinfo
228structure is basically a pointer to the beginning of the array of devstat
229structures from the
230.Va kern.devstat.all
231.Xr sysctl 8
232variable (or the corresponding values read via
233.Xr kvm 3 ) .
234The generation subelement of the
235.Vt devinfo
236structure contains the corresponding generation number.
237The
238.Va numdevs
239subelement of the
240.Vt devinfo
241structure contains the current
242number of devices registered with the kernel
243.Nm
244subsystem.
245.Pp
246The
247.Fn devstat_selectdevs
248function
249selects devices to display based upon a number of criteria:
250.Bl -tag -width indent
251.It specified devices
252Specified devices are the first selection priority.
253These are generally devices specified by name by the user e.g.\&
254.Li da0 , da1 , cd0 .
255.It match patterns
256These are pattern matching expressions generated by
257.Fn devstat_buildmatch
258from user input.
259.It performance
260If performance mode is enabled, devices will be sorted based on the
261.Va bytes
262field in the
263.Vt device_selection
264structure passed in to
265.Fn devstat_selectdevs .
266The
267.Va bytes
268value currently must be maintained by the user.
269In the future, this may be done for him in a
270.Nm
271library routine.
272If no devices have been selected by name or by pattern, the performance
273tracking code will select every device in the system, and sort them by
274performance.
275If devices have been selected by name or pattern, the performance tracking
276code will honor those selections and will only sort among the selected
277devices.
278.It order in the devstat list
279If the selection mode is set to
280.Dv DS_SELECT_ADD ,
281and if there are still less
282than
283.Fa maxshowdevs
284devices selected,
285.Fn devstat_selectdevs
286will automatically select up to
287.Fa maxshowdevs
288devices.
289.El
290.Pp
291The
292.Fn devstat_selectdevs
293function
294performs selections in four different modes:
295.Bl -tag -width ".Dv DS_SELECT_ADDONLY"
296.It Dv DS_SELECT_ADD
297In
298.Dq add
299mode,
300.Fn devstat_selectdevs
301will select any unselected devices specified by name or matching pattern.
302It will also select more devices, in devstat list order, until the number
303of selected devices is equal to
304.Fa maxshowdevs
305or until all devices are
306selected.
307.It Dv DS_SELECT_ONLY
308In
309.Dq only
310mode,
311.Fn devstat_selectdevs
312will clear all current selections, and will only select devices specified
313by name or by matching pattern.
314.It Dv DS_SELECT_REMOVE
315In
316.Dq remove
317mode,
318.Fn devstat_selectdevs
319will remove devices specified by name or by matching pattern.
320It will not select any additional devices.
321.It Dv DS_SELECT_ADDONLY
322In
323.Dq "add only"
324mode,
325.Fn devstat_selectdevs
326will select any unselected devices specified by name or matching pattern.
327In this respect it is identical to
328.Dq add
329mode.
330It will not, however, select any devices other than those specified.
331.El
332.Pp
333In all selection modes,
334.Fn devstat_selectdevs
335will not select any more than
336.Fa maxshowdevs
337devices.
338One exception to this is when you are in
339.Dq top
340mode and no devices have been selected.
341In this case,
342.Fn devstat_selectdevs
343will select every device in the system.
344Client programs must pay attention to selection order when deciding whether
345to pay attention to a particular device.
346This may be the wrong behavior, and probably requires additional thought.
347.Pp
348The
349.Fn devstat_selectdevs
350function
351handles allocation and resizing of the
352.Fa dev_select
353structure passed in
354by the client.
355The
356.Fn devstat_selectdevs
357function
358uses the
359.Fa numdevs
360and
361.Fa current_generation
362fields to track the
363current
364.Nm
365generation and number of devices.
366If
367.Fa num_selections
368is not the same
369as
370.Fa numdevs
371or if
372.Fa select_generation
373is not the same as
374.Fa current_generation ,
375.Fn devstat_selectdevs
376will resize the selection list as necessary, and re-initialize the
377selection array.
378.Pp
379The
380.Fn devstat_buildmatch
381function
382takes a comma separated match string and compiles it into a
383.Vt devstat_match
384structure that is understood by
385.Fn devstat_selectdevs .
386Match strings have the following format:
387.Pp
388.D1 Ar device , Ns Ar type , Ns Ar if
389.Pp
390The
391.Fn devstat_buildmatch
392function
393takes care of allocating and reallocating the match list as necessary.
394Currently known match types include:
395.Bl -tag -width indent
396.It device type:
397.Bl -tag -width ".Li enclosure" -compact
398.It Li da
399Direct Access devices
400.It Li sa
401Sequential Access devices
402.It Li printer
403Printers
404.It Li proc
405Processor devices
406.It Li worm
407Write Once Read Multiple devices
408.It Li cd
409CD devices
410.It Li scanner
411Scanner devices
412.It Li optical
413Optical Memory devices
414.It Li changer
415Medium Changer devices
416.It Li comm
417Communication devices
418.It Li array
419Storage Array devices
420.It Li enclosure
421Enclosure Services devices
422.It Li floppy
423Floppy devices
424.El
425.It interface:
426.Bl -tag -width ".Li enclosure" -compact
427.It Li IDE
428Integrated Drive Electronics devices
429.It Li SCSI
430Small Computer System Interface devices
431.It Li NVME
432NVM Express 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 Mt 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