mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-19 14:04:17 +03:00
dmstats: add histogram support
Add support to dmstats to create and report histograms. Add a --histogram switch to 'create' that accepts a string description of bin boundaries and DR_STATS and DR_STATS_META fields to report bin configuration and absolute and relative histogram values: hist_bins hist_bounds hist_ranges hist_count hist_count_bounds hist_count_ranges hist_percent hist_percent_bounds hist_percent_ranges A new 'histogram' subcommand displays a report that emphasizes histogram data as either counters or percentage values.
This commit is contained in:
parent
a0cf3d47f1
commit
3c0fc6f0da
@ -4,6 +4,8 @@ Version 1.02.107 -
|
|||||||
|
|
||||||
Version 1.02.106 - 26th August 2015
|
Version 1.02.106 - 26th August 2015
|
||||||
===================================
|
===================================
|
||||||
|
Add basic report fields for displaying latency histogram data.
|
||||||
|
Add dmstats --histogram to specify histogram boundaries for a region.
|
||||||
Add public methods to libdm-stats to access numerical histogram data.
|
Add public methods to libdm-stats to access numerical histogram data.
|
||||||
Add the ability to parse histogram data into numeric form to libdm-stats.
|
Add the ability to parse histogram data into numeric form to libdm-stats.
|
||||||
Add 'precise' column to statistics reports.
|
Add 'precise' column to statistics reports.
|
||||||
|
154
man/dmstats.8.in
154
man/dmstats.8.in
@ -32,6 +32,8 @@ dmstats \(em device-mapper statistics management
|
|||||||
.IR nr_areas ]
|
.IR nr_areas ]
|
||||||
.RB |[ \-\-areasize
|
.RB |[ \-\-areasize
|
||||||
.IR area_size ]]
|
.IR area_size ]]
|
||||||
|
.RB [ \-\-histogram
|
||||||
|
.IR boundaries ]
|
||||||
.RB [ \-\-precise ]
|
.RB [ \-\-precise ]
|
||||||
.RB [[ \-\-start
|
.RB [[ \-\-start
|
||||||
.IR start_sector ]
|
.IR start_sector ]
|
||||||
@ -56,6 +58,28 @@ dmstats \(em device-mapper statistics management
|
|||||||
.B dmstats help
|
.B dmstats help
|
||||||
.RB [ \-c | \-C | \-\-columns ]
|
.RB [ \-c | \-C | \-\-columns ]
|
||||||
.br
|
.br
|
||||||
|
.B dmstats histogram
|
||||||
|
.RI [ device_name ]
|
||||||
|
.RB [ \-\-interval
|
||||||
|
.IR seconds ]
|
||||||
|
.RB [ \-\-count
|
||||||
|
.IR count ]
|
||||||
|
.RB [ \-\-units
|
||||||
|
.IR units ]
|
||||||
|
.RB [ \-\-allprograms ]
|
||||||
|
.RB [ \-\-programid
|
||||||
|
.IR id ]
|
||||||
|
.RB [ \-\-relative ]
|
||||||
|
.RB [ \-\-regionid
|
||||||
|
.IR id ]
|
||||||
|
.RB [ \-O | \-\-sort
|
||||||
|
.IR sort_fields ]
|
||||||
|
.RB [ \-S | \-\-select
|
||||||
|
.IR Selection ]
|
||||||
|
.RB [ \-\-units
|
||||||
|
.IR units ]
|
||||||
|
.RB [ \-\-nosuffix ]
|
||||||
|
.br
|
||||||
.B dmstats list
|
.B dmstats list
|
||||||
.RI [ device_name ]
|
.RI [ device_name ]
|
||||||
.RB [ \-\-allprograms
|
.RB [ \-\-allprograms
|
||||||
@ -154,6 +178,13 @@ When printing statistics counters, also atomically reset them to zero.
|
|||||||
Specify the iteration count for repeating reports. If the count
|
Specify the iteration count for repeating reports. If the count
|
||||||
argument is zero reports will continue to repeat until interrupted.
|
argument is zero reports will continue to repeat until interrupted.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-histogram \fIboundaries
|
||||||
|
Specify the boundaries of a latency histogram to be tracked for the
|
||||||
|
region as a comma separated list of latency values. Latency values are
|
||||||
|
given in nanoseconds. An optional unit suffix of ns, us, ms, or s may be
|
||||||
|
given after each value to specify units of nanoseconds, microseconds,
|
||||||
|
miliseconds or seconds respectively.
|
||||||
|
.TP
|
||||||
.B \-\-interval \fIseconds
|
.B \-\-interval \fIseconds
|
||||||
Specify the interval in seconds between successive iterations for
|
Specify the interval in seconds between successive iterations for
|
||||||
repeating reports. If \-\-interval is specified but \-\-count is not,
|
repeating reports. If \-\-interval is specified but \-\-count is not,
|
||||||
@ -192,6 +223,10 @@ string is stored with the region. Subsequent operations may supply a
|
|||||||
program ID in order to select only regions with a matching value. The
|
program ID in order to select only regions with a matching value. The
|
||||||
default program ID for dmstats-managed regions is "dmstats".
|
default program ID for dmstats-managed regions is "dmstats".
|
||||||
.TP
|
.TP
|
||||||
|
.BR \-\-relative
|
||||||
|
If displaying the histogram report show relative (percentage) values
|
||||||
|
instead of absolute counts.
|
||||||
|
.TP
|
||||||
.BR \-S | \-\-select \ \fIselection
|
.BR \-S | \-\-select \ \fIselection
|
||||||
Display only rows that match selection criteria. All rows with the
|
Display only rows that match selection criteria. All rows with the
|
||||||
additional "selected" column (-o selected) showing 1 if the row matches
|
additional "selected" column (-o selected) showing 1 if the row matches
|
||||||
@ -245,6 +280,8 @@ regions (with the exception of in-flight IO counters).
|
|||||||
.IR nr_areas ]
|
.IR nr_areas ]
|
||||||
.RB [ \-\-areasize
|
.RB [ \-\-areasize
|
||||||
.IR area_size ]
|
.IR area_size ]
|
||||||
|
.RB [ \-\-histogram
|
||||||
|
.IR boundaries ]
|
||||||
.RB [ \-\-precise ]
|
.RB [ \-\-precise ]
|
||||||
.RB [[ \-\-start
|
.RB [[ \-\-start
|
||||||
.IR start_sector ]
|
.IR start_sector ]
|
||||||
@ -268,6 +305,20 @@ device-mapper device's table.
|
|||||||
If the \fB\-\-precise\fP option is used the command will attempt to
|
If the \fB\-\-precise\fP option is used the command will attempt to
|
||||||
create a region using nanosecond precision counters.
|
create a region using nanosecond precision counters.
|
||||||
|
|
||||||
|
If \fB\-\-histogram\fP is given a latency histogram will be tracked for
|
||||||
|
the new region. The boundaries of the histogram bins are given as a
|
||||||
|
comma separated list of latency values. There is an implicit lower bound
|
||||||
|
of zero on the first bin and an implicit upper bound of infinity (or the
|
||||||
|
configured interval duration) on the final bin.
|
||||||
|
|
||||||
|
Latencies are given in nanoseconds. An optional unit suffix of ns, us,
|
||||||
|
ms, or s may be given after each value to specify units of nanoseconds,
|
||||||
|
microseconds, miliseconds or seconds respectively, so for example, 10ms
|
||||||
|
is equivalent to 10000000. Latency values with a precision of less than
|
||||||
|
one milisecond can only be used when precise timestamps are enabled: if
|
||||||
|
\fB\-\-precise\fP is not given and values less than one milisecond are
|
||||||
|
used it will be enabled automatically.
|
||||||
|
|
||||||
An optional \fBprogram_id\fP or \fBaux_data\fP string may be associated
|
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
|
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
|
for subsequent list, print, and report operations. The \fBaux_data\fP
|
||||||
@ -309,6 +360,38 @@ Outputs a summary of the commands available, optionally including
|
|||||||
the list of report fields.
|
the list of report fields.
|
||||||
.br
|
.br
|
||||||
.TP
|
.TP
|
||||||
|
.B histogram
|
||||||
|
.RB [ \-\-allprograms ]
|
||||||
|
.RB [ \-\-interval
|
||||||
|
.IR seconds ]
|
||||||
|
.RB [ \-\-count
|
||||||
|
.IR count ]
|
||||||
|
.RB [ \-\-units
|
||||||
|
.IR unit ]
|
||||||
|
.RB [ \-\-relative ]
|
||||||
|
.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 that
|
||||||
|
emphasizes latency histograms in the default field options. 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.
|
||||||
|
|
||||||
|
If \fB\-\-relative\fP is given the default histogram field displays the
|
||||||
|
relative histogram instead of absolute counts.
|
||||||
|
.br
|
||||||
|
.TP
|
||||||
.B list
|
.B list
|
||||||
.RI [ device_name ]
|
.RI [ device_name ]
|
||||||
.RB [ \-\-allprograms ]
|
.RB [ \-\-allprograms ]
|
||||||
@ -592,6 +675,77 @@ 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
|
field. This can provide an easy measure of both I/O completion time and
|
||||||
the backlog that may be accumulating.
|
the backlog that may be accumulating.
|
||||||
.br
|
.br
|
||||||
|
.SS Histogram fields
|
||||||
|
Histograms measure the frequency distribution of user specified I/O
|
||||||
|
latency intervals. Histogram bin boundaries are specified when a region
|
||||||
|
is created.
|
||||||
|
|
||||||
|
A brief representation of the histogram values and latency intervals can
|
||||||
|
be included in the report using these fields.
|
||||||
|
.P
|
||||||
|
.HP
|
||||||
|
.B hist_count
|
||||||
|
.br
|
||||||
|
A list of the histogram counts for the current statistics area in order
|
||||||
|
of ascending latency value. Each value represents the number of I/Os
|
||||||
|
with latency times falling into that bin's time range during the sample
|
||||||
|
period.
|
||||||
|
.HP
|
||||||
|
.B hist_count_bounds
|
||||||
|
.br
|
||||||
|
A list of the histogram counts for the current statistics area in order
|
||||||
|
of ascending latency value including bin boundaries: each count is
|
||||||
|
prefixed by the lower bound of the corresponding histogram bin.
|
||||||
|
.HP
|
||||||
|
.B hist_count_ranges
|
||||||
|
.br
|
||||||
|
A list of the histogram counts for the current statistics area in order
|
||||||
|
of ascending latency value including bin boundaries: each count is
|
||||||
|
prefixed by both the lower and upper bounds of the corresponding
|
||||||
|
histogram bin.
|
||||||
|
.HP
|
||||||
|
.B hist_percent
|
||||||
|
.br
|
||||||
|
A list of the relative histogram values for the current statistics area
|
||||||
|
in order of ascending latency value, expressed as a percentage. Each
|
||||||
|
value represents the proportion of I/Os with latency times falling into
|
||||||
|
that bin's time range during the sample period.
|
||||||
|
.HP
|
||||||
|
.B hist_percent_bounds
|
||||||
|
.br
|
||||||
|
A list of the relative histogram values for the current statistics area
|
||||||
|
in order of ascending latency value, expressed as a percentage and
|
||||||
|
including bin boundaries. Each value represents the proportion of I/Os
|
||||||
|
with latency times falling into that bin's time range during the sample
|
||||||
|
period and is prefixed with the corresponding bin's lower bound.
|
||||||
|
.HP
|
||||||
|
.B hist_percent_ranges
|
||||||
|
.br
|
||||||
|
A list of the relative histogram values for the current statistics area
|
||||||
|
in order of ascending latency value, expressed as a percentage and
|
||||||
|
including bin boundaries. Each value represents the proportion of I/Os
|
||||||
|
with latency times falling into that bin's time range during the sample
|
||||||
|
period and is prefixed with the corresponding bin's lower and upper
|
||||||
|
bounds.
|
||||||
|
.HP
|
||||||
|
.B hist_bounds
|
||||||
|
.br
|
||||||
|
A list of the histogram boundary values for the current statistics area
|
||||||
|
in order of ascending latency value. The values are expressed in whole
|
||||||
|
units of seconds, miliseconds, microseconds or nanoseconds with a suffix
|
||||||
|
indicating the unit.
|
||||||
|
.HP
|
||||||
|
.B hist_ranges
|
||||||
|
.br
|
||||||
|
A list of the histogram bin ranges for the current statistics area in
|
||||||
|
order of ascending latency value. The values are expressed as
|
||||||
|
"LOWER-UPPER" in whole units of seconds, miliseconds, microseconds or
|
||||||
|
nanoseconds with a suffix indicating the unit.
|
||||||
|
.HP
|
||||||
|
.B hist_bins
|
||||||
|
.br
|
||||||
|
The number of latency histogram bins configured for the area.
|
||||||
|
.br
|
||||||
.br
|
.br
|
||||||
.P
|
.P
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
|
208
tools/dmsetup.c
208
tools/dmsetup.c
@ -172,6 +172,7 @@ enum {
|
|||||||
FORCE_ARG,
|
FORCE_ARG,
|
||||||
GID_ARG,
|
GID_ARG,
|
||||||
HELP_ARG,
|
HELP_ARG,
|
||||||
|
HISTOGRAM_ARG,
|
||||||
INACTIVE_ARG,
|
INACTIVE_ARG,
|
||||||
INTERVAL_ARG,
|
INTERVAL_ARG,
|
||||||
LENGTH_ARG,
|
LENGTH_ARG,
|
||||||
@ -195,6 +196,7 @@ enum {
|
|||||||
RAW_ARG,
|
RAW_ARG,
|
||||||
READAHEAD_ARG,
|
READAHEAD_ARG,
|
||||||
REGION_ID_ARG,
|
REGION_ID_ARG,
|
||||||
|
RELATIVE_ARG,
|
||||||
RETRY_ARG,
|
RETRY_ARG,
|
||||||
ROWS_ARG,
|
ROWS_ARG,
|
||||||
SEPARATOR_ARG,
|
SEPARATOR_ARG,
|
||||||
@ -3436,6 +3438,153 @@ static int _dm_stats_precise_disp(struct dm_report *rh,
|
|||||||
return dm_report_field_int(rh, field, (const int *) &precise);
|
return dm_report_field_int(rh, field, (const int *) &precise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *_get_histogram_string(const struct dm_stats *dms, int rel,
|
||||||
|
int vals, int bounds)
|
||||||
|
{
|
||||||
|
const struct dm_histogram *dmh;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
if (!(dmh = dm_stats_get_histogram(dms, DM_STATS_REGION_CURRENT,
|
||||||
|
DM_STATS_AREA_CURRENT)))
|
||||||
|
return ""; /* No histogram. */
|
||||||
|
|
||||||
|
flags |= (vals) ? DM_HISTOGRAM_VALUES
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
flags |= bounds;
|
||||||
|
|
||||||
|
flags |= (rel) ? DM_HISTOGRAM_PERCENT
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
flags |= DM_HISTOGRAM_SUFFIX;
|
||||||
|
|
||||||
|
/* FIXME: make unit conversion optional. */
|
||||||
|
return dm_histogram_to_string(dmh, -1, 0, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _stats_hist_count_disp(struct dm_report *rh,
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
int bounds)
|
||||||
|
{
|
||||||
|
const struct dm_stats *dms = (const struct dm_stats *) data;
|
||||||
|
const char *histogram;
|
||||||
|
|
||||||
|
histogram = _get_histogram_string(dms, 0, 1, bounds); /* counts */
|
||||||
|
|
||||||
|
if (!histogram)
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
return dm_report_field_string(rh, field, (const char * const *) &histogram);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dm_stats_hist_count_disp(struct dm_report *rh,
|
||||||
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
void *private __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return _stats_hist_count_disp(rh, field, data, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dm_stats_hist_count_bounds_disp(struct dm_report *rh,
|
||||||
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
void *private __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return _stats_hist_count_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_LOWER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dm_stats_hist_count_ranges_disp(struct dm_report *rh,
|
||||||
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
void *private __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return _stats_hist_count_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_RANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _stats_hist_percent_disp(struct dm_report *rh,
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
int bounds)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* FIXME: configurable to-string options. */
|
||||||
|
const struct dm_stats *dms = (const struct dm_stats *) data;
|
||||||
|
const char *histogram;
|
||||||
|
|
||||||
|
histogram = _get_histogram_string(dms, 1, 1, bounds); /* relative values */
|
||||||
|
|
||||||
|
if (!histogram)
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
return dm_report_field_string(rh, field, (const char * const *) &histogram);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dm_stats_hist_percent_disp(struct dm_report *rh,
|
||||||
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
void *private __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return _stats_hist_percent_disp(rh, field, data, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dm_stats_hist_percent_bounds_disp(struct dm_report *rh,
|
||||||
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
void *private __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return _stats_hist_percent_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_LOWER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dm_stats_hist_percent_ranges_disp(struct dm_report *rh,
|
||||||
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
void *private __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return _stats_hist_percent_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_RANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _stats_hist_bounds_disp(struct dm_report *rh,
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
int bounds)
|
||||||
|
{
|
||||||
|
/* FIXME: configurable to-string options. */
|
||||||
|
const struct dm_stats *dms = (const struct dm_stats *) data;
|
||||||
|
const char *histogram;
|
||||||
|
|
||||||
|
histogram = _get_histogram_string(dms, 0, 0, bounds);
|
||||||
|
|
||||||
|
if (!histogram)
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
return dm_report_field_string(rh, field, (const char * const *) &histogram);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dm_stats_hist_bounds_disp(struct dm_report *rh,
|
||||||
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
void *private __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return _stats_hist_bounds_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_LOWER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dm_stats_hist_ranges_disp(struct dm_report *rh,
|
||||||
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
void *private __attribute__((unused)))
|
||||||
|
{
|
||||||
|
return _stats_hist_bounds_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_RANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dm_stats_hist_bins_disp(struct dm_report *rh,
|
||||||
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
|
struct dm_report_field *field, const void *data,
|
||||||
|
void *private __attribute__((unused)))
|
||||||
|
{
|
||||||
|
const struct dm_stats *dms = (const struct dm_stats *) data;
|
||||||
|
int bins;
|
||||||
|
bins = dm_stats_get_region_nr_histogram_bins(dms, DM_STATS_REGION_CURRENT);
|
||||||
|
return dm_report_field_int(rh, field, (const int *) &bins);
|
||||||
|
}
|
||||||
|
|
||||||
static int _dm_stats_rrqm_disp(struct dm_report *rh,
|
static int _dm_stats_rrqm_disp(struct dm_report *rh,
|
||||||
struct dm_pool *mem __attribute__((unused)),
|
struct dm_pool *mem __attribute__((unused)),
|
||||||
struct dm_report_field *field, const void *data,
|
struct dm_report_field *field, const void *data,
|
||||||
@ -4017,6 +4166,14 @@ FIELD_F(STATS, NUM, "TPut", 5, dm_stats_tput, "tput", "Throughput.")
|
|||||||
FIELD_F(STATS, NUM, "SvcTm", 5, dm_stats_svctm, "svctm", "Service time.")
|
FIELD_F(STATS, NUM, "SvcTm", 5, dm_stats_svctm, "svctm", "Service time.")
|
||||||
FIELD_F(STATS, NUM, "Util%", 5, dm_stats_util, "util", "Utilization.")
|
FIELD_F(STATS, NUM, "Util%", 5, dm_stats_util, "util", "Utilization.")
|
||||||
|
|
||||||
|
/* Histogram fields */
|
||||||
|
FIELD_F(STATS, STR, "Histogram Counts", 16, dm_stats_hist_count, "hist_count", "Latency histogram counts.")
|
||||||
|
FIELD_F(STATS, STR, "Histogram Counts", 16, dm_stats_hist_count_bounds, "hist_count_bounds", "Latency histogram counts with bin boundaries.")
|
||||||
|
FIELD_F(STATS, STR, "Histogram Counts", 16, dm_stats_hist_count_ranges, "hist_count_ranges", "Latency histogram counts with bin ranges.")
|
||||||
|
FIELD_F(STATS, STR, "Histogram%", 10, dm_stats_hist_percent, "hist_percent", "Relative latency histogram.")
|
||||||
|
FIELD_F(STATS, STR, "Histogram%", 10, dm_stats_hist_percent_bounds, "hist_percent_bounds", "Relative latency histogram with bin boundaries.")
|
||||||
|
FIELD_F(STATS, STR, "Histogram%", 10, dm_stats_hist_percent_ranges, "hist_percent_ranges", "Relative latency histogram with bin ranges.")
|
||||||
|
|
||||||
/* Stats interval duration estimates */
|
/* Stats interval duration estimates */
|
||||||
FIELD_F(STATS, NUM, "IntervalNSec", 10, dm_stats_sample_interval_ns, "interval_ns", "Sampling interval in nanoseconds.")
|
FIELD_F(STATS, NUM, "IntervalNSec", 10, dm_stats_sample_interval_ns, "interval_ns", "Sampling interval in nanoseconds.")
|
||||||
FIELD_F(STATS, NUM, "Interval", 8, dm_stats_sample_interval, "interval", "Sampling interval.")
|
FIELD_F(STATS, NUM, "Interval", 8, dm_stats_sample_interval, "interval", "Sampling interval.")
|
||||||
@ -4032,7 +4189,10 @@ FIELD_F(STATS_META, SIZ, "AOff", 5, dm_stats_area_offset, "area_offset", "Area o
|
|||||||
FIELD_F(STATS_META, NUM, "#Areas", 3, dm_stats_area_count, "area_count", "Area count.")
|
FIELD_F(STATS_META, NUM, "#Areas", 3, dm_stats_area_count, "area_count", "Area count.")
|
||||||
FIELD_F(STATS_META, STR, "ProgID", 6, dm_stats_program_id, "program_id", "Program ID.")
|
FIELD_F(STATS_META, STR, "ProgID", 6, dm_stats_program_id, "program_id", "Program ID.")
|
||||||
FIELD_F(STATS_META, STR, "AuxDat", 6, dm_stats_aux_data, "aux_data", "Auxiliary data.")
|
FIELD_F(STATS_META, STR, "AuxDat", 6, dm_stats_aux_data, "aux_data", "Auxiliary data.")
|
||||||
FIELD_F(STATS_META, STR, "Precise", 5, dm_stats_precise, "precise", "Set if the nanosecond precision timers are enabled.")
|
FIELD_F(STATS_META, STR, "Precise", 7, dm_stats_precise, "precise", "Set if nanosecond precision counters are enabled.")
|
||||||
|
FIELD_F(STATS_META, STR, "#Bins", 9, dm_stats_hist_bins, "hist_bins", "The number of histogram bins configured.")
|
||||||
|
FIELD_F(STATS_META, STR, "Histogram Bounds", 16, dm_stats_hist_bounds, "hist_bounds", "Latency histogram bin boundaries.")
|
||||||
|
FIELD_F(STATS_META, STR, "Histogram Ranges", 16, dm_stats_hist_ranges, "hist_ranges", "Latency histogram bin ranges.")
|
||||||
{0, 0, 0, 0, "", "", NULL, NULL},
|
{0, 0, 0, 0, "", "", NULL, NULL},
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
};
|
};
|
||||||
@ -4056,14 +4216,20 @@ static const char *splitname_report_options = "vg_name,lv_name,lv_layer";
|
|||||||
|
|
||||||
/* Device, region and area metadata. */
|
/* Device, region and area metadata. */
|
||||||
#define STATS_DEV_INFO "name,region_id"
|
#define STATS_DEV_INFO "name,region_id"
|
||||||
#define STATS_AREA_INFO STATS_DEV_INFO ",region_start,region_len,area_count,area_id,area_start,area_len"
|
#define STATS_AREA_INFO "area_id,area_start,area_len"
|
||||||
|
#define STATS_AREA_INFO_FULL STATS_DEV_INFO ",region_start,region_len,area_count,area_id,area_start,area_len"
|
||||||
#define STATS_REGION_INFO STATS_DEV_INFO ",region_start,region_len,area_count,area_len"
|
#define STATS_REGION_INFO STATS_DEV_INFO ",region_start,region_len,area_count,area_len"
|
||||||
|
|
||||||
|
/* Minimal set of fields for histogram report. */
|
||||||
|
#define STATS_HIST STATS_REGION_INFO ",util,await"
|
||||||
|
|
||||||
/* Default stats report options. */
|
/* Default stats report options. */
|
||||||
static const char *_stats_default_report_options = STATS_DEV_INFO ",area_id,area_start,area_len," METRICS;
|
static const char *_stats_default_report_options = STATS_DEV_INFO "," STATS_AREA_INFO "," METRICS;
|
||||||
static const char *_stats_raw_report_options = STATS_DEV_INFO ",area_id,area_start,area_len," COUNTERS;
|
static const char *_stats_raw_report_options = STATS_DEV_INFO "," STATS_AREA_INFO "," COUNTERS;
|
||||||
static const char *_stats_list_options = STATS_REGION_INFO ",program_id";
|
static const char *_stats_list_options = STATS_REGION_INFO ",program_id";
|
||||||
static const char *_stats_area_list_options = STATS_AREA_INFO ",program_id";
|
static const char *_stats_area_list_options = STATS_AREA_INFO_FULL ",program_id";
|
||||||
|
static const char *_stats_hist_options = STATS_HIST ",hist_count_bounds";
|
||||||
|
static const char *_stats_hist_relative_options = STATS_HIST ",hist_percent_bounds";
|
||||||
|
|
||||||
static int _report_init(const struct command *cmd, const char *subcommand)
|
static int _report_init(const struct command *cmd, const char *subcommand)
|
||||||
{
|
{
|
||||||
@ -4089,6 +4255,10 @@ static int _report_init(const struct command *cmd, const char *subcommand)
|
|||||||
options = (char *) ((_switches[VERBOSE_ARG])
|
options = (char *) ((_switches[VERBOSE_ARG])
|
||||||
? _stats_area_list_options
|
? _stats_area_list_options
|
||||||
: _stats_list_options);
|
: _stats_list_options);
|
||||||
|
else if (!strcmp(subcommand, "histogram"))
|
||||||
|
options = (char *) ((_switches[RELATIVE_ARG])
|
||||||
|
? _stats_hist_relative_options
|
||||||
|
: _stats_hist_options);
|
||||||
else {
|
else {
|
||||||
options = (char *) ((!_switches[RAW_ARG])
|
options = (char *) ((!_switches[RAW_ARG])
|
||||||
? _stats_default_report_options
|
? _stats_default_report_options
|
||||||
@ -4481,12 +4651,16 @@ static int _do_stats_create_regions(struct dm_stats *dms,
|
|||||||
const char *aux_data)
|
const char *aux_data)
|
||||||
{
|
{
|
||||||
uint64_t this_start = 0, this_len = len, region_id = UINT64_C(0);
|
uint64_t this_start = 0, this_len = len, region_id = UINT64_C(0);
|
||||||
|
const char *devname = NULL, *histogram = _string_args[HISTOGRAM_ARG];
|
||||||
|
int r = 0, precise = _switches[PRECISE_ARG];
|
||||||
|
struct dm_histogram *bounds = NULL; /* histogram bounds */
|
||||||
char *target_type, *params; /* unused */
|
char *target_type, *params; /* unused */
|
||||||
struct dm_task *dmt;
|
struct dm_task *dmt;
|
||||||
struct dm_info info;
|
struct dm_info info;
|
||||||
void *next = NULL;
|
void *next = NULL;
|
||||||
const char *devname = NULL;
|
|
||||||
int r = 0, precise = _switches[PRECISE_ARG];
|
if (histogram && !(bounds = dm_histogram_bounds_from_string(histogram)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) {
|
if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) {
|
||||||
dm_stats_destroy(dms);
|
dm_stats_destroy(dms);
|
||||||
@ -4533,7 +4707,7 @@ static int _do_stats_create_regions(struct dm_stats *dms,
|
|||||||
this_len = (segments) ? segment_len : this_len;
|
this_len = (segments) ? segment_len : this_len;
|
||||||
if (!dm_stats_create_region(dms, ®ion_id,
|
if (!dm_stats_create_region(dms, ®ion_id,
|
||||||
this_start, this_len, step,
|
this_start, this_len, step,
|
||||||
precise, NULL,
|
precise, bounds,
|
||||||
program_id, aux_data)) {
|
program_id, aux_data)) {
|
||||||
log_error("%s: Could not create statistics region.",
|
log_error("%s: Could not create statistics region.",
|
||||||
devname);
|
devname);
|
||||||
@ -4550,6 +4724,7 @@ static int _do_stats_create_regions(struct dm_stats *dms,
|
|||||||
out:
|
out:
|
||||||
dm_task_destroy(dmt);
|
dm_task_destroy(dmt);
|
||||||
dm_stats_destroy(dms);
|
dm_stats_destroy(dms);
|
||||||
|
dm_histogram_bounds_destroy(bounds);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4652,6 +4827,14 @@ static int _stats_create(CMD_ARGS)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_switches[HISTOGRAM_ARG]) {
|
||||||
|
if (!dm_stats_driver_supports_histogram()) {
|
||||||
|
log_error("Using --histogram requires driver version "
|
||||||
|
"4.32.0 or later.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!strlen(program_id))
|
if (!strlen(program_id))
|
||||||
/* force creation of a region with no id */
|
/* force creation of a region with no id */
|
||||||
dm_stats_set_program_id(dms, 1, NULL);
|
dm_stats_set_program_id(dms, 1, NULL);
|
||||||
@ -4886,6 +5069,7 @@ static struct command _stats_subcommands[] = {
|
|||||||
{"clear", "--regionid <id> [<device>]", 0, -1, 1, 0, _stats_clear},
|
{"clear", "--regionid <id> [<device>]", 0, -1, 1, 0, _stats_clear},
|
||||||
{"create", CREATE_OPTS "\n\t\t" ID_OPTS "[<device>]", 0, -1, 1, 0, _stats_create},
|
{"create", CREATE_OPTS "\n\t\t" ID_OPTS "[<device>]", 0, -1, 1, 0, _stats_create},
|
||||||
{"delete", "--regionid <id> <device>", 1, -1, 1, 0, _stats_delete},
|
{"delete", "--regionid <id> <device>", 1, -1, 1, 0, _stats_delete},
|
||||||
|
{"histogram", REPORT_OPTS "[<device>]", 0, -1, 1, 0, _stats_report},
|
||||||
{"list", "[--programid <id>] [<device>]", 0, -1, 1, 0, _stats_report},
|
{"list", "[--programid <id>] [<device>]", 0, -1, 1, 0, _stats_report},
|
||||||
{"print", PRINT_OPTS "[<device>]", 0, -1, 1, 0, _stats_print},
|
{"print", PRINT_OPTS "[<device>]", 0, -1, 1, 0, _stats_print},
|
||||||
{"report", REPORT_OPTS "[<device>]", 0, -1, 1, 0, _stats_report},
|
{"report", REPORT_OPTS "[<device>]", 0, -1, 1, 0, _stats_report},
|
||||||
@ -5500,6 +5684,7 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
|
|||||||
{"force", 0, &ind, FORCE_ARG},
|
{"force", 0, &ind, FORCE_ARG},
|
||||||
{"gid", 1, &ind, GID_ARG},
|
{"gid", 1, &ind, GID_ARG},
|
||||||
{"help", 0, &ind, HELP_ARG},
|
{"help", 0, &ind, HELP_ARG},
|
||||||
|
{"histogram", 1, &ind, HISTOGRAM_ARG},
|
||||||
{"inactive", 0, &ind, INACTIVE_ARG},
|
{"inactive", 0, &ind, INACTIVE_ARG},
|
||||||
{"interval", 1, &ind, INTERVAL_ARG},
|
{"interval", 1, &ind, INTERVAL_ARG},
|
||||||
{"length", 1, &ind, LENGTH_ARG},
|
{"length", 1, &ind, LENGTH_ARG},
|
||||||
@ -5523,6 +5708,7 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
|
|||||||
{"raw", 0, &ind, RAW_ARG},
|
{"raw", 0, &ind, RAW_ARG},
|
||||||
{"readahead", 1, &ind, READAHEAD_ARG},
|
{"readahead", 1, &ind, READAHEAD_ARG},
|
||||||
{"regionid", 1, &ind, REGION_ID_ARG},
|
{"regionid", 1, &ind, REGION_ID_ARG},
|
||||||
|
{"relative", 0, &ind, RELATIVE_ARG},
|
||||||
{"retry", 0, &ind, RETRY_ARG},
|
{"retry", 0, &ind, RETRY_ARG},
|
||||||
{"rows", 0, &ind, ROWS_ARG},
|
{"rows", 0, &ind, ROWS_ARG},
|
||||||
{"segments", 0, &ind, SEGMENTS_ARG},
|
{"segments", 0, &ind, SEGMENTS_ARG},
|
||||||
@ -5638,6 +5824,10 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
|
|||||||
return 0;
|
return 0;
|
||||||
if (c == 'h' || ind == HELP_ARG)
|
if (c == 'h' || ind == HELP_ARG)
|
||||||
_switches[HELP_ARG]++;
|
_switches[HELP_ARG]++;
|
||||||
|
if (ind == HISTOGRAM_ARG) {
|
||||||
|
_switches[HISTOGRAM_ARG]++;
|
||||||
|
_string_args[HISTOGRAM_ARG] = optarg;
|
||||||
|
}
|
||||||
if (ind == CLEAR_ARG)
|
if (ind == CLEAR_ARG)
|
||||||
_switches[CLEAR_ARG]++;
|
_switches[CLEAR_ARG]++;
|
||||||
if (c == 'c' || c == 'C' || ind == COLS_ARG)
|
if (c == 'c' || c == 'C' || ind == COLS_ARG)
|
||||||
@ -5678,6 +5868,8 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
|
|||||||
_switches[REGION_ID_ARG]++;
|
_switches[REGION_ID_ARG]++;
|
||||||
_int_args[REGION_ID_ARG] = atoi(optarg);
|
_int_args[REGION_ID_ARG] = atoi(optarg);
|
||||||
}
|
}
|
||||||
|
if (ind == RELATIVE_ARG)
|
||||||
|
_switches[RELATIVE_ARG]++;
|
||||||
if (ind == SEPARATOR_ARG) {
|
if (ind == SEPARATOR_ARG) {
|
||||||
_switches[SEPARATOR_ARG]++;
|
_switches[SEPARATOR_ARG]++;
|
||||||
_string_args[SEPARATOR_ARG] = optarg;
|
_string_args[SEPARATOR_ARG] = optarg;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user