Blame SOURCES/lvm2-2_02_131-dmstats-fixups.patch

a4cb28
 libdm/libdm-stats.c | 223 ++++++++++++++++++++++++++++++----------------------
a4cb28
 tools/dmsetup.c     |   1 +
a4cb28
 2 files changed, 131 insertions(+), 93 deletions(-)
a4cb28
a4cb28
diff --git a/libdm/libdm-stats.c b/libdm/libdm-stats.c
a4cb28
index 93c7760..ee62fe6 100644
a4cb28
--- a/libdm/libdm-stats.c
a4cb28
+++ b/libdm/libdm-stats.c
a4cb28
@@ -144,17 +144,24 @@ struct dm_stats *dm_stats_create(const char *program_id)
a4cb28
 		return_NULL;
a4cb28
 
a4cb28
 	/* FIXME: better hint. */
a4cb28
-	if (!(dms->mem = dm_pool_create("stats_pool", 4096)))
a4cb28
-		goto_bad;
a4cb28
+	if (!(dms->mem = dm_pool_create("stats_pool", 4096))) {
a4cb28
+		dm_free(dms);
a4cb28
+		return_NULL;
a4cb28
+	}
a4cb28
 
a4cb28
 	if (!(dms->hist_mem = dm_pool_create("histogram_pool", hist_hint)))
a4cb28
-		return_0;
a4cb28
+		goto_bad;
a4cb28
 
a4cb28
 	if (!program_id || !strlen(program_id))
a4cb28
 		dms->program_id = _program_id_from_proc();
a4cb28
 	else
a4cb28
 		dms->program_id = dm_strdup(program_id);
a4cb28
 
a4cb28
+	if (!dms->program_id) {
a4cb28
+		dm_pool_destroy(dms->hist_mem);
a4cb28
+		goto_bad;
a4cb28
+	}
a4cb28
+
a4cb28
 	dms->major = -1;
a4cb28
 	dms->minor = -1;
a4cb28
 	dms->name = NULL;
a4cb28
@@ -171,6 +178,7 @@ struct dm_stats *dm_stats_create(const char *program_id)
a4cb28
 	return dms;
a4cb28
 
a4cb28
 bad:
a4cb28
+	dm_pool_destroy(dms->mem);
a4cb28
 	dm_free(dms);
a4cb28
 	return NULL;
a4cb28
 }
a4cb28
@@ -186,15 +194,15 @@ static int _stats_region_present(const struct dm_stats_region *region)
a4cb28
 static void _stats_histograms_destroy(struct dm_pool *mem,
a4cb28
 				      struct dm_stats_region *region)
a4cb28
 {
a4cb28
-	uint64_t n;
a4cb28
-
a4cb28
 	/* Unpopulated handle. */
a4cb28
 	if (!region->counters)
a4cb28
 		return;
a4cb28
 
a4cb28
-	for (n = _nr_areas_region(region) - 1; n; n--)
a4cb28
-		if (region->counters[n].histogram)
a4cb28
-			dm_pool_free(mem, region->counters[n].histogram);
a4cb28
+	/*
a4cb28
+	 * Only the first histogram needs to be freed explicitly.
a4cb28
+	 */
a4cb28
+	if (region->counters[0].histogram)
a4cb28
+		dm_pool_free(mem, region->counters[0].histogram);
a4cb28
 }
a4cb28
 
a4cb28
 static void _stats_region_destroy(struct dm_stats_region *region)
a4cb28
@@ -316,11 +324,54 @@ int dm_stats_driver_supports_histogram(void)
a4cb28
 	return _stats_check_precise_timestamps(NULL);
a4cb28
 }
a4cb28
 
