dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

Blame SOURCES/imsm-rebuild-from-2-disk-RAID10.patch

2c1b57
From fb12a7454000c56aa0439c5bc07fb29de2f3f2a1 Mon Sep 17 00:00:00 2001
2c1b57
From: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
2c1b57
Date: Thu, 10 Aug 2017 15:47:22 +0200
2c1b57
Subject: [RHEL7.5 PATCH 163/169] imsm: rebuild from 2-disk RAID10
2c1b57
2c1b57
When RAID10 loses 2 disks and it is still operational, it cannot be
2c1b57
rebuilt. The rebuild process starts for the first disk and completes,
2c1b57
however completion is not recorded in metadata. There is an assumption
2c1b57
that rebuild completion corresponds to transition from degraded to
2c1b57
normal state. It's not the case for 2-disk RAID10 as it's still degraded
2c1b57
after rebuild to first disk completes.
2c1b57
2c1b57
Check if disk rebuild flag is set in the second map and clear it. So far it
2c1b57
has been checked only in the first map (where it was not set). The flag in
2c1b57
the second map has not been cleared but rebuild completion dropped second
2c1b57
map so the problem was not visible.
2c1b57
2c1b57
If rebuild completion is notified and array still has failed disks and is in
2c1b57
degraded state, check first if rebuild position is really unset (the same
2c1b57
check as for array in normal state). If so, mark migration as done but don't
2c1b57
change array state (it should remain degraded). Update failed disk number.
2c1b57
2c1b57
On rebuild start don't clear the rebuild flag in the destination map for all
2c1b57
the drives because failed state is lost for one of them. Just do a copy of
2c1b57
a map and clear the flag in the destination map for the disk that goes into
2c1b57
rebuild. Similarily preserve the rebuild flag in the map during disk removal.
2c1b57
2c1b57
If the disk is missing on array start and migration has been in progress,
2c1b57
don't just cancel it. Check first if maybe one of the disks was not under
2c1b57
rebuild (rebuild flag present both in source and destination map). If so,
2c1b57
rebuild was running despite of failed disk so there is no need to cancel
2c1b57
migration.
2c1b57
2c1b57
Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
2c1b57
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2c1b57
---
2c1b57
 super-intel.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
2c1b57
 1 file changed, 67 insertions(+), 10 deletions(-)
