]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/md/md.c
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / drivers / md / md.c
index 46b3a044eadf41166a60cab6f10153fd1e75f09f..cb20d0b0555adee7c12d5e643a65d142f7f054e0 100644 (file)
@@ -2087,6 +2087,7 @@ static void sync_sbs(mddev_t * mddev, int nospares)
        /* First make sure individual recovery_offsets are correct */
        list_for_each_entry(rdev, &mddev->disks, same_set) {
                if (rdev->raid_disk >= 0 &&
+                   mddev->delta_disks >= 0 &&
                    !test_bit(In_sync, &rdev->flags) &&
                    mddev->curr_resync_completed > rdev->recovery_offset)
                                rdev->recovery_offset = mddev->curr_resync_completed;
@@ -3001,6 +3002,9 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
                return -EINVAL;
        }
 
+       list_for_each_entry(rdev, &mddev->disks, same_set)
+               rdev->new_raid_disk = rdev->raid_disk;
+
        /* ->takeover must set new_* and/or delta_disks
         * if it succeeds, and may set them when it fails.
         */
@@ -3051,13 +3055,35 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
                mddev->safemode = 0;
        }
 
-       module_put(mddev->pers->owner);
-       /* Invalidate devices that are now superfluous */
-       list_for_each_entry(rdev, &mddev->disks, same_set)
-               if (rdev->raid_disk >= mddev->raid_disks) {
-                       rdev->raid_disk = -1;
+       list_for_each_entry(rdev, &mddev->disks, same_set) {
+               char nm[20];
+               if (rdev->raid_disk < 0)
+                       continue;
+               if (rdev->new_raid_disk > mddev->raid_disks)
+                       rdev->new_raid_disk = -1;
+               if (rdev->new_raid_disk == rdev->raid_disk)
+                       continue;
+               sprintf(nm, "rd%d", rdev->raid_disk);
+               sysfs_remove_link(&mddev->kobj, nm);
+       }
+       list_for_each_entry(rdev, &mddev->disks, same_set) {
+               if (rdev->raid_disk < 0)
+                       continue;
+               if (rdev->new_raid_disk == rdev->raid_disk)
+                       continue;
+               rdev->raid_disk = rdev->new_raid_disk;
+               if (rdev->raid_disk < 0)
                        clear_bit(In_sync, &rdev->flags);
+               else {
+                       char nm[20];
+                       sprintf(nm, "rd%d", rdev->raid_disk);
+                       if(sysfs_create_link(&mddev->kobj, &rdev->kobj, nm))
+                               printk("md: cannot register %s for %s after level change\n",
+                                      nm, mdname(mddev));
                }
+       }
+
+       module_put(mddev->pers->owner);
        mddev->pers = pers;
        mddev->private = priv;
        strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
@@ -5895,6 +5921,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
        atomic_inc(&mddev->openers);
        mutex_unlock(&mddev->open_mutex);
 
+       check_disk_size_change(mddev->gendisk, bdev);
  out:
        return err;
 }
@@ -6846,6 +6873,7 @@ void md_do_sync(mddev_t *mddev)
                        rcu_read_lock();
                        list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
                                if (rdev->raid_disk >= 0 &&
+                                   mddev->delta_disks >= 0 &&
                                    !test_bit(Faulty, &rdev->flags) &&
                                    !test_bit(In_sync, &rdev->flags) &&
                                    rdev->recovery_offset < mddev->curr_resync)