diff options
author | NeilBrown <neilb@suse.de> | 2013-06-17 08:55:31 +0200 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-06-17 08:55:31 +0200 |
commit | f80057aec5d314798251e318555cb8ac92e4c06f (patch) | |
tree | a608c1049fce2ca0719c46847ea00afa4b44f7dc | |
parent | mdadm.h: add little bits of doco for 'struct superswitch'. (diff) | |
download | mdadm-f80057aec5d314798251e318555cb8ac92e4c06f.tar.xz mdadm-f80057aec5d314798251e318555cb8ac92e4c06f.zip |
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 <alex.bolshoy@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | Assemble.c | 18 | ||||
-rw-r--r-- | Incremental.c | 8 |
2 files changed, 21 insertions, 5 deletions
@@ -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<<MD_DISK_SYNC)) && + d->events > max_events) + d->disk.state |= (1 << MD_DISK_REMOVED); + } free(best); free(devmap); return cnt + replcnt; |