Blame SOURCES/0012-imsm-finish-recovery-when-drive-with-rebuild-fails.patch

c8f3db
From a4e96fd8f3f0b5416783237c1cb6ee87e7eff23d Mon Sep 17 00:00:00 2001
c8f3db
From: Mariusz Tkaczyk <mariusz.tkaczyk@intel.com>
c8f3db
Date: Fri, 8 Feb 2019 11:07:10 +0100
c8f3db
Subject: [RHEL7.7 PATCH 12/21] imsm: finish recovery when drive with rebuild
c8f3db
 fails
c8f3db
c8f3db
Commit d7a1fda2769b ("imsm: update metadata correctly while raid10 double
c8f3db
degradation") resolves main Imsm double degradation problems but it
c8f3db
omits one case. Now metadata hangs in the rebuilding state if the drive
c8f3db
under rebuild is removed during recovery from double degradation.
c8f3db
c8f3db
The root cause of this problem is comparing new map_state with current
c8f3db
and if they both are degraded assuming that nothing new happens.
c8f3db
c8f3db
Don't rely on map states, just check if device is failed. If the drive
c8f3db
under rebuild fails then finish migration, in other cases update map
c8f3db
state only (second fail means that destination map state can't be normal).
c8f3db
c8f3db
To avoid problems with reassembling move end_migration (called after
c8f3db
double degradation successful recovery) after check if recovery really
c8f3db
finished, for details see (7ce057018 "imsm: fix: rebuild does not
c8f3db
continue after reboot").
c8f3db
Remove redundant code responsible for finishing rebuild process. Function
c8f3db
end_migration do exactly the same. Set last_checkpoint to 0, to prepare
c8f3db
it for the next rebuild.
c8f3db
c8f3db
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@intel.com>
c8f3db
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
c8f3db
---
c8f3db
 super-intel.c | 26 +++++++++++---------------
c8f3db
 1 file changed, 11 insertions(+), 15 deletions(-)
c8f3db
c8f3db
diff --git a/super-intel.c b/super-intel.c
c8f3db
index d2035cc..38a1b6c 100644
c8f3db
--- a/super-intel.c
c8f3db
+++ b/super-intel.c
c8f3db
@@ -8560,26 +8560,22 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
c8f3db
 		}
c8f3db
 		if (is_rebuilding(dev)) {
c8f3db
 			dprintf_cont("while rebuilding ");
c8f3db
-			if (map->map_state != map_state)  {
c8f3db
-				dprintf_cont("map state change ");
c8f3db
+			if (state & DS_FAULTY)  {
c8f3db
+				dprintf_cont("removing failed drive ");
c8f3db
 				if (n == map->failed_disk_num) {
c8f3db
 					dprintf_cont("end migration");
c8f3db
 					end_migration(dev, super, map_state);
c8f3db
+					a->last_checkpoint = 0;
c8f3db
 				} else {
c8f3db
-					dprintf_cont("raid10 double degradation, map state change");
c8f3db
+					dprintf_cont("fail detected during rebuild, changing map state");
c8f3db
 					map->map_state = map_state;
c8f3db
 				}
c8f3db
 				super->updates_pending++;
c8f3db
-			} else if (!rebuild_done)
c8f3db
-				break;
c8f3db
-			else if (n == map->failed_disk_num) {
c8f3db
-				/* r10 double degraded to degraded transition */
c8f3db
-				dprintf_cont("raid10 double degradation end migration");
c8f3db
-				end_migration(dev, super, map_state);
c8f3db
-				a->last_checkpoint = 0;
c8f3db
-				super->updates_pending++;
c8f3db
 			}
c8f3db
 
c8f3db
+			if (!rebuild_done)
c8f3db
+				break;
c8f3db
+
c8f3db
 			/* check if recovery is really finished */
c8f3db
 			for (mdi = a->info.devs; mdi ; mdi = mdi->next)
c8f3db
 				if (mdi->recovery_start != MaxSector) {
c8f3db
@@ -8588,7 +8584,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
c8f3db
 				}
c8f3db
 			if (recovery_not_finished) {
c8f3db
 				dprintf_cont("\n");
c8f3db
-				dprintf_cont("Rebuild has not finished yet, map state changes only if raid10 double degradation happens");
c8f3db
+				dprintf_cont("Rebuild has not finished yet");
c8f3db
 				if (a->last_checkpoint < mdi->recovery_start) {
c8f3db
 					a->last_checkpoint =
c8f3db
 						mdi->recovery_start;
c8f3db
@@ -8598,9 +8594,9 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
c8f3db
 			}
c8f3db
 
c8f3db
 			dprintf_cont(" Rebuild done, still degraded");
c8f3db
-			dev->vol.migr_state = 0;
c8f3db
-			set_migr_type(dev, 0);
c8f3db
-			dev->vol.curr_migr_unit = 0;
c8f3db
+			end_migration(dev, super, map_state);
c8f3db
+			a->last_checkpoint = 0;
c8f3db
+			super->updates_pending++;
c8f3db
 
c8f3db
 			for (i = 0; i < map->num_members; i++) {
c8f3db
 				int idx = get_imsm_ord_tbl_ent(dev, i, MAP_0);
c8f3db
-- 
c8f3db
2.7.5
c8f3db