mirror of
git://sourceware.org/git/lvm2.git
synced 2025-04-01 18:50:41 +03:00
Fix handling of partial VG for lvm1 format metadata
If some lvm1 device is missing, lvm fails on all operations # vgcfgbackup -f bck -P vg_test Partial mode. Incomplete volume groups will be activated read-only. 3 PV(s) found for VG vg_test: expected 4 PV segment VG free_count mismatch: 152599 != 228909 PV segment VG extent_count mismatch: 152600 != 228910 Internal error: PV segments corrupted in vg_test. Volume group "vg_test" not found Allow loading of lvm1 partial VG by allocating "new" missing PV, which covers lost space. Also this fake mising PV inform code that it is partial VG. https://bugzilla.redhat.com/show_bug.cgi?id=501390
This commit is contained in:
parent
1588334093
commit
8eaef39b33
@ -1,5 +1,6 @@
|
||||
Version 2.02.74 -
|
||||
=====================================
|
||||
Fix partial mode operations for lvm1 metadata format.
|
||||
Track recursive filter iteration to avoid refreshing while in use. (2.02.56)
|
||||
Revert to old glibc vsnprintf behaviour in emit_to_buffer() to catch overflow.
|
||||
Allocate buffer for metadata tags dynamically to remove 4k limit.
|
||||
|
@ -21,9 +21,10 @@
|
||||
#include "lvm1-label.h"
|
||||
#include "format1.h"
|
||||
#include "segtype.h"
|
||||
#include "pv_alloc.h"
|
||||
|
||||
/* VG consistency checks */
|
||||
static int _check_vgs(struct dm_list *pvs)
|
||||
static int _check_vgs(struct dm_list *pvs, struct volume_group *vg)
|
||||
{
|
||||
struct dm_list *pvh, *t;
|
||||
struct disk_list *dl = NULL;
|
||||
@ -105,11 +106,53 @@ static int _check_vgs(struct dm_list *pvs)
|
||||
if (pv_count != first->vgd.pv_cur) {
|
||||
log_error("%d PV(s) found for VG %s: expected %d",
|
||||
pv_count, first->pvd.vg_name, first->vgd.pv_cur);
|
||||
vg->status |= PARTIAL_VG;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _fix_partial_vg(struct volume_group *vg, struct dm_list *pvs)
|
||||
{
|
||||
uint32_t extent_count = 0;
|
||||
struct disk_list *dl;
|
||||
struct dm_list *pvh;
|
||||
struct pv_list *pvl;
|
||||
|
||||
dm_list_iterate(pvh, pvs) {
|
||||
dl = dm_list_item(pvh, struct disk_list);
|
||||
extent_count += dl->pvd.pe_total;
|
||||
}
|
||||
|
||||
/* FIXME: move this to one place to pv_manip */
|
||||
if (!(pvl = dm_pool_zalloc(vg->vgmem, sizeof(*pvl))) ||
|
||||
!(pvl->pv = dm_pool_zalloc(vg->vgmem, sizeof(*pvl->pv))))
|
||||
return_0;
|
||||
|
||||
if (!id_create(&pvl->pv->id))
|
||||
goto_out;
|
||||
if (!(pvl->pv->vg_name = dm_pool_strdup(vg->vgmem, vg->name)))
|
||||
goto_out;
|
||||
memcpy(&pvl->pv->vgid, &vg->id, sizeof(vg->id));
|
||||
pvl->pv->status |= MISSING_PV;
|
||||
dm_list_init(&pvl->pv->tags);
|
||||
dm_list_init(&pvl->pv->segments);
|
||||
|
||||
pvl->pv->pe_size = vg->extent_size;
|
||||
pvl->pv->pe_count = vg->extent_count - extent_count;
|
||||
if (!alloc_pv_segment_whole_pv(vg->vgmem, pvl->pv))
|
||||
goto_out;
|
||||
|
||||
add_pvl_to_vgs(vg, pvl);
|
||||
log_debug("%s: partial VG, allocated missing PV using %d extents.",
|
||||
vg->name, pvl->pv->pe_count);
|
||||
|
||||
return 1;
|
||||
out:
|
||||
dm_pool_free(vg->vgmem, pvl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct volume_group *_build_vg(struct format_instance *fid,
|
||||
struct dm_list *pvs,
|
||||
struct dm_pool *mem)
|
||||
@ -134,7 +177,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
||||
dm_list_init(&vg->tags);
|
||||
dm_list_init(&vg->removed_pvs);
|
||||
|
||||
if (!_check_vgs(pvs))
|
||||
if (!_check_vgs(pvs, vg))
|
||||
goto_bad;
|
||||
|
||||
dl = dm_list_item(pvs->n, struct disk_list);
|
||||
@ -154,6 +197,10 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
||||
if (!import_snapshots(mem, vg, pvs))
|
||||
goto_bad;
|
||||
|
||||
/* Fix extents counts by adding missing PV if partial VG */
|
||||
if ((vg->status & PARTIAL_VG) && !_fix_partial_vg(vg, pvs))
|
||||
goto_bad;
|
||||
|
||||
return vg;
|
||||
|
||||
bad:
|
||||
|
@ -40,3 +40,12 @@ sed 's/flags = \[\"MISSING\"\]/flags = \[\]/' "$(pwd)/backup.$$" > "$(pwd)/backu
|
||||
pvcreate -ff -y --norestorefile -u $pv1_uuid $dev1
|
||||
pvcreate -ff -y --norestorefile -u $pv2_uuid $dev2
|
||||
vgcfgrestore -f "$(pwd)/backup.$$1" $vg
|
||||
vgremove -ff $vg
|
||||
|
||||
# vgcfgbackup correctly stores metadata LVM1 with missing PVs
|
||||
pvcreate -M1 $devs
|
||||
vgcreate -M1 -c n $vg $devs
|
||||
lvcreate -l1 -n $lv1 $vg $dev1
|
||||
pvremove -ff -y $dev2
|
||||
not lvcreate -l1 -n $lv1 $vg $dev3
|
||||
vgcfgbackup -f "$(pwd)/backup.$$" $vg
|
||||
|
Loading…
x
Reference in New Issue
Block a user