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

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



Milan Broz <mbroz redhat com> writes:
> please try this test - it tries to allocate new log - not sure if it is what we want,
> but lvconvert fails but log lv is later visible, vg is still inconsistent
> and I am confused what the correct state should be:-)
The problem was that the code neglected to write out the consistent volume
before trying to add new bits (which could obviously fail). The attached
version of the patch fixes that (it also contains your test now).

Mon Mar 30 17:10:12 CEST 2009  Petr Rockai <me mornfall net>
  * Write out a consistent LV before trying to replace missing bits.
Mon Mar 30 17:09:55 CEST 2009  Petr Rockai <me mornfall net>
  * Comment formatting.
Mon Mar 30 17:09:32 CEST 2009  Petr Rockai <me mornfall net>
  * Add a test for graceful failure of lvconvert --repair.
Wed Feb 11 18:22:59 CET 2009  Petr Rockai <me mornfall net>
  * Trap errors and bail out.
Wed Feb 11 18:22:49 CET 2009  Petr Rockai <me mornfall net>
  * Consistency++.
Wed Feb 11 18:22:18 CET 2009  Petr Rockai <me mornfall net>
  * Clean up unhelpful log message.
Fri Jan 30 02:19:43 CET 2009  Petr Rockai <me mornfall net>
  * Do not accidentally remove the *working* leg in lvconvert --repair.
Fri Jan 30 02:07:46 CET 2009  Petr Rockai <me mornfall net>
  * Add a test for lvconvert --repair functionality.
Fri Jan 30 02:06:55 CET 2009  Petr Rockai <me mornfall net>
  * Improve log message (lvconvert --repair).
Fri Jan 30 02:06:17 CET 2009  Petr Rockai <me mornfall net>
  * For lvconvert --repair, we need partial_activation in the intermediate activates.
Fri Jan 30 02:02:30 CET 2009  Petr Rockai <me mornfall net>
  * Do not include missing PVs in allocation maps.
Fri Jan 30 02:09:54 CET 2009  Petr Rockai <me mornfall net>
  * Implementation of lvconvert --repair.
Fri Jan 30 02:23:53 CET 2009  Petr Rockai <me mornfall net>
  * In testing lvm.conf, exclude all but pvN mapper devices from scanning.
Fri Jan 30 02:20:26 CET 2009  Petr Rockai <me mornfall net>
  * Make vgreduce --removemissing return failure when it can't make the VG consistent.
Fri Jan 30 02:03:49 CET 2009  Petr Rockai <me mornfall net>
  * test-lib.sh: Turn make_ioerror into an actual useful use_ioerror function.
diff -rN -u -p old-lvconvert-repair/lib/metadata/metadata.c new-lvconvert-repair/lib/metadata/metadata.c
--- old-lvconvert-repair/lib/metadata/metadata.c	2009-03-30 17:12:38.117339740 +0200
+++ new-lvconvert-repair/lib/metadata/metadata.c	2009-03-30 17:12:38.169339436 +0200
@@ -1243,7 +1243,8 @@ static int _lv_each_dependency(struct lo
 			       int (*fn)(struct logical_volume *lv, void *data),
 			       void *data)
 {
-	int i, s;
+	size_t i;
+	uint32_t s;
 	struct lv_segment *lvseg;
 
 	struct logical_volume *deps[] = {
diff -rN -u -p old-lvconvert-repair/lib/metadata/mirror.c new-lvconvert-repair/lib/metadata/mirror.c
--- old-lvconvert-repair/lib/metadata/mirror.c	2009-03-30 17:12:38.117339740 +0200
+++ new-lvconvert-repair/lib/metadata/mirror.c	2009-03-30 17:12:38.169339436 +0200
@@ -441,7 +441,12 @@ static int _is_mirror_image_removable(st
 
 			pv_found = 0;
 			dm_list_iterate_items(pvl, removable_pvs) {
-				if (pv->dev->dev == pvl->pv->dev->dev) {
+				if (id_equal(&pv->id, &pvl->pv->id)) {
+					pv_found = 1;
+					break;
+				}
+				if (pvl->pv->dev && pv->dev &&
+				    pv->dev->dev == pvl->pv->dev->dev) {
 					pv_found = 1;
 					break;
 				}
diff -rN -u -p old-lvconvert-repair/lib/metadata/pv_map.c new-lvconvert-repair/lib/metadata/pv_map.c
--- old-lvconvert-repair/lib/metadata/pv_map.c	2009-03-30 17:12:38.113338883 +0200
+++ new-lvconvert-repair/lib/metadata/pv_map.c	2009-03-30 17:12:38.169339436 +0200
@@ -129,6 +129,9 @@ 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)
+			continue;
+		assert(pvl->pv->dev);
 
 		pvm = NULL;
 
diff -rN -u -p old-lvconvert-repair/test/test-utils.sh new-lvconvert-repair/test/test-utils.sh
--- old-lvconvert-repair/test/test-utils.sh	2009-03-30 17:12:38.117339740 +0200
+++ new-lvconvert-repair/test/test-utils.sh	2009-03-30 17:12:38.209337955 +0200
@@ -50,10 +50,15 @@ teardown_() {
 	testlib_cleanup_ # call test-lib cleanup routine, too
 }
 
-make_ioerror() {
-	echo 0 10000000 error | dmsetup create ioerror
-	dmsetup resume ioerror
-	ln -s $G_dev_/mapper/ioerror $G_dev_/ioerror
+use_ioerror() {
+	cat >> $G_root_/etc/lvm.conf <<-EOF
+	activation {
+		missing_stripe_filler="$G_dev_/ioerror"
+	}
+EOF
+	echo 0 10000000 error | dmsetup create ${PREFIX}ioerror
+	dmsetup resume ${PREFIX}ioerror
+	ln -s $G_dev_/mapper/${PREFIX}ioerror $G_dev_/ioerror
 }
 
 prepare_loop() {
@@ -179,7 +184,7 @@ prepare_lvmconf() {
   devices {
     dir = "$G_dev_"
     scan = "$G_dev_"
-    filter = [ "a/dev\/mirror/", "a/dev\/mapper/", "r/.*/" ]
+    filter = [ "a/dev\/mirror/", "a/dev\/mapper\/.*pv[0-9_]*$/", "r/.*/" ]
     cache_dir = "$G_root_/etc"
     sysfs_scan = 0
   }
diff -rN -u -p old-lvconvert-repair/test/t-lvconvert-repair.sh new-lvconvert-repair/test/t-lvconvert-repair.sh
--- old-lvconvert-repair/test/t-lvconvert-repair.sh	1970-01-01 01:00:00.000000000 +0100
+++ new-lvconvert-repair/test/t-lvconvert-repair.sh	2009-03-30 17:12:38.205338983 +0200
@@ -0,0 +1,46 @@
+#!/bin/bash
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+prepare_vg 4
+
+vgreduce $vg $dev4
+lvcreate -m 1 -L 1 -n mirror $vg
+
+lvchange -a n $vg/mirror
+vgextend $vg $dev4
+disable_dev $dev1
+lvchange --partial -a y $vg/mirror
+
+not vgreduce -v --removemissing $vg
+lvconvert --repair $vg/mirror
+vgreduce --removemissing $vg
+
+enable_dev $dev1
+vgextend $vg $dev1
+disable_dev $dev2
+lvconvert --repair $vg/mirror
+vgreduce --removemissing $vg
+
+enable_dev $dev2
+vgextend $vg $dev2
+disable_dev $dev3
+lvconvert --repair $vg/mirror
+vgreduce --removemissing $vg
+
+enable_dev $dev3
+vgextend $vg $dev3
+lvcreate -m 2 -l 1 -n mirror2 $vg $dev1 $dev2 $dev3 $dev4
+vgchange -a n $vg
+pvremove -ff -y $dev4
+echo 'y' | not lvconvert --repair $vg/mirror2
+vgs
diff -rN -u -p old-lvconvert-repair/test/t-mdata-strings.sh new-lvconvert-repair/test/t-mdata-strings.sh
--- old-lvconvert-repair/test/t-mdata-strings.sh	2009-03-30 17:12:38.117339740 +0200
+++ new-lvconvert-repair/test/t-mdata-strings.sh	2009-03-30 17:12:38.205338983 +0200
@@ -15,12 +15,12 @@
 
 aux prepare_devs 1
 
-pv_suffix="__\"! #\$%^&*()'\\\"__"
+pv_ugly="__\"! #\$%^&*()'\\\"__pv1"
 
 # 'set up temp files, loopback devices' 
 name=$(basename "$dev1")
-dmsetup rename "$name" "$name$pv_suffix" 
-dev1=$(dirname "$dev1")/$name$pv_suffix
+dmsetup rename "$name" "$PREFIX$pv_ugly" 
+dev1=$(dirname "$dev1")/$PREFIX$pv_ugly
 
 # 'pvcreate, vgcreate on filename with backslashed chars' 
 pvcreate "$dev1" 
diff -rN -u -p old-lvconvert-repair/test/t-partial-activate.sh new-lvconvert-repair/test/t-partial-activate.sh
--- old-lvconvert-repair/test/t-partial-activate.sh	2009-03-30 17:12:38.117339740 +0200
+++ new-lvconvert-repair/test/t-partial-activate.sh	2009-03-30 17:12:38.205338983 +0200
@@ -6,7 +6,6 @@ lvcreate -m 1 -l 1 -n mirror $vg
 lvchange -a n $vg/mirror
 disable_dev $dev1
 
-# FIXME should this return an error code due to that big fat WARNING?
-vgreduce --removemissing $vg
+not vgreduce --removemissing $vg
 not lvchange -v -a y $vg/mirror
 lvchange -v --partial -a y $vg/mirror
diff -rN -u -p old-lvconvert-repair/tools/args.h new-lvconvert-repair/tools/args.h
--- old-lvconvert-repair/tools/args.h	2009-03-30 17:12:38.117339740 +0200
+++ new-lvconvert-repair/tools/args.h	2009-03-30 17:12:38.209337955 +0200
@@ -49,6 +49,7 @@ arg(nosync_ARG, '\0', "nosync", NULL, 0)
 arg(resync_ARG, '\0', "resync", NULL, 0)
 arg(corelog_ARG, '\0', "corelog", NULL, 0)
 arg(mirrorlog_ARG, '\0', "mirrorlog", string_arg, 0)
+arg(repair_ARG, '\0', "repair", NULL, 0)
 arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0)
 arg(config_ARG, '\0', "config", string_arg, 0)
 arg(trustcache_ARG, '\0', "trustcache", NULL, 0)
diff -rN -u -p old-lvconvert-repair/tools/commands.h new-lvconvert-repair/tools/commands.h
--- old-lvconvert-repair/tools/commands.h	2009-03-30 17:12:38.117339740 +0200
+++ new-lvconvert-repair/tools/commands.h	2009-03-30 17:12:38.209337955 +0200
@@ -94,6 +94,7 @@ xx(lvconvert,
    0,
    "lvconvert "
    "[-m|--mirrors Mirrors [{--mirrorlog {disk|core}|--corelog}]]\n"
+   "\t[--repair]\n"
    "\t[-R|--regionsize MirrorLogRegionSize]\n"
    "\t[--alloc AllocationPolicy]\n"
    "\t[-b|--background]\n"
@@ -115,7 +116,8 @@ xx(lvconvert,
    "\tOriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]\n",
 
    alloc_ARG, background_ARG, chunksize_ARG, corelog_ARG, interval_ARG,
-   mirrorlog_ARG, mirrors_ARG, regionsize_ARG, snapshot_ARG, test_ARG, zero_ARG)
+   mirrorlog_ARG, mirrors_ARG, regionsize_ARG, repair_ARG, snapshot_ARG,
+   test_ARG, zero_ARG)
 
 xx(lvcreate,
    "Create a logical volume",
diff -rN -u -p old-lvconvert-repair/tools/lvconvert.c new-lvconvert-repair/tools/lvconvert.c
--- old-lvconvert-repair/tools/lvconvert.c	2009-03-30 17:12:38.117339740 +0200
+++ new-lvconvert-repair/tools/lvconvert.c	2009-03-30 17:12:38.213340698 +0200
@@ -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;
+		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_error("Unable to allocate physical volume list.");
+			return_0;
+		}
+		new_pvl->pv = pvl->pv;
+		dm_list_add(r, &new_pvl->list);
+	}
+	return r;
+}
+
 /* walk down the stacked mirror LV to the original mirror LV */
 static struct logical_volume *_original_lv(struct logical_volume *lv)
 {
@@ -383,17 +438,26 @@ static int lvconvert_mirrors(struct cmd_
 	const char *mirrorlog;
 	unsigned corelog = 0;
 	struct logical_volume *original_lv;
+	struct logical_volume *log_lv;
+	int failed_mirrors = 0, failed_log = 0;
+	struct dm_list *old_pvh, *remove_pvs = NULL;
 
 	seg = first_seg(lv);
 	existing_mirrors = lv_mirror_count(lv);
 
 	/* If called with no argument, try collapsing the resync layers */
 	if (!arg_count(cmd, mirrors_ARG) && !arg_count(cmd, mirrorlog_ARG) &&
-	    !arg_count(cmd, corelog_ARG) && !arg_count(cmd, regionsize_ARG)) {
+	    !arg_count(cmd, corelog_ARG) && !arg_count(cmd, regionsize_ARG) &&
+	    !arg_count(cmd, repair_ARG)) {
 		lp->need_polling = 1;
 		return 1;
 	}
 
+	if (arg_count(cmd, mirrors_ARG) && arg_count(cmd, repair_ARG)) {
+		log_error("You can only use one of -m, --repair.");
+		return 0;
+	}
+
 	/*
 	 * Adjust required number of mirrors
 	 *
@@ -411,38 +475,59 @@ static int lvconvert_mirrors(struct cmd_
 	else
 		lp->mirrors += 1;
 
-	/*
-	 * Did the user try to subtract more legs than available?
-	 */
-	if (lp->mirrors < 1) {
-		log_error("Logical volume %s only has %" PRIu32 " mirrors.",
-			  lv->name, existing_mirrors);
-		return 0;
-	}
-
-	/*
-	 * Adjust log type
-	 */
-	if (arg_count(cmd, corelog_ARG))
-		corelog = 1;
-
-	mirrorlog = arg_str_value(cmd, mirrorlog_ARG,
-				  corelog ? "core" : DEFAULT_MIRRORLOG);
-	if (!strcmp("disk", mirrorlog)) {
-		if (corelog) {
-			log_error("--mirrorlog disk and --corelog "
-				  "are incompatible");
+	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;
+		}
+		if ((failed_mirrors = _count_failed_mirrors(lv)) < 0)
+			return_0;
+		lp->mirrors -= failed_mirrors;
+		log_error("Mirror status: %d/%d legs failed.",
+			  failed_mirrors, existing_mirrors);
+		old_pvh = lp->pvh;
+		if (!(lp->pvh = _failed_pv_list(cmd, lv->vg)))
+			return_0;
+		log_lv=first_seg(lv)->log_lv;
+		if (!log_lv || log_lv->status & PARTIAL_LV)
+			failed_log = corelog = 1;
+	} else {
+		/*
+		 * Did the user try to subtract more legs than available?
+		 */
+		if (lp->mirrors < 1) {
+			log_error("Logical volume %s only has %" PRIu32 " mirrors.",
+				  lv->name, existing_mirrors);
+			return 0;
+		}
+		
+		/*
+		 * Adjust log type
+		 */
+		if (arg_count(cmd, corelog_ARG))
+			corelog = 1;
+		
+		mirrorlog = arg_str_value(cmd, mirrorlog_ARG,
+					  corelog ? "core" : DEFAULT_MIRRORLOG);
+		if (!strcmp("disk", mirrorlog)) {
+			if (corelog) {
+				log_error("--mirrorlog disk and --corelog "
+					  "are incompatible");
+				return 0;
+			}
+			corelog = 0;
+		} else if (!strcmp("core", mirrorlog))
+			corelog = 1;
+		else {
+			log_error("Unknown mirrorlog type: %s", mirrorlog);
 			return 0;
 		}
-		corelog = 0;
-	} else if (!strcmp("core", mirrorlog))
-		corelog = 1;
-	else {
-		log_error("Unknown mirrorlog type: %s", mirrorlog);
-		return 0;
-	}
 
-	log_verbose("Setting logging type to %s", mirrorlog);
+		log_verbose("Setting logging type to %s", mirrorlog);
+	}
 
 	/*
 	 * Region size must not change on existing mirrors
@@ -455,6 +540,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;
+	}
+	
+ restart:
+	/*
 	 * Converting from mirror to linear
 	 */
 	if ((lp->mirrors == 1)) {
@@ -463,17 +560,24 @@ static int lvconvert_mirrors(struct cmd_
 				  lv->name);
 			return 1;
 		}
-
-		if (!lv_remove_mirrors(cmd, lv, existing_mirrors - 1, 1,
-				       lp->pv_count ? lp->pvh : NULL, 0))
-			return_0;
-		goto commit_changes;
 	}
 
 	/*
-	 * Converting from linear to mirror
+	 * Downconversion.
 	 */
-	if (!(lv->status & MIRRORED)) {
+	if (lp->mirrors < existing_mirrors) {
+		/* Reduce number of mirrors */
+		if (arg_count(cmd, repair_ARG) || lp->pv_count)
+			remove_pvs = lp->pvh;
+		if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors,
+				       (corelog || lp->mirrors == 1) ? 1U : 0U,
+				       remove_pvs, 0))
+			return_0;
+	} else if (!(lv->status & MIRRORED)) {
+		/*
+		 * Converting from linear to mirror
+		 */
+	
 		/* FIXME Share code with lvcreate */
 
 		/* FIXME Why is this restriction here?  Fix it! */
@@ -484,6 +588,11 @@ static int lvconvert_mirrors(struct cmd_
 			}
 		}
 
+		/*
+		 * FIXME should we give not only lp->pvh, but also all PVs
+		 * currently taken by the mirror? Would make more sense from
+		 * user perspective.
+		 */
 		if (!lv_add_mirrors(cmd, lv, lp->mirrors - 1, 1,
 				    adjusted_mirror_region_size(
 						lv->vg->extent_size,
@@ -494,46 +603,7 @@ static int lvconvert_mirrors(struct cmd_
 			return_0;
 		if (lp->wait_completion)
 			lp->need_polling = 1;
-		goto commit_changes;
-	}
-
-	/*
-	 * Converting from mirror to mirror with different leg count,
-	 * or different log type.
-	 */
-	if (dm_list_size(&lv->segments) != 1) {
-		log_error("Logical volume %s has multiple "
-			  "mirror segments.", lv->name);
-		return 0;
-	}
-
-	if (lp->mirrors == existing_mirrors) {
-		/*
-		 * Convert Mirror log type
-		 */
-		original_lv = _original_lv(lv);
-		if (!first_seg(original_lv)->log_lv && !corelog) {
-			if (!add_mirror_log(cmd, original_lv, 1,
-					    adjusted_mirror_region_size(
-							lv->vg->extent_size,
-							lv->le_count,
-							lp->region_size),
-					    lp->pvh, lp->alloc))
-				return_0;
-		} else if (first_seg(original_lv)->log_lv && corelog) {
-			if (!remove_mirror_log(cmd, original_lv,
-					       lp->pv_count ? lp->pvh : NULL))
-				return_0;
-		} else {
-			/* No change */
-			log_error("Logical volume %s already has %"
-				  PRIu32 " mirror(s).", lv->name,
-				  lp->mirrors - 1);
-			if (lv->status & CONVERTING)
-				lp->need_polling = 1;
-			return 1;
-		}
-	} else if (lp->mirrors > existing_mirrors) {
+	} else if (lp->mirrors > existing_mirrors || failed_mirrors) {
 		if (lv->status & MIRROR_NOTSYNCED) {
 			log_error("Not adding mirror to mirrored LV "
 				  "without initial resync");
@@ -575,15 +645,36 @@ static int lvconvert_mirrors(struct cmd_
 			return_0;
 		lv->status |= CONVERTING;
 		lp->need_polling = 1;
-	} else {
-		/* Reduce number of mirrors */
-		if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors,
-				       corelog ? 1U : 0U,
-				       lp->pv_count ? lp->pvh : NULL, 0))
-			return_0;
 	}
 
-commit_changes:
+	if (lp->mirrors == existing_mirrors) {
+		/*
+		 * Convert Mirror log type
+		 */
+		original_lv = _original_lv(lv);
+		if (!first_seg(original_lv)->log_lv && !corelog) {
+			if (!add_mirror_log(cmd, original_lv, 1,
+					    adjusted_mirror_region_size(
+							lv->vg->extent_size,
+							lv->le_count,
+							lp->region_size),
+					    lp->pvh, lp->alloc))
+				return_0;
+		} else if (first_seg(original_lv)->log_lv && corelog) {
+			if (!remove_mirror_log(cmd, original_lv,
+					       lp->pv_count ? lp->pvh : NULL))
+				return_0;
+		} else {
+			/* No change */
+			log_error("Logical volume %s already has %"
+				  PRIu32 " mirror(s).", lv->name,
+				  lp->mirrors - 1);
+			if (lv->status & CONVERTING)
+				lp->need_polling = 1;
+			return 1;
+		}
+	}
+
 	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
 
 	if (!vg_write(lv->vg))
@@ -609,6 +700,17 @@ commit_changes:
 		return 0;
 	}
 
+	if (failed_log || failed_mirrors) {
+		lp->pvh = old_pvh;
+		if (failed_log)
+			failed_log = corelog = 0;
+		lp->mirrors += failed_mirrors;
+		failed_mirrors = 0;
+		existing_mirrors = lv_mirror_count(lv);
+		/* Now replace missing devices. */
+		goto restart;
+	}
+
 	if (!lp->need_polling)
 		log_print("Logical volume %s converted.", lv->name);
 
diff -rN -u -p old-lvconvert-repair/tools/toollib.c new-lvconvert-repair/tools/toollib.c
--- old-lvconvert-repair/tools/toollib.c	2009-03-30 17:12:38.113338883 +0200
+++ new-lvconvert-repair/tools/toollib.c	2009-03-30 17:12:38.217340299 +0200
@@ -998,6 +998,11 @@ static int _create_pv_entry(struct dm_po
 		return 1;
 	}
 
+	if (allocatable_only && (pvl->pv->status & MISSING_PV)) {
+		log_error("Physical volume %s is missing", pvname);
+		return 1;
+	}
+
 	if (allocatable_only &&
 	    (pvl->pv->pe_count == pvl->pv->pe_alloc_count)) {
 		log_err("No free extents on physical volume \"%s\"", pvname);
diff -rN -u -p old-lvconvert-repair/tools/vgreduce.c new-lvconvert-repair/tools/vgreduce.c
--- old-lvconvert-repair/tools/vgreduce.c	2009-03-30 17:12:38.117339740 +0200
+++ new-lvconvert-repair/tools/vgreduce.c	2009-03-30 17:12:38.217340299 +0200
@@ -467,7 +467,7 @@ int vgreduce(struct cmd_context *cmd, in
 {
 	struct volume_group *vg;
 	char *vg_name;
-	int ret = 1;
+	int ret = ECMD_PROCESSED;
 	int consistent = 1;
 	int fixed = 1;
 	int repairing = arg_count(cmd, removemissing_ARG);
@@ -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)) {
Yours,
   Petr.

-- 
Peter Rockai | me()mornfall!net | prockai()redhat!com
 http://blog.mornfall.net | http://web.mornfall.net

"In My Egotistical Opinion, most people's C programs should be
 indented six feet downward and covered with dirt."
     -- Blair P. Houghton on the subject of C program indentation

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