xref: /dflybsd-src/contrib/lvm2/dist/lib/label/label.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /*	$NetBSD: label.c,v 1.1.1.2 2009/12/02 00:26:32 haad Exp $	*/
2*86d7f5d3SJohn Marino 
3*86d7f5d3SJohn Marino /*
4*86d7f5d3SJohn Marino  * Copyright (C) 2002-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 "label.h"
20*86d7f5d3SJohn Marino #include "crc.h"
21*86d7f5d3SJohn Marino #include "xlate.h"
22*86d7f5d3SJohn Marino #include "lvmcache.h"
23*86d7f5d3SJohn Marino #include "metadata.h"
24*86d7f5d3SJohn Marino 
25*86d7f5d3SJohn Marino #include <sys/stat.h>
26*86d7f5d3SJohn Marino #include <fcntl.h>
27*86d7f5d3SJohn Marino #include <unistd.h>
28*86d7f5d3SJohn Marino 
29*86d7f5d3SJohn Marino /* FIXME Allow for larger labels?  Restricted to single sector currently */
30*86d7f5d3SJohn Marino 
31*86d7f5d3SJohn Marino /*
32*86d7f5d3SJohn Marino  * Internal labeller struct.
33*86d7f5d3SJohn Marino  */
34*86d7f5d3SJohn Marino struct labeller_i {
35*86d7f5d3SJohn Marino 	struct dm_list list;
36*86d7f5d3SJohn Marino 
37*86d7f5d3SJohn Marino 	struct labeller *l;
38*86d7f5d3SJohn Marino 	char name[0];
39*86d7f5d3SJohn Marino };
40*86d7f5d3SJohn Marino 
41*86d7f5d3SJohn Marino static struct dm_list _labellers;
42*86d7f5d3SJohn Marino 
_alloc_li(const char * name,struct labeller * l)43*86d7f5d3SJohn Marino static struct labeller_i *_alloc_li(const char *name, struct labeller *l)
44*86d7f5d3SJohn Marino {
45*86d7f5d3SJohn Marino 	struct labeller_i *li;
46*86d7f5d3SJohn Marino 	size_t len;
47*86d7f5d3SJohn Marino 
48*86d7f5d3SJohn Marino 	len = sizeof(*li) + strlen(name) + 1;
49*86d7f5d3SJohn Marino 
50*86d7f5d3SJohn Marino 	if (!(li = dm_malloc(len))) {
51*86d7f5d3SJohn Marino 		log_error("Couldn't allocate memory for labeller list object.");
52*86d7f5d3SJohn Marino 		return NULL;
53*86d7f5d3SJohn Marino 	}
54*86d7f5d3SJohn Marino 
55*86d7f5d3SJohn Marino 	li->l = l;
56*86d7f5d3SJohn Marino 	strcpy(li->name, name);
57*86d7f5d3SJohn Marino 
58*86d7f5d3SJohn Marino 	return li;
59*86d7f5d3SJohn Marino }
60*86d7f5d3SJohn Marino 
_free_li(struct labeller_i * li)61*86d7f5d3SJohn Marino static void _free_li(struct labeller_i *li)
62*86d7f5d3SJohn Marino {
63*86d7f5d3SJohn Marino 	dm_free(li);
64*86d7f5d3SJohn Marino }
65*86d7f5d3SJohn Marino 
label_init(void)66*86d7f5d3SJohn Marino int label_init(void)
67*86d7f5d3SJohn Marino {
68*86d7f5d3SJohn Marino 	dm_list_init(&_labellers);
69*86d7f5d3SJohn Marino 	return 1;
70*86d7f5d3SJohn Marino }
71*86d7f5d3SJohn Marino 
label_exit(void)72*86d7f5d3SJohn Marino void label_exit(void)
73*86d7f5d3SJohn Marino {
74*86d7f5d3SJohn Marino 	struct dm_list *c, *n;
75*86d7f5d3SJohn Marino 	struct labeller_i *li;
76*86d7f5d3SJohn Marino 
77*86d7f5d3SJohn Marino 	for (c = _labellers.n; c && c != &_labellers; c = n) {
78*86d7f5d3SJohn Marino 		n = c->n;
79*86d7f5d3SJohn Marino 		li = dm_list_item(c, struct labeller_i);
80*86d7f5d3SJohn Marino 		li->l->ops->destroy(li->l);
81*86d7f5d3SJohn Marino 		_free_li(li);
82*86d7f5d3SJohn Marino 	}
83*86d7f5d3SJohn Marino 
84*86d7f5d3SJohn Marino 	dm_list_init(&_labellers);
85*86d7f5d3SJohn Marino }
86*86d7f5d3SJohn Marino 
label_register_handler(const char * name,struct labeller * handler)87*86d7f5d3SJohn Marino int label_register_handler(const char *name, struct labeller *handler)
88*86d7f5d3SJohn Marino {
89*86d7f5d3SJohn Marino 	struct labeller_i *li;
90*86d7f5d3SJohn Marino 
91*86d7f5d3SJohn Marino 	if (!(li = _alloc_li(name, handler)))
92*86d7f5d3SJohn Marino 		return_0;
93*86d7f5d3SJohn Marino 
94*86d7f5d3SJohn Marino 	dm_list_add(&_labellers, &li->list);
95*86d7f5d3SJohn Marino 	return 1;
96*86d7f5d3SJohn Marino }
97*86d7f5d3SJohn Marino 
label_get_handler(const char * name)98*86d7f5d3SJohn Marino struct labeller *label_get_handler(const char *name)
99*86d7f5d3SJohn Marino {
100*86d7f5d3SJohn Marino 	struct labeller_i *li;
101*86d7f5d3SJohn Marino 
102*86d7f5d3SJohn Marino 	dm_list_iterate_items(li, &_labellers)
103*86d7f5d3SJohn Marino 		if (!strcmp(li->name, name))
104*86d7f5d3SJohn Marino 			return li->l;
105*86d7f5d3SJohn Marino 
106*86d7f5d3SJohn Marino 	return NULL;
107*86d7f5d3SJohn Marino }
108*86d7f5d3SJohn Marino 
_find_labeller(struct device * dev,char * buf,uint64_t * label_sector,uint64_t scan_sector)109*86d7f5d3SJohn Marino static struct labeller *_find_labeller(struct device *dev, char *buf,
110*86d7f5d3SJohn Marino 				       uint64_t *label_sector,
111*86d7f5d3SJohn Marino 				       uint64_t scan_sector)
112*86d7f5d3SJohn Marino {
113*86d7f5d3SJohn Marino 	struct labeller_i *li;
114*86d7f5d3SJohn Marino 	struct labeller *r = NULL;
115*86d7f5d3SJohn Marino 	struct label_header *lh;
116*86d7f5d3SJohn Marino 	struct lvmcache_info *info;
117*86d7f5d3SJohn Marino 	uint64_t sector;
118*86d7f5d3SJohn Marino 	int found = 0;
119*86d7f5d3SJohn Marino 	char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
120*86d7f5d3SJohn Marino 
121*86d7f5d3SJohn Marino 	if (!dev_read(dev, scan_sector << SECTOR_SHIFT,
122*86d7f5d3SJohn Marino 		      LABEL_SCAN_SIZE, readbuf)) {
123*86d7f5d3SJohn Marino 		log_debug("%s: Failed to read label area", dev_name(dev));
124*86d7f5d3SJohn Marino 		goto out;
125*86d7f5d3SJohn Marino 	}
126*86d7f5d3SJohn Marino 
127*86d7f5d3SJohn Marino 	/* Scan a few sectors for a valid label */
128*86d7f5d3SJohn Marino 	for (sector = 0; sector < LABEL_SCAN_SECTORS;
129*86d7f5d3SJohn Marino 	     sector += LABEL_SIZE >> SECTOR_SHIFT) {
130*86d7f5d3SJohn Marino 		lh = (struct label_header *) (readbuf +
131*86d7f5d3SJohn Marino 					      (sector << SECTOR_SHIFT));
132*86d7f5d3SJohn Marino 
133*86d7f5d3SJohn Marino 		if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
134*86d7f5d3SJohn Marino 			if (found) {
135*86d7f5d3SJohn Marino 				log_error("Ignoring additional label on %s at "
136*86d7f5d3SJohn Marino 					  "sector %" PRIu64, dev_name(dev),
137*86d7f5d3SJohn Marino 					  sector + scan_sector);
138*86d7f5d3SJohn Marino 			}
139*86d7f5d3SJohn Marino 			if (xlate64(lh->sector_xl) != sector + scan_sector) {
140*86d7f5d3SJohn Marino 				log_info("%s: Label for sector %" PRIu64
141*86d7f5d3SJohn Marino 					 " found at sector %" PRIu64
142*86d7f5d3SJohn Marino 					 " - ignoring", dev_name(dev),
143*86d7f5d3SJohn Marino 					 (uint64_t)xlate64(lh->sector_xl),
144*86d7f5d3SJohn Marino 					 sector + scan_sector);
145*86d7f5d3SJohn Marino 				continue;
146*86d7f5d3SJohn Marino 			}
147*86d7f5d3SJohn Marino 			if (calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
148*86d7f5d3SJohn Marino 				     ((uintptr_t) &lh->offset_xl - (uintptr_t) lh)) !=
149*86d7f5d3SJohn Marino 			    xlate32(lh->crc_xl)) {
150*86d7f5d3SJohn Marino 				log_info("Label checksum incorrect on %s - "
151*86d7f5d3SJohn Marino 					 "ignoring", dev_name(dev));
152*86d7f5d3SJohn Marino 				continue;
153*86d7f5d3SJohn Marino 			}
154*86d7f5d3SJohn Marino 			if (found)
155*86d7f5d3SJohn Marino 				continue;
156*86d7f5d3SJohn Marino 		}
157*86d7f5d3SJohn Marino 
158*86d7f5d3SJohn Marino 		dm_list_iterate_items(li, &_labellers) {
159*86d7f5d3SJohn Marino 			if (li->l->ops->can_handle(li->l, (char *) lh,
160*86d7f5d3SJohn Marino 						   sector + scan_sector)) {
161*86d7f5d3SJohn Marino 				log_very_verbose("%s: %s label detected",
162*86d7f5d3SJohn Marino 						 dev_name(dev), li->name);
163*86d7f5d3SJohn Marino 				if (found) {
164*86d7f5d3SJohn Marino 					log_error("Ignoring additional label "
165*86d7f5d3SJohn Marino 						  "on %s at sector %" PRIu64,
166*86d7f5d3SJohn Marino 						  dev_name(dev),
167*86d7f5d3SJohn Marino 						  sector + scan_sector);
168*86d7f5d3SJohn Marino 					continue;
169*86d7f5d3SJohn Marino 				}
170*86d7f5d3SJohn Marino 				r = li->l;
171*86d7f5d3SJohn Marino 				memcpy(buf, lh, LABEL_SIZE);
172*86d7f5d3SJohn Marino 				if (label_sector)
173*86d7f5d3SJohn Marino 					*label_sector = sector + scan_sector;
174*86d7f5d3SJohn Marino 				found = 1;
175*86d7f5d3SJohn Marino 				break;
176*86d7f5d3SJohn Marino 			}
177*86d7f5d3SJohn Marino 		}
178*86d7f5d3SJohn Marino 	}
179*86d7f5d3SJohn Marino 
180*86d7f5d3SJohn Marino       out:
181*86d7f5d3SJohn Marino 	if (!found) {
182*86d7f5d3SJohn Marino 		if ((info = info_from_pvid(dev->pvid, 0)))
183*86d7f5d3SJohn Marino 			lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
184*86d7f5d3SJohn Marino 						      info->fmt->orphan_vg_name,
185*86d7f5d3SJohn Marino 						      0, NULL);
186*86d7f5d3SJohn Marino 		log_very_verbose("%s: No label detected", dev_name(dev));
187*86d7f5d3SJohn Marino 	}
188*86d7f5d3SJohn Marino 
189*86d7f5d3SJohn Marino 	return r;
190*86d7f5d3SJohn Marino }
191*86d7f5d3SJohn Marino 
192*86d7f5d3SJohn Marino /* FIXME Also wipe associated metadata area headers? */
label_remove(struct device * dev)193*86d7f5d3SJohn Marino int label_remove(struct device *dev)
194*86d7f5d3SJohn Marino {
195*86d7f5d3SJohn Marino 	char buf[LABEL_SIZE] __attribute((aligned(8)));
196*86d7f5d3SJohn Marino 	char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8)));
197*86d7f5d3SJohn Marino 	int r = 1;
198*86d7f5d3SJohn Marino 	uint64_t sector;
199*86d7f5d3SJohn Marino 	int wipe;
200*86d7f5d3SJohn Marino 	struct labeller_i *li;
201*86d7f5d3SJohn Marino 	struct label_header *lh;
202*86d7f5d3SJohn Marino 
203*86d7f5d3SJohn Marino 	memset(buf, 0, LABEL_SIZE);
204*86d7f5d3SJohn Marino 
205*86d7f5d3SJohn Marino 	log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev));
206*86d7f5d3SJohn Marino 
207*86d7f5d3SJohn Marino 	if (!dev_open(dev))
208*86d7f5d3SJohn Marino 		return_0;
209*86d7f5d3SJohn Marino 
210*86d7f5d3SJohn Marino 	/*
211*86d7f5d3SJohn Marino 	 * We flush the device just in case someone is stupid
212*86d7f5d3SJohn Marino 	 * enough to be trying to import an open pv into lvm.
213*86d7f5d3SJohn Marino 	 */
214*86d7f5d3SJohn Marino 	dev_flush(dev);
215*86d7f5d3SJohn Marino 
216*86d7f5d3SJohn Marino 	if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
217*86d7f5d3SJohn Marino 		log_debug("%s: Failed to read label area", dev_name(dev));
218*86d7f5d3SJohn Marino 		goto out;
219*86d7f5d3SJohn Marino 	}
220*86d7f5d3SJohn Marino 
221*86d7f5d3SJohn Marino 	/* Scan first few sectors for anything looking like a label */
222*86d7f5d3SJohn Marino 	for (sector = 0; sector < LABEL_SCAN_SECTORS;
223*86d7f5d3SJohn Marino 	     sector += LABEL_SIZE >> SECTOR_SHIFT) {
224*86d7f5d3SJohn Marino 		lh = (struct label_header *) (readbuf +
225*86d7f5d3SJohn Marino 					      (sector << SECTOR_SHIFT));
226*86d7f5d3SJohn Marino 
227*86d7f5d3SJohn Marino 		wipe = 0;
228*86d7f5d3SJohn Marino 
229*86d7f5d3SJohn Marino 		if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
230*86d7f5d3SJohn Marino 			if (xlate64(lh->sector_xl) == sector)
231*86d7f5d3SJohn Marino 				wipe = 1;
232*86d7f5d3SJohn Marino 		} else {
233*86d7f5d3SJohn Marino 			dm_list_iterate_items(li, &_labellers) {
234*86d7f5d3SJohn Marino 				if (li->l->ops->can_handle(li->l, (char *) lh,
235*86d7f5d3SJohn Marino 							   sector)) {
236*86d7f5d3SJohn Marino 					wipe = 1;
237*86d7f5d3SJohn Marino 					break;
238*86d7f5d3SJohn Marino 				}
239*86d7f5d3SJohn Marino 			}
240*86d7f5d3SJohn Marino 		}
241*86d7f5d3SJohn Marino 
242*86d7f5d3SJohn Marino 		if (wipe) {
243*86d7f5d3SJohn Marino 			log_info("%s: Wiping label at sector %" PRIu64,
244*86d7f5d3SJohn Marino 				 dev_name(dev), sector);
245*86d7f5d3SJohn Marino 			if (!dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE,
246*86d7f5d3SJohn Marino 				       buf)) {
247*86d7f5d3SJohn Marino 				log_error("Failed to remove label from %s at "
248*86d7f5d3SJohn Marino 					  "sector %" PRIu64, dev_name(dev),
249*86d7f5d3SJohn Marino 					  sector);
250*86d7f5d3SJohn Marino 				r = 0;
251*86d7f5d3SJohn Marino 			}
252*86d7f5d3SJohn Marino 		}
253*86d7f5d3SJohn Marino 	}
254*86d7f5d3SJohn Marino 
255*86d7f5d3SJohn Marino       out:
256*86d7f5d3SJohn Marino 	if (!dev_close(dev))
257*86d7f5d3SJohn Marino 		stack;
258*86d7f5d3SJohn Marino 
259*86d7f5d3SJohn Marino 	return r;
260*86d7f5d3SJohn Marino }
261*86d7f5d3SJohn Marino 
label_read(struct device * dev,struct label ** result,uint64_t scan_sector)262*86d7f5d3SJohn Marino int label_read(struct device *dev, struct label **result,
263*86d7f5d3SJohn Marino 		uint64_t scan_sector)
264*86d7f5d3SJohn Marino {
265*86d7f5d3SJohn Marino 	char buf[LABEL_SIZE] __attribute((aligned(8)));
266*86d7f5d3SJohn Marino 	struct labeller *l;
267*86d7f5d3SJohn Marino 	uint64_t sector;
268*86d7f5d3SJohn Marino 	struct lvmcache_info *info;
269*86d7f5d3SJohn Marino 	int r = 0;
270*86d7f5d3SJohn Marino 
271*86d7f5d3SJohn Marino 	if ((info = info_from_pvid(dev->pvid, 1))) {
272*86d7f5d3SJohn Marino 		log_debug("Using cached label for %s", dev_name(dev));
273*86d7f5d3SJohn Marino 		*result = info->label;
274*86d7f5d3SJohn Marino 		return 1;
275*86d7f5d3SJohn Marino 	}
276*86d7f5d3SJohn Marino 
277*86d7f5d3SJohn Marino 	if (!dev_open(dev)) {
278*86d7f5d3SJohn Marino 		stack;
279*86d7f5d3SJohn Marino 
280*86d7f5d3SJohn Marino 		if ((info = info_from_pvid(dev->pvid, 0)))
281*86d7f5d3SJohn Marino 			lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
282*86d7f5d3SJohn Marino 						      info->fmt->orphan_vg_name,
283*86d7f5d3SJohn Marino 						      0, NULL);
284*86d7f5d3SJohn Marino 
285*86d7f5d3SJohn Marino 		return r;
286*86d7f5d3SJohn Marino 	}
287*86d7f5d3SJohn Marino 
288*86d7f5d3SJohn Marino 	if (!(l = _find_labeller(dev, buf, &sector, scan_sector)))
289*86d7f5d3SJohn Marino 		goto out;
290*86d7f5d3SJohn Marino 
291*86d7f5d3SJohn Marino 	if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
292*86d7f5d3SJohn Marino 		(*result)->sector = sector;
293*86d7f5d3SJohn Marino 
294*86d7f5d3SJohn Marino       out:
295*86d7f5d3SJohn Marino 	if (!dev_close(dev))
296*86d7f5d3SJohn Marino 		stack;
297*86d7f5d3SJohn Marino 
298*86d7f5d3SJohn Marino 	return r;
299*86d7f5d3SJohn Marino }
300*86d7f5d3SJohn Marino 
301*86d7f5d3SJohn Marino /* Caller may need to use label_get_handler to create label struct! */
label_write(struct device * dev,struct label * label)302*86d7f5d3SJohn Marino int label_write(struct device *dev, struct label *label)
303*86d7f5d3SJohn Marino {
304*86d7f5d3SJohn Marino 	char buf[LABEL_SIZE] __attribute((aligned(8)));
305*86d7f5d3SJohn Marino 	struct label_header *lh = (struct label_header *) buf;
306*86d7f5d3SJohn Marino 	int r = 1;
307*86d7f5d3SJohn Marino 
308*86d7f5d3SJohn Marino 	if (!label->labeller->ops->write) {
309*86d7f5d3SJohn Marino 		log_error("Label handler does not support label writes");
310*86d7f5d3SJohn Marino 		return 0;
311*86d7f5d3SJohn Marino 	}
312*86d7f5d3SJohn Marino 
313*86d7f5d3SJohn Marino 	if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) {
314*86d7f5d3SJohn Marino 		log_error("Label sector %" PRIu64 " beyond range (%ld)",
315*86d7f5d3SJohn Marino 			  label->sector, LABEL_SCAN_SECTORS);
316*86d7f5d3SJohn Marino 		return 0;
317*86d7f5d3SJohn Marino 	}
318*86d7f5d3SJohn Marino 
319*86d7f5d3SJohn Marino 	memset(buf, 0, LABEL_SIZE);
320*86d7f5d3SJohn Marino 
321*86d7f5d3SJohn Marino 	strncpy((char *)lh->id, LABEL_ID, sizeof(lh->id));
322*86d7f5d3SJohn Marino 	lh->sector_xl = xlate64(label->sector);
323*86d7f5d3SJohn Marino 	lh->offset_xl = xlate32(sizeof(*lh));
324*86d7f5d3SJohn Marino 
325*86d7f5d3SJohn Marino 	if (!(label->labeller->ops->write)(label, buf))
326*86d7f5d3SJohn Marino 		return_0;
327*86d7f5d3SJohn Marino 
328*86d7f5d3SJohn Marino 	lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
329*86d7f5d3SJohn Marino 				      ((uintptr_t) &lh->offset_xl - (uintptr_t) lh)));
330*86d7f5d3SJohn Marino 
331*86d7f5d3SJohn Marino 	if (!dev_open(dev))
332*86d7f5d3SJohn Marino 		return_0;
333*86d7f5d3SJohn Marino 
334*86d7f5d3SJohn Marino 	log_info("%s: Writing label to sector %" PRIu64 " with stored offset %"
335*86d7f5d3SJohn Marino 		 PRIu32 ".", dev_name(dev), label->sector,
336*86d7f5d3SJohn Marino 		 xlate32(lh->offset_xl));
337*86d7f5d3SJohn Marino 	if (!dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
338*86d7f5d3SJohn Marino 		log_debug("Failed to write label to %s", dev_name(dev));
339*86d7f5d3SJohn Marino 		r = 0;
340*86d7f5d3SJohn Marino 	}
341*86d7f5d3SJohn Marino 
342*86d7f5d3SJohn Marino 	if (!dev_close(dev))
343*86d7f5d3SJohn Marino 		stack;
344*86d7f5d3SJohn Marino 
345*86d7f5d3SJohn Marino 	return r;
346*86d7f5d3SJohn Marino }
347*86d7f5d3SJohn Marino 
348*86d7f5d3SJohn Marino /* Unused */
label_verify(struct device * dev)349*86d7f5d3SJohn Marino int label_verify(struct device *dev)
350*86d7f5d3SJohn Marino {
351*86d7f5d3SJohn Marino 	struct labeller *l;
352*86d7f5d3SJohn Marino 	char buf[LABEL_SIZE] __attribute((aligned(8)));
353*86d7f5d3SJohn Marino 	uint64_t sector;
354*86d7f5d3SJohn Marino 	struct lvmcache_info *info;
355*86d7f5d3SJohn Marino 	int r = 0;
356*86d7f5d3SJohn Marino 
357*86d7f5d3SJohn Marino 	if (!dev_open(dev)) {
358*86d7f5d3SJohn Marino 		if ((info = info_from_pvid(dev->pvid, 0)))
359*86d7f5d3SJohn Marino 			lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
360*86d7f5d3SJohn Marino 						      info->fmt->orphan_vg_name,
361*86d7f5d3SJohn Marino 						      0, NULL);
362*86d7f5d3SJohn Marino 
363*86d7f5d3SJohn Marino 		return_0;
364*86d7f5d3SJohn Marino 	}
365*86d7f5d3SJohn Marino 
366*86d7f5d3SJohn Marino 	if (!(l = _find_labeller(dev, buf, &sector, UINT64_C(0))))
367*86d7f5d3SJohn Marino 		goto out;
368*86d7f5d3SJohn Marino 
369*86d7f5d3SJohn Marino 	r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;
370*86d7f5d3SJohn Marino 
371*86d7f5d3SJohn Marino       out:
372*86d7f5d3SJohn Marino 	if (!dev_close(dev))
373*86d7f5d3SJohn Marino 		stack;
374*86d7f5d3SJohn Marino 
375*86d7f5d3SJohn Marino 	return r;
376*86d7f5d3SJohn Marino }
377*86d7f5d3SJohn Marino 
label_destroy(struct label * label)378*86d7f5d3SJohn Marino void label_destroy(struct label *label)
379*86d7f5d3SJohn Marino {
380*86d7f5d3SJohn Marino 	label->labeller->ops->destroy_label(label->labeller, label);
381*86d7f5d3SJohn Marino 	dm_free(label);
382*86d7f5d3SJohn Marino }
383*86d7f5d3SJohn Marino 
label_create(struct labeller * labeller)384*86d7f5d3SJohn Marino struct label *label_create(struct labeller *labeller)
385*86d7f5d3SJohn Marino {
386*86d7f5d3SJohn Marino 	struct label *label;
387*86d7f5d3SJohn Marino 
388*86d7f5d3SJohn Marino 	if (!(label = dm_malloc(sizeof(*label)))) {
389*86d7f5d3SJohn Marino 		log_error("label allocaction failed");
390*86d7f5d3SJohn Marino 		return NULL;
391*86d7f5d3SJohn Marino 	}
392*86d7f5d3SJohn Marino 	memset(label, 0, sizeof(*label));
393*86d7f5d3SJohn Marino 
394*86d7f5d3SJohn Marino 	label->labeller = labeller;
395*86d7f5d3SJohn Marino 
396*86d7f5d3SJohn Marino 	labeller->ops->initialise_label(labeller, label);
397*86d7f5d3SJohn Marino 
398*86d7f5d3SJohn Marino 	return label;
399*86d7f5d3SJohn Marino }
400