mrc0mmand / rpms / lvm2

Forked from rpms/lvm2 2 years ago
Clone

Blame SOURCES/lvm2-revert-fix-for-lvconvert-repair-for-raid-lvs.patch

c0e5af
 WHATS_NEW                                     |   1 -
c0e5af
 daemons/dmeventd/plugins/raid/dmeventd_raid.c |  42 +++--------
c0e5af
 lib/metadata/lv.c                             |   7 ++
c0e5af
 lib/metadata/raid_manip.c                     |   2 +-
c0e5af
 test/shell/lvconvert-repair-raid.sh           | 104 ++------------------------
c0e5af
 tools/lvconvert.c                             |  19 +++++
c0e5af
 6 files changed, 41 insertions(+), 134 deletions(-)
c0e5af
c0e5af
diff --git a/WHATS_NEW b/WHATS_NEW
c0e5af
index 25f6742..977e578 100644
c0e5af
--- a/WHATS_NEW
c0e5af
+++ b/WHATS_NEW
c0e5af
@@ -3,7 +3,6 @@ Version 2.02.166 - 26th September 2016
c0e5af
   Fix lvm2-activation-generator to read all LVM2 config sources. (2.02.155)
c0e5af
   Fix lvchange-rebuild-raid.sh to cope with older target versions.
c0e5af
   Use dm_config_parse_without_dup_node_check() to speedup metadata reading.
c0e5af
-  Fix lvconvert --repair regression
c0e5af
   Fix reported origin lv field for cache volumes. (2.02.133)
c0e5af
   Always specify snapshot cow LV for monitoring not internal LV. (2.02.165)
c0e5af
   Fix lvchange --discard|--zero for active thin-pool.
c0e5af
diff --git a/daemons/dmeventd/plugins/raid/dmeventd_raid.c b/daemons/dmeventd/plugins/raid/dmeventd_raid.c
c0e5af
index bec594a..770fbc6 100644
c0e5af
--- a/daemons/dmeventd/plugins/raid/dmeventd_raid.c
c0e5af
+++ b/daemons/dmeventd/plugins/raid/dmeventd_raid.c
c0e5af
@@ -1,5 +1,5 @@
c0e5af
 /*
c0e5af
- * Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved.
c0e5af
+ * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
c0e5af
  *
c0e5af
  * This file is part of LVM2.
c0e5af
  *
c0e5af
@@ -13,20 +13,14 @@
c0e5af
  */
c0e5af
 
c0e5af
 #include "lib.h"
c0e5af
-#include "defaults.h"
c0e5af
 #include "dmeventd_lvm.h"
c0e5af
 #include "libdevmapper-event.h"
c0e5af
 
c0e5af
-/* Hold enough elements for the mximum number of RAID images */
c0e5af
-#define	RAID_DEVS_ELEMS	((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
c0e5af
-
c0e5af
 struct dso_state {
c0e5af
 	struct dm_pool *mem;
c0e5af
 	char cmd_lvscan[512];
c0e5af
 	char cmd_lvconvert[512];
c0e5af
-	uint64_t raid_devs[RAID_DEVS_ELEMS];
c0e5af
 	int failed;
c0e5af
-	int warned;
c0e5af
 };
c0e5af
 
c0e5af
 DM_EVENT_LOG_FN("raid")
