diff options
-rw-r--r-- | managemon.c | 50 | ||||
-rw-r--r-- | mdmon.h | 1 | ||||
-rw-r--r-- | monitor.c | 17 |
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) @@ -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; }; @@ -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(); } |