Blame SOURCES/0036-mdadm-Introduce-new-array-state-broken-for-raid0-lin.patch

f5dd7b
From 43ebc9105e9dafe5145b3e801c05da4736bf6e02 Mon Sep 17 00:00:00 2001
f5dd7b
From: "Guilherme G. Piccoli" <gpiccoli@canonical.com>
f5dd7b
Date: Tue, 3 Sep 2019 16:49:01 -0300
f5dd7b
Subject: [RHEL7.8 PATCH V2 36/47] mdadm: Introduce new array state 'broken'
f5dd7b
 for raid0/linear
f5dd7b
f5dd7b
Currently if a md raid0/linear array gets one or more members removed while
f5dd7b
being mounted, kernel keeps showing state 'clean' in the 'array_state'
f5dd7b
sysfs attribute. Despite udev signaling the member device is gone, 'mdadm'
f5dd7b
cannot issue the STOP_ARRAY ioctl successfully, given the array is mounted.
f5dd7b
f5dd7b
Nothing else hints that something is wrong (except that the removed devices
f5dd7b
don't show properly in the output of mdadm 'detail' command). There is no
f5dd7b
other property to be checked, and if user is not performing reads/writes
f5dd7b
to the array, even kernel log is quiet and doesn't give a clue about the
f5dd7b
missing member.
f5dd7b
f5dd7b
This patch is the mdadm counterpart of kernel new array state 'broken'.
f5dd7b
The 'broken' state mimics the state 'clean' in every aspect, being useful
f5dd7b
only to distinguish if an array has some member missing. All necessary
f5dd7b
paths in mdadm were changed to deal with 'broken' state, and in case the
f5dd7b
tool runs in a kernel that is not updated, it'll work normally, i.e., it
f5dd7b
doesn't require the 'broken' state in order to work.
f5dd7b
Also, this patch changes the way the array state is showed in the 'detail'
f5dd7b
command (for raid0/linear only) - now it takes the 'array_state' sysfs
f5dd7b
attribute into account instead of only rely in the MD_SB_CLEAN flag.
f5dd7b
f5dd7b
Cc: Jes Sorensen <jes.sorensen@gmail.com>
f5dd7b
Cc: NeilBrown <neilb@suse.de>
f5dd7b
Cc: Song Liu <songliubraving@fb.com>
f5dd7b
Signed-off-by: Guilherme G. Piccoli <gpiccoli@canonical.com>
f5dd7b
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
f5dd7b
---
f5dd7b
 Detail.c  | 14 ++++++++++++--
f5dd7b
 Monitor.c |  8 ++++++--
f5dd7b
 maps.c    |  1 +
f5dd7b
 mdadm.h   |  1 +
f5dd7b
 mdmon.h   |  2 +-
f5dd7b
 monitor.c |  4 ++--
f5dd7b
 6 files changed, 23 insertions(+), 7 deletions(-)
f5dd7b
f5dd7b
diff --git a/Detail.c b/Detail.c
f5dd7b
index ad60434..3e61e37 100644
f5dd7b
--- a/Detail.c
f5dd7b
+++ b/Detail.c
f5dd7b
@@ -81,6 +81,7 @@ int Detail(char *dev, struct context *c)
f5dd7b
 	int external;
f5dd7b
 	int inactive;
f5dd7b
 	int is_container = 0;
f5dd7b
+	char *arrayst;
f5dd7b
 
f5dd7b
 	if (fd < 0) {
f5dd7b
 		pr_err("cannot open %s: %s\n",
f5dd7b
@@ -485,9 +486,18 @@ int Detail(char *dev, struct context *c)
f5dd7b
 			else
f5dd7b
 				st = ", degraded";
f5dd7b
 
f5dd7b
+			if (array.state & (1 << MD_SB_CLEAN)) {
f5dd7b
+				if ((array.level == 0) ||
f5dd7b
+				    (array.level == LEVEL_LINEAR))
f5dd7b
+					arrayst = map_num(sysfs_array_states,
f5dd7b
+							  sra->array_state);
f5dd7b
+				else
f5dd7b
+					arrayst = "clean";
f5dd7b
+			} else
f5dd7b
+				arrayst = "active";
f5dd7b
+
f5dd7b
 			printf("             State : %s%s%s%s%s%s \n",
f5dd7b
-			       (array.state & (1 << MD_SB_CLEAN)) ?
f5dd7b
-			       "clean" : "active", st,
f5dd7b
+			       arrayst, st,
f5dd7b
 			       (!e || (e->percent < 0 &&
f5dd7b
 				       e->percent != RESYNC_PENDING &&
f5dd7b
 				       e->percent != RESYNC_DELAYED)) ?
f5dd7b
diff --git a/Monitor.c b/Monitor.c
f5dd7b
index 036103f..b527165 100644
f5dd7b
--- a/Monitor.c
f5dd7b
+++ b/Monitor.c
f5dd7b
@@ -1055,8 +1055,11 @@ int Wait(char *dev)
f5dd7b
 	}
f5dd7b
 }
f5dd7b
 
f5dd7b
+/* The state "broken" is used only for RAID0/LINEAR - it's the same as
f5dd7b
+ * "clean", but used in case the array has one or more members missing.
f5dd7b
+ */
f5dd7b
 static char *clean_states[] = {
f5dd7b
-	"clear", "inactive", "readonly", "read-auto", "clean", NULL };
f5dd7b
+	"clear", "inactive", "readonly", "read-auto", "clean", "broken", NULL };
f5dd7b
 
f5dd7b
 int WaitClean(char *dev, int verbose)
f5dd7b
 {
f5dd7b
@@ -1116,7 +1119,8 @@ int WaitClean(char *dev, int verbose)
f5dd7b
 			rv = read(state_fd, buf, sizeof(buf));
f5dd7b
 			if (rv < 0)
f5dd7b
 				break;
f5dd7b
-			if (sysfs_match_word(buf, clean_states) <= 4)
f5dd7b
+			if (sysfs_match_word(buf, clean_states) <
f5dd7b
+			    (int)ARRAY_SIZE(clean_states) - 1)
f5dd7b
 				break;
f5dd7b
 			rv = sysfs_wait(state_fd, &delay);
f5dd7b
 			if (rv < 0 && errno != EINTR)
f5dd7b
diff --git a/maps.c b/maps.c
f5dd7b
index 02a0474..49b7f2c 100644
f5dd7b
--- a/maps.c
f5dd7b
+++ b/maps.c
f5dd7b
@@ -150,6 +150,7 @@ mapping_t sysfs_array_states[] = {
f5dd7b
 	{ "read-auto", ARRAY_READ_AUTO },
f5dd7b
 	{ "clean", ARRAY_CLEAN },
f5dd7b
 	{ "write-pending", ARRAY_WRITE_PENDING },
f5dd7b
+	{ "broken", ARRAY_BROKEN },
f5dd7b
 	{ NULL, ARRAY_UNKNOWN_STATE }
f5dd7b
 };
f5dd7b
 
f5dd7b
diff --git a/mdadm.h b/mdadm.h
f5dd7b
index 43b07d5..c88ceab 100644
f5dd7b
--- a/mdadm.h
f5dd7b
+++ b/mdadm.h
f5dd7b
@@ -373,6 +373,7 @@ struct mdinfo {
f5dd7b
 		ARRAY_ACTIVE,
f5dd7b
 		ARRAY_WRITE_PENDING,
f5dd7b
 		ARRAY_ACTIVE_IDLE,
f5dd7b
+		ARRAY_BROKEN,
f5dd7b
 		ARRAY_UNKNOWN_STATE,
f5dd7b
 	} array_state;
f5dd7b
 	struct md_bb bb;
f5dd7b
diff --git a/mdmon.h b/mdmon.h
f5dd7b
index 818367c..b3d72ac 100644
f5dd7b
--- a/mdmon.h
f5dd7b
+++ b/mdmon.h
f5dd7b
@@ -21,7 +21,7 @@
f5dd7b
 extern const char Name[];
f5dd7b
 
f5dd7b
 enum array_state { clear, inactive, suspended, readonly, read_auto,
f5dd7b
-		   clean, active, write_pending, active_idle, bad_word};
f5dd7b
+		   clean, active, write_pending, active_idle, broken, bad_word};
f5dd7b
 
f5dd7b
 enum sync_action { idle, reshape, resync, recover, check, repair, bad_action };
f5dd7b
 
f5dd7b
diff --git a/monitor.c b/monitor.c
f5dd7b
index 81537ed..e0d3be6 100644
f5dd7b
--- a/monitor.c
f5dd7b
+++ b/monitor.c
f5dd7b
@@ -26,7 +26,7 @@
f5dd7b
 
f5dd7b
 static char *array_states[] = {
f5dd7b
 	"clear", "inactive", "suspended", "readonly", "read-auto",
f5dd7b
-	"clean", "active", "write-pending", "active-idle", NULL };
f5dd7b
+	"clean", "active", "write-pending", "active-idle", "broken", NULL };
f5dd7b
 static char *sync_actions[] = {
f5dd7b
 	"idle", "reshape", "resync", "recover", "check", "repair", NULL
f5dd7b
 };
f5dd7b
@@ -476,7 +476,7 @@ static int read_and_act(struct active_array *a, fd_set *fds)
f5dd7b
 		a->next_state = clean;
f5dd7b
 		ret |= ARRAY_DIRTY;
f5dd7b
 	}
f5dd7b
-	if (a->curr_state == clean) {
f5dd7b
+	if ((a->curr_state == clean) || (a->curr_state == broken)) {
f5dd7b
 		a->container->ss->set_array_state(a, 1);
f5dd7b
 	}
f5dd7b
 	if (a->curr_state == active ||
f5dd7b
-- 
f5dd7b
2.7.5
f5dd7b