2 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU Lesser General Public License v.2.1.
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 /* FIXME Allow for larger labels? Restricted to single sector currently */
30 * Internal labeller struct.
39 static struct dm_list _labellers;
41 static struct labeller_i *_alloc_li(const char *name, struct labeller *l)
43 struct labeller_i *li;
46 len = sizeof(*li) + strlen(name) + 1;
48 if (!(li = dm_malloc(len))) {
49 log_error("Couldn't allocate memory for labeller list object.");
54 strcpy(li->name, name);
59 static void _free_li(struct labeller_i *li)
66 dm_list_init(&_labellers);
72 struct dm_list *c, *n;
73 struct labeller_i *li;
75 for (c = _labellers.n; c && c != &_labellers; c = n) {
77 li = dm_list_item(c, struct labeller_i);
78 li->l->ops->destroy(li->l);
82 dm_list_init(&_labellers);
85 int label_register_handler(const char *name, struct labeller *handler)
87 struct labeller_i *li;
89 if (!(li = _alloc_li(name, handler)))
92 dm_list_add(&_labellers, &li->list);
96 struct labeller *label_get_handler(const char *name)
98 struct labeller_i *li;
100 dm_list_iterate_items(li, &_labellers)
101 if (!strcmp(li->name, name))
107 static struct labeller *_find_labeller(struct device *dev, char *buf,
108 uint64_t *label_sector,
109 uint64_t scan_sector)
111 struct labeller_i *li;
112 struct labeller *r = NULL;
113 struct label_header *lh;
114 struct lvmcache_info *info;
117 char readbuf[LABEL_SCAN_SIZE] __attribute__((aligned(8)));
119 if (!dev_read(dev, scan_sector << SECTOR_SHIFT,
120 LABEL_SCAN_SIZE, readbuf)) {
121 log_debug("%s: Failed to read label area", dev_name(dev));
125 /* Scan a few sectors for a valid label */
126 for (sector = 0; sector < LABEL_SCAN_SECTORS;
127 sector += LABEL_SIZE >> SECTOR_SHIFT) {
128 lh = (struct label_header *) (readbuf +
129 (sector << SECTOR_SHIFT));
131 if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
133 log_error("Ignoring additional label on %s at "
134 "sector %" PRIu64, dev_name(dev),
135 sector + scan_sector);
137 if (xlate64(lh->sector_xl) != sector + scan_sector) {
138 log_info("%s: Label for sector %" PRIu64
139 " found at sector %" PRIu64
140 " - ignoring", dev_name(dev),
141 (uint64_t)xlate64(lh->sector_xl),
142 sector + scan_sector);
145 if (calc_crc(INITIAL_CRC, (uint8_t *)&lh->offset_xl, LABEL_SIZE -
146 ((uint8_t *) &lh->offset_xl - (uint8_t *) lh)) !=
147 xlate32(lh->crc_xl)) {
148 log_info("Label checksum incorrect on %s - "
149 "ignoring", dev_name(dev));
156 dm_list_iterate_items(li, &_labellers) {
157 if (li->l->ops->can_handle(li->l, (char *) lh,
158 sector + scan_sector)) {
159 log_very_verbose("%s: %s label detected",
160 dev_name(dev), li->name);
162 log_error("Ignoring additional label "
163 "on %s at sector %" PRIu64,
165 sector + scan_sector);
169 memcpy(buf, lh, LABEL_SIZE);
171 *label_sector = sector + scan_sector;
180 if ((info = info_from_pvid(dev->pvid, 0)))
181 lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
182 info->fmt->orphan_vg_name,
184 log_very_verbose("%s: No label detected", dev_name(dev));
190 /* FIXME Also wipe associated metadata area headers? */
191 int label_remove(struct device *dev)
193 char buf[LABEL_SIZE] __attribute__((aligned(8)));
194 char readbuf[LABEL_SCAN_SIZE] __attribute__((aligned(8)));
198 struct labeller_i *li;
199 struct label_header *lh;
201 memset(buf, 0, LABEL_SIZE);
203 log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev));
209 * We flush the device just in case someone is stupid
210 * enough to be trying to import an open pv into lvm.
214 if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
215 log_debug("%s: Failed to read label area", dev_name(dev));
219 /* Scan first few sectors for anything looking like a label */
220 for (sector = 0; sector < LABEL_SCAN_SECTORS;
221 sector += LABEL_SIZE >> SECTOR_SHIFT) {
222 lh = (struct label_header *) (readbuf +
223 (sector << SECTOR_SHIFT));
227 if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) {
228 if (xlate64(lh->sector_xl) == sector)
231 dm_list_iterate_items(li, &_labellers) {
232 if (li->l->ops->can_handle(li->l, (char *) lh,
241 log_info("%s: Wiping label at sector %" PRIu64,
242 dev_name(dev), sector);
243 if (!dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE,
245 log_error("Failed to remove label from %s at "
246 "sector %" PRIu64, dev_name(dev),
260 int label_read(struct device *dev, struct label **result,
261 uint64_t scan_sector)
263 char buf[LABEL_SIZE] __attribute__((aligned(8)));
266 struct lvmcache_info *info;
269 if ((info = info_from_pvid(dev->pvid, 1))) {
270 log_debug("Using cached label for %s", dev_name(dev));
271 *result = info->label;
275 if (!dev_open(dev)) {
278 if ((info = info_from_pvid(dev->pvid, 0)))
279 lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
280 info->fmt->orphan_vg_name,
286 if (!(l = _find_labeller(dev, buf, §or, scan_sector)))
289 if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
290 (*result)->sector = sector;
299 /* Caller may need to use label_get_handler to create label struct! */
300 int label_write(struct device *dev, struct label *label)
302 char buf[LABEL_SIZE] __attribute__((aligned(8)));
303 struct label_header *lh = (struct label_header *) buf;
306 if (!label->labeller->ops->write) {
307 log_error("Label handler does not support label writes");
311 if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) {
312 log_error("Label sector %" PRIu64 " beyond range (%ld)",
313 label->sector, LABEL_SCAN_SECTORS);
317 memset(buf, 0, LABEL_SIZE);
319 strncpy((char *)lh->id, LABEL_ID, sizeof(lh->id));
320 lh->sector_xl = xlate64(label->sector);
321 lh->offset_xl = xlate32(sizeof(*lh));
323 if (!(label->labeller->ops->write)(label, buf))
326 lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, (uint8_t *)&lh->offset_xl, LABEL_SIZE -
327 ((uint8_t *) &lh->offset_xl - (uint8_t *) lh)));
332 log_info("%s: Writing label to sector %" PRIu64 " with stored offset %"
333 PRIu32 ".", dev_name(dev), label->sector,
334 xlate32(lh->offset_xl));
335 if (!dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
336 log_debug("Failed to write label to %s", dev_name(dev));
347 int label_verify(struct device *dev)
350 char buf[LABEL_SIZE] __attribute__((aligned(8)));
352 struct lvmcache_info *info;
355 if (!dev_open(dev)) {
356 if ((info = info_from_pvid(dev->pvid, 0)))
357 lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
358 info->fmt->orphan_vg_name,
364 if (!(l = _find_labeller(dev, buf, §or, UINT64_C(0))))
367 r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;
376 void label_destroy(struct label *label)
378 label->labeller->ops->destroy_label(label->labeller, label);
382 struct label *label_create(struct labeller *labeller)
386 if (!(label = dm_zalloc(sizeof(*label)))) {
387 log_error("label allocaction failed");
391 label->labeller = labeller;
393 labeller->ops->initialise_label(labeller, label);