1*86d7f5d3SJohn Marino /* $NetBSD: disk-rep.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 "xlate.h"
21*86d7f5d3SJohn Marino #include "filter.h"
22*86d7f5d3SJohn Marino #include "lvmcache.h"
23*86d7f5d3SJohn Marino
24*86d7f5d3SJohn Marino #include <fcntl.h>
25*86d7f5d3SJohn Marino
26*86d7f5d3SJohn Marino #define xx16(v) disk->v = xlate16(disk->v)
27*86d7f5d3SJohn Marino #define xx32(v) disk->v = xlate32(disk->v)
28*86d7f5d3SJohn Marino #define xx64(v) disk->v = xlate64(disk->v)
29*86d7f5d3SJohn Marino
30*86d7f5d3SJohn Marino /*
31*86d7f5d3SJohn Marino * Functions to perform the endian conversion
32*86d7f5d3SJohn Marino * between disk and core. The same code works
33*86d7f5d3SJohn Marino * both ways of course.
34*86d7f5d3SJohn Marino */
_xlate_pvd(struct pv_disk * disk)35*86d7f5d3SJohn Marino static void _xlate_pvd(struct pv_disk *disk)
36*86d7f5d3SJohn Marino {
37*86d7f5d3SJohn Marino xx16(version);
38*86d7f5d3SJohn Marino
39*86d7f5d3SJohn Marino xx32(pv_on_disk.base);
40*86d7f5d3SJohn Marino xx32(pv_on_disk.size);
41*86d7f5d3SJohn Marino xx32(vg_on_disk.base);
42*86d7f5d3SJohn Marino xx32(vg_on_disk.size);
43*86d7f5d3SJohn Marino xx32(pv_uuidlist_on_disk.base);
44*86d7f5d3SJohn Marino xx32(pv_uuidlist_on_disk.size);
45*86d7f5d3SJohn Marino xx32(lv_on_disk.base);
46*86d7f5d3SJohn Marino xx32(lv_on_disk.size);
47*86d7f5d3SJohn Marino xx32(pe_on_disk.base);
48*86d7f5d3SJohn Marino xx32(pe_on_disk.size);
49*86d7f5d3SJohn Marino
50*86d7f5d3SJohn Marino xx32(pv_major);
51*86d7f5d3SJohn Marino xx32(pv_number);
52*86d7f5d3SJohn Marino xx32(pv_status);
53*86d7f5d3SJohn Marino xx32(pv_allocatable);
54*86d7f5d3SJohn Marino xx32(pv_size);
55*86d7f5d3SJohn Marino xx32(lv_cur);
56*86d7f5d3SJohn Marino xx32(pe_size);
57*86d7f5d3SJohn Marino xx32(pe_total);
58*86d7f5d3SJohn Marino xx32(pe_allocated);
59*86d7f5d3SJohn Marino xx32(pe_start);
60*86d7f5d3SJohn Marino }
61*86d7f5d3SJohn Marino
_xlate_lvd(struct lv_disk * disk)62*86d7f5d3SJohn Marino static void _xlate_lvd(struct lv_disk *disk)
63*86d7f5d3SJohn Marino {
64*86d7f5d3SJohn Marino xx32(lv_access);
65*86d7f5d3SJohn Marino xx32(lv_status);
66*86d7f5d3SJohn Marino xx32(lv_open);
67*86d7f5d3SJohn Marino xx32(lv_dev);
68*86d7f5d3SJohn Marino xx32(lv_number);
69*86d7f5d3SJohn Marino xx32(lv_mirror_copies);
70*86d7f5d3SJohn Marino xx32(lv_recovery);
71*86d7f5d3SJohn Marino xx32(lv_schedule);
72*86d7f5d3SJohn Marino xx32(lv_size);
73*86d7f5d3SJohn Marino xx32(lv_snapshot_minor);
74*86d7f5d3SJohn Marino xx16(lv_chunk_size);
75*86d7f5d3SJohn Marino xx16(dummy);
76*86d7f5d3SJohn Marino xx32(lv_allocated_le);
77*86d7f5d3SJohn Marino xx32(lv_stripes);
78*86d7f5d3SJohn Marino xx32(lv_stripesize);
79*86d7f5d3SJohn Marino xx32(lv_badblock);
80*86d7f5d3SJohn Marino xx32(lv_allocation);
81*86d7f5d3SJohn Marino xx32(lv_io_timeout);
82*86d7f5d3SJohn Marino xx32(lv_read_ahead);
83*86d7f5d3SJohn Marino }
84*86d7f5d3SJohn Marino
_xlate_vgd(struct vg_disk * disk)85*86d7f5d3SJohn Marino static void _xlate_vgd(struct vg_disk *disk)
86*86d7f5d3SJohn Marino {
87*86d7f5d3SJohn Marino xx32(vg_number);
88*86d7f5d3SJohn Marino xx32(vg_access);
89*86d7f5d3SJohn Marino xx32(vg_status);
90*86d7f5d3SJohn Marino xx32(lv_max);
91*86d7f5d3SJohn Marino xx32(lv_cur);
92*86d7f5d3SJohn Marino xx32(lv_open);
93*86d7f5d3SJohn Marino xx32(pv_max);
94*86d7f5d3SJohn Marino xx32(pv_cur);
95*86d7f5d3SJohn Marino xx32(pv_act);
96*86d7f5d3SJohn Marino xx32(dummy);
97*86d7f5d3SJohn Marino xx32(vgda);
98*86d7f5d3SJohn Marino xx32(pe_size);
99*86d7f5d3SJohn Marino xx32(pe_total);
100*86d7f5d3SJohn Marino xx32(pe_allocated);
101*86d7f5d3SJohn Marino xx32(pvg_total);
102*86d7f5d3SJohn Marino }
103*86d7f5d3SJohn Marino
_xlate_extents(struct pe_disk * extents,uint32_t count)104*86d7f5d3SJohn Marino static void _xlate_extents(struct pe_disk *extents, uint32_t count)
105*86d7f5d3SJohn Marino {
106*86d7f5d3SJohn Marino unsigned i;
107*86d7f5d3SJohn Marino
108*86d7f5d3SJohn Marino for (i = 0; i < count; i++) {
109*86d7f5d3SJohn Marino extents[i].lv_num = xlate16(extents[i].lv_num);
110*86d7f5d3SJohn Marino extents[i].le_num = xlate16(extents[i].le_num);
111*86d7f5d3SJohn Marino }
112*86d7f5d3SJohn Marino }
113*86d7f5d3SJohn Marino
114*86d7f5d3SJohn Marino /*
115*86d7f5d3SJohn Marino * Handle both minor metadata formats.
116*86d7f5d3SJohn Marino */
_munge_formats(struct pv_disk * pvd)117*86d7f5d3SJohn Marino static int _munge_formats(struct pv_disk *pvd)
118*86d7f5d3SJohn Marino {
119*86d7f5d3SJohn Marino uint32_t pe_start;
120*86d7f5d3SJohn Marino unsigned b, e;
121*86d7f5d3SJohn Marino
122*86d7f5d3SJohn Marino switch (pvd->version) {
123*86d7f5d3SJohn Marino case 1:
124*86d7f5d3SJohn Marino pvd->pe_start = ((pvd->pe_on_disk.base +
125*86d7f5d3SJohn Marino pvd->pe_on_disk.size) >> SECTOR_SHIFT);
126*86d7f5d3SJohn Marino break;
127*86d7f5d3SJohn Marino
128*86d7f5d3SJohn Marino case 2:
129*86d7f5d3SJohn Marino pvd->version = 1;
130*86d7f5d3SJohn Marino pe_start = pvd->pe_start << SECTOR_SHIFT;
131*86d7f5d3SJohn Marino pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
132*86d7f5d3SJohn Marino break;
133*86d7f5d3SJohn Marino
134*86d7f5d3SJohn Marino default:
135*86d7f5d3SJohn Marino return 0;
136*86d7f5d3SJohn Marino }
137*86d7f5d3SJohn Marino
138*86d7f5d3SJohn Marino /* UUID too long? */
139*86d7f5d3SJohn Marino if (pvd->pv_uuid[ID_LEN]) {
140*86d7f5d3SJohn Marino /* Retain ID_LEN chars from end */
141*86d7f5d3SJohn Marino for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
142*86d7f5d3SJohn Marino if (!pvd->pv_uuid[e]) {
143*86d7f5d3SJohn Marino e--;
144*86d7f5d3SJohn Marino break;
145*86d7f5d3SJohn Marino }
146*86d7f5d3SJohn Marino }
147*86d7f5d3SJohn Marino for (b = 0; b < ID_LEN; b++) {
148*86d7f5d3SJohn Marino pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
149*86d7f5d3SJohn Marino /* FIXME Remove all invalid chars */
150*86d7f5d3SJohn Marino if (pvd->pv_uuid[b] == '/')
151*86d7f5d3SJohn Marino pvd->pv_uuid[b] = '#';
152*86d7f5d3SJohn Marino }
153*86d7f5d3SJohn Marino memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
154*86d7f5d3SJohn Marino }
155*86d7f5d3SJohn Marino
156*86d7f5d3SJohn Marino /* If UUID is missing, create one */
157*86d7f5d3SJohn Marino if (pvd->pv_uuid[0] == '\0') {
158*86d7f5d3SJohn Marino uuid_from_num((char *)pvd->pv_uuid, pvd->pv_number);
159*86d7f5d3SJohn Marino pvd->pv_uuid[ID_LEN] = '\0';
160*86d7f5d3SJohn Marino }
161*86d7f5d3SJohn Marino
162*86d7f5d3SJohn Marino return 1;
163*86d7f5d3SJohn Marino }
164*86d7f5d3SJohn Marino
165*86d7f5d3SJohn Marino /*
166*86d7f5d3SJohn Marino * If exported, remove "PV_EXP" from end of VG name
167*86d7f5d3SJohn Marino */
_munge_exported_vg(struct pv_disk * pvd)168*86d7f5d3SJohn Marino static void _munge_exported_vg(struct pv_disk *pvd)
169*86d7f5d3SJohn Marino {
170*86d7f5d3SJohn Marino int l;
171*86d7f5d3SJohn Marino size_t s;
172*86d7f5d3SJohn Marino
173*86d7f5d3SJohn Marino /* Return if PV not in a VG */
174*86d7f5d3SJohn Marino if ((!*pvd->vg_name))
175*86d7f5d3SJohn Marino return;
176*86d7f5d3SJohn Marino /* FIXME also check vgd->status & VG_EXPORTED? */
177*86d7f5d3SJohn Marino
178*86d7f5d3SJohn Marino l = strlen((char *)pvd->vg_name);
179*86d7f5d3SJohn Marino s = sizeof(EXPORTED_TAG);
180*86d7f5d3SJohn Marino if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
181*86d7f5d3SJohn Marino pvd->vg_name[l - s + 1] = '\0';
182*86d7f5d3SJohn Marino pvd->pv_status |= VG_EXPORTED;
183*86d7f5d3SJohn Marino }
184*86d7f5d3SJohn Marino }
185*86d7f5d3SJohn Marino
munge_pvd(struct device * dev,struct pv_disk * pvd)186*86d7f5d3SJohn Marino int munge_pvd(struct device *dev, struct pv_disk *pvd)
187*86d7f5d3SJohn Marino {
188*86d7f5d3SJohn Marino _xlate_pvd(pvd);
189*86d7f5d3SJohn Marino
190*86d7f5d3SJohn Marino if (pvd->id[0] != 'H' || pvd->id[1] != 'M') {
191*86d7f5d3SJohn Marino log_very_verbose("%s does not have a valid LVM1 PV identifier",
192*86d7f5d3SJohn Marino dev_name(dev));
193*86d7f5d3SJohn Marino return 0;
194*86d7f5d3SJohn Marino }
195*86d7f5d3SJohn Marino
196*86d7f5d3SJohn Marino if (!_munge_formats(pvd)) {
197*86d7f5d3SJohn Marino log_very_verbose("format1: Unknown metadata version %d "
198*86d7f5d3SJohn Marino "found on %s", pvd->version, dev_name(dev));
199*86d7f5d3SJohn Marino return 0;
200*86d7f5d3SJohn Marino }
201*86d7f5d3SJohn Marino
202*86d7f5d3SJohn Marino /* If VG is exported, set VG name back to the real name */
203*86d7f5d3SJohn Marino _munge_exported_vg(pvd);
204*86d7f5d3SJohn Marino
205*86d7f5d3SJohn Marino return 1;
206*86d7f5d3SJohn Marino }
207*86d7f5d3SJohn Marino
_read_pvd(struct device * dev,struct pv_disk * pvd)208*86d7f5d3SJohn Marino static int _read_pvd(struct device *dev, struct pv_disk *pvd)
209*86d7f5d3SJohn Marino {
210*86d7f5d3SJohn Marino if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
211*86d7f5d3SJohn Marino log_very_verbose("Failed to read PV data from %s",
212*86d7f5d3SJohn Marino dev_name(dev));
213*86d7f5d3SJohn Marino return 0;
214*86d7f5d3SJohn Marino }
215*86d7f5d3SJohn Marino
216*86d7f5d3SJohn Marino return munge_pvd(dev, pvd);
217*86d7f5d3SJohn Marino }
218*86d7f5d3SJohn Marino
_read_lvd(struct device * dev,uint64_t pos,struct lv_disk * disk)219*86d7f5d3SJohn Marino static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
220*86d7f5d3SJohn Marino {
221*86d7f5d3SJohn Marino if (!dev_read(dev, pos, sizeof(*disk), disk))
222*86d7f5d3SJohn Marino return_0;
223*86d7f5d3SJohn Marino
224*86d7f5d3SJohn Marino _xlate_lvd(disk);
225*86d7f5d3SJohn Marino
226*86d7f5d3SJohn Marino return 1;
227*86d7f5d3SJohn Marino }
228*86d7f5d3SJohn Marino
read_vgd(struct device * dev,struct vg_disk * vgd,struct pv_disk * pvd)229*86d7f5d3SJohn Marino int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
230*86d7f5d3SJohn Marino {
231*86d7f5d3SJohn Marino uint64_t pos = pvd->vg_on_disk.base;
232*86d7f5d3SJohn Marino
233*86d7f5d3SJohn Marino if (!dev_read(dev, pos, sizeof(*vgd), vgd))
234*86d7f5d3SJohn Marino return_0;
235*86d7f5d3SJohn Marino
236*86d7f5d3SJohn Marino _xlate_vgd(vgd);
237*86d7f5d3SJohn Marino
238*86d7f5d3SJohn Marino if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
239*86d7f5d3SJohn Marino return_0;
240*86d7f5d3SJohn Marino
241*86d7f5d3SJohn Marino /* If UUID is missing, create one */
242*86d7f5d3SJohn Marino if (vgd->vg_uuid[0] == '\0')
243*86d7f5d3SJohn Marino uuid_from_num((char *)vgd->vg_uuid, vgd->vg_number);
244*86d7f5d3SJohn Marino
245*86d7f5d3SJohn Marino return 1;
246*86d7f5d3SJohn Marino }
247*86d7f5d3SJohn Marino
_read_uuids(struct disk_list * data)248*86d7f5d3SJohn Marino static int _read_uuids(struct disk_list *data)
249*86d7f5d3SJohn Marino {
250*86d7f5d3SJohn Marino unsigned num_read = 0;
251*86d7f5d3SJohn Marino struct uuid_list *ul;
252*86d7f5d3SJohn Marino char buffer[NAME_LEN] __attribute((aligned(8)));
253*86d7f5d3SJohn Marino uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
254*86d7f5d3SJohn Marino uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
255*86d7f5d3SJohn Marino
256*86d7f5d3SJohn Marino while (pos < end && num_read < data->vgd.pv_cur) {
257*86d7f5d3SJohn Marino if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
258*86d7f5d3SJohn Marino return_0;
259*86d7f5d3SJohn Marino
260*86d7f5d3SJohn Marino if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
261*86d7f5d3SJohn Marino return_0;
262*86d7f5d3SJohn Marino
263*86d7f5d3SJohn Marino memcpy(ul->uuid, buffer, NAME_LEN);
264*86d7f5d3SJohn Marino ul->uuid[NAME_LEN - 1] = '\0';
265*86d7f5d3SJohn Marino
266*86d7f5d3SJohn Marino dm_list_add(&data->uuids, &ul->list);
267*86d7f5d3SJohn Marino
268*86d7f5d3SJohn Marino pos += NAME_LEN;
269*86d7f5d3SJohn Marino num_read++;
270*86d7f5d3SJohn Marino }
271*86d7f5d3SJohn Marino
272*86d7f5d3SJohn Marino return 1;
273*86d7f5d3SJohn Marino }
274*86d7f5d3SJohn Marino
_check_lvd(struct lv_disk * lvd)275*86d7f5d3SJohn Marino static int _check_lvd(struct lv_disk *lvd)
276*86d7f5d3SJohn Marino {
277*86d7f5d3SJohn Marino return !(lvd->lv_name[0] == '\0');
278*86d7f5d3SJohn Marino }
279*86d7f5d3SJohn Marino
_read_lvs(struct disk_list * data)280*86d7f5d3SJohn Marino static int _read_lvs(struct disk_list *data)
281*86d7f5d3SJohn Marino {
282*86d7f5d3SJohn Marino unsigned int i, lvs_read = 0;
283*86d7f5d3SJohn Marino uint64_t pos;
284*86d7f5d3SJohn Marino struct lvd_list *ll;
285*86d7f5d3SJohn Marino struct vg_disk *vgd = &data->vgd;
286*86d7f5d3SJohn Marino
287*86d7f5d3SJohn Marino for (i = 0; (i < vgd->lv_max) && (lvs_read < vgd->lv_cur); i++) {
288*86d7f5d3SJohn Marino pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
289*86d7f5d3SJohn Marino ll = dm_pool_alloc(data->mem, sizeof(*ll));
290*86d7f5d3SJohn Marino
291*86d7f5d3SJohn Marino if (!ll)
292*86d7f5d3SJohn Marino return_0;
293*86d7f5d3SJohn Marino
294*86d7f5d3SJohn Marino if (!_read_lvd(data->dev, pos, &ll->lvd))
295*86d7f5d3SJohn Marino return_0;
296*86d7f5d3SJohn Marino
297*86d7f5d3SJohn Marino if (!_check_lvd(&ll->lvd))
298*86d7f5d3SJohn Marino continue;
299*86d7f5d3SJohn Marino
300*86d7f5d3SJohn Marino lvs_read++;
301*86d7f5d3SJohn Marino dm_list_add(&data->lvds, &ll->list);
302*86d7f5d3SJohn Marino }
303*86d7f5d3SJohn Marino
304*86d7f5d3SJohn Marino return 1;
305*86d7f5d3SJohn Marino }
306*86d7f5d3SJohn Marino
_read_extents(struct disk_list * data)307*86d7f5d3SJohn Marino static int _read_extents(struct disk_list *data)
308*86d7f5d3SJohn Marino {
309*86d7f5d3SJohn Marino size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
310*86d7f5d3SJohn Marino struct pe_disk *extents = dm_pool_alloc(data->mem, len);
311*86d7f5d3SJohn Marino uint64_t pos = data->pvd.pe_on_disk.base;
312*86d7f5d3SJohn Marino
313*86d7f5d3SJohn Marino if (!extents)
314*86d7f5d3SJohn Marino return_0;
315*86d7f5d3SJohn Marino
316*86d7f5d3SJohn Marino if (!dev_read(data->dev, pos, len, extents))
317*86d7f5d3SJohn Marino return_0;
318*86d7f5d3SJohn Marino
319*86d7f5d3SJohn Marino _xlate_extents(extents, data->pvd.pe_total);
320*86d7f5d3SJohn Marino data->extents = extents;
321*86d7f5d3SJohn Marino
322*86d7f5d3SJohn Marino return 1;
323*86d7f5d3SJohn Marino }
324*86d7f5d3SJohn Marino
__update_lvmcache(const struct format_type * fmt,struct disk_list * dl,struct device * dev,const char * vgid,unsigned exported)325*86d7f5d3SJohn Marino static void __update_lvmcache(const struct format_type *fmt,
326*86d7f5d3SJohn Marino struct disk_list *dl,
327*86d7f5d3SJohn Marino struct device *dev, const char *vgid,
328*86d7f5d3SJohn Marino unsigned exported)
329*86d7f5d3SJohn Marino {
330*86d7f5d3SJohn Marino struct lvmcache_info *info;
331*86d7f5d3SJohn Marino const char *vgname = *((char *)dl->pvd.vg_name) ?
332*86d7f5d3SJohn Marino (char *)dl->pvd.vg_name : fmt->orphan_vg_name;
333*86d7f5d3SJohn Marino
334*86d7f5d3SJohn Marino if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
335*86d7f5d3SJohn Marino vgname, vgid, exported ? EXPORTED_VG : 0))) {
336*86d7f5d3SJohn Marino stack;
337*86d7f5d3SJohn Marino return;
338*86d7f5d3SJohn Marino }
339*86d7f5d3SJohn Marino
340*86d7f5d3SJohn Marino info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
341*86d7f5d3SJohn Marino dm_list_init(&info->mdas);
342*86d7f5d3SJohn Marino info->status &= ~CACHE_INVALID;
343*86d7f5d3SJohn Marino }
344*86d7f5d3SJohn Marino
__read_disk(const struct format_type * fmt,struct device * dev,struct dm_pool * mem,const char * vg_name)345*86d7f5d3SJohn Marino static struct disk_list *__read_disk(const struct format_type *fmt,
346*86d7f5d3SJohn Marino struct device *dev, struct dm_pool *mem,
347*86d7f5d3SJohn Marino const char *vg_name)
348*86d7f5d3SJohn Marino {
349*86d7f5d3SJohn Marino struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
350*86d7f5d3SJohn Marino const char *name = dev_name(dev);
351*86d7f5d3SJohn Marino
352*86d7f5d3SJohn Marino if (!dl)
353*86d7f5d3SJohn Marino return_NULL;
354*86d7f5d3SJohn Marino
355*86d7f5d3SJohn Marino dl->dev = dev;
356*86d7f5d3SJohn Marino dl->mem = mem;
357*86d7f5d3SJohn Marino dm_list_init(&dl->uuids);
358*86d7f5d3SJohn Marino dm_list_init(&dl->lvds);
359*86d7f5d3SJohn Marino
360*86d7f5d3SJohn Marino if (!_read_pvd(dev, &dl->pvd))
361*86d7f5d3SJohn Marino goto_bad;
362*86d7f5d3SJohn Marino
363*86d7f5d3SJohn Marino /*
364*86d7f5d3SJohn Marino * is it an orphan ?
365*86d7f5d3SJohn Marino */
366*86d7f5d3SJohn Marino if (!*dl->pvd.vg_name) {
367*86d7f5d3SJohn Marino log_very_verbose("%s is not a member of any format1 VG", name);
368*86d7f5d3SJohn Marino
369*86d7f5d3SJohn Marino __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
370*86d7f5d3SJohn Marino return (vg_name) ? NULL : dl;
371*86d7f5d3SJohn Marino }
372*86d7f5d3SJohn Marino
373*86d7f5d3SJohn Marino if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
374*86d7f5d3SJohn Marino log_error("Failed to read VG data from PV (%s)", name);
375*86d7f5d3SJohn Marino __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
376*86d7f5d3SJohn Marino goto bad;
377*86d7f5d3SJohn Marino }
378*86d7f5d3SJohn Marino
379*86d7f5d3SJohn Marino if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
380*86d7f5d3SJohn Marino log_very_verbose("%s is not a member of the VG %s",
381*86d7f5d3SJohn Marino name, vg_name);
382*86d7f5d3SJohn Marino __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
383*86d7f5d3SJohn Marino goto bad;
384*86d7f5d3SJohn Marino }
385*86d7f5d3SJohn Marino
386*86d7f5d3SJohn Marino __update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
387*86d7f5d3SJohn Marino dl->vgd.vg_status & VG_EXPORTED);
388*86d7f5d3SJohn Marino
389*86d7f5d3SJohn Marino if (!_read_uuids(dl)) {
390*86d7f5d3SJohn Marino log_error("Failed to read PV uuid list from %s", name);
391*86d7f5d3SJohn Marino goto bad;
392*86d7f5d3SJohn Marino }
393*86d7f5d3SJohn Marino
394*86d7f5d3SJohn Marino if (!_read_lvs(dl)) {
395*86d7f5d3SJohn Marino log_error("Failed to read LV's from %s", name);
396*86d7f5d3SJohn Marino goto bad;
397*86d7f5d3SJohn Marino }
398*86d7f5d3SJohn Marino
399*86d7f5d3SJohn Marino if (!_read_extents(dl)) {
400*86d7f5d3SJohn Marino log_error("Failed to read extents from %s", name);
401*86d7f5d3SJohn Marino goto bad;
402*86d7f5d3SJohn Marino }
403*86d7f5d3SJohn Marino
404*86d7f5d3SJohn Marino log_very_verbose("Found %s in %sVG %s", name,
405*86d7f5d3SJohn Marino (dl->vgd.vg_status & VG_EXPORTED) ? "exported " : "",
406*86d7f5d3SJohn Marino dl->pvd.vg_name);
407*86d7f5d3SJohn Marino
408*86d7f5d3SJohn Marino return dl;
409*86d7f5d3SJohn Marino
410*86d7f5d3SJohn Marino bad:
411*86d7f5d3SJohn Marino dm_pool_free(dl->mem, dl);
412*86d7f5d3SJohn Marino return NULL;
413*86d7f5d3SJohn Marino }
414*86d7f5d3SJohn Marino
read_disk(const struct format_type * fmt,struct device * dev,struct dm_pool * mem,const char * vg_name)415*86d7f5d3SJohn Marino struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
416*86d7f5d3SJohn Marino struct dm_pool *mem, const char *vg_name)
417*86d7f5d3SJohn Marino {
418*86d7f5d3SJohn Marino struct disk_list *dl;
419*86d7f5d3SJohn Marino
420*86d7f5d3SJohn Marino if (!dev_open(dev))
421*86d7f5d3SJohn Marino return_NULL;
422*86d7f5d3SJohn Marino
423*86d7f5d3SJohn Marino dl = __read_disk(fmt, dev, mem, vg_name);
424*86d7f5d3SJohn Marino
425*86d7f5d3SJohn Marino if (!dev_close(dev))
426*86d7f5d3SJohn Marino stack;
427*86d7f5d3SJohn Marino
428*86d7f5d3SJohn Marino return dl;
429*86d7f5d3SJohn Marino }
430*86d7f5d3SJohn Marino
_add_pv_to_list(struct dm_list * head,struct disk_list * data)431*86d7f5d3SJohn Marino static void _add_pv_to_list(struct dm_list *head, struct disk_list *data)
432*86d7f5d3SJohn Marino {
433*86d7f5d3SJohn Marino struct pv_disk *pvd;
434*86d7f5d3SJohn Marino struct disk_list *diskl;
435*86d7f5d3SJohn Marino
436*86d7f5d3SJohn Marino dm_list_iterate_items(diskl, head) {
437*86d7f5d3SJohn Marino pvd = &diskl->pvd;
438*86d7f5d3SJohn Marino if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
439*86d7f5d3SJohn Marino sizeof(pvd->pv_uuid))) {
440*86d7f5d3SJohn Marino if (!dev_subsystem_part_major(data->dev)) {
441*86d7f5d3SJohn Marino log_very_verbose("Ignoring duplicate PV %s on "
442*86d7f5d3SJohn Marino "%s", pvd->pv_uuid,
443*86d7f5d3SJohn Marino dev_name(data->dev));
444*86d7f5d3SJohn Marino return;
445*86d7f5d3SJohn Marino }
446*86d7f5d3SJohn Marino log_very_verbose("Duplicate PV %s - using %s %s",
447*86d7f5d3SJohn Marino pvd->pv_uuid, dev_subsystem_name(data->dev),
448*86d7f5d3SJohn Marino dev_name(data->dev));
449*86d7f5d3SJohn Marino dm_list_del(&diskl->list);
450*86d7f5d3SJohn Marino break;
451*86d7f5d3SJohn Marino }
452*86d7f5d3SJohn Marino }
453*86d7f5d3SJohn Marino dm_list_add(head, &data->list);
454*86d7f5d3SJohn Marino }
455*86d7f5d3SJohn Marino
456*86d7f5d3SJohn Marino /*
457*86d7f5d3SJohn Marino * Build a list of pv_d's structures, allocated from mem.
458*86d7f5d3SJohn Marino * We keep track of the first object allocated from the pool
459*86d7f5d3SJohn Marino * so we can free off all the memory if something goes wrong.
460*86d7f5d3SJohn Marino */
read_pvs_in_vg(const struct format_type * fmt,const char * vg_name,struct dev_filter * filter,struct dm_pool * mem,struct dm_list * head)461*86d7f5d3SJohn Marino int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
462*86d7f5d3SJohn Marino struct dev_filter *filter, struct dm_pool *mem,
463*86d7f5d3SJohn Marino struct dm_list *head)
464*86d7f5d3SJohn Marino {
465*86d7f5d3SJohn Marino struct dev_iter *iter;
466*86d7f5d3SJohn Marino struct device *dev;
467*86d7f5d3SJohn Marino struct disk_list *data = NULL;
468*86d7f5d3SJohn Marino struct lvmcache_vginfo *vginfo;
469*86d7f5d3SJohn Marino struct lvmcache_info *info;
470*86d7f5d3SJohn Marino
471*86d7f5d3SJohn Marino /* Fast path if we already saw this VG and cached the list of PVs */
472*86d7f5d3SJohn Marino if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
473*86d7f5d3SJohn Marino vginfo->infos.n) {
474*86d7f5d3SJohn Marino dm_list_iterate_items(info, &vginfo->infos) {
475*86d7f5d3SJohn Marino dev = info->dev;
476*86d7f5d3SJohn Marino if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
477*86d7f5d3SJohn Marino break;
478*86d7f5d3SJohn Marino _add_pv_to_list(head, data);
479*86d7f5d3SJohn Marino }
480*86d7f5d3SJohn Marino
481*86d7f5d3SJohn Marino /* Did we find the whole VG? */
482*86d7f5d3SJohn Marino if (!vg_name || is_orphan_vg(vg_name) ||
483*86d7f5d3SJohn Marino (data && *data->pvd.vg_name &&
484*86d7f5d3SJohn Marino dm_list_size(head) == data->vgd.pv_cur))
485*86d7f5d3SJohn Marino return 1;
486*86d7f5d3SJohn Marino
487*86d7f5d3SJohn Marino /* Failed */
488*86d7f5d3SJohn Marino dm_list_init(head);
489*86d7f5d3SJohn Marino /* vgcache_del(vg_name); */
490*86d7f5d3SJohn Marino }
491*86d7f5d3SJohn Marino
492*86d7f5d3SJohn Marino if (!(iter = dev_iter_create(filter, 1))) {
493*86d7f5d3SJohn Marino log_error("read_pvs_in_vg: dev_iter_create failed");
494*86d7f5d3SJohn Marino return 0;
495*86d7f5d3SJohn Marino }
496*86d7f5d3SJohn Marino
497*86d7f5d3SJohn Marino /* Otherwise do a complete scan */
498*86d7f5d3SJohn Marino for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
499*86d7f5d3SJohn Marino if ((data = read_disk(fmt, dev, mem, vg_name))) {
500*86d7f5d3SJohn Marino _add_pv_to_list(head, data);
501*86d7f5d3SJohn Marino }
502*86d7f5d3SJohn Marino }
503*86d7f5d3SJohn Marino dev_iter_destroy(iter);
504*86d7f5d3SJohn Marino
505*86d7f5d3SJohn Marino if (dm_list_empty(head))
506*86d7f5d3SJohn Marino return 0;
507*86d7f5d3SJohn Marino
508*86d7f5d3SJohn Marino return 1;
509*86d7f5d3SJohn Marino }
510*86d7f5d3SJohn Marino
_write_vgd(struct disk_list * data)511*86d7f5d3SJohn Marino static int _write_vgd(struct disk_list *data)
512*86d7f5d3SJohn Marino {
513*86d7f5d3SJohn Marino struct vg_disk *vgd = &data->vgd;
514*86d7f5d3SJohn Marino uint64_t pos = data->pvd.vg_on_disk.base;
515*86d7f5d3SJohn Marino
516*86d7f5d3SJohn Marino log_debug("Writing %s VG metadata to %s at %" PRIu64 " len %" PRIsize_t,
517*86d7f5d3SJohn Marino data->pvd.vg_name, dev_name(data->dev), pos, sizeof(*vgd));
518*86d7f5d3SJohn Marino
519*86d7f5d3SJohn Marino _xlate_vgd(vgd);
520*86d7f5d3SJohn Marino if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
521*86d7f5d3SJohn Marino return_0;
522*86d7f5d3SJohn Marino
523*86d7f5d3SJohn Marino _xlate_vgd(vgd);
524*86d7f5d3SJohn Marino
525*86d7f5d3SJohn Marino return 1;
526*86d7f5d3SJohn Marino }
527*86d7f5d3SJohn Marino
_write_uuids(struct disk_list * data)528*86d7f5d3SJohn Marino static int _write_uuids(struct disk_list *data)
529*86d7f5d3SJohn Marino {
530*86d7f5d3SJohn Marino struct uuid_list *ul;
531*86d7f5d3SJohn Marino uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
532*86d7f5d3SJohn Marino uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
533*86d7f5d3SJohn Marino
534*86d7f5d3SJohn Marino dm_list_iterate_items(ul, &data->uuids) {
535*86d7f5d3SJohn Marino if (pos >= end) {
536*86d7f5d3SJohn Marino log_error("Too many uuids to fit on %s",
537*86d7f5d3SJohn Marino dev_name(data->dev));
538*86d7f5d3SJohn Marino return 0;
539*86d7f5d3SJohn Marino }
540*86d7f5d3SJohn Marino
541*86d7f5d3SJohn Marino log_debug("Writing %s uuidlist to %s at %" PRIu64 " len %d",
542*86d7f5d3SJohn Marino data->pvd.vg_name, dev_name(data->dev),
543*86d7f5d3SJohn Marino pos, NAME_LEN);
544*86d7f5d3SJohn Marino
545*86d7f5d3SJohn Marino if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
546*86d7f5d3SJohn Marino return_0;
547*86d7f5d3SJohn Marino
548*86d7f5d3SJohn Marino pos += NAME_LEN;
549*86d7f5d3SJohn Marino }
550*86d7f5d3SJohn Marino
551*86d7f5d3SJohn Marino return 1;
552*86d7f5d3SJohn Marino }
553*86d7f5d3SJohn Marino
_write_lvd(struct device * dev,uint64_t pos,struct lv_disk * disk)554*86d7f5d3SJohn Marino static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
555*86d7f5d3SJohn Marino {
556*86d7f5d3SJohn Marino log_debug("Writing %s LV %s metadata to %s at %" PRIu64 " len %"
557*86d7f5d3SJohn Marino PRIsize_t, disk->vg_name, disk->lv_name, dev_name(dev),
558*86d7f5d3SJohn Marino pos, sizeof(*disk));
559*86d7f5d3SJohn Marino
560*86d7f5d3SJohn Marino _xlate_lvd(disk);
561*86d7f5d3SJohn Marino if (!dev_write(dev, pos, sizeof(*disk), disk))
562*86d7f5d3SJohn Marino return_0;
563*86d7f5d3SJohn Marino
564*86d7f5d3SJohn Marino _xlate_lvd(disk);
565*86d7f5d3SJohn Marino
566*86d7f5d3SJohn Marino return 1;
567*86d7f5d3SJohn Marino }
568*86d7f5d3SJohn Marino
_write_lvs(struct disk_list * data)569*86d7f5d3SJohn Marino static int _write_lvs(struct disk_list *data)
570*86d7f5d3SJohn Marino {
571*86d7f5d3SJohn Marino struct lvd_list *ll;
572*86d7f5d3SJohn Marino uint64_t pos, offset;
573*86d7f5d3SJohn Marino
574*86d7f5d3SJohn Marino pos = data->pvd.lv_on_disk.base;
575*86d7f5d3SJohn Marino
576*86d7f5d3SJohn Marino if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, 0)) {
577*86d7f5d3SJohn Marino log_error("Couldn't zero lv area on device '%s'",
578*86d7f5d3SJohn Marino dev_name(data->dev));
579*86d7f5d3SJohn Marino return 0;
580*86d7f5d3SJohn Marino }
581*86d7f5d3SJohn Marino
582*86d7f5d3SJohn Marino dm_list_iterate_items(ll, &data->lvds) {
583*86d7f5d3SJohn Marino offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
584*86d7f5d3SJohn Marino if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
585*86d7f5d3SJohn Marino log_error("lv_number %d too large", ll->lvd.lv_number);
586*86d7f5d3SJohn Marino return 0;
587*86d7f5d3SJohn Marino }
588*86d7f5d3SJohn Marino
589*86d7f5d3SJohn Marino if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
590*86d7f5d3SJohn Marino return_0;
591*86d7f5d3SJohn Marino }
592*86d7f5d3SJohn Marino
593*86d7f5d3SJohn Marino return 1;
594*86d7f5d3SJohn Marino }
595*86d7f5d3SJohn Marino
_write_extents(struct disk_list * data)596*86d7f5d3SJohn Marino static int _write_extents(struct disk_list *data)
597*86d7f5d3SJohn Marino {
598*86d7f5d3SJohn Marino size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
599*86d7f5d3SJohn Marino struct pe_disk *extents = data->extents;
600*86d7f5d3SJohn Marino uint64_t pos = data->pvd.pe_on_disk.base;
601*86d7f5d3SJohn Marino
602*86d7f5d3SJohn Marino log_debug("Writing %s extents metadata to %s at %" PRIu64 " len %"
603*86d7f5d3SJohn Marino PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
604*86d7f5d3SJohn Marino pos, len);
605*86d7f5d3SJohn Marino
606*86d7f5d3SJohn Marino _xlate_extents(extents, data->pvd.pe_total);
607*86d7f5d3SJohn Marino if (!dev_write(data->dev, pos, len, extents))
608*86d7f5d3SJohn Marino return_0;
609*86d7f5d3SJohn Marino
610*86d7f5d3SJohn Marino _xlate_extents(extents, data->pvd.pe_total);
611*86d7f5d3SJohn Marino
612*86d7f5d3SJohn Marino return 1;
613*86d7f5d3SJohn Marino }
614*86d7f5d3SJohn Marino
_write_pvd(struct disk_list * data)615*86d7f5d3SJohn Marino static int _write_pvd(struct disk_list *data)
616*86d7f5d3SJohn Marino {
617*86d7f5d3SJohn Marino char *buf;
618*86d7f5d3SJohn Marino uint64_t pos = data->pvd.pv_on_disk.base;
619*86d7f5d3SJohn Marino size_t size = data->pvd.pv_on_disk.size;
620*86d7f5d3SJohn Marino
621*86d7f5d3SJohn Marino if (size < sizeof(struct pv_disk)) {
622*86d7f5d3SJohn Marino log_error("Invalid PV structure size.");
623*86d7f5d3SJohn Marino return 0;
624*86d7f5d3SJohn Marino }
625*86d7f5d3SJohn Marino
626*86d7f5d3SJohn Marino /* Make sure that the gap between the PV structure and
627*86d7f5d3SJohn Marino the next one is zeroed in order to make non LVM tools
628*86d7f5d3SJohn Marino happy (idea from AED) */
629*86d7f5d3SJohn Marino buf = dm_malloc(size);
630*86d7f5d3SJohn Marino if (!buf) {
631*86d7f5d3SJohn Marino log_error("Couldn't allocate temporary PV buffer.");
632*86d7f5d3SJohn Marino return 0;
633*86d7f5d3SJohn Marino }
634*86d7f5d3SJohn Marino
635*86d7f5d3SJohn Marino memset(buf, 0, size);
636*86d7f5d3SJohn Marino memcpy(buf, &data->pvd, sizeof(struct pv_disk));
637*86d7f5d3SJohn Marino
638*86d7f5d3SJohn Marino log_debug("Writing %s PV metadata to %s at %" PRIu64 " len %"
639*86d7f5d3SJohn Marino PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
640*86d7f5d3SJohn Marino pos, size);
641*86d7f5d3SJohn Marino
642*86d7f5d3SJohn Marino _xlate_pvd((struct pv_disk *) buf);
643*86d7f5d3SJohn Marino if (!dev_write(data->dev, pos, size, buf)) {
644*86d7f5d3SJohn Marino dm_free(buf);
645*86d7f5d3SJohn Marino return_0;
646*86d7f5d3SJohn Marino }
647*86d7f5d3SJohn Marino
648*86d7f5d3SJohn Marino dm_free(buf);
649*86d7f5d3SJohn Marino return 1;
650*86d7f5d3SJohn Marino }
651*86d7f5d3SJohn Marino
652*86d7f5d3SJohn Marino /*
653*86d7f5d3SJohn Marino * assumes the device has been opened.
654*86d7f5d3SJohn Marino */
__write_all_pvd(const struct format_type * fmt __attribute ((unused)),struct disk_list * data)655*86d7f5d3SJohn Marino static int __write_all_pvd(const struct format_type *fmt __attribute((unused)),
656*86d7f5d3SJohn Marino struct disk_list *data)
657*86d7f5d3SJohn Marino {
658*86d7f5d3SJohn Marino const char *pv_name = dev_name(data->dev);
659*86d7f5d3SJohn Marino
660*86d7f5d3SJohn Marino if (!_write_pvd(data)) {
661*86d7f5d3SJohn Marino log_error("Failed to write PV structure onto %s", pv_name);
662*86d7f5d3SJohn Marino return 0;
663*86d7f5d3SJohn Marino }
664*86d7f5d3SJohn Marino
665*86d7f5d3SJohn Marino /* vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt); */
666*86d7f5d3SJohn Marino /*
667*86d7f5d3SJohn Marino * Stop here for orphan pv's.
668*86d7f5d3SJohn Marino */
669*86d7f5d3SJohn Marino if (data->pvd.vg_name[0] == '\0') {
670*86d7f5d3SJohn Marino /* if (!test_mode())
671*86d7f5d3SJohn Marino vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt); */
672*86d7f5d3SJohn Marino return 1;
673*86d7f5d3SJohn Marino }
674*86d7f5d3SJohn Marino
675*86d7f5d3SJohn Marino /* if (!test_mode())
676*86d7f5d3SJohn Marino vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev,
677*86d7f5d3SJohn Marino fmt); */
678*86d7f5d3SJohn Marino
679*86d7f5d3SJohn Marino if (!_write_vgd(data)) {
680*86d7f5d3SJohn Marino log_error("Failed to write VG data to %s", pv_name);
681*86d7f5d3SJohn Marino return 0;
682*86d7f5d3SJohn Marino }
683*86d7f5d3SJohn Marino
684*86d7f5d3SJohn Marino if (!_write_uuids(data)) {
685*86d7f5d3SJohn Marino log_error("Failed to write PV uuid list to %s", pv_name);
686*86d7f5d3SJohn Marino return 0;
687*86d7f5d3SJohn Marino }
688*86d7f5d3SJohn Marino
689*86d7f5d3SJohn Marino if (!_write_lvs(data)) {
690*86d7f5d3SJohn Marino log_error("Failed to write LV's to %s", pv_name);
691*86d7f5d3SJohn Marino return 0;
692*86d7f5d3SJohn Marino }
693*86d7f5d3SJohn Marino
694*86d7f5d3SJohn Marino if (!_write_extents(data)) {
695*86d7f5d3SJohn Marino log_error("Failed to write extents to %s", pv_name);
696*86d7f5d3SJohn Marino return 0;
697*86d7f5d3SJohn Marino }
698*86d7f5d3SJohn Marino
699*86d7f5d3SJohn Marino return 1;
700*86d7f5d3SJohn Marino }
701*86d7f5d3SJohn Marino
702*86d7f5d3SJohn Marino /*
703*86d7f5d3SJohn Marino * opens the device and hands to the above fn.
704*86d7f5d3SJohn Marino */
_write_all_pvd(const struct format_type * fmt,struct disk_list * data)705*86d7f5d3SJohn Marino static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
706*86d7f5d3SJohn Marino {
707*86d7f5d3SJohn Marino int r;
708*86d7f5d3SJohn Marino
709*86d7f5d3SJohn Marino if (!dev_open(data->dev))
710*86d7f5d3SJohn Marino return_0;
711*86d7f5d3SJohn Marino
712*86d7f5d3SJohn Marino r = __write_all_pvd(fmt, data);
713*86d7f5d3SJohn Marino
714*86d7f5d3SJohn Marino if (!dev_close(data->dev))
715*86d7f5d3SJohn Marino stack;
716*86d7f5d3SJohn Marino
717*86d7f5d3SJohn Marino return r;
718*86d7f5d3SJohn Marino }
719*86d7f5d3SJohn Marino
720*86d7f5d3SJohn Marino /*
721*86d7f5d3SJohn Marino * Writes all the given pv's to disk. Does very
722*86d7f5d3SJohn Marino * little sanity checking, so make sure correct
723*86d7f5d3SJohn Marino * data is passed to here.
724*86d7f5d3SJohn Marino */
write_disks(const struct format_type * fmt,struct dm_list * pvs)725*86d7f5d3SJohn Marino int write_disks(const struct format_type *fmt, struct dm_list *pvs)
726*86d7f5d3SJohn Marino {
727*86d7f5d3SJohn Marino struct disk_list *dl;
728*86d7f5d3SJohn Marino
729*86d7f5d3SJohn Marino dm_list_iterate_items(dl, pvs) {
730*86d7f5d3SJohn Marino if (!(_write_all_pvd(fmt, dl)))
731*86d7f5d3SJohn Marino return_0;
732*86d7f5d3SJohn Marino
733*86d7f5d3SJohn Marino log_very_verbose("Successfully wrote data to %s",
734*86d7f5d3SJohn Marino dev_name(dl->dev));
735*86d7f5d3SJohn Marino }
736*86d7f5d3SJohn Marino
737*86d7f5d3SJohn Marino return 1;
738*86d7f5d3SJohn Marino }
739