summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryn M. Reeves <bmr@redhat.com>2016-07-07 13:53:06 +0100
committerBryn M. Reeves <bmr@redhat.com>2016-07-08 17:27:52 +0100
commitbd1f4987eb954705e6ba8997ac37de025074e539 (patch)
tree1dc5fd341e7476579ba6ce5acc5e1a0d7513cca6
parentdb63587ce2473f3ceaea1c8ccc911eb3f1cacd0f (diff)
downloadlvm2-bd1f4987eb954705e6ba8997ac37de025074e539.tar.gz
dmstats: group regions by default with --segments
Grouping is also useful in combination with --segments: creating a group allows both individual segment data and data for the device as a whole to be presented in the same report. Support grouping for 'create --segments' in the same manner as for 'create --filemap'; group regions by default, applying an optional alias specified with --alias, unless the user specifies --nogroup.
-rw-r--r--tools/dmsetup.c83
1 files changed, 76 insertions, 7 deletions
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index b31788c64..eb7c83a24 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -4768,6 +4768,56 @@ static uint64_t _nr_areas_from_step(uint64_t len, int64_t step)
return (len / step) + !!(len % (uint64_t) step);
}
+/* maximum length of a string representation of an integer */
+#define max_int_strlen(i) (strlen(#i))
+#define MAX_UINT64_STRLEN max_int_strlen(UINT64_MAX)
+static int _stats_group_segments(struct dm_stats *dms, uint64_t *region_ids,
+ int count, const char *alias)
+{
+ /* NULL, commas, and count * region_id */
+ size_t bufsize = 1 + count + count * MAX_UINT64_STRLEN;
+ char *this_region, *regions = NULL;
+ uint64_t group_id;
+ int r, i;
+
+ this_region = regions = dm_malloc(bufsize);
+
+ if (!regions) {
+ log_error("Could not allocate memory for region_id table.");
+ return 0;
+ }
+
+ for (i = 0; i < count; i++) {
+ /*
+ * We don't expect large numbers of segments (compared to e.g.
+ * --filemap): use a fixed-size buffer based on the number of
+ * region identifiers and do not collapse continuous ranges
+ * of identifiers in the group descriptor argument.
+ */
+ r = dm_snprintf(this_region, bufsize, FMTu64 "%s", region_ids[i],
+ (i < (count - 1)) ? "," : "");
+ if (r < 0)
+ goto_bad;
+ this_region += r;
+ bufsize -= r;
+ }
+
+ /* refresh handle */
+ if (!(r = dm_stats_list(dms, NULL)))
+ goto bad;
+
+ if ((r = dm_stats_create_group(dms, regions, alias, &group_id)))
+ printf("Grouped regions %s as group ID " FMTu64 "%s%s\n",
+ regions, group_id, (alias) ? " with alias " : "",
+ (alias) ? : "");
+ else
+ log_error("Failed to create group for regions %s", regions);
+
+bad:
+ dm_free(regions);
+ return r;
+}
+
/*
* Create a single region starting at start and spanning len sectors,
* or, if the segments argument is no-zero create one region for each
@@ -4784,8 +4834,9 @@ static int _do_stats_create_regions(struct dm_stats *dms,
{
uint64_t this_start = 0, this_len = len, region_id = UINT64_C(0);
const char *devname = NULL, *histogram = _string_args[BOUNDS_ARG];
- int r = 0, precise = _switches[PRECISE_ARG];
+ int r = 0, count = 0, precise = _switches[PRECISE_ARG];
struct dm_histogram *bounds = NULL; /* histogram bounds */
+ uint64_t *region_ids = NULL; /* segments */
char *target_type, *params; /* unused */
struct dm_task *dmt;
struct dm_info info;
@@ -4794,6 +4845,12 @@ static int _do_stats_create_regions(struct dm_stats *dms,
if (histogram && !(bounds = dm_histogram_bounds_from_string(histogram)))
return_0;
+ if (_switches[ALIAS_ARG] && _switches[NOGROUP_ARG]) {
+ log_error("Cannot set alias with --nogroup.");
+ dm_stats_destroy(dms);
+ return 0;
+ }
+
if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) {
dm_histogram_bounds_destroy(bounds);
dm_stats_destroy(dms);
@@ -4818,6 +4875,11 @@ static int _do_stats_create_regions(struct dm_stats *dms,
if (!(devname = dm_task_get_name(dmt)))
goto_out;
+ if (!segments || (info.target_count == 1))
+ region_ids = &region_id;
+ else
+ region_ids = dm_malloc(info.target_count * sizeof(*region_ids));
+
do {
uint64_t segment_start, segment_len;
next = dm_get_next_target(dmt, next, &segment_start, &segment_len,
@@ -4838,10 +4900,10 @@ static int _do_stats_create_regions(struct dm_stats *dms,
*/
this_start = (segments) ? segment_start : start;
this_len = (segments) ? segment_len : this_len;
- if (!dm_stats_create_region(dms, &region_id,
- this_start, this_len, step,
- precise, bounds,
- program_id, user_data)) {
+ if (!(r = dm_stats_create_region(dms, &region_ids[count],
+ this_start, this_len, step,
+ precise, bounds,
+ program_id, user_data))) {
log_error("%s: Could not create statistics region.",
devname);
goto out;
@@ -4849,12 +4911,19 @@ static int _do_stats_create_regions(struct dm_stats *dms,
printf("%s: Created new region with "FMTu64" area(s) as "
"region ID "FMTu64"\n", devname,
- _nr_areas_from_step(this_len, step), region_id);
+ _nr_areas_from_step(this_len, step),
+ region_ids[count++]);
}
} while (next);
- r = 1;
+
+ if (!_switches[NOGROUP_ARG] && segments)
+ r = _stats_group_segments(dms, region_ids, count,
+ _string_args[ALIAS_ARG]);
out:
+ if (region_ids != &region_id)
+ dm_free(region_ids);
+
dm_task_destroy(dmt);
dm_stats_destroy(dms);
dm_histogram_bounds_destroy(bounds);