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