c0e5af
@@ -37,39 +31,20 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
c0e5af
 {
c0e5af
 	struct dm_status_raid *status;
c0e5af
 	const char *d;
c0e5af
-	int dead = 0, r = 1;
c0e5af
 
c0e5af
 	if (!dm_get_status_raid(state->mem, params, &status)) {
c0e5af
 		log_error("Failed to process status line for %s.", device);
c0e5af
 		return 0;
c0e5af
 	}
c0e5af
 
c0e5af
-	d = status->dev_health;
c0e5af
-	while ((d = strchr(d, 'D'))) {
c0e5af
-		uint32_t dev = (uint32_t)(d - status->dev_health);
c0e5af
-
c0e5af
-		if (!(state->raid_devs[dev / 64] & (1 << (dev % 64))))
c0e5af
-			log_error("Device #%u of %s array, %s, has failed.",
c0e5af
-				  dev, status->raid_type, device);
c0e5af
-
c0e5af
-		state->raid_devs[dev / 64] |= (1 << (dev % 64));
c0e5af
-		d++;
c0e5af
-		dead = 1;
c0e5af
-	}
c0e5af
-
c0e5af
-	if (dead) {
c0e5af
-		if (status->insync_regions < status->total_regions) {
c0e5af
-			if (!state->warned)
c0e5af
-				log_warn("WARNING: waiting for resynchronization to finish "
c0e5af
-					 "before initiating repair on RAID device %s", device);
c0e5af
-
c0e5af
-			state->warned = 1;
c0e5af
-			goto out; /* Not yet done syncing with accessible devices */
c0e5af
-		}
c0e5af
-
c0e5af
+	if ((d = strchr(status->dev_health, 'D'))) {
c0e5af
 		if (state->failed)
c0e5af
 			goto out; /* already reported */
c0e5af
 
c0e5af
+		log_error("Device #%d of %s array, %s, has failed.",
c0e5af
+			  (int)(d - status->dev_health),
c0e5af
+			  status->raid_type, device);
c0e5af
+
c0e5af
 		state->failed = 1;
c0e5af
 		if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan))
c0e5af
 			log_warn("WARNING: Re-scan of RAID device %s failed.", device);
c0e5af
@@ -77,7 +52,8 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
c0e5af
 		/* if repair goes OK, report success even if lvscan has failed */
c0e5af
 		if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) {
c0e5af
 			log_info("Repair of RAID device %s failed.", device);
c0e5af
-			r = 0;
c0e5af
+			dm_pool_free(state->mem, status);
c0e5af
+			return 0;
c0e5af
 		}
c0e5af
 	} else {
c0e5af
 		state->failed = 0;
c0e5af
@@ -88,7 +64,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
c0e5af
 out:
c0e5af
 	dm_pool_free(state->mem, status);
c0e5af
 
c0e5af
-	return r;
c0e5af
+	return 1;
c0e5af
 }
c0e5af
 
