2 * Copyright (C) 2001-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
24 #define xx16(v) disk->v = xlate16(disk->v)
25 #define xx32(v) disk->v = xlate32(disk->v)
26 #define xx64(v) disk->v = xlate64(disk->v)
29 * Functions to perform the endian conversion
30 * between disk and core. The same code works
31 * both ways of course.
33 static void _xlate_pvd(struct pv_disk *disk)
37 xx32(pv_on_disk.base);
38 xx32(pv_on_disk.size);
39 xx32(vg_on_disk.base);
40 xx32(vg_on_disk.size);
41 xx32(pv_uuidlist_on_disk.base);
42 xx32(pv_uuidlist_on_disk.size);
43 xx32(lv_on_disk.base);
44 xx32(lv_on_disk.size);
45 xx32(pe_on_disk.base);
46 xx32(pe_on_disk.size);
60 static void _xlate_lvd(struct lv_disk *disk)
67 xx32(lv_mirror_copies);
71 xx32(lv_snapshot_minor);
74 xx32(lv_allocated_le);
83 static void _xlate_vgd(struct vg_disk *disk)
102 static void _xlate_extents(struct pe_disk *extents, uint32_t count)
106 for (i = 0; i < count; i++) {
107 extents[i].lv_num = xlate16(extents[i].lv_num);
108 extents[i].le_num = xlate16(extents[i].le_num);
113 * Handle both minor metadata formats.
115 static int _munge_formats(struct pv_disk *pvd)
120 switch (pvd->version) {
122 pvd->pe_start = ((pvd->pe_on_disk.base +
123 pvd->pe_on_disk.size) >> SECTOR_SHIFT);
128 pe_start = pvd->pe_start << SECTOR_SHIFT;
129 pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
137 if (pvd->pv_uuid[ID_LEN]) {
138 /* Retain ID_LEN chars from end */
139 for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
140 if (!pvd->pv_uuid[e]) {
145 for (b = 0; b < ID_LEN; b++) {
146 pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
147 /* FIXME Remove all invalid chars */
148 if (pvd->pv_uuid[b] == '/')
149 pvd->pv_uuid[b] = '#';
151 memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
154 /* If UUID is missing, create one */
155 if (pvd->pv_uuid[0] == '\0') {
156 uuid_from_num((char *)pvd->pv_uuid, pvd->pv_number);
157 pvd->pv_uuid[ID_LEN] = '\0';
164 * If exported, remove "PV_EXP" from end of VG name
166 static void _munge_exported_vg(struct pv_disk *pvd)
171 /* Return if PV not in a VG */
172 if ((!*pvd->vg_name))
174 /* FIXME also check vgd->status & VG_EXPORTED? */
176 l = strlen((char *)pvd->vg_name);
177 s = sizeof(EXPORTED_TAG);
178 if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
179 pvd->vg_name[l - s + 1] = '\0';
180 pvd->pv_status |= VG_EXPORTED;
184 int munge_pvd(struct device *dev, struct pv_disk *pvd)
188 if (pvd->id[0] != 'H' || pvd->id[1] != 'M') {
189 log_very_verbose("%s does not have a valid LVM1 PV identifier",
194 if (!_munge_formats(pvd)) {
195 log_very_verbose("format1: Unknown metadata version %d "
196 "found on %s", pvd->version, dev_name(dev));
200 /* If VG is exported, set VG name back to the real name */
201 _munge_exported_vg(pvd);
206 static int _read_pvd(struct device *dev, struct pv_disk *pvd)
208 if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
209 log_very_verbose("Failed to read PV data from %s",
214 return munge_pvd(dev, pvd);
217 static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
219 if (!dev_read(dev, pos, sizeof(*disk), disk))
227 int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
229 uint64_t pos = pvd->vg_on_disk.base;
231 if (!dev_read(dev, pos, sizeof(*vgd), vgd))
236 if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
239 /* If UUID is missing, create one */
240 if (vgd->vg_uuid[0] == '\0')
241 uuid_from_num((char *)vgd->vg_uuid, vgd->vg_number);
246 static int _read_uuids(struct disk_list *data)
248 unsigned num_read = 0;
249 struct uuid_list *ul;
250 char buffer[NAME_LEN] __attribute__((aligned(8)));
251 uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
252 uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
254 while (pos < end && num_read < data->vgd.pv_cur) {
255 if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
258 if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
261 memcpy(ul->uuid, buffer, NAME_LEN);
262 ul->uuid[NAME_LEN - 1] = '\0';
264 dm_list_add(&data->uuids, &ul->list);
273 static int _check_lvd(struct lv_disk *lvd)
275 return !(lvd->lv_name[0] == '\0');
278 static int _read_lvs(struct disk_list *data)
280 unsigned int i, lvs_read = 0;
283 struct vg_disk *vgd = &data->vgd;
285 for (i = 0; (i < vgd->lv_max) && (lvs_read < vgd->lv_cur); i++) {
286 pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
287 ll = dm_pool_alloc(data->mem, sizeof(*ll));
292 if (!_read_lvd(data->dev, pos, &ll->lvd))
295 if (!_check_lvd(&ll->lvd))
299 dm_list_add(&data->lvds, &ll->list);
305 static int _read_extents(struct disk_list *data)
307 size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
308 struct pe_disk *extents = dm_pool_alloc(data->mem, len);
309 uint64_t pos = data->pvd.pe_on_disk.base;
314 if (!dev_read(data->dev, pos, len, extents))
317 _xlate_extents(extents, data->pvd.pe_total);
318 data->extents = extents;
323 static void __update_lvmcache(const struct format_type *fmt,
324 struct disk_list *dl,
325 struct device *dev, const char *vgid,
328 struct lvmcache_info *info;
329 const char *vgname = *((char *)dl->pvd.vg_name) ?
330 (char *)dl->pvd.vg_name : fmt->orphan_vg_name;
332 if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
333 vgname, vgid, exported ? EXPORTED_VG : 0))) {
338 info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
339 dm_list_init(&info->mdas);
340 info->status &= ~CACHE_INVALID;
343 static struct disk_list *__read_disk(const struct format_type *fmt,
344 struct device *dev, struct dm_pool *mem,
347 struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
348 const char *name = dev_name(dev);
355 dm_list_init(&dl->uuids);
356 dm_list_init(&dl->lvds);
358 if (!_read_pvd(dev, &dl->pvd))
364 if (!*dl->pvd.vg_name) {
365 log_very_verbose("%s is not a member of any format1 VG", name);
367 __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
368 return (vg_name) ? NULL : dl;
371 if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
372 log_error("Failed to read VG data from PV (%s)", name);
373 __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
377 if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
378 log_very_verbose("%s is not a member of the VG %s",
380 __update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
384 __update_lvmcache(fmt, dl, dev, (char *)dl->vgd.vg_uuid,
385 dl->vgd.vg_status & VG_EXPORTED);
387 if (!_read_uuids(dl)) {
388 log_error("Failed to read PV uuid list from %s", name);
392 if (!_read_lvs(dl)) {
393 log_error("Failed to read LV's from %s", name);
397 if (!_read_extents(dl)) {
398 log_error("Failed to read extents from %s", name);
402 log_very_verbose("Found %s in %sVG %s", name,
403 (dl->vgd.vg_status & VG_EXPORTED) ? "exported " : "",
409 dm_pool_free(dl->mem, dl);
413 struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
414 struct dm_pool *mem, const char *vg_name)
416 struct disk_list *dl;
421 dl = __read_disk(fmt, dev, mem, vg_name);
429 static void _add_pv_to_list(struct dm_list *head, struct disk_list *data)
432 struct disk_list *diskl;
434 dm_list_iterate_items(diskl, head) {
436 if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
437 sizeof(pvd->pv_uuid))) {
438 if (!dev_subsystem_part_major(data->dev)) {
439 log_very_verbose("Ignoring duplicate PV %s on "
441 dev_name(data->dev));
444 log_very_verbose("Duplicate PV %s - using %s %s",
445 pvd->pv_uuid, dev_subsystem_name(data->dev),
446 dev_name(data->dev));
447 dm_list_del(&diskl->list);
451 dm_list_add(head, &data->list);
455 * Build a list of pv_d's structures, allocated from mem.
456 * We keep track of the first object allocated from the pool
457 * so we can free off all the memory if something goes wrong.
459 int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
460 struct dev_filter *filter, struct dm_pool *mem,
461 struct dm_list *head)
463 struct dev_iter *iter;
465 struct disk_list *data = NULL;
466 struct lvmcache_vginfo *vginfo;
467 struct lvmcache_info *info;
469 /* Fast path if we already saw this VG and cached the list of PVs */
470 if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
472 dm_list_iterate_items(info, &vginfo->infos) {
474 if (!dev || !(data = read_disk(fmt, dev, mem, vg_name)))
476 _add_pv_to_list(head, data);
479 /* Did we find the whole VG? */
480 if (!vg_name || is_orphan_vg(vg_name) ||
481 (data && *data->pvd.vg_name &&
482 dm_list_size(head) == data->vgd.pv_cur))
487 /* vgcache_del(vg_name); */
490 if (!(iter = dev_iter_create(filter, 1))) {
491 log_error("read_pvs_in_vg: dev_iter_create failed");
495 /* Otherwise do a complete scan */
496 for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
497 if ((data = read_disk(fmt, dev, mem, vg_name))) {
498 _add_pv_to_list(head, data);
501 dev_iter_destroy(iter);
503 if (dm_list_empty(head))
509 static int _write_vgd(struct disk_list *data)
511 struct vg_disk *vgd = &data->vgd;
512 uint64_t pos = data->pvd.vg_on_disk.base;
514 log_debug("Writing %s VG metadata to %s at %" PRIu64 " len %" PRIsize_t,
515 data->pvd.vg_name, dev_name(data->dev), pos, sizeof(*vgd));
518 if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
526 static int _write_uuids(struct disk_list *data)
528 struct uuid_list *ul;
529 uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
530 uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
532 dm_list_iterate_items(ul, &data->uuids) {
534 log_error("Too many uuids to fit on %s",
535 dev_name(data->dev));
539 log_debug("Writing %s uuidlist to %s at %" PRIu64 " len %d",
540 data->pvd.vg_name, dev_name(data->dev),
543 if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
552 static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
554 log_debug("Writing %s LV %s metadata to %s at %" PRIu64 " len %"
555 PRIsize_t, disk->vg_name, disk->lv_name, dev_name(dev),
559 if (!dev_write(dev, pos, sizeof(*disk), disk))
567 static int _write_lvs(struct disk_list *data)
570 uint64_t pos, offset;
572 pos = data->pvd.lv_on_disk.base;
574 if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, 0)) {
575 log_error("Couldn't zero lv area on device '%s'",
576 dev_name(data->dev));
580 dm_list_iterate_items(ll, &data->lvds) {
581 offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
582 if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
583 log_error("lv_number %d too large", ll->lvd.lv_number);
587 if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
594 static int _write_extents(struct disk_list *data)
596 size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
597 struct pe_disk *extents = data->extents;
598 uint64_t pos = data->pvd.pe_on_disk.base;
600 log_debug("Writing %s extents metadata to %s at %" PRIu64 " len %"
601 PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
604 _xlate_extents(extents, data->pvd.pe_total);
605 if (!dev_write(data->dev, pos, len, extents))
608 _xlate_extents(extents, data->pvd.pe_total);
613 static int _write_pvd(struct disk_list *data)
616 uint64_t pos = data->pvd.pv_on_disk.base;
617 size_t size = data->pvd.pv_on_disk.size;
619 if (size < sizeof(struct pv_disk)) {
620 log_error("Invalid PV structure size.");
624 /* Make sure that the gap between the PV structure and
625 the next one is zeroed in order to make non LVM tools
626 happy (idea from AED) */
627 buf = dm_zalloc(size);
629 log_error("Couldn't allocate temporary PV buffer.");
633 memcpy(buf, &data->pvd, sizeof(struct pv_disk));
635 log_debug("Writing %s PV metadata to %s at %" PRIu64 " len %"
636 PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
639 _xlate_pvd((struct pv_disk *) buf);
640 if (!dev_write(data->dev, pos, size, buf)) {
650 * assumes the device has been opened.
652 static int __write_all_pvd(const struct format_type *fmt __attribute__((unused)),
653 struct disk_list *data)
655 const char *pv_name = dev_name(data->dev);
657 if (!_write_pvd(data)) {
658 log_error("Failed to write PV structure onto %s", pv_name);
662 /* vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt); */
664 * Stop here for orphan pv's.
666 if (data->pvd.vg_name[0] == '\0') {
668 vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt); */
673 vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev,
676 if (!_write_vgd(data)) {
677 log_error("Failed to write VG data to %s", pv_name);
681 if (!_write_uuids(data)) {
682 log_error("Failed to write PV uuid list to %s", pv_name);
686 if (!_write_lvs(data)) {
687 log_error("Failed to write LV's to %s", pv_name);
691 if (!_write_extents(data)) {
692 log_error("Failed to write extents to %s", pv_name);
700 * opens the device and hands to the above fn.
702 static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
706 if (!dev_open(data->dev))
709 r = __write_all_pvd(fmt, data);
711 if (!dev_close(data->dev))
718 * Writes all the given pv's to disk. Does very
719 * little sanity checking, so make sure correct
720 * data is passed to here.
722 int write_disks(const struct format_type *fmt, struct dm_list *pvs)
724 struct disk_list *dl;
726 dm_list_iterate_items(dl, pvs) {
727 if (!(_write_all_pvd(fmt, dl)))
730 log_very_verbose("Successfully wrote data to %s",