devstat(9)
NAME
- devstat, devstat_add_entry, devstat_end_transaction, devstat_end_transaction_bio, devstat_remove_entry, devstat_start_transaction - kernel interface for keeping de
- vice statistics
SYNOPSIS
#include <sys/devicestat.h> void devstat_add_entry(struct devstat *ds, const char *dev_name, int unit_number, u_int32_t block_size, devstat_support_flags flags, devstat_type_flags device_type, devstat_priority priority); void devstat_remove_entry(struct devstat *ds); void devstat_start_transaction(struct devstat *ds); void devstat_end_transaction(struct devstat *ds, u_int32_t bytes, devstat_tag_type tag_type, devstat_trans_flags flags); void devstat_end_transaction_bio(struct devstat *ds, struct bio *bp);
DESCRIPTION
- The devstat subsystem is an interface for recording device
- statistics, as
its name implies. The idea is to keep reasonably detailed - statistics
while utilizing a minimum amount of CPU time to record them. - Thus, no
statistical calculations are actually performed in the ker - nel portion of
the devstat code. Instead, that is left for user programs - to handle.
- devstat_add_entry() registers a device with the devstat sub
- system. The
caller is expected to have already allocated and zeroed the - devstat
structure before calling this function. devstat_add_entry() - takes several arguments:
- ds The devstat structure, allocated and zeroed by
- the client.
- dev_name The device name, e.g. da, cd, sa.
- unit_number Device unit number.
- block_size Block size of the device, if supported. If the
- device does
- not support a block size, or if the blocksize
- is unknown at
the time the device is added to the devstat - list, it should
be set to 0. - flags Flags indicating operations supported or not
- supported by
- the device. See below for details.
- device_type The device type. This is broken into three
- sections: base
- device type (e.g. direct access, CDROM, sequen
- tial access),
interface type (IDE, SCSI or other) and a pass - through flag
to indicate pas-through devices. See below for - a complete
list of types. - priority The device priority. The priority is used to
- determine how
- devices are sorted within devstat's list of de
- vices.
Devices are sorted first by priority (highest - to lowest),
and then by attach order. See below for a com - plete list of
available priorities. - devstat_remove_entry() removes a device from the devstat
- subsystem. It
takes the devstat structure for the device in question as an - argument.
The devstat generation number is incremented and the number - of devices is
decremented. - devstat_start_transaction() registers the start of a trans
- action with the
devstat subsystem. The busy count is incremented with each - transaction
start. When a device goes from idle to busy, the system up - time is
recorded in the start_time field of the devstat structure. - devstat_end_transaction() registers the end of a transaction
- with the
devstat subsystem. It takes four arguments: - ds The devstat structure for the device in question.
- bytes The number of bytes transferred in this transac
- tion.
- tag_type Transaction tag type. See below for tag types.
- flags Transaction flags indicating whether the transac
- tion was a
- read, write, or whether no data was transferred.
- devstat_end_transaction_bio() is a wrapper for
- devstat_end_transaction()
which pulls all the information from a struct bio which is - ready for
biodone(). - The devstat structure is composed of the following fields:
- dev_links Each devstat structure is placed in a
- linked list when
- it is registered. The dev_links field
- contains a
pointer to the next entry in the list of - devstat
structures. - device_number The device number is a unique identifier
- for each
- device. The device number is incremented
- for each new
device that is registered. The device - number is currently only a 32-bit integer, but it
- could be enlarged
if someone has a system with more than - four billion
device arrival events. - device_name The device name is a text string given by
- the regis
- tering driver to identify itself. (e.g.
- ``da'',
``cd'', ``sa'', etc.) - unit_number The unit number identifies the particular
- instance of
- the peripheral driver in question.
- bytes_written This is the number of bytes that have
- been written to
- the device. This number is currently an
- unsigned 64
bit integer. This will hopefully elimi - nate the
counter wrap that would come very quickly - on some systems if 32 bit integers were used.
- bytes_read This is the number of bytes that have
- been read from
- the device.
- bytes_freed This is the number of bytes that have
- been
- freed/erased on the device.
- num_reads This is the number of reads from the de
- vice.
- num_writes This is the number of writes to the de
- vice.
- num_frees This is the number of free/erase opera
- tions on the
- device.
- num_other This is the number of transactions to the
- device which
- are neither reads or writes. For in
- stance, SCSI
drivers often send a test unit ready com - mand to SCSI
devices. The test unit ready command - does not read or
write any data. It merely causes the de - vice to return
its status. - busy_count This is the current number of outstanding
- transactions
- for the device. This should never go be
- low zero, and
on an idle device it should be zero. If - either one of
these conditions is not true, it indi - cates a problem
in the way devstat_start_transaction() - and
devstat_end_transaction() are being - called in client
code. There should be one and only one - transaction
start event and one transaction end event - for each
transaction. - block_size This is the block size of the device, if
- the device
- has a block size.
- tag_types This is an array of counters to record
- the number of
- various tag types that are sent to a de
- vice. See
below for a list of tag types. - dev_creation_time This is the time, as reported by
- getmicrotime() that
- the device was registered.
- busy_time This is the amount of time that the de
- vice busy count
- has been greater than zero. This is only
- updated when
the busy count returns to zero. - start_time This is the time, as reported by
- getmicrouptime() that
- the device busy count went from zero to
- one.
- last_comp_time This is the time as reported by
- getmicrouptime() that
- a transaction last completed. It is used
- along with
start_time to calculate the device busy - time.
- flags These flags indicate which statistics
- measurements are
- supported by a particular device. These
- flags are
primarily intended to serve as an aid to - userland programs that decipher the statistics.
- device_type This is the device type. It consists of
- three parts:
- the device type (e.g. direct access,
- CDROM, sequential
access, etc.), the interface (IDE, SCSI - or other) and
whether or not the device in question is - a passthrough driver. See below for a complete
- list of
device types. - priority This is the priority. This is the first
- parameter
- used to determine where to insert a de
- vice in the
devstat list. The second parameter is - attach order.
See below for a list of available priori - ties.
- Each device is given a device type. Pass-through devices
- have the same
underlying device type and interface as the device they pro - vide an interface for, but they also have the pass-through flag set. The
- base device
types are identical to the SCSI device type numbers, so with - SCSI peripherals, the device type returned from an inquiry is usually
- ORed with the
SCSI interface type and the pass-through flag if appropri - ate. The device
type flags are as follows:
typedef enum {DEVSTAT_TYPE_DIRECT = 0x000,
DEVSTAT_TYPE_SEQUENTIAL = 0x001,
DEVSTAT_TYPE_PRINTER = 0x002,
DEVSTAT_TYPE_PROCESSOR = 0x003,
DEVSTAT_TYPE_WORM = 0x004,
DEVSTAT_TYPE_CDROM = 0x005,
DEVSTAT_TYPE_SCANNER = 0x006,
DEVSTAT_TYPE_OPTICAL = 0x007,
DEVSTAT_TYPE_CHANGER = 0x008,
DEVSTAT_TYPE_COMM = 0x009,
DEVSTAT_TYPE_ASC0 = 0x00a,
DEVSTAT_TYPE_ASC1 = 0x00b,
DEVSTAT_TYPE_STORARRAY = 0x00c,
DEVSTAT_TYPE_ENCLOSURE = 0x00d,
DEVSTAT_TYPE_FLOPPY = 0x00e,
DEVSTAT_TYPE_MASK = 0x00f,
DEVSTAT_TYPE_IF_SCSI = 0x010,
DEVSTAT_TYPE_IF_IDE = 0x020,
DEVSTAT_TYPE_IF_OTHER = 0x030,
DEVSTAT_TYPE_IF_MASK = 0x0f0,
DEVSTAT_TYPE_PASS = 0x100- } devstat_type_flags;
- Devices have a priority associated with them, which controls
- roughly
where they are placed in the devstat list. The priorities - are as follows:
typedef enum {DEVSTAT_PRIORITY_MIN = 0x000,
DEVSTAT_PRIORITY_OTHER = 0x020,
DEVSTAT_PRIORITY_PASS = 0x030,
DEVSTAT_PRIORITY_FD = 0x040,
DEVSTAT_PRIORITY_WFD = 0x050,
DEVSTAT_PRIORITY_TAPE = 0x060,
DEVSTAT_PRIORITY_CD = 0x090,
DEVSTAT_PRIORITY_DISK = 0x110,
DEVSTAT_PRIORITY_ARRAY = 0x120,
DEVSTAT_PRIORITY_MAX = 0xfff- } devstat_priority;
- Each device has associated with it flags to indicate what
- operations are
supported or not supported. The devstat_support_flags val - ues are as follows:
- DEVSTAT_ALL_SUPPORTED Every statistic type is supported
- by the device.
- DEVSTAT_NO_BLOCKSIZE This device does not have a block
- size.
- DEVSTAT_NO_ORDERED_TAGS This device does not support or
- dered tags.
- DEVSTAT_BS_UNAVAILABLE This device supports a blocksize,
- but it is cur
- rently unavailable. This flag is
- most often
used with removable media drives. - Transactions to a device fall into one of three categories,
- which are
represented in the flags passed into - devstat_end_transaction(). The transaction types are as follows:
typedef enum {DEVSTAT_NO_DATA = 0x00,
DEVSTAT_READ = 0x01,
DEVSTAT_WRITE = 0x02,
DEVSTAT_FREE = 0x03- } devstat_trans_flags;
- There are four possible values for the tag_type argument to devstat_end_transaction():
- DEVSTAT_TAG_SIMPLE The transaction had a simple tag.
- DEVSTAT_TAG_HEAD The transaction had a head of queue
- tag.
- DEVSTAT_TAG_ORDERED The transaction had an ordered tag.
- DEVSTAT_TAG_NONE The device does not support tags.
- The tag type values correspond to the lower four bits of the
- SCSI tag
definitions. In CAM, for instance, the tag_action from the - CCB is ORed
with 0xf to determine the tag type to pass in to
devstat_end_transaction(). - There is a macro, DEVSTAT_VERSION that is defined in This is
- the current
version of the devstat subsystem, and it should be incre - mented each time
a change is made that would require recompilation of user - land programs
that access devstat statistics. Userland programs use this - version, via
the kern.devstat.version sysctl variable to determine - whether they are in
sync with the kernel devstat structures.
SEE ALSO
systat(1), devstat(3), iostat(8), rpc.rstatd(8), vmstat(8)
HISTORY
The devstat statistics system appeared in FreeBSD 3.0.
AUTHORS
Kenneth Merry <ken@FreeBSD.org>
BUGS
- There may be a need for spl() protection around some of the
- devstat list
manipulation code to insure, for example, that the list of - devices is not
changed while someone is fetching the kern.devstat.all - sysctl variable.
- It is impossible with the current devstat architecture to
- accurately measure time per transaction. The only feasible way to accu
- rately measure
time per transaction would be to record a timestamp for ev - ery transaction. This measurement is probably not worthwhile for most
- people as it
would adversely affect the performance of the system and - cost space to
store the timestamps for individual transactions. - BSD May 22, 1998