2c1b57
2c1b57
diff --git a/super-intel.c b/super-intel.c
2c1b57
index 51b7cc3..125c3a9 100644
2c1b57
--- a/super-intel.c
2c1b57
+++ b/super-intel.c
2c1b57
@@ -4023,7 +4023,7 @@ static void migrate(struct imsm_dev *dev, struct intel_super *super,
2c1b57
 
2c1b57
 	/* duplicate and then set the target end state in map[0] */
2c1b57
 	memcpy(dest, src, sizeof_imsm_map(src));
2c1b57
-	if (migr_type == MIGR_REBUILD || migr_type == MIGR_GEN_MIGR) {
2c1b57
+	if (migr_type == MIGR_GEN_MIGR) {
2c1b57
 		__u32 ord;
2c1b57
 		int i;
2c1b57
 
2c1b57
@@ -7936,14 +7936,35 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
2c1b57
 	/* end process for initialization and rebuild only
2c1b57
 	 */
2c1b57
 	if (is_gen_migration(dev) == 0) {
2c1b57
-		__u8 map_state;
2c1b57
-		int failed;
2c1b57
+		int failed = imsm_count_failed(super, dev, MAP_0);
2c1b57
 
2c1b57
-		failed = imsm_count_failed(super, dev, MAP_0);
2c1b57
-		map_state = imsm_check_degraded(super, dev, failed, MAP_0);
2c1b57
+		if (failed) {
2c1b57
+			__u8 map_state;
2c1b57
+			struct imsm_map *map = get_imsm_map(dev, MAP_0);
2c1b57
+			struct imsm_map *map1;
2c1b57
+			int i, ord, ord_map1;
2c1b57
+			int rebuilt = 1;
2c1b57
 
2c1b57
-		if (failed)
2c1b57
-			end_migration(dev, super, map_state);
2c1b57
+			for (i = 0; i < map->num_members; i++) {
2c1b57
+				ord = get_imsm_ord_tbl_ent(dev, i, MAP_0);
2c1b57
+				if (!(ord & IMSM_ORD_REBUILD))
2c1b57
+					continue;
2c1b57
+
2c1b57
+				map1 = get_imsm_map(dev, MAP_1);
2c1b57
+				if (!map1)
2c1b57
+					continue;
2c1b57
+
2c1b57
+				ord_map1 = __le32_to_cpu(map1->disk_ord_tbl[i]);
2c1b57
+				if (ord_map1 & IMSM_ORD_REBUILD)
2c1b57
+					rebuilt = 0;
2c1b57
+			}
2c1b57
+
2c1b57
+			if (rebuilt) {
2c1b57
+				map_state = imsm_check_degraded(super, dev,
2c1b57
+								failed, MAP_0);
2c1b57
+				end_migration(dev, super, map_state);
2c1b57
+			}
2c1b57
+		}
2c1b57
 	}
2c1b57
 	for (dl = super->missing; dl; dl = dl->next)
2c1b57
 		mark_missing(super, dev, &dl->disk, dl->index);
2c1b57
@@ -8225,8 +8246,10 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
2c1b57
 	int failed;
2c1b57
 	int ord;
2c1b57
 	__u8 map_state;
2c1b57
+	int rebuild_done = 0;
2c1b57
+	int i;
2c1b57
 
2c1b57
-	ord = imsm_disk_slot_to_ord(a, n);
2c1b57
+	ord = get_imsm_ord_tbl_ent(dev, n, MAP_X);
2c1b57
 	if (ord < 0)
2c1b57
 		return;
2c1b57
 
2c1b57
@@ -8244,6 +8267,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
2c1b57
 		struct imsm_map *migr_map = get_imsm_map(dev, MAP_1);
2c1b57
 
2c1b57
 		set_imsm_ord_tbl_ent(migr_map, n, ord_to_idx(ord));
2c1b57
+		rebuild_done = 1;
2c1b57
 		super->updates_pending++;
2c1b57
 	}
2c1b57
 
2c1b57
@@ -8306,7 +8330,39 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
2c1b57
 				dprintf_cont(" Map state change");
2c1b57
 				end_migration(dev, super, map_state);
2c1b57
 				super->updates_pending++;
2c1b57
+			} else if (!rebuild_done) {
2c1b57
+				break;
2c1b57
+			}
2c1b57
+
2c1b57
+			/* check if recovery is really finished */
2c1b57
+			for (mdi = a->info.devs; mdi ; mdi = mdi->next)
2c1b57
+				if (mdi->recovery_start != MaxSector) {
2c1b57
+					recovery_not_finished = 1;
2c1b57
+					break;
2c1b57
+				}
2c1b57
+			if (recovery_not_finished) {
2c1b57
+				dprintf_cont("\n");
2c1b57
+				dprintf("Rebuild has not finished yet, state not changed");
2c1b57
+				if (a->last_checkpoint < mdi->recovery_start) {
2c1b57
+					a->last_checkpoint =
2c1b57
+						mdi->recovery_start;
2c1b57
+					super->updates_pending++;
2c1b57
+				}
2c1b57
+				break;
2c1b57
 			}
2c1b57
+
2c1b57
+			dprintf_cont(" Rebuild done, still degraded");
2c1b57
+			dev->vol.migr_state = 0;
2c1b57
+			set_migr_type(dev, 0);
2c1b57
+			dev->vol.curr_migr_unit = 0;
2c1b57
+
2c1b57
+			for (i = 0; i < map->num_members; i++) {
2c1b57
+				int idx = get_imsm_ord_tbl_ent(dev, i, MAP_0);
2c1b57
+
2c1b57
+				if (idx & IMSM_ORD_REBUILD)
2c1b57
+					map->failed_disk_num = i;
2c1b57
+			}
2c1b57
+			super->updates_pending++;
2c1b57
 			break;
2c1b57
 		}
2c1b57
 		if (is_gen_migration(dev)) {
2c1b57
@@ -9936,7 +9992,7 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
2c1b57
 	struct imsm_dev *dev;
2c1b57
 	struct imsm_map *map;
2c1b57
 	unsigned int i, j, num_members;
2c1b57
-	__u32 ord;
2c1b57
+	__u32 ord, ord_map0;
2c1b57
 	struct bbm_log *log = super->bbm_log;
2c1b57
 
2c1b57
 	dprintf("deleting device[%d] from imsm_super\n", index);
2c1b57
@@ -9958,12 +10014,13 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
2c1b57
 			 * ord-flags to the first map
2c1b57
 			 */
2c1b57
 			ord = get_imsm_ord_tbl_ent(dev, j, MAP_X);
2c1b57
+			ord_map0 = get_imsm_ord_tbl_ent(dev, j, MAP_0);
2c1b57
 
2c1b57
 			if (ord_to_idx(ord) <= index)
2c1b57
 				continue;
2c1b57
 
2c1b57
 			map = get_imsm_map(dev, MAP_0);
2c1b57
-			set_imsm_ord_tbl_ent(map, j, ord_to_idx(ord - 1));
2c1b57
+			set_imsm_ord_tbl_ent(map, j, ord_map0 - 1);
2c1b57
 			map = get_imsm_map(dev, MAP_1);
2c1b57
 			if (map)
2c1b57
 				set_imsm_ord_tbl_ent(map, j, ord - 1);
2c1b57
-- 
2c1b57
2.7.4
2c1b57