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"
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
;
41 struct physical_volume _pv
;
42 struct logical_volume _lv
;
43 struct volume_group _vg
;
44 struct lv_segment _seg
;
45 struct pv_segment _pvseg
;
48 static char _alloc_policy_char(alloc_policy_t alloc
)
51 case ALLOC_CONTIGUOUS
:
64 static const uint64_t _minusone
= UINT64_C(-1);
67 * Data-munging functions to prepare each data type for display and sorting
69 static int _string_disp(struct dm_report
*rh
, struct dm_pool
*mem
__attribute((unused
)),
70 struct dm_report_field
*field
,
71 const void *data
, void *private __attribute((unused
)))
73 return dm_report_field_string(rh
, field
, (const char **) data
);
76 static int _dev_name_disp(struct dm_report
*rh
, struct dm_pool
*mem
__attribute((unused
)),
77 struct dm_report_field
*field
,
78 const void *data
, void *private __attribute((unused
)))
80 const char *name
= dev_name(*(const struct device
**) data
);
82 return dm_report_field_string(rh
, field
, &name
);
85 static int _format_pvsegs(struct dm_pool
*mem
, struct dm_report_field
*field
,
86 const void *data
, int range_format
)
88 const struct lv_segment
*seg
= (const struct lv_segment
*) data
;
90 const char *name
= NULL
;
94 if (!dm_pool_begin_object(mem
, 256)) {
95 log_error("dm_pool_begin_object failed");
99 for (s
= 0; s
< seg
->area_count
; s
++) {
100 switch (seg_type(seg
, s
)) {
102 name
= seg_lv(seg
, s
)->name
;
103 extent
= seg_le(seg
, s
);
106 name
= dev_name(seg_dev(seg
, s
));
107 extent
= seg_pe(seg
, s
);
109 case AREA_UNASSIGNED
:
114 if (!dm_pool_grow_object(mem
, name
, strlen(name
))) {
115 log_error("dm_pool_grow_object failed");
119 if (dm_snprintf(extent_str
, sizeof(extent_str
),
121 range_format
? ":" : "(", extent
,
122 range_format
? "-" : ")") < 0) {
123 log_error("Extent number dm_snprintf failed");
126 if (!dm_pool_grow_object(mem
, extent_str
, strlen(extent_str
))) {
127 log_error("dm_pool_grow_object failed");
132 if (dm_snprintf(extent_str
, sizeof(extent_str
),
133 "%" PRIu32
, extent
+ seg
->area_len
- 1) < 0) {
134 log_error("Extent number dm_snprintf failed");
137 if (!dm_pool_grow_object(mem
, extent_str
, strlen(extent_str
))) {
138 log_error("dm_pool_grow_object failed");
143 if ((s
!= seg
->area_count
- 1) &&
144 !dm_pool_grow_object(mem
, range_format
? " " : ",", 1)) {
145 log_error("dm_pool_grow_object failed");
150 if (!dm_pool_grow_object(mem
, "\0", 1)) {
151 log_error("dm_pool_grow_object failed");
155 dm_report_field_set_value(field
, dm_pool_end_object(mem
), NULL
);
160 static int _devices_disp(struct dm_report
*rh
__attribute((unused
)), struct dm_pool
*mem
,
161 struct dm_report_field
*field
,
162 const void *data
, void *private __attribute((unused
)))
164 return _format_pvsegs(mem
, field
, data
, 0);
167 static int _peranges_disp(struct dm_report
*rh
__attribute((unused
)), struct dm_pool
*mem
,
168 struct dm_report_field
*field
,
169 const void *data
, void *private __attribute((unused
)))
171 return _format_pvsegs(mem
, field
, data
, 1);
174 static int _tags_disp(struct dm_report
*rh
__attribute((unused
)), struct dm_pool
*mem
,
175 struct dm_report_field
*field
,
176 const void *data
, void *private __attribute((unused
)))
178 const struct dm_list
*tags
= (const struct dm_list
*) data
;
181 if (!dm_pool_begin_object(mem
, 256)) {
182 log_error("dm_pool_begin_object failed");
186 dm_list_iterate_items(sl
, tags
) {
187 if (!dm_pool_grow_object(mem
, sl
->str
, strlen(sl
->str
)) ||
188 (sl
->list
.n
!= tags
&& !dm_pool_grow_object(mem
, ",", 1))) {
189 log_error("dm_pool_grow_object failed");
194 if (!dm_pool_grow_object(mem
, "\0", 1)) {
195 log_error("dm_pool_grow_object failed");
199 dm_report_field_set_value(field
, dm_pool_end_object(mem
), NULL
);
204 static int _modules_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
205 struct dm_report_field
*field
,
206 const void *data
, void *private)
208 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
209 struct dm_list
*modules
;
211 if (!(modules
= str_list_create(mem
))) {
212 log_error("modules str_list allocation failed");
216 if (!list_lv_modules(mem
, lv
, modules
))
219 return _tags_disp(rh
, mem
, field
, modules
, private);
222 static int _vgfmt_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
223 struct dm_report_field
*field
,
224 const void *data
, void *private)
226 const struct volume_group
*vg
= (const struct volume_group
*) data
;
229 dm_report_field_set_value(field
, "", NULL
);
233 return _string_disp(rh
, mem
, field
, &vg
->fid
->fmt
->name
, private);
236 static int _pvfmt_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
237 struct dm_report_field
*field
,
238 const void *data
, void *private)
240 const struct physical_volume
*pv
=
241 (const struct physical_volume
*) data
;
244 dm_report_field_set_value(field
, "", NULL
);
248 return _string_disp(rh
, mem
, field
, &pv
->fmt
->name
, private);
251 static int _lvkmaj_disp(struct dm_report
*rh
, struct dm_pool
*mem
__attribute((unused
)),
252 struct dm_report_field
*field
,
253 const void *data
, void *private __attribute((unused
)))
255 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
258 if (lv_info(lv
->vg
->cmd
, lv
, &info
, 0, 0) && info
.exists
)
259 return dm_report_field_int(rh
, field
, &info
.major
);
261 return dm_report_field_uint64(rh
, field
, &_minusone
);
264 static int _lvkmin_disp(struct dm_report
*rh
, struct dm_pool
*mem
__attribute((unused
)),
265 struct dm_report_field
*field
,
266 const void *data
, void *private __attribute((unused
)))
268 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
271 if (lv_info(lv
->vg
->cmd
, lv
, &info
, 0, 0) && info
.exists
)
272 return dm_report_field_int(rh
, field
, &info
.minor
);
274 return dm_report_field_uint64(rh
, field
, &_minusone
);
277 static int _lv_mimage_in_sync(const struct logical_volume
*lv
)
280 percent_range_t percent_range
;
281 struct lv_segment
*mirror_seg
= find_mirror_seg(first_seg(lv
));
283 if (!(lv
->status
& MIRROR_IMAGE
) || !mirror_seg
)
286 if (!lv_mirror_percent(lv
->vg
->cmd
, mirror_seg
->lv
, 0, &percent
,
287 &percent_range
, NULL
))
290 return (percent_range
== PERCENT_100
) ? 1 : 0;
293 static int _lvstatus_disp(struct dm_report
*rh
__attribute((unused
)), struct dm_pool
*mem
,
294 struct dm_report_field
*field
,
295 const void *data
, void *private __attribute((unused
)))
297 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
301 percent_range_t percent_range
;
303 if (!(repstr
= dm_pool_zalloc(mem
, 7))) {
304 log_error("dm_pool_alloc failed");
308 /* Blank if this is a "free space" LV. */
312 if (lv
->status
& PVMOVE
)
314 else if (lv
->status
& CONVERTING
)
316 else if (lv
->status
& VIRTUAL
)
318 /* Origin takes precedence over Mirror */
319 else if (lv_is_origin(lv
))
321 else if (lv
->status
& MIRRORED
) {
322 if (lv
->status
& MIRROR_NOTSYNCED
)
326 }else if (lv
->status
& MIRROR_IMAGE
)
327 if (_lv_mimage_in_sync(lv
))
331 else if (lv
->status
& MIRROR_LOG
)
333 else if (lv_is_cow(lv
))
338 if (lv
->status
& PVMOVE
)
340 else if (lv
->status
& LVM_WRITE
)
342 else if (lv
->status
& LVM_READ
)
347 repstr
[2] = _alloc_policy_char(lv
->alloc
);
349 if (lv
->status
& LOCKED
)
350 repstr
[2] = toupper(repstr
[2]);
352 if (lv
->status
& FIXED_MINOR
)
353 repstr
[3] = 'm'; /* Fixed Minor */
357 if (lv_info(lv
->vg
->cmd
, lv
, &info
, 1, 0) && info
.exists
) {
359 repstr
[4] = 's'; /* Suspended */
360 else if (info
.live_table
)
361 repstr
[4] = 'a'; /* Active */
362 else if (info
.inactive_table
)
363 repstr
[4] = 'i'; /* Inactive with table */
365 repstr
[4] = 'd'; /* Inactive without table */
367 /* Snapshot dropped? */
368 if (info
.live_table
&& lv_is_cow(lv
) &&
369 (!lv_snapshot_percent(lv
, &snap_percent
, &percent_range
) ||
370 percent_range
== PERCENT_INVALID
)) {
371 repstr
[0] = toupper(repstr
[0]);
373 repstr
[4] = 'S'; /* Susp Inv snapshot */
375 repstr
[4] = 'I'; /* Invalid snapshot */
379 repstr
[5] = 'o'; /* Open */
388 dm_report_field_set_value(field
, repstr
, NULL
);
392 static int _pvstatus_disp(struct dm_report
*rh
__attribute((unused
)), struct dm_pool
*mem
,
393 struct dm_report_field
*field
,
394 const void *data
, void *private __attribute((unused
)))
396 const uint32_t status
= *(const uint32_t *) data
;
399 if (!(repstr
= dm_pool_zalloc(mem
, 3))) {
400 log_error("dm_pool_alloc failed");
404 if (status
& ALLOCATABLE_PV
)
409 if (status
& EXPORTED_VG
)
414 dm_report_field_set_value(field
, repstr
, NULL
);
418 static int _vgstatus_disp(struct dm_report
*rh
__attribute((unused
)), struct dm_pool
*mem
,
419 struct dm_report_field
*field
,
420 const void *data
, void *private __attribute((unused
)))
422 const struct volume_group
*vg
= (const struct volume_group
*) data
;
425 if (!(repstr
= dm_pool_zalloc(mem
, 7))) {
426 log_error("dm_pool_alloc failed");
430 if (vg
->status
& LVM_WRITE
)
435 if (vg_is_resizeable(vg
))
440 if (vg_is_exported(vg
))
445 if (vg_missing_pv_count(vg
))
450 repstr
[4] = _alloc_policy_char(vg
->alloc
);
452 if (vg_is_clustered(vg
))
457 dm_report_field_set_value(field
, repstr
, NULL
);
461 static int _segtype_disp(struct dm_report
*rh
__attribute((unused
)),
462 struct dm_pool
*mem
__attribute((unused
)),
463 struct dm_report_field
*field
,
464 const void *data
, void *private __attribute((unused
)))
466 const struct lv_segment
*seg
= (const struct lv_segment
*) data
;
468 if (seg
->area_count
== 1) {
469 dm_report_field_set_value(field
, "linear", NULL
);
473 dm_report_field_set_value(field
, seg
->segtype
->ops
->name(seg
), NULL
);
477 static int _loglv_disp(struct dm_report
*rh
, struct dm_pool
*mem
__attribute((unused
)),
478 struct dm_report_field
*field
,
479 const void *data
, void *private __attribute((unused
)))
481 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
482 struct lv_segment
*seg
;
484 dm_list_iterate_items(seg
, &lv
->segments
) {
485 if (!seg_is_mirrored(seg
) || !seg
->log_lv
)
487 return dm_report_field_string(rh
, field
,
488 (const char **) &seg
->log_lv
->name
);
491 dm_report_field_set_value(field
, "", NULL
);
495 static int _lvname_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
496 struct dm_report_field
*field
,
497 const void *data
, void *private __attribute((unused
)))
499 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
500 char *repstr
, *lvname
;
503 if (lv_is_visible(lv
)) {
505 return dm_report_field_string(rh
, field
, (const char **) &repstr
);
508 len
= strlen(lv
->name
) + 3;
509 if (!(repstr
= dm_pool_zalloc(mem
, len
))) {
510 log_error("dm_pool_alloc failed");
514 if (dm_snprintf(repstr
, len
, "[%s]", lv
->name
) < 0) {
515 log_error("lvname snprintf failed");
519 if (!(lvname
= dm_pool_strdup(mem
, lv
->name
))) {
520 log_error("dm_pool_strdup failed");
524 dm_report_field_set_value(field
, repstr
, lvname
);
529 static int _origin_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
530 struct dm_report_field
*field
,
531 const void *data
, void *private)
533 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
536 return _lvname_disp(rh
, mem
, field
, origin_from_cow(lv
), private);
538 dm_report_field_set_value(field
, "", NULL
);
542 static int _movepv_disp(struct dm_report
*rh
, struct dm_pool
*mem
__attribute((unused
)),
543 struct dm_report_field
*field
,
544 const void *data
, void *private __attribute((unused
)))
546 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
548 struct lv_segment
*seg
;
550 dm_list_iterate_items(seg
, &lv
->segments
) {
551 if (!(seg
->status
& PVMOVE
))
553 name
= dev_name(seg_dev(seg
, 0));
554 return dm_report_field_string(rh
, field
, &name
);
557 dm_report_field_set_value(field
, "", NULL
);
561 static int _convertlv_disp(struct dm_report
*rh
, struct dm_pool
*mem
__attribute((unused
)),
562 struct dm_report_field
*field
,
563 const void *data
, void *private __attribute((unused
)))
565 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
566 const char *name
= NULL
;
567 struct lv_segment
*seg
;
569 if (lv
->status
& CONVERTING
) {
570 if (lv
->status
& MIRRORED
) {
573 /* Temporary mirror is always area_num == 0 */
574 if (seg_type(seg
, 0) == AREA_LV
&&
575 is_temporary_mirror_layer(seg_lv(seg
, 0)))
576 name
= seg_lv(seg
, 0)->name
;
581 return dm_report_field_string(rh
, field
, &name
);
583 dm_report_field_set_value(field
, "", NULL
);
587 static int _size32_disp(struct dm_report
*rh
__attribute((unused
)), struct dm_pool
*mem
,
588 struct dm_report_field
*field
,
589 const void *data
, void *private)
591 const uint32_t size
= *(const uint32_t *) data
;
592 const char *disp
, *repstr
;
595 if (!*(disp
= display_size_units(private, (uint64_t) size
)))
598 if (!(repstr
= dm_pool_strdup(mem
, disp
))) {
599 log_error("dm_pool_strdup failed");
603 if (!(sortval
= dm_pool_alloc(mem
, sizeof(uint64_t)))) {
604 log_error("dm_pool_alloc failed");
608 *sortval
= (const uint64_t) size
;
610 dm_report_field_set_value(field
, repstr
, sortval
);
615 static int _size64_disp(struct dm_report
*rh
__attribute((unused
)),
617 struct dm_report_field
*field
,
618 const void *data
, void *private)
620 const uint64_t size
= *(const uint64_t *) data
;
621 const char *disp
, *repstr
;
624 if (!*(disp
= display_size_units(private, size
)))
627 if (!(repstr
= dm_pool_strdup(mem
, disp
))) {
628 log_error("dm_pool_strdup failed");
632 if (!(sortval
= dm_pool_alloc(mem
, sizeof(uint64_t)))) {
633 log_error("dm_pool_alloc failed");
638 dm_report_field_set_value(field
, repstr
, sortval
);
643 static int _lvreadahead_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
644 struct dm_report_field
*field
,
645 const void *data
, void *private __attribute((unused
)))
647 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
649 if (lv
->read_ahead
== DM_READ_AHEAD_AUTO
) {
650 dm_report_field_set_value(field
, "auto", &_minusone
);
654 return _size32_disp(rh
, mem
, field
, &lv
->read_ahead
, private);
657 static int _lvkreadahead_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
658 struct dm_report_field
*field
,
662 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
665 if (!lv_info(lv
->vg
->cmd
, lv
, &info
, 0, 1) || !info
.exists
)
666 return dm_report_field_uint64(rh
, field
, &_minusone
);
668 return _size32_disp(rh
, mem
, field
, &info
.read_ahead
, private);
671 static int _vgsize_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
672 struct dm_report_field
*field
,
673 const void *data
, void *private)
675 const struct volume_group
*vg
= (const struct volume_group
*) data
;
678 size
= (uint64_t) vg_size(vg
);
680 return _size64_disp(rh
, mem
, field
, &size
, private);
683 static int _segstart_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
684 struct dm_report_field
*field
,
685 const void *data
, void *private)
687 const struct lv_segment
*seg
= (const struct lv_segment
*) data
;
690 start
= (uint64_t) seg
->le
* seg
->lv
->vg
->extent_size
;
692 return _size64_disp(rh
, mem
, field
, &start
, private);
695 static int _segstartpe_disp(struct dm_report
*rh
,
696 struct dm_pool
*mem
__attribute((unused
)),
697 struct dm_report_field
*field
,
699 void *private __attribute((unused
)))
701 const struct lv_segment
*seg
= (const struct lv_segment
*) data
;
703 return dm_report_field_uint32(rh
, field
, &seg
->le
);
706 static int _segsize_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
707 struct dm_report_field
*field
,
708 const void *data
, void *private)
710 const struct lv_segment
*seg
= (const struct lv_segment
*) data
;
713 size
= (uint64_t) seg
->len
* seg
->lv
->vg
->extent_size
;
715 return _size64_disp(rh
, mem
, field
, &size
, private);
718 static int _chunksize_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
719 struct dm_report_field
*field
,
720 const void *data
, void *private)
722 const struct lv_segment
*seg
= (const struct lv_segment
*) data
;
725 if (lv_is_cow(seg
->lv
))
726 size
= (uint64_t) find_cow(seg
->lv
)->chunk_size
;
730 return _size64_disp(rh
, mem
, field
, &size
, private);
733 static int _originsize_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
734 struct dm_report_field
*field
,
735 const void *data
, void *private)
737 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
741 size
= (uint64_t) find_cow(lv
)->len
* lv
->vg
->extent_size
;
742 else if (lv_is_origin(lv
))
747 return _size64_disp(rh
, mem
, field
, &size
, private);
750 static int _pvused_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
751 struct dm_report_field
*field
,
752 const void *data
, void *private)
754 const struct physical_volume
*pv
=
755 (const struct physical_volume
*) data
;
761 used
= (uint64_t) pv
->pe_alloc_count
* pv
->pe_size
;
763 return _size64_disp(rh
, mem
, field
, &used
, private);
766 static int _pvfree_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
767 struct dm_report_field
*field
,
768 const void *data
, void *private)
770 const struct physical_volume
*pv
=
771 (const struct physical_volume
*) data
;
775 freespace
= pv
->size
;
777 freespace
= (uint64_t) (pv
->pe_count
- pv
->pe_alloc_count
) * pv
->pe_size
;
779 return _size64_disp(rh
, mem
, field
, &freespace
, private);
782 static int _pvsize_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
783 struct dm_report_field
*field
,
784 const void *data
, void *private)
786 const struct physical_volume
*pv
=
787 (const struct physical_volume
*) data
;
793 size
= (uint64_t) pv
->pe_count
* pv
->pe_size
;
795 return _size64_disp(rh
, mem
, field
, &size
, private);
798 static int _devsize_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
799 struct dm_report_field
*field
,
800 const void *data
, void *private)
802 const struct device
*dev
= *(const struct device
**) data
;
805 if (!dev_get_size(dev
, &size
))
808 return _size64_disp(rh
, mem
, field
, &size
, private);
811 static int _vgfree_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
812 struct dm_report_field
*field
,
813 const void *data
, void *private)
815 const struct volume_group
*vg
= (const struct volume_group
*) data
;
818 freespace
= (uint64_t) vg_free(vg
);
820 return _size64_disp(rh
, mem
, field
, &freespace
, private);
823 static int _uuid_disp(struct dm_report
*rh
__attribute((unused
)), struct dm_pool
*mem
,
824 struct dm_report_field
*field
,
825 const void *data
, void *private __attribute((unused
)))
829 if (!(repstr
= dm_pool_alloc(mem
, 40))) {
830 log_error("dm_pool_alloc failed");
834 if (!id_write_format((const struct id
*) data
, repstr
, 40))
837 dm_report_field_set_value(field
, repstr
, NULL
);
841 static int _uint32_disp(struct dm_report
*rh
, struct dm_pool
*mem
__attribute((unused
)),
842 struct dm_report_field
*field
,
843 const void *data
, void *private __attribute((unused
)))
845 return dm_report_field_uint32(rh
, field
, data
);
848 static int _int32_disp(struct dm_report
*rh
, struct dm_pool
*mem
__attribute((unused
)),
849 struct dm_report_field
*field
,
850 const void *data
, void *private __attribute((unused
)))
852 return dm_report_field_int32(rh
, field
, data
);
855 static int _pvmdas_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
856 struct dm_report_field
*field
,
857 const void *data
, void *private)
860 const struct physical_volume
*pv
=
861 (const struct physical_volume
*) data
;
863 count
= pv_mda_count(pv
);
865 return _uint32_disp(rh
, mem
, field
, &count
, private);
868 static int _vgmdas_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
869 struct dm_report_field
*field
,
870 const void *data
, void *private)
872 const struct volume_group
*vg
= (const struct volume_group
*) data
;
875 count
= vg_mda_count(vg
);
877 return _uint32_disp(rh
, mem
, field
, &count
, private);
880 static int _pvmdafree_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
881 struct dm_report_field
*field
,
882 const void *data
, void *private)
884 struct lvmcache_info
*info
;
885 uint64_t freespace
= UINT64_MAX
, mda_free
;
886 const char *pvid
= (const char *)(&((struct id
*) data
)->uuid
);
887 struct metadata_area
*mda
;
889 if ((info
= info_from_pvid(pvid
, 0)))
890 dm_list_iterate_items(mda
, &info
->mdas
) {
891 if (!mda
->ops
->mda_free_sectors
)
893 mda_free
= mda
->ops
->mda_free_sectors(mda
);
894 if (mda_free
< freespace
)
895 freespace
= mda_free
;
898 if (freespace
== UINT64_MAX
)
899 freespace
= UINT64_C(0);
901 return _size64_disp(rh
, mem
, field
, &freespace
, private);
904 static uint64_t _find_min_mda_size(struct dm_list
*mdas
)
906 uint64_t min_mda_size
= UINT64_MAX
, mda_size
;
907 struct metadata_area
*mda
;
909 dm_list_iterate_items(mda
, mdas
) {
910 if (!mda
->ops
->mda_total_sectors
)
912 mda_size
= mda
->ops
->mda_total_sectors(mda
);
913 if (mda_size
< min_mda_size
)
914 min_mda_size
= mda_size
;
917 if (min_mda_size
== UINT64_MAX
)
918 min_mda_size
= UINT64_C(0);
923 static int _pvmdasize_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
924 struct dm_report_field
*field
,
925 const void *data
, void *private)
927 struct lvmcache_info
*info
;
928 uint64_t min_mda_size
= 0;
929 const char *pvid
= (const char *)(&((struct id
*) data
)->uuid
);
931 /* PVs could have 2 mdas of different sizes (rounding effect) */
932 if ((info
= info_from_pvid(pvid
, 0)))
933 min_mda_size
= _find_min_mda_size(&info
->mdas
);
935 return _size64_disp(rh
, mem
, field
, &min_mda_size
, private);
938 static int _vgmdasize_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
939 struct dm_report_field
*field
,
940 const void *data
, void *private)
942 const struct volume_group
*vg
= (const struct volume_group
*) data
;
943 uint64_t min_mda_size
;
945 min_mda_size
= _find_min_mda_size(&vg
->fid
->metadata_areas
);
947 return _size64_disp(rh
, mem
, field
, &min_mda_size
, private);
950 static int _vgmdafree_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
951 struct dm_report_field
*field
,
952 const void *data
, void *private)
954 const struct volume_group
*vg
= (const struct volume_group
*) data
;
955 uint64_t freespace
= UINT64_MAX
, mda_free
;
956 struct metadata_area
*mda
;
958 dm_list_iterate_items(mda
, &vg
->fid
->metadata_areas
) {
959 if (!mda
->ops
->mda_free_sectors
)
961 mda_free
= mda
->ops
->mda_free_sectors(mda
);
962 if (mda_free
< freespace
)
963 freespace
= mda_free
;
966 if (freespace
== UINT64_MAX
)
967 freespace
= UINT64_C(0);
969 return _size64_disp(rh
, mem
, field
, &freespace
, private);
972 static int _lvcount_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
973 struct dm_report_field
*field
,
974 const void *data
, void *private)
976 const struct volume_group
*vg
= (const struct volume_group
*) data
;
979 count
= vg_visible_lvs(vg
);
981 return _uint32_disp(rh
, mem
, field
, &count
, private);
984 static int _lvsegcount_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
985 struct dm_report_field
*field
,
986 const void *data
, void *private)
988 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
991 count
= dm_list_size(&lv
->segments
);
993 return _uint32_disp(rh
, mem
, field
, &count
, private);
996 static int _snapcount_disp(struct dm_report
*rh
, struct dm_pool
*mem
,
997 struct dm_report_field
*field
,
998 const void *data
, void *private)
1000 const struct volume_group
*vg
= (const struct volume_group
*) data
;
1003 count
= snapshot_count(vg
);
1005 return _uint32_disp(rh
, mem
, field
, &count
, private);
1008 static int _snpercent_disp(struct dm_report
*rh
__attribute((unused
)), struct dm_pool
*mem
,
1009 struct dm_report_field
*field
,
1010 const void *data
, void *private __attribute((unused
)))
1012 const struct logical_volume
*lv
= (const struct logical_volume
*) data
;
1015 percent_range_t percent_range
;
1019 /* Suppress snapshot percentage if not using driver */
1020 if (!activation()) {
1021 dm_report_field_set_value(field
, "", NULL
);
1025 if (!(sortval
= dm_pool_alloc(mem
, sizeof(uint64_t)))) {
1026 log_error("dm_pool_alloc failed");
1030 if (!lv_is_cow(lv
) ||
1031 (lv_info(lv
->vg
->cmd
, lv
, &info
, 0, 0) && !info
.exists
)) {
1032 *sortval
= UINT64_C(0);
1033 dm_report_field_set_value(field
, "", sortval
);
1037 if (!lv_snapshot_percent(lv
, &snap_percent
, &percent_range
) ||
1038 (percent_range
== PERCENT_INVALID
)) {
1039 *sortval
= UINT64_C(100);
1040 dm_report_field_set_value(field
, "100.00", sortval
);
1044 if (!(repstr
= dm_pool_zalloc(mem
, 8))) {
1045 log_error("dm_pool_alloc failed");
1049 if (dm_snprintf(repstr
, 7, "%.2f", snap_percent
) < 0) {
1050 log_error("snapshot percentage too large");
1054 *sortval
= snap_percent
* UINT64_C(1000);
1055 dm_report_field_set_value(field
, repstr
, sortval
);
1060 static int _copypercent_disp(struct dm_report
*rh
__attribute((unused
)),
1061 struct dm_pool
*mem
,
1062 struct dm_report_field
*field
,
1063 const void *data
, void *private __attribute((unused
)))
1065 struct logical_volume
*lv
= (struct logical_volume
*) data
;
1067 percent_range_t percent_range
;
1071 if (!(sortval
= dm_pool_alloc(mem
, sizeof(uint64_t)))) {
1072 log_error("dm_pool_alloc failed");
1076 if ((!(lv
->status
& PVMOVE
) && !(lv
->status
& MIRRORED
)) ||
1077 !lv_mirror_percent(lv
->vg
->cmd
, lv
, 0, &percent
, &percent_range
,
1078 NULL
) || (percent_range
== PERCENT_INVALID
)) {
1079 *sortval
= UINT64_C(0);
1080 dm_report_field_set_value(field
, "", sortval
);
1084 percent
= copy_percent(lv
, &percent_range
);
1086 if (!(repstr
= dm_pool_zalloc(mem
, 8))) {
1087 log_error("dm_pool_alloc failed");
1091 if (dm_snprintf(repstr
, 7, "%.2f", percent
) < 0) {
1092 log_error("copy percentage too large");
1096 *sortval
= percent
* UINT64_C(1000);
1097 dm_report_field_set_value(field
, repstr
, sortval
);
1102 /* Report object types */
1104 /* necessary for displaying something for PVs not belonging to VG */
1105 static struct format_instance _dummy_fid
= {
1106 .metadata_areas
= { &(_dummy_fid
.metadata_areas
), &(_dummy_fid
.metadata_areas
) },
1109 static struct volume_group _dummy_vg
= {
1111 .name
= (char *) "",
1112 .system_id
= (char *) "",
1113 .pvs
= { &(_dummy_vg
.pvs
), &(_dummy_vg
.pvs
) },
1114 .lvs
= { &(_dummy_vg
.lvs
), &(_dummy_vg
.lvs
) },
1115 .tags
= { &(_dummy_vg
.tags
), &(_dummy_vg
.tags
) },
1118 static void *_obj_get_vg(void *obj
)
1120 struct volume_group
*vg
= ((struct lvm_report_object
*)obj
)->vg
;
1122 return vg
? vg
: &_dummy_vg
;
1125 static void *_obj_get_lv(void *obj
)
1127 return ((struct lvm_report_object
*)obj
)->lv
;
1130 static void *_obj_get_pv(void *obj
)
1132 return ((struct lvm_report_object
*)obj
)->pv
;
1135 static void *_obj_get_seg(void *obj
)
1137 return ((struct lvm_report_object
*)obj
)->seg
;
1140 static void *_obj_get_pvseg(void *obj
)
1142 return ((struct lvm_report_object
*)obj
)->pvseg
;
1145 static const struct dm_report_object_type _report_types
[] = {
1146 { VGS
, "Volume Group", "vg_", _obj_get_vg
},
1147 { LVS
, "Logical Volume", "lv_", _obj_get_lv
},
1148 { PVS
, "Physical Volume", "pv_", _obj_get_pv
},
1149 { LABEL
, "Physical Volume Label", "pv_", _obj_get_pv
},
1150 { SEGS
, "Logical Volume Segment", "seg_", _obj_get_seg
},
1151 { PVSEGS
, "Physical Volume Segment", "pvseg_", _obj_get_pvseg
},
1152 { 0, "", "", NULL
},
1156 * Import column definitions
1159 #define STR DM_REPORT_FIELD_TYPE_STRING
1160 #define NUM DM_REPORT_FIELD_TYPE_NUMBER
1161 #define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, sorttype, (off_t)((uintptr_t)&_dummy._ ## strct.field - (uintptr_t)&_dummy._ ## strct), width, id, head, &_ ## func ## _disp, desc},
1163 static struct dm_report_field_type _fields
[] = {
1164 #include "columns.h"
1165 {0, 0, 0, 0, "", "", NULL
, NULL
},
1172 void *report_init(struct cmd_context
*cmd
, const char *format
, const char *keys
,
1173 report_type_t
*report_type
, const char *separator
,
1174 int aligned
, int buffered
, int headings
, int field_prefixes
,
1175 int quoted
, int columns_as_rows
)
1177 uint32_t report_flags
= 0;
1181 report_flags
|= DM_REPORT_OUTPUT_ALIGNED
;
1184 report_flags
|= DM_REPORT_OUTPUT_BUFFERED
;
1187 report_flags
|= DM_REPORT_OUTPUT_HEADINGS
;
1190 report_flags
|= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX
;
1193 report_flags
|= DM_REPORT_OUTPUT_FIELD_UNQUOTED
;
1195 if (columns_as_rows
)
1196 report_flags
|= DM_REPORT_OUTPUT_COLUMNS_AS_ROWS
;
1198 rh
= dm_report_init(report_type
, _report_types
, _fields
, format
,
1199 separator
, report_flags
, keys
, cmd
);
1201 if (rh
&& field_prefixes
)
1202 dm_report_set_output_field_name_prefix(rh
, "lvm2_");
1208 * Create a row of data for an object
1210 int report_object(void *handle
, struct volume_group
*vg
,
1211 struct logical_volume
*lv
, struct physical_volume
*pv
,
1212 struct lv_segment
*seg
, struct pv_segment
*pvseg
)
1214 struct lvm_report_object obj
;
1216 /* The two format fields might as well match. */
1218 _dummy_fid
.fmt
= pv
->fmt
;
1226 return dm_report_object(handle
, &obj
);