a4cb28
+static int _fill_hist_arg(char *hist_arg, size_t hist_len, uint64_t scale,
a4cb28
+			  struct dm_histogram *bounds)
a4cb28
+{
a4cb28
+	int i, l, len = 0, nr_bins;
a4cb28
+	char *arg = hist_arg;
a4cb28
+	uint64_t value;
a4cb28
+
a4cb28
+	nr_bins = bounds->nr_bins;
a4cb28
+
a4cb28
+	for (i = 0; i < nr_bins; i++) {
a4cb28
+		value = bounds->bins[i].upper / scale;
a4cb28
+		if ((l = dm_snprintf(arg, hist_len - len, FMTu64"%s", value,
a4cb28
+				     (i == (nr_bins - 1)) ? "" : ",")) < 0)
a4cb28
+			return_0;
a4cb28
+		len += l;
a4cb28
+		arg += l;
a4cb28
+	}
a4cb28
+	return 1;
a4cb28
+}
a4cb28
+
a4cb28
+static void *_get_hist_arg(struct dm_histogram *bounds, uint64_t scale,
a4cb28
+			   size_t *len)
a4cb28
+{
a4cb28
+	struct dm_histogram_bin *entry, *bins;
a4cb28
+	size_t hist_len = 1; /* terminating '\0' */
a4cb28
+	double value;
a4cb28
+
a4cb28
+	entry = bins = bounds->bins;
a4cb28
+
a4cb28
+	entry += bounds->nr_bins - 1;
a4cb28
+	while(entry >= bins) {
a4cb28
+		value = (double) (entry--)->upper;
a4cb28
+		/* Use lround to avoid size_t -> double cast warning. */
a4cb28
+		hist_len += 1 + (size_t) lround(log10(value / scale));
a4cb28
+		if (entry != bins)
a4cb28
+			hist_len++; /* ',' */
a4cb28
+	}
a4cb28
+
a4cb28
+	*len = hist_len;
a4cb28
+
a4cb28
+	return dm_zalloc(hist_len);
a4cb28
+}
a4cb28
+
a4cb28
 static char *_build_histogram_arg(struct dm_histogram *bounds, int *precise)
a4cb28
 {
a4cb28
 	struct dm_histogram_bin *entry, *bins;
a4cb28
-	size_t hist_len = 1, len = 0;
a4cb28
-	char *hist_arg, *arg = NULL;
a4cb28
+	size_t hist_len;
a4cb28
+	char *hist_arg;
a4cb28
 	uint64_t scale;
a4cb28
 
a4cb28
 	entry = bins = bounds->bins;
a4cb28
@@ -331,53 +382,37 @@ static char *_build_histogram_arg(struct dm_histogram *bounds, int *precise)
a4cb28
 		return NULL;
a4cb28
 	}
a4cb28
 
a4cb28
+	/* Validate entries and set *precise if precision < 1ms. */
a4cb28
 	entry += bounds->nr_bins - 1;
a4cb28
-	while(entry >= bins) {
a4cb28
-		double value;
a4cb28
+	while (entry >= bins) {
a4cb28
 		if (entry != bins) {
a4cb28
 			if (entry->upper < (entry - 1)->upper) {
a4cb28
 				log_error("Histogram boundaries must be in "
a4cb28
 					  "order of increasing magnitude.");
a4cb28
 				return 0;
a4cb28
 			}
a4cb28
-			hist_len++; /* ',' */
a4cb28
 		}
a4cb28
 
a4cb28
 		/*
a4cb28
 		 * Only enable precise_timestamps automatically if any
a4cb28
 		 * value in the histogram bounds uses precision < 1ms.
a4cb28
 		 */
a4cb28
-		if (!*precise && (entry->upper % NSEC_PER_MSEC))
a4cb28
+		if (((entry--)->upper % NSEC_PER_MSEC) && !*precise)
a4cb28
 			*precise = 1;
a4cb28
-
a4cb28
-		value = (double) (entry--)->upper;
a4cb28
-		/* Use lround to avoid size_t -> double cast warning. */
a4cb28
-		hist_len += 1 + (size_t) lround(log10(value));
a4cb28
 	}
a4cb28
 
a4cb28
-	if (!(hist_arg = dm_zalloc(hist_len))) {
a4cb28
+	scale = (*precise) ? 1 : NSEC_PER_MSEC;
a4cb28
+
a4cb28
+	/* Calculate hist_len and allocate a character buffer. */
a4cb28
+	if (!(hist_arg = _get_hist_arg(bounds, scale, &hist_len))) {
a4cb28
 		log_error("Could not allocate memory for histogram argument.");
a4cb28
 		return 0;
a4cb28
 	}
a4cb28
 
a4cb28
-	arg = hist_arg;
a4cb28
-
a4cb28
-	if (*precise)
a4cb28
-		scale = 1;
a4cb28
-	else
a4cb28
-		scale = (*precise) ? 1 : NSEC_PER_MSEC;
a4cb28
+	/* Fill hist_arg with boundary strings. */
a4cb28
+	if (!_fill_hist_arg(hist_arg, hist_len, scale, bounds))
a4cb28
+		goto_bad;
a4cb28
 
a4cb28
-	for (entry = bins; entry < (bins + bounds->nr_bins); entry++) {
a4cb28
-		uint64_t value;
a4cb28
-		ssize_t l = 0;
a4cb28
-		int last = !(entry < (bins + bounds->nr_bins - 1));
a4cb28
-		value = entry->upper / scale;
a4cb28
-		if ((l = dm_snprintf(arg, hist_len - len, FMTu64"%s", value,
a4cb28
-				     (last) ? "" : ",")) < 0)
a4cb28
-			goto_bad;
a4cb28
-		len += (size_t) l;
a4cb28
-		arg += (size_t) l;
a4cb28
-	}
a4cb28
 	return hist_arg;
a4cb28
 
a4cb28
 bad:
a4cb28
@@ -419,13 +454,13 @@ static int _stats_parse_histogram_spec(struct dm_stats *dms,
a4cb28
 				       const char *histogram)
a4cb28
 {
a4cb28
 	static const char *_valid_chars = "0123456789,";
a4cb28
-	uint64_t scale = region->timescale;
a4cb28
+	uint64_t scale = region->timescale, this_val = 0;
a4cb28
 	struct dm_pool *mem = dms->hist_mem;
a4cb28
 	struct dm_histogram_bin cur;
a4cb28
 	struct dm_histogram hist;
a4cb28
 	int nr_bins = 1;
a4cb28
-	const char *c, *v;
a4cb28
-	char *p;
a4cb28
+	const char *c, *v, *val_start;
a4cb28
+	char *p, *endptr = NULL;
a4cb28
 
a4cb28
 	/* Advance past "histogram:". */
a4cb28
 	histogram = strchr(histogram, ':');
a4cb28
@@ -466,9 +501,8 @@ static int _stats_parse_histogram_spec(struct dm_stats *dms,
a4cb28
 				  histogram);
a4cb28
 			goto bad;
a4cb28
 		} else {
a4cb28
-			const char *val_start = c;
a4cb28
-			char *endptr = NULL;
a4cb28
-			uint64_t this_val = 0;
a4cb28
+			val_start = c;
a4cb28
+			endptr = NULL;
a4cb28
 
a4cb28
 			this_val = strtoull(val_start, &endptr, 10);
a4cb28
 			if (!endptr) {
a4cb28
@@ -592,11 +626,11 @@ static int _stats_parse_list_region(struct dm_stats *dms,
a4cb28
 
a4cb28
 static int _stats_parse_list(struct dm_stats *dms, const char *resp)
a4cb28
 {
a4cb28
-	struct dm_pool *mem = dms->mem;
a4cb28
-	struct dm_stats_region cur;
a4cb28
 	uint64_t max_region = 0, nr_regions = 0;
a4cb28
+	struct dm_stats_region cur, fill;
a4cb28
+	struct dm_pool *mem = dms->mem;
a4cb28
 	FILE *list_rows;
a4cb28
-	/* FIXME: determine correct maximum line length based on kernel format */
a4cb28
+	/* FIXME: use correct maximum line length for kernel format */
a4cb28
 	char line[256];
a4cb28
 
a4cb28
 	if (!resp) {
a4cb28
@@ -631,7 +665,6 @@ static int _stats_parse_list(struct dm_stats *dms, const char *resp)
a4cb28
 
a4cb28
 		/* handle holes in the list of region_ids */
a4cb28
 		if (cur.region_id > max_region) {
a4cb28
-			struct dm_stats_region fill;
a4cb28
 			memset(&fill, 0, sizeof(fill));
a4cb28
 			fill.region_id = DM_STATS_REGION_NOT_PRESENT;
a4cb28
 			do {
a4cb28
@@ -707,54 +740,51 @@ static int _stats_parse_histogram(struct dm_pool *mem, char *hist_str,
a4cb28
 				  struct dm_histogram **histogram,
a4cb28
 				  struct dm_stats_region *region)
a4cb28
 {
a4cb28
+	struct dm_histogram hist, *bounds = region->bounds;
a4cb28
 	static const char *_valid_chars = "0123456789:";
a4cb28
 	int nr_bins = region->bounds->nr_bins;
a4cb28
-	struct dm_histogram hist, *bounds = region->bounds;
a4cb28
+	const char *c, *v, *val_start;
a4cb28
 	struct dm_histogram_bin cur;
a4cb28
-	uint64_t sum = 0;
a4cb28
-	const char *c, *v;
a4cb28
+	uint64_t sum = 0, this_val;
a4cb28
+	char *endptr = NULL;
a4cb28
 	int bin = 0;
a4cb28
 
a4cb28
 	c = hist_str;
a4cb28
 
a4cb28
-	dm_pool_begin_object(mem, sizeof(cur));
a4cb28
+	if (!dm_pool_begin_object(mem, sizeof(cur)))
a4cb28
+		return_0;
a4cb28
 
a4cb28
 	hist.nr_bins = nr_bins;
a4cb28
 
a4cb28
-	dm_pool_grow_object(mem, &hist, sizeof(hist));
a4cb28
+	if (!dm_pool_grow_object(mem, &hist, sizeof(hist)))
a4cb28
+		goto_bad;
a4cb28
 
a4cb28
 	do {
a4cb28
 		memset(&cur, 0, sizeof(cur));
a4cb28
 		for (v = _valid_chars; *v; v++)
a4cb28
 			if (*c == *v)
a4cb28
 				break;
a4cb28
-		if (!*v) {
a4cb28
-			stack;
a4cb28
+		if (!*v)
a4cb28
 			goto badchar;
a4cb28
-		}
a4cb28
 
a4cb28
-		if (*c == ',') {
a4cb28
-			log_error("Invalid histogram: %s", hist_str);
a4cb28
-			return 0;
a4cb28
-		} else {
a4cb28
-			const char *val_start = c;
a4cb28
-			char *endptr = NULL;
a4cb28
-			uint64_t this_val = 0;
a4cb28
+		if (*c == ',')
a4cb28
+			goto badchar;
a4cb28
+		else {
a4cb28
+			val_start = c;
a4cb28
+			endptr = NULL;
a4cb28
 
a4cb28
 			this_val = strtoull(val_start, &endptr, 10);
a4cb28
 			if (!endptr) {
a4cb28
 				log_error("Could not parse histogram value.");
a4cb28
-				return 0;
a4cb28
+				goto bad;
a4cb28
 			}
a4cb28
 			c = endptr; /* Advance to colon, or end. */
a4cb28
 
a4cb28
 			if (*c == ':')
a4cb28
 				c++;
a4cb28
-			else if (*c & (*c != '\n')) {
a4cb28
+			else if (*c & (*c != '\n'))
a4cb28
 				/* Expected ':', '\n', or NULL. */
a4cb28
-				stack;
a4cb28
 				goto badchar;
a4cb28
-			}
a4cb28
 
a4cb28
 			if (*c == ':')
a4cb28
 				c++;
a4cb28
@@ -763,7 +793,8 @@ static int _stats_parse_histogram(struct dm_pool *mem, char *hist_str,
a4cb28
 			cur.count = this_val;
a4cb28
 			sum += this_val;
a4cb28
 
a4cb28
-			dm_pool_grow_object(mem, &cur, sizeof(cur));
a4cb28
+			if (!dm_pool_grow_object(mem, &cur, sizeof(cur)))
a4cb28
+				goto_bad;
a4cb28
 
a4cb28
 			bin++;
a4cb28
 		}
a4cb28
@@ -778,6 +809,8 @@ static int _stats_parse_histogram(struct dm_pool *mem, char *hist_str,
a4cb28
 
a4cb28
 badchar:
a4cb28
 	log_error("Invalid character in histogram data: '%c' (0x%x)", *c, *c);
a4cb28
+bad:
a4cb28
+	dm_pool_abandon_object(mem);
a4cb28
 	return 0;
a4cb28
 }
a4cb28
 
a4cb28
@@ -786,8 +819,8 @@ static int _stats_parse_region(struct dm_stats *dms, const char *resp,
a4cb28
 			       uint64_t timescale)
a4cb28
 {
a4cb28
 	struct dm_histogram *hist = NULL;
a4cb28
-	struct dm_stats_counters cur;
a4cb28
 	struct dm_pool *mem = dms->mem;
a4cb28
+	struct dm_stats_counters cur;
a4cb28
 	FILE *stats_rows = NULL;
a4cb28
 	uint64_t start, len;
a4cb28
 	char row[256];
a4cb28
@@ -1040,12 +1073,12 @@ static int _stats_create_region(struct dm_stats *dms, uint64_t *region_id,
a4cb28
 				int precise, const char *hist_arg,
a4cb28
 				const char *program_id,	const char *aux_data)
a4cb28
 {
a4cb28
-	struct dm_task *dmt = NULL;
a4cb28
-	char msg[1024], range[64];
a4cb28
 	const char *err_fmt = "Could not prepare @stats_create %s.";
a4cb28
 	const char *precise_str = PRECISE_ARG;
a4cb28
 	const char *resp, *opt_args = NULL;
a4cb28
-	int r = 0, nr_opt = 0; /* number of optional args. */
a4cb28
+	char msg[1024], range[64], *endptr = NULL;
a4cb28
+	struct dm_task *dmt = NULL;
a4cb28
+	int r = 0, nr_opt = 0;
a4cb28
 
a4cb28
 	if (!_stats_bound(dms))
a4cb28
 		return_0;
a4cb28
@@ -1105,7 +1138,6 @@ static int _stats_create_region(struct dm_stats *dms, uint64_t *region_id,
a4cb28
 	}
a4cb28
 
a4cb28
 	if (region_id) {
a4cb28
-		char *endptr = NULL;
a4cb28
 		*region_id = strtoull(resp, &endptr, 10);
a4cb28
 		if (resp == endptr)
a4cb28
 			goto_out;
a4cb28
@@ -1195,11 +1227,11 @@ static struct dm_task *_stats_print_region(struct dm_stats *dms,
a4cb28
 				    uint64_t region_id, unsigned start_line,
a4cb28
 				    unsigned num_lines, unsigned clear)
a4cb28
 {
a4cb28
-	struct dm_task *dmt = NULL;
a4cb28
 	/* @stats_print[_clear] <region_id> [<start_line> <num_lines>] */
a4cb28
 	const char *clear_str = "_clear", *lines_fmt = "%u %u";
a4cb28
 	const char *msg_fmt = "@stats_print%s " FMTu64 " %s";
a4cb28
 	const char *err_fmt = "Could not prepare @stats_print %s.";
a4cb28
+	struct dm_task *dmt = NULL;
a4cb28
 	char msg[1024], lines[64];
a4cb28
 
a4cb28
 	if (start_line || num_lines)
a4cb28
@@ -1292,6 +1324,8 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id,
a4cb28
 		      uint64_t region_id)
a4cb28
 {
a4cb28
 	int all_regions = (region_id == DM_STATS_REGIONS_ALL);
a4cb28
+	struct dm_task *dmt = NULL; /* @stats_print task */
a4cb28
+	const char *resp;
a4cb28
 
a4cb28
 	if (!_stats_bound(dms))
a4cb28
 		return_0;
a4cb28
@@ -1311,9 +1345,6 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id,
a4cb28
 
a4cb28
 	dm_stats_walk_start(dms);
a4cb28
 	do {
a4cb28
-		struct dm_task *dmt = NULL; /* @stats_print task */
a4cb28
-		const char *resp;
a4cb28
-
a4cb28
 		region_id = (all_regions)
a4cb28
 			     ? dm_stats_get_current_region(dms) : region_id;
a4cb28
 
a4cb28
@@ -1967,10 +1998,12 @@ static struct dm_histogram *_alloc_dm_histogram(int nr_bins)
a4cb28
 struct dm_histogram *dm_histogram_bounds_from_string(const char *bounds_str)
a4cb28
 {
a4cb28
 	static const char *_valid_chars = "0123456789,muns";
a4cb28
-	struct dm_histogram *dmh;
a4cb28
+	uint64_t this_val = 0, mult = 1;
a4cb28
+	const char *c, *v, *val_start;
a4cb28
 	struct dm_histogram_bin *cur;
a4cb28
-	const char *c, *v;
a4cb28
+	struct dm_histogram *dmh;
a4cb28
 	int nr_entries = 1;
a4cb28
+	char *endptr;
a4cb28
 
a4cb28
 	c = bounds_str;
a4cb28
 
a4cb28
@@ -2003,9 +2036,8 @@ struct dm_histogram *dm_histogram_bounds_from_string(const char *bounds_str)
a4cb28
 				  bounds_str);
a4cb28
 			goto bad;
a4cb28
 		} else {
a4cb28
-			const char *val_start = c;
a4cb28
-			char *endptr = NULL;
a4cb28
-			uint64_t this_val = 0, mult = 1;
a4cb28
+			val_start = c;
a4cb28
+			endptr = NULL;
a4cb28
 
a4cb28
 			this_val = strtoull(val_start, &endptr, 10);
a4cb28
 			if (!endptr) {
a4cb28
@@ -2058,10 +2090,10 @@ bad:
a4cb28
 
a4cb28
 struct dm_histogram *dm_histogram_bounds_from_uint64(const uint64_t *bounds)
a4cb28
 {
a4cb28
-	struct dm_histogram *dmh;
a4cb28
+	const uint64_t *entry = bounds;
a4cb28
 	struct dm_histogram_bin *cur;
a4cb28
+	struct dm_histogram *dmh;
a4cb28
 	int nr_entries = 1;
a4cb28
-	const uint64_t *entry = bounds;
a4cb28
 
a4cb28
 	if (!bounds || !bounds[0]) {
a4cb28
 		log_error("Could not parse empty histogram bounds array");
a4cb28
@@ -2113,6 +2145,7 @@ void dm_histogram_bounds_destroy(struct dm_histogram *bounds)
a4cb28
  */
a4cb28
 static void _scale_bound_value_to_suffix(uint64_t *bound, const char **suffix)
a4cb28
 {
a4cb28
+	*suffix = "ns";
a4cb28
 	if (!(*bound % NSEC_PER_SEC)) {
a4cb28
 		*bound /= NSEC_PER_SEC;
a4cb28
 		*suffix = "s";
a4cb28
@@ -2191,12 +2224,14 @@ const char *dm_histogram_to_string(const struct dm_histogram *dmh, int bin,
a4cb28
 				   int width, int flags)
a4cb28
 {
a4cb28
 	int minwidth, bounds, values, start, last;
a4cb28
-	uint64_t lower, upper; /* bounds of the current bin. */
a4cb28
+	uint64_t lower, upper, val_u64; /* bounds of the current bin. */
a4cb28
 	/* Use the histogram pool for string building. */
a4cb28
 	struct dm_pool *mem = dmh->dms->hist_mem;
a4cb28
 	char buf[64], bounds_buf[64];
a4cb28
 	const char *sep = "";
a4cb28
+	int bounds_width;
a4cb28
 	ssize_t len = 0;
a4cb28
+	float val_flt;
a4cb28
 
a4cb28
 	bounds = flags & DM_HISTOGRAM_BOUNDS_MASK;
a4cb28
 	values = flags & DM_HISTOGRAM_VALUES;
a4cb28
@@ -2222,12 +2257,11 @@ const char *dm_histogram_to_string(const struct dm_histogram *dmh, int bin,
a4cb28
 	/* Set bounds string to the empty string. */
a4cb28
 	bounds_buf[0] = '\0';
a4cb28
 
a4cb28
-	dm_pool_begin_object(mem, 64);
a4cb28
+	if (!dm_pool_begin_object(mem, 64))
a4cb28
+		return_0;
a4cb28
 
a4cb28
 	for (bin = start; bin <= last; bin++) {
a4cb28
 		if (bounds) {
a4cb28
-			int bounds_width;
a4cb28
-
a4cb28
 			/* Default bounds width depends on time suffixes. */
a4cb28
 			bounds_width = (!(flags & DM_HISTOGRAM_SUFFIX))
a4cb28
 					? BOUND_WIDTH_NOSUFFIX
a4cb28
@@ -2260,15 +2294,14 @@ const char *dm_histogram_to_string(const struct dm_histogram *dmh, int bin,
a4cb28
 
a4cb28
 		if (flags & DM_HISTOGRAM_PERCENT) {
a4cb28
 			dm_percent_t pr;
a4cb28
-			float value;
a4cb28
 			pr = dm_histogram_get_bin_percent(dmh, bin);
a4cb28
-			value = dm_percent_to_float(pr);
a4cb28
+			val_flt = dm_percent_to_float(pr);
a4cb28
 			len = dm_snprintf(buf, sizeof(buf), "%s%*.2f%%%s",
a4cb28
-					  bounds_buf, width, value, sep);
a4cb28
+					  bounds_buf, width, val_flt, sep);
a4cb28
 		} else if (values) {
a4cb28
-			uint64_t value = dmh->bins[bin].count;
a4cb28
+			val_u64 = dmh->bins[bin].count;
a4cb28
 			len = dm_snprintf(buf, sizeof(buf), "%s%*"PRIu64"%s",
a4cb28
-					  bounds_buf, width, value, sep);
a4cb28
+					  bounds_buf, width, val_u64, sep);
a4cb28
 		} else if (bounds)
a4cb28
 			len = dm_snprintf(buf, sizeof(buf), "%s%s", bounds_buf,
a4cb28
 					  sep);
a4cb28
@@ -2277,9 +2310,13 @@ const char *dm_histogram_to_string(const struct dm_histogram *dmh, int bin,
a4cb28
 			goto_bad;
a4cb28
 
a4cb28
 		width = minwidth; /* re-set histogram column width. */
a4cb28
-		dm_pool_grow_object(mem, buf, (size_t) len);
a4cb28
+		if (!dm_pool_grow_object(mem, buf, (size_t) len))
a4cb28
+			goto_bad;
a4cb28
 	}
a4cb28
-	dm_pool_grow_object(mem, "\0", 1);
a4cb28
+
a4cb28
+	if (!dm_pool_grow_object(mem, "\0", 1))
a4cb28
+		goto_bad;
a4cb28
+
a4cb28
 	return (const char *) dm_pool_end_object(mem);
a4cb28
 
a4cb28
 bad:
a4cb28
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
a4cb28
index 61ad5a9..8b7ad74 100644
a4cb28
--- a/tools/dmsetup.c
a4cb28
+++ b/tools/dmsetup.c
a4cb28
@@ -4674,6 +4674,7 @@ static int _do_stats_create_regions(struct dm_stats *dms,
a4cb28
 		return_0;
a4cb28
 
a4cb28
 	if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) {
a4cb28
+		dm_histogram_bounds_destroy(bounds);
a4cb28
 		dm_stats_destroy(dms);
a4cb28
 		return_0;
a4cb28
 	}