[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#943520: mdadm: Introduce broken state parsing to mdadm



Package: mdadm
Version: 4.1-2
Severity: normal
Tags: patch
User: ubuntu-devel@lists.ubuntu.com
Usertags: origin-ubuntu focal ubuntu-patch

Dear Maintainer,

* Currently, mounted raid0/md-linear arrays have no indication/warning when one or more members are removed or suffer from some non-recoverable error condition. The mdadm tool shows "clean" state regardless if a member was removed.

* The patch proposed in this SRU addresses this issue by introducing a new state "broken", which is analog to "clean" but indicates that array is not in a good/correct state. The commit, available upstream as 43ebc910 ("mdadm: Introduce new array state 'broken' for raid0/linear") [0], was extensively discussed and received a good amount of reviews/analysis by both the current mdadm maintainer as well as an old maintainer.

* One important note here is that this patch requires a counter-part in the kernel to be fully functional, which was SRUed in LP: #1847773.
It works fine/transparently without this kernel counter-part though.


In Ubuntu, the attached patch was applied to achieve the following:

  * Introduce "broken" state for RAID0/Linear in mdadm (LP: #1847924)


Thanks for considering the patch.
diff -Nru mdadm-4.1/debian/control mdadm-4.1/debian/control
--- mdadm-4.1/debian/control	2019-05-04 23:58:27.000000000 -0400
+++ mdadm-4.1/debian/control	2019-10-13 17:04:34.000000000 -0400
@@ -1,8 +1,7 @@
 Source: mdadm
 Section: admin
 Priority: optional
-Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
-XSBC-Original-Maintainer: Debian QA Group <packages@qa.debian.org>
+Maintainer: Debian QA Group <packages@qa.debian.org>
 Build-Depends: debhelper (>= 11), po-debconf, groff-base
 Standards-Version: 4.3.0
 Vcs-Git: https://git.dgit.debian.org/mdadm
diff -Nru mdadm-4.1/debian/patches/lp-1847924-introduce-new-array-state-broken.patch mdadm-4.1/debian/patches/lp-1847924-introduce-new-array-state-broken.patch
--- mdadm-4.1/debian/patches/lp-1847924-introduce-new-array-state-broken.patch	1969-12-31 19:00:00.000000000 -0500
+++ mdadm-4.1/debian/patches/lp-1847924-introduce-new-array-state-broken.patch	2019-10-13 17:04:34.000000000 -0400
@@ -0,0 +1,159 @@
+Subject: Introduce new array state 'broken' for raid0/linear
+
+Currently if a md raid0/linear array gets one or more members removed while
+being mounted, kernel keeps showing state 'clean' in the 'array_state'
+sysfs attribute. Despite udev signaling the member device is gone, 'mdadm'
+cannot issue the STOP_ARRAY ioctl successfully, given the array is mounted.
+
+Nothing else hints that something is wrong (except that the removed devices
+don't show properly in the output of mdadm 'detail' command). There is no
+other property to be checked, and if user is not performing reads/writes
+to the array, even kernel log is quiet and doesn't give a clue about the
+missing member.
+
+This patch is the mdadm counterpart of kernel new array state 'broken'.
+The 'broken' state mimics the state 'clean' in every aspect, being useful
+only to distinguish if an array has some member missing. All necessary
+paths in mdadm were changed to deal with 'broken' state, and in case the
+tool runs in a kernel that is not updated, it'll work normally, i.e., it
+doesn't require the 'broken' state in order to work.
+Also, this patch changes the way the array state is showed in the 'detail'
+command (for raid0/linear only) - now it takes the 'array_state' sysfs
+attribute into account instead of only rely in the MD_SB_CLEAN flag.
+
+Author: Guilherme G. Piccoli <gpiccoli@canonical.com>
+Origin: upstream,
+git.kernel.org/pub/scm/utils/mdadm/mdadm.git/commit/?id=cb77f8c598ede2b7efec23f899b1cda44c315195
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1847924
+Last-Update: 2019-10-13
+---
+ Detail.c  | 14 ++++++++++++--
+ Monitor.c |  8 ++++++--
+ maps.c    |  1 +
+ mdadm.h   |  1 +
+ mdmon.h   |  2 +-
+ monitor.c |  4 ++--
+ 6 files changed, 23 insertions(+), 7 deletions(-)
+
+diff --git a/Detail.c b/Detail.c
+index b3e857a..d24f334 100644
+--- a/Detail.c
++++ b/Detail.c
+@@ -81,6 +81,7 @@ int Detail(char *dev, struct context *c)
+ 	int external;
+ 	int inactive;
+ 	int is_container = 0;
++	char *arrayst;
+ 
+ 	if (fd < 0) {
+ 		pr_err("cannot open %s: %s\n",
+@@ -485,9 +486,18 @@ int Detail(char *dev, struct context *c)
+ 			else
+ 				st = ", degraded";
+ 
++			if (array.state & (1 << MD_SB_CLEAN)) {
++				if ((array.level == 0) ||
++				    (array.level == LEVEL_LINEAR))
++					arrayst = map_num(sysfs_array_states,
++							  sra->array_state);
++				else
++					arrayst = "clean";
++			} else
++				arrayst = "active";
++
+ 			printf("             State : %s%s%s%s%s%s \n",
+-			       (array.state & (1 << MD_SB_CLEAN)) ?
+-			       "clean" : "active", st,
++			       arrayst, st,
+ 			       (!e || (e->percent < 0 &&
+ 				       e->percent != RESYNC_PENDING &&
+ 				       e->percent != RESYNC_DELAYED)) ?
+diff --git a/Monitor.c b/Monitor.c
+index 036103f..b527165 100644
+--- a/Monitor.c
++++ b/Monitor.c
+@@ -1055,8 +1055,11 @@ int Wait(char *dev)
+ 	}
+ }
+ 
++/* The state "broken" is used only for RAID0/LINEAR - it's the same as
++ * "clean", but used in case the array has one or more members missing.
++ */
+ static char *clean_states[] = {
+-	"clear", "inactive", "readonly", "read-auto", "clean", NULL };
++	"clear", "inactive", "readonly", "read-auto", "clean", "broken", NULL };
+ 
+ int WaitClean(char *dev, int verbose)
+ {
+@@ -1116,7 +1119,8 @@ int WaitClean(char *dev, int verbose)
+ 			rv = read(state_fd, buf, sizeof(buf));
+ 			if (rv < 0)
+ 				break;
+-			if (sysfs_match_word(buf, clean_states) <= 4)
++			if (sysfs_match_word(buf, clean_states) <
++			    (int)ARRAY_SIZE(clean_states) - 1)
+ 				break;
+ 			rv = sysfs_wait(state_fd, &delay);
+ 			if (rv < 0 && errno != EINTR)
+diff --git a/maps.c b/maps.c
+index 02a0474..49b7f2c 100644
+--- a/maps.c
++++ b/maps.c
+@@ -150,6 +150,7 @@ mapping_t sysfs_array_states[] = {
+ 	{ "read-auto", ARRAY_READ_AUTO },
+ 	{ "clean", ARRAY_CLEAN },
+ 	{ "write-pending", ARRAY_WRITE_PENDING },
++	{ "broken", ARRAY_BROKEN },
+ 	{ NULL, ARRAY_UNKNOWN_STATE }
+ };
+ 
+diff --git a/mdadm.h b/mdadm.h
+index 705bd9b..216b491 100644
+--- a/mdadm.h
++++ b/mdadm.h
+@@ -345,6 +345,7 @@ struct mdinfo {
+ 		ARRAY_ACTIVE,
+ 		ARRAY_WRITE_PENDING,
+ 		ARRAY_ACTIVE_IDLE,
++		ARRAY_BROKEN,
+ 		ARRAY_UNKNOWN_STATE,
+ 	} array_state;
+ 	struct md_bb bb;
+diff --git a/mdmon.h b/mdmon.h
+index 818367c..b3d72ac 100644
+--- a/mdmon.h
++++ b/mdmon.h
+@@ -21,7 +21,7 @@
+ extern const char Name[];
+ 
+ enum array_state { clear, inactive, suspended, readonly, read_auto,
+-		   clean, active, write_pending, active_idle, bad_word};
++		   clean, active, write_pending, active_idle, broken, bad_word};
+ 
+ enum sync_action { idle, reshape, resync, recover, check, repair, bad_action };
+ 
+diff --git a/monitor.c b/monitor.c
+index 81537ed..e0d3be6 100644
+--- a/monitor.c
++++ b/monitor.c
+@@ -26,7 +26,7 @@
+ 
+ static char *array_states[] = {
+ 	"clear", "inactive", "suspended", "readonly", "read-auto",
+-	"clean", "active", "write-pending", "active-idle", NULL };
++	"clean", "active", "write-pending", "active-idle", "broken", NULL };
+ static char *sync_actions[] = {
+ 	"idle", "reshape", "resync", "recover", "check", "repair", NULL
+ };
+@@ -476,7 +476,7 @@ static int read_and_act(struct active_array *a, fd_set *fds)
+ 		a->next_state = clean;
+ 		ret |= ARRAY_DIRTY;
+ 	}
+-	if (a->curr_state == clean) {
++	if ((a->curr_state == clean) || (a->curr_state == broken)) {
+ 		a->container->ss->set_array_state(a, 1);
+ 	}
+ 	if (a->curr_state == active ||
+-- 
+2.23.0
+
diff -Nru mdadm-4.1/debian/patches/series mdadm-4.1/debian/patches/series
--- mdadm-4.1/debian/patches/series	2019-06-18 11:27:42.000000000 -0400
+++ mdadm-4.1/debian/patches/series	2019-10-13 17:04:34.000000000 -0400
@@ -15,3 +15,4 @@
 readlink-path.patch
 mdmonitor-service-simplify.diff
 randomize-timers.patch
+lp-1847924-introduce-new-array-state-broken.patch

Reply to: