From 0f99b4bd73c916004fe94d17c7f37c8c6f68c8b8 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 16 Dec 2010 09:07:52 +1100 Subject: [PATCH] mdmon: when a reshape is detected, add any newly added devices to the array. When mdadm starts a reshape, it might add some devices to the array first. mdmon needs to notice the reshape starting and check for any new devices. If there are any they need to be provided to be monitored. Signed-off-by: NeilBrown --- managemon.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- mdmon.h | 1 + monitor.c | 17 +++++++++++++++-- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/managemon.c b/managemon.c index 7e4924f..5cc50d8 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 5c51566..6d1776f 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 f166bc8..f566890 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(); }