1 /* $NetBSD: report.c,v 1.1.1.3 2009/12/02 00:26:46 haad Exp $ */
4 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
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.
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
21 #include "toolcontext.h"
22 #include "lvm-string.h"
30 struct lvm_report_object {
31 struct volume_group *vg;
32 struct logical_volume *lv;
33 struct physical_volume *pv;
34 struct lv_segment *seg;
35 struct pv_segment *pvseg;
42 struct physical_volume _pv;
43 struct logical_volume _lv;
44 struct volume_group _vg;
45 struct lv_segment _seg;
46 struct pv_segment _pvseg;
49 static char _alloc_policy_char(alloc_policy_t alloc)
52 case ALLOC_CONTIGUOUS:
65 static const uint64_t _minusone = UINT64_C(-1);
68 * Data-munging functions to prepare each data type for display and sorting
70 static int _string_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
71 struct dm_report_field *field,
72 const void *data, void *private __attribute((unused)))
74 return dm_report_field_string(rh, field, (const char **) data);
77 static int _dev_name_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
78 struct dm_report_field *field,
79 const void *data, void *private __attribute((unused)))
81 const char *name = dev_name(*(const struct device **) data);
83 return dm_report_field_string(rh, field, &name);
86 static int _format_pvsegs(struct dm_pool *mem, struct dm_report_field *field,
87 const void *data, int range_format)
89 const struct lv_segment *seg = (const struct lv_segment *) data;
91 const char *name = NULL;
95 if (!dm_pool_begin_object(mem, 256)) {
96 log_error("dm_pool_begin_object failed");
100 for (s = 0; s < seg->area_count; s++) {
101 switch (seg_type(seg, s)) {
103 name = seg_lv(seg, s)->name;
104 extent = seg_le(seg, s);
107 name = dev_name(seg_dev(seg, s));
108 extent = seg_pe(seg, s);
110 case AREA_UNASSIGNED:
115 if (!dm_pool_grow_object(mem, name, strlen(name))) {
116 log_error("dm_pool_grow_object failed");
120 if (dm_snprintf(extent_str, sizeof(extent_str),
122 range_format ? ":" : "(", extent,
123 range_format ? "-" : ")") < 0) {
124 log_error("Extent number dm_snprintf failed");
127 if (!dm_pool_grow_object(mem, extent_str, strlen(extent_str))) {
128 log_error("dm_pool_grow_object failed");
133 if (dm_snprintf(extent_str, sizeof(extent_str),
134 "%" PRIu32, extent + seg->area_len - 1) < 0) {
135 log_error("Extent number dm_snprintf failed");
138 if (!dm_pool_grow_object(mem, extent_str, strlen(extent_str))) {
139 log_error("dm_pool_grow_object failed");
144 if ((s != seg->area_count - 1) &&
145 !dm_pool_grow_object(mem, range_format ? " " : ",", 1)) {
146 log_error("dm_pool_grow_object failed");
151 if (!dm_pool_grow_object(mem, "\0", 1)) {
152 log_error("dm_pool_grow_object failed");
156 dm_report_field_set_value(field, dm_pool_end_object(mem), NULL);
161 static int _devices_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
162 struct dm_report_field *field,
163 const void *data, void *private __attribute((unused)))
165 return _format_pvsegs(mem, field, data, 0);
168 static int _peranges_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
169 struct dm_report_field *field,
170 const void *data, void *private __attribute((unused)))
172 return _format_pvsegs(mem, field, data, 1);
175 static int _tags_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
176 struct dm_report_field *field,
177 const void *data, void *private __attribute((unused)))
179 const struct dm_list *tags = (const struct dm_list *) data;
182 if (!dm_pool_begin_object(mem, 256)) {
183 log_error("dm_pool_begin_object failed");
187 dm_list_iterate_items(sl, tags) {
188 if (!dm_pool_grow_object(mem, sl->str, strlen(sl->str)) ||
189 (sl->list.n != tags && !dm_pool_grow_object(mem, ",", 1))) {
190 log_error("dm_pool_grow_object failed");
195 if (!dm_pool_grow_object(mem, "\0", 1)) {
196 log_error("dm_pool_grow_object failed");
200 dm_report_field_set_value(field, dm_pool_end_object(mem), NULL);
205 static int _modules_disp(struct dm_report *rh, struct dm_pool *mem,
206 struct dm_report_field *field,
207 const void *data, void *private)
209 const struct logical_volume *lv = (const struct logical_volume *) data;
210 struct dm_list *modules;
212 if (!(modules = str_list_create(mem))) {
213 log_error("modules str_list allocation failed");
217 if (!list_lv_modules(mem, lv, modules))
220 return _tags_disp(rh, mem, field, modules, private);
223 static int _vgfmt_disp(struct dm_report *rh, struct dm_pool *mem,
224 struct dm_report_field *field,
225 const void *data, void *private)
227 const struct volume_group *vg = (const struct volume_group *) data;
230 dm_report_field_set_value(field, "", NULL);
234 return _string_disp(rh, mem, field, &vg->fid->fmt->name, private);
237 static int _pvfmt_disp(struct dm_report *rh, struct dm_pool *mem,
238 struct dm_report_field *field,
239 const void *data, void *private)
241 const struct physical_volume *pv =
242 (const struct physical_volume *) data;
245 dm_report_field_set_value(field, "", NULL);
249 return _string_disp(rh, mem, field, &pv->fmt->name, private);
252 static int _lvkmaj_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
253 struct dm_report_field *field,
254 const void *data, void *private __attribute((unused)))
256 const struct logical_volume *lv = (const struct logical_volume *) data;
259 if (lv_info(lv->vg->cmd, lv, &info, 0, 0) && info.exists)
260 return dm_report_field_int(rh, field, &info.major);
262 return dm_report_field_uint64(rh, field, &_minusone);
265 static int _lvkmin_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
266 struct dm_report_field *field,
267 const void *data, void *private __attribute((unused)))
269 const struct logical_volume *lv = (const struct logical_volume *) data;
272 if (lv_info(lv->vg->cmd, lv, &info, 0, 0) && info.exists)
273 return dm_report_field_int(rh, field, &info.minor);
275 return dm_report_field_uint64(rh, field, &_minusone);
278 static int _lv_mimage_in_sync(const struct logical_volume *lv)
281 percent_range_t percent_range;
282 struct lv_segment *mirror_seg = find_mirror_seg(first_seg(lv));
284 if (!(lv->status & MIRROR_IMAGE) || !mirror_seg)
287 if (!lv_mirror_percent(lv->vg->cmd, mirror_seg->lv, 0, &percent,
288 &percent_range, NULL))
291 return (percent_range == PERCENT_100) ? 1 : 0;
294 static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
295 struct dm_report_field *field,
296 const void *data, void *private __attribute((unused)))
298 const struct logical_volume *lv = (const struct logical_volume *) data;
302 percent_range_t percent_range;
304 if (!(repstr = dm_pool_zalloc(mem, 7))) {
305 log_error("dm_pool_alloc failed");
309 /* Blank if this is a "free space" LV. */
313 if (lv->status & PVMOVE)
315 else if (lv->status & CONVERTING)
317 else if (lv->status & VIRTUAL)
319 /* Origin takes precedence over Mirror */
320 else if (lv_is_origin(lv))
322 else if (lv->status & MIRRORED) {
323 if (lv->status & MIRROR_NOTSYNCED)
327 }else if (lv->status & MIRROR_IMAGE)
328 if (_lv_mimage_in_sync(lv))
332 else if (lv->status & MIRROR_LOG)
334 else if (lv_is_cow(lv))
339 if (lv->status & PVMOVE)
341 else if (lv->status & LVM_WRITE)
343 else if (lv->status & LVM_READ)
348 repstr[2] = _alloc_policy_char(lv->alloc);
350 if (lv->status & LOCKED)
351 repstr[2] = toupper(repstr[2]);
353 if (lv->status & FIXED_MINOR)
354 repstr[3] = 'm'; /* Fixed Minor */
358 if (lv_info(lv->vg->cmd, lv, &info, 1, 0) && info.exists) {
360 repstr[4] = 's'; /* Suspended */
361 else if (info.live_table)
362 repstr[4] = 'a'; /* Active */
363 else if (info.inactive_table)
364 repstr[4] = 'i'; /* Inactive with table */
366 repstr[4] = 'd'; /* Inactive without table */
368 /* Snapshot dropped? */
369 if (info.live_table && lv_is_cow(lv) &&
370 (!lv_snapshot_percent(lv, &snap_percent, &percent_range) ||
371 percent_range == PERCENT_INVALID)) {
372 repstr[0] = toupper(repstr[0]);
374 repstr[4] = 'S'; /* Susp Inv snapshot */
376 repstr[4] = 'I'; /* Invalid snapshot */
380 repstr[5] = 'o'; /* Open */
389 dm_report_field_set_value(field, repstr, NULL);
393 static int _pvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
394 struct dm_report_field *field,
395 const void *data, void *private __attribute((unused)))
397 const uint32_t status = *(const uint32_t *) data;
400 if (!(repstr = dm_pool_zalloc(mem, 3))) {
401 log_error("dm_pool_alloc failed");
405 if (status & ALLOCATABLE_PV)
410 if (status & EXPORTED_VG)
415 dm_report_field_set_value(field, repstr, NULL);
419 static int _vgstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
420 struct dm_report_field *field,
421 const void *data, void *private __attribute((unused)))
423 const struct volume_group *vg = (const struct volume_group *) data;
426 if (!(repstr = dm_pool_zalloc(mem, 7))) {
427 log_error("dm_pool_alloc failed");
431 if (vg->status & LVM_WRITE)
436 if (vg_is_resizeable(vg))
441 if (vg_is_exported(vg))
446 if (vg_missing_pv_count(vg))
451 repstr[4] = _alloc_policy_char(vg->alloc);
453 if (vg_is_clustered(vg))
458 dm_report_field_set_value(field, repstr, NULL);
462 static int _segtype_disp(struct dm_report *rh __attribute((unused)),
463 struct dm_pool *mem __attribute((unused)),
464 struct dm_report_field *field,
465 const void *data, void *private __attribute((unused)))
467 const struct lv_segment *seg = (const struct lv_segment *) data;
469 if (seg->area_count == 1) {
470 dm_report_field_set_value(field, "linear", NULL);
474 dm_report_field_set_value(field, seg->segtype->ops->name(seg), NULL);
478 static int _loglv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
479 struct dm_report_field *field,
480 const void *data, void *private __attribute((unused)))
482 const struct logical_volume *lv = (const struct logical_volume *) data;
483 struct lv_segment *seg;
485 dm_list_iterate_items(seg, &lv->segments) {
486 if (!seg_is_mirrored(seg) || !seg->log_lv)
488 return dm_report_field_string(rh, field,
489 (const char **) &seg->log_lv->name);
492 dm_report_field_set_value(field, "", NULL);
496 static int _lvname_disp(struct dm_report *rh, struct dm_pool *mem,
497 struct dm_report_field *field,
498 const void *data, void *private __attribute((unused)))
500 const struct logical_volume *lv = (const struct logical_volume *) data;
501 char *repstr, *lvname;
504 if (lv_is_visible(lv)) {
506 return dm_report_field_string(rh, field, (const char **) &repstr);
509 len = strlen(lv->name) + 3;
510 if (!(repstr = dm_pool_zalloc(mem, len))) {
511 log_error("dm_pool_alloc failed");
515 if (dm_snprintf(repstr, len, "[%s]", lv->name) < 0) {
516 log_error("lvname snprintf failed");
520 if (!(lvname = dm_pool_strdup(mem, lv->name))) {
521 log_error("dm_pool_strdup failed");
525 dm_report_field_set_value(field, repstr, lvname);
530 static int _origin_disp(struct dm_report *rh, struct dm_pool *mem,
531 struct dm_report_field *field,
532 const void *data, void *private)
534 const struct logical_volume *lv = (const struct logical_volume *) data;
537 return _lvname_disp(rh, mem, field, origin_from_cow(lv), private);
539 dm_report_field_set_value(field, "", NULL);
543 static int _movepv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
544 struct dm_report_field *field,
545 const void *data, void *private __attribute((unused)))
547 const struct logical_volume *lv = (const struct logical_volume *) data;
549 struct lv_segment *seg;
551 dm_list_iterate_items(seg, &lv->segments) {
552 if (!(seg->status & PVMOVE))
554 name = dev_name(seg_dev(seg, 0));
555 return dm_report_field_string(rh, field, &name);
558 dm_report_field_set_value(field, "", NULL);
562 static int _convertlv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
563 struct dm_report_field *field,
564 const void *data, void *private __attribute((unused)))
566 const struct logical_volume *lv = (const struct logical_volume *) data;
567 const char *name = NULL;
568 struct lv_segment *seg;
570 if (lv->status & CONVERTING) {
571 if (lv->status & MIRRORED) {
574 /* Temporary mirror is always area_num == 0 */
575 if (seg_type(seg, 0) == AREA_LV &&
576 is_temporary_mirror_layer(seg_lv(seg, 0)))
577 name = seg_lv(seg, 0)->name;
582 return dm_report_field_string(rh, field, &name);
584 dm_report_field_set_value(field, "", NULL);
588 static int _size32_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
589 struct dm_report_field *field,
590 const void *data, void *private)
592 const uint32_t size = *(const uint32_t *) data;
593 const char *disp, *repstr;
596 if (!*(disp = display_size_units(private, (uint64_t) size)))
599 if (!(repstr = dm_pool_strdup(mem, disp))) {
600 log_error("dm_pool_strdup failed");
604 if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
605 log_error("dm_pool_alloc failed");
609 *sortval = (const uint64_t) size;
611 dm_report_field_set_value(field, repstr, sortval);
616 static int _size64_disp(struct dm_report *rh __attribute((unused)),
618 struct dm_report_field *field,
619 const void *data, void *private)
621 const uint64_t size = *(const uint64_t *) data;
622 const char *disp, *repstr;
625 if (!*(disp = display_size_units(private, size)))
628 if (!(repstr = dm_pool_strdup(mem, disp))) {
629 log_error("dm_pool_strdup failed");
633 if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
634 log_error("dm_pool_alloc failed");
639 dm_report_field_set_value(field, repstr, sortval);
644 static int _lvreadahead_disp(struct dm_report *rh, struct dm_pool *mem,
645 struct dm_report_field *field,
646 const void *data, void *private __attribute((unused)))
648 const struct logical_volume *lv = (const struct logical_volume *) data;
650 if (lv->read_ahead == DM_READ_AHEAD_AUTO) {
651 dm_report_field_set_value(field, "auto", &_minusone);
655 return _size32_disp(rh, mem, field, &lv->read_ahead, private);
658 static int _lvkreadahead_disp(struct dm_report *rh, struct dm_pool *mem,
659 struct dm_report_field *field,
663 const struct logical_volume *lv = (const struct logical_volume *) data;
666 if (!lv_info(lv->vg->cmd, lv, &info, 0, 1) || !info.exists)
667 return dm_report_field_uint64(rh, field, &_minusone);
669 return _size32_disp(rh, mem, field, &info.read_ahead, private);
672 static int _vgsize_disp(struct dm_report *rh, struct dm_pool *mem,
673 struct dm_report_field *field,
674 const void *data, void *private)
676 const struct volume_group *vg = (const struct volume_group *) data;
679 size = (uint64_t) vg_size(vg);
681 return _size64_disp(rh, mem, field, &size, private);
684 static int _segstart_disp(struct dm_report *rh, struct dm_pool *mem,
685 struct dm_report_field *field,
686 const void *data, void *private)
688 const struct lv_segment *seg = (const struct lv_segment *) data;
691 start = (uint64_t) seg->le * seg->lv->vg->extent_size;
693 return _size64_disp(rh, mem, field, &start, private);
696 static int _segstartpe_disp(struct dm_report *rh,
697 struct dm_pool *mem __attribute((unused)),
698 struct dm_report_field *field,
700 void *private __attribute((unused)))
702 const struct lv_segment *seg = (const struct lv_segment *) data;
704 return dm_report_field_uint32(rh, field, &seg->le);
707 static int _segsize_disp(struct dm_report *rh, struct dm_pool *mem,
708 struct dm_report_field *field,
709 const void *data, void *private)
711 const struct lv_segment *seg = (const struct lv_segment *) data;
714 size = (uint64_t) seg->len * seg->lv->vg->extent_size;
716 return _size64_disp(rh, mem, field, &size, private);
719 static int _chunksize_disp(struct dm_report *rh, struct dm_pool *mem,
720 struct dm_report_field *field,
721 const void *data, void *private)
723 const struct lv_segment *seg = (const struct lv_segment *) data;
726 if (lv_is_cow(seg->lv))
727 size = (uint64_t) find_cow(seg->lv)->chunk_size;
731 return _size64_disp(rh, mem, field, &size, private);
734 static int _originsize_disp(struct dm_report *rh, struct dm_pool *mem,
735 struct dm_report_field *field,
736 const void *data, void *private)
738 const struct logical_volume *lv = (const struct logical_volume *) data;
742 size = (uint64_t) find_cow(lv)->len * lv->vg->extent_size;
743 else if (lv_is_origin(lv))
748 return _size64_disp(rh, mem, field, &size, private);
751 static int _pvused_disp(struct dm_report *rh, struct dm_pool *mem,
752 struct dm_report_field *field,
753 const void *data, void *private)
755 const struct physical_volume *pv =
756 (const struct physical_volume *) data;
762 used = (uint64_t) pv->pe_alloc_count * pv->pe_size;
764 return _size64_disp(rh, mem, field, &used, private);
767 static int _pvfree_disp(struct dm_report *rh, struct dm_pool *mem,
768 struct dm_report_field *field,
769 const void *data, void *private)
771 const struct physical_volume *pv =
772 (const struct physical_volume *) data;
776 freespace = pv->size;
778 freespace = (uint64_t) (pv->pe_count - pv->pe_alloc_count) * pv->pe_size;
780 return _size64_disp(rh, mem, field, &freespace, private);
783 static int _pvsize_disp(struct dm_report *rh, struct dm_pool *mem,
784 struct dm_report_field *field,
785 const void *data, void *private)
787 const struct physical_volume *pv =
788 (const struct physical_volume *) data;
794 size = (uint64_t) pv->pe_count * pv->pe_size;
796 return _size64_disp(rh, mem, field, &size, private);
799 static int _devsize_disp(struct dm_report *rh, struct dm_pool *mem,
800 struct dm_report_field *field,
801 const void *data, void *private)
803 const struct device *dev = *(const struct device **) data;
806 if (!dev_get_size(dev, &size))
809 return _size64_disp(rh, mem, field, &size, private);
812 static int _vgfree_disp(struct dm_report *rh, struct dm_pool *mem,
813 struct dm_report_field *field,
814 const void *data, void *private)
816 const struct volume_group *vg = (const struct volume_group *) data;
819 freespace = (uint64_t) vg_free(vg);
821 return _size64_disp(rh, mem, field, &freespace, private);
824 static int _uuid_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
825 struct dm_report_field *field,
826 const void *data, void *private __attribute((unused)))
830 if (!(repstr = dm_pool_alloc(mem, 40))) {
831 log_error("dm_pool_alloc failed");
835 if (!id_write_format((const struct id *) data, repstr, 40))
838 dm_report_field_set_value(field, repstr, NULL);
842 static int _uint32_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
843 struct dm_report_field *field,
844 const void *data, void *private __attribute((unused)))
846 return dm_report_field_uint32(rh, field, data);
849 static int _int32_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)),
850 struct dm_report_field *field,
851 const void *data, void *private __attribute((unused)))
853 return dm_report_field_int32(rh, field, data);
856 static int _pvmdas_disp(struct dm_report *rh, struct dm_pool *mem,
857 struct dm_report_field *field,
858 const void *data, void *private)
861 const struct physical_volume *pv =
862 (const struct physical_volume *) data;
864 count = pv_mda_count(pv);
866 return _uint32_disp(rh, mem, field, &count, private);
869 static int _vgmdas_disp(struct dm_report *rh, struct dm_pool *mem,
870 struct dm_report_field *field,
871 const void *data, void *private)
873 const struct volume_group *vg = (const struct volume_group *) data;
876 count = vg_mda_count(vg);
878 return _uint32_disp(rh, mem, field, &count, private);
881 static int _pvmdafree_disp(struct dm_report *rh, struct dm_pool *mem,
882 struct dm_report_field *field,
883 const void *data, void *private)
885 struct lvmcache_info *info;
886 uint64_t freespace = UINT64_MAX, mda_free;
887 const char *pvid = (const char *)(&((struct id *) data)->uuid);
888 struct metadata_area *mda;
890 if ((info = info_from_pvid(pvid, 0)))
891 dm_list_iterate_items(mda, &info->mdas) {
892 if (!mda->ops->mda_free_sectors)
894 mda_free = mda->ops->mda_free_sectors(mda);
895 if (mda_free < freespace)
896 freespace = mda_free;
899 if (freespace == UINT64_MAX)
900 freespace = UINT64_C(0);
902 return _size64_disp(rh, mem, field, &freespace, private);
905 static uint64_t _find_min_mda_size(struct dm_list *mdas)
907 uint64_t min_mda_size = UINT64_MAX, mda_size;
908 struct metadata_area *mda;
910 dm_list_iterate_items(mda, mdas) {
911 if (!mda->ops->mda_total_sectors)
913 mda_size = mda->ops->mda_total_sectors(mda);
914 if (mda_size < min_mda_size)
915 min_mda_size = mda_size;
918 if (min_mda_size == UINT64_MAX)
919 min_mda_size = UINT64_C(0);
924 static int _pvmdasize_disp(struct dm_report *rh, struct dm_pool *mem,
925 struct dm_report_field *field,
926 const void *data, void *private)
928 struct lvmcache_info *info;
929 uint64_t min_mda_size = 0;
930 const char *pvid = (const char *)(&((struct id *) data)->uuid);
932 /* PVs could have 2 mdas of different sizes (rounding effect) */
933 if ((info = info_from_pvid(pvid, 0)))
934 min_mda_size = _find_min_mda_size(&info->mdas);
936 return _size64_disp(rh, mem, field, &min_mda_size, private);
939 static int _vgmdasize_disp(struct dm_report *rh, struct dm_pool *mem,
940 struct dm_report_field *field,
941 const void *data, void *private)
943 const struct volume_group *vg = (const struct volume_group *) data;
944 uint64_t min_mda_size;
946 min_mda_size = _find_min_mda_size(&vg->fid->metadata_areas);
948 return _size64_disp(rh, mem, field, &min_mda_size, private);
951 static int _vgmdafree_disp(struct dm_report *rh, struct dm_pool *mem,
952 struct dm_report_field *field,
953 const void *data, void *private)
955 const struct volume_group *vg = (const struct volume_group *) data;
956 uint64_t freespace = UINT64_MAX, mda_free;
957 struct metadata_area *mda;
959 dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
960 if (!mda->ops->mda_free_sectors)
962 mda_free = mda->ops->mda_free_sectors(mda);
963 if (mda_free < freespace)
964 freespace = mda_free;
967 if (freespace == UINT64_MAX)
968 freespace = UINT64_C(0);
970 return _size64_disp(rh, mem, field, &freespace, private);
973 static int _lvcount_disp(struct dm_report *rh, struct dm_pool *mem,
974 struct dm_report_field *field,
975 const void *data, void *private)
977 const struct volume_group *vg = (const struct volume_group *) data;
980 count = vg_visible_lvs(vg);
982 return _uint32_disp(rh, mem, field, &count, private);
985 static int _lvsegcount_disp(struct dm_report *rh, struct dm_pool *mem,
986 struct dm_report_field *field,
987 const void *data, void *private)
989 const struct logical_volume *lv = (const struct logical_volume *) data;
992 count = dm_list_size(&lv->segments);
994 return _uint32_disp(rh, mem, field, &count, private);
997 static int _snapcount_disp(struct dm_report *rh, struct dm_pool *mem,
998 struct dm_report_field *field,
999 const void *data, void *private)
1001 const struct volume_group *vg = (const struct volume_group *) data;
1004 count = snapshot_count(vg);
1006 return _uint32_disp(rh, mem, field, &count, private);
1009 static int _snpercent_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
1010 struct dm_report_field *field,
1011 const void *data, void *private __attribute((unused)))
1013 const struct logical_volume *lv = (const struct logical_volume *) data;
1016 percent_range_t percent_range;
1020 /* Suppress snapshot percentage if not using driver */
1021 if (!activation()) {
1022 dm_report_field_set_value(field, "", NULL);
1026 if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
1027 log_error("dm_pool_alloc failed");
1031 if (!lv_is_cow(lv) ||
1032 (lv_info(lv->vg->cmd, lv, &info, 0, 0) && !info.exists)) {
1033 *sortval = UINT64_C(0);
1034 dm_report_field_set_value(field, "", sortval);
1038 if (!lv_snapshot_percent(lv, &snap_percent, &percent_range) ||
1039 (percent_range == PERCENT_INVALID)) {
1040 *sortval = UINT64_C(100);
1041 dm_report_field_set_value(field, "100.00", sortval);
1045 if (!(repstr = dm_pool_zalloc(mem, 8))) {
1046 log_error("dm_pool_alloc failed");
1050 if (dm_snprintf(repstr, 7, "%.2f", snap_percent) < 0) {
1051 log_error("snapshot percentage too large");
1055 *sortval = snap_percent * UINT64_C(1000);
1056 dm_report_field_set_value(field, repstr, sortval);
1061 static int _copypercent_disp(struct dm_report *rh __attribute((unused)),
1062 struct dm_pool *mem,
1063 struct dm_report_field *field,
1064 const void *data, void *private __attribute((unused)))
1066 struct logical_volume *lv = (struct logical_volume *) data;
1068 percent_range_t percent_range;
1072 if (!(sortval = dm_pool_alloc(mem, sizeof(uint64_t)))) {
1073 log_error("dm_pool_alloc failed");
1077 if ((!(lv->status & PVMOVE) && !(lv->status & MIRRORED)) ||
1078 !lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, &percent_range,
1079 NULL) || (percent_range == PERCENT_INVALID)) {
1080 *sortval = UINT64_C(0);
1081 dm_report_field_set_value(field, "", sortval);
1085 percent = copy_percent(lv, &percent_range);
1087 if (!(repstr = dm_pool_zalloc(mem, 8))) {
1088 log_error("dm_pool_alloc failed");
1092 if (dm_snprintf(repstr, 7, "%.2f", percent) < 0) {
1093 log_error("copy percentage too large");
1097 *sortval = percent * UINT64_C(1000);
1098 dm_report_field_set_value(field, repstr, sortval);
1103 /* Report object types */
1105 /* necessary for displaying something for PVs not belonging to VG */
1106 static struct format_instance _dummy_fid = {
1107 .metadata_areas = { &(_dummy_fid.metadata_areas), &(_dummy_fid.metadata_areas) },
1110 static struct volume_group _dummy_vg = {
1112 .name = (char *) "",
1113 .system_id = (char *) "",
1114 .pvs = { &(_dummy_vg.pvs), &(_dummy_vg.pvs) },
1115 .lvs = { &(_dummy_vg.lvs), &(_dummy_vg.lvs) },
1116 .tags = { &(_dummy_vg.tags), &(_dummy_vg.tags) },
1119 static void *_obj_get_vg(void *obj)
1121 struct volume_group *vg = ((struct lvm_report_object *)obj)->vg;
1123 return vg ? vg : &_dummy_vg;
1126 static void *_obj_get_lv(void *obj)
1128 return ((struct lvm_report_object *)obj)->lv;
1131 static void *_obj_get_pv(void *obj)
1133 return ((struct lvm_report_object *)obj)->pv;
1136 static void *_obj_get_seg(void *obj)
1138 return ((struct lvm_report_object *)obj)->seg;
1141 static void *_obj_get_pvseg(void *obj)
1143 return ((struct lvm_report_object *)obj)->pvseg;
1146 static const struct dm_report_object_type _report_types[] = {
1147 { VGS, "Volume Group", "vg_", _obj_get_vg },
1148 { LVS, "Logical Volume", "lv_", _obj_get_lv },
1149 { PVS, "Physical Volume", "pv_", _obj_get_pv },
1150 { LABEL, "Physical Volume Label", "pv_", _obj_get_pv },
1151 { SEGS, "Logical Volume Segment", "seg_", _obj_get_seg },
1152 { PVSEGS, "Physical Volume Segment", "pvseg_", _obj_get_pvseg },
1153 { 0, "", "", NULL },
1157 * Import column definitions
1160 #define STR DM_REPORT_FIELD_TYPE_STRING
1161 #define NUM DM_REPORT_FIELD_TYPE_NUMBER
1162 #define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, sorttype, offsetof(struct strct, field), width, id, head, &_ ## func ## _disp, desc},
1164 static struct dm_report_field_type _fields[] = {
1165 #define lv logical_volume
1166 #define pv physical_volume
1167 #define vg volume_group
1168 #define seg lv_segment
1169 #define pvseg pv_segment
1170 #include "columns.h"
1171 {0, 0, 0, 0, "", "", NULL, NULL},
1183 void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
1184 report_type_t *report_type, const char *separator,
1185 int aligned, int buffered, int headings, int field_prefixes,
1186 int quoted, int columns_as_rows)
1188 uint32_t report_flags = 0;
1192 report_flags |= DM_REPORT_OUTPUT_ALIGNED;
1195 report_flags |= DM_REPORT_OUTPUT_BUFFERED;
1198 report_flags |= DM_REPORT_OUTPUT_HEADINGS;
1201 report_flags |= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX;
1204 report_flags |= DM_REPORT_OUTPUT_FIELD_UNQUOTED;
1206 if (columns_as_rows)
1207 report_flags |= DM_REPORT_OUTPUT_COLUMNS_AS_ROWS;
1209 rh = dm_report_init(report_type, _report_types, _fields, format,
1210 separator, report_flags, keys, cmd);
1212 if (rh && field_prefixes)
1213 dm_report_set_output_field_name_prefix(rh, "lvm2_");
1219 * Create a row of data for an object
1221 int report_object(void *handle, struct volume_group *vg,
1222 struct logical_volume *lv, struct physical_volume *pv,
1223 struct lv_segment *seg, struct pv_segment *pvseg)
1225 struct lvm_report_object obj;
1227 /* The two format fields might as well match. */
1229 _dummy_fid.fmt = pv->fmt;
1237 return dm_report_object(handle, &obj);