Package: mdadm
Version: 4.1-2
Severity: normal
Tags: patch
User: ubuntu-de...@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-disc...@lists.ubuntu.com>
-XSBC-Original-Maintainer: Debian QA Group <packa...@qa.debian.org>
+Maintainer: Debian QA Group <packa...@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 <gpicc...@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 via email to