1*7c604eeaShaad /*	$NetBSD: display.c,v 1.1.1.3 2009/12/02 00:26:43 haad Exp $	*/
256a34939Shaad 
356a34939Shaad /*
456a34939Shaad  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
556a34939Shaad  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
656a34939Shaad  *
756a34939Shaad  * This file is part of LVM2.
856a34939Shaad  *
956a34939Shaad  * This copyrighted material is made available to anyone wishing to use,
1056a34939Shaad  * modify, copy, or redistribute it subject to the terms and conditions
1156a34939Shaad  * of the GNU Lesser General Public License v.2.1.
1256a34939Shaad  *
1356a34939Shaad  * You should have received a copy of the GNU Lesser General Public License
1456a34939Shaad  * along with this program; if not, write to the Free Software Foundation,
1556a34939Shaad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1656a34939Shaad  */
1756a34939Shaad 
1856a34939Shaad #include "lib.h"
1956a34939Shaad #include "metadata.h"
2056a34939Shaad #include "display.h"
2156a34939Shaad #include "activate.h"
2256a34939Shaad #include "toolcontext.h"
2356a34939Shaad #include "segtype.h"
2456a34939Shaad 
2556a34939Shaad #define SIZE_BUF 128
2656a34939Shaad 
2756a34939Shaad typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
2856a34939Shaad 
2956a34939Shaad static const struct {
3056a34939Shaad 	alloc_policy_t alloc;
3156a34939Shaad 	const char str[12]; /* must be changed when size extends 11 chars */
3256a34939Shaad } _policies[] = {
3356a34939Shaad 	{
3456a34939Shaad 	ALLOC_CONTIGUOUS, "contiguous"}, {
3556a34939Shaad 	ALLOC_CLING, "cling"}, {
3656a34939Shaad 	ALLOC_NORMAL, "normal"}, {
3756a34939Shaad 	ALLOC_ANYWHERE, "anywhere"}, {
3856a34939Shaad 	ALLOC_INHERIT, "inherit"}
3956a34939Shaad };
4056a34939Shaad 
4156a34939Shaad static const int _num_policies = sizeof(_policies) / sizeof(*_policies);
4256a34939Shaad 
units_to_bytes(const char * units,char * unit_type)4356a34939Shaad uint64_t units_to_bytes(const char *units, char *unit_type)
4456a34939Shaad {
4556a34939Shaad 	char *ptr = NULL;
4656a34939Shaad 	uint64_t v;
4756a34939Shaad 
4856a34939Shaad 	if (isdigit(*units)) {
4956a34939Shaad 		v = (uint64_t) strtod(units, &ptr);
5056a34939Shaad 		if (ptr == units)
5156a34939Shaad 			return 0;
5256a34939Shaad 		units = ptr;
5356a34939Shaad 	} else
5456a34939Shaad 		v = 1;
5556a34939Shaad 
5656a34939Shaad 	if (v == 1)
5756a34939Shaad 		*unit_type = *units;
5856a34939Shaad 	else
5956a34939Shaad 		*unit_type = 'U';
6056a34939Shaad 
6156a34939Shaad 	switch (*units) {
6256a34939Shaad 	case 'h':
6356a34939Shaad 	case 'H':
6456a34939Shaad 		v = UINT64_C(1);
6556a34939Shaad 		*unit_type = *units;
6656a34939Shaad 		break;
6756a34939Shaad 	case 'b':
6856a34939Shaad 	case 'B':
6956a34939Shaad 		v *= UINT64_C(1);
7056a34939Shaad 		break;
7156a34939Shaad #define KILO UINT64_C(1024)
72*7c604eeaShaad 	case 's':
73*7c604eeaShaad 	case 'S':
74*7c604eeaShaad 		v *= (KILO/2);
75*7c604eeaShaad 		break;
7656a34939Shaad 	case 'k':
7756a34939Shaad 		v *= KILO;
7856a34939Shaad 		break;
7956a34939Shaad 	case 'm':
8056a34939Shaad 		v *= KILO * KILO;
8156a34939Shaad 		break;
8256a34939Shaad 	case 'g':
8356a34939Shaad 		v *= KILO * KILO * KILO;
8456a34939Shaad 		break;
8556a34939Shaad 	case 't':
8656a34939Shaad 		v *= KILO * KILO * KILO * KILO;
8756a34939Shaad 		break;
8856a34939Shaad 	case 'p':
8956a34939Shaad 		v *= KILO * KILO * KILO * KILO * KILO;
9056a34939Shaad 		break;
9156a34939Shaad 	case 'e':
9256a34939Shaad 		v *= KILO * KILO * KILO * KILO * KILO * KILO;
9356a34939Shaad 		break;
9456a34939Shaad #undef KILO
9556a34939Shaad #define KILO UINT64_C(1000)
9656a34939Shaad 	case 'K':
9756a34939Shaad 		v *= KILO;
9856a34939Shaad 		break;
9956a34939Shaad 	case 'M':
10056a34939Shaad 		v *= KILO * KILO;
10156a34939Shaad 		break;
10256a34939Shaad 	case 'G':
10356a34939Shaad 		v *= KILO * KILO * KILO;
10456a34939Shaad 		break;
10556a34939Shaad 	case 'T':
10656a34939Shaad 		v *= KILO * KILO * KILO * KILO;
10756a34939Shaad 		break;
10856a34939Shaad 	case 'P':
10956a34939Shaad 		v *= KILO * KILO * KILO * KILO * KILO;
11056a34939Shaad 		break;
11156a34939Shaad 	case 'E':
11256a34939Shaad 		v *= KILO * KILO * KILO * KILO * KILO * KILO;
11356a34939Shaad 		break;
11456a34939Shaad #undef KILO
11556a34939Shaad 	default:
11656a34939Shaad 		return 0;
11756a34939Shaad 	}
11856a34939Shaad 
11956a34939Shaad 	if (*(units + 1))
12056a34939Shaad 		return 0;
12156a34939Shaad 
12256a34939Shaad 	return v;
12356a34939Shaad }
12456a34939Shaad 
get_alloc_string(alloc_policy_t alloc)12556a34939Shaad const char *get_alloc_string(alloc_policy_t alloc)
12656a34939Shaad {
12756a34939Shaad 	int i;
12856a34939Shaad 
12956a34939Shaad 	for (i = 0; i < _num_policies; i++)
13056a34939Shaad 		if (_policies[i].alloc == alloc)
13156a34939Shaad 			return _policies[i].str;
13256a34939Shaad 
13356a34939Shaad 	return NULL;
13456a34939Shaad }
13556a34939Shaad 
get_alloc_from_string(const char * str)13656a34939Shaad alloc_policy_t get_alloc_from_string(const char *str)
13756a34939Shaad {
13856a34939Shaad 	int i;
13956a34939Shaad 
14056a34939Shaad 	for (i = 0; i < _num_policies; i++)
14156a34939Shaad 		if (!strcmp(_policies[i].str, str))
14256a34939Shaad 			return _policies[i].alloc;
14356a34939Shaad 
14456a34939Shaad 	/* Special case for old metadata */
14556a34939Shaad 	if(!strcmp("next free", str))
14656a34939Shaad 		return ALLOC_NORMAL;
14756a34939Shaad 
14856a34939Shaad 	log_error("Unrecognised allocation policy %s", str);
14956a34939Shaad 	return ALLOC_INVALID;
15056a34939Shaad }
15156a34939Shaad 
152*7c604eeaShaad #define BASE_UNKNOWN 0
153*7c604eeaShaad #define BASE_SHARED 1
154*7c604eeaShaad #define BASE_1024 7
155*7c604eeaShaad #define BASE_1000 13
156*7c604eeaShaad #define BASE_SPECIAL 19
157*7c604eeaShaad #define NUM_UNIT_PREFIXES 6
158*7c604eeaShaad #define NUM_SPECIAL 3
159*7c604eeaShaad 
16056a34939Shaad /* Size supplied in sectors */
_display_size(const struct cmd_context * cmd,uint64_t size,size_len_t sl)16156a34939Shaad static const char *_display_size(const struct cmd_context *cmd,
16256a34939Shaad 				 uint64_t size, size_len_t sl)
16356a34939Shaad {
164*7c604eeaShaad 	unsigned base = BASE_UNKNOWN;
165*7c604eeaShaad 	unsigned s;
16656a34939Shaad 	int suffix = 1, precision;
16756a34939Shaad 	uint64_t byte = UINT64_C(0);
16856a34939Shaad 	uint64_t units = UINT64_C(1024);
16956a34939Shaad 	char *size_buf = NULL;
17056a34939Shaad 	const char * const size_str[][3] = {
171*7c604eeaShaad 		/* BASE_UNKNOWN */
172*7c604eeaShaad 		{"         ", "   ", " "},	/* [0] */
173*7c604eeaShaad 
174*7c604eeaShaad 		/* BASE_SHARED - Used if cmd->si_unit_consistency = 0 */
175*7c604eeaShaad 		{" Exabyte", " EB", "E"},	/* [1] */
176*7c604eeaShaad 		{" Petabyte", " PB", "P"},	/* [2] */
177*7c604eeaShaad 		{" Terabyte", " TB", "T"},	/* [3] */
178*7c604eeaShaad 		{" Gigabyte", " GB", "G"},	/* [4] */
179*7c604eeaShaad 		{" Megabyte", " MB", "M"},	/* [5] */
180*7c604eeaShaad 		{" Kilobyte", " KB", "K"},	/* [6] */
181*7c604eeaShaad 
182*7c604eeaShaad 		/* BASE_1024 - Used if cmd->si_unit_consistency = 1 */
183*7c604eeaShaad 		{" Exbibyte", " EiB", "e"},	/* [7] */
184*7c604eeaShaad 		{" Pebibyte", " PiB", "p"},	/* [8] */
185*7c604eeaShaad 		{" Tebibyte", " TiB", "t"},	/* [9] */
186*7c604eeaShaad 		{" Gibibyte", " GiB", "g"},	/* [10] */
187*7c604eeaShaad 		{" Mebibyte", " MiB", "m"},	/* [11] */
188*7c604eeaShaad 		{" Kibibyte", " KiB", "k"},	/* [12] */
189*7c604eeaShaad 
190*7c604eeaShaad 		/* BASE_1000 - Used if cmd->si_unit_consistency = 1 */
191*7c604eeaShaad 		{" Exabyte",  " EB", "E"},	/* [13] */
192*7c604eeaShaad 		{" Petabyte", " PB", "P"},	/* [14] */
193*7c604eeaShaad 		{" Terabyte", " TB", "T"},	/* [15] */
194*7c604eeaShaad 		{" Gigabyte", " GB", "G"},	/* [16] */
195*7c604eeaShaad 		{" Megabyte", " MB", "M"},	/* [17] */
196*7c604eeaShaad 		{" Kilobyte", " kB", "K"},	/* [18] */
197*7c604eeaShaad 
198*7c604eeaShaad 		/* BASE_SPECIAL */
199*7c604eeaShaad 		{" Byte    ", " B ", "B"},	/* [19] */
200*7c604eeaShaad 		{" Units   ", " Un", "U"},	/* [20] */
201*7c604eeaShaad 		{" Sectors ", " Se", "S"},	/* [21] */
20256a34939Shaad 	};
20356a34939Shaad 
20456a34939Shaad 	if (!(size_buf = dm_pool_alloc(cmd->mem, SIZE_BUF))) {
20556a34939Shaad 		log_error("no memory for size display buffer");
20656a34939Shaad 		return "";
20756a34939Shaad 	}
20856a34939Shaad 
20956a34939Shaad 	suffix = cmd->current_settings.suffix;
21056a34939Shaad 
211*7c604eeaShaad 	if (!cmd->si_unit_consistency) {
212*7c604eeaShaad 		/* Case-independent match */
213*7c604eeaShaad 		for (s = 0; s < NUM_UNIT_PREFIXES; s++)
21456a34939Shaad 			if (toupper((int) cmd->current_settings.unit_type) ==
215*7c604eeaShaad 			    *size_str[BASE_SHARED + s][2]) {
216*7c604eeaShaad 				base = BASE_SHARED;
21756a34939Shaad 				break;
218*7c604eeaShaad 			}
219*7c604eeaShaad 	} else {
220*7c604eeaShaad 		/* Case-dependent match for powers of 1000 */
221*7c604eeaShaad 		for (s = 0; s < NUM_UNIT_PREFIXES; s++)
222*7c604eeaShaad 			if (cmd->current_settings.unit_type ==
223*7c604eeaShaad 			    *size_str[BASE_1000 + s][2]) {
224*7c604eeaShaad 				base = BASE_1000;
225*7c604eeaShaad 				break;
226*7c604eeaShaad 			}
227*7c604eeaShaad 
228*7c604eeaShaad 		/* Case-dependent match for powers of 1024 */
229*7c604eeaShaad 		if (base == BASE_UNKNOWN)
230*7c604eeaShaad 			for (s = 0; s < NUM_UNIT_PREFIXES; s++)
231*7c604eeaShaad 			if (cmd->current_settings.unit_type ==
232*7c604eeaShaad 			    *size_str[BASE_1024 + s][2]) {
233*7c604eeaShaad 				base = BASE_1024;
234*7c604eeaShaad 				break;
235*7c604eeaShaad 			}
236*7c604eeaShaad 	}
237*7c604eeaShaad 
238*7c604eeaShaad 	if (base == BASE_UNKNOWN)
239*7c604eeaShaad 		/* Check for special units - s, b or u */
240*7c604eeaShaad 		for (s = 0; s < NUM_SPECIAL; s++)
241*7c604eeaShaad 			if (toupper((int) cmd->current_settings.unit_type) ==
242*7c604eeaShaad 			    *size_str[BASE_SPECIAL + s][2]) {
243*7c604eeaShaad 				base = BASE_SPECIAL;
244*7c604eeaShaad 				break;
245*7c604eeaShaad 			}
24656a34939Shaad 
24756a34939Shaad 	if (size == UINT64_C(0)) {
248*7c604eeaShaad 		if (base == BASE_UNKNOWN)
249*7c604eeaShaad 			s = 0;
250*7c604eeaShaad 		sprintf(size_buf, "0%s", suffix ? size_str[base + s][sl] : "");
25156a34939Shaad 		return size_buf;
25256a34939Shaad 	}
25356a34939Shaad 
25456a34939Shaad 	size *= UINT64_C(512);
25556a34939Shaad 
256*7c604eeaShaad 	if (base != BASE_UNKNOWN)
25756a34939Shaad 		byte = cmd->current_settings.unit_factor;
25856a34939Shaad 	else {
259*7c604eeaShaad 		/* Human-readable style */
260*7c604eeaShaad 		if (cmd->current_settings.unit_type == 'H') {
26156a34939Shaad 			units = UINT64_C(1000);
262*7c604eeaShaad 			base = BASE_1000;
263*7c604eeaShaad 		} else {
26456a34939Shaad 			units = UINT64_C(1024);
265*7c604eeaShaad 			base = BASE_1024;
266*7c604eeaShaad 		}
267*7c604eeaShaad 
268*7c604eeaShaad 		if (!cmd->si_unit_consistency)
269*7c604eeaShaad 			base = BASE_SHARED;
270*7c604eeaShaad 
27156a34939Shaad 		byte = units * units * units * units * units * units;
272*7c604eeaShaad 
273*7c604eeaShaad 		for (s = 0; s < NUM_UNIT_PREFIXES && size < byte; s++)
274*7c604eeaShaad 			byte /= units;
275*7c604eeaShaad 
276*7c604eeaShaad 		suffix = 1;
27756a34939Shaad 	}
27856a34939Shaad 
27956a34939Shaad 	/* FIXME Make precision configurable */
28056a34939Shaad 	switch(toupper((int) cmd->current_settings.unit_type)) {
28156a34939Shaad 	case 'B':
28256a34939Shaad 	case 'S':
28356a34939Shaad 		precision = 0;
28456a34939Shaad 		break;
28556a34939Shaad 	default:
28656a34939Shaad 		precision = 2;
28756a34939Shaad 	}
28856a34939Shaad 
28956a34939Shaad 	snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
290*7c604eeaShaad 		 (double) size / byte, suffix ? size_str[base + s][sl] : "");
29156a34939Shaad 
29256a34939Shaad 	return size_buf;
29356a34939Shaad }
29456a34939Shaad 
display_size_long(const struct cmd_context * cmd,uint64_t size)29556a34939Shaad const char *display_size_long(const struct cmd_context *cmd, uint64_t size)
29656a34939Shaad {
29756a34939Shaad 	return _display_size(cmd, size, SIZE_LONG);
29856a34939Shaad }
29956a34939Shaad 
display_size_units(const struct cmd_context * cmd,uint64_t size)30056a34939Shaad const char *display_size_units(const struct cmd_context *cmd, uint64_t size)
30156a34939Shaad {
30256a34939Shaad 	return _display_size(cmd, size, SIZE_UNIT);
30356a34939Shaad }
30456a34939Shaad 
display_size(const struct cmd_context * cmd,uint64_t size)30556a34939Shaad const char *display_size(const struct cmd_context *cmd, uint64_t size)
30656a34939Shaad {
30756a34939Shaad 	return _display_size(cmd, size, SIZE_SHORT);
30856a34939Shaad }
30956a34939Shaad 
pvdisplay_colons(const struct physical_volume * pv)31056a34939Shaad void pvdisplay_colons(const struct physical_volume *pv)
31156a34939Shaad {
31256a34939Shaad 	char uuid[64] __attribute((aligned(8)));
31356a34939Shaad 
31456a34939Shaad 	if (!pv)
31556a34939Shaad 		return;
31656a34939Shaad 
31756a34939Shaad 	if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
31856a34939Shaad 		stack;
31956a34939Shaad 		return;
32056a34939Shaad 	}
32156a34939Shaad 
32256a34939Shaad 	log_print("%s:%s:%" PRIu64 ":-1:%u:%u:-1:%" PRIu32 ":%u:%u:%u:%s",
32356a34939Shaad 		  pv_dev_name(pv), pv->vg_name, pv->size,
32456a34939Shaad 		  /* FIXME pv->pv_number, Derive or remove? */
32556a34939Shaad 		  pv->status,	/* FIXME Support old or new format here? */
32656a34939Shaad 		  pv->status & ALLOCATABLE_PV,	/* FIXME remove? */
32756a34939Shaad 		  /* FIXME pv->lv_cur, Remove? */
32856a34939Shaad 		  pv->pe_size / 2,
32956a34939Shaad 		  pv->pe_count,
33056a34939Shaad 		  pv->pe_count - pv->pe_alloc_count,
33156a34939Shaad 		  pv->pe_alloc_count, *uuid ? uuid : "none");
33256a34939Shaad 
33356a34939Shaad 	return;
33456a34939Shaad }
33556a34939Shaad 
pvdisplay_segments(const struct physical_volume * pv)33656a34939Shaad void pvdisplay_segments(const struct physical_volume *pv)
33756a34939Shaad {
33856a34939Shaad 	const struct pv_segment *pvseg;
33956a34939Shaad 
34056a34939Shaad 	if (pv->pe_size)
34156a34939Shaad 		log_print("--- Physical Segments ---");
34256a34939Shaad 
34356a34939Shaad 	dm_list_iterate_items(pvseg, &pv->segments) {
34456a34939Shaad 		log_print("Physical extent %u to %u:",
34556a34939Shaad 			  pvseg->pe, pvseg->pe + pvseg->len - 1);
34656a34939Shaad 
34756a34939Shaad 		if (pvseg_is_allocated(pvseg)) {
34856a34939Shaad 			log_print("  Logical volume\t%s%s/%s",
34956a34939Shaad 				  pvseg->lvseg->lv->vg->cmd->dev_dir,
35056a34939Shaad 				  pvseg->lvseg->lv->vg->name,
35156a34939Shaad 				  pvseg->lvseg->lv->name);
35256a34939Shaad 			log_print("  Logical extents\t%d to %d",
35356a34939Shaad 				  pvseg->lvseg->le, pvseg->lvseg->le +
35456a34939Shaad 				  pvseg->lvseg->len - 1);
35556a34939Shaad 		} else
35656a34939Shaad 			log_print("  FREE");
35756a34939Shaad 	}
35856a34939Shaad 
35956a34939Shaad 	log_print(" ");
36056a34939Shaad 	return;
36156a34939Shaad }
36256a34939Shaad 
36356a34939Shaad /* FIXME Include label fields */
pvdisplay_full(const struct cmd_context * cmd,const struct physical_volume * pv,void * handle __attribute ((unused)))36456a34939Shaad void pvdisplay_full(const struct cmd_context *cmd,
36556a34939Shaad 		    const struct physical_volume *pv,
36656a34939Shaad 		    void *handle __attribute((unused)))
36756a34939Shaad {
36856a34939Shaad 	char uuid[64] __attribute((aligned(8)));
36956a34939Shaad 	const char *size;
37056a34939Shaad 
37156a34939Shaad 	uint32_t pe_free;
37256a34939Shaad 	uint64_t data_size, pvsize, unusable;
37356a34939Shaad 
37456a34939Shaad 	if (!pv)
37556a34939Shaad 		return;
37656a34939Shaad 
37756a34939Shaad 	if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
37856a34939Shaad 		stack;
37956a34939Shaad 		return;
38056a34939Shaad 	}
38156a34939Shaad 
38256a34939Shaad 	log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW ");
38356a34939Shaad 	log_print("PV Name               %s", pv_dev_name(pv));
38456a34939Shaad 	log_print("VG Name               %s%s",
38556a34939Shaad 		  is_orphan(pv) ? "" : pv->vg_name,
38656a34939Shaad 		  pv->status & EXPORTED_VG ? " (exported)" : "");
38756a34939Shaad 
38856a34939Shaad 	data_size = (uint64_t) pv->pe_count * pv->pe_size;
38956a34939Shaad 	if (pv->size > data_size + pv->pe_start) {
39056a34939Shaad 		pvsize = pv->size;
39156a34939Shaad 		unusable = pvsize - data_size;
39256a34939Shaad 	} else {
39356a34939Shaad 		pvsize = data_size + pv->pe_start;
39456a34939Shaad 		unusable = pvsize - pv->size;
39556a34939Shaad 	}
39656a34939Shaad 
39756a34939Shaad 	size = display_size(cmd, pvsize);
39856a34939Shaad 	if (data_size)
39956a34939Shaad 		log_print("PV Size               %s / not usable %s",	/*  [LVM: %s]", */
40056a34939Shaad 			  size, display_size(cmd, unusable));
40156a34939Shaad 	else
40256a34939Shaad 		log_print("PV Size               %s", size);
40356a34939Shaad 
40456a34939Shaad 	/* PV number not part of LVM2 design
40556a34939Shaad 	   log_print("PV#                   %u", pv->pv_number);
40656a34939Shaad 	 */
40756a34939Shaad 
40856a34939Shaad 	pe_free = pv->pe_count - pv->pe_alloc_count;
40956a34939Shaad 	if (pv->pe_count && (pv->status & ALLOCATABLE_PV))
41056a34939Shaad 		log_print("Allocatable           yes %s",
41156a34939Shaad 			  (!pe_free && pv->pe_count) ? "(but full)" : "");
41256a34939Shaad 	else
41356a34939Shaad 		log_print("Allocatable           NO");
41456a34939Shaad 
41556a34939Shaad 	/* LV count is no longer available when displaying PV
41656a34939Shaad 	   log_print("Cur LV                %u", vg->lv_count);
41756a34939Shaad 	 */
418*7c604eeaShaad 
419*7c604eeaShaad 	if (cmd->si_unit_consistency)
420*7c604eeaShaad 		log_print("PE Size               %s", display_size(cmd, (uint64_t) pv->pe_size));
421*7c604eeaShaad 	else
42256a34939Shaad 		log_print("PE Size (KByte)       %" PRIu32, pv->pe_size / 2);
423*7c604eeaShaad 
42456a34939Shaad 	log_print("Total PE              %u", pv->pe_count);
42556a34939Shaad 	log_print("Free PE               %" PRIu32, pe_free);
42656a34939Shaad 	log_print("Allocated PE          %u", pv->pe_alloc_count);
42756a34939Shaad 	log_print("PV UUID               %s", *uuid ? uuid : "none");
42856a34939Shaad 	log_print(" ");
42956a34939Shaad 
43056a34939Shaad 	return;
43156a34939Shaad }
43256a34939Shaad 
pvdisplay_short(const struct cmd_context * cmd __attribute ((unused)),const struct volume_group * vg __attribute ((unused)),const struct physical_volume * pv,void * handle __attribute ((unused)))43356a34939Shaad int pvdisplay_short(const struct cmd_context *cmd __attribute((unused)),
43456a34939Shaad 		    const struct volume_group *vg __attribute((unused)),
43556a34939Shaad 		    const struct physical_volume *pv,
43656a34939Shaad 		    void *handle __attribute((unused)))
43756a34939Shaad {
43856a34939Shaad 	char uuid[64] __attribute((aligned(8)));
43956a34939Shaad 
44056a34939Shaad 	if (!pv)
44156a34939Shaad 		return 0;
44256a34939Shaad 
44356a34939Shaad 	if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
44456a34939Shaad 		return_0;
44556a34939Shaad 
44656a34939Shaad 	log_print("PV Name               %s     ", pv_dev_name(pv));
44756a34939Shaad 	/* FIXME  pv->pv_number); */
44856a34939Shaad 	log_print("PV UUID               %s", *uuid ? uuid : "none");
44956a34939Shaad 	log_print("PV Status             %sallocatable",
45056a34939Shaad 		  (pv->status & ALLOCATABLE_PV) ? "" : "NOT ");
45156a34939Shaad 	log_print("Total PE / Free PE    %u / %u",
45256a34939Shaad 		  pv->pe_count, pv->pe_count - pv->pe_alloc_count);
45356a34939Shaad 
45456a34939Shaad 	log_print(" ");
45556a34939Shaad 	return 0;
45656a34939Shaad }
45756a34939Shaad 
lvdisplay_colons(const struct logical_volume * lv)45856a34939Shaad void lvdisplay_colons(const struct logical_volume *lv)
45956a34939Shaad {
46056a34939Shaad 	int inkernel;
46156a34939Shaad 	struct lvinfo info;
46256a34939Shaad 	inkernel = lv_info(lv->vg->cmd, lv, &info, 1, 0) && info.exists;
46356a34939Shaad 
46456a34939Shaad 	log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
46556a34939Shaad 		  lv->vg->cmd->dev_dir,
46656a34939Shaad 		  lv->vg->name,
46756a34939Shaad 		  lv->name,
46856a34939Shaad 		  lv->vg->name,
46956a34939Shaad 		  (lv->status & (LVM_READ | LVM_WRITE)) >> 8, inkernel ? 1 : 0,
47056a34939Shaad 		  /* FIXME lv->lv_number,  */
47156a34939Shaad 		  inkernel ? info.open_count : 0, lv->size, lv->le_count,
47256a34939Shaad 		  /* FIXME Add num allocated to struct! lv->lv_allocated_le, */
47356a34939Shaad 		  (lv->alloc == ALLOC_CONTIGUOUS ? 2 : 0), lv->read_ahead,
47456a34939Shaad 		  inkernel ? info.major : -1, inkernel ? info.minor : -1);
47556a34939Shaad 	return;
47656a34939Shaad }
47756a34939Shaad 
lvdisplay_full(struct cmd_context * cmd,const struct logical_volume * lv,void * handle __attribute ((unused)))47856a34939Shaad int lvdisplay_full(struct cmd_context *cmd,
47956a34939Shaad 		   const struct logical_volume *lv,
48056a34939Shaad 		   void *handle __attribute((unused)))
48156a34939Shaad {
48256a34939Shaad 	struct lvinfo info;
48356a34939Shaad 	int inkernel, snap_active = 0;
48456a34939Shaad 	char uuid[64] __attribute((aligned(8)));
485*7c604eeaShaad 	struct lv_segment *snap_seg = NULL, *mirror_seg = NULL;
48656a34939Shaad 	float snap_percent;	/* fused, fsize; */
487*7c604eeaShaad 	percent_range_t percent_range;
48856a34939Shaad 
48956a34939Shaad 	if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid)))
49056a34939Shaad 		return_0;
49156a34939Shaad 
49256a34939Shaad 	inkernel = lv_info(cmd, lv, &info, 1, 1) && info.exists;
49356a34939Shaad 
49456a34939Shaad 	log_print("--- Logical volume ---");
49556a34939Shaad 
49656a34939Shaad 	log_print("LV Name                %s%s/%s", lv->vg->cmd->dev_dir,
49756a34939Shaad 		  lv->vg->name, lv->name);
49856a34939Shaad 	log_print("VG Name                %s", lv->vg->name);
49956a34939Shaad 
50056a34939Shaad 	log_print("LV UUID                %s", uuid);
50156a34939Shaad 
50256a34939Shaad 	log_print("LV Write Access        %s",
50356a34939Shaad 		  (lv->status & LVM_WRITE) ? "read/write" : "read only");
50456a34939Shaad 
50556a34939Shaad 	if (lv_is_origin(lv)) {
50656a34939Shaad 		log_print("LV snapshot status     source of");
50756a34939Shaad 
50856a34939Shaad 		dm_list_iterate_items_gen(snap_seg, &lv->snapshot_segs,
50956a34939Shaad 				       origin_list) {
51056a34939Shaad 			if (inkernel &&
51156a34939Shaad 			    (snap_active = lv_snapshot_percent(snap_seg->cow,
512*7c604eeaShaad 							       &snap_percent,
513*7c604eeaShaad 							       &percent_range)))
514*7c604eeaShaad 				if (percent_range == PERCENT_INVALID)
51556a34939Shaad 					snap_active = 0;
51656a34939Shaad 			log_print("                       %s%s/%s [%s]",
51756a34939Shaad 				  lv->vg->cmd->dev_dir, lv->vg->name,
51856a34939Shaad 				  snap_seg->cow->name,
519*7c604eeaShaad 				  snap_active ? "active" : "INACTIVE");
52056a34939Shaad 		}
52156a34939Shaad 		snap_seg = NULL;
52256a34939Shaad 	} else if ((snap_seg = find_cow(lv))) {
52356a34939Shaad 		if (inkernel &&
52456a34939Shaad 		    (snap_active = lv_snapshot_percent(snap_seg->cow,
525*7c604eeaShaad 						       &snap_percent,
526*7c604eeaShaad 						       &percent_range)))
527*7c604eeaShaad 			if (percent_range == PERCENT_INVALID)
52856a34939Shaad 				snap_active = 0;
52956a34939Shaad 
53056a34939Shaad 		log_print("LV snapshot status     %s destination for %s%s/%s",
531*7c604eeaShaad 			  snap_active ? "active" : "INACTIVE",
53256a34939Shaad 			  lv->vg->cmd->dev_dir, lv->vg->name,
53356a34939Shaad 			  snap_seg->origin->name);
53456a34939Shaad 	}
53556a34939Shaad 
53656a34939Shaad 	if (inkernel && info.suspended)
53756a34939Shaad 		log_print("LV Status              suspended");
53856a34939Shaad 	else
53956a34939Shaad 		log_print("LV Status              %savailable",
54056a34939Shaad 			  inkernel ? "" : "NOT ");
54156a34939Shaad 
54256a34939Shaad /********* FIXME lv_number
54356a34939Shaad     log_print("LV #                   %u", lv->lv_number + 1);
54456a34939Shaad ************/
54556a34939Shaad 
54656a34939Shaad 	if (inkernel)
54756a34939Shaad 		log_print("# open                 %u", info.open_count);
54856a34939Shaad 
54956a34939Shaad 	log_print("LV Size                %s",
55056a34939Shaad 		  display_size(cmd,
55156a34939Shaad 			       snap_seg ? snap_seg->origin->size : lv->size));
55256a34939Shaad 
55356a34939Shaad 	log_print("Current LE             %u",
55456a34939Shaad 		  snap_seg ? snap_seg->origin->le_count : lv->le_count);
55556a34939Shaad 
55656a34939Shaad 	if (snap_seg) {
55756a34939Shaad 		log_print("COW-table size         %s",
55856a34939Shaad 			  display_size(cmd, (uint64_t) lv->size));
55956a34939Shaad 		log_print("COW-table LE           %u", lv->le_count);
56056a34939Shaad 
56156a34939Shaad 		if (snap_active)
56256a34939Shaad 			log_print("Allocated to snapshot  %.2f%% ", snap_percent);
56356a34939Shaad 
56456a34939Shaad 		log_print("Snapshot chunk size    %s",
56556a34939Shaad 			  display_size(cmd, (uint64_t) snap_seg->chunk_size));
56656a34939Shaad 	}
56756a34939Shaad 
568*7c604eeaShaad 	if (lv->status & MIRRORED) {
569*7c604eeaShaad  		mirror_seg = first_seg(lv);
570*7c604eeaShaad 		log_print("Mirrored volumes       %" PRIu32, mirror_seg->area_count);
571*7c604eeaShaad 		if (lv->status & CONVERTING)
572*7c604eeaShaad 			log_print("LV type        Mirror undergoing conversion");
573*7c604eeaShaad 	}
574*7c604eeaShaad 
57556a34939Shaad 	log_print("Segments               %u", dm_list_size(&lv->segments));
57656a34939Shaad 
57756a34939Shaad /********* FIXME Stripes & stripesize for each segment
578*7c604eeaShaad 	log_print("Stripe size            %s", display_size(cmd, (uint64_t) lv->stripesize));
57956a34939Shaad ***********/
58056a34939Shaad 
58156a34939Shaad 	log_print("Allocation             %s", get_alloc_string(lv->alloc));
58256a34939Shaad 	if (lv->read_ahead == DM_READ_AHEAD_AUTO)
58356a34939Shaad 		log_print("Read ahead sectors     auto");
58456a34939Shaad 	else if (lv->read_ahead == DM_READ_AHEAD_NONE)
58556a34939Shaad 		log_print("Read ahead sectors     0");
58656a34939Shaad 	else
58756a34939Shaad 		log_print("Read ahead sectors     %u", lv->read_ahead);
58856a34939Shaad 
58956a34939Shaad 	if (inkernel && lv->read_ahead != info.read_ahead)
59056a34939Shaad 		log_print("- currently set to     %u", info.read_ahead);
59156a34939Shaad 
59256a34939Shaad 	if (lv->status & FIXED_MINOR) {
59356a34939Shaad 		if (lv->major >= 0)
59456a34939Shaad 			log_print("Persistent major       %d", lv->major);
59556a34939Shaad 		log_print("Persistent minor       %d", lv->minor);
59656a34939Shaad 	}
59756a34939Shaad 
59856a34939Shaad 	if (inkernel)
59956a34939Shaad 		log_print("Block device           %d:%d", info.major,
60056a34939Shaad 			  info.minor);
60156a34939Shaad 
60256a34939Shaad 	log_print(" ");
60356a34939Shaad 
60456a34939Shaad 	return 0;
60556a34939Shaad }
60656a34939Shaad 
display_stripe(const struct lv_segment * seg,uint32_t s,const char * pre)60756a34939Shaad void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
60856a34939Shaad {
60956a34939Shaad 	switch (seg_type(seg, s)) {
61056a34939Shaad 	case AREA_PV:
61156a34939Shaad 		/* FIXME Re-check the conditions for 'Missing' */
61256a34939Shaad 		log_print("%sPhysical volume\t%s", pre,
61356a34939Shaad 			  seg_pv(seg, s) ?
61456a34939Shaad 			  pv_dev_name(seg_pv(seg, s)) :
61556a34939Shaad 			    "Missing");
61656a34939Shaad 
61756a34939Shaad 		if (seg_pv(seg, s))
61856a34939Shaad 			log_print("%sPhysical extents\t%d to %d", pre,
61956a34939Shaad 				  seg_pe(seg, s),
62056a34939Shaad 				  seg_pe(seg, s) + seg->area_len - 1);
62156a34939Shaad 		break;
62256a34939Shaad 	case AREA_LV:
62356a34939Shaad 		log_print("%sLogical volume\t%s", pre,
62456a34939Shaad 			  seg_lv(seg, s) ?
62556a34939Shaad 			  seg_lv(seg, s)->name : "Missing");
62656a34939Shaad 
62756a34939Shaad 		if (seg_lv(seg, s))
62856a34939Shaad 			log_print("%sLogical extents\t%d to %d", pre,
62956a34939Shaad 				  seg_le(seg, s),
63056a34939Shaad 				  seg_le(seg, s) + seg->area_len - 1);
63156a34939Shaad 		break;
63256a34939Shaad 	case AREA_UNASSIGNED:
63356a34939Shaad 		log_print("%sUnassigned area", pre);
63456a34939Shaad 	}
63556a34939Shaad }
63656a34939Shaad 
lvdisplay_segments(const struct logical_volume * lv)63756a34939Shaad int lvdisplay_segments(const struct logical_volume *lv)
63856a34939Shaad {
63956a34939Shaad 	const struct lv_segment *seg;
64056a34939Shaad 
64156a34939Shaad 	log_print("--- Segments ---");
64256a34939Shaad 
64356a34939Shaad 	dm_list_iterate_items(seg, &lv->segments) {
64456a34939Shaad 		log_print("Logical extent %u to %u:",
64556a34939Shaad 			  seg->le, seg->le + seg->len - 1);
64656a34939Shaad 
64756a34939Shaad 		log_print("  Type\t\t%s", seg->segtype->ops->name(seg));
64856a34939Shaad 
64956a34939Shaad 		if (seg->segtype->ops->display)
65056a34939Shaad 			seg->segtype->ops->display(seg);
65156a34939Shaad 	}
65256a34939Shaad 
65356a34939Shaad 	log_print(" ");
65456a34939Shaad 	return 1;
65556a34939Shaad }
65656a34939Shaad 
vgdisplay_extents(const struct volume_group * vg __attribute ((unused)))65756a34939Shaad void vgdisplay_extents(const struct volume_group *vg __attribute((unused)))
65856a34939Shaad {
65956a34939Shaad 	return;
66056a34939Shaad }
66156a34939Shaad 
vgdisplay_full(const struct volume_group * vg)66256a34939Shaad void vgdisplay_full(const struct volume_group *vg)
66356a34939Shaad {
66456a34939Shaad 	uint32_t access_str;
66556a34939Shaad 	uint32_t active_pvs;
66656a34939Shaad 	char uuid[64] __attribute((aligned(8)));
66756a34939Shaad 
66856a34939Shaad 	active_pvs = vg->pv_count - vg_missing_pv_count(vg);
66956a34939Shaad 
67056a34939Shaad 	log_print("--- Volume group ---");
67156a34939Shaad 	log_print("VG Name               %s", vg->name);
67256a34939Shaad 	log_print("System ID             %s", vg->system_id);
67356a34939Shaad 	log_print("Format                %s", vg->fid->fmt->name);
67456a34939Shaad 	if (vg->fid->fmt->features & FMT_MDAS) {
67556a34939Shaad 		log_print("Metadata Areas        %d",
67656a34939Shaad 			  dm_list_size(&vg->fid->metadata_areas));
67756a34939Shaad 		log_print("Metadata Sequence No  %d", vg->seqno);
67856a34939Shaad 	}
67956a34939Shaad 	access_str = vg->status & (LVM_READ | LVM_WRITE);
68056a34939Shaad 	log_print("VG Access             %s%s%s%s",
68156a34939Shaad 		  access_str == (LVM_READ | LVM_WRITE) ? "read/write" : "",
68256a34939Shaad 		  access_str == LVM_READ ? "read" : "",
68356a34939Shaad 		  access_str == LVM_WRITE ? "write" : "",
68456a34939Shaad 		  access_str == 0 ? "error" : "");
68556a34939Shaad 	log_print("VG Status             %s%sresizable",
686*7c604eeaShaad 		  vg_is_exported(vg) ? "exported/" : "",
687*7c604eeaShaad 		  vg_is_resizeable(vg) ? "" : "NOT ");
68856a34939Shaad 	/* vg number not part of LVM2 design
68956a34939Shaad 	   log_print ("VG #                  %u\n", vg->vg_number);
69056a34939Shaad 	 */
69156a34939Shaad 	if (vg_is_clustered(vg)) {
69256a34939Shaad 		log_print("Clustered             yes");
69356a34939Shaad 		log_print("Shared                %s",
69456a34939Shaad 			  vg->status & SHARED ? "yes" : "no");
69556a34939Shaad 	}
69656a34939Shaad 
69756a34939Shaad 	log_print("MAX LV                %u", vg->max_lv);
698*7c604eeaShaad 	log_print("Cur LV                %u", vg_visible_lvs(vg));
69956a34939Shaad 	log_print("Open LV               %u", lvs_in_vg_opened(vg));
70056a34939Shaad /****** FIXME Max LV Size
70156a34939Shaad       log_print ( "MAX LV Size           %s",
70256a34939Shaad                ( s1 = display_size ( LVM_LV_SIZE_MAX(vg))));
70356a34939Shaad       free ( s1);
70456a34939Shaad *********/
70556a34939Shaad 	log_print("Max PV                %u", vg->max_pv);
70656a34939Shaad 	log_print("Cur PV                %u", vg->pv_count);
70756a34939Shaad 	log_print("Act PV                %u", active_pvs);
70856a34939Shaad 
70956a34939Shaad 	log_print("VG Size               %s",
71056a34939Shaad 		  display_size(vg->cmd,
71156a34939Shaad 			       (uint64_t) vg->extent_count * vg->extent_size));
71256a34939Shaad 
71356a34939Shaad 	log_print("PE Size               %s",
71456a34939Shaad 		  display_size(vg->cmd, (uint64_t) vg->extent_size));
71556a34939Shaad 
71656a34939Shaad 	log_print("Total PE              %u", vg->extent_count);
71756a34939Shaad 
71856a34939Shaad 	log_print("Alloc PE / Size       %u / %s",
71956a34939Shaad 		  vg->extent_count - vg->free_count,
72056a34939Shaad 		  display_size(vg->cmd,
72156a34939Shaad 			       ((uint64_t) vg->extent_count - vg->free_count) *
72256a34939Shaad 			       vg->extent_size));
72356a34939Shaad 
72456a34939Shaad 	log_print("Free  PE / Size       %u / %s", vg->free_count,
725*7c604eeaShaad 		  display_size(vg->cmd, vg_free(vg)));
72656a34939Shaad 
72756a34939Shaad 	if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
72856a34939Shaad 		stack;
72956a34939Shaad 		return;
73056a34939Shaad 	}
73156a34939Shaad 
73256a34939Shaad 	log_print("VG UUID               %s", uuid);
73356a34939Shaad 	log_print(" ");
73456a34939Shaad 
73556a34939Shaad 	return;
73656a34939Shaad }
73756a34939Shaad 
vgdisplay_colons(const struct volume_group * vg)73856a34939Shaad void vgdisplay_colons(const struct volume_group *vg)
73956a34939Shaad {
74056a34939Shaad 	uint32_t active_pvs;
74156a34939Shaad 	const char *access_str;
74256a34939Shaad 	char uuid[64] __attribute((aligned(8)));
74356a34939Shaad 
74456a34939Shaad 	active_pvs = vg->pv_count - vg_missing_pv_count(vg);
74556a34939Shaad 
74656a34939Shaad 	switch (vg->status & (LVM_READ | LVM_WRITE)) {
74756a34939Shaad 		case LVM_READ | LVM_WRITE:
74856a34939Shaad 			access_str = "r/w";
74956a34939Shaad 			break;
75056a34939Shaad 		case LVM_READ:
75156a34939Shaad 			access_str = "r";
75256a34939Shaad 			break;
75356a34939Shaad 		case LVM_WRITE:
75456a34939Shaad 			access_str = "w";
75556a34939Shaad 			break;
75656a34939Shaad 		default:
75756a34939Shaad 			access_str = "";
75856a34939Shaad 	}
75956a34939Shaad 
76056a34939Shaad 	if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
76156a34939Shaad 		stack;
76256a34939Shaad 		return;
76356a34939Shaad 	}
76456a34939Shaad 
76556a34939Shaad 	log_print("%s:%s:%d:-1:%u:%u:%u:-1:%u:%u:%u:%" PRIu64 ":%" PRIu32
76656a34939Shaad 		  ":%u:%u:%u:%s",
76756a34939Shaad 		vg->name,
76856a34939Shaad 		access_str,
76956a34939Shaad 		vg->status,
77056a34939Shaad 		/* internal volume group number; obsolete */
77156a34939Shaad 		vg->max_lv,
772*7c604eeaShaad 		vg_visible_lvs(vg),
77356a34939Shaad 		lvs_in_vg_opened(vg),
77456a34939Shaad 		/* FIXME: maximum logical volume size */
77556a34939Shaad 		vg->max_pv,
77656a34939Shaad 		vg->pv_count,
77756a34939Shaad 		active_pvs,
77856a34939Shaad 		(uint64_t) vg->extent_count * (vg->extent_size / 2),
77956a34939Shaad 		vg->extent_size / 2,
78056a34939Shaad 		vg->extent_count,
78156a34939Shaad 		vg->extent_count - vg->free_count,
78256a34939Shaad 		vg->free_count,
78356a34939Shaad 		uuid[0] ? uuid : "none");
78456a34939Shaad 	return;
78556a34939Shaad }
78656a34939Shaad 
vgdisplay_short(const struct volume_group * vg)78756a34939Shaad void vgdisplay_short(const struct volume_group *vg)
78856a34939Shaad {
78956a34939Shaad 	log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
79056a34939Shaad /********* FIXME if "open" print "/used" else print "/idle"???  ******/
79156a34939Shaad 		  display_size(vg->cmd,
79256a34939Shaad 			       (uint64_t) vg->extent_count * vg->extent_size),
79356a34939Shaad 		  display_size(vg->cmd,
79456a34939Shaad 			       ((uint64_t) vg->extent_count -
79556a34939Shaad 				vg->free_count) * vg->extent_size),
796*7c604eeaShaad 		  display_size(vg->cmd, vg_free(vg)));
79756a34939Shaad 	return;
79856a34939Shaad }
79956a34939Shaad 
display_formats(const struct cmd_context * cmd)80056a34939Shaad void display_formats(const struct cmd_context *cmd)
80156a34939Shaad {
80256a34939Shaad 	const struct format_type *fmt;
80356a34939Shaad 
80456a34939Shaad 	dm_list_iterate_items(fmt, &cmd->formats) {
80556a34939Shaad 		log_print("%s", fmt->name);
80656a34939Shaad 	}
80756a34939Shaad }
80856a34939Shaad 
display_segtypes(const struct cmd_context * cmd)80956a34939Shaad void display_segtypes(const struct cmd_context *cmd)
81056a34939Shaad {
81156a34939Shaad 	const struct segment_type *segtype;
81256a34939Shaad 
81356a34939Shaad 	dm_list_iterate_items(segtype, &cmd->segtypes) {
81456a34939Shaad 		log_print("%s", segtype->name);
81556a34939Shaad 	}
81656a34939Shaad }
81756a34939Shaad 
yes_no_prompt(const char * prompt,...)81856a34939Shaad char yes_no_prompt(const char *prompt, ...)
81956a34939Shaad {
82056a34939Shaad 	int c = 0, ret = 0;
82156a34939Shaad 	va_list ap;
82256a34939Shaad 
82356a34939Shaad 	sigint_allow();
82456a34939Shaad 	do {
82556a34939Shaad 		if (c == '\n' || !c) {
82656a34939Shaad 			va_start(ap, prompt);
82756a34939Shaad 			vprintf(prompt, ap);
82856a34939Shaad 			va_end(ap);
829*7c604eeaShaad 			fflush(stdout);
83056a34939Shaad 		}
83156a34939Shaad 
83256a34939Shaad 		if ((c = getchar()) == EOF) {
83356a34939Shaad 			ret = 'n';
83456a34939Shaad 			break;
83556a34939Shaad 		}
83656a34939Shaad 
83756a34939Shaad 		c = tolower(c);
83856a34939Shaad 		if ((c == 'y') || (c == 'n'))
83956a34939Shaad 			ret = c;
84056a34939Shaad 	} while (!ret || c != '\n');
84156a34939Shaad 
84256a34939Shaad 	sigint_restore();
84356a34939Shaad 
84456a34939Shaad 	if (c != '\n')
84556a34939Shaad 		printf("\n");
84656a34939Shaad 
84756a34939Shaad 	return ret;
84856a34939Shaad }
84956a34939Shaad 
850