4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define xx16(v) disk->v = xlate16(disk->v)
27 #define xx32(v) disk->v = xlate32(disk->v)
28 #define xx64(v) disk->v = xlate64(disk->v)
31 * Functions to perform the endian conversion
32 * between disk and core. The same code works
33 * both ways of course.
35 static void _xlate_pvd(struct pv_disk
*disk
)
39 xx32(pv_on_disk
.base
);
40 xx32(pv_on_disk
.size
);
41 xx32(vg_on_disk
.base
);
42 xx32(vg_on_disk
.size
);
43 xx32(pv_uuidlist_on_disk
.base
);
44 xx32(pv_uuidlist_on_disk
.size
);
45 xx32(lv_on_disk
.base
);
46 xx32(lv_on_disk
.size
);
47 xx32(pe_on_disk
.base
);
48 xx32(pe_on_disk
.size
);
62 static void _xlate_lvd(struct lv_disk
*disk
)
69 xx32(lv_mirror_copies
);
73 xx32(lv_snapshot_minor
);
76 xx32(lv_allocated_le
);
85 static void _xlate_vgd(struct vg_disk
*disk
)
104 static void _xlate_extents(struct pe_disk
*extents
, uint32_t count
)
108 for (i
= 0; i
< count
; i
++) {
109 extents
[i
].lv_num
= xlate16(extents
[i
].lv_num
);
110 extents
[i
].le_num
= xlate16(extents
[i
].le_num
);
115 * Handle both minor metadata formats.
117 static int _munge_formats(struct pv_disk
*pvd
)
122 switch (pvd
->version
) {
124 pvd
->pe_start
= ((pvd
->pe_on_disk
.base
+
125 pvd
->pe_on_disk
.size
) >> SECTOR_SHIFT
);
130 pe_start
= pvd
->pe_start
<< SECTOR_SHIFT
;
131 pvd
->pe_on_disk
.size
= pe_start
- pvd
->pe_on_disk
.base
;
139 if (pvd
->pv_uuid
[ID_LEN
]) {
140 /* Retain ID_LEN chars from end */
141 for (e
= ID_LEN
; e
< sizeof(pvd
->pv_uuid
); e
++) {
142 if (!pvd
->pv_uuid
[e
]) {
147 for (b
= 0; b
< ID_LEN
; b
++) {
148 pvd
->pv_uuid
[b
] = pvd
->pv_uuid
[++e
- ID_LEN
];
149 /* FIXME Remove all invalid chars */
150 if (pvd
->pv_uuid
[b
] == '/')
151 pvd
->pv_uuid
[b
] = '#';
153 memset(&pvd
->pv_uuid
[ID_LEN
], 0, sizeof(pvd
->pv_uuid
) - ID_LEN
);
156 /* If UUID is missing, create one */
157 if (pvd
->pv_uuid
[0] == '\0') {
158 uuid_from_num((char *)pvd
->pv_uuid
, pvd
->pv_number
);
159 pvd
->pv_uuid
[ID_LEN
] = '\0';
166 * If exported, remove "PV_EXP" from end of VG name
168 static void _munge_exported_vg(struct pv_disk
*pvd
)
173 /* Return if PV not in a VG */
174 if ((!*pvd
->vg_name
))
176 /* FIXME also check vgd->status & VG_EXPORTED? */
178 l
= strlen((char *)pvd
->vg_name
);
179 s
= sizeof(EXPORTED_TAG
);
180 if (!strncmp((char *)pvd
->vg_name
+ l
- s
+ 1, EXPORTED_TAG
, s
)) {
181 pvd
->vg_name
[l
- s
+ 1] = '\0';
182 pvd
->pv_status
|= VG_EXPORTED
;
186 int munge_pvd(struct device
*dev
, struct pv_disk
*pvd
)
190 if (pvd
->id
[0] != 'H' || pvd
->id
[1] != 'M') {
191 log_very_verbose("%s does not have a valid LVM1 PV identifier",
196 if (!_munge_formats(pvd
)) {
197 log_very_verbose("format1: Unknown metadata version %d "
198 "found on %s", pvd
->version
, dev_name(dev
));
202 /* If VG is exported, set VG name back to the real name */
203 _munge_exported_vg(pvd
);
208 static int _read_pvd(struct device
*dev
, struct pv_disk
*pvd
)
210 if (!dev_read(dev
, UINT64_C(0), sizeof(*pvd
), pvd
)) {
211 log_very_verbose("Failed to read PV data from %s",
216 return munge_pvd(dev
, pvd
);
219 static int _read_lvd(struct device
*dev
, uint64_t pos
, struct lv_disk
*disk
)
221 if (!dev_read(dev
, pos
, sizeof(*disk
), disk
))
229 int read_vgd(struct device
*dev
, struct vg_disk
*vgd
, struct pv_disk
*pvd
)
231 uint64_t pos
= pvd
->vg_on_disk
.base
;
233 if (!dev_read(dev
, pos
, sizeof(*vgd
), vgd
))
238 if ((vgd
->lv_max
> MAX_LV
) || (vgd
->pv_max
> MAX_PV
))
241 /* If UUID is missing, create one */
242 if (vgd
->vg_uuid
[0] == '\0')
243 uuid_from_num((char *)vgd
->vg_uuid
, vgd
->vg_number
);
248 static int _read_uuids(struct disk_list
*data
)
250 unsigned num_read
= 0;
251 struct uuid_list
*ul
;
252 char buffer
[NAME_LEN
] __attribute((aligned(8)));
253 uint64_t pos
= data
->pvd
.pv_uuidlist_on_disk
.base
;
254 uint64_t end
= pos
+ data
->pvd
.pv_uuidlist_on_disk
.size
;
256 while (pos
< end
&& num_read
< data
->vgd
.pv_cur
) {
257 if (!dev_read(data
->dev
, pos
, sizeof(buffer
), buffer
))
260 if (!(ul
= dm_pool_alloc(data
->mem
, sizeof(*ul
))))
263 memcpy(ul
->uuid
, buffer
, NAME_LEN
);
264 ul
->uuid
[NAME_LEN
- 1] = '\0';
266 dm_list_add(&data
->uuids
, &ul
->list
);
275 static int _check_lvd(struct lv_disk
*lvd
)
277 return !(lvd
->lv_name
[0] == '\0');
280 static int _read_lvs(struct disk_list
*data
)
282 unsigned int i
, lvs_read
= 0;
285 struct vg_disk
*vgd
= &data
->vgd
;
287 for (i
= 0; (i
< vgd
->lv_max
) && (lvs_read
< vgd
->lv_cur
); i
++) {
288 pos
= data
->pvd
.lv_on_disk
.base
+ (i
* sizeof(struct lv_disk
));
289 ll
= dm_pool_alloc(data
->mem
, sizeof(*ll
));
294 if (!_read_lvd(data
->dev
, pos
, &ll
->lvd
))
297 if (!_check_lvd(&ll
->lvd
))
301 dm_list_add(&data
->lvds
, &ll
->list
);
307 static int _read_extents(struct disk_list
*data
)
309 size_t len
= sizeof(struct pe_disk
) * data
->pvd
.pe_total
;
310 struct pe_disk
*extents
= dm_pool_alloc(data
->mem
, len
);
311 uint64_t pos
= data
->pvd
.pe_on_disk
.base
;
316 if (!dev_read(data
->dev
, pos
, len
, extents
))
319 _xlate_extents(extents
, data
->pvd
.pe_total
);
320 data
->extents
= extents
;
325 static void __update_lvmcache(const struct format_type
*fmt
,
326 struct disk_list
*dl
,
327 struct device
*dev
, const char *vgid
,
330 struct lvmcache_info
*info
;
331 const char *vgname
= *((char *)dl
->pvd
.vg_name
) ?
332 (char *)dl
->pvd
.vg_name
: fmt
->orphan_vg_name
;
334 if (!(info
= lvmcache_add(fmt
->labeller
, (char *)dl
->pvd
.pv_uuid
, dev
,
335 vgname
, vgid
, exported
? EXPORTED_VG
: 0))) {
340 info
->device_size
= xlate32(dl
->pvd
.pv_size
) << SECTOR_SHIFT
;
341 dm_list_init(&info
->mdas
);
342 info
->status
&= ~CACHE_INVALID
;
345 static struct disk_list
*__read_disk(const struct format_type
*fmt
,
346 struct device
*dev
, struct dm_pool
*mem
,
349 struct disk_list
*dl
= dm_pool_zalloc(mem
, sizeof(*dl
));
350 const char *name
= dev_name(dev
);
357 dm_list_init(&dl
->uuids
);
358 dm_list_init(&dl
->lvds
);
360 if (!_read_pvd(dev
, &dl
->pvd
))
366 if (!*dl
->pvd
.vg_name
) {
367 log_very_verbose("%s is not a member of any format1 VG", name
);
369 __update_lvmcache(fmt
, dl
, dev
, fmt
->orphan_vg_name
, 0);
370 return (vg_name
) ? NULL
: dl
;
373 if (!read_vgd(dl
->dev
, &dl
->vgd
, &dl
->pvd
)) {
374 log_error("Failed to read VG data from PV (%s)", name
);
375 __update_lvmcache(fmt
, dl
, dev
, fmt
->orphan_vg_name
, 0);
379 if (vg_name
&& strcmp(vg_name
, (char *)dl
->pvd
.vg_name
)) {
380 log_very_verbose("%s is not a member of the VG %s",
382 __update_lvmcache(fmt
, dl
, dev
, fmt
->orphan_vg_name
, 0);
386 __update_lvmcache(fmt
, dl
, dev
, (char *)dl
->vgd
.vg_uuid
,
387 dl
->vgd
.vg_status
& VG_EXPORTED
);
389 if (!_read_uuids(dl
)) {
390 log_error("Failed to read PV uuid list from %s", name
);
394 if (!_read_lvs(dl
)) {
395 log_error("Failed to read LV's from %s", name
);
399 if (!_read_extents(dl
)) {
400 log_error("Failed to read extents from %s", name
);
404 log_very_verbose("Found %s in %sVG %s", name
,
405 (dl
->vgd
.vg_status
& VG_EXPORTED
) ? "exported " : "",
411 dm_pool_free(dl
->mem
, dl
);
415 struct disk_list
*read_disk(const struct format_type
*fmt
, struct device
*dev
,
416 struct dm_pool
*mem
, const char *vg_name
)
418 struct disk_list
*dl
;
423 dl
= __read_disk(fmt
, dev
, mem
, vg_name
);
431 static void _add_pv_to_list(struct dm_list
*head
, struct disk_list
*data
)
434 struct disk_list
*diskl
;
436 dm_list_iterate_items(diskl
, head
) {
438 if (!strncmp((char *)data
->pvd
.pv_uuid
, (char *)pvd
->pv_uuid
,
439 sizeof(pvd
->pv_uuid
))) {
440 if (!dev_subsystem_part_major(data
->dev
)) {
441 log_very_verbose("Ignoring duplicate PV %s on "
443 dev_name(data
->dev
));
446 log_very_verbose("Duplicate PV %s - using %s %s",
447 pvd
->pv_uuid
, dev_subsystem_name(data
->dev
),
448 dev_name(data
->dev
));
449 dm_list_del(&diskl
->list
);
453 dm_list_add(head
, &data
->list
);
457 * Build a list of pv_d's structures, allocated from mem.
458 * We keep track of the first object allocated from the pool
459 * so we can free off all the memory if something goes wrong.
461 int read_pvs_in_vg(const struct format_type
*fmt
, const char *vg_name
,
462 struct dev_filter
*filter
, struct dm_pool
*mem
,
463 struct dm_list
*head
)
465 struct dev_iter
*iter
;
467 struct disk_list
*data
= NULL
;
468 struct lvmcache_vginfo
*vginfo
;
469 struct lvmcache_info
*info
;
471 /* Fast path if we already saw this VG and cached the list of PVs */
472 if (vg_name
&& (vginfo
= vginfo_from_vgname(vg_name
, NULL
)) &&
474 dm_list_iterate_items(info
, &vginfo
->infos
) {
476 if (dev
&& !(data
= read_disk(fmt
, dev
, mem
, vg_name
)))
478 _add_pv_to_list(head
, data
);
481 /* Did we find the whole VG? */
482 if (!vg_name
|| is_orphan_vg(vg_name
) ||
483 (data
&& *data
->pvd
.vg_name
&&
484 dm_list_size(head
) == data
->vgd
.pv_cur
))
489 /* vgcache_del(vg_name); */
492 if (!(iter
= dev_iter_create(filter
, 1))) {
493 log_error("read_pvs_in_vg: dev_iter_create failed");
497 /* Otherwise do a complete scan */
498 for (dev
= dev_iter_get(iter
); dev
; dev
= dev_iter_get(iter
)) {
499 if ((data
= read_disk(fmt
, dev
, mem
, vg_name
))) {
500 _add_pv_to_list(head
, data
);
503 dev_iter_destroy(iter
);
505 if (dm_list_empty(head
))
511 static int _write_vgd(struct disk_list
*data
)
513 struct vg_disk
*vgd
= &data
->vgd
;
514 uint64_t pos
= data
->pvd
.vg_on_disk
.base
;
516 log_debug("Writing %s VG metadata to %s at %" PRIu64
" len %" PRIsize_t
,
517 data
->pvd
.vg_name
, dev_name(data
->dev
), pos
, sizeof(*vgd
));
520 if (!dev_write(data
->dev
, pos
, sizeof(*vgd
), vgd
))
528 static int _write_uuids(struct disk_list
*data
)
530 struct uuid_list
*ul
;
531 uint64_t pos
= data
->pvd
.pv_uuidlist_on_disk
.base
;
532 uint64_t end
= pos
+ data
->pvd
.pv_uuidlist_on_disk
.size
;
534 dm_list_iterate_items(ul
, &data
->uuids
) {
536 log_error("Too many uuids to fit on %s",
537 dev_name(data
->dev
));
541 log_debug("Writing %s uuidlist to %s at %" PRIu64
" len %d",
542 data
->pvd
.vg_name
, dev_name(data
->dev
),
545 if (!dev_write(data
->dev
, pos
, NAME_LEN
, ul
->uuid
))
554 static int _write_lvd(struct device
*dev
, uint64_t pos
, struct lv_disk
*disk
)
556 log_debug("Writing %s LV %s metadata to %s at %" PRIu64
" len %"
557 PRIsize_t
, disk
->vg_name
, disk
->lv_name
, dev_name(dev
),
561 if (!dev_write(dev
, pos
, sizeof(*disk
), disk
))
569 static int _write_lvs(struct disk_list
*data
)
572 uint64_t pos
, offset
;
574 pos
= data
->pvd
.lv_on_disk
.base
;
576 if (!dev_set(data
->dev
, pos
, data
->pvd
.lv_on_disk
.size
, 0)) {
577 log_error("Couldn't zero lv area on device '%s'",
578 dev_name(data
->dev
));
582 dm_list_iterate_items(ll
, &data
->lvds
) {
583 offset
= sizeof(struct lv_disk
) * ll
->lvd
.lv_number
;
584 if (offset
+ sizeof(struct lv_disk
) > data
->pvd
.lv_on_disk
.size
) {
585 log_error("lv_number %d too large", ll
->lvd
.lv_number
);
589 if (!_write_lvd(data
->dev
, pos
+ offset
, &ll
->lvd
))
596 static int _write_extents(struct disk_list
*data
)
598 size_t len
= sizeof(struct pe_disk
) * data
->pvd
.pe_total
;
599 struct pe_disk
*extents
= data
->extents
;
600 uint64_t pos
= data
->pvd
.pe_on_disk
.base
;
602 log_debug("Writing %s extents metadata to %s at %" PRIu64
" len %"
603 PRIsize_t
, data
->pvd
.vg_name
, dev_name(data
->dev
),
606 _xlate_extents(extents
, data
->pvd
.pe_total
);
607 if (!dev_write(data
->dev
, pos
, len
, extents
))
610 _xlate_extents(extents
, data
->pvd
.pe_total
);
615 static int _write_pvd(struct disk_list
*data
)
618 uint64_t pos
= data
->pvd
.pv_on_disk
.base
;
619 size_t size
= data
->pvd
.pv_on_disk
.size
;
621 if (size
< sizeof(struct pv_disk
)) {
622 log_error("Invalid PV structure size.");
626 /* Make sure that the gap between the PV structure and
627 the next one is zeroed in order to make non LVM tools
628 happy (idea from AED) */
629 buf
= dm_malloc(size
);
631 log_error("Couldn't allocate temporary PV buffer.");
635 memset(buf
, 0, size
);
636 memcpy(buf
, &data
->pvd
, sizeof(struct pv_disk
));
638 log_debug("Writing %s PV metadata to %s at %" PRIu64
" len %"
639 PRIsize_t
, data
->pvd
.vg_name
, dev_name(data
->dev
),
642 _xlate_pvd((struct pv_disk
*) buf
);
643 if (!dev_write(data
->dev
, pos
, size
, buf
)) {
653 * assumes the device has been opened.
655 static int __write_all_pvd(const struct format_type
*fmt
__attribute((unused
)),
656 struct disk_list
*data
)
658 const char *pv_name
= dev_name(data
->dev
);
660 if (!_write_pvd(data
)) {
661 log_error("Failed to write PV structure onto %s", pv_name
);
665 /* vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt); */
667 * Stop here for orphan pv's.
669 if (data
->pvd
.vg_name
[0] == '\0') {
671 vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt); */
676 vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev,
679 if (!_write_vgd(data
)) {
680 log_error("Failed to write VG data to %s", pv_name
);
684 if (!_write_uuids(data
)) {
685 log_error("Failed to write PV uuid list to %s", pv_name
);
689 if (!_write_lvs(data
)) {
690 log_error("Failed to write LV's to %s", pv_name
);
694 if (!_write_extents(data
)) {
695 log_error("Failed to write extents to %s", pv_name
);
703 * opens the device and hands to the above fn.
705 static int _write_all_pvd(const struct format_type
*fmt
, struct disk_list
*data
)
709 if (!dev_open(data
->dev
))
712 r
= __write_all_pvd(fmt
, data
);
714 if (!dev_close(data
->dev
))
721 * Writes all the given pv's to disk. Does very
722 * little sanity checking, so make sure correct
723 * data is passed to here.
725 int write_disks(const struct format_type
*fmt
, struct dm_list
*pvs
)
727 struct disk_list
*dl
;
729 dm_list_iterate_items(dl
, pvs
) {
730 if (!(_write_all_pvd(fmt
, dl
)))
733 log_very_verbose("Successfully wrote data to %s",