summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mdadm.h1
-rw-r--r--monitor.c51
2 files changed, 31 insertions, 21 deletions
diff --git a/mdadm.h b/mdadm.h
index c841f33e..2a7d038d 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -414,6 +414,7 @@ struct mdinfo {
#define DS_BLOCKED 16
#define DS_REMOVE 1024
#define DS_UNBLOCK 2048
+ #define DS_EXTERNAL_BB 4096
int prev_state, curr_state, next_state;
/* info read from sysfs */
diff --git a/monitor.c b/monitor.c
index a4f707cc..6429afc6 100644
--- a/monitor.c
+++ b/monitor.c
@@ -150,6 +150,8 @@ int read_dev_state(int fd)
rv |= DS_SPARE;
if (sysfs_attr_match(cp, "blocked"))
rv |= DS_BLOCKED;
+ if (sysfs_attr_match(cp, "external_bbl"))
+ rv |= DS_EXTERNAL_BB;
cp = strchr(cp, ',');
if (cp)
cp++;
@@ -306,9 +308,6 @@ static int check_for_cleared_bb(struct active_array *a, struct mdinfo *mdi)
struct md_bb *bb;
int i;
- if (!ss->get_bad_blocks)
- return -1;
-
/*
* Get a list of bad blocks for an array, then read list of
* acknowledged bad blocks from kernel and compare it against metadata
@@ -397,7 +396,7 @@ static void signal_manager(void)
#define ARRAY_DIRTY 1
#define ARRAY_BUSY 2
-static int read_and_act(struct active_array *a, fd_set *fds)
+static int read_and_act(struct active_array *a)
{
unsigned long long sync_completed;
int check_degraded = 0;
@@ -425,23 +424,32 @@ static int read_and_act(struct active_array *a, fd_set *fds)
for (mdi = a->info.devs; mdi ; mdi = mdi->next) {
mdi->next_state = 0;
mdi->curr_state = 0;
- if (mdi->state_fd >= 0) {
- read_resync_start(mdi->recovery_fd,
- &mdi->recovery_start);
- mdi->curr_state = read_dev_state(mdi->state_fd);
- }
- /*
- * If array is blocked and metadata handler is able to handle
- * BB, check if you can acknowledge them to md driver. If
- * successful, clear faulty state and unblock the array.
- */
- if ((mdi->curr_state & DS_BLOCKED) &&
- a->container->ss->record_bad_block &&
- (process_dev_ubb(a, mdi) > 0)) {
+
+ if (!is_fd_valid(mdi->state_fd))
+ /* We are removing this device, skip it then */
+ continue;
+
+ read_resync_start(mdi->recovery_fd, &mdi->recovery_start);
+ mdi->curr_state = read_dev_state(mdi->state_fd);
+
+ if (!(mdi->curr_state & DS_EXTERNAL_BB))
+ /*
+ * It assumes that superswitch badblock functions are set if disk
+ * has external badblocks support configured.
+ */
+ continue;
+
+ if ((mdi->curr_state & DS_BLOCKED) && process_dev_ubb(a, mdi) > 0)
+ /*
+ * Blocked has two meanings: we need to acknowledge failure or badblocks
+ * (if supported). Here, badblocks are handled.
+ *
+ * If successful, unblock the array. This is not perfect but
+ * process_dev_ubb() may disable badblock support in case of failure.
+ */
mdi->next_state |= DS_UNBLOCK;
- }
- if (FD_ISSET(mdi->bb_fd, fds))
- check_for_cleared_bb(a, mdi);
+
+ check_for_cleared_bb(a, mdi);
}
gettimeofday(&tv, NULL);
@@ -855,7 +863,8 @@ static int wait_and_act(struct supertype *container, int nowait)
signal_manager();
}
if (a->container && !a->to_remove) {
- int ret = read_and_act(a, &rfds);
+ int ret = read_and_act(a);
+
rv |= 1;
dirty_arrays += !!(ret & ARRAY_DIRTY);
/* when terminating stop manipulating the array after it