mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-05 13:18:20 +03:00
dmstats: add libdm-stats library and 'dmsetup stats' command
Add the libdm-stats module to libdm: this implements a simple interface for creating, managing and interrogating I/O statistics regions and areas on device-mapper devices. The library interface is documented in libdevmapper.h and provides a 'dm_stats' handle that is used to perform statistics operations and obtain data. Public methods are provided to create and destroy handles and to list, create, and destroy statistics regions as well as to obtain and parse counter data and calculate rate-based metrics. This commit also adds a 'dmsetup stats' (aka 'dmstats') command with 'clear', 'create', 'delete', 'list', 'print', and 'report' sub-commands. See the library documentation and the dmstats.8 manual page for detailed API and command descriptions.
This commit is contained in:
parent
f06d866110
commit
d62a8d2f15
14
WHATS_NEW_DM
14
WHATS_NEW_DM
@ -1,5 +1,19 @@
|
||||
Version 1.02.104 -
|
||||
=================================
|
||||
Add dmstats.8 man page
|
||||
Add report stats sub-command to provide repeating stats reports.
|
||||
Add clear, delete, list, and print stats sub-commands.
|
||||
Add --segments switch to create one region per device segment.
|
||||
Add create stats sub-command and --start, --length, --areas and --areasize.
|
||||
Recognize 'dmstats' as an alias for 'dmsetup stats' when run with this name.
|
||||
Add a 'stats' command to dmsetup to configure, manage and report stats data.
|
||||
Add --regionid, --allregions to specify a single stats region or all regions.
|
||||
Add --allprograms for stats commands that filter by program ID.
|
||||
Add --auxdata and --programid arguments to specify aux data and program ID.
|
||||
Add statistics fields to -o <field>
|
||||
Add libdm-stats library to allow management of device-mapper statistics.
|
||||
Add --nosuffix to suppress unit suffixes in report output.
|
||||
Add --units to control report field output units.
|
||||
Add support to redisplay column headings for repeating column reports.
|
||||
Fix report header and row resource leaks.
|
||||
Report timestamps of ioctls with dmsetup -vvv.
|
||||
|
@ -1,5 +1,73 @@
|
||||
dm_report_column_headings
|
||||
dm_size_to_string
|
||||
dm_stats_bind_devno
|
||||
dm_stats_bind_name
|
||||
dm_stats_bind_uuid
|
||||
dm_stats_buffer_destroy
|
||||
dm_stats_clear_region
|
||||
dm_stats_create
|
||||
dm_stats_create_region
|
||||
dm_stats_delete_region
|
||||
dm_stats_destroy
|
||||
dm_stats_get_area_start
|
||||
dm_stats_get_average_queue_size
|
||||
dm_stats_get_average_rd_wait_time
|
||||
dm_stats_get_average_request_size
|
||||
dm_stats_get_average_wait_time
|
||||
dm_stats_get_average_wr_wait_time
|
||||
dm_stats_get_current_area
|
||||
dm_stats_get_current_area_len
|
||||
dm_stats_get_current_area_start
|
||||
dm_stats_get_current_nr_areas
|
||||
dm_stats_get_current_region
|
||||
dm_stats_get_current_region_area_len
|
||||
dm_stats_get_current_region_aux_data
|
||||
dm_stats_get_current_region_len
|
||||
dm_stats_get_current_region_program_id
|
||||
dm_stats_get_current_region_start
|
||||
dm_stats_get_io_in_progress
|
||||
dm_stats_get_io_nsecs
|
||||
dm_stats_get_nr_areas
|
||||
dm_stats_get_nr_regions
|
||||
dm_stats_get_rd_merges_per_sec
|
||||
dm_stats_get_read_nsecs
|
||||
dm_stats_get_reads
|
||||
dm_stats_get_read_sectors
|
||||
dm_stats_get_read_sectors_per_sec
|
||||
dm_stats_get_reads_merged
|
||||
dm_stats_get_reads_per_sec
|
||||
dm_stats_get_region_area_len
|
||||
dm_stats_get_region_aux_data
|
||||
dm_stats_get_region_len
|
||||
dm_stats_get_region_nr_areas
|
||||
dm_stats_get_region_program_id
|
||||
dm_stats_get_region_start
|
||||
dm_stats_get_sampling_interval_ms
|
||||
dm_stats_get_sampling_interval_ns
|
||||
dm_stats_get_service_time
|
||||
dm_stats_get_throughput
|
||||
dm_stats_get_total_read_nsecs
|
||||
dm_stats_get_total_write_nsecs
|
||||
dm_stats_get_utilization
|
||||
dm_stats_get_weighted_io_nsecs
|
||||
dm_stats_get_write_nsecs
|
||||
dm_stats_get_writes
|
||||
dm_stats_get_write_sectors
|
||||
dm_stats_get_write_sectors_per_sec
|
||||
dm_stats_get_writes_merged
|
||||
dm_stats_get_writes_per_sec
|
||||
dm_stats_get_wr_merges_per_sec
|
||||
dm_stats_list
|
||||
dm_stats_populate
|
||||
dm_stats_print_region
|
||||
dm_stats_region_present
|
||||
dm_stats_set_program_id
|
||||
dm_stats_set_sampling_interval_ms
|
||||
dm_stats_set_sampling_interval_ns
|
||||
dm_stats_walk_end
|
||||
dm_stats_walk_next
|
||||
dm_stats_walk_next_region
|
||||
dm_stats_walk_start
|
||||
dm_task_get_ioctl_timestamp
|
||||
dm_task_set_record_timestamp
|
||||
dm_timestamp_alloc
|
||||
|
@ -26,6 +26,7 @@ SOURCES =\
|
||||
libdm-string.c \
|
||||
libdm-report.c \
|
||||
libdm-timestamp.c \
|
||||
libdm-stats.c \
|
||||
libdm-config.c \
|
||||
mm/dbg_malloc.c \
|
||||
mm/pool.c \
|
||||
|
@ -395,6 +395,502 @@ struct dm_status_thin {
|
||||
int dm_get_status_thin(struct dm_pool *mem, const char *params,
|
||||
struct dm_status_thin **status);
|
||||
|
||||
/*
|
||||
* device-mapper statistics support
|
||||
*/
|
||||
|
||||
/*
|
||||
* Statistics handle.
|
||||
*
|
||||
* Operations on dm_stats objects include managing statistics regions
|
||||
* and obtaining and manipulating current counter values from the
|
||||
* kernel. Methods are provided to return baisc count values and to
|
||||
* derive time-based metrics when a suitable interval estimate is
|
||||
* provided.
|
||||
*
|
||||
* Internally the dm_stats handle contains a pointer to a table of one
|
||||
* or more dm_stats_region objects representing the regions registered
|
||||
* with the dm_stats_create_region() method. These in turn point to a
|
||||
* table of one or more dm_stats_counters objects containing the
|
||||
* counter sets for each defined area within the region:
|
||||
*
|
||||
* dm_stats->dm_stats_region[nr_regions]->dm_stats_counters[nr_areas]
|
||||
*
|
||||
* This structure is private to the library and may change in future
|
||||
* versions: all users should make use of the public interface and treat
|
||||
* the dm_stats type as an opaque handle.
|
||||
*
|
||||
* Regions and counter sets are stored in order of increasing region_id.
|
||||
* Depending on region specifications and the sequence of create and
|
||||
* delete operations this may not correspond to increasing sector
|
||||
* number: users of the library should not assume that this is the case
|
||||
* unless region creation is deliberately managed to ensure this (by
|
||||
* always creating regions in strict order of ascending sector address).
|
||||
*
|
||||
* Regions may also overlap so the same sector range may be included in
|
||||
* more than one region or area: applications should be prepared to deal
|
||||
* with this or manage regions such that it does not occur.
|
||||
*/
|
||||
struct dm_stats;
|
||||
|
||||
/*
|
||||
* Allocate a dm_stats handle to use for subsequent device-mapper
|
||||
* statistics operations. A program_id may be specified and will be
|
||||
* used by default for subsequent operations on this handle.
|
||||
*
|
||||
* If program_id is NULL or the empty string a program_id will be
|
||||
* automatically set to the value contained in /proc/self/comm.
|
||||
*/
|
||||
struct dm_stats *dm_stats_create(const char *program_id);
|
||||
|
||||
/*
|
||||
* Bind a dm_stats handle to the specified device major and minor
|
||||
* values. Any previous binding is cleared and any preexisting counter
|
||||
* data contained in the handle is released.
|
||||
*/
|
||||
int dm_stats_bind_devno(struct dm_stats *dms, int major, int minor);
|
||||
|
||||
/*
|
||||
* Bind a dm_stats handle to the specified device name.
|
||||
* Any previous binding is cleared and any preexisting counter
|
||||
* data contained in the handle is released.
|
||||
*/
|
||||
int dm_stats_bind_name(struct dm_stats *dms, const char *name);
|
||||
|
||||
/*
|
||||
* Bind a dm_stats handle to the specified device UUID.
|
||||
* Any previous binding is cleared and any preexisting counter
|
||||
* data contained in the handle is released.
|
||||
*/
|
||||
int dm_stats_bind_uuid(struct dm_stats *dms, const char *uuid);
|
||||
|
||||
#define DM_STATS_ALL_PROGRAMS ""
|
||||
/*
|
||||
* Parse the response from a @stats_list message. dm_stats_list will
|
||||
* allocate the necessary dm_stats and dm_stats region structures from
|
||||
* the embedded dm_pool. No counter data will be obtained (the counters
|
||||
* members of dm_stats_region objects are set to NULL).
|
||||
*
|
||||
* A program_id may optionally be supplied; if the argument is non-NULL
|
||||
* only regions with a matching program_id value will be considered. If
|
||||
* the argument is NULL then the default program_id associated with the
|
||||
* dm_stats handle will be used. Passing the special value
|
||||
* DM_STATS_ALL_PROGRAMS will cause all regions to be queried
|
||||
* regardless of region program_id.
|
||||
*/
|
||||
int dm_stats_list(struct dm_stats *dms, const char *program_id);
|
||||
|
||||
#define DM_STATS_REGIONS_ALL UINT64_MAX
|
||||
/*
|
||||
* Populate a dm_stats object with statistics for one or more regions of
|
||||
* the specified device.
|
||||
*
|
||||
* A program_id may optionally be supplied; if the argument is non-NULL
|
||||
* only regions with a matching program_id value will be considered. If
|
||||
* the argument is NULL then the default program_id associated with the
|
||||
* dm_stats handle will be used. Passing the special value
|
||||
* DM_STATS_ALL_PROGRAMS will cause all regions to be queried
|
||||
* regardless of region program_id.
|
||||
*
|
||||
* Passing the special value DM_STATS_REGIONS_ALL as the region_id
|
||||
* argument will attempt to retrieve all regions selected by the
|
||||
* program_id argument.
|
||||
*
|
||||
* If region_id is used to request a single region_id to be populated
|
||||
* the program_id is ignored.
|
||||
*/
|
||||
int dm_stats_populate(struct dm_stats *dms, const char *program_id,
|
||||
uint64_t region_id);
|
||||
|
||||
/*
|
||||
* Create a new statistics region on the device bound to dms.
|
||||
*
|
||||
* start and len specify the region start and length in 512b sectors.
|
||||
* Passing zero for both start and len will create a region spanning
|
||||
* the entire device.
|
||||
*
|
||||
* Step determines how to subdivide the region into discrete counter
|
||||
* sets: a positive value specifies the size of areas into which the
|
||||
* region should be split while a negative value will split the region
|
||||
* into a number of areas equal to the absolute value of step:
|
||||
*
|
||||
* - a region with one area spanning the entire device:
|
||||
*
|
||||
* dm_stats_create_region(dms, 0, 0, -1, p, a);
|
||||
*
|
||||
* - a region with areas of 1MiB:
|
||||
*
|
||||
* dm_stats_create_region(dms, 0, 0, 1 << 11, p, a);
|
||||
*
|
||||
* - one 1MiB region starting at 1024 sectors with two areas:
|
||||
*
|
||||
* dm_stats_create_region(dms, 1024, 1 << 11, -2, p, a);
|
||||
*
|
||||
* program_id is an optional string argument that identifies the
|
||||
* program creating the region. If program_id is NULL or the empty
|
||||
* string the default program_id stored in the handle will be used.
|
||||
*
|
||||
* aux_data is an optional string argument passed to the kernel that is
|
||||
* stored with the statistics region. It is not currently accessed by
|
||||
* the library or kernel and may be used to store arbitrary user data.
|
||||
*
|
||||
* The region_id of the newly-created region is returned in *region_id
|
||||
* if it is non-NULL.
|
||||
*/
|
||||
int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
|
||||
uint64_t start, uint64_t len, int64_t step,
|
||||
const char *program_id, const char *aux_data);
|
||||
|
||||
/*
|
||||
* Delete the specified statistics region. This will also mark the
|
||||
* region as not-present and discard any existing statistics data.
|
||||
*/
|
||||
int dm_stats_delete_region(struct dm_stats *dms, uint64_t region_id);
|
||||
|
||||
/*
|
||||
* Clear the specified statistics region. This requests the kernel to
|
||||
* zero all counter values (except in-flight I/O). Note that this
|
||||
* operation is not atomic with respect to reads of the counters; any IO
|
||||
* events occurring between the last print operation and the clear will
|
||||
* be lost. This can be avoided by using the atomic print-and-clear
|
||||
* function of the dm_stats_print_region() call or by using the higher
|
||||
* level dm_stats_populate() interface.
|
||||
*/
|
||||
int dm_stats_clear_region(struct dm_stats *dms, uint64_t region_id);
|
||||
|
||||
/*
|
||||
* Print the current counter values for the specified statistics region
|
||||
* and return them as a string. The memory for the string buffer will
|
||||
* be allocated from the dm_stats handle's private pool and should be
|
||||
* returned by calling dm_stats_buffer_destroy() when no longer
|
||||
* required. The pointer will become invalid following any call that
|
||||
* clears or reinitializes the handle (destroy, list, populate, bind).
|
||||
*
|
||||
* This allows applications that wish to access the raw message response
|
||||
* to obtain it via a dm_stats handle; no parsing of the textual counter
|
||||
* data is carried out by this function.
|
||||
*
|
||||
* Most users are recommended to use the dm_stats_populate() call
|
||||
* instead since this will automatically parse the statistics data into
|
||||
* numeric form accessible via the dm_stats_get_*() counter access
|
||||
* methods.
|
||||
*
|
||||
* A subset of the data lines may be requested by setting the
|
||||
* start_line and num_lines parameters. If both are zero all data
|
||||
* lines are returned.
|
||||
*
|
||||
* If the clear parameter is non-zero the operation will also
|
||||
* atomically reset all counter values to zero (except in-flight IO).
|
||||
*/
|
||||
char *dm_stats_print_region(struct dm_stats *dms, uint64_t region_id,
|
||||
unsigned start_line, unsigned num_lines,
|
||||
unsigned clear);
|
||||
|
||||
/*
|
||||
* Destroy a statistics response buffer obtained from a call to
|
||||
* dm_stats_print_region().
|
||||
*/
|
||||
void dm_stats_buffer_destroy(struct dm_stats *dms, char *buffer);
|
||||
|
||||
/*
|
||||
* Determine the number of regions contained in a dm_stats handle
|
||||
* following a dm_stats_list() or dm_stats_populate() call.
|
||||
*
|
||||
* The value returned is the number of registered regions visible with the
|
||||
* progam_id value used for the list or populate operation and may not be
|
||||
* equal to the highest present region_id (either due to program_id
|
||||
* filtering or gaps in the sequence of region_id values).
|
||||
*
|
||||
* Always returns zero on an empty handle.
|
||||
*/
|
||||
uint64_t dm_stats_get_nr_regions(const struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Test whether region_id is present in this dm_stats handle.
|
||||
*/
|
||||
int dm_stats_region_present(const struct dm_stats *dms, uint64_t region_id);
|
||||
|
||||
/*
|
||||
* Returns the number of areas (counter sets) contained in the specified
|
||||
* region_id of the supplied dm_stats handle.
|
||||
*/
|
||||
uint64_t dm_stats_get_region_nr_areas(const struct dm_stats *dms,
|
||||
uint64_t region_id);
|
||||
|
||||
/*
|
||||
* Returns the total number of areas (counter sets) in all regions of the
|
||||
* given dm_stats object.
|
||||
*/
|
||||
uint64_t dm_stats_get_nr_areas(const struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Destroy a dm_stats object and all associated regions and counter
|
||||
* sets.
|
||||
*/
|
||||
void dm_stats_destroy(struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Counter sampling interval
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the sampling interval for counter data to the specified value in
|
||||
* either nanoseconds or milliseconds.
|
||||
*
|
||||
* The interval is used to calculate time-based metrics from the basic
|
||||
* counter data: an interval must be set before calling any of the
|
||||
* metric methods.
|
||||
*
|
||||
* For best accuracy the duration should be measured and updated at the
|
||||
* end of each interval.
|
||||
*
|
||||
* All values are stored internally with nanosecond precision and are
|
||||
* converted to or from ms when the millisecond interfaces are used.
|
||||
*/
|
||||
void dm_stats_set_sampling_interval_ns(struct dm_stats *dms,
|
||||
uint64_t interval_ns);
|
||||
|
||||
void dm_stats_set_sampling_interval_ms(struct dm_stats *dms,
|
||||
uint64_t interval_ms);
|
||||
|
||||
/*
|
||||
* Retrieve the configured sampling interval in either nanoseconds or
|
||||
* milliseconds.
|
||||
*/
|
||||
uint64_t dm_stats_get_sampling_interval_ns(const struct dm_stats *dms);
|
||||
uint64_t dm_stats_get_sampling_interval_ms(const struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Override program_id. This may be used to change the default
|
||||
* program_id value for an existing handle. If the allow_empty argument
|
||||
* is non-zero a NULL or empty program_id is permitted.
|
||||
*
|
||||
* Use with caution! Most users of the library should set a valid,
|
||||
* non-NULL program_id for every statistics region created. Failing to
|
||||
* do so may result in confusing state when multiple programs are
|
||||
* creating and managing statistics regions.
|
||||
*
|
||||
* All users of the library are encouraged to choose an unambiguous,
|
||||
* unique program_id: this could be based on PID (for programs that
|
||||
* create, report, and delete regions in a single process), session id,
|
||||
* executable name, or some other distinguishing string.
|
||||
*
|
||||
* Use of the empty string as a program_id does not simplify use of the
|
||||
* library or the command line tools and use of this value is strongly
|
||||
* discouraged.
|
||||
*/
|
||||
int dm_stats_set_program_id(struct dm_stats *dms, int allow_empty,
|
||||
const char *program_id);
|
||||
|
||||
/*
|
||||
* Region properties: size, length & area_len.
|
||||
*
|
||||
* Region start and length are returned in units of 512b as specified
|
||||
* at region creation time. The area_len value gives the size of areas
|
||||
* into which the region has been subdivided. For regions with a single
|
||||
* area spanning the range this value is equal to the region length.
|
||||
*
|
||||
* For regions created with a specified number of areas the value
|
||||
* represents the size of the areas into which the kernel divided the
|
||||
* region excluding any rounding of the last area size. The number of
|
||||
* areas may be obtained using the dm_stats_nr_areas_region() call.
|
||||
*
|
||||
* All values are returned in units of 512b sectors.
|
||||
*/
|
||||
uint64_t dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
|
||||
uint64_t region_id);
|
||||
uint64_t dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
|
||||
uint64_t region_id);
|
||||
uint64_t dm_stats_get_region_area_len(const struct dm_stats *dms,
|
||||
uint64_t *area_len, uint64_t region_id);
|
||||
|
||||
/*
|
||||
* Area properties: start and length.
|
||||
*
|
||||
* The area length is always equal to the area length of the region
|
||||
* that contains it and is obtained from dm_stats_get_region_area_len().
|
||||
*
|
||||
* The start offset of an area is a function of the area_id and the
|
||||
* containing region's start and area length.
|
||||
*
|
||||
* All values are returned in units of 512b sectors.
|
||||
*/
|
||||
uint64_t dm_stats_get_area_start(const struct dm_stats *dms, uint64_t *start,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
/*
|
||||
* Retrieve program_id and aux_data for a specific region. Only valid
|
||||
* following a call to dm_stats_list(). The returned pointer does not
|
||||
* need to be freed separately from the dm_stats handle but will become
|
||||
* invalid after a dm_stats_destroy(), dm_stats_list(),
|
||||
* dm_stats_populate(), or dm_stats_bind*() of the handle from which it
|
||||
* was obtained.
|
||||
*/
|
||||
const char *dm_stats_get_region_program_id(const struct dm_stats *dms,
|
||||
uint64_t region_id);
|
||||
|
||||
const char *dm_stats_get_region_aux_data(const struct dm_stats *dms,
|
||||
uint64_t region_id);
|
||||
|
||||
/*
|
||||
* Statistics cursor
|
||||
*
|
||||
* A dm_stats handle maintains an optional cursor into the statistics
|
||||
* regions and areas that it stores. Iterators are provided to visit
|
||||
* each region, or each area in a handle and accessor methods are
|
||||
* provided to obtain properties and values for the region or area
|
||||
* at the current cursor position.
|
||||
*
|
||||
* Using the cursor simplifies walking all regions or areas when the
|
||||
* region table is sparse (i.e. contains some present and some
|
||||
* non-present region_id values either due to program_id filtering
|
||||
* or the ordering of region creation and deletion).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialise the cursor of a dm_stats handle to address the first
|
||||
* present region. It is valid to attempt to walk a NULL stats handle
|
||||
* or a handle containing no present regions; in this case any call to
|
||||
* dm_stats_walk_next() becomes a no-op and all calls to
|
||||
* dm_stats_walk_end() return true.
|
||||
*/
|
||||
void dm_stats_walk_start(struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Advance the statistics cursor to the next area, or to the next
|
||||
* present region if at the end of the current region.
|
||||
*/
|
||||
void dm_stats_walk_next(struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Advance the statistics cursor to the next region.
|
||||
*/
|
||||
void dm_stats_walk_next_region(struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Test whether the end of a statistics walk has been reached.
|
||||
*/
|
||||
int dm_stats_walk_end(struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Stats iterators
|
||||
*
|
||||
* C 'for' and 'do'/'while' style iterators for dm_stats data.
|
||||
*
|
||||
* It is not safe to call any function that modifies the region table
|
||||
* within the loop body (i.e. dm_stats_list(), dm_stats_populate(),
|
||||
* dm_stats_init(), or dm_stats_destroy()).
|
||||
*
|
||||
* All counter and property (dm_stats_get_*) access methods, as well as
|
||||
* dm_stats_populate_region() can be safely called from loops.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Iterate over the regions table visiting each region.
|
||||
*
|
||||
* If the region table is empty or unpopulated the loop body will not be
|
||||
* executed.
|
||||
*/
|
||||
#define dm_stats_foreach_region(dms) \
|
||||
for (dm_stats_walk_start((dms)); \
|
||||
!dm_stats_walk_end((dms)); dm_stats_walk_next_region((dms)))
|
||||
|
||||
/*
|
||||
* Iterate over the regions table visiting each area.
|
||||
*
|
||||
* If the region table is empty or unpopulated the loop body will not
|
||||
* be executed.
|
||||
*/
|
||||
#define dm_stats_foreach_area(dms) \
|
||||
for (dm_stats_walk_start((dms)); \
|
||||
!dm_stats_walk_end((dms)); dm_stats_walk_next((dms)))
|
||||
|
||||
/*
|
||||
* Start a walk iterating over the regions contained in dm_stats handle
|
||||
* 'dms'.
|
||||
*
|
||||
* The body of the loop should call dm_stats_walk_next() or
|
||||
* dm_stats_walk_next_region() to advance to the next element.
|
||||
*
|
||||
* The loop body is executed at least once even if the stats handle is
|
||||
* empty.
|
||||
*/
|
||||
#define dm_stats_walk_do(dms) \
|
||||
dm_stats_walk_start((dms)); \
|
||||
do
|
||||
|
||||
/*
|
||||
* Start a 'while' style loop or end a 'do..while' loop iterating over the
|
||||
* regions contained in dm_stats handle 'dms'.
|
||||
*/
|
||||
#define dm_stats_walk_while(dms) \
|
||||
while(!dm_stats_walk_end((dms)))
|
||||
|
||||
/*
|
||||
* Cursor relative property methods
|
||||
*
|
||||
* Calls with the prefix dm_stats_get_current_* operate relative to the
|
||||
* current cursor location, returning properties for the current region
|
||||
* or area of the supplied dm_stats handle.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Returns the number of areas (counter sets) contained in the current
|
||||
* region of the supplied dm_stats handle.
|
||||
*/
|
||||
uint64_t dm_stats_get_current_nr_areas(const struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Retrieve the current values of the stats cursor.
|
||||
*/
|
||||
uint64_t dm_stats_get_current_region(const struct dm_stats *dms);
|
||||
uint64_t dm_stats_get_current_area(const struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Current region properties: size, length & area_len.
|
||||
*
|
||||
* See the comments for the equivalent dm_stats_get_* versions for a
|
||||
* complete description of these methods.
|
||||
*
|
||||
* All values are returned in units of 512b sectors.
|
||||
*/
|
||||
uint64_t dm_stats_get_current_region_start(const struct dm_stats *dms,
|
||||
uint64_t *start);
|
||||
|
||||
uint64_t dm_stats_get_current_region_len(const struct dm_stats *dms,
|
||||
uint64_t *len);
|
||||
|
||||
uint64_t dm_stats_get_current_region_area_len(const struct dm_stats *dms,
|
||||
uint64_t *area_len);
|
||||
|
||||
/*
|
||||
* Current area properties: start and length.
|
||||
*
|
||||
* See the comments for the equivalent dm_stats_get_* versions for a
|
||||
* complete description of these methods.
|
||||
*
|
||||
* All values are returned in units of 512b sectors.
|
||||
*/
|
||||
uint64_t dm_stats_get_current_area_start(const struct dm_stats *dms,
|
||||
uint64_t *start);
|
||||
|
||||
uint64_t dm_stats_get_current_area_len(const struct dm_stats *dms,
|
||||
uint64_t *start);
|
||||
|
||||
/*
|
||||
* Return a pointer to the program_id string for region at the current
|
||||
* cursor location.
|
||||
*/
|
||||
const char *dm_stats_get_current_region_program_id(const struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Return a pointer to the aux_data string for the region at the current
|
||||
* cursor location.
|
||||
*/
|
||||
const char *dm_stats_get_current_region_aux_data(const struct dm_stats *dms);
|
||||
|
||||
/*
|
||||
* Call this to actually run the ioctl.
|
||||
*/
|
||||
@ -1941,6 +2437,153 @@ int dm_report_field_percent(struct dm_report *rh, struct dm_report_field *field,
|
||||
void dm_report_field_set_value(struct dm_report_field *field, const void *value,
|
||||
const void *sortvalue);
|
||||
|
||||
/*
|
||||
* Stats counter access methods
|
||||
*
|
||||
* Each method returns the corresponding stats counter value from the
|
||||
* supplied dm_stats handle for the specified region_id and area_id.
|
||||
* If either region_id or area_id uses one of the special values
|
||||
* DM_STATS_REGION_CURRENT or DM_STATS_AREA_CURRENT then the region
|
||||
* or area is selected according to the current state of the dm_stats
|
||||
* handle's embedded cursor.
|
||||
*
|
||||
* See the kernel documentation for complete descriptions of each
|
||||
* counter field:
|
||||
*
|
||||
* Documentation/device-mapper/statistics.txt
|
||||
* Documentation/iostats.txt
|
||||
*
|
||||
* reads: the number of reads completed
|
||||
* reads_merged: the number of reads merged
|
||||
* read_sectors: the number of sectors read
|
||||
* read_nsecs: the number of nanoseconds spent reading
|
||||
* writes: the number of writes completed
|
||||
* writes_merged: the number of writes merged
|
||||
* write_sectors: the number of sectors written
|
||||
* write_nsecs: the number of nanoseconds spent writing
|
||||
* io_in_progress: the number of I/Os currently in progress
|
||||
* io_nsecs: the number of nanoseconds spent doing I/Os
|
||||
* weighted_io_nsecs: the weighted number of nanoseconds spent doing I/Os
|
||||
* total_read_nsecs: the total time spent reading in nanoseconds
|
||||
* total_write_nsecs: the total time spent writing in nanoseconds
|
||||
*/
|
||||
|
||||
#define DM_STATS_REGION_CURRENT UINT64_MAX
|
||||
#define DM_STATS_AREA_CURRENT UINT64_MAX
|
||||
|
||||
uint64_t dm_stats_get_reads(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_reads_merged(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_read_sectors(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_read_nsecs(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_writes(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_writes_merged(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_write_sectors(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_write_nsecs(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_io_in_progress(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_io_nsecs(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_weighted_io_nsecs(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_total_read_nsecs(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
uint64_t dm_stats_get_total_write_nsecs(const struct dm_stats *dms,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
/*
|
||||
* Derived statistics access methods
|
||||
*
|
||||
* Each method returns the corresponding value calculated from the
|
||||
* counters stored in the supplied dm_stats handle for the specified
|
||||
* region_id and area_id. If either region_id or area_id uses one of the
|
||||
* special values DM_STATS_REGION_CURRENT or DM_STATS_AREA_CURRENT then
|
||||
* the region or area is selected according to the current state of the
|
||||
* dm_stats handle's embedded cursor.
|
||||
*
|
||||
* The set of metrics is based on the fields provided by the Linux
|
||||
* iostats program.
|
||||
*
|
||||
* rd_merges_per_sec: the number of reads merged per second
|
||||
* wr_merges_per_sec: the number of writes merged per second
|
||||
* reads_per_sec: the number of reads completed per second
|
||||
* writes_per_sec: the number of writes completed per second
|
||||
* read_sectors_per_sec: the number of sectors read per second
|
||||
* write_sectors_per_sec: the number of sectors written per second
|
||||
* average_request_size: the average size of requests submitted
|
||||
* service_time: the average service time (in ns) for requests issued
|
||||
* average_queue_size: the average queue length
|
||||
* average_wait_time: the average time for requests to be served (in ns)
|
||||
* average_rd_wait_time: the average read wait time
|
||||
* average_wr_wait_time: the average write wait time
|
||||
*/
|
||||
|
||||
int dm_stats_get_rd_merges_per_sec(const struct dm_stats *dms, double *rrqm,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
int dm_stats_get_wr_merges_per_sec(const struct dm_stats *dms, double *rrqm,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
int dm_stats_get_reads_per_sec(const struct dm_stats *dms, double *rd_s,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
int dm_stats_get_writes_per_sec(const struct dm_stats *dms, double *wr_s,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
int dm_stats_get_read_sectors_per_sec(const struct dm_stats *dms,
|
||||
double *rsec_s, uint64_t region_id,
|
||||
uint64_t area_id);
|
||||
|
||||
int dm_stats_get_write_sectors_per_sec(const struct dm_stats *dms,
|
||||
double *wr_s, uint64_t region_id,
|
||||
uint64_t area_id);
|
||||
|
||||
int dm_stats_get_average_request_size(const struct dm_stats *dms,
|
||||
double *arqsz, uint64_t region_id,
|
||||
uint64_t area_id);
|
||||
|
||||
int dm_stats_get_service_time(const struct dm_stats *dms, double *svctm,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
int dm_stats_get_average_queue_size(const struct dm_stats *dms, double *qusz,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
int dm_stats_get_average_wait_time(const struct dm_stats *dms, double *await,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
int dm_stats_get_average_rd_wait_time(const struct dm_stats *dms,
|
||||
double *await, uint64_t region_id,
|
||||
uint64_t area_id);
|
||||
|
||||
int dm_stats_get_average_wr_wait_time(const struct dm_stats *dms,
|
||||
double *await, uint64_t region_id,
|
||||
uint64_t area_id);
|
||||
|
||||
int dm_stats_get_throughput(const struct dm_stats *dms, double *tput,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
int dm_stats_get_utilization(const struct dm_stats *dms, dm_percent_t *util,
|
||||
uint64_t region_id, uint64_t area_id);
|
||||
|
||||
/*************************
|
||||
* config file parse/print
|
||||
*************************/
|
||||
|
1360
libdm/libdm-stats.c
Normal file
1360
libdm/libdm-stats.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -83,7 +83,7 @@ ifneq ("@THIN@", "none")
|
||||
MAN7+=lvmthin.7
|
||||
endif
|
||||
|
||||
MAN8DM=dmsetup.8 $(DMEVENTDMAN) $(BLKDEACTIVATEMAN)
|
||||
MAN8DM=dmsetup.8 dmstats.8 $(DMEVENTDMAN) $(BLKDEACTIVATEMAN)
|
||||
MAN5DIR=$(mandir)/man5
|
||||
MAN7DIR=$(mandir)/man7
|
||||
MAN8DIR=$(mandir)/man8
|
||||
|
693
man/dmstats.8.in
Normal file
693
man/dmstats.8.in
Normal file
@ -0,0 +1,693 @@
|
||||
.TH DMSTATS 8 "Jul 25 2015" "Linux" "MAINTENANCE COMMANDS"
|
||||
.SH NAME
|
||||
dmstats \(em device-mapper statistics management
|
||||
.SH SYNOPSIS
|
||||
.ad l
|
||||
.B dmsetup stats
|
||||
.I command
|
||||
.RB [ options ]
|
||||
.br
|
||||
|
||||
.B dmstats <command>
|
||||
.RB [[
|
||||
.IR device_name ]
|
||||
.RB |[ \-\-uuid
|
||||
.IR uuid ]
|
||||
.RB |[ \-\-major
|
||||
.IR major
|
||||
.RB \-\-minor
|
||||
.IR minor ]]
|
||||
.br
|
||||
|
||||
.B dmstats clear
|
||||
.I device_name
|
||||
.RB [ \-\-allregions
|
||||
.RB | \-\-regionid
|
||||
.IR id ]
|
||||
.br
|
||||
.B dmstats create
|
||||
.I device_name
|
||||
.RB [[ \-\-areas
|
||||
.IR nr_areas ]
|
||||
.RB |[ \-\-areasize
|
||||
.IR area_size ]]
|
||||
.RB [[ \-\-start
|
||||
.IR start_sector ]
|
||||
.RB [ \-\-length
|
||||
.IR length ]
|
||||
.RB |[ \-\-segments ]]
|
||||
.RB [ \-\-auxdata
|
||||
.IR data ]
|
||||
.RB [ \-\-programid
|
||||
.IR id ]
|
||||
.br
|
||||
.B dmstats delete
|
||||
.I device_name
|
||||
.RB [ \-\-force ]
|
||||
.RB [ \-\-allregions
|
||||
.RB | \-\-regionid
|
||||
.IR id ]
|
||||
.RB [ \-\-allprograms
|
||||
.RB | \-\-programid
|
||||
.IR id ]
|
||||
.br
|
||||
.B dmstats help
|
||||
.RB [ \-c | \-C | \-\-columns ]
|
||||
.br
|
||||
.B dmstats list
|
||||
.RI [ device_name ]
|
||||
.RB [ \-\-allprograms
|
||||
.RB | \-\-programid
|
||||
.IR id ]
|
||||
.RB [ \-\-units
|
||||
.IR units ]
|
||||
.RB [ \-\-nosuffix ]
|
||||
.br
|
||||
.B dmstats print
|
||||
.RI [ device_name ]
|
||||
.RB [ \-\-clear ]
|
||||
.RB [ \-\-allprograms
|
||||
.RB | \-\-programid
|
||||
.IR id ]
|
||||
.RB [ \-\-allregions
|
||||
.RB | \-\-regionid
|
||||
.IR id ]
|
||||
.br
|
||||
.B dmstats report
|
||||
.RI [ device_name ]
|
||||
.RB [ \-\-interval
|
||||
.IR seconds ]
|
||||
.RB [ \-\-count
|
||||
.IR count ]
|
||||
.RB [ \-\-units
|
||||
.IR units ]
|
||||
.RB [ \-\-allprograms ]
|
||||
.RB [ \-\-programid
|
||||
.IR id ]
|
||||
.RB [ \-\-regionid
|
||||
.IR id ]
|
||||
.RB [ \-O | \-\-sort
|
||||
.IR sort_fields ]
|
||||
.RB [ \-S | \-\-select
|
||||
.IR Selection ]
|
||||
.RB [ \-\-units
|
||||
.IR units ]
|
||||
.RB [ \-\-nosuffix ]
|
||||
.br
|
||||
.ad b
|
||||
.SH DESCRIPTION
|
||||
The dmstats program manages IO statistics regions for devices that use
|
||||
the device-mapper driver. Statistics regions may be created, deleted,
|
||||
listed and reported on using the tool.
|
||||
|
||||
The first argument to dmstats is a command.
|
||||
|
||||
The second argument is the device name, uuid, or major and minor
|
||||
numbers.
|
||||
|
||||
Further options permit the selection of regions, output format
|
||||
control, and reporting behaviour.
|
||||
|
||||
When the program is run using the 'dmstats' alias, the command
|
||||
\fBmust\fP be the first argument and any switches and options should be
|
||||
specified following the command itself. This limitation is not present
|
||||
when run as 'dmsetup stats'.
|
||||
|
||||
When no device argument is given dmstats will by default operate on all
|
||||
device-mapper devices present. The \fBcreate\fP and \fBdelete\fP
|
||||
commands require the use of \fB--force\fP when used in this way.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-\-allprograms
|
||||
Include regions from all program IDs for list and report operations.
|
||||
.TP
|
||||
.B \-\-allregions
|
||||
Include all present regions for commands that normally accept a single
|
||||
region identifier.
|
||||
.TP
|
||||
.B \-\-areas \fInr_areas
|
||||
Specify the number of statistics areas to create within a new region.
|
||||
.TP
|
||||
.B \-\-areasize \fIarea_size
|
||||
Specify the size of areas into which a new region should be divided. An
|
||||
optional suffix selects units of bBsSkKmMgGtTpPeE: (b)ytes,
|
||||
(s)ectors, (k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes,
|
||||
(p)etabytes, (e)xabytes. Capitalise to use multiples of 1000 (S.I.)
|
||||
instead of 1024.
|
||||
.TP
|
||||
.B \-\-auxdata \fIaux_data
|
||||
Specify auxilliary data (a string) to be stored with a new region.
|
||||
.TP
|
||||
.B \-\-clear
|
||||
When printing statistics counters, also atomically reset them to zero.
|
||||
.TP
|
||||
.B \-\-count \fIcount
|
||||
Specify the iteration count for repeating reports. If the count
|
||||
argument is zero reports will continue to repeat until interrupted.
|
||||
.TP
|
||||
.B \-\-interval \fIseconds
|
||||
Specify the interval in seconds between successive iterations for
|
||||
repeating reports. If \-\-interval is specified but \-\-count is not,
|
||||
reports will continue to repeat until interrupted.
|
||||
.TP
|
||||
.B \-\-length \fIlength
|
||||
Specify the length of a new statistics region in sectors. An optional
|
||||
suffix selects units of bBsSkKmMgGtTpPeE: (b)ytes, (s)ectors,
|
||||
(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes, (p)etabytes,
|
||||
(e)xabytes. Capitalise to use multiples of 1000 (S.I.) instead of 1024.
|
||||
.TP
|
||||
.BR \-j | \-\-major\ \fImajor
|
||||
Specify the major number.
|
||||
.TP
|
||||
.BR \-m | \-\-minor\ \fIminor
|
||||
Specify the minor number.
|
||||
.TP
|
||||
.B \-\-nosuffix
|
||||
Suppress the suffix on output sizes. Use with \fB\-\-units\fP
|
||||
(except h and H) if processing the output.
|
||||
.TP
|
||||
.BR \-o | \-\-options
|
||||
Specify which report fields to display.
|
||||
.TP
|
||||
.BR \-O | \-\-sort\ \fIsort_fields
|
||||
Sort output according to the list of fields given. Precede any
|
||||
sort_field with - for a reverse sort on that column.
|
||||
.TP
|
||||
.B \-\-programid \fIid
|
||||
Specify a program ID string. When creating new statistics regions this
|
||||
string is stored with the region. Subsequent operations may supply a
|
||||
program ID in order to select only regions with a matching value. The
|
||||
default program ID for dmstats-managed regions is "dmstats".
|
||||
.TP
|
||||
.BR \-S | \-\-select \ \fIselection
|
||||
Display only rows that match selection criteria. All rows with the
|
||||
additional "selected" column (-o selected) showing 1 if the row matches
|
||||
the selection and 0 otherwise. The selection criteria are defined by
|
||||
specifying column names and their valid values while making use of
|
||||
supported comparison operators.
|
||||
.TP
|
||||
.B \-\-start \fIstart
|
||||
Specify the start offset of a new statistics region in sectors. An
|
||||
optional suffix selects units of bBsSkKmMgGtTpPeE: (b)ytes,
|
||||
(s)ectors, (k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes,
|
||||
(p)etabytes, (e)xabytes. Capitalise to use multiples of 1000 (S.I.)
|
||||
instead of 1024.
|
||||
.TP
|
||||
.B \-\-segments
|
||||
Create a new statistics region for each target contained in the target
|
||||
device. This causes a separate region to be allocated for each segment
|
||||
of the device.
|
||||
.TP
|
||||
.BR \-\-units \ hHbBsSkKmMgGtTpPeE
|
||||
Set the display units for report output. All sizes are output in these
|
||||
units: (h)uman-readable, (b)ytes, (s)ectors, (k)ilobytes, (m)egabytes,
|
||||
(g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes. Capitalise to use
|
||||
multiples of 1000 (S.I.) instead of 1024. Can also specify custom units
|
||||
e.g. \fB\-\-units 3M\fP
|
||||
.TP
|
||||
.BR \-u | \-\-uuid
|
||||
Specify the uuid.
|
||||
.TP
|
||||
.BR \-v | \-\-verbose \ [ \-v | \-\-verbose ]
|
||||
Produce additional output.
|
||||
.br
|
||||
.SH COMMANDS
|
||||
.TP
|
||||
.B clear
|
||||
.I device_name
|
||||
.RB [ \-\-allregions
|
||||
.RB | \-\-regionid
|
||||
.IR id ]
|
||||
.RB [ \-\-allprograms
|
||||
.RB | \-\-programid
|
||||
.IR id ]
|
||||
.br
|
||||
Instructs the kernel to clear statistics counters for the speficied
|
||||
regions (with the exception of in-flight IO counters).
|
||||
.br
|
||||
.TP
|
||||
.B create
|
||||
.I device_name
|
||||
.RB [ \-\-areas
|
||||
.IR nr_areas ]
|
||||
.RB [ \-\-areasize
|
||||
.IR area_size ]
|
||||
.RB [[ \-\-start
|
||||
.IR start_sector ]
|
||||
.RB [ \-\-length
|
||||
.IR length ]
|
||||
.RB |[ \-\-segments ]]
|
||||
.RB [ \-\-auxdata
|
||||
.IR data ]
|
||||
.RB [ \-\-programid
|
||||
.IR id ]
|
||||
.br
|
||||
Creates one or more new statistics regions on the specified device(s).
|
||||
|
||||
The region will span the entire device unless \fB\-\-start\fP and
|
||||
\fB\-\-length\fP or \fB\-\-target\fP are given. The \fB\-\-start\fP and
|
||||
\fB\-\-length\fP options allow a region of arbitrary length to be placed
|
||||
at an arbitrary offset into the device. The \fB\-\-segments\fP option
|
||||
causes a new region to be created for each target in the corresponding
|
||||
device-mapper device's table.
|
||||
|
||||
An optional \fBprogram_id\fP or \fBaux_data\fP string may be associated
|
||||
with the region. A \fBprogram_id\fP may then be used to select regions
|
||||
for subsequent list, print, and report operations. The \fBaux_data\fP
|
||||
stores an arbitrary string and is not used by dmstats or the
|
||||
device-mapper kernel statistics subsystem.
|
||||
|
||||
By default dmstats creates regions with a \fBprogram_id\fP of
|
||||
"DMSTATS1".
|
||||
|
||||
On success the \fBregion_id\fP of the newly created region is printed to
|
||||
stdout.
|
||||
.br
|
||||
.TP
|
||||
.B delete
|
||||
.I [ device_name ]
|
||||
.RB [ \-\-force ]
|
||||
.RB [ \-\-allregions
|
||||
.RB | \-\-regionid
|
||||
.IR id ]
|
||||
.RB [ \-\-allprograms
|
||||
.RB | \-\-programid
|
||||
.IR id ]
|
||||
.br
|
||||
Delete the specified statistics region. All counters and resources used
|
||||
by the region are released and the region will not appear in the output
|
||||
of subsequent list, print, or report operations.
|
||||
|
||||
All regions registered on a device may be removed using
|
||||
\fB\-\-allregions\fP.
|
||||
|
||||
To remove all regions on all devices \fB\-\-force\fP must be used.
|
||||
.br
|
||||
.TP
|
||||
.B help
|
||||
.RB [ \-c | \-C | \-\-columns ]
|
||||
.br
|
||||
Outputs a summary of the commands available, optionally including
|
||||
the list of report fields.
|
||||
.br
|
||||
.TP
|
||||
.B list
|
||||
.RI [ device_name ]
|
||||
.RB [ \-\-allprograms ]
|
||||
.RB [ \-\-programid
|
||||
.IR id ]
|
||||
.br
|
||||
List the statistics regions registered on the device. If the
|
||||
\fB\-\-allprograms\fP switch is given all regions will be listed
|
||||
regardless of region program ID values.
|
||||
.br
|
||||
.TP
|
||||
.B print
|
||||
.RB [ \-\-clear ]
|
||||
.IR
|
||||
.RB [ \-\-allregions
|
||||
.RB | \-\-regionid
|
||||
.IR id ]
|
||||
.RB [ \-\-allprograms
|
||||
.RB | \-\-programid
|
||||
.IR id ]
|
||||
.br
|
||||
Print raw statistics counters for the specified region or for all
|
||||
present regions.
|
||||
.br
|
||||
.TP
|
||||
.B report
|
||||
.RB [ \-\-allprograms ]
|
||||
.RB [ \-\-interval
|
||||
.IR seconds ]
|
||||
.RB [ \-\-count
|
||||
.IR count ]
|
||||
.RB [ \-\-units
|
||||
.IR unit ]
|
||||
.RB [ \-\-regionid
|
||||
.IR id ]
|
||||
.RB [ \-\-programid
|
||||
.IR id ]
|
||||
.RB [ \-O | \-\-sort
|
||||
.IR sort_fields ]
|
||||
.RB [ \-S | \-\-select
|
||||
.IR Selection ]
|
||||
.RB [ \-\-units
|
||||
.IR units ]
|
||||
.br
|
||||
Start a report for the specified region or for all present regions. If
|
||||
the count argument is specified, the report will repeat at a fixed
|
||||
interval set by the \fB\-\-interval\fP option. The default interval is
|
||||
one second.
|
||||
|
||||
If the \fB\-\-allprograms\fP switch is given, all regions will be
|
||||
listed, regardless of region program ID values.
|
||||
.br
|
||||
.SH REGIONS AND AREAS
|
||||
The device-mapper statistics facility allows separate performance
|
||||
counters to be maintained for arbitrary regions of devices. A region may
|
||||
span any range: from a single sector to the whole device. A region may
|
||||
be further sub-divided into a number of distinct areas (one or more),
|
||||
each with its own counter set.
|
||||
|
||||
By default new regions span the entire device. The \fB\-\-start\fP and
|
||||
\fB\-\-length\fP options allows a region of any size to be placed at any
|
||||
location on the device.
|
||||
|
||||
A region may be either divided into the specified number of equal-sized
|
||||
areas, or into areas of the given size by specifying one of
|
||||
\fB\-\-areas\fP or \fB\-\-areasize\fP when creating a region with the
|
||||
\fBcreate\fP command. Depending on the size of the areas and the device
|
||||
region the final area within the region may be smaller than requested.
|
||||
|
||||
.SS Region identifiers
|
||||
Each region is assigned an identifier when it is created that is used to
|
||||
reference the region in subsequent operations. Region identifiers are
|
||||
unique within a given device (including across different \fBprogram_id\fP
|
||||
values).
|
||||
.br
|
||||
Depending on the sequence of create and delete operations, gaps may
|
||||
exist in the sequence of \fBregion_id\fP values for a particular device.
|
||||
|
||||
.SH REPORT FIELDS
|
||||
The dmstats report provides several types of field that may be added to
|
||||
the default field set, or used to create custom reports.
|
||||
.br
|
||||
All performance counters and metrics are calculated per-area.
|
||||
.br
|
||||
.SS Derived metrics
|
||||
A number of metrics fields are included that provide high level
|
||||
performance indicators. These are based on the fields provided by the
|
||||
conventional Linux iostat program and are derived from the basic counter
|
||||
values provided by the kernel for each area.
|
||||
.br
|
||||
.HP
|
||||
.B rrqm
|
||||
.br
|
||||
Read requests merged per second.
|
||||
.HP
|
||||
.B wrqm
|
||||
.br
|
||||
Write requests merged per second.
|
||||
.HP
|
||||
.B rs
|
||||
.br
|
||||
Read requests per second.
|
||||
.HP
|
||||
.B ws
|
||||
.br
|
||||
Write requests per second.
|
||||
.HP
|
||||
.B rsec
|
||||
.br
|
||||
Sectors read per second.
|
||||
.HP
|
||||
.B wsec
|
||||
.br
|
||||
Sectors written per second.
|
||||
.HP
|
||||
.B arqsz
|
||||
.br
|
||||
The average size of requests submitted to the area.
|
||||
.HP
|
||||
.B qusz
|
||||
.br
|
||||
The average queue length.
|
||||
.HP
|
||||
.B await
|
||||
.br
|
||||
The average wait time for read and write requests.
|
||||
.HP
|
||||
.B r_await
|
||||
.br
|
||||
The average wait time for read requests.
|
||||
.HP
|
||||
.B w_await
|
||||
.br
|
||||
The average wait time for write requests.
|
||||
.HP
|
||||
.B tput
|
||||
.br
|
||||
The device throughput in requests per second.
|
||||
.HP
|
||||
.B svctm
|
||||
.br
|
||||
The average service time (in milliseconds) for I/O requests that
|
||||
were issued to the device.
|
||||
.HP
|
||||
.B util
|
||||
.br
|
||||
Percentage of CPU time during which I/O requests were issued to the
|
||||
device (bandwidth utilization for the device). Device saturation occurs
|
||||
when this value is close to 100%.
|
||||
.br
|
||||
.SS Region and area meta fields
|
||||
Meta fields provide information about the region or area that the
|
||||
statistics values relate to. This includes the region and area
|
||||
identifier, start, length, and counts, as well as the program ID and
|
||||
auxiliary data values.
|
||||
.br
|
||||
.HP
|
||||
.B region_id
|
||||
.br
|
||||
Region identifier. This is a non-negative integer returned by the kernel
|
||||
when a statistics region is created.
|
||||
.HP
|
||||
.B region_start
|
||||
.br
|
||||
.br
|
||||
The region start sector in units of 512 byte sectors.
|
||||
.HP
|
||||
.B region_len
|
||||
.br
|
||||
The length of the region in units of 512 byte sectors.
|
||||
.HP
|
||||
.B area_id
|
||||
.br
|
||||
Area identifier. Area identifiers are assigned by the device-mapper
|
||||
statistics library and uniquely identify each area within a region. Each
|
||||
ID corresponds to a distinct set of performance counters for that area
|
||||
of the statistics region. Area identifiers are always monotonically
|
||||
increasing within a region so that higher ID values correspond to
|
||||
greater sector addresses within the region and no gaps in the sequence
|
||||
of identifiers exist. Sorting a report by device, region start, and area
|
||||
ID (the default) will then produce rows in order of ascending region and
|
||||
area address.
|
||||
.HP
|
||||
.B area_start
|
||||
.br
|
||||
The area start sector in units of 512 byte sectors.
|
||||
.HP
|
||||
.B area_len
|
||||
.br
|
||||
The length of the area in units of 512 byte sectors.
|
||||
.HP
|
||||
.B area_count
|
||||
.br
|
||||
The number of areas in this region.
|
||||
.HP
|
||||
.B program_id
|
||||
.br
|
||||
The program ID value associated with this region.
|
||||
.HP
|
||||
.B aux_data
|
||||
.br
|
||||
The auxiliary data value associated with this region.
|
||||
.br
|
||||
.SS Basic counters
|
||||
Basic counters provide access to the raw counter data from the kernel,
|
||||
allowing further processing to be carried out by another program.
|
||||
|
||||
The kernel provides thirteen separate counters for each statistics
|
||||
area. The first eleven of these match the counters provided in
|
||||
/proc/diskstats or /sys/block/*/*/stat. The final pair provide separate
|
||||
counters for read and write time.
|
||||
.P
|
||||
.HP
|
||||
.B reads
|
||||
.br
|
||||
The number of reads successfully completed this interval.
|
||||
.HP
|
||||
.B read_merges
|
||||
.br
|
||||
The number of read requests merged this interval. This field is
|
||||
incremented every time a pair of requests are merged to create a single
|
||||
request to be issued to the device.
|
||||
.HP
|
||||
.B read_sectors
|
||||
.br
|
||||
The number of 512 byte sectors read this interval.
|
||||
.HP
|
||||
.B read_nsecs
|
||||
.br
|
||||
The number of nanoseconds spent reading during this interval.
|
||||
.HP
|
||||
.B writes
|
||||
.br
|
||||
The number of writes successfully completed this interval.
|
||||
.HP
|
||||
.B write_merges
|
||||
.br
|
||||
The number of write requests merged this interval. This field is
|
||||
incremented every time a pair of requests are merged to create a single
|
||||
request to be issued to the device.
|
||||
.HP
|
||||
.B write_sectors
|
||||
.br
|
||||
The number of 512 byte sectors written this interval.
|
||||
.HP
|
||||
.B write_nsecs
|
||||
.br
|
||||
The number of nanoseconds spent writing during this interval.
|
||||
.HP
|
||||
.B in_progress
|
||||
.br
|
||||
The number of reads and writes currently in progress.
|
||||
.HP
|
||||
.B io_nsecs
|
||||
.br
|
||||
The number of nanoseconds spent reading and writing.
|
||||
.HP
|
||||
.B weighted_io_nsecs
|
||||
.br
|
||||
This field is incremented at each I/O start, I/O completion, I/O merge,
|
||||
or read of these stats by the number of I/Os in progress multiplied by
|
||||
the number of milliseconds spent doing I/O since the last update of this
|
||||
field. This can provide an easy measure of both I/O completion time and
|
||||
the backlog that may be accumulating.
|
||||
.br
|
||||
.br
|
||||
.P
|
||||
.SH EXAMPLES
|
||||
Create a whole-device region with one area on vg00/lvol1
|
||||
.br
|
||||
.br
|
||||
# dmstats create vg00/lvol1
|
||||
.br
|
||||
Created region: 0
|
||||
.br
|
||||
.br
|
||||
|
||||
|
||||
Create a 32M region 1G into device d0
|
||||
.br
|
||||
.br
|
||||
# dmstats create --start 1G --length 32M d0
|
||||
.br
|
||||
Created region: 2
|
||||
.br
|
||||
|
||||
|
||||
Create a whole-device region with 8 areas on every device
|
||||
.br
|
||||
.br
|
||||
# dmstats create --areas 8
|
||||
.br
|
||||
Created region: 0
|
||||
.br
|
||||
Created region: 0
|
||||
.br
|
||||
Created region: 0
|
||||
.br
|
||||
Created region: 2
|
||||
.br
|
||||
Created region: 0
|
||||
.br
|
||||
Created region: 0
|
||||
.br
|
||||
.br
|
||||
|
||||
Delete all regions on all devices
|
||||
.br
|
||||
.br
|
||||
# dmstats delete --allregions --force
|
||||
.br
|
||||
.br
|
||||
|
||||
Create a whole-device region with areas 10GiB in size on vg00/lvol1
|
||||
using dmsetup
|
||||
.br
|
||||
.br
|
||||
# dmsetup stats create --areasize 10G vg00/lvol1
|
||||
.br
|
||||
Created region: 1
|
||||
.br
|
||||
.br
|
||||
|
||||
Create a 1GiB region with 16 areas at the start of vg00/lvol1
|
||||
.br
|
||||
# dmstats create --start 0 --len 1G --areas=16 vg00/lvol1
|
||||
.br
|
||||
Created region: 2
|
||||
.br
|
||||
.br
|
||||
|
||||
List the statistics regions registered on vg00/lvol1
|
||||
.br
|
||||
# dmstats list vg00/lvol1
|
||||
.br
|
||||
RegionID RegStart RegLen AreaSize ProgramID AuxData
|
||||
.br
|
||||
0 0 104857600 20971520 dmstats
|
||||
.br
|
||||
1 0 104857600 20971520 dmstats
|
||||
.br
|
||||
2 0 2097152 131072 dmstats
|
||||
.br
|
||||
.br
|
||||
|
||||
Display five statistics reports for vg00/lvol1 at an interval of one second
|
||||
.br
|
||||
.br
|
||||
# dmstats report --interval 1 --count 5 vg00/lvol1
|
||||
.br
|
||||
Name RgID ArID RRqM/s WRqM/s R/s W/s RSz/s WSz/s AvRqSz QSize SvcTm Util% AWait
|
||||
.br
|
||||
vg00-lvol1 0 0 0.00 0.00 8.00 0.00 48.00k 0 6.00k 0.00 5.50 4.40 6.62
|
||||
.br
|
||||
vg00-lvol1 0 1 0.00 0.00 22.00 0.00 624.00k 0 28.00k 0.00 5.23 11.50 5.36
|
||||
.br
|
||||
vg00-lvol1 0 2 0.00 0.00 353.00 0.00 1.84m 0 5.00k 0.00 1.34 47.40 1.33
|
||||
.br
|
||||
vg00-lvol1 0 3 0.00 0.00 73.00 0.00 592.00k 0 8.00k 0.00 2.10 15.30 2.10
|
||||
.br
|
||||
vg00-lvol1 0 4 0.00 0.00 5.00 0.00 52.00k 0 10.00k 0.00 4.00 2.00 4.00
|
||||
.br
|
||||
[...]
|
||||
.br
|
||||
.br
|
||||
|
||||
Create one region for reach target contained in device vg00/lvol1
|
||||
.br
|
||||
.br
|
||||
# dmstats create --segments vg00/lvol1
|
||||
.br
|
||||
Created region: 0
|
||||
.br
|
||||
Created region: 1
|
||||
.br
|
||||
Created region: 2
|
||||
.br
|
||||
.br
|
||||
|
||||
Print raw counters for region 4 on device d0
|
||||
.br
|
||||
.br
|
||||
# dmstats print --regionid 4 d0
|
||||
.br
|
||||
2097152+65536 0 0 0 0 29 0 264 701 0 41 701 0 41
|
||||
.br
|
||||
.br
|
||||
.SH AUTHORS
|
||||
Bryn M. Reeves <bmr@redhat.com>
|
||||
|
||||
.SH SEE ALSO
|
||||
LVM2 resource page https://www.sourceware.org/lvm2/
|
||||
.br
|
||||
Device-mapper resource page: http://sources.redhat.com/dm/
|
||||
.br
|
||||
|
||||
Device-mapper statistics kernel documentation
|
||||
.br
|
||||
Documentation/device-mapper/statistics.txt
|
1644
tools/dmsetup.c
1644
tools/dmsetup.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user