diff options
author | NeilBrown <neilb@suse.de> | 2013-06-17 16:55:31 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-06-17 16:55:31 +1000 |
commit | f80057aec5d314798251e318555cb8ac92e4c06f (patch) | |
tree | a608c1049fce2ca0719c46847ea00afa4b44f7dc /Assemble.c | |
parent | e2f408a4c03115452fdf467b75a8e1e5eee8cb6e (diff) |
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>
Diffstat (limited to 'Assemble.c')
-rw-r--r-- | Assemble.c | 18 |
1 files changed, 13 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 || |