dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

Blame SOURCES/0025-mdmon-fix-wrong-array-state-when-disk-fails-during-m.patch

f5dd7b
From ae7d61e35ec2ab6361c3e509a8db00698ef3396f Mon Sep 17 00:00:00 2001
f5dd7b
From: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
f5dd7b
Date: Tue, 7 May 2019 16:08:47 +0200
f5dd7b
Subject: [RHEL7.8 PATCH V2 25/47] mdmon: fix wrong array state when disk fails
f5dd7b
 during mdmon startup
f5dd7b
f5dd7b
If a member drive disappears and is set faulty by the kernel during
f5dd7b
mdmon startup, after ss->load_container() but before manage_new(), mdmon
f5dd7b
will try to readd the faulty drive to the array and start rebuilding.
f5dd7b
Metadata on the active drive is updated, but the faulty drive is not
f5dd7b
removed from the array and is left in a "blocked" state and any write
f5dd7b
request to the array will block. If the faulty drive reappears in the
f5dd7b
system e.g. after a reboot, the array will not assemble because metadata
f5dd7b
on the drives will be incompatible (at least on imsm).
f5dd7b
f5dd7b
Fix this by adding a new option for sysfs_read(): "GET_DEVS_ALL". This
f5dd7b
is an extension for the "GET_DEVS" option and causes all member devices
f5dd7b
to be returned, even if the associated block device has been removed.
f5dd7b
Use this option in manage_new() to include the faulty device on the
f5dd7b
active_array's devices list. Mdmon will then properly remove the faulty
f5dd7b
device from the array and update the metadata to reflect the degraded
f5dd7b
state.
f5dd7b
f5dd7b
Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
f5dd7b
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
f5dd7b
---
f5dd7b
 managemon.c   |  2 +-
f5dd7b
 mdadm.h       |  1 +
f5dd7b
 super-intel.c |  2 +-
f5dd7b
 sysfs.c       | 23 ++++++++++++++---------
f5dd7b
 4 files changed, 17 insertions(+), 11 deletions(-)
f5dd7b
f5dd7b
diff --git a/managemon.c b/managemon.c
f5dd7b
index 29b91ba..200cf83 100644
f5dd7b
--- a/managemon.c
f5dd7b
+++ b/managemon.c
f5dd7b
@@ -678,7 +678,7 @@ static void manage_new(struct mdstat_ent *mdstat,
f5dd7b
 	mdi = sysfs_read(-1, mdstat->devnm,
f5dd7b
 			 GET_LEVEL|GET_CHUNK|GET_DISKS|GET_COMPONENT|
f5dd7b
 			 GET_SAFEMODE|GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE|
f5dd7b
-			 GET_LAYOUT);
f5dd7b
+			 GET_LAYOUT|GET_DEVS_ALL);
f5dd7b
 
f5dd7b
 	if (!mdi)
f5dd7b
 		return;
f5dd7b
diff --git a/mdadm.h b/mdadm.h
f5dd7b
index 705bd9b..427cc52 100644
f5dd7b
--- a/mdadm.h
f5dd7b
+++ b/mdadm.h
f5dd7b
@@ -647,6 +647,7 @@ enum sysfs_read_flags {
f5dd7b
 	GET_ERROR	= (1 << 24),
f5dd7b
 	GET_ARRAY_STATE = (1 << 25),
f5dd7b
 	GET_CONSISTENCY_POLICY	= (1 << 26),
f5dd7b
+	GET_DEVS_ALL	= (1 << 27),
f5dd7b
 };
f5dd7b
 
f5dd7b
 /* If fd >= 0, get the array it is open on,
f5dd7b
diff --git a/super-intel.c b/super-intel.c
f5dd7b
index 2ba045a..4fd5e84 100644
f5dd7b
--- a/super-intel.c
f5dd7b
+++ b/super-intel.c
f5dd7b
@@ -8560,7 +8560,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
f5dd7b
 	disk = get_imsm_disk(super, ord_to_idx(ord));
f5dd7b
 
f5dd7b
 	/* check for new failures */
f5dd7b
-	if (state & DS_FAULTY) {
f5dd7b
+	if (disk && (state & DS_FAULTY)) {
f5dd7b
 		if (mark_failure(super, dev, disk, ord_to_idx(ord)))
f5dd7b
 			super->updates_pending++;
f5dd7b
 	}
f5dd7b
diff --git a/sysfs.c b/sysfs.c
f5dd7b
index df6fdda..2dd9ab6 100644
f5dd7b
--- a/sysfs.c
f5dd7b
+++ b/sysfs.c
f5dd7b
@@ -313,17 +313,22 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options)
f5dd7b
 			/* assume this is a stale reference to a hot
f5dd7b
 			 * removed device
f5dd7b
 			 */
f5dd7b
-			free(dev);
f5dd7b
-			continue;
f5dd7b
+			if (!(options & GET_DEVS_ALL)) {
f5dd7b
+				free(dev);
f5dd7b
+				continue;
f5dd7b
+			}
f5dd7b
+		} else {
f5dd7b
+			sscanf(buf, "%d:%d", &dev->disk.major, &dev->disk.minor);
f5dd7b
 		}
f5dd7b
-		sscanf(buf, "%d:%d", &dev->disk.major, &dev->disk.minor);
f5dd7b
 
f5dd7b
-		/* special case check for block devices that can go 'offline' */
f5dd7b
-		strcpy(dbase, "block/device/state");
f5dd7b
-		if (load_sys(fname, buf, sizeof(buf)) == 0 &&
f5dd7b
-		    strncmp(buf, "offline", 7) == 0) {
f5dd7b
-			free(dev);
f5dd7b
-			continue;
f5dd7b
+		if (!(options & GET_DEVS_ALL)) {
f5dd7b
+			/* special case check for block devices that can go 'offline' */
f5dd7b
+			strcpy(dbase, "block/device/state");
f5dd7b
+			if (load_sys(fname, buf, sizeof(buf)) == 0 &&
f5dd7b
+			    strncmp(buf, "offline", 7) == 0) {
f5dd7b
+				free(dev);
f5dd7b
+				continue;
f5dd7b
+			}
f5dd7b
 		}
f5dd7b
 
f5dd7b
 		/* finally add this disk to the array */
f5dd7b
-- 
f5dd7b
2.7.5
f5dd7b