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

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