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