]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Assemble/Incr: Don't include spares with too-high event count.
authorNeilBrown <neilb@suse.de>
Mon, 17 Jun 2013 06:55:31 +0000 (16:55 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 17 Jun 2013 06:55:31 +0000 (16:55 +1000)
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>
Assemble.c
Incremental.c

index b45abc2f408d4ad27ff4f7d55a03af8b51470d62..c927c209dbca2ebbb0b59007ca7f99f6804b204d 100644 (file)
@@ -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 ||
index f9c0feb9ebd4c882797899aad41b402d76837df5..ce89702fbc416b6d8df65e5f4aab2b4c4a9bb569 100644 (file)
@@ -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;