/* Caller may need to use label_get_handler to create label struct! */ int label_write(struct device *dev, struct label *label) { #pragma pack(8) char buf[LABEL_SIZE]; //__attribute((aligned(8))); #pragma pack() struct label_header *lh = (struct label_header *) buf; int r = 1; if (!label->labeller->ops->write) { log_err("Label handler does not support label writes"); return 0; } if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) { log_error("Label sector %" PRIu64 " beyond range (%ld)", label->sector, LABEL_SCAN_SECTORS); return 0; } memset(buf, 0, LABEL_SIZE); strncpy((char *)lh->id, LABEL_ID, sizeof(lh->id)); lh->sector_xl = xlate64(label->sector); lh->offset_xl = xlate32(sizeof(*lh)); if (!(label->labeller->ops->write)(label, buf)) { stack; return 0; } lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE - ((char *) &lh->offset_xl - (char *) lh))); //((void *) &lh->offset_xl - (void *) lh))); if (!dev_open(dev)) { stack; return 0; } log_info("%s: Writing label to sector %" PRIu64, dev_name(dev), label->sector); if (!dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) { log_debug("Failed to write label to %s", dev_name(dev)); r = 0; } if (!dev_close(dev)) stack; return r; }
static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset) { uint32_t md_magic; /* Version 1 is little endian; version 0.90.0 is machine endian */ if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) && ((md_magic == xlate32(MD_SB_MAGIC)) || (md_magic == MD_SB_MAGIC))) return 1; return 0; }
static void __update_lvmcache(const struct format_type *fmt, struct disk_list *dl, struct device *dev, const char *vgid, unsigned exported) { struct lvmcache_info *info; const char *vgname = *((char *)dl->pvd.vg_name) ? (char *)dl->pvd.vg_name : fmt->orphan_vg_name; if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev, vgname, vgid, exported ? EXPORTED_VG : 0))) { stack; return; } lvmcache_set_device_size(info, ((uint64_t)xlate32(dl->pvd.pv_size)) << SECTOR_SHIFT); lvmcache_del_mdas(info); lvmcache_make_valid(info); }
static void __update_lvmcache(const struct format_type *fmt, struct disk_list *dl, struct device *dev, const char *vgid, unsigned exported) { struct lvmcache_info *info; const char *vgname = *((char *)dl->pvd.vg_name) ? (char *)dl->pvd.vg_name : fmt->orphan_vg_name; if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev, vgname, vgid, exported ? EXPORTED_VG : 0))) { stack; return; } info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT; dm_list_init(&info->mdas); info->status &= ~CACHE_INVALID; }
static struct labeller *_find_labeller(struct device *dev, char *buf, uint64_t *label_sector, uint64_t scan_sector) { #pragma pack(8) char readbuf[LABEL_SCAN_SIZE]; #pragma pack() struct labeller_i *li; struct labeller *r = NULL; struct label_header *lh; struct lvmcache_info *info; uint64_t sector; int found = 0; //char readbuf[LABEL_SCAN_SIZE] __attribute((aligned(8))); if (!dev_read(dev, scan_sector << SECTOR_SHIFT, LABEL_SCAN_SIZE, readbuf)) { log_debug("%s: Failed to read label area", dev_name(dev)); goto out; } /* Scan a few sectors for a valid label */ for (sector = 0; sector < LABEL_SCAN_SECTORS; sector += LABEL_SIZE >> SECTOR_SHIFT) { lh = (struct label_header *) (readbuf + (sector << SECTOR_SHIFT)); if (!strncmp((char *)lh->id, LABEL_ID, sizeof(lh->id))) { if (found) { log_error("Ignoring additional label on %s at " "sector %" PRIu64, dev_name(dev), sector + scan_sector); } if (xlate64(lh->sector_xl) != sector + scan_sector) { log_info("%s: Label for sector %" PRIu64 " found at sector %" PRIu64 " - ignoring", dev_name(dev), xlate64(lh->sector_xl), sector + scan_sector); continue; } if (calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE - ((char *) &lh->offset_xl - (char *) lh)) != //((void *) &lh->offset_xl - (void *) lh)) != xlate32(lh->crc_xl)) { log_info("Label checksum incorrect on %s - " "ignoring", dev_name(dev)); continue; } if (found) continue; } //list_iterate_items(li, &_labellers) { list_iterate_items(li, struct labeller_i, &_labellers) { if (li->l->ops->can_handle(li->l, (char *) lh, sector + scan_sector)) { log_very_verbose("%s: %s label detected", dev_name(dev), li->name); if (found) { log_error("Ignoring additional label " "on %s at sector %" PRIu64, dev_name(dev), sector + scan_sector); continue; } r = li->l; memcpy(buf, lh, LABEL_SIZE); if (label_sector) *label_sector = sector + scan_sector; found = 1; break; } } } out: if (!found) { if ((info = info_from_pvid(dev->pvid))) lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0, NULL); log_very_verbose("%s: No label detected", dev_name(dev)); } return r; }