display.c revision 1.1.1.3 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