|
|
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 |
|