xref: /dflybsd-src/contrib/lvm2/dist/lib/format1/format1.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /*	$NetBSD: format1.c,v 1.1.1.2 2009/12/02 00:26:48 haad Exp $	*/
2*86d7f5d3SJohn Marino 
3*86d7f5d3SJohn Marino /*
4*86d7f5d3SJohn Marino  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5*86d7f5d3SJohn Marino  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
6*86d7f5d3SJohn Marino  *
7*86d7f5d3SJohn Marino  * This file is part of LVM2.
8*86d7f5d3SJohn Marino  *
9*86d7f5d3SJohn Marino  * This copyrighted material is made available to anyone wishing to use,
10*86d7f5d3SJohn Marino  * modify, copy, or redistribute it subject to the terms and conditions
11*86d7f5d3SJohn Marino  * of the GNU Lesser General Public License v.2.1.
12*86d7f5d3SJohn Marino  *
13*86d7f5d3SJohn Marino  * You should have received a copy of the GNU Lesser General Public License
14*86d7f5d3SJohn Marino  * along with this program; if not, write to the Free Software Foundation,
15*86d7f5d3SJohn Marino  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16*86d7f5d3SJohn Marino  */
17*86d7f5d3SJohn Marino 
18*86d7f5d3SJohn Marino #include "lib.h"
19*86d7f5d3SJohn Marino #include "disk-rep.h"
20*86d7f5d3SJohn Marino #include "limits.h"
21*86d7f5d3SJohn Marino #include "display.h"
22*86d7f5d3SJohn Marino #include "toolcontext.h"
23*86d7f5d3SJohn Marino #include "lvm1-label.h"
24*86d7f5d3SJohn Marino #include "format1.h"
25*86d7f5d3SJohn Marino #include "segtype.h"
26*86d7f5d3SJohn Marino 
27*86d7f5d3SJohn Marino /* VG consistency checks */
_check_vgs(struct dm_list * pvs)28*86d7f5d3SJohn Marino static int _check_vgs(struct dm_list *pvs)
29*86d7f5d3SJohn Marino {
30*86d7f5d3SJohn Marino 	struct dm_list *pvh, *t;
31*86d7f5d3SJohn Marino 	struct disk_list *dl = NULL;
32*86d7f5d3SJohn Marino 	struct disk_list *first = NULL;
33*86d7f5d3SJohn Marino 
34*86d7f5d3SJohn Marino 	uint32_t pv_count = 0;
35*86d7f5d3SJohn Marino 	uint32_t exported = 0;
36*86d7f5d3SJohn Marino 	int first_time = 1;
37*86d7f5d3SJohn Marino 
38*86d7f5d3SJohn Marino 	/*
39*86d7f5d3SJohn Marino 	 * If there are exported and unexported PVs, ignore exported ones.
40*86d7f5d3SJohn Marino 	 * This means an active VG won't be affected if disks are inserted
41*86d7f5d3SJohn Marino 	 * bearing an exported VG with the same name.
42*86d7f5d3SJohn Marino 	 */
43*86d7f5d3SJohn Marino 	dm_list_iterate_items(dl, pvs) {
44*86d7f5d3SJohn Marino 		if (first_time) {
45*86d7f5d3SJohn Marino 			exported = dl->pvd.pv_status & VG_EXPORTED;
46*86d7f5d3SJohn Marino 			first_time = 0;
47*86d7f5d3SJohn Marino 			continue;
48*86d7f5d3SJohn Marino 		}
49*86d7f5d3SJohn Marino 
50*86d7f5d3SJohn Marino 		if (exported != (dl->pvd.pv_status & VG_EXPORTED)) {
51*86d7f5d3SJohn Marino 			/* Remove exported PVs */
52*86d7f5d3SJohn Marino 			dm_list_iterate_safe(pvh, t, pvs) {
53*86d7f5d3SJohn Marino 				dl = dm_list_item(pvh, struct disk_list);
54*86d7f5d3SJohn Marino 				if (dl->pvd.pv_status & VG_EXPORTED)
55*86d7f5d3SJohn Marino 					dm_list_del(pvh);
56*86d7f5d3SJohn Marino 			}
57*86d7f5d3SJohn Marino 			break;
58*86d7f5d3SJohn Marino 		}
59*86d7f5d3SJohn Marino 	}
60*86d7f5d3SJohn Marino 
61*86d7f5d3SJohn Marino 	/* Remove any PVs with VG structs that differ from the first */
62*86d7f5d3SJohn Marino 	dm_list_iterate_safe(pvh, t, pvs) {
63*86d7f5d3SJohn Marino 		dl = dm_list_item(pvh, struct disk_list);
64*86d7f5d3SJohn Marino 
65*86d7f5d3SJohn Marino 		if (!first)
66*86d7f5d3SJohn Marino 			first = dl;
67*86d7f5d3SJohn Marino 
68*86d7f5d3SJohn Marino 		else if (memcmp(&first->vgd, &dl->vgd, sizeof(first->vgd))) {
69*86d7f5d3SJohn Marino 			log_error("VG data differs between PVs %s and %s",
70*86d7f5d3SJohn Marino 				  dev_name(first->dev), dev_name(dl->dev));
71*86d7f5d3SJohn Marino 			log_debug("VG data on %s: %s %s %" PRIu32 " %" PRIu32
72*86d7f5d3SJohn Marino 				  "  %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
73*86d7f5d3SJohn Marino 				  PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32
74*86d7f5d3SJohn Marino 				  " %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
75*86d7f5d3SJohn Marino 				  PRIu32 " %" PRIu32 " %" PRIu32,
76*86d7f5d3SJohn Marino 				  dev_name(first->dev), first->vgd.vg_uuid,
77*86d7f5d3SJohn Marino 				  first->vgd.vg_name_dummy,
78*86d7f5d3SJohn Marino 				  first->vgd.vg_number, first->vgd.vg_access,
79*86d7f5d3SJohn Marino 				  first->vgd.vg_status, first->vgd.lv_max,
80*86d7f5d3SJohn Marino 				  first->vgd.lv_cur, first->vgd.lv_open,
81*86d7f5d3SJohn Marino 				  first->vgd.pv_max, first->vgd.pv_cur,
82*86d7f5d3SJohn Marino 				  first->vgd.pv_act, first->vgd.dummy,
83*86d7f5d3SJohn Marino 				  first->vgd.vgda, first->vgd.pe_size,
84*86d7f5d3SJohn Marino 				  first->vgd.pe_total, first->vgd.pe_allocated,
85*86d7f5d3SJohn Marino 				  first->vgd.pvg_total);
86*86d7f5d3SJohn Marino 			log_debug("VG data on %s: %s %s %" PRIu32 " %" PRIu32
87*86d7f5d3SJohn Marino 				  "  %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
88*86d7f5d3SJohn Marino 				  PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32
89*86d7f5d3SJohn Marino 				  " %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
90*86d7f5d3SJohn Marino 				  PRIu32 " %" PRIu32 " %" PRIu32,
91*86d7f5d3SJohn Marino 				  dev_name(dl->dev), dl->vgd.vg_uuid,
92*86d7f5d3SJohn Marino 				  dl->vgd.vg_name_dummy, dl->vgd.vg_number,
93*86d7f5d3SJohn Marino 				  dl->vgd.vg_access, dl->vgd.vg_status,
94*86d7f5d3SJohn Marino 				  dl->vgd.lv_max, dl->vgd.lv_cur,
95*86d7f5d3SJohn Marino 				  dl->vgd.lv_open, dl->vgd.pv_max,
96*86d7f5d3SJohn Marino 				  dl->vgd.pv_cur, dl->vgd.pv_act, dl->vgd.dummy,
97*86d7f5d3SJohn Marino 				  dl->vgd.vgda, dl->vgd.pe_size,
98*86d7f5d3SJohn Marino 				  dl->vgd.pe_total, dl->vgd.pe_allocated,
99*86d7f5d3SJohn Marino 				  dl->vgd.pvg_total);
100*86d7f5d3SJohn Marino 			dm_list_del(pvh);
101*86d7f5d3SJohn Marino 			return 0;
102*86d7f5d3SJohn Marino 		}
103*86d7f5d3SJohn Marino 		pv_count++;
104*86d7f5d3SJohn Marino 	}
105*86d7f5d3SJohn Marino 
106*86d7f5d3SJohn Marino 	/* On entry to fn, list known to be non-empty */
107*86d7f5d3SJohn Marino 	if (pv_count != first->vgd.pv_cur) {
108*86d7f5d3SJohn Marino 		log_error("%d PV(s) found for VG %s: expected %d",
109*86d7f5d3SJohn Marino 			  pv_count, first->pvd.vg_name, first->vgd.pv_cur);
110*86d7f5d3SJohn Marino 	}
111*86d7f5d3SJohn Marino 
112*86d7f5d3SJohn Marino 	return 1;
113*86d7f5d3SJohn Marino }
114*86d7f5d3SJohn Marino 
_build_vg(struct format_instance * fid,struct dm_list * pvs,struct dm_pool * mem)115*86d7f5d3SJohn Marino static struct volume_group *_build_vg(struct format_instance *fid,
116*86d7f5d3SJohn Marino 				      struct dm_list *pvs,
117*86d7f5d3SJohn Marino 				      struct dm_pool *mem)
118*86d7f5d3SJohn Marino {
119*86d7f5d3SJohn Marino 	struct volume_group *vg = dm_pool_alloc(mem, sizeof(*vg));
120*86d7f5d3SJohn Marino 	struct disk_list *dl;
121*86d7f5d3SJohn Marino 
122*86d7f5d3SJohn Marino 	if (!vg)
123*86d7f5d3SJohn Marino 		goto_bad;
124*86d7f5d3SJohn Marino 
125*86d7f5d3SJohn Marino 	if (dm_list_empty(pvs))
126*86d7f5d3SJohn Marino 		goto_bad;
127*86d7f5d3SJohn Marino 
128*86d7f5d3SJohn Marino 	memset(vg, 0, sizeof(*vg));
129*86d7f5d3SJohn Marino 
130*86d7f5d3SJohn Marino 	vg->cmd = fid->fmt->cmd;
131*86d7f5d3SJohn Marino 	vg->vgmem = mem;
132*86d7f5d3SJohn Marino 	vg->fid = fid;
133*86d7f5d3SJohn Marino 	vg->seqno = 0;
134*86d7f5d3SJohn Marino 	dm_list_init(&vg->pvs);
135*86d7f5d3SJohn Marino 	dm_list_init(&vg->lvs);
136*86d7f5d3SJohn Marino 	dm_list_init(&vg->tags);
137*86d7f5d3SJohn Marino 	dm_list_init(&vg->removed_pvs);
138*86d7f5d3SJohn Marino 
139*86d7f5d3SJohn Marino 	if (!_check_vgs(pvs))
140*86d7f5d3SJohn Marino 		goto_bad;
141*86d7f5d3SJohn Marino 
142*86d7f5d3SJohn Marino 	dl = dm_list_item(pvs->n, struct disk_list);
143*86d7f5d3SJohn Marino 
144*86d7f5d3SJohn Marino 	if (!import_vg(mem, vg, dl))
145*86d7f5d3SJohn Marino 		goto_bad;
146*86d7f5d3SJohn Marino 
147*86d7f5d3SJohn Marino 	if (!import_pvs(fid->fmt, mem, vg, pvs, &vg->pvs, &vg->pv_count))
148*86d7f5d3SJohn Marino 		goto_bad;
149*86d7f5d3SJohn Marino 
150*86d7f5d3SJohn Marino 	if (!import_lvs(mem, vg, pvs))
151*86d7f5d3SJohn Marino 		goto_bad;
152*86d7f5d3SJohn Marino 
153*86d7f5d3SJohn Marino 	if (!import_extents(fid->fmt->cmd, vg, pvs))
154*86d7f5d3SJohn Marino 		goto_bad;
155*86d7f5d3SJohn Marino 
156*86d7f5d3SJohn Marino 	if (!import_snapshots(mem, vg, pvs))
157*86d7f5d3SJohn Marino 		goto_bad;
158*86d7f5d3SJohn Marino 
159*86d7f5d3SJohn Marino 	return vg;
160*86d7f5d3SJohn Marino 
161*86d7f5d3SJohn Marino       bad:
162*86d7f5d3SJohn Marino 	dm_pool_free(mem, vg);
163*86d7f5d3SJohn Marino 	return NULL;
164*86d7f5d3SJohn Marino }
165*86d7f5d3SJohn Marino 
_format1_vg_read(struct format_instance * fid,const char * vg_name,struct metadata_area * mda __attribute ((unused)))166*86d7f5d3SJohn Marino static struct volume_group *_format1_vg_read(struct format_instance *fid,
167*86d7f5d3SJohn Marino 				     const char *vg_name,
168*86d7f5d3SJohn Marino 				     struct metadata_area *mda __attribute((unused)))
169*86d7f5d3SJohn Marino {
170*86d7f5d3SJohn Marino 	struct dm_pool *mem = dm_pool_create("lvm1 vg_read", VG_MEMPOOL_CHUNK);
171*86d7f5d3SJohn Marino 	struct dm_list pvs;
172*86d7f5d3SJohn Marino 	struct volume_group *vg = NULL;
173*86d7f5d3SJohn Marino 	dm_list_init(&pvs);
174*86d7f5d3SJohn Marino 
175*86d7f5d3SJohn Marino 	if (!mem)
176*86d7f5d3SJohn Marino 		return_NULL;
177*86d7f5d3SJohn Marino 
178*86d7f5d3SJohn Marino 	/* Strip dev_dir if present */
179*86d7f5d3SJohn Marino 	vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
180*86d7f5d3SJohn Marino 
181*86d7f5d3SJohn Marino 	if (!read_pvs_in_vg
182*86d7f5d3SJohn Marino 	    (fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs))
183*86d7f5d3SJohn Marino 		goto_bad;
184*86d7f5d3SJohn Marino 
185*86d7f5d3SJohn Marino 	if (!(vg = _build_vg(fid, &pvs, mem)))
186*86d7f5d3SJohn Marino 		goto_bad;
187*86d7f5d3SJohn Marino 
188*86d7f5d3SJohn Marino 	return vg;
189*86d7f5d3SJohn Marino bad:
190*86d7f5d3SJohn Marino 	dm_pool_destroy(mem);
191*86d7f5d3SJohn Marino 	return NULL;
192*86d7f5d3SJohn Marino }
193*86d7f5d3SJohn Marino 
_flatten_pv(struct format_instance * fid,struct dm_pool * mem,struct volume_group * vg,struct physical_volume * pv,const char * dev_dir)194*86d7f5d3SJohn Marino static struct disk_list *_flatten_pv(struct format_instance *fid,
195*86d7f5d3SJohn Marino 				     struct dm_pool *mem, struct volume_group *vg,
196*86d7f5d3SJohn Marino 				     struct physical_volume *pv,
197*86d7f5d3SJohn Marino 				     const char *dev_dir)
198*86d7f5d3SJohn Marino {
199*86d7f5d3SJohn Marino 	struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
200*86d7f5d3SJohn Marino 
201*86d7f5d3SJohn Marino 	if (!dl)
202*86d7f5d3SJohn Marino 		return_NULL;
203*86d7f5d3SJohn Marino 
204*86d7f5d3SJohn Marino 	dl->mem = mem;
205*86d7f5d3SJohn Marino 	dl->dev = pv->dev;
206*86d7f5d3SJohn Marino 
207*86d7f5d3SJohn Marino 	dm_list_init(&dl->uuids);
208*86d7f5d3SJohn Marino 	dm_list_init(&dl->lvds);
209*86d7f5d3SJohn Marino 
210*86d7f5d3SJohn Marino 	if (!export_pv(fid->fmt->cmd, mem, vg, &dl->pvd, pv) ||
211*86d7f5d3SJohn Marino 	    !export_vg(&dl->vgd, vg) ||
212*86d7f5d3SJohn Marino 	    !export_uuids(dl, vg) ||
213*86d7f5d3SJohn Marino 	    !export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
214*86d7f5d3SJohn Marino 		dm_pool_free(mem, dl);
215*86d7f5d3SJohn Marino 		return_NULL;
216*86d7f5d3SJohn Marino 	}
217*86d7f5d3SJohn Marino 
218*86d7f5d3SJohn Marino 	return dl;
219*86d7f5d3SJohn Marino }
220*86d7f5d3SJohn Marino 
_flatten_vg(struct format_instance * fid,struct dm_pool * mem,struct volume_group * vg,struct dm_list * pvds,const char * dev_dir,struct dev_filter * filter)221*86d7f5d3SJohn Marino static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
222*86d7f5d3SJohn Marino 		       struct volume_group *vg,
223*86d7f5d3SJohn Marino 		       struct dm_list *pvds, const char *dev_dir,
224*86d7f5d3SJohn Marino 		       struct dev_filter *filter)
225*86d7f5d3SJohn Marino {
226*86d7f5d3SJohn Marino 	struct pv_list *pvl;
227*86d7f5d3SJohn Marino 	struct disk_list *data;
228*86d7f5d3SJohn Marino 
229*86d7f5d3SJohn Marino 	dm_list_iterate_items(pvl, &vg->pvs) {
230*86d7f5d3SJohn Marino 		if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir)))
231*86d7f5d3SJohn Marino 			return_0;
232*86d7f5d3SJohn Marino 
233*86d7f5d3SJohn Marino 		dm_list_add(pvds, &data->list);
234*86d7f5d3SJohn Marino 	}
235*86d7f5d3SJohn Marino 
236*86d7f5d3SJohn Marino 	export_numbers(pvds, vg);
237*86d7f5d3SJohn Marino 	export_pv_act(pvds);
238*86d7f5d3SJohn Marino 
239*86d7f5d3SJohn Marino 	if (!export_vg_number(fid, pvds, vg->name, filter))
240*86d7f5d3SJohn Marino 		return_0;
241*86d7f5d3SJohn Marino 
242*86d7f5d3SJohn Marino 	return 1;
243*86d7f5d3SJohn Marino }
244*86d7f5d3SJohn Marino 
_format1_vg_write(struct format_instance * fid,struct volume_group * vg,struct metadata_area * mda __attribute ((unused)))245*86d7f5d3SJohn Marino static int _format1_vg_write(struct format_instance *fid, struct volume_group *vg,
246*86d7f5d3SJohn Marino 		     struct metadata_area *mda __attribute((unused)))
247*86d7f5d3SJohn Marino {
248*86d7f5d3SJohn Marino 	struct dm_pool *mem = dm_pool_create("lvm1 vg_write", VG_MEMPOOL_CHUNK);
249*86d7f5d3SJohn Marino 	struct dm_list pvds;
250*86d7f5d3SJohn Marino 	int r = 0;
251*86d7f5d3SJohn Marino 
252*86d7f5d3SJohn Marino 	if (!mem)
253*86d7f5d3SJohn Marino 		return_0;
254*86d7f5d3SJohn Marino 
255*86d7f5d3SJohn Marino 	dm_list_init(&pvds);
256*86d7f5d3SJohn Marino 
257*86d7f5d3SJohn Marino 	r = (_flatten_vg(fid, mem, vg, &pvds, fid->fmt->cmd->dev_dir,
258*86d7f5d3SJohn Marino 			 fid->fmt->cmd->filter) &&
259*86d7f5d3SJohn Marino 	     write_disks(fid->fmt, &pvds));
260*86d7f5d3SJohn Marino 
261*86d7f5d3SJohn Marino 	lvmcache_update_vg(vg, 0);
262*86d7f5d3SJohn Marino 	dm_pool_destroy(mem);
263*86d7f5d3SJohn Marino 	return r;
264*86d7f5d3SJohn Marino }
265*86d7f5d3SJohn Marino 
_format1_pv_read(const struct format_type * fmt,const char * pv_name,struct physical_volume * pv,struct dm_list * mdas __attribute ((unused)),int scan_label_only __attribute ((unused)))266*86d7f5d3SJohn Marino static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
267*86d7f5d3SJohn Marino 		    struct physical_volume *pv, struct dm_list *mdas __attribute((unused)),
268*86d7f5d3SJohn Marino 		    int scan_label_only __attribute((unused)))
269*86d7f5d3SJohn Marino {
270*86d7f5d3SJohn Marino 	struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
271*86d7f5d3SJohn Marino 	struct disk_list *dl;
272*86d7f5d3SJohn Marino 	struct device *dev;
273*86d7f5d3SJohn Marino 	int r = 0;
274*86d7f5d3SJohn Marino 
275*86d7f5d3SJohn Marino 	log_very_verbose("Reading physical volume data %s from disk", pv_name);
276*86d7f5d3SJohn Marino 
277*86d7f5d3SJohn Marino 	if (!mem)
278*86d7f5d3SJohn Marino 		return_0;
279*86d7f5d3SJohn Marino 
280*86d7f5d3SJohn Marino 	if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
281*86d7f5d3SJohn Marino 		goto_out;
282*86d7f5d3SJohn Marino 
283*86d7f5d3SJohn Marino 	if (!(dl = read_disk(fmt, dev, mem, NULL)))
284*86d7f5d3SJohn Marino 		goto_out;
285*86d7f5d3SJohn Marino 
286*86d7f5d3SJohn Marino 	if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd))
287*86d7f5d3SJohn Marino 		goto_out;
288*86d7f5d3SJohn Marino 
289*86d7f5d3SJohn Marino 	pv->fmt = fmt;
290*86d7f5d3SJohn Marino 
291*86d7f5d3SJohn Marino 	r = 1;
292*86d7f5d3SJohn Marino 
293*86d7f5d3SJohn Marino       out:
294*86d7f5d3SJohn Marino 	dm_pool_destroy(mem);
295*86d7f5d3SJohn Marino 	return r;
296*86d7f5d3SJohn Marino }
297*86d7f5d3SJohn Marino 
_format1_pv_setup(const struct format_type * fmt,uint64_t pe_start,uint32_t extent_count,uint32_t extent_size,unsigned long data_alignment __attribute ((unused)),unsigned long data_alignment_offset __attribute ((unused)),int pvmetadatacopies __attribute ((unused)),uint64_t pvmetadatasize __attribute ((unused)),struct dm_list * mdas __attribute ((unused)),struct physical_volume * pv,struct volume_group * vg __attribute ((unused)))298*86d7f5d3SJohn Marino static int _format1_pv_setup(const struct format_type *fmt,
299*86d7f5d3SJohn Marino 		     uint64_t pe_start, uint32_t extent_count,
300*86d7f5d3SJohn Marino 		     uint32_t extent_size,
301*86d7f5d3SJohn Marino 		     unsigned long data_alignment __attribute((unused)),
302*86d7f5d3SJohn Marino 		     unsigned long data_alignment_offset __attribute((unused)),
303*86d7f5d3SJohn Marino 		     int pvmetadatacopies __attribute((unused)),
304*86d7f5d3SJohn Marino 		     uint64_t pvmetadatasize __attribute((unused)), struct dm_list *mdas __attribute((unused)),
305*86d7f5d3SJohn Marino 		     struct physical_volume *pv, struct volume_group *vg __attribute((unused)))
306*86d7f5d3SJohn Marino {
307*86d7f5d3SJohn Marino 	if (pv->size > MAX_PV_SIZE)
308*86d7f5d3SJohn Marino 		pv->size--;
309*86d7f5d3SJohn Marino 	if (pv->size > MAX_PV_SIZE) {
310*86d7f5d3SJohn Marino 		log_error("Physical volumes cannot be bigger than %s",
311*86d7f5d3SJohn Marino 			  display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE));
312*86d7f5d3SJohn Marino 		return 0;
313*86d7f5d3SJohn Marino 	}
314*86d7f5d3SJohn Marino 
315*86d7f5d3SJohn Marino 	/* Nothing more to do if extent size isn't provided */
316*86d7f5d3SJohn Marino 	if (!extent_size)
317*86d7f5d3SJohn Marino 		return 1;
318*86d7f5d3SJohn Marino 
319*86d7f5d3SJohn Marino 	/*
320*86d7f5d3SJohn Marino 	 * This works out pe_start and pe_count.
321*86d7f5d3SJohn Marino 	 */
322*86d7f5d3SJohn Marino 	if (!calculate_extent_count(pv, extent_size, extent_count, pe_start))
323*86d7f5d3SJohn Marino 		return_0;
324*86d7f5d3SJohn Marino 
325*86d7f5d3SJohn Marino 	/* Retain existing extent locations exactly */
326*86d7f5d3SJohn Marino 	if (((pe_start || extent_count) && (pe_start != pv->pe_start)) ||
327*86d7f5d3SJohn Marino 	    (extent_count && (extent_count != pv->pe_count))) {
328*86d7f5d3SJohn Marino 		log_error("Metadata would overwrite physical extents");
329*86d7f5d3SJohn Marino 		return 0;
330*86d7f5d3SJohn Marino 	}
331*86d7f5d3SJohn Marino 
332*86d7f5d3SJohn Marino 	return 1;
333*86d7f5d3SJohn Marino }
334*86d7f5d3SJohn Marino 
_format1_lv_setup(struct format_instance * fid,struct logical_volume * lv)335*86d7f5d3SJohn Marino static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
336*86d7f5d3SJohn Marino {
337*86d7f5d3SJohn Marino 	uint64_t max_size = UINT_MAX;
338*86d7f5d3SJohn Marino 
339*86d7f5d3SJohn Marino 	if (!*lv->lvid.s)
340*86d7f5d3SJohn Marino 		lvid_from_lvnum(&lv->lvid, &lv->vg->id, find_free_lvnum(lv));
341*86d7f5d3SJohn Marino 
342*86d7f5d3SJohn Marino 	if (lv->le_count > MAX_LE_TOTAL) {
343*86d7f5d3SJohn Marino 		log_error("logical volumes cannot contain more than "
344*86d7f5d3SJohn Marino 			  "%d extents.", MAX_LE_TOTAL);
345*86d7f5d3SJohn Marino 		return 0;
346*86d7f5d3SJohn Marino 	}
347*86d7f5d3SJohn Marino 	if (lv->size > max_size) {
348*86d7f5d3SJohn Marino 		log_error("logical volumes cannot be larger than %s",
349*86d7f5d3SJohn Marino 			  display_size(fid->fmt->cmd, max_size));
350*86d7f5d3SJohn Marino 		return 0;
351*86d7f5d3SJohn Marino 	}
352*86d7f5d3SJohn Marino 
353*86d7f5d3SJohn Marino 	return 1;
354*86d7f5d3SJohn Marino }
355*86d7f5d3SJohn Marino 
_format1_pv_write(const struct format_type * fmt,struct physical_volume * pv,struct dm_list * mdas __attribute ((unused)),int64_t sector __attribute ((unused)))356*86d7f5d3SJohn Marino static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv,
357*86d7f5d3SJohn Marino 		     struct dm_list *mdas __attribute((unused)), int64_t sector __attribute((unused)))
358*86d7f5d3SJohn Marino {
359*86d7f5d3SJohn Marino 	struct dm_pool *mem;
360*86d7f5d3SJohn Marino 	struct disk_list *dl;
361*86d7f5d3SJohn Marino 	struct dm_list pvs;
362*86d7f5d3SJohn Marino 	struct label *label;
363*86d7f5d3SJohn Marino 	struct lvmcache_info *info;
364*86d7f5d3SJohn Marino 
365*86d7f5d3SJohn Marino 	if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
366*86d7f5d3SJohn Marino 				  pv->vg_name, NULL, 0)))
367*86d7f5d3SJohn Marino 		return_0;
368*86d7f5d3SJohn Marino 	label = info->label;
369*86d7f5d3SJohn Marino 	info->device_size = pv->size << SECTOR_SHIFT;
370*86d7f5d3SJohn Marino 	info->fmt = fmt;
371*86d7f5d3SJohn Marino 
372*86d7f5d3SJohn Marino 	dm_list_init(&info->mdas);
373*86d7f5d3SJohn Marino 
374*86d7f5d3SJohn Marino 	dm_list_init(&pvs);
375*86d7f5d3SJohn Marino 
376*86d7f5d3SJohn Marino 	/* Ensure any residual PE structure is gone */
377*86d7f5d3SJohn Marino 	pv->pe_size = pv->pe_count = 0;
378*86d7f5d3SJohn Marino 	pv->pe_start = LVM1_PE_ALIGN;
379*86d7f5d3SJohn Marino 
380*86d7f5d3SJohn Marino 	if (!(mem = dm_pool_create("lvm1 pv_write", 1024)))
381*86d7f5d3SJohn Marino 		return_0;
382*86d7f5d3SJohn Marino 
383*86d7f5d3SJohn Marino 	if (!(dl = dm_pool_alloc(mem, sizeof(*dl))))
384*86d7f5d3SJohn Marino 		goto_bad;
385*86d7f5d3SJohn Marino 
386*86d7f5d3SJohn Marino 	dl->mem = mem;
387*86d7f5d3SJohn Marino 	dl->dev = pv->dev;
388*86d7f5d3SJohn Marino 
389*86d7f5d3SJohn Marino 	if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv))
390*86d7f5d3SJohn Marino 		goto_bad;
391*86d7f5d3SJohn Marino 
392*86d7f5d3SJohn Marino 	/* must be set to be able to zero gap after PV structure in
393*86d7f5d3SJohn Marino 	   dev_write in order to make other disk tools happy */
394*86d7f5d3SJohn Marino 	dl->pvd.pv_on_disk.base = METADATA_BASE;
395*86d7f5d3SJohn Marino 	dl->pvd.pv_on_disk.size = PV_SIZE;
396*86d7f5d3SJohn Marino 	dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT;
397*86d7f5d3SJohn Marino 
398*86d7f5d3SJohn Marino 	dm_list_add(&pvs, &dl->list);
399*86d7f5d3SJohn Marino 	if (!write_disks(fmt, &pvs))
400*86d7f5d3SJohn Marino 		goto_bad;
401*86d7f5d3SJohn Marino 
402*86d7f5d3SJohn Marino 	dm_pool_destroy(mem);
403*86d7f5d3SJohn Marino 	return 1;
404*86d7f5d3SJohn Marino 
405*86d7f5d3SJohn Marino       bad:
406*86d7f5d3SJohn Marino 	dm_pool_destroy(mem);
407*86d7f5d3SJohn Marino 	return 0;
408*86d7f5d3SJohn Marino }
409*86d7f5d3SJohn Marino 
_format1_vg_setup(struct format_instance * fid,struct volume_group * vg)410*86d7f5d3SJohn Marino static int _format1_vg_setup(struct format_instance *fid, struct volume_group *vg)
411*86d7f5d3SJohn Marino {
412*86d7f5d3SJohn Marino 	/* just check max_pv and max_lv */
413*86d7f5d3SJohn Marino 	if (!vg->max_lv || vg->max_lv >= MAX_LV)
414*86d7f5d3SJohn Marino 		vg->max_lv = MAX_LV - 1;
415*86d7f5d3SJohn Marino 
416*86d7f5d3SJohn Marino 	if (!vg->max_pv || vg->max_pv >= MAX_PV)
417*86d7f5d3SJohn Marino 		vg->max_pv = MAX_PV - 1;
418*86d7f5d3SJohn Marino 
419*86d7f5d3SJohn Marino 	if (vg->extent_size > MAX_PE_SIZE || vg->extent_size < MIN_PE_SIZE) {
420*86d7f5d3SJohn Marino 		log_error("Extent size must be between %s and %s",
421*86d7f5d3SJohn Marino 			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE),
422*86d7f5d3SJohn Marino 			  display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE));
423*86d7f5d3SJohn Marino 
424*86d7f5d3SJohn Marino 		return 0;
425*86d7f5d3SJohn Marino 	}
426*86d7f5d3SJohn Marino 
427*86d7f5d3SJohn Marino 	if (vg->extent_size % MIN_PE_SIZE) {
428*86d7f5d3SJohn Marino 		log_error("Extent size must be multiple of %s",
429*86d7f5d3SJohn Marino 			  display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE));
430*86d7f5d3SJohn Marino 		return 0;
431*86d7f5d3SJohn Marino 	}
432*86d7f5d3SJohn Marino 
433*86d7f5d3SJohn Marino 	/* Redundant? */
434*86d7f5d3SJohn Marino 	if (vg->extent_size & (vg->extent_size - 1)) {
435*86d7f5d3SJohn Marino 		log_error("Extent size must be power of 2");
436*86d7f5d3SJohn Marino 		return 0;
437*86d7f5d3SJohn Marino 	}
438*86d7f5d3SJohn Marino 
439*86d7f5d3SJohn Marino 	return 1;
440*86d7f5d3SJohn Marino }
441*86d7f5d3SJohn Marino 
_format1_segtype_supported(struct format_instance * fid __attribute ((unused)),const struct segment_type * segtype)442*86d7f5d3SJohn Marino static int _format1_segtype_supported(struct format_instance *fid __attribute((unused)),
443*86d7f5d3SJohn Marino 				      const struct segment_type *segtype)
444*86d7f5d3SJohn Marino {
445*86d7f5d3SJohn Marino 	if (!(segtype->flags & SEG_FORMAT1_SUPPORT))
446*86d7f5d3SJohn Marino 		return_0;
447*86d7f5d3SJohn Marino 
448*86d7f5d3SJohn Marino 	return 1;
449*86d7f5d3SJohn Marino }
450*86d7f5d3SJohn Marino 
451*86d7f5d3SJohn Marino static struct metadata_area_ops _metadata_format1_ops = {
452*86d7f5d3SJohn Marino 	.vg_read = _format1_vg_read,
453*86d7f5d3SJohn Marino 	.vg_write = _format1_vg_write,
454*86d7f5d3SJohn Marino };
455*86d7f5d3SJohn Marino 
_format1_create_instance(const struct format_type * fmt,const char * vgname __attribute ((unused)),const char * vgid __attribute ((unused)),void * private __attribute ((unused)))456*86d7f5d3SJohn Marino static struct format_instance *_format1_create_instance(const struct format_type *fmt,
457*86d7f5d3SJohn Marino 						const char *vgname __attribute((unused)),
458*86d7f5d3SJohn Marino 						const char *vgid __attribute((unused)),
459*86d7f5d3SJohn Marino 						void *private __attribute((unused)))
460*86d7f5d3SJohn Marino {
461*86d7f5d3SJohn Marino 	struct format_instance *fid;
462*86d7f5d3SJohn Marino 	struct metadata_area *mda;
463*86d7f5d3SJohn Marino 
464*86d7f5d3SJohn Marino 	if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid))))
465*86d7f5d3SJohn Marino 		return_NULL;
466*86d7f5d3SJohn Marino 
467*86d7f5d3SJohn Marino 	fid->fmt = fmt;
468*86d7f5d3SJohn Marino 	dm_list_init(&fid->metadata_areas);
469*86d7f5d3SJohn Marino 
470*86d7f5d3SJohn Marino 	/* Define a NULL metadata area */
471*86d7f5d3SJohn Marino 	if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
472*86d7f5d3SJohn Marino 		dm_pool_free(fmt->cmd->mem, fid);
473*86d7f5d3SJohn Marino 		return_NULL;
474*86d7f5d3SJohn Marino 	}
475*86d7f5d3SJohn Marino 
476*86d7f5d3SJohn Marino 	mda->ops = &_metadata_format1_ops;
477*86d7f5d3SJohn Marino 	mda->metadata_locn = NULL;
478*86d7f5d3SJohn Marino 	dm_list_add(&fid->metadata_areas, &mda->list);
479*86d7f5d3SJohn Marino 
480*86d7f5d3SJohn Marino 	return fid;
481*86d7f5d3SJohn Marino }
482*86d7f5d3SJohn Marino 
_format1_destroy_instance(struct format_instance * fid __attribute ((unused)))483*86d7f5d3SJohn Marino static void _format1_destroy_instance(struct format_instance *fid __attribute((unused)))
484*86d7f5d3SJohn Marino {
485*86d7f5d3SJohn Marino 	return;
486*86d7f5d3SJohn Marino }
487*86d7f5d3SJohn Marino 
_format1_destroy(const struct format_type * fmt)488*86d7f5d3SJohn Marino static void _format1_destroy(const struct format_type *fmt)
489*86d7f5d3SJohn Marino {
490*86d7f5d3SJohn Marino 	dm_free((void *) fmt);
491*86d7f5d3SJohn Marino }
492*86d7f5d3SJohn Marino 
493*86d7f5d3SJohn Marino static struct format_handler _format1_ops = {
494*86d7f5d3SJohn Marino 	.pv_read = _format1_pv_read,
495*86d7f5d3SJohn Marino 	.pv_setup = _format1_pv_setup,
496*86d7f5d3SJohn Marino 	.pv_write = _format1_pv_write,
497*86d7f5d3SJohn Marino 	.lv_setup = _format1_lv_setup,
498*86d7f5d3SJohn Marino 	.vg_setup = _format1_vg_setup,
499*86d7f5d3SJohn Marino 	.segtype_supported = _format1_segtype_supported,
500*86d7f5d3SJohn Marino 	.create_instance = _format1_create_instance,
501*86d7f5d3SJohn Marino 	.destroy_instance = _format1_destroy_instance,
502*86d7f5d3SJohn Marino 	.destroy = _format1_destroy,
503*86d7f5d3SJohn Marino };
504*86d7f5d3SJohn Marino 
505*86d7f5d3SJohn Marino #ifdef LVM1_INTERNAL
init_lvm1_format(struct cmd_context * cmd)506*86d7f5d3SJohn Marino struct format_type *init_lvm1_format(struct cmd_context *cmd)
507*86d7f5d3SJohn Marino #else				/* Shared */
508*86d7f5d3SJohn Marino struct format_type *init_format(struct cmd_context *cmd);
509*86d7f5d3SJohn Marino struct format_type *init_format(struct cmd_context *cmd)
510*86d7f5d3SJohn Marino #endif
511*86d7f5d3SJohn Marino {
512*86d7f5d3SJohn Marino 	struct format_type *fmt = dm_malloc(sizeof(*fmt));
513*86d7f5d3SJohn Marino 
514*86d7f5d3SJohn Marino 	if (!fmt)
515*86d7f5d3SJohn Marino 		return_NULL;
516*86d7f5d3SJohn Marino 
517*86d7f5d3SJohn Marino 	fmt->cmd = cmd;
518*86d7f5d3SJohn Marino 	fmt->ops = &_format1_ops;
519*86d7f5d3SJohn Marino 	fmt->name = FMT_LVM1_NAME;
520*86d7f5d3SJohn Marino 	fmt->alias = NULL;
521*86d7f5d3SJohn Marino 	fmt->orphan_vg_name = FMT_LVM1_ORPHAN_VG_NAME;
522*86d7f5d3SJohn Marino 	fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE |
523*86d7f5d3SJohn Marino 			FMT_RESTRICTED_READAHEAD;
524*86d7f5d3SJohn Marino 	fmt->private = NULL;
525*86d7f5d3SJohn Marino 
526*86d7f5d3SJohn Marino 	if (!(fmt->labeller = lvm1_labeller_create(fmt))) {
527*86d7f5d3SJohn Marino 		log_error("Couldn't create lvm1 label handler.");
528*86d7f5d3SJohn Marino 		return NULL;
529*86d7f5d3SJohn Marino 	}
530*86d7f5d3SJohn Marino 
531*86d7f5d3SJohn Marino 	if (!(label_register_handler(FMT_LVM1_NAME, fmt->labeller))) {
532*86d7f5d3SJohn Marino 		log_error("Couldn't register lvm1 label handler.");
533*86d7f5d3SJohn Marino 		return NULL;
534*86d7f5d3SJohn Marino 	}
535*86d7f5d3SJohn Marino 
536*86d7f5d3SJohn Marino 	log_very_verbose("Initialised format: %s", fmt->name);
537*86d7f5d3SJohn Marino 
538*86d7f5d3SJohn Marino 	return fmt;
539*86d7f5d3SJohn Marino }
540