c0e5af
 void process_event(struct dm_task *dmt,
c0e5af
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
c0e5af
index 70036f9..53a1044 100644
c0e5af
--- a/lib/metadata/lv.c
c0e5af
+++ b/lib/metadata/lv.c
c0e5af
@@ -988,6 +988,7 @@ int lv_mirror_image_in_sync(const struct logical_volume *lv)
c0e5af
 int lv_raid_image_in_sync(const struct logical_volume *lv)
c0e5af
 {
c0e5af
 	unsigned s;
c0e5af
+	dm_percent_t percent;
c0e5af
 	char *raid_health;
c0e5af
 	struct lv_segment *seg, *raid_seg = NULL;
c0e5af
 
c0e5af
@@ -1017,6 +1018,12 @@ int lv_raid_image_in_sync(const struct logical_volume *lv)
c0e5af
 		return 0;
c0e5af
 	}
c0e5af
 
c0e5af
+	if (!lv_raid_percent(raid_seg->lv, &percent))
c0e5af
+		return_0;
c0e5af
+
c0e5af
+	if (percent == DM_PERCENT_100)
c0e5af
+		return 1;
c0e5af
+
c0e5af
 	/* Find out which sub-LV this is. */
c0e5af
 	for (s = 0; s < raid_seg->area_count; s++)
c0e5af
 		if (seg_lv(raid_seg, s) == lv)
c0e5af
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
c0e5af
index deb88a2..e5fdf4f 100644
c0e5af
--- a/lib/metadata/raid_manip.c
c0e5af
+++ b/lib/metadata/raid_manip.c
c0e5af
@@ -3658,7 +3658,7 @@ static int _lv_raid_rebuild_or_replace(struct logical_volume *lv,
c0e5af
 		return 0;
c0e5af
 	}
c0e5af
 
c0e5af
-	if (!_raid_in_sync(lv)) {
c0e5af
+	if (!mirror_in_sync() && !_raid_in_sync(lv)) {
c0e5af
 		log_error("Unable to replace devices in %s/%s while it is"
c0e5af
 			  " not in-sync.", lv->vg->name, lv->name);
c0e5af
 		return 0;
c0e5af
diff --git a/test/shell/lvconvert-repair-raid.sh b/test/shell/lvconvert-repair-raid.sh
c0e5af
index b51d8fe..1ef91c4 100644
c0e5af
--- a/test/shell/lvconvert-repair-raid.sh
c0e5af
+++ b/test/shell/lvconvert-repair-raid.sh
c0e5af
@@ -22,52 +22,11 @@ aux lvmconf 'allocation/maximise_cling = 0' \
c0e5af
 
c0e5af
 aux prepare_vg 8
c0e5af
 
c0e5af
-function delay
c0e5af
-{
c0e5af
-	for d in $(< DEVICES)
c0e5af
-	do
c0e5af
-		aux delay_dev "$d" 0 $1 $(get first_extent_sector "$d")
c0e5af
-	done
c0e5af
-}
c0e5af
-
c0e5af
 # It's possible small raid arrays do have problems with reporting in-sync.
c0e5af
 # So try bigger size
c0e5af
-RAID_SIZE=32
c0e5af
-
c0e5af
-# Fast sync and repair afterwards
c0e5af
-delay 0
c0e5af
-
c0e5af
-# RAID1 dual-leg single replace after initial sync
c0e5af
-lvcreate --type raid1 -m 1 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2"
c0e5af
-aux wait_for_sync $vg $lv1
c0e5af
-aux disable_dev "$dev2"
c0e5af
-lvconvert -y --repair $vg/$lv1
c0e5af
-vgreduce --removemissing $vg
c0e5af
-aux enable_dev "$dev2"
c0e5af
-vgextend $vg "$dev2"
c0e5af
-lvremove -ff $vg/$lv1
c0e5af
-
c0e5af
-# Delayed sync to allow for repair during rebuild
c0e5af
-delay 50
c0e5af
-
c0e5af
-# RAID1 triple-leg single replace during initial sync
c0e5af
-lvcreate --type raid1 -m 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3"
c0e5af
-aux disable_dev "$dev2" "$dev3"
c0e5af
-not lvconvert -y --repair $vg/$lv1
c0e5af
-aux wait_for_sync $vg $lv1
c0e5af
-lvconvert -y --repair $vg/$lv1
c0e5af
-vgreduce --removemissing $vg
c0e5af
-aux enable_dev "$dev2" "$dev3"
c0e5af
-vgextend $vg "$dev2" "$dev3"
c0e5af
-lvremove -ff $vg/$lv1
c0e5af
-
c0e5af
-
c0e5af
-# Larger RAID size possible for striped RAID
c0e5af
 RAID_SIZE=64
c0e5af
 
c0e5af
-# Fast sync and repair afterwards
c0e5af
-delay 0
c0e5af
-# RAID5 single replace after initial sync
c0e5af
+# RAID5 single replace
c0e5af
 lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3"
c0e5af
 aux wait_for_sync $vg $lv1
c0e5af
 aux disable_dev "$dev3"
c0e5af
@@ -75,69 +34,16 @@ lvconvert -y --repair $vg/$lv1
c0e5af
 vgreduce --removemissing $vg
c0e5af
 aux enable_dev "$dev3"
c0e5af
 vgextend $vg "$dev3"
c0e5af
-lvremove -ff $vg/$lv1
c0e5af
+lvremove -ff $vg
c0e5af
 
c0e5af
-# Delayed sync to allow for repair during rebuild
c0e5af
-delay 50
c0e5af
-
c0e5af
-# RAID5 single replace during initial sync
c0e5af
-lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3"
c0e5af
-aux disable_dev "$dev3"
c0e5af
-not lvconvert -y --repair $vg/$lv1
c0e5af
-aux wait_for_sync $vg $lv1
c0e5af
-lvconvert -y --repair $vg/$lv1
c0e5af
-vgreduce --removemissing $vg
c0e5af
-aux enable_dev "$dev3"
c0e5af
-vgextend $vg "$dev3"
c0e5af
-lvremove -ff $vg/$lv1
c0e5af
-
c0e5af
-# Fast sync and repair afterwards
c0e5af
-delay 0
c0e5af
-
c0e5af
-# RAID6 double replace after initial sync
c0e5af
+# RAID6 double replace
c0e5af
 lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \
c0e5af
     "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
c0e5af
 aux wait_for_sync $vg $lv1
c0e5af
 aux disable_dev "$dev4" "$dev5"
c0e5af
 lvconvert -y --repair $vg/$lv1
c0e5af
 vgreduce --removemissing $vg
c0e5af
-aux enable_dev "$dev4" "$dev5"
c0e5af
-vgextend $vg "$dev4" "$dev5"
c0e5af
-lvremove -ff $vg/$lv1
c0e5af
-
c0e5af
-# Delayed sync to allow for repair during rebuild
c0e5af
-delay 50
c0e5af
-
c0e5af
-# RAID6 single replace after initial sync
c0e5af
-lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \
c0e5af
-    "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
c0e5af
-aux disable_dev "$dev4"
c0e5af
-not lvconvert -y --repair $vg/$lv1
c0e5af
-delay 0 # Fast sync and repair afterwards
c0e5af
-aux disable_dev "$dev4" # Need to disable again after changing delay
c0e5af
-aux wait_for_sync $vg $lv1
c0e5af
-lvconvert -y --repair $vg/$lv1
c0e5af
-vgreduce --removemissing $vg
c0e5af
 aux enable_dev "$dev4"
c0e5af
-vgextend $vg "$dev4"
c0e5af
-lvremove -ff $vg/$lv1
c0e5af
-
c0e5af
-# Delayed sync to allow for repair during rebuild
c0e5af
-delay 50
c0e5af
-
c0e5af
-# RAID10 single replace after initial sync
c0e5af
-lvcreate --type raid10 -m 1 -i 2 -L $RAID_SIZE -n $lv1 $vg \
c0e5af
-    "$dev1" "$dev2" "$dev3" "$dev4"
c0e5af
-aux disable_dev "$dev4"
c0e5af
-not lvconvert -y --repair $vg/$lv1
c0e5af
-delay 0 # Fast sync and repair afterwards
c0e5af
-aux disable_dev "$dev4" # Need to disable again after changing delay
c0e5af
-aux disable_dev "$dev1"
c0e5af
-aux wait_for_sync $vg $lv1
c0e5af
-lvconvert -y --repair $vg/$lv1
c0e5af
-vgreduce --removemissing $vg
c0e5af
-aux enable_dev "$dev4"
c0e5af
-vgextend $vg "$dev4"
c0e5af
-lvremove -ff $vg/$lv1
c0e5af
-
c0e5af
+aux enable_dev "$dev5"
c0e5af
+vgextend $vg "$dev4" "$dev5"
c0e5af
 vgremove -ff $vg
c0e5af
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
c0e5af
index 3607247..d1d21b6 100644
c0e5af
--- a/tools/lvconvert.c
c0e5af
+++ b/tools/lvconvert.c
c0e5af
@@ -1826,6 +1826,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
c0e5af
 	struct dm_list *failed_pvs;
c0e5af
 	struct cmd_context *cmd = lv->vg->cmd;
c0e5af
 	struct lv_segment *seg = first_seg(lv);
c0e5af
+	dm_percent_t sync_percent;
c0e5af
 
c0e5af
 	if (_linear_type_requested(lp->type_str)) {
c0e5af
 		if (arg_is_set(cmd, mirrors_ARG) && (arg_uint_value(cmd, mirrors_ARG, 0) != 0)) {
c0e5af
@@ -1973,6 +1974,24 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
c0e5af
 			return 0;
c0e5af
 		}
c0e5af
 
c0e5af
+		if (!lv_raid_percent(lv, &sync_percent)) {
c0e5af
+			log_error("Unable to determine sync status of %s.",
c0e5af
+				  display_lvname(lv));
c0e5af
+			return 0;
c0e5af
+		}
c0e5af
+
c0e5af
+		if (sync_percent != DM_PERCENT_100) {
c0e5af
+			log_warn("WARNING: %s is not in-sync.", display_lvname(lv));
c0e5af
+			log_warn("WARNING: Portions of the array may be unrecoverable.");
c0e5af
+
c0e5af
+			/*
c0e5af
+			 * The kernel will not allow a device to be replaced
c0e5af
+			 * in an array that is not in-sync unless we override
c0e5af
+			 * by forcing the array to be considered "in-sync".
c0e5af
+			 */
c0e5af
+			init_mirror_in_sync(1);
c0e5af
+		}
c0e5af
+
c0e5af
 		_lvconvert_raid_repair_ask(cmd, lp, &replace);
c0e5af
 
c0e5af
 		if (replace) {