summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/metadata/metadata.c60
-rw-r--r--tools/vgmerge.c4
-rw-r--r--tools/vgsplit.c1
3 files changed, 65 insertions, 0 deletions
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index a942332a..5f75a66d 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2153,6 +2153,61 @@ void lv_calculate_readahead(const struct logical_volume *lv, uint32_t *read_ahea
}
}
+/*
+ * Check that an LV and all its PV references are correctly listed in vg->lvs
+ * and vg->pvs, respectively. This only looks at a single LV, but *not* at the
+ * LVs it is using. To do the latter, you should use _lv_postorder with this
+ * function. C.f. vg_validate.
+ */
+static int _lv_validate_references_single(struct logical_volume *lv, void *data)
+{
+ struct volume_group *vg = lv->vg;
+ struct lv_segment *lvseg;
+ struct pv_list *pvl;
+ struct lv_list *lvl;
+ int s;
+ int r = 1;
+ int ok = 0;
+
+ dm_list_iterate_items(lvl, &vg->lvs) {
+ if (lvl->lv == lv) {
+ ok = 1;
+ break;
+ }
+ }
+
+ if (!ok) {
+ log_error(INTERNAL_ERROR
+ "Referenced LV %s not listed in VG %s.",
+ lv->name, vg->name);
+ r = 0;
+ }
+
+ dm_list_iterate_items(lvseg, &lv->segments) {
+ for (s = 0; s < lvseg->area_count; ++s) {
+ if (seg_type(lvseg, s) == AREA_PV) {
+ ok = 0;
+ /* look up the reference in vg->pvs */
+ dm_list_iterate_items(pvl, &vg->pvs) {
+ if (pvl->pv == seg_pv(lvseg, s)) {
+ ok = 1;
+ break;
+ }
+ }
+
+ if (!ok) {
+ log_error(INTERNAL_ERROR
+ "Referenced PV %s not listed in VG %s.",
+ pv_dev_name(seg_pv(lvseg, s)), vg->name);
+ r = 0;
+ }
+ }
+ }
+ }
+
+ return r;
+}
+
int vg_validate(struct volume_group *vg)
{
struct pv_list *pvl, *pvl2;
@@ -2320,6 +2375,11 @@ int vg_validate(struct volume_group *vg)
}
dm_list_iterate_items(lvl, &vg->lvs) {
+ if (!_lv_postorder(lvl->lv, _lv_validate_references_single, NULL))
+ r = 0;
+ }
+
+ dm_list_iterate_items(lvl, &vg->lvs) {
if (!(lvl->lv->status & PVMOVE))
continue;
dm_list_iterate_items(seg, &lvl->lv->segments) {
diff --git a/tools/vgmerge.c b/tools/vgmerge.c
index 4d55510e..391764f9 100644
--- a/tools/vgmerge.c
+++ b/tools/vgmerge.c
@@ -114,6 +114,10 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
}
}
+ dm_list_iterate_items(lvl1, &vg_from->lvs) {
+ lvl1->lv->vg = vg_to;
+ }
+
while (!dm_list_empty(&vg_from->lvs)) {
struct dm_list *lvh = vg_from->lvs.n;
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
index 045c699f..bd2f0ab3 100644
--- a/tools/vgsplit.c
+++ b/tools/vgsplit.c
@@ -34,6 +34,7 @@ static int _move_one_lv(struct volume_group *vg_from,
struct logical_volume *lv = dm_list_item(lvh, struct lv_list)->lv;
dm_list_move(&vg_to->lvs, lvh);
+ lv->vg = vg_to;
if (lv_is_active(lv)) {
log_error("Logical volume \"%s\" must be inactive", lv->name);