From: NeilBrown Date: Mon, 17 Jun 2013 06:55:31 +0000 (+1000) Subject: Assemble/Incr: Don't include spares with too-high event count. X-Git-Tag: mdadm-3.3-rc1~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f80057aec5d314798251e318555cb8ac92e4c06f;p=thirdparty%2Fmdadm.git Assemble/Incr: Don't include spares with too-high event count. Some failure scenarios can leave a spare with a higher event count than an in-sync device. Assembling an array like this will confuse the kernel. So detect spares with event counts higher than the best non-spare event count and exclude them from the array. Reported-by: Alexander Lyakas Signed-off-by: NeilBrown --- diff --git a/Assemble.c b/Assemble.c index b45abc2f..c927c209 100644 --- a/Assemble.c +++ b/Assemble.c @@ -690,11 +690,12 @@ static int load_devices(struct devs *devices, char *devmap, devices[devcnt].i = *content; devices[devcnt].i.disk.major = major(stb.st_rdev); devices[devcnt].i.disk.minor = minor(stb.st_rdev); - if (most_recent < devcnt) { - if (devices[devcnt].i.events - > devices[most_recent].i.events) + + if (devices[devcnt].i.events + > devices[most_recent].i.events && + devices[devcnt].i.disk.state == 6) most_recent = devcnt; - } + if (content->array.level == LEVEL_MULTIPATH) /* with multipath, the raid_disk from the superblock is meaningless */ i = devcnt; @@ -1456,8 +1457,15 @@ try_again: best[i] = -1; continue; } + /* Require event counter to be same as, or just less than, + * most recent. If it is bigger, it must be a stray spare and + * should be ignored. + */ if (devices[j].i.events+event_margin >= - devices[most_recent].i.events) { + devices[most_recent].i.events && + devices[j].i.events <= + devices[most_recent].i.events + ) { devices[j].uptodate = 1; if (i < content->array.raid_disks * 2) { if (devices[j].i.recovery_start == MaxSector || diff --git a/Incremental.c b/Incremental.c index f9c0feb9..ce89702f 100644 --- a/Incremental.c +++ b/Incremental.c @@ -760,6 +760,14 @@ static int count_active(struct supertype *st, struct mdinfo *sra, if (avail[i]) cnt++; } + /* Also need to reject any spare device with an event count that + * is too high + */ + for (d = sra->devs; d; d = d->next) { + if (!(d->disk.state & (1<events > max_events) + d->disk.state |= (1 << MD_DISK_REMOVED); + } free(best); free(devmap); return cnt + replcnt;