Blame SOURCES/0006-imsm-update-metadata-correctly-while-raid10-double-d.patch

c8f3db
From d7a1fda2769ba272d89de6caeab35d52b73a9c3c Mon Sep 17 00:00:00 2001
c8f3db
From: Mariusz Tkaczyk <mariusz.tkaczyk@intel.com>
c8f3db
Date: Wed, 17 Oct 2018 12:11:41 +0200
c8f3db
Subject: [RHEL7.7 PATCH 06/21] imsm: update metadata correctly while raid10
c8f3db
 double degradation
c8f3db
c8f3db
Mdmon calls end_migration() when map state changes from normal to
c8f3db
degraded. It is not valid because in raid 10 double degradation case
c8f3db
mdmon breaks checkpointing but array is still rebuilding.
c8f3db
In this case mdmon has to mark map as degraded and continues marking
c8f3db
recovery checkpoint in metadata. Migration can be finished only if newly
c8f3db
failed device is a rebuilding device.
c8f3db
c8f3db
Add catching double degraded to degraded transition. Migration is
c8f3db
finished but map state doesn't change, array is still degraded.
c8f3db
c8f3db
Update failed_disk_num correctly. If double degradation
c8f3db
happens rebuild will start on the lowest slot, but this variable points
c8f3db
to the first failed slot. If second fail happens while rebuild this
c8f3db
variable shouldn't be updated until rebuild is not finished.
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 | 25 +++++++++++++++++++------
c8f3db
 1 file changed, 19 insertions(+), 6 deletions(-)
c8f3db
c8f3db
diff --git a/super-intel.c b/super-intel.c
c8f3db
index 6438987..d2035cc 100644
c8f3db
--- a/super-intel.c
c8f3db
+++ b/super-intel.c
c8f3db
@@ -8136,7 +8136,8 @@ static int mark_failure(struct intel_super *super,
c8f3db
 			set_imsm_ord_tbl_ent(map2, slot2,
c8f3db
 					     idx | IMSM_ORD_REBUILD);
c8f3db
 	}
c8f3db
-	if (map->failed_disk_num == 0xff)
c8f3db
+	if (map->failed_disk_num == 0xff ||
c8f3db
+		(!is_rebuilding(dev) && map->failed_disk_num > slot))
c8f3db
 		map->failed_disk_num = slot;
c8f3db
 
c8f3db
 	clear_disk_badblocks(super->bbm_log, ord_to_idx(ord));
c8f3db
@@ -8558,13 +8559,25 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
c8f3db
 			break;
c8f3db
 		}
c8f3db
 		if (is_rebuilding(dev)) {
c8f3db
-			dprintf_cont("while rebuilding.");
c8f3db
+			dprintf_cont("while rebuilding ");
c8f3db
 			if (map->map_state != map_state)  {
c8f3db
-				dprintf_cont(" Map state change");
c8f3db
-				end_migration(dev, super, map_state);
c8f3db
+				dprintf_cont("map state change ");
c8f3db
+				if (n == map->failed_disk_num) {
c8f3db
+					dprintf_cont("end migration");
c8f3db
+					end_migration(dev, super, map_state);
c8f3db
+				} else {
c8f3db
+					dprintf_cont("raid10 double degradation, map state change");
c8f3db
+					map->map_state = map_state;
c8f3db
+				}
c8f3db
 				super->updates_pending++;
c8f3db
-			} else if (!rebuild_done) {
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
 			/* check if recovery is really finished */
c8f3db
@@ -8575,7 +8588,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("Rebuild has not finished yet, state not changed");
c8f3db
+				dprintf_cont("Rebuild has not finished yet, map state changes only if raid10 double degradation happens");
c8f3db
 				if (a->last_checkpoint < mdi->recovery_start) {
c8f3db
 					a->last_checkpoint =
c8f3db
 						mdi->recovery_start;
c8f3db
-- 
c8f3db
2.7.5
c8f3db