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

[lvm-devel] [PATCH] Allow incomplete mirror repairs in lvconvert --repair.



Hi,

the attached patch should address RHBZ 560105 and 560111. This changes
lvconvert --repair as follows:

- downconvert (like before)
- try to replace everything (like before)
- if the second step fails, try to reduce number of mirror images (one
  at a time) until only 2 remain
- if this still fails and we used to have a disk log, try 2-way + corelog

This should basically give you an LV that is closest to the original
mirror, in the space constraints of free PV areas.

Please note that this patch also changes the failure/success returns of
(manual) lvconvert --repair. As far as the initial downconversion
succeeds -- i.e. the resulting LV is not partial, we report success.

Failures to replace (part of) the failed devices are now reported as
warnings.

Yours,
   Petr.

diff -rN -u -p old-upstream/test/t-lvconvert-repair-policy.sh new-upstream/test/t-lvconvert-repair-policy.sh
--- old-upstream/test/t-lvconvert-repair-policy.sh	2010-02-15 22:57:56.000000000 +0100
+++ new-upstream/test/t-lvconvert-repair-policy.sh	2010-02-15 22:57:57.000000000 +0100
@@ -47,9 +47,9 @@ lvs | grep mirror_mlog
 cleanup $dev1
 
 disable_dev $dev2 $dev4
-# no room for repair, downconversion should happen
+# no room for repair, corelog conversion should happen
 repair 'activation { mirror_image_fault_policy = "replace" }'
-lvs | grep -- -wi-a-
+lvs | grep -- mwi-a-
 cleanup $dev2 $dev4
 
 disable_dev $dev2 $dev4
diff -rN -u -p old-upstream/test/t-lvconvert-repair.sh new-upstream/test/t-lvconvert-repair.sh
--- old-upstream/test/t-lvconvert-repair.sh	2010-02-15 22:57:56.000000000 +0100
+++ new-upstream/test/t-lvconvert-repair.sh	2010-02-15 22:57:57.000000000 +0100
@@ -69,5 +69,5 @@ 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 -y -i 1 --repair $vg/mirror2
+echo 'y' | lvconvert -y -i 1 --repair $vg/mirror2
 vgs
