]> sourceware.org Git - lvm2.git/commitdiff
Fix handling of partial VG for lvm1 format metadata
authorMilan Broz <mbroz@redhat.com>
Wed, 22 Sep 2010 13:45:21 +0000 (13:45 +0000)
committerMilan Broz <mbroz@redhat.com>
Wed, 22 Sep 2010 13:45:21 +0000 (13:45 +0000)
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

WHATS_NEW
lib/format1/format1.c
test/t-vgcfgbackup-usage.sh

index 3444069cfdbb942983b502158098d7a05e1b4f22..77ca105d5592801ec2729fd51c3c7b0beb791bc2 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -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.
index a354bb5d7644c0219af5753af9a5398a5bf4baea..f41fd7f6add34410cb6ac188170e5d29db54d9e8 100644 (file)
 #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:
index d7b043257a36514bb4926ef9e329dc3c36a484f9..38efa9c5311b613ea13db67affc0af81d92a9845 100644 (file)
@@ -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
This page took 0.041111 seconds and 5 git commands to generate.