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 <neilb@suse.de>
This commit is contained in:
NeilBrown 2010-12-16 09:07:52 +11:00
parent b5420ef325
commit 0f99b4bd73
3 changed files with 61 additions and 7 deletions

View File

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

View File

@ -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;
};

View File

@ -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();
}