diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index b279756ed..9b6bd08e6 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,6 @@ Version 1.02.197 - =================================== + Fix invalid JSON report if using DM_REPORT_OUTPUT_MULTIPLE_TIMES and selection. Propagate ioctl errno from dm_task_run when creating new table line. Add support for group aliases in dmstats. Add support for exit-on file for dmeventd to reduce shutdown delays. diff --git a/device_mapper/libdm-report.c b/device_mapper/libdm-report.c index c3bab4906..602ba51a7 100644 --- a/device_mapper/libdm-report.c +++ b/device_mapper/libdm-report.c @@ -4811,12 +4811,36 @@ static int _output_as_rows(struct dm_report *rh) return 0; } +static struct dm_list *_get_last_displayed_rowh(struct dm_report *rh) +{ + struct dm_list *rowh; + struct row *row; + + /* + * We need to find 'last displayed row', not just 'last row'. + * + * This is because the report may be marked with + * DM_REPORT_OUTPUT_MULTIPLE_TIMES flag. In that case, the report + * may be used more than once and with different selection + * criteria each time. Therefore, such report may also contain + * rows which we do not display on output with current selection + * criteria. + */ + for (rowh = dm_list_last(&rh->rows); rowh; rowh = dm_list_prev(&rh->rows, rowh)) { + row = dm_list_item(rowh, struct row); + if (_should_display_row(row)) + return rowh; + } + + return NULL; +} + static int _output_as_columns(struct dm_report *rh) { struct dm_list *fh, *rowh, *ftmp, *rtmp; struct row *row = NULL; struct dm_report_field *field; - struct dm_list *last_row; + struct dm_list *last_rowh; int do_field_delim; char *line; @@ -4825,7 +4849,7 @@ static int _output_as_columns(struct dm_report *rh) _report_headings(rh); /* Print and clear buffer */ - last_row = dm_list_last(&rh->rows); + last_rowh = _get_last_displayed_rowh(rh); dm_list_iterate_safe(rowh, rtmp, &rh->rows) { row = dm_list_item(rowh, struct row); @@ -4879,7 +4903,7 @@ static int _output_as_columns(struct dm_report *rh) log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG); goto bad; } - if (rowh != last_row && + if (rowh != last_rowh && !dm_pool_grow_object(rh->mem, JSON_SEPARATOR, 0)) { log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG); goto bad; diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c index 5f5f0a773..18cad454f 100644 --- a/libdm/libdm-report.c +++ b/libdm/libdm-report.c @@ -4810,12 +4810,36 @@ static int _output_as_rows(struct dm_report *rh) return 0; } +static struct dm_list *_get_last_displayed_rowh(struct dm_report *rh) +{ + struct dm_list *rowh; + struct row *row; + + /* + * We need to find 'last displayed row', not just 'last row'. + * + * This is because the report may be marked with + * DM_REPORT_OUTPUT_MULTIPLE_TIMES flag. In that case, the report + * may be used more than once and with different selection + * criteria each time. Therefore, such report may also contain + * rows which we do not display on output with current selection + * criteria. + */ + for (rowh = dm_list_last(&rh->rows); rowh; rowh = dm_list_prev(&rh->rows, rowh)) { + row = dm_list_item(rowh, struct row); + if (_should_display_row(row)) + return rowh; + } + + return NULL; +} + static int _output_as_columns(struct dm_report *rh) { struct dm_list *fh, *rowh, *ftmp, *rtmp; struct row *row = NULL; struct dm_report_field *field; - struct dm_list *last_row; + struct dm_list *last_rowh; int do_field_delim; char *line; @@ -4824,7 +4848,7 @@ static int _output_as_columns(struct dm_report *rh) _report_headings(rh); /* Print and clear buffer */ - last_row = dm_list_last(&rh->rows); + last_rowh = _get_last_displayed_rowh(rh); dm_list_iterate_safe(rowh, rtmp, &rh->rows) { row = dm_list_item(rowh, struct row); @@ -4878,7 +4902,7 @@ static int _output_as_columns(struct dm_report *rh) log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG); goto bad; } - if (rowh != last_row && + if (rowh != last_rowh && !dm_pool_grow_object(rh->mem, JSON_SEPARATOR, 0)) { log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG); goto bad;