[lvm-devel] [PATCH] lvconvert --repair

Milan Broz mbroz at redhat.com
Thu Feb 5 18:06:12 UTC 2009


Petr Rockai wrote:
> The first patch is just a few minor bits in the testing infrastructure, not
> overly important (but it is needed for the new t-lvconvent-repair.sh testcase
> to pass, due to vgreduce --removemissing return code).

This is the only important chunk in this patch, simple bugfix

--- old-lvconvert-reorder-2/tools/vgreduce.c	2009-01-30 11:03:12.589282389 +0100
+++ new-lvconvert-reorder-2/tools/vgreduce.c	2009-01-30 11:03:12.685281881 +0100
@@ -575,6 +575,8 @@ int vgreduce(struct cmd_context *cmd, in
 		if (fixed)
 			log_print("Wrote out consistent volume group %s",
 				  vg_name);
+		else
+			ret = ECMD_FAILED;
 
 	} else {
 		if (!vg_check_status(vg, EXPORTED_VG | LVM_WRITE | RESIZEABLE_VG)) {

ACK, but as a separate fix/commit

Also there should be
-	int ret = 1;
+	int ret = ECMD_PROCESSED;

to be consistent enough...

Acked-by: Milan Broz <mbroz at redhat.com>


-------
> The second patch does the actual implementation. It should be up to date with
> CVS as of today. It should be relatively straightforward, although it did
> require adding MISSING_PV checks to some places that were missing them (it's
> been harmless till now, since no allocation was ever done on VGs with PVs
> missing, but it's crucial for lvconvert --repair).


- missing man page update

--- old-lvconvert-reorder-2/lib/metadata/pv_map.c	2009-01-30 11:03:20.569284247 +0100
+++ new-lvconvert-reorder-2/lib/metadata/pv_map.c	2009-01-30 11:03:20.625285639 +0100
@@ -129,6 +129,11 @@ static int _create_maps(struct dm_pool *
 	dm_list_iterate_items(pvl, pvs) {
 		if (!(pvl->pv->status & ALLOCATABLE_PV))
 			continue;
+		if (pvl->pv->status & MISSING_PV) {
+			log_very_verbose("skipping missing pv ...");

Do we have name of PV (hint in metadata?) or something to print here?


diff -rN -u -p old-lvconvert-reorder-2/tools/lvconvert.c new-lvconvert-reorder-2/tools/lvconvert.c
--- old-lvconvert-reorder-2/tools/lvconvert.c	2009-01-30 11:03:20.573279378 +0100
+++ new-lvconvert-reorder-2/tools/lvconvert.c	2009-01-30 11:03:20.661284767 +0100
@@ -364,6 +364,61 @@ static int _insert_lvconvert_layer(struc
 	return 1;
 }
 
+static int _area_missing(struct lv_segment *lvseg, int s)
+{
+	if (seg_type(lvseg, s) == AREA_LV) {
+		if (seg_lv(lvseg, s)->status & PARTIAL_LV)
+			return 1;
+	} else if (seg_type(lvseg, s) == AREA_PV) {
+		if (seg_pv(lvseg, s)->status & MISSING_PV)
+			return 1;
+	}
+	return 0;
+}
+
+/* FIXME we want to handle mirror stacks here... */
+static int _count_failed_mirrors(struct logical_volume *lv)
+{
+	struct lv_segment *lvseg;
+	int ret = 0;
+	int s;
+	dm_list_iterate_items(lvseg, &lv->segments) {
+		if (!seg_is_mirrored(lvseg))
+			return -1;

why -1 here and not simply continue or return_0 ?

If this can really happen, it adds mirror lp->mirrors...

		int failed_mirrors = 0;
		...
		failed_mirrors = _count_failed_mirrors(lv);
		lp->mirrors -= failed_mirrors;
		log_error("Mirror status: %d/%d legs failed.",
			  failed_mirrors, existing_mirrors);
...

+		for(s = 0; s < lvseg->area_count; ++s) {
+			if (_area_missing(lvseg, s))
+				++ ret;
+		}
+	}
+	return ret;
+}


+static struct dm_list *_failed_pv_list(struct cmd_context *cmd,
+				       struct volume_group *vg)
+{
+	struct dm_list *r;
+	struct pv_list *pvl, *new_pvl;
+
+	if (!(r = dm_pool_alloc(cmd->mem, sizeof(*r)))) {
+		log_error("Allocation of list failed");
+		return_0;
+	}
+
+	dm_list_init(r);
+	dm_list_iterate_items(pvl, &vg->pvs) {
+		if (!(pvl->pv->status & MISSING_PV))
+			continue;
+
+		if (!(new_pvl = dm_pool_alloc(cmd->mem, sizeof(*new_pvl)))) {
+			log_err("Unable to allocate physical volume list.");
+			return 0;

s/log_err/log_error, return_0 :)

also it should check for 0 othewwise it expects empty list (not NULL) later
I mean this

		- lp->pvh = _failed_pv_list(cmd, lv->vg);

		+ if (!(lp->pvh = ...)
		+	return_0; 


+	if (arg_count(cmd,repair_ARG)) {
+		cmd->handles_missing_pvs = 1;
+		cmd->partial_activation = 1;
+		lp->need_polling = 0;
+		if (!(lv->status & PARTIAL_LV)) {
+			log_error("The mirror is consistent, nothing to repair.");
+			return_0;

why return_0? PEBKAC :)

+		}
+		failed_mirrors = _count_failed_mirrors(lv);
see above

+		lp->mirrors -= failed_mirrors;
+		log_error("Mirror status: %d/%d legs failed.",
+			  failed_mirrors, existing_mirrors);
+		old_pvh = lp->pvh;
+		lp->pvh = _failed_pv_list(cmd, lv->vg);
ditto

+		log_lv=first_seg(lv)->log_lv;

Someone could say that there should be space before and after equal sign :-]


@@ -455,6 +538,18 @@ static int lvconvert_mirrors(struct cmd_
 	}
 
 	/*
+	 * FIXME This check used to precede mirror->mirror conversion
+	 * but didn't affect mirror->linear or linear->mirror. I do
+	 * not understand what is its intention, in fact.
+	 */
+	if (dm_list_size(&lv->segments) != 1) {
+		log_error("Logical volume %s has multiple "
+			  "mirror segments.", lv->name);
+		return 0;
+	}

I think we temporarily restrict mirrors to only one segment mirrors.
Linear can have more segments of course.

There is probably gap in logic, if combined with --alloc anywhere...
(But trying to test that I found another error:-)

----
Why this testcase doesn't work (resp. doesn't finish without
manual intervention and hangs in lvconvert?)
It seems that some devices are left suspended...

prepare_vg 3

lvcreate --alloc anywhere -m1 -L 1 -n mirror $vg

dd if=/dev/zero of=$dev1 bs=1M count=1

#not vgreduce -v --removemissing $vg
lvconvert --repair $vg/mirror
vgreduce --removemissing $vg


Milan
--
mbroz at redhat.com




More information about the lvm-devel mailing list