xref: /netbsd/external/gpl2/lvm2/dist/lib/report/report.c (revision a0b1c410)
1 /*	$NetBSD: report.c,v 1.2 2011/05/30 16:03:02 joerg Exp $	*/
2 
3 /*
4  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
5  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
6  *
7  * This file is part of LVM2.
8  *
9  * This copyrighted material is made available to anyone wishing to use,
10  * modify, copy, or redistribute it subject to the terms and conditions
11  * of the GNU Lesser General Public License v.2.1.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, write to the Free Software Foundation,
15  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17 
18 #include "lib.h"
19 #include "metadata.h"
20 #include "report.h"
21 #include "toolcontext.h"
22 #include "lvm-string.h"
23 #include "display.h"
24 #include "activate.h"
25 #include "segtype.h"
26 #include "str_list.h"
27 #include "lvmcache.h"
28 
29 #include <stddef.h> /* offsetof() */
30 
31 struct lvm_report_object {
32 	struct volume_group *vg;
33 	struct logical_volume *lv;
34 	struct physical_volume *pv;
35 	struct lv_segment *seg;
36 	struct pv_segment *pvseg;
37 };
38 
_alloc_policy_char(alloc_policy_t alloc)39 static char _alloc_policy_char(alloc_policy_t alloc)
40 {
41 	switch (alloc) {
42 	case ALLOC_CONTIGUOUS:
43 		return 'c';
44 	case ALLOC_CLING:
45 		return 'l';
46 	case ALLOC_NORMAL:
47 		return 'n';
48 	case ALLOC_ANYWHERE:
49 		return 'a';
50 	default:
51 		return 'i';
52 	}
53 }
54 
55 static const uint64_t _minusone = UINT64_C(-1);
56 
57 /*
58  * Data-munging functions to prepare each data type for display and sorting
59  */
_string_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))60 static int _string_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
61 			struct dm_report_field *field,
62 			const void *data, void *private __attribute((unused)))
63 {
64 	return dm_report_field_string(rh, field, (const char **) data);
65 }
66 
_dev_name_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))67 static int _dev_name_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
68 			  struct dm_report_field *field,
69 			  const void *data, void *private __attribute((unused)))
70 {
71 	const char *name = dev_name(*(const struct device **) data);
72 
73 	return dm_report_field_string(rh, field, &name);
74 }
75 
_format_pvsegs(struct dm_pool * mem,struct dm_report_field * field,const void * data,int range_format)76 static int _format_pvsegs(struct dm_pool *mem, struct dm_report_field *field,
77 			  const void *data, int range_format)
78 {
79 	const struct lv_segment *seg = (const struct lv_segment *) data;
80 	unsigned int s;
81 	const char *name = NULL;
82 	uint32_t extent = 0;
83 	char extent_str[32];
84 
85 	if (!dm_pool_begin_object(mem, 256)) {
86 		log_error("dm_pool_begin_object failed");
87 		return 0;
88 	}
89 
90 	for (s = 0; s < seg->area_count; s++) {
91 		switch (seg_type(seg, s)) {
92 		case AREA_LV:
93 			name = seg_lv(seg, s)->name;
94 			extent = seg_le(seg, s);
95 			break;
96 		case AREA_PV:
97 			name = dev_name(seg_dev(seg, s));
98 			extent = seg_pe(seg, s);
99 			break;
100 		case AREA_UNASSIGNED:
101 			name = "unassigned";
102 			extent = 0;
103 		}
104 
105 		if (!dm_pool_grow_object(mem, name, strlen(name))) {
106 			log_error("dm_pool_grow_object failed");
107 			return 0;
108 		}
109 
110 		if (dm_snprintf(extent_str, sizeof(extent_str),
111 				"%s%" PRIu32 "%s",
112 				range_format ? ":" : "(", extent,
113 				range_format ? "-"  : ")") < 0) {
114 			log_error("Extent number dm_snprintf failed");
115 			return 0;
116 		}
117 		if (!dm_pool_grow_object(mem, extent_str, strlen(extent_str))) {
118 			log_error("dm_pool_grow_object failed");
119 			return 0;
120 		}
121 
122 		if (range_format) {
123 			if (dm_snprintf(extent_str, sizeof(extent_str),
124 					"%" PRIu32, extent + seg->area_len - 1) < 0) {
125 				log_error("Extent number dm_snprintf failed");
126 				return 0;
127 			}
128 			if (!dm_pool_grow_object(mem, extent_str, strlen(extent_str))) {
129 				log_error("dm_pool_grow_object failed");
130 				return 0;
131 			}
132 		}
133 
134 		if ((s != seg->area_count - 1) &&
135 		    !dm_pool_grow_object(mem, range_format ? " " : ",", 1)) {
136 			log_error("dm_pool_grow_object failed");
137 			return 0;
138 		}
139 	}
140 
141 	if (!dm_pool_grow_object(mem, "\0", 1)) {
142 		log_error("dm_pool_grow_object failed");
143 		return 0;
144 	}
145 
146 	dm_report_field_set_value(field, dm_pool_end_object(mem), NULL);
147 
148 	return 1;
149 }
150 
_devices_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))151 static int _devices_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
152 			 struct dm_report_field *field,
153 			 const void *data, void *private __attribute((unused)))
154 {
155 	return _format_pvsegs(mem, field, data, 0);
156 }
157 
_peranges_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))158 static int _peranges_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
159 			  struct dm_report_field *field,
160 			  const void *data, void *private __attribute((unused)))
161 {
162 	return _format_pvsegs(mem, field, data, 1);
163 }
164 
_tags_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))165 static int _tags_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
166 		      struct dm_report_field *field,
167 		      const void *data, void *private __attribute((unused)))
168 {
169 	const struct dm_list *tags = (const struct dm_list *) data;
170 	struct str_list *sl;
171 
172 	if (!dm_pool_begin_object(mem, 256)) {
173 		log_error("dm_pool_begin_object failed");
174 		return 0;
175 	}
176 
177 	dm_list_iterate_items(sl, tags) {
178 		if (!dm_pool_grow_object(mem, sl->str, strlen(sl->str)) ||
179 		    (sl->list.n != tags && !dm_pool_grow_object(mem, ",", 1))) {
180 			log_error("dm_pool_grow_object failed");
181 			return 0;
182 		}
183 	}
184 
185 	if (!dm_pool_grow_object(mem, "\0", 1)) {
186 		log_error("dm_pool_grow_object failed");
187 		return 0;
188 	}
189 
190 	dm_report_field_set_value(field, dm_pool_end_object(mem), NULL);
191 
192 	return 1;
193 }
194 
_modules_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)195 static int _modules_disp(struct dm_report *rh, struct dm_pool *mem,
196 			 struct dm_report_field *field,
197 			 const void *data, void *private)
198 {
199 	const struct logical_volume *lv = (const struct logical_volume *) data;
200 	struct dm_list *modules;
201 
202 	if (!(modules = str_list_create(mem))) {
203 		log_error("modules str_list allocation failed");
204 		return 0;
205 	}
206 
207 	if (!list_lv_modules(mem, lv, modules))
208 		return_0;
209 
210 	return _tags_disp(rh, mem, field, modules, private);
211 }
212 
_vgfmt_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)213 static int _vgfmt_disp(struct dm_report *rh, struct dm_pool *mem,
214 		       struct dm_report_field *field,
215 		       const void *data, void *private)
216 {
217 	const struct volume_group *vg = (const struct volume_group *) data;
218 
219 	if (!vg->fid) {
220 		dm_report_field_set_value(field, "", NULL);
221 		return 1;
222 	}
223 
224 	return _string_disp(rh, mem, field, &vg->fid->fmt->name, private);
225 }
226 
_pvfmt_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)227 static int _pvfmt_disp(struct dm_report *rh, struct dm_pool *mem,
228 		       struct dm_report_field *field,
229 		       const void *data, void *private)
230 {
231 	const struct physical_volume *pv =
232 	    (const struct physical_volume *) data;
233 
234 	if (!pv->fmt) {
235 		dm_report_field_set_value(field, "", NULL);
236 		return 1;
237 	}
238 
239 	return _string_disp(rh, mem, field, &pv->fmt->name, private);
240 }
241 
_lvkmaj_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))242 static int _lvkmaj_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
243 			struct dm_report_field *field,
244 			const void *data, void *private __attribute((unused)))
245 {
246 	const struct logical_volume *lv = (const struct logical_volume *) data;
247 	struct lvinfo info;
248 
249 	if (lv_info(lv->vg->cmd, lv, &info, 0, 0) && info.exists)
250 		return dm_report_field_int(rh, field, &info.major);
251 
252 	return dm_report_field_uint64(rh, field, &_minusone);
253 }
254 
_lvkmin_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))255 static int _lvkmin_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
256 			struct dm_report_field *field,
257 			const void *data, void *private __attribute((unused)))
258 {
259 	const struct logical_volume *lv = (const struct logical_volume *) data;
260 	struct lvinfo info;
261 
262 	if (lv_info(lv->vg->cmd, lv, &info, 0, 0) && info.exists)
263 		return dm_report_field_int(rh, field, &info.minor);
264 
265 	return dm_report_field_uint64(rh, field, &_minusone);
266 }
267 
_lv_mimage_in_sync(const struct logical_volume * lv)268 static int _lv_mimage_in_sync(const struct logical_volume *lv)
269 {
270 	float percent;
271 	percent_range_t percent_range;
272 	struct lv_segment *mirror_seg = find_mirror_seg(first_seg(lv));
273 
274 	if (!(lv->status & MIRROR_IMAGE) || !mirror_seg)
275 		return_0;
276 
277 	if (!lv_mirror_percent(lv->vg->cmd, mirror_seg->lv, 0, &percent,
278 			       &percent_range, NULL))
279 		return_0;
280 
281 	return (percent_range == PERCENT_100) ? 1 : 0;
282 }
283 
_lvstatus_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))284 static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
285 			  struct dm_report_field *field,
286 			  const void *data, void *private __attribute((unused)))
287 {
288 	const struct logical_volume *lv = (const struct logical_volume *) data;
289 	struct lvinfo info;
290 	char *repstr;
291 	float snap_percent;
292 	percent_range_t percent_range;
293 
294 	if (!(repstr = dm_pool_zalloc(mem, 7))) {
295 		log_error("dm_pool_alloc failed");
296 		return 0;
297 	}
298 
299 	/* Blank if this is a "free space" LV. */
300 	if (!*lv->name)
301 		goto out;
302 
303 	if (lv->status & PVMOVE)
304 		repstr[0] = 'p';
305 	else if (lv->status & CONVERTING)
306 		repstr[0] = 'c';
307 	else if (lv->status & VIRTUAL)
308 		repstr[0] = 'v';
309 	/* Origin takes precedence over Mirror */
310 	else if (lv_is_origin(lv))
311 		repstr[0] = 'o';
312 	else if (lv->status & MIRRORED) {
313 		if (lv->status & MIRROR_NOTSYNCED)
314 			repstr[0] = 'M';
315 		else
316 			repstr[0] = 'm';
317 	}else if (lv->status & MIRROR_IMAGE)
318 		if (_lv_mimage_in_sync(lv))
319 			repstr[0] = 'i';
320 		else
321 			repstr[0] = 'I';
322 	else if (lv->status & MIRROR_LOG)
323 		repstr[0] = 'l';
324 	else if (lv_is_cow(lv))
325 		repstr[0] = 's';
326 	else
327 		repstr[0] = '-';
328 
329 	if (lv->status & PVMOVE)
330 		repstr[1] = '-';
331 	else if (lv->status & LVM_WRITE)
332 		repstr[1] = 'w';
333 	else if (lv->status & LVM_READ)
334 		repstr[1] = 'r';
335 	else
336 		repstr[1] = '-';
337 
338 	repstr[2] = _alloc_policy_char(lv->alloc);
339 
340 	if (lv->status & LOCKED)
341 		repstr[2] = toupper(repstr[2]);
342 
343 	if (lv->status & FIXED_MINOR)
344 		repstr[3] = 'm';	/* Fixed Minor */
345 	else
346 		repstr[3] = '-';
347 
348 	if (lv_info(lv->vg->cmd, lv, &info, 1, 0) && info.exists) {
349 		if (info.suspended)
350 			repstr[4] = 's';	/* Suspended */
351 		else if (info.live_table)
352 			repstr[4] = 'a';	/* Active */
353 		else if (info.inactive_table)
354 			repstr[4] = 'i';	/* Inactive with table */
355 		else
356 			repstr[4] = 'd';	/* Inactive without table */
357 
358 		/* Snapshot dropped? */
359 		if (info.live_table && lv_is_cow(lv) &&
360 		    (!lv_snapshot_percent(lv, &snap_percent, &percent_range) ||
361 		     percent_range == PERCENT_INVALID)) {
362 			repstr[0] = toupper(repstr[0]);
363 			if (info.suspended)
364 				repstr[4] = 'S'; /* Susp Inv snapshot */
365 			else
366 				repstr[4] = 'I'; /* Invalid snapshot */
367 		}
368 
369 		if (info.open_count)
370 			repstr[5] = 'o';	/* Open */
371 		else
372 			repstr[5] = '-';
373 	} else {
374 		repstr[4] = '-';
375 		repstr[5] = '-';
376 	}
377 
378 out:
379 	dm_report_field_set_value(field, repstr, NULL);
380 	return 1;
381 }
382 
_pvstatus_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))383 static int _pvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
384 			  struct dm_report_field *field,
385 			  const void *data, void *private __attribute((unused)))
386 {
387 	const uint32_t status = *(const uint32_t *) data;
388 	char *repstr;
389 
390 	if (!(repstr = dm_pool_zalloc(mem, 3))) {
391 		log_error("dm_pool_alloc failed");
392 		return 0;
393 	}
394 
395 	if (status & ALLOCATABLE_PV)
396 		repstr[0] = 'a';
397 	else
398 		repstr[0] = '-';
399 
400 	if (status & EXPORTED_VG)
401 		repstr[1] = 'x';
402 	else
403 		repstr[1] = '-';
404 
405 	dm_report_field_set_value(field, repstr, NULL);
406 	return 1;
407 }
408 
_vgstatus_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))409 static int _vgstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
410 			  struct dm_report_field *field,
411 			  const void *data, void *private __attribute((unused)))
412 {
413 	const struct volume_group *vg = (const struct volume_group *) data;
414 	char *repstr;
415 
416 	if (!(repstr = dm_pool_zalloc(mem, 7))) {
417 		log_error("dm_pool_alloc failed");
418 		return 0;
419 	}
420 
421 	if (vg->status & LVM_WRITE)
422 		repstr[0] = 'w';
423 	else
424 		repstr[0] = 'r';
425 
426 	if (vg_is_resizeable(vg))
427 		repstr[1] = 'z';
428 	else
429 		repstr[1] = '-';
430 
431 	if (vg_is_exported(vg))
432 		repstr[2] = 'x';
433 	else
434 		repstr[2] = '-';
435 
436 	if (vg_missing_pv_count(vg))
437 		repstr[3] = 'p';
438 	else
439 		repstr[3] = '-';
440 
441 	repstr[4] = _alloc_policy_char(vg->alloc);
442 
443 	if (vg_is_clustered(vg))
444 		repstr[5] = 'c';
445 	else
446 		repstr[5] = '-';
447 
448 	dm_report_field_set_value(field, repstr, NULL);
449 	return 1;
450 }
451 
_segtype_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))452 static int _segtype_disp(struct dm_report *rh __attribute((unused)),
453 			 struct dm_pool *mem __attribute((unused)),
454 			 struct dm_report_field *field,
455 			 const void *data, void *private __attribute((unused)))
456 {
457 	const struct lv_segment *seg = (const struct lv_segment *) data;
458 
459 	if (seg->area_count == 1) {
460 		dm_report_field_set_value(field, "linear", NULL);
461 		return 1;
462 	}
463 
464 	dm_report_field_set_value(field, seg->segtype->ops->name(seg), NULL);
465 	return 1;
466 }
467 
_loglv_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))468 static int _loglv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
469 		       struct dm_report_field *field,
470 		       const void *data, void *private __attribute((unused)))
471 {
472 	const struct logical_volume *lv = (const struct logical_volume *) data;
473 	struct lv_segment *seg;
474 
475 	dm_list_iterate_items(seg, &lv->segments) {
476 		if (!seg_is_mirrored(seg) || !seg->log_lv)
477 			continue;
478 		return dm_report_field_string(rh, field,
479 					      (const char **) &seg->log_lv->name);
480 	}
481 
482 	dm_report_field_set_value(field, "", NULL);
483 	return 1;
484 }
485 
_lvname_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))486 static int _lvname_disp(struct dm_report *rh, struct dm_pool *mem,
487 			struct dm_report_field *field,
488 			const void *data, void *private __attribute((unused)))
489 {
490 	const struct logical_volume *lv = (const struct logical_volume *) data;
491 	char *repstr, *lvname;
492 	size_t len;
493 
494 	if (lv_is_visible(lv)) {
495 		repstr = lv->name;
496 		return dm_report_field_string(rh, field, (const char **) &repstr);
497 	}
498 
499 	len = strlen(lv->name) + 3;
500 	if (!(repstr = dm_pool_zalloc(mem, len))) {
501 		log_error("dm_pool_alloc failed");
502 		return 0;
503 	}
504 
505 	if (dm_snprintf(repstr, len, "[%s]", lv->name) < 0) {
506 		log_error("lvname snprintf failed");
507 		return 0;
508 	}
509 
510 	if (!(lvname = dm_pool_strdup(mem, lv->name))) {
511 		log_error("dm_pool_strdup failed");
512 		return 0;
513 	}
514 
515 	dm_report_field_set_value(field, repstr, lvname);
516 
517 	return 1;
518 }
519 
_origin_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)520 static int _origin_disp(struct dm_report *rh, struct dm_pool *mem,
521 			struct dm_report_field *field,
522 			const void *data, void *private)
523 {
524 	const struct logical_volume *lv = (const struct logical_volume *) data;
525 
526 	if (lv_is_cow(lv))
527 		return _lvname_disp(rh, mem, field, origin_from_cow(lv), private);
528 
529 	dm_report_field_set_value(field, "", NULL);
530 	return 1;
531 }
532 
_movepv_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))533 static int _movepv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
534 			struct dm_report_field *field,
535 			const void *data, void *private __attribute((unused)))
536 {
537 	const struct logical_volume *lv = (const struct logical_volume *) data;
538 	const char *name;
539 	struct lv_segment *seg;
540 
541 	dm_list_iterate_items(seg, &lv->segments) {
542 		if (!(seg->status & PVMOVE))
543 			continue;
544 		name = dev_name(seg_dev(seg, 0));
545 		return dm_report_field_string(rh, field, &name);
546 	}
547 
548 	dm_report_field_set_value(field, "", NULL);
549 	return 1;
550 }
551 
_convertlv_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))552 static int _convertlv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
553 			   struct dm_report_field *field,
554 			   const void *data, void *private __attribute((unused)))
555 {
556 	const struct logical_volume *lv = (const struct logical_volume *) data;
557 	const char *name = NULL;
558 	struct lv_segment *seg;
559 
560 	if (lv->status & CONVERTING) {
561 		if (lv->status & MIRRORED) {
562 			seg = first_seg(lv);
563 
564 			/* Temporary mirror is always area_num == 0 */
565 			if (seg_type(seg, 0) == AREA_LV &&
566 			    is_temporary_mirror_layer(seg_lv(seg, 0)))
567 				name = seg_lv(seg, 0)->name;
568 		}
569 	}
570 
571 	if (name)
572 		return dm_report_field_string(rh, field, &name);
573 
574 	dm_report_field_set_value(field, "", NULL);
575 	return 1;
576 }
577 
_size32_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)578 static int _size32_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
579 			struct dm_report_field *field,
580 			const void *data, void *private)
581 {
582 	const uint32_t size = *(const uint32_t *) data;
583 	const char *disp, *repstr;
584 	uint64_t *sortval;
585 
586 	if (!*(disp = display_size_units(private, (uint64_t) size)))
587 		return_0;
588 
589 	if (!(repstr = dm_pool_strdup(mem, disp))) {
590 		log_error("dm_pool_strdup failed");
591 		return 0;
592 	}
593 
594 	if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
595 		log_error("dm_pool_alloc failed");
596 		return 0;
597 	}
598 
599 	*sortval = (const uint64_t) size;
600 
601 	dm_report_field_set_value(field, repstr, sortval);
602 
603 	return 1;
604 }
605 
_size64_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)606 static int _size64_disp(struct dm_report *rh __attribute((unused)),
607 			struct dm_pool *mem,
608 			struct dm_report_field *field,
609 			const void *data, void *private)
610 {
611 	const uint64_t size = *(const uint64_t *) data;
612 	const char *disp, *repstr;
613 	uint64_t *sortval;
614 
615 	if (!*(disp = display_size_units(private, size)))
616 		return_0;
617 
618 	if (!(repstr = dm_pool_strdup(mem, disp))) {
619 		log_error("dm_pool_strdup failed");
620 		return 0;
621 	}
622 
623 	if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
624 		log_error("dm_pool_alloc failed");
625 		return 0;
626 	}
627 
628 	*sortval = size;
629 	dm_report_field_set_value(field, repstr, sortval);
630 
631 	return 1;
632 }
633 
_lvreadahead_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))634 static int _lvreadahead_disp(struct dm_report *rh, struct dm_pool *mem,
635 			     struct dm_report_field *field,
636 			     const void *data, void *private __attribute((unused)))
637 {
638 	const struct logical_volume *lv = (const struct logical_volume *) data;
639 
640 	if (lv->read_ahead == DM_READ_AHEAD_AUTO) {
641 		dm_report_field_set_value(field, "auto", &_minusone);
642 		return 1;
643 	}
644 
645 	return _size32_disp(rh, mem, field, &lv->read_ahead, private);
646 }
647 
_lvkreadahead_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)648 static int _lvkreadahead_disp(struct dm_report *rh, struct dm_pool *mem,
649 			      struct dm_report_field *field,
650 			      const void *data,
651 			      void *private)
652 {
653 	const struct logical_volume *lv = (const struct logical_volume *) data;
654 	struct lvinfo info;
655 
656 	if (!lv_info(lv->vg->cmd, lv, &info, 0, 1) || !info.exists)
657 		return dm_report_field_uint64(rh, field, &_minusone);
658 
659 	return _size32_disp(rh, mem, field, &info.read_ahead, private);
660 }
661 
_vgsize_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)662 static int _vgsize_disp(struct dm_report *rh, struct dm_pool *mem,
663 			struct dm_report_field *field,
664 			const void *data, void *private)
665 {
666 	const struct volume_group *vg = (const struct volume_group *) data;
667 	uint64_t size;
668 
669 	size = (uint64_t) vg_size(vg);
670 
671 	return _size64_disp(rh, mem, field, &size, private);
672 }
673 
_segstart_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)674 static int _segstart_disp(struct dm_report *rh, struct dm_pool *mem,
675 			  struct dm_report_field *field,
676 			  const void *data, void *private)
677 {
678 	const struct lv_segment *seg = (const struct lv_segment *) data;
679 	uint64_t start;
680 
681 	start = (uint64_t) seg->le * seg->lv->vg->extent_size;
682 
683 	return _size64_disp(rh, mem, field, &start, private);
684 }
685 
_segstartpe_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))686 static int _segstartpe_disp(struct dm_report *rh,
687 			    struct dm_pool *mem __attribute((unused)),
688 			    struct dm_report_field *field,
689 			    const void *data,
690 			    void *private __attribute((unused)))
691 {
692 	const struct lv_segment *seg = (const struct lv_segment *) data;
693 
694 	return dm_report_field_uint32(rh, field, &seg->le);
695 }
696 
_segsize_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)697 static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem,
698 			 struct dm_report_field *field,
699 			 const void *data, void *private)
700 {
701 	const struct lv_segment *seg = (const struct lv_segment *) data;
702 	uint64_t size;
703 
704 	size = (uint64_t) seg->len * seg->lv->vg->extent_size;
705 
706 	return _size64_disp(rh, mem, field, &size, private);
707 }
708 
_chunksize_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)709 static int _chunksize_disp(struct dm_report *rh, struct dm_pool *mem,
710 			   struct dm_report_field *field,
711 			   const void *data, void *private)
712 {
713 	const struct lv_segment *seg = (const struct lv_segment *) data;
714 	uint64_t size;
715 
716 	if (lv_is_cow(seg->lv))
717 		size = (uint64_t) find_cow(seg->lv)->chunk_size;
718 	else
719 		size = UINT64_C(0);
720 
721 	return _size64_disp(rh, mem, field, &size, private);
722 }
723 
_originsize_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)724 static int _originsize_disp(struct dm_report *rh, struct dm_pool *mem,
725 			    struct dm_report_field *field,
726 			    const void *data, void *private)
727 {
728 	const struct logical_volume *lv = (const struct logical_volume *) data;
729 	uint64_t size;
730 
731 	if (lv_is_cow(lv))
732 		size = (uint64_t) find_cow(lv)->len * lv->vg->extent_size;
733 	else if (lv_is_origin(lv))
734 		size = lv->size;
735 	else
736 		size = UINT64_C(0);
737 
738 	return _size64_disp(rh, mem, field, &size, private);
739 }
740 
_pvused_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)741 static int _pvused_disp(struct dm_report *rh, struct dm_pool *mem,
742 			struct dm_report_field *field,
743 			const void *data, void *private)
744 {
745 	const struct physical_volume *pv =
746 	    (const struct physical_volume *) data;
747 	uint64_t used;
748 
749 	if (!pv->pe_count)
750 		used = 0LL;
751 	else
752 		used = (uint64_t) pv->pe_alloc_count * pv->pe_size;
753 
754 	return _size64_disp(rh, mem, field, &used, private);
755 }
756 
_pvfree_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)757 static int _pvfree_disp(struct dm_report *rh, struct dm_pool *mem,
758 			struct dm_report_field *field,
759 			const void *data, void *private)
760 {
761 	const struct physical_volume *pv =
762 	    (const struct physical_volume *) data;
763 	uint64_t freespace;
764 
765 	if (!pv->pe_count)
766 		freespace = pv->size;
767 	else
768 		freespace = (uint64_t) (pv->pe_count - pv->pe_alloc_count) * pv->pe_size;
769 
770 	return _size64_disp(rh, mem, field, &freespace, private);
771 }
772 
_pvsize_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)773 static int _pvsize_disp(struct dm_report *rh, struct dm_pool *mem,
774 			struct dm_report_field *field,
775 			const void *data, void *private)
776 {
777 	const struct physical_volume *pv =
778 	    (const struct physical_volume *) data;
779 	uint64_t size;
780 
781 	if (!pv->pe_count)
782 		size = pv->size;
783 	else
784 		size = (uint64_t) pv->pe_count * pv->pe_size;
785 
786 	return _size64_disp(rh, mem, field, &size, private);
787 }
788 
_devsize_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)789 static int _devsize_disp(struct dm_report *rh, struct dm_pool *mem,
790 			 struct dm_report_field *field,
791 			 const void *data, void *private)
792 {
793 	const struct device *dev = *(const struct device **) data;
794 	uint64_t size;
795 
796 	if (!dev_get_size(dev, &size))
797 		size = 0;
798 
799 	return _size64_disp(rh, mem, field, &size, private);
800 }
801 
_vgfree_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)802 static int _vgfree_disp(struct dm_report *rh, struct dm_pool *mem,
803 			struct dm_report_field *field,
804 			const void *data, void *private)
805 {
806 	const struct volume_group *vg = (const struct volume_group *) data;
807 	uint64_t freespace;
808 
809 	freespace = (uint64_t) vg_free(vg);
810 
811 	return _size64_disp(rh, mem, field, &freespace, private);
812 }
813 
_uuid_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))814 static int _uuid_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
815 		      struct dm_report_field *field,
816 		      const void *data, void *private __attribute((unused)))
817 {
818 	char *repstr = NULL;
819 
820 	if (!(repstr = dm_pool_alloc(mem, 40))) {
821 		log_error("dm_pool_alloc failed");
822 		return 0;
823 	}
824 
825 	if (!id_write_format((const struct id *) data, repstr, 40))
826 		return_0;
827 
828 	dm_report_field_set_value(field, repstr, NULL);
829 	return 1;
830 }
831 
_uint32_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))832 static int _uint32_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
833 			struct dm_report_field *field,
834 			const void *data, void *private __attribute((unused)))
835 {
836 	return dm_report_field_uint32(rh, field, data);
837 }
838 
_int32_disp(struct dm_report * rh,struct dm_pool * mem __attribute ((unused)),struct dm_report_field * field,const void * data,void * private __attribute ((unused)))839 static int _int32_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
840 		       struct dm_report_field *field,
841 		       const void *data, void *private __attribute((unused)))
842 {
843 	return dm_report_field_int32(rh, field, data);
844 }
845 
_pvmdas_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)846 static int _pvmdas_disp(struct dm_report *rh, struct dm_pool *mem,
847 			struct dm_report_field *field,
848 			const void *data, void *private)
849 {
850 	uint32_t count;
851 	const struct physical_volume *pv =
852 	    (const struct physical_volume *) data;
853 
854 	count = pv_mda_count(pv);
855 
856 	return _uint32_disp(rh, mem, field, &count, private);
857 }
858 
_vgmdas_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)859 static int _vgmdas_disp(struct dm_report *rh, struct dm_pool *mem,
860 			struct dm_report_field *field,
861 			const void *data, void *private)
862 {
863 	const struct volume_group *vg = (const struct volume_group *) data;
864 	uint32_t count;
865 
866 	count = vg_mda_count(vg);
867 
868 	return _uint32_disp(rh, mem, field, &count, private);
869 }
870 
_pvmdafree_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)871 static int _pvmdafree_disp(struct dm_report *rh, struct dm_pool *mem,
872 			   struct dm_report_field *field,
873 			   const void *data, void *private)
874 {
875 	struct lvmcache_info *info;
876 	uint64_t freespace = UINT64_MAX, mda_free;
877 	const char *pvid = (const char *)(&((struct id *) data)->uuid);
878 	struct metadata_area *mda;
879 
880 	if ((info = info_from_pvid(pvid, 0)))
881 		dm_list_iterate_items(mda, &info->mdas) {
882 			if (!mda->ops->mda_free_sectors)
883 				continue;
884 			mda_free = mda->ops->mda_free_sectors(mda);
885 			if (mda_free < freespace)
886 				freespace = mda_free;
887 		}
888 
889 	if (freespace == UINT64_MAX)
890 		freespace = UINT64_C(0);
891 
892 	return _size64_disp(rh, mem, field, &freespace, private);
893 }
894 
_find_min_mda_size(struct dm_list * mdas)895 static uint64_t _find_min_mda_size(struct dm_list *mdas)
896 {
897 	uint64_t min_mda_size = UINT64_MAX, mda_size;
898 	struct metadata_area *mda;
899 
900 	dm_list_iterate_items(mda, mdas) {
901 		if (!mda->ops->mda_total_sectors)
902 			continue;
903 		mda_size = mda->ops->mda_total_sectors(mda);
904 		if (mda_size < min_mda_size)
905 			min_mda_size = mda_size;
906 	}
907 
908 	if (min_mda_size == UINT64_MAX)
909 		min_mda_size = UINT64_C(0);
910 
911 	return min_mda_size;
912 }
913 
_pvmdasize_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)914 static int _pvmdasize_disp(struct dm_report *rh, struct dm_pool *mem,
915 			   struct dm_report_field *field,
916 			   const void *data, void *private)
917 {
918 	struct lvmcache_info *info;
919 	uint64_t min_mda_size = 0;
920 	const char *pvid = (const char *)(&((struct id *) data)->uuid);
921 
922 	/* PVs could have 2 mdas of different sizes (rounding effect) */
923 	if ((info = info_from_pvid(pvid, 0)))
924 		min_mda_size = _find_min_mda_size(&info->mdas);
925 
926 	return _size64_disp(rh, mem, field, &min_mda_size, private);
927 }
928 
_vgmdasize_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)929 static int _vgmdasize_disp(struct dm_report *rh, struct dm_pool *mem,
930 			   struct dm_report_field *field,
931 			   const void *data, void *private)
932 {
933 	const struct volume_group *vg = (const struct volume_group *) data;
934 	uint64_t min_mda_size;
935 
936 	min_mda_size = _find_min_mda_size(&vg->fid->metadata_areas);
937 
938 	return _size64_disp(rh, mem, field, &min_mda_size, private);
939 }
940 
_vgmdafree_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)941 static int _vgmdafree_disp(struct dm_report *rh, struct dm_pool *mem,
942 			   struct dm_report_field *field,
943 			   const void *data, void *private)
944 {
945 	const struct volume_group *vg = (const struct volume_group *) data;
946 	uint64_t freespace = UINT64_MAX, mda_free;
947 	struct metadata_area *mda;
948 
949 	dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
950 		if (!mda->ops->mda_free_sectors)
951 			continue;
952 		mda_free = mda->ops->mda_free_sectors(mda);
953 		if (mda_free < freespace)
954 			freespace = mda_free;
955 	}
956 
957 	if (freespace == UINT64_MAX)
958 		freespace = UINT64_C(0);
959 
960 	return _size64_disp(rh, mem, field, &freespace, private);
961 }
962 
_lvcount_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)963 static int _lvcount_disp(struct dm_report *rh, struct dm_pool *mem,
964 			 struct dm_report_field *field,
965 			 const void *data, void *private)
966 {
967 	const struct volume_group *vg = (const struct volume_group *) data;
968 	uint32_t count;
969 
970 	count = vg_visible_lvs(vg);
971 
972 	return _uint32_disp(rh, mem, field, &count, private);
973 }
974 
_lvsegcount_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)975 static int _lvsegcount_disp(struct dm_report *rh, struct dm_pool *mem,
976 			    struct dm_report_field *field,
977 			    const void *data, void *private)
978 {
979 	const struct logical_volume *lv = (const struct logical_volume *) data;
980 	uint32_t count;
981 
982 	count = dm_list_size(&lv->segments);
983 
984 	return _uint32_disp(rh, mem, field, &count, private);
985 }
986 
_snapcount_disp(struct dm_report * rh,struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private)987 static int _snapcount_disp(struct dm_report *rh, struct dm_pool *mem,
988 			   struct dm_report_field *field,
989 			   const void *data, void *private)
990 {
991 	const struct volume_group *vg = (const struct volume_group *) data;
992 	uint32_t count;
993 
994 	count = snapshot_count(vg);
995 
996 	return _uint32_disp(rh, mem, field, &count, private);
997 }
998 
_snpercent_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))999 static int _snpercent_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
1000 			   struct dm_report_field *field,
1001 			   const void *data, void *private __attribute((unused)))
1002 {
1003 	const struct logical_volume *lv = (const struct logical_volume *) data;
1004 	struct lvinfo info;
1005 	float snap_percent;
1006 	percent_range_t percent_range;
1007 	uint64_t *sortval;
1008 	char *repstr;
1009 
1010 	/* Suppress snapshot percentage if not using driver */
1011 	if (!activation()) {
1012 		dm_report_field_set_value(field, "", NULL);
1013 		return 1;
1014 	}
1015 
1016 	if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
1017 		log_error("dm_pool_alloc failed");
1018 		return 0;
1019 	}
1020 
1021 	if (!lv_is_cow(lv) ||
1022 	    (lv_info(lv->vg->cmd, lv, &info, 0, 0) && !info.exists)) {
1023 		*sortval = UINT64_C(0);
1024 		dm_report_field_set_value(field, "", sortval);
1025 		return 1;
1026 	}
1027 
1028 	if (!lv_snapshot_percent(lv, &snap_percent, &percent_range) ||
1029 				 (percent_range == PERCENT_INVALID)) {
1030 		*sortval = UINT64_C(100);
1031 		dm_report_field_set_value(field, "100.00", sortval);
1032 		return 1;
1033 	}
1034 
1035 	if (!(repstr = dm_pool_zalloc(mem, 8))) {
1036 		log_error("dm_pool_alloc failed");
1037 		return 0;
1038 	}
1039 
1040 	if (dm_snprintf(repstr, 7, "%.2f", snap_percent) < 0) {
1041 		log_error("snapshot percentage too large");
1042 		return 0;
1043 	}
1044 
1045 	*sortval = snap_percent * UINT64_C(1000);
1046 	dm_report_field_set_value(field, repstr, sortval);
1047 
1048 	return 1;
1049 }
1050 
_copypercent_disp(struct dm_report * rh __attribute ((unused)),struct dm_pool * mem,struct dm_report_field * field,const void * data,void * private __attribute ((unused)))1051 static int _copypercent_disp(struct dm_report *rh __attribute((unused)),
1052 			     struct dm_pool *mem,
1053 			     struct dm_report_field *field,
1054 			     const void *data, void *private __attribute((unused)))
1055 {
1056 	struct logical_volume *lv = (struct logical_volume *) data;
1057 	float percent;
1058 	percent_range_t percent_range;
1059 	uint64_t *sortval;
1060 	char *repstr;
1061 
1062 	if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
1063 		log_error("dm_pool_alloc failed");
1064 		return 0;
1065 	}
1066 
1067 	if ((!(lv->status & PVMOVE) && !(lv->status & MIRRORED)) ||
1068 	    !lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, &percent_range,
1069 			       NULL) || (percent_range == PERCENT_INVALID)) {
1070 		*sortval = UINT64_C(0);
1071 		dm_report_field_set_value(field, "", sortval);
1072 		return 1;
1073 	}
1074 
1075 	percent = copy_percent(lv, &percent_range);
1076 
1077 	if (!(repstr = dm_pool_zalloc(mem, 8))) {
1078 		log_error("dm_pool_alloc failed");
1079 		return 0;
1080 	}
1081 
1082 	if (dm_snprintf(repstr, 7, "%.2f", percent) < 0) {
1083 		log_error("copy percentage too large");
1084 		return 0;
1085 	}
1086 
1087 	*sortval = percent * UINT64_C(1000);
1088 	dm_report_field_set_value(field, repstr, sortval);
1089 
1090 	return 1;
1091 }
1092 
1093 /* Report object types */
1094 
1095 /* necessary for displaying something for PVs not belonging to VG */
1096 static struct format_instance _dummy_fid = {
1097 	.metadata_areas = { &(_dummy_fid.metadata_areas), &(_dummy_fid.metadata_areas) },
1098 };
1099 
1100 static struct volume_group _dummy_vg = {
1101 	.fid = &_dummy_fid,
1102 	.name = (char *) "",
1103 	.system_id = (char *) "",
1104 	.pvs = { &(_dummy_vg.pvs), &(_dummy_vg.pvs) },
1105 	.lvs = { &(_dummy_vg.lvs), &(_dummy_vg.lvs) },
1106 	.tags = { &(_dummy_vg.tags), &(_dummy_vg.tags) },
1107 };
1108 
_obj_get_vg(void * obj)1109 static void *_obj_get_vg(void *obj)
1110 {
1111 	struct volume_group *vg = ((struct lvm_report_object *)obj)->vg;
1112 
1113 	return vg ? vg : &_dummy_vg;
1114 }
1115 
_obj_get_lv(void * obj)1116 static void *_obj_get_lv(void *obj)
1117 {
1118 	return ((struct lvm_report_object *)obj)->lv;
1119 }
1120 
_obj_get_pv(void * obj)1121 static void *_obj_get_pv(void *obj)
1122 {
1123 	return ((struct lvm_report_object *)obj)->pv;
1124 }
1125 
_obj_get_seg(void * obj)1126 static void *_obj_get_seg(void *obj)
1127 {
1128 	return ((struct lvm_report_object *)obj)->seg;
1129 }
1130 
_obj_get_pvseg(void * obj)1131 static void *_obj_get_pvseg(void *obj)
1132 {
1133 	return ((struct lvm_report_object *)obj)->pvseg;
1134 }
1135 
1136 static const struct dm_report_object_type _report_types[] = {
1137 	{ VGS, "Volume Group", "vg_", _obj_get_vg },
1138 	{ LVS, "Logical Volume", "lv_", _obj_get_lv },
1139 	{ PVS, "Physical Volume", "pv_", _obj_get_pv },
1140 	{ LABEL, "Physical Volume Label", "pv_", _obj_get_pv },
1141 	{ SEGS, "Logical Volume Segment", "seg_", _obj_get_seg },
1142 	{ PVSEGS, "Physical Volume Segment", "pvseg_", _obj_get_pvseg },
1143 	{ 0, "", "", NULL },
1144 };
1145 
1146 /*
1147  * Import column definitions
1148  */
1149 
1150 #define STR DM_REPORT_FIELD_TYPE_STRING
1151 #define NUM DM_REPORT_FIELD_TYPE_NUMBER
1152 #define FIELD(type, strct, sorttype, head, field, width, func, id, desc) \
1153 	{type, sorttype, offsetof(type_ ## strct, field), width, \
1154 	 id, head, &_ ## func ## _disp, desc},
1155 
1156 typedef struct physical_volume type_pv;
1157 typedef struct logical_volume type_lv;
1158 typedef struct volume_group type_vg;
1159 typedef struct lv_segment type_seg;
1160 typedef struct pv_segment type_pvseg;
1161 
1162 static const struct dm_report_field_type _fields[] = {
1163 #include "columns.h"
1164 {0, 0, 0, 0, "", "", NULL, NULL},
1165 };
1166 
1167 #undef STR
1168 #undef NUM
1169 #undef FIELD
1170 
report_init(struct cmd_context * cmd,const char * format,const char * keys,report_type_t * report_type,const char * separator,int aligned,int buffered,int headings,int field_prefixes,int quoted,int columns_as_rows)1171 void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
1172 		  report_type_t *report_type, const char *separator,
1173 		  int aligned, int buffered, int headings, int field_prefixes,
1174 		  int quoted, int columns_as_rows)
1175 {
1176 	uint32_t report_flags = 0;
1177 	void *rh;
1178 
1179 	if (aligned)
1180 		report_flags |= DM_REPORT_OUTPUT_ALIGNED;
1181 
1182 	if (buffered)
1183 		report_flags |= DM_REPORT_OUTPUT_BUFFERED;
1184 
1185 	if (headings)
1186 		report_flags |= DM_REPORT_OUTPUT_HEADINGS;
1187 
1188 	if (field_prefixes)
1189 		report_flags |= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX;
1190 
1191 	if (!quoted)
1192 		report_flags |= DM_REPORT_OUTPUT_FIELD_UNQUOTED;
1193 
1194 	if (columns_as_rows)
1195 		report_flags |= DM_REPORT_OUTPUT_COLUMNS_AS_ROWS;
1196 
1197 	rh = dm_report_init(report_type, _report_types, _fields, format,
1198 			    separator, report_flags, keys, cmd);
1199 
1200 	if (rh && field_prefixes)
1201 		dm_report_set_output_field_name_prefix(rh, "lvm2_");
1202 
1203 	return rh;
1204 }
1205 
1206 /*
1207  * Create a row of data for an object
1208  */
report_object(void * handle,struct volume_group * vg,struct logical_volume * lv,struct physical_volume * pv,struct lv_segment * seg,struct pv_segment * pvseg)1209 int report_object(void *handle, struct volume_group *vg,
1210 		  struct logical_volume *lv, struct physical_volume *pv,
1211 		  struct lv_segment *seg, struct pv_segment *pvseg)
1212 {
1213 	struct lvm_report_object obj;
1214 
1215 	/* The two format fields might as well match. */
1216 	if (!vg && pv)
1217 		_dummy_fid.fmt = pv->fmt;
1218 
1219 	obj.vg = vg;
1220 	obj.lv = lv;
1221 	obj.pv = pv;
1222 	obj.seg = seg;
1223 	obj.pvseg = pvseg;
1224 
1225 	return dm_report_object(handle, &obj);
1226 }
1227