[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[lvm-devel] [PATCH] Check LV/PV reference consistency in vg_validate



Hi,

the attached patch adds further consistency checking to vg_validate
(this time, it ensures that all segment areas point to LVs or PVs that
are listed in the respective VG).

It also fixes pointer bugs in vgsplit and vgmerge that were detected by
these new checks.

Yours,
   Petr

diff -rN -up old-vgreduce-removemissing/lib/metadata/metadata.c new-vgreduce-removemissing/lib/metadata/metadata.c
--- old-vgreduce-removemissing/lib/metadata/metadata.c	2010-12-14 18:31:58.000000000 +0100
+++ new-vgreduce-removemissing/lib/metadata/metadata.c	2010-12-14 18:31:58.000000000 +0100
@@ -2153,6 +2153,51 @@ void lv_calculate_readahead(const struct
 	}
 }
 
+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;
+	}
+
+	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;
+				}
+
+				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 +2365,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 -rN -up old-vgreduce-removemissing/tools/vgmerge.c new-vgreduce-removemissing/tools/vgmerge.c
--- old-vgreduce-removemissing/tools/vgmerge.c	2010-12-14 18:31:58.000000000 +0100
+++ new-vgreduce-removemissing/tools/vgmerge.c	2010-12-14 18:31:58.000000000 +0100
@@ -114,6 +114,10 @@ static int _vgmerge_single(struct cmd_co
 		}
 	}
 
+	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 -rN -up old-vgreduce-removemissing/tools/vgsplit.c new-vgreduce-removemissing/tools/vgsplit.c
--- old-vgreduce-removemissing/tools/vgsplit.c	2010-12-14 18:31:58.000000000 +0100
+++ new-vgreduce-removemissing/tools/vgsplit.c	2010-12-14 18:31:58.000000000 +0100
@@ -34,6 +34,7 @@ static int _move_one_lv(struct volume_gr
 	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);

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]