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