]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
md/raid5: recognise replacements when assembling array.
authorNeilBrown <neilb@suse.de>
Fri, 9 Dec 2011 03:27:04 +0000 (14:27 +1100)
committerNeilBrown <neilb@suse.de>
Fri, 9 Dec 2011 03:27:04 +0000 (14:27 +1100)
If a Replacement is seen, file it as such.

If we see two replacements (or two normal devices) for the one slot,
abort.

Signed-off-by: NeilBrown <neilb@suse.de>
drivers/md/raid5.c

index d87a8dc5ca6ccee5bdb6183a2e58e7fa216d8a99..9546cd8606526ca809dcd049901c3a4201e4d674 100644 (file)
@@ -4832,7 +4832,15 @@ static struct r5conf *setup_conf(struct mddev *mddev)
                        continue;
                disk = conf->disks + raid_disk;
 
-               disk->rdev = rdev;
+               if (test_bit(Replacement, &rdev->flags)) {
+                       if (disk->replacement)
+                               goto abort;
+                       disk->replacement = rdev;
+               } else {
+                       if (disk->rdev)
+                               goto abort;
+                       disk->rdev = rdev;
+               }
 
                if (test_bit(In_sync, &rdev->flags)) {
                        char b[BDEVNAME_SIZE];
@@ -4921,6 +4929,7 @@ static int run(struct mddev *mddev)
        int dirty_parity_disks = 0;
        struct md_rdev *rdev;
        sector_t reshape_offset = 0;
+       int i;
 
        if (mddev->recovery_cp != MaxSector)
                printk(KERN_NOTICE "md/raid:%s: not clean"
@@ -5010,12 +5019,25 @@ static int run(struct mddev *mddev)
        conf->thread = NULL;
        mddev->private = conf;
 
-       /*
-        * 0 for a fully functional array, 1 or 2 for a degraded array.
-        */
-       list_for_each_entry(rdev, &mddev->disks, same_set) {
-               if (rdev->raid_disk < 0)
+       for (i = 0; i < conf->raid_disks && conf->previous_raid_disks;
+            i++) {
+               rdev = conf->disks[i].rdev;
+               if (!rdev && conf->disks[i].replacement) {
+                       /* The replacement is all we have yet */
+                       rdev = conf->disks[i].replacement;
+                       conf->disks[i].replacement = NULL;
+                       clear_bit(Replacement, &rdev->flags);
+                       conf->disks[i].rdev = rdev;
+               }
+               if (!rdev)
                        continue;
+               if (conf->disks[i].replacement &&
+                   conf->reshape_progress != MaxSector) {
+                       /* replacements and reshape simply do not mix. */
+                       printk(KERN_ERR "md: cannot handle concurrent "
+                              "replacement and reshape.\n");
+                       goto abort;
+               }
                if (test_bit(In_sync, &rdev->flags)) {
                        working_disks++;
                        continue;
@@ -5049,6 +5071,9 @@ static int run(struct mddev *mddev)
                dirty_parity_disks++;
        }
 
+       /*
+        * 0 for a fully functional array, 1 or 2 for a degraded array.
+        */
        mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks)
                           - working_disks);