164 lines
5.3 KiB
Diff
164 lines
5.3 KiB
Diff
|
From 43ebc9105e9dafe5145b3e801c05da4736bf6e02 Mon Sep 17 00:00:00 2001
|
||
|
From: "Guilherme G. Piccoli" <gpiccoli@canonical.com>
|
||
|
Date: Tue, 3 Sep 2019 16:49:01 -0300
|
||
|
Subject: [RHEL7.8 PATCH V2 36/47] mdadm: 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.
|
||
|
|
||
|
Cc: Jes Sorensen <jes.sorensen@gmail.com>
|
||
|
Cc: NeilBrown <neilb@suse.de>
|
||
|
Cc: Song Liu <songliubraving@fb.com>
|
||
|
Signed-off-by: Guilherme G. Piccoli <gpiccoli@canonical.com>
|
||
|
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
|
||
|
---
|
||
|
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 ad60434..3e61e37 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 43b07d5..c88ceab 100644
|
||
|
--- a/mdadm.h
|
||
|
+++ b/mdadm.h
|
||
|
@@ -373,6 +373,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.7.5
|
||
|
|