[lvm-devel] [PATCH] Use dynamic allocation for buffer when reporting tags
Peter Rajnoha
prajnoha at redhat.com
Mon Nov 1 12:04:50 UTC 2010
There's been a patch done recently to use dynamic allocation
for metadata tags buffer which works fine now even with large
set of tags/long tags (rhbz #633033).
But we need the same dynamic allocation when trying to output
the list of tags in reports which still use constant size
buffer and hence makes problems (rhbz #648219).
Peter
---
libdm/libdm-report.c | 48 +++++++++++++++++++++++++++++++++++++++---------
1 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 7631e21..55b8b80 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -757,7 +757,8 @@ static int _report_headings(struct dm_report *rh)
{
struct field_properties *fp;
const char *heading;
- char buf[1024];
+ char *buf;
+ size_t buf_size = 0;
if (rh->flags & RH_HEADINGS_PRINTED)
return 1;
@@ -773,6 +774,18 @@ static int _report_headings(struct dm_report *rh)
return 0;
}
+ dm_list_iterate_items(fp, &rh->field_props) {
+ if (buf_size < fp->width)
+ buf_size = fp->width;
+ }
+ /* Including trailing '\0'! */
+ buf_size++;
+
+ if (!(buf = dm_malloc(buf_size))) {
+ log_error("dm_report: Could not allocate memory for heading buffer.");
+ goto bad;
+ }
+
/* First heading line */
dm_list_iterate_items(fp, &rh->field_props) {
if (fp->flags & FLD_HIDDEN)
@@ -780,7 +793,7 @@ static int _report_headings(struct dm_report *rh)
heading = rh->fields[fp->field_num].heading;
if (rh->flags & DM_REPORT_OUTPUT_ALIGNED) {
- if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
+ if (dm_snprintf(buf, buf_size, "%-*.*s",
fp->width, fp->width, heading) < 0) {
log_error("dm_report: snprintf heading failed");
goto bad;
@@ -806,9 +819,13 @@ static int _report_headings(struct dm_report *rh)
}
log_print("%s", (char *) dm_pool_end_object(rh->mem));
+ dm_free(buf);
+
return 1;
bad:
+ if (buf)
+ dm_free(buf);
dm_pool_abandon_object(rh->mem);
return 0;
}
@@ -892,7 +909,8 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field)
int32_t width;
uint32_t align;
const char *repstr;
- char buf[4096];
+ char *buf;
+ size_t buf_size = 0;
if (rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) {
if (!(field_id = strdup(rh->fields[field->props->field_num].id))) {
@@ -935,25 +953,33 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field)
if (!(align = field->props->flags & DM_REPORT_FIELD_ALIGN_MASK))
align = (field->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ?
DM_REPORT_FIELD_ALIGN_RIGHT : DM_REPORT_FIELD_ALIGN_LEFT;
+
+ /* Including trailing '\0'! */
+ buf_size = width + 1;
+ if (!(buf = dm_malloc(buf_size))) {
+ log_error("dm_report: Could not allocate memory for output line buffer.");
+ return 0;
+ }
+
if (align & DM_REPORT_FIELD_ALIGN_LEFT) {
- if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
+ if (dm_snprintf(buf, buf_size, "%-*.*s",
width, width, repstr) < 0) {
log_error("dm_report: left-aligned snprintf() failed");
- return 0;
+ goto bad;
}
if (!dm_pool_grow_object(rh->mem, buf, width)) {
log_error("dm_report: Unable to extend output line");
- return 0;
+ goto bad;
}
} else if (align & DM_REPORT_FIELD_ALIGN_RIGHT) {
- if (dm_snprintf(buf, sizeof(buf), "%*.*s",
+ if (dm_snprintf(buf, buf_size, "%*.*s",
width, width, repstr) < 0) {
log_error("dm_report: right-aligned snprintf() failed");
- return 0;
+ goto bad;
}
if (!dm_pool_grow_object(rh->mem, buf, width)) {
log_error("dm_report: Unable to extend output line");
- return 0;
+ goto bad;
}
}
}
@@ -966,6 +992,10 @@ static int _output_field(struct dm_report *rh, struct dm_report_field *field)
}
return 1;
+
+bad:
+ dm_free(buf);
+ return 0;
}
static int _output_as_rows(struct dm_report *rh)
More information about the lvm-devel
mailing list