dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

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

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