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