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

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