Tizen 2.1 base
[external/device-mapper.git] / lib / display / display.c
1 /*
2  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3  * Copyright (C) 2004-2007 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 "display.h"
19 #include "activate.h"
20 #include "toolcontext.h"
21 #include "segtype.h"
22
23 #define SIZE_BUF 128
24
25 typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
26
27 static const struct {
28         alloc_policy_t alloc;
29         const char str[14]; /* must be changed when size extends 13 chars */
30         const char repchar;
31 } _policies[] = {
32         {
33         ALLOC_CONTIGUOUS, "contiguous", 'c'}, {
34         ALLOC_CLING, "cling", 'l'}, {
35         ALLOC_CLING_BY_TAGS, "cling_by_tags", 't'}, {   /* Only used in log mesgs */
36         ALLOC_NORMAL, "normal", 'n'}, {
37         ALLOC_ANYWHERE, "anywhere", 'a'}, {
38         ALLOC_INHERIT, "inherit", 'i'}
39 };
40
41 static const int _num_policies = sizeof(_policies) / sizeof(*_policies);
42
43 uint64_t units_to_bytes(const char *units, char *unit_type)
44 {
45         char *ptr = NULL;
46         uint64_t v;
47
48         if (isdigit(*units)) {
49                 v = (uint64_t) strtod(units, &ptr);
50                 if (ptr == units)
51                         return 0;
52                 units = ptr;
53         } else
54                 v = 1;
55
56         if (v == 1)
57                 *unit_type = *units;
58         else
59                 *unit_type = 'U';
60
61         switch (*units) {
62         case 'h':
63         case 'H':
64                 v = UINT64_C(1);
65                 *unit_type = *units;
66                 break;
67         case 'b':
68         case 'B':
69                 v *= UINT64_C(1);
70                 break;
71 #define KILO UINT64_C(1024)
72         case 's':
73         case 'S':
74                 v *= (KILO/2);
75                 break;
76         case 'k':
77                 v *= KILO;
78                 break;
79         case 'm':
80                 v *= KILO * KILO;
81                 break;
82         case 'g':
83                 v *= KILO * KILO * KILO;
84                 break;
85         case 't':
86                 v *= KILO * KILO * KILO * KILO;
87                 break;
88         case 'p':
89                 v *= KILO * KILO * KILO * KILO * KILO;
90                 break;
91         case 'e':
92                 v *= KILO * KILO * KILO * KILO * KILO * KILO;
93                 break;
94 #undef KILO
95 #define KILO UINT64_C(1000)
96         case 'K':
97                 v *= KILO;
98                 break;
99         case 'M':
100                 v *= KILO * KILO;
101                 break;
102         case 'G':
103                 v *= KILO * KILO * KILO;
104                 break;
105         case 'T':
106                 v *= KILO * KILO * KILO * KILO;
107                 break;
108         case 'P':
109                 v *= KILO * KILO * KILO * KILO * KILO;
110                 break;
111         case 'E':
112                 v *= KILO * KILO * KILO * KILO * KILO * KILO;
113                 break;
114 #undef KILO
115         default:
116                 return 0;
117         }
118
119         if (*(units + 1))
120                 return 0;
121
122         return v;
123 }
124
125 const char alloc_policy_char(alloc_policy_t alloc)
126 {
127         int i;
128
129         for (i = 0; i < _num_policies; i++)
130                 if (_policies[i].alloc == alloc)
131                         return _policies[i].repchar;
132
133         return '-';
134 }
135
136 const char *get_alloc_string(alloc_policy_t alloc)
137 {
138         int i;
139
140         for (i = 0; i < _num_policies; i++)
141                 if (_policies[i].alloc == alloc)
142                         return _policies[i].str;
143
144         return NULL;
145 }
146
147 alloc_policy_t get_alloc_from_string(const char *str)
148 {
149         int i;
150
151         /* cling_by_tags is part of cling */
152         if (!strcmp("cling_by_tags", str))
153                 return ALLOC_CLING;
154
155         for (i = 0; i < _num_policies; i++)
156                 if (!strcmp(_policies[i].str, str))
157                         return _policies[i].alloc;
158
159         /* Special case for old metadata */
160         if (!strcmp("next free", str))
161                 return ALLOC_NORMAL;
162
163         log_error("Unrecognised allocation policy %s", str);
164         return ALLOC_INVALID;
165 }
166
167 #define BASE_UNKNOWN 0
168 #define BASE_SHARED 1
169 #define BASE_1024 7
170 #define BASE_1000 13
171 #define BASE_SPECIAL 19
172 #define NUM_UNIT_PREFIXES 6
173 #define NUM_SPECIAL 3
174
175 /* Size supplied in sectors */
176 static const char *_display_size(const struct cmd_context *cmd,
177                                  uint64_t size, size_len_t sl)
178 {
179         unsigned base = BASE_UNKNOWN;
180         unsigned s;
181         int suffix = 1, precision;
182         uint64_t byte = UINT64_C(0);
183         uint64_t units = UINT64_C(1024);
184         char *size_buf = NULL;
185         const char * const size_str[][3] = {
186                 /* BASE_UNKNOWN */
187                 {"         ", "   ", " "},      /* [0] */
188
189                 /* BASE_SHARED - Used if cmd->si_unit_consistency = 0 */
190                 {" Exabyte", " EB", "E"},       /* [1] */
191                 {" Petabyte", " PB", "P"},      /* [2] */
192                 {" Terabyte", " TB", "T"},      /* [3] */
193                 {" Gigabyte", " GB", "G"},      /* [4] */
194                 {" Megabyte", " MB", "M"},      /* [5] */
195                 {" Kilobyte", " KB", "K"},      /* [6] */
196
197                 /* BASE_1024 - Used if cmd->si_unit_consistency = 1 */
198                 {" Exbibyte", " EiB", "e"},     /* [7] */
199                 {" Pebibyte", " PiB", "p"},     /* [8] */
200                 {" Tebibyte", " TiB", "t"},     /* [9] */
201                 {" Gibibyte", " GiB", "g"},     /* [10] */
202                 {" Mebibyte", " MiB", "m"},     /* [11] */
203                 {" Kibibyte", " KiB", "k"},     /* [12] */
204
205                 /* BASE_1000 - Used if cmd->si_unit_consistency = 1 */
206                 {" Exabyte",  " EB", "E"},      /* [13] */
207                 {" Petabyte", " PB", "P"},      /* [14] */
208                 {" Terabyte", " TB", "T"},      /* [15] */
209                 {" Gigabyte", " GB", "G"},      /* [16] */
210                 {" Megabyte", " MB", "M"},      /* [17] */
211                 {" Kilobyte", " kB", "K"},      /* [18] */
212
213                 /* BASE_SPECIAL */
214                 {" Byte    ", " B ", "B"},      /* [19] */
215                 {" Units   ", " Un", "U"},      /* [20] */
216                 {" Sectors ", " Se", "S"},      /* [21] */
217         };
218
219         if (!(size_buf = dm_pool_alloc(cmd->mem, SIZE_BUF))) {
220                 log_error("no memory for size display buffer");
221                 return "";
222         }
223
224         suffix = cmd->current_settings.suffix;
225
226         if (!cmd->si_unit_consistency) {
227                 /* Case-independent match */
228                 for (s = 0; s < NUM_UNIT_PREFIXES; s++)
229                         if (toupper((int) cmd->current_settings.unit_type) ==
230                             *size_str[BASE_SHARED + s][2]) {
231                                 base = BASE_SHARED;
232                                 break;
233                         }
234         } else {
235                 /* Case-dependent match for powers of 1000 */
236                 for (s = 0; s < NUM_UNIT_PREFIXES; s++)
237                         if (cmd->current_settings.unit_type ==
238                             *size_str[BASE_1000 + s][2]) {
239                                 base = BASE_1000;
240                                 break;
241                         }
242
243                 /* Case-dependent match for powers of 1024 */
244                 if (base == BASE_UNKNOWN)
245                         for (s = 0; s < NUM_UNIT_PREFIXES; s++)
246                         if (cmd->current_settings.unit_type ==
247                             *size_str[BASE_1024 + s][2]) {
248                                 base = BASE_1024;
249                                 break;
250                         }
251         }
252
253         if (base == BASE_UNKNOWN)
254                 /* Check for special units - s, b or u */
255                 for (s = 0; s < NUM_SPECIAL; s++)
256                         if (toupper((int) cmd->current_settings.unit_type) ==
257                             *size_str[BASE_SPECIAL + s][2]) {
258                                 base = BASE_SPECIAL;
259                                 break;
260                         }
261
262         if (size == UINT64_C(0)) {
263                 if (base == BASE_UNKNOWN)
264                         s = 0;
265                 sprintf(size_buf, "0%s", suffix ? size_str[base + s][sl] : "");
266                 return size_buf;
267         }
268
269         size *= UINT64_C(512);
270
271         if (base != BASE_UNKNOWN)
272                 byte = cmd->current_settings.unit_factor;
273         else {
274                 /* Human-readable style */
275                 if (cmd->current_settings.unit_type == 'H') {
276                         units = UINT64_C(1000);
277                         base = BASE_1000;
278                 } else {
279                         units = UINT64_C(1024);
280                         base = BASE_1024;
281                 }
282
283                 if (!cmd->si_unit_consistency)
284                         base = BASE_SHARED;
285
286                 byte = units * units * units * units * units * units;
287
288                 for (s = 0; s < NUM_UNIT_PREFIXES && size < byte; s++)
289                         byte /= units;
290
291                 suffix = 1;
292         }
293
294         /* FIXME Make precision configurable */
295         switch(toupper((int) cmd->current_settings.unit_type)) {
296         case 'B':
297         case 'S':
298                 precision = 0;
299                 break;
300         default:
301                 precision = 2;
302         }
303
304         snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
305                  (double) size / byte, suffix ? size_str[base + s][sl] : "");
306
307         return size_buf;
308 }
309
310 const char *display_size_long(const struct cmd_context *cmd, uint64_t size)
311 {
312         return _display_size(cmd, size, SIZE_LONG);
313 }
314
315 const char *display_size_units(const struct cmd_context *cmd, uint64_t size)
316 {
317         return _display_size(cmd, size, SIZE_UNIT);
318 }
319
320 const char *display_size(const struct cmd_context *cmd, uint64_t size)
321 {
322         return _display_size(cmd, size, SIZE_SHORT);
323 }
324
325 void pvdisplay_colons(const struct physical_volume *pv)
326 {
327         char uuid[64] __attribute__((aligned(8)));
328
329         if (!pv)
330                 return;
331
332         if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
333                 stack;
334                 return;
335         }
336
337         log_print("%s:%s:%" PRIu64 ":-1:%" PRIu64 ":%" PRIu64 ":-1:%" PRIu32 ":%u:%u:%u:%s",
338                   pv_dev_name(pv), pv->vg_name, pv->size,
339                   /* FIXME pv->pv_number, Derive or remove? */
340                   pv->status,   /* FIXME Support old or new format here? */
341                   pv->status & ALLOCATABLE_PV,  /* FIXME remove? */
342                   /* FIXME pv->lv_cur, Remove? */
343                   pv->pe_size / 2,
344                   pv->pe_count,
345                   pv->pe_count - pv->pe_alloc_count,
346                   pv->pe_alloc_count, *uuid ? uuid : "none");
347 }
348
349 void pvdisplay_segments(const struct physical_volume *pv)
350 {
351         const struct pv_segment *pvseg;
352
353         if (pv->pe_size)
354                 log_print("--- Physical Segments ---");
355
356         dm_list_iterate_items(pvseg, &pv->segments) {
357                 log_print("Physical extent %u to %u:",
358                           pvseg->pe, pvseg->pe + pvseg->len - 1);
359
360                 if (pvseg_is_allocated(pvseg)) {
361                         log_print("  Logical volume\t%s%s/%s",
362                                   pvseg->lvseg->lv->vg->cmd->dev_dir,
363                                   pvseg->lvseg->lv->vg->name,
364                                   pvseg->lvseg->lv->name);
365                         log_print("  Logical extents\t%d to %d",
366                                   pvseg->lvseg->le, pvseg->lvseg->le +
367                                   pvseg->lvseg->len - 1);
368                 } else
369                         log_print("  FREE");
370         }
371
372         log_print(" ");
373 }
374
375 /* FIXME Include label fields */
376 void pvdisplay_full(const struct cmd_context *cmd,
377                     const struct physical_volume *pv,
378                     void *handle __attribute__((unused)))
379 {
380         char uuid[64] __attribute__((aligned(8)));
381         const char *size;
382
383         uint32_t pe_free;
384         uint64_t data_size, pvsize, unusable;
385
386         if (!pv)
387                 return;
388
389         if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
390                 stack;
391                 return;
392         }
393
394         log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW ");
395         log_print("PV Name               %s", pv_dev_name(pv));
396         log_print("VG Name               %s%s",
397                   is_orphan(pv) ? "" : pv->vg_name,
398                   pv->status & EXPORTED_VG ? " (exported)" : "");
399
400         data_size = (uint64_t) pv->pe_count * pv->pe_size;
401         if (pv->size > data_size + pv->pe_start) {
402                 pvsize = pv->size;
403                 unusable = pvsize - data_size;
404         } else {
405                 pvsize = data_size + pv->pe_start;
406                 unusable = pvsize - pv->size;
407         }
408
409         size = display_size(cmd, pvsize);
410         if (data_size)
411                 log_print("PV Size               %s / not usable %s",   /*  [LVM: %s]", */
412                           size, display_size(cmd, unusable));
413         else
414                 log_print("PV Size               %s", size);
415
416         /* PV number not part of LVM2 design
417            log_print("PV#                   %u", pv->pv_number);
418          */
419
420         pe_free = pv->pe_count - pv->pe_alloc_count;
421         if (pv->pe_count && (pv->status & ALLOCATABLE_PV))
422                 log_print("Allocatable           yes %s",
423                           (!pe_free && pv->pe_count) ? "(but full)" : "");
424         else
425                 log_print("Allocatable           NO");
426
427         /* LV count is no longer available when displaying PV
428            log_print("Cur LV                %u", vg->lv_count);
429          */
430
431         if (cmd->si_unit_consistency)
432                 log_print("PE Size               %s", display_size(cmd, (uint64_t) pv->pe_size));
433         else
434                 log_print("PE Size (KByte)       %" PRIu32, pv->pe_size / 2);
435
436         log_print("Total PE              %u", pv->pe_count);
437         log_print("Free PE               %" PRIu32, pe_free);
438         log_print("Allocated PE          %u", pv->pe_alloc_count);
439         log_print("PV UUID               %s", *uuid ? uuid : "none");
440         log_print(" ");
441 }
442
443 int pvdisplay_short(const struct cmd_context *cmd __attribute__((unused)),
444                     const struct volume_group *vg __attribute__((unused)),
445                     const struct physical_volume *pv,
446                     void *handle __attribute__((unused)))
447 {
448         char uuid[64] __attribute__((aligned(8)));
449
450         if (!pv)
451                 return 0;
452
453         if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
454                 return_0;
455
456         log_print("PV Name               %s     ", pv_dev_name(pv));
457         /* FIXME  pv->pv_number); */
458         log_print("PV UUID               %s", *uuid ? uuid : "none");
459         log_print("PV Status             %sallocatable",
460                   (pv->status & ALLOCATABLE_PV) ? "" : "NOT ");
461         log_print("Total PE / Free PE    %u / %u",
462                   pv->pe_count, pv->pe_count - pv->pe_alloc_count);
463
464         log_print(" ");
465         return 0;
466 }
467
468 void lvdisplay_colons(const struct logical_volume *lv)
469 {
470         int inkernel;
471         struct lvinfo info;
472         inkernel = lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) && info.exists;
473
474         log_print("%s%s/%s:%s:%" PRIu64 ":%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
475                   lv->vg->cmd->dev_dir,
476                   lv->vg->name,
477                   lv->name,
478                   lv->vg->name,
479                   (lv->status & (LVM_READ | LVM_WRITE)) >> 8, inkernel ? 1 : 0,
480                   /* FIXME lv->lv_number,  */
481                   inkernel ? info.open_count : 0, lv->size, lv->le_count,
482                   /* FIXME Add num allocated to struct! lv->lv_allocated_le, */
483                   (lv->alloc == ALLOC_CONTIGUOUS ? 2 : 0), lv->read_ahead,
484                   inkernel ? info.major : -1, inkernel ? info.minor : -1);
485 }
486
487 int lvdisplay_full(struct cmd_context *cmd,
488                    const struct logical_volume *lv,
489                    void *handle __attribute__((unused)))
490 {
491         struct lvinfo info;
492         int inkernel, snap_active = 0;
493         char uuid[64] __attribute__((aligned(8)));
494         struct lv_segment *snap_seg = NULL, *mirror_seg = NULL;
495         percent_t snap_percent;
496
497         if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid)))
498                 return_0;
499
500         inkernel = lv_info(cmd, lv, 0, &info, 1, 1) && info.exists;
501
502         log_print("--- Logical volume ---");
503
504         log_print("LV Name                %s%s/%s", lv->vg->cmd->dev_dir,
505                   lv->vg->name, lv->name);
506         log_print("VG Name                %s", lv->vg->name);
507
508         log_print("LV UUID                %s", uuid);
509
510         log_print("LV Write Access        %s",
511                   (lv->status & LVM_WRITE) ? "read/write" : "read only");
512
513         if (lv_is_origin(lv)) {
514                 log_print("LV snapshot status     source of");
515
516                 dm_list_iterate_items_gen(snap_seg, &lv->snapshot_segs,
517                                        origin_list) {
518                         if (inkernel &&
519                             (snap_active = lv_snapshot_percent(snap_seg->cow,
520                                                                &snap_percent)))
521                                 if (snap_percent == PERCENT_INVALID)
522                                         snap_active = 0;
523                         log_print("                       %s%s/%s [%s]",
524                                   lv->vg->cmd->dev_dir, lv->vg->name,
525                                   snap_seg->cow->name,
526                                   snap_active ? "active" : "INACTIVE");
527                 }
528                 snap_seg = NULL;
529         } else if ((snap_seg = find_cow(lv))) {
530                 if (inkernel &&
531                     (snap_active = lv_snapshot_percent(snap_seg->cow,
532                                                        &snap_percent)))
533                         if (snap_percent == PERCENT_INVALID)
534                                 snap_active = 0;
535
536                 log_print("LV snapshot status     %s destination for %s%s/%s",
537                           snap_active ? "active" : "INACTIVE",
538                           lv->vg->cmd->dev_dir, lv->vg->name,
539                           snap_seg->origin->name);
540         }
541
542         if (inkernel && info.suspended)
543                 log_print("LV Status              suspended");
544         else
545                 log_print("LV Status              %savailable",
546                           inkernel ? "" : "NOT ");
547
548 /********* FIXME lv_number
549     log_print("LV #                   %u", lv->lv_number + 1);
550 ************/
551
552         if (inkernel)
553                 log_print("# open                 %u", info.open_count);
554
555         log_print("LV Size                %s",
556                   display_size(cmd,
557                                snap_seg ? snap_seg->origin->size : lv->size));
558
559         log_print("Current LE             %u",
560                   snap_seg ? snap_seg->origin->le_count : lv->le_count);
561
562         if (snap_seg) {
563                 log_print("COW-table size         %s",
564                           display_size(cmd, (uint64_t) lv->size));
565                 log_print("COW-table LE           %u", lv->le_count);
566
567                 if (snap_active)
568                         log_print("Allocated to snapshot  %.2f%% ",
569                                   percent_to_float(snap_percent));
570
571                 log_print("Snapshot chunk size    %s",
572                           display_size(cmd, (uint64_t) snap_seg->chunk_size));
573         }
574
575         if (lv->status & MIRRORED) {
576                 mirror_seg = first_seg(lv);
577                 log_print("Mirrored volumes       %" PRIu32, mirror_seg->area_count);
578                 if (lv->status & CONVERTING)
579                         log_print("LV type        Mirror undergoing conversion");
580         }
581
582         log_print("Segments               %u", dm_list_size(&lv->segments));
583
584 /********* FIXME Stripes & stripesize for each segment
585         log_print("Stripe size            %s", display_size(cmd, (uint64_t) lv->stripesize));
586 ***********/
587
588         log_print("Allocation             %s", get_alloc_string(lv->alloc));
589         if (lv->read_ahead == DM_READ_AHEAD_AUTO)
590                 log_print("Read ahead sectors     auto");
591         else if (lv->read_ahead == DM_READ_AHEAD_NONE)
592                 log_print("Read ahead sectors     0");
593         else
594                 log_print("Read ahead sectors     %u", lv->read_ahead);
595
596         if (inkernel && lv->read_ahead != info.read_ahead)
597                 log_print("- currently set to     %u", info.read_ahead);
598
599         if (lv->status & FIXED_MINOR) {
600                 if (lv->major >= 0)
601                         log_print("Persistent major       %d", lv->major);
602                 log_print("Persistent minor       %d", lv->minor);
603         }
604
605         if (inkernel)
606                 log_print("Block device           %d:%d", info.major,
607                           info.minor);
608
609         log_print(" ");
610
611         return 0;
612 }
613
614 void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
615 {
616         switch (seg_type(seg, s)) {
617         case AREA_PV:
618                 /* FIXME Re-check the conditions for 'Missing' */
619                 log_print("%sPhysical volume\t%s", pre,
620                           seg_pv(seg, s) ?
621                           pv_dev_name(seg_pv(seg, s)) :
622                             "Missing");
623
624                 if (seg_pv(seg, s))
625                         log_print("%sPhysical extents\t%d to %d", pre,
626                                   seg_pe(seg, s),
627                                   seg_pe(seg, s) + seg->area_len - 1);
628                 break;
629         case AREA_LV:
630                 log_print("%sLogical volume\t%s", pre,
631                           seg_lv(seg, s) ?
632                           seg_lv(seg, s)->name : "Missing");
633
634                 if (seg_lv(seg, s))
635                         log_print("%sLogical extents\t%d to %d", pre,
636                                   seg_le(seg, s),
637                                   seg_le(seg, s) + seg->area_len - 1);
638                 break;
639         case AREA_UNASSIGNED:
640                 log_print("%sUnassigned area", pre);
641         }
642 }
643
644 int lvdisplay_segments(const struct logical_volume *lv)
645 {
646         const struct lv_segment *seg;
647
648         log_print("--- Segments ---");
649
650         dm_list_iterate_items(seg, &lv->segments) {
651                 log_print("Logical extent %u to %u:",
652                           seg->le, seg->le + seg->len - 1);
653
654                 log_print("  Type\t\t%s", seg->segtype->ops->name(seg));
655
656                 if (seg->segtype->ops->display)
657                         seg->segtype->ops->display(seg);
658         }
659
660         log_print(" ");
661         return 1;
662 }
663
664 void vgdisplay_extents(const struct volume_group *vg __attribute__((unused)))
665 {
666 }
667
668 void vgdisplay_full(const struct volume_group *vg)
669 {
670         uint32_t access_str;
671         uint32_t active_pvs;
672         char uuid[64] __attribute__((aligned(8)));
673
674         active_pvs = vg->pv_count - vg_missing_pv_count(vg);
675
676         log_print("--- Volume group ---");
677         log_print("VG Name               %s", vg->name);
678         log_print("System ID             %s", vg->system_id);
679         log_print("Format                %s", vg->fid->fmt->name);
680         if (vg->fid->fmt->features & FMT_MDAS) {
681                 log_print("Metadata Areas        %d",
682                           vg_mda_count(vg));
683                 log_print("Metadata Sequence No  %d", vg->seqno);
684         }
685         access_str = vg->status & (LVM_READ | LVM_WRITE);
686         log_print("VG Access             %s%s%s%s",
687                   access_str == (LVM_READ | LVM_WRITE) ? "read/write" : "",
688                   access_str == LVM_READ ? "read" : "",
689                   access_str == LVM_WRITE ? "write" : "",
690                   access_str == 0 ? "error" : "");
691         log_print("VG Status             %s%sresizable",
692                   vg_is_exported(vg) ? "exported/" : "",
693                   vg_is_resizeable(vg) ? "" : "NOT ");
694         /* vg number not part of LVM2 design
695            log_print ("VG #                  %u\n", vg->vg_number);
696          */
697         if (vg_is_clustered(vg)) {
698                 log_print("Clustered             yes");
699                 log_print("Shared                %s",
700                           vg->status & SHARED ? "yes" : "no");
701         }
702
703         log_print("MAX LV                %u", vg->max_lv);
704         log_print("Cur LV                %u", vg_visible_lvs(vg));
705         log_print("Open LV               %u", lvs_in_vg_opened(vg));
706 /****** FIXME Max LV Size
707       log_print ( "MAX LV Size           %s",
708                ( s1 = display_size ( LVM_LV_SIZE_MAX(vg))));
709       free ( s1);
710 *********/
711         log_print("Max PV                %u", vg->max_pv);
712         log_print("Cur PV                %u", vg->pv_count);
713         log_print("Act PV                %u", active_pvs);
714
715         log_print("VG Size               %s",
716                   display_size(vg->cmd,
717                                (uint64_t) vg->extent_count * vg->extent_size));
718
719         log_print("PE Size               %s",
720                   display_size(vg->cmd, (uint64_t) vg->extent_size));
721
722         log_print("Total PE              %u", vg->extent_count);
723
724         log_print("Alloc PE / Size       %u / %s",
725                   vg->extent_count - vg->free_count,
726                   display_size(vg->cmd,
727                                ((uint64_t) vg->extent_count - vg->free_count) *
728                                vg->extent_size));
729
730         log_print("Free  PE / Size       %u / %s", vg->free_count,
731                   display_size(vg->cmd, vg_free(vg)));
732
733         if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
734                 stack;
735                 return;
736         }
737
738         log_print("VG UUID               %s", uuid);
739         log_print(" ");
740 }
741
742 void vgdisplay_colons(const struct volume_group *vg)
743 {
744         uint32_t active_pvs;
745         const char *access_str;
746         char uuid[64] __attribute__((aligned(8)));
747
748         active_pvs = vg->pv_count - vg_missing_pv_count(vg);
749
750         switch (vg->status & (LVM_READ | LVM_WRITE)) {
751                 case LVM_READ | LVM_WRITE:
752                         access_str = "r/w";
753                         break;
754                 case LVM_READ:
755                         access_str = "r";
756                         break;
757                 case LVM_WRITE:
758                         access_str = "w";
759                         break;
760                 default:
761                         access_str = "";
762         }
763
764         if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
765                 stack;
766                 return;
767         }
768
769         log_print("%s:%s:%" PRIu64 ":-1:%u:%u:%u:-1:%u:%u:%u:%" PRIu64 ":%" PRIu32
770                   ":%u:%u:%u:%s",
771                 vg->name,
772                 access_str,
773                 vg->status,
774                 /* internal volume group number; obsolete */
775                 vg->max_lv,
776                 vg_visible_lvs(vg),
777                 lvs_in_vg_opened(vg),
778                 /* FIXME: maximum logical volume size */
779                 vg->max_pv,
780                 vg->pv_count,
781                 active_pvs,
782                 (uint64_t) vg->extent_count * (vg->extent_size / 2),
783                 vg->extent_size / 2,
784                 vg->extent_count,
785                 vg->extent_count - vg->free_count,
786                 vg->free_count,
787                 uuid[0] ? uuid : "none");
788 }
789
790 void vgdisplay_short(const struct volume_group *vg)
791 {
792         log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
793 /********* FIXME if "open" print "/used" else print "/idle"???  ******/
794                   display_size(vg->cmd,
795                                (uint64_t) vg->extent_count * vg->extent_size),
796                   display_size(vg->cmd,
797                                ((uint64_t) vg->extent_count -
798                                 vg->free_count) * vg->extent_size),
799                   display_size(vg->cmd, vg_free(vg)));
800 }
801
802 void display_formats(const struct cmd_context *cmd)
803 {
804         const struct format_type *fmt;
805
806         dm_list_iterate_items(fmt, &cmd->formats) {
807                 log_print("%s", fmt->name);
808         }
809 }
810
811 void display_segtypes(const struct cmd_context *cmd)
812 {
813         const struct segment_type *segtype;
814
815         dm_list_iterate_items(segtype, &cmd->segtypes) {
816                 log_print("%s", segtype->name);
817         }
818 }
819
820 char yes_no_prompt(const char *prompt, ...)
821 {
822         int c = 0, ret = 0;
823         va_list ap;
824
825         sigint_allow();
826         do {
827                 if (c == '\n' || !c) {
828                         va_start(ap, prompt);
829                         vprintf(prompt, ap);
830                         va_end(ap);
831                         fflush(stdout);
832                 }
833
834                 if ((c = getchar()) == EOF) {
835                         ret = 'n';
836                         break;
837                 }
838
839                 c = tolower(c);
840                 if ((c == 'y') || (c == 'n'))
841                         ret = c;
842         } while (!ret || c != '\n');
843
844         sigint_restore();
845
846         if (c != '\n')
847                 printf("\n");
848
849         return ret;
850 }
851