diff -rN -u -p old-upstream/tools/lvconvert.c new-upstream/tools/lvconvert.c
--- old-upstream/tools/lvconvert.c	2010-02-15 22:57:56.000000000 +0100
+++ new-upstream/tools/lvconvert.c	2010-02-15 22:57:57.000000000 +0100
@@ -718,12 +718,11 @@ static int _lvconvert_mirrors(struct cmd
 	unsigned log_count = 1;
 	int r = 0;
 	struct logical_volume *log_lv, *layer_lv;
-	int failed_mirrors = 0, failed_log = 0;
+	int failed_mirrors = 0, failed_log = 0, original_log = 0;
 	struct dm_list *old_pvh = NULL, *remove_pvs = NULL, *failed_pvs = NULL;
 
-	int repair = arg_count(cmd, repair_ARG);
+	int repair = arg_is_set(cmd, repair_ARG);
 	int replace_log = 1, replace_mirrors = 1;
-	int failure_code = 0;
 
 	seg = first_seg(lv);
 	existing_mirrors = lv_mirror_count(lv);
@@ -799,6 +798,7 @@ static int _lvconvert_mirrors(struct cmd
 			failed_log = 1;
 			log_count = 0;
 		}
+		original_log = log_count;
 	} else {
 		/*
 		 * Did the user try to subtract more legs than available?
@@ -884,15 +884,15 @@ static int _lvconvert_mirrors(struct cmd
 			if (!lv_split_mirror_images(lv, lp->lv_split_name,
 						    existing_mirrors - lp->mirrors,
 						    remove_pvs))
-				return 0;
+				goto out;
 		} else if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors,
 					      (!log_count || lp->mirrors == 1) ? 1U : 0U,
 					      remove_pvs, 0))
-			return_0;
+			goto_out;
 
 		if (lp->mirrors > 1 &&
 		    !_lv_update_log_type(cmd, lp, lv, log_count))
-			return_0;
+			goto_out;
 	} else if (!(lv->status & MIRRORED)) {
 		/*
 		 * Converting from linear to mirror
@@ -920,8 +920,7 @@ static int _lvconvert_mirrors(struct cmd
 						lp->region_size),
 				    log_count, lp->pvh, lp->alloc,
 				    MIRROR_BY_LV)) {
-			stack;
-			return failure_code;
+			goto_out;
 		}
 		if (lp->wait_completion)
 			lp->need_polling = 1;
@@ -942,7 +941,7 @@ static int _lvconvert_mirrors(struct cmd
 		if (lv_is_origin(lv)) {
 			log_error("Can't add additional mirror images to "
 				  "mirrors that are under snapshots");
-			return failure_code;
+			goto_out;
 		}
 
 		/*
@@ -950,10 +949,8 @@ static int _lvconvert_mirrors(struct cmd
 		 * insertion to make the end result consistent with
 		 * linear-to-mirror conversion.
 		 */
-		if (!_lv_update_log_type(cmd, lp, lv, log_count)) {
-			stack;
-			return failure_code;
-		}
+		if (!_lv_update_log_type(cmd, lp, lv, log_count))
+			goto_out;
 		/* Insert a temporary layer for syncing,
 		 * only if the original lv is using disk log. */
 		if (seg->log_lv && !_insert_lvconvert_layer(cmd, lv)) {
@@ -980,8 +977,7 @@ static int _lvconvert_mirrors(struct cmd
 					  "and dmsetup may be required.");
 				return 0;
 			}
-			stack;
-			return failure_code;
+			goto_out;
 		}
 		if (seg->log_lv)
 			lv->status |= CONVERTING;
@@ -990,10 +986,8 @@ static int _lvconvert_mirrors(struct cmd
 
 	if (lp->mirrors == existing_mirrors) {
 		if (_using_corelog(lv) != !log_count) {
-			if (!_lv_update_log_type(cmd, lp, lv, log_count)) {
-				stack;
-				return failure_code;
-			}
+			if (!_lv_update_log_type(cmd, lp, lv, log_count))
+				goto_out;
 		} else {
 			log_error("Logical volume %s already has %"
 				  PRIu32 " mirror(s).", lv->name,
@@ -1038,23 +1032,38 @@ static int _lvconvert_mirrors(struct cmd
 			lp->mirrors += failed_mirrors;
 		failed_mirrors = 0;
 		existing_mirrors = lv_mirror_count(lv);
-		/*
-		 * Ignore failure in upconversion if this is a policy-driven
-		 * action. If we got this far, only unexpected failures are
-		 * reported.
-		 */
-		if (arg_count(cmd, use_policies_ARG))
-			failure_code = 1;
+		repair = 2;
 		/* Now replace missing devices. */
 		if (replace_log || replace_mirrors)
 			goto restart;
 	}
 
+	repair = 1; /* all done */
+
 	if (!lp->need_polling)
 		log_print("Logical volume %s converted.", lv->name);
 
 	r = 1;
 out:
+	if (repair > 1 && r == 0) {
+		if (lp->mirrors > 2) {
+			lp->mirrors--;
+			goto restart;
+		} else if (log_count) {
+			log_count = 0;
+			goto restart;
+		} else
+			r = 1; /* downconvert went OK, consider this a success */
+	}
+
+	if (repair == 1 && r == 1) {
+		if (lp->mirrors != existing_mirrors)
+			log_warn("WARNING: Failed to replace %d of %d images in volume %s",
+				 existing_mirrors - lp->mirrors, existing_mirrors, lv->name);
+		if (log_count != original_log)
+			log_warn("WARNING: Failed to replace mirror log in volume %s", lv->name);
+	}
+
 	backup(lv->vg);
 	return r;
 }

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