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>
This commit is contained in:
parent
e2f408a4c0
commit
f80057aec5
18
Assemble.c
18
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 ||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue