summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--managemon.c50
-rw-r--r--mdmon.h1
-rw-r--r--monitor.c17
3 files changed, 61 insertions, 7 deletions
diff --git a/managemon.c b/managemon.c
index 7e4924fe..5cc50d8d 100644
--- a/managemon.c
+++ b/managemon.c
@@ -420,12 +420,12 @@ static void manage_member(struct mdstat_ent *mdstat,
* We do not need to look for device state changes here, that
* is dealt with by the monitor.
*
- * We just look for changes which suggest that a reshape is
- * being requested.
- * Unfortunately decreases in raid_disks don't show up in
- * mdstat until the reshape completes FIXME.
+ * If a reshape is being requested, monitor will have noticed
+ * that sync_action changed and will have set check_reshape.
+ * We just need to see if new devices have appeared. All metadata
+ * updates will already have been processed.
*
- * Actually, we also want to handle degraded arrays here by
+ * We also want to handle degraded arrays here by
* trying to find and assign a spare.
* We do that whenever the monitor tells us too.
*/
@@ -488,6 +488,46 @@ static void manage_member(struct mdstat_ent *mdstat,
}
free_updates(&updates);
}
+
+ if (a->check_reshape) {
+ /* mdadm might have added some devices to the array.
+ * We want to disk_init_and_add any such device to a
+ * duplicate_aa and replace a with that.
+ * mdstat doesn't have enough info so we sysfs_read
+ * and look for new stuff.
+ */
+ struct mdinfo *info, *d, *d2, *newd;
+ struct active_array *newa = NULL;
+ a->check_reshape = 0;
+ info = sysfs_read(-1, mdstat->devnum,
+ GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE);
+ if (!info)
+ goto out2;
+ for (d = info->devs; d; d = d->next) {
+ if (d->disk.raid_disk < 0)
+ continue;
+ for (d2 = a->info.devs; d2; d2 = d2->next)
+ if (d2->disk.raid_disk ==
+ d->disk.raid_disk)
+ break;
+ if (d2)
+ /* already have this one */
+ continue;
+ if (!newa) {
+ newa = duplicate_aa(a);
+ if (!newa)
+ break;
+ }
+ newd = malloc(sizeof(*newd));
+ if (!newd)
+ continue;
+ disk_init_and_add(newd, d, newa);
+ }
+ out2:
+ sysfs_free(info);
+ if (newa)
+ replace_array(a->container, a, newa);
+ }
}
static int aa_ready(struct active_array *aa)
diff --git a/mdmon.h b/mdmon.h
index 5c515663..6d1776f9 100644
--- a/mdmon.h
+++ b/mdmon.h
@@ -46,6 +46,7 @@ struct active_array {
enum sync_action prev_action, curr_action, next_action;
int check_degraded; /* flag set by mon, read by manage */
+ int check_reshape; /* flag set by mon, read by manage */
int devnum;
};
diff --git a/monitor.c b/monitor.c
index f166bc8f..f5668905 100644
--- a/monitor.c
+++ b/monitor.c
@@ -215,6 +215,7 @@ static int read_and_act(struct active_array *a)
{
unsigned long long sync_completed;
int check_degraded = 0;
+ int check_reshape = 0;
int deactivate = 0;
struct mdinfo *mdi;
int dirty = 0;
@@ -305,6 +306,15 @@ static int read_and_act(struct active_array *a)
}
}
+ if (!deactivate &&
+ a->curr_action == reshape &&
+ a->prev_action != reshape)
+ /* reshape was requested by mdadm. Need to see if
+ * new devices have been added. Manager does that
+ * when it sees check_reshape
+ */
+ check_reshape = 1;
+
/* Check for failures and if found:
* 1/ Record the failure in the metadata and unblock the device.
* FIXME update the kernel to stop notifying on failed drives when
@@ -393,9 +403,12 @@ static int read_and_act(struct active_array *a)
mdi->next_state = 0;
}
- if (check_degraded) {
+ if (check_degraded || check_reshape) {
/* manager will do the actual check */
- a->check_degraded = 1;
+ if (check_degraded)
+ a->check_degraded = 1;
+ if (check_reshape)
+ a->check_reshape = 1;
signal_manager();
}