summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryn M. Reeves <bmr@redhat.com>2016-06-19 13:38:41 +0100
committerBryn M. Reeves <bmr@redhat.com>2016-07-05 19:53:16 +0100
commitca0a4cececf372a5d420e9402fec86d5cd013bf5 (patch)
tree0733f7ace8f8a4b7fde83fdef1aac085603b55f3
parent8b179e09a4b921d2be925c997dd1125176e616c5 (diff)
downloadlvm2-ca0a4cececf372a5d420e9402fec86d5cd013bf5.tar.gz
dmstats: report groups and region summaries
Walk avaiable groups and regions (in addition to areas) and report aggregate statistics and properties. A new switch is added to filter the type of obects inclued in the report: --statstype={all,area,region,group} The type of the current row is also available in a new DR_STATS_META field 'type'.
-rw-r--r--tools/dmsetup.c118
1 files changed, 95 insertions, 23 deletions
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index dfb362bfa..d1f93fd64 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -209,6 +209,7 @@ enum {
SHOWKEYS_ARG,
SORT_ARG,
START_ARG,
+ STATSTYPE_ARG,
TABLE_ARG,
TARGET_ARG,
SEGMENTS_ARG,
@@ -264,7 +265,16 @@ static struct dm_timestamp *_initial_timestamp = NULL;
static uint64_t _disp_factor = 512; /* display sizes in sectors */
static char _disp_units = 's';
const char *_program_id = DM_STATS_PROGRAM_ID; /* program_id used for reports. */
-static int _stats_report_by_areas = 1; /* output per-area info for stats reports. */
+static uint64_t _statstype = 0; /* stats objects to report */
+
+/* string names for stats object types */
+const char *_stats_types[] = {
+ "all",
+ "area",
+ "region",
+ "group",
+ NULL
+};
/* report timekeeping */
static struct dm_timestamp *_cycle_timestamp = NULL;
@@ -804,7 +814,7 @@ out:
static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
{
struct dmsetup_report_obj obj;
-
+ uint64_t walk_flags = _statstype;
int r = 0;
if (!info->exists) {
@@ -835,6 +845,13 @@ static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
dm_task_get_name(dmt), '-')))
goto_out;
+ if (!(_report_type & (DR_STATS | DR_STATS_META))) {
+ if (!dm_report_object(_report, &obj))
+ goto_out;
+ r = 1;
+ goto out;
+ }
+
/*
* Obtain statistics for the current reporting object and set
* the interval estimate used for stats rate conversion.
@@ -854,10 +871,9 @@ static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
log_debug("Adjusted sample interval duration: %12"PRIu64"ns", _last_interval);
/* use measured approximation for calculations */
dm_stats_set_sampling_interval_ns(obj.stats, _last_interval);
- }
-
- /* Only a dm_stats_list is needed for DR_STATS_META reports. */
- if (!obj.stats && (_report_type & DR_STATS_META)) {
+ } else if (!obj.stats && (_report_type & DR_STATS_META)
+ /* Only a dm_stats_list is needed for DR_STATS_META reports. */
+ && !(_report_type & DR_STATS)) {
if (!(obj.stats = dm_stats_create(DM_STATS_PROGRAM_ID)))
goto_out;
@@ -871,20 +887,18 @@ static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
goto_out;
}
- /*
- * Walk any statistics regions contained in the current
- * reporting object: for objects with a NULL stats handle,
- * or a handle containing no registered regions, this loop
- * always executes exactly once.
- */
+ /* group report with no groups? */
+ if ((walk_flags == DM_STATS_WALK_GROUP)
+ && !dm_stats_get_nr_groups(obj.stats))
+ goto out;
+
+ dm_stats_walk_init(obj.stats, walk_flags);
dm_stats_walk_do(obj.stats) {
if (!dm_report_object(_report, &obj))
goto_out;
- if (_stats_report_by_areas)
- dm_stats_walk_next(obj.stats);
- else
- dm_stats_walk_next_region(obj.stats);
+ dm_stats_walk_next(obj.stats);
} dm_stats_walk_while(obj.stats);
+
r = 1;
out:
@@ -3251,6 +3265,13 @@ static int _dm_stats_region_id_disp(struct dm_report *rh,
{
const struct dm_stats *dms = (const struct dm_stats *) data;
uint64_t region_id = dm_stats_get_current_region(dms);
+
+ if (dm_stats_current_object_type(dms) == DM_STATS_OBJECT_TYPE_GROUP) {
+ /* FIXME: output group region list and use group_id as sortval. */
+ dm_report_field_set_value(field, "-", &region_id);
+ return 1;
+ }
+
return dm_report_field_uint64(rh, field, &region_id);
}
@@ -3317,6 +3338,10 @@ static int _dm_stats_area_id_disp(struct dm_report *rh,
{
const struct dm_stats *dms = (const struct dm_stats *) data;
uint64_t area_id = dm_stats_get_current_area(dms);
+
+ if (dm_stats_current_object_type(dms) == DM_STATS_OBJECT_TYPE_GROUP)
+ area_id = 0;
+
return dm_report_field_uint64(rh, field, &area_id);
}
@@ -3430,7 +3455,7 @@ static int _dm_stats_group_id_disp(struct dm_report *rh,
group_id = dm_stats_get_group_id(dms,
dm_stats_get_current_region(dms));
- if (group_id == UINT64_MAX) {
+ if (!dm_stats_group_present(dms, group_id)) {
dm_report_field_set_value(field, "-", &group_id);
return 1;
}
@@ -3475,6 +3500,17 @@ static int _dm_stats_name_disp(struct dm_report *rh,
return dm_report_field_string(rh, field, (const char * const *) &stats_name);
}
+static int _dm_stats_object_type_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 type = dm_stats_current_object_type(dms);
+
+ return dm_report_field_string(rh, field, (const char * const *) &_stats_types[type]);
+}
+
static int _dm_stats_precise_disp(struct dm_report *rh,
struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field, const void *data,
@@ -4242,7 +4278,8 @@ FIELD_F(STATS_META, STR, "Precise", 7, dm_stats_precise, "precise", "Set if nano
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.")
-FIELD_F(STATS, STR, "Name", 16, dm_stats_name, "stats_name", "Stats name of current row.")
+FIELD_F(STATS_META, STR, "Name", 16, dm_stats_name, "stats_name", "Stats name of current object.")
+FIELD_F(STATS_META, STR, "Object Type", 11, dm_stats_object_type, "type", "Type of stats object being reported.")
{0, 0, 0, 0, "", "", NULL, NULL},
/* *INDENT-ON* */
};
@@ -4577,6 +4614,7 @@ static int _stats_clear_regions(struct dm_stats *dms, uint64_t region_id)
if (!dm_stats_get_nr_regions(dms))
return 1;
+ dm_stats_walk_init(dms, DM_STATS_WALK_REGION);
dm_stats_walk_do(dms) {
if (allregions)
region_id = dm_stats_get_current_region(dms);
@@ -4591,7 +4629,7 @@ static int _stats_clear_regions(struct dm_stats *dms, uint64_t region_id)
return 0;
}
log_info("Cleared statistics region %"PRIu64".", region_id);
- dm_stats_walk_next_region(dms);
+ dm_stats_walk_next(dms);
} dm_stats_walk_while(dms);
return 1;
@@ -4966,6 +5004,7 @@ static int _stats_delete(CMD_ARGS)
}
if (_switches[ALL_REGIONS_ARG]) {
+ dm_stats_walk_init(dms, DM_STATS_WALK_REGION);
dm_stats_walk_do(dms) {
region_id = dm_stats_get_current_region(dms);
if (!dm_stats_delete_region(dms, region_id)) {
@@ -4973,7 +5012,7 @@ static int _stats_delete(CMD_ARGS)
goto out;
}
log_info("Deleted statistics region %" PRIu64, region_id);
- dm_stats_walk_next_region(dms);
+ dm_stats_walk_next(dms);
} dm_stats_walk_while(dms);
} else {
dm_stats_delete_region(dms, region_id);
@@ -5031,6 +5070,7 @@ static int _stats_print(CMD_ARGS)
goto out;
}
+ dm_stats_walk_init(dms, DM_STATS_WALK_REGION);
dm_stats_walk_do(dms) {
if (_switches[ALL_REGIONS_ARG])
region_id = dm_stats_get_current_region(dms);
@@ -5049,7 +5089,7 @@ static int _stats_print(CMD_ARGS)
printf("%s", stbuff);
dm_stats_buffer_destroy(dms, stbuff);
- dm_stats_walk_next_region(dms);
+ dm_stats_walk_next(dms);
} dm_stats_walk_while(dms);
@@ -5073,8 +5113,14 @@ static int _stats_report(CMD_ARGS)
if (_switches[ALL_PROGRAMS_ARG])
_program_id = "";
- if (!_switches[VERBOSE_ARG] && !strcmp(subcommand, "list"))
- _stats_report_by_areas = 0;
+ if (_switches[VERBOSE_ARG] && !strcmp(subcommand, "list"))
+ _statstype |= (DM_STATS_WALK_ALL
+ | DM_STATS_WALK_SKIP_SINGLE_AREA);
+
+ if (!strcmp(subcommand, "report"))
+ /* suppress duplicate rows of output */
+ _statstype |= (DM_STATS_WALK_ALL
+ | DM_STATS_WALK_SKIP_SINGLE_AREA);
if (names)
name = names->name;
@@ -5478,7 +5524,15 @@ static const struct command *_find_stats_subcommand(const char *name)
static int _stats(CMD_ARGS)
{
+ const char *type_arg = _string_args[STATSTYPE_ARG];
+ const char **type = _stats_types;
const struct command *stats_cmd;
+ uint64_t type_flags[] = {
+ DM_STATS_WALK_ALL,
+ DM_STATS_WALK_AREA,
+ DM_STATS_WALK_REGION,
+ DM_STATS_WALK_GROUP
+ };
if (!(stats_cmd = _find_stats_subcommand(subcommand))) {
log_error("Unknown stats command.");
@@ -5496,6 +5550,19 @@ static int _stats(CMD_ARGS)
return 0;
}
+ if (_switches[STATSTYPE_ARG]) {
+ for (type = _stats_types; *type; type++) {
+ if (strstr(type_arg, *type))
+ _statstype |= type_flags[type - _stats_types];
+ }
+ if (!_statstype) {
+ log_error("Invalid argument to --statstype, expected: "
+ "\"all\", \"area\", \"region\" or \"group\"");
+ return 0;
+ }
+ } else
+ _statstype = DM_STATS_WALK_REGION | DM_STATS_WALK_GROUP;
+
/*
* Pass the sub-command through to allow a single function to be
* used to implement several distinct sub-commands (e.g. 'report'
@@ -5917,6 +5984,7 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
{"showkeys", 0, &ind, SHOWKEYS_ARG},
{"sort", 1, &ind, SORT_ARG},
{"start", 1, &ind, START_ARG},
+ {"statstype", 1, &ind, STATSTYPE_ARG},
{"table", 1, &ind, TABLE_ARG},
{"target", 1, &ind, TARGET_ARG},
{"tree", 0, &ind, TREE_ARG},
@@ -6225,6 +6293,10 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
_switches[SETUUID_ARG]++;
if (ind == SHOWKEYS_ARG)
_switches[SHOWKEYS_ARG]++;
+ if (ind == STATSTYPE_ARG) {
+ _switches[STATSTYPE_ARG]++;
+ _string_args[STATSTYPE_ARG] = optarg;
+ }
if (ind == TABLE_ARG) {
_switches[TABLE_ARG]++;
if (!(_table = dm_strdup(optarg))) {