strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
 
        if (mddev->reshape_position != MaxSector &&
-           pers->reshape == NULL) {
+           pers->start_reshape == NULL) {
                /* This personality cannot handle reshaping... */
                mddev->pers = NULL;
                module_put(pers->owner);
 {
        int rv;
        /* change the number of raid disks */
-       if (mddev->pers->reshape == NULL)
+       if (mddev->pers->check_reshape == NULL)
                return -EINVAL;
        if (raid_disks <= 0 ||
            raid_disks >= mddev->max_disks)
                return -EINVAL;
-       if (mddev->sync_thread)
+       if (mddev->sync_thread || mddev->reshape_position != MaxSector)
                return -EBUSY;
-       rv = mddev->pers->reshape(mddev, raid_disks);
+       mddev->delta_disks = raid_disks - mddev->raid_disks;
+
+       rv = mddev->pers->check_reshape(mddev);
        return rv;
 }
 
 
        return 0;
 }
 
-static int raid1_reshape(mddev_t *mddev, int raid_disks)
+static int raid1_reshape(mddev_t *mddev)
 {
        /* We need to:
         * 1/ resize the r1bio_pool
        struct pool_info *newpoolinfo;
        mirror_info_t *newmirrors;
        conf_t *conf = mddev_to_conf(mddev);
-       int cnt;
+       int cnt, raid_disks;
 
        int d, d2;
 
+       /* Cannot change chunk_size, layout, or level */
+       if (mddev->chunk_size != mddev->new_chunk ||
+           mddev->layout != mddev->new_layout ||
+           mddev->level != mddev->new_level) {
+               mddev->new_chunk = mddev->chunk_size;
+               mddev->new_layout = mddev->layout;
+               mddev->new_level = mddev->level;
+               return -EINVAL;
+       }
+
+       raid_disks = mddev->raid_disks + mddev->delta_disks;
+
        if (raid_disks < conf->raid_disks) {
                cnt=0;
                for (d= 0; d < conf->raid_disks; d++)
 
        mddev->degraded += (raid_disks - conf->raid_disks);
        conf->raid_disks = mddev->raid_disks = raid_disks;
+       mddev->delta_disks = 0;
 
        conf->last_used = 0; /* just make sure it is in-range */
        lower_barrier(conf);
        .spare_active   = raid1_spare_active,
        .sync_request   = sync_request,
        .resize         = raid1_resize,
-       .reshape        = raid1_reshape,
+       .check_reshape  = raid1_reshape,
        .quiesce        = raid1_quiesce,
 };
 
 
 }
 
 #ifdef CONFIG_MD_RAID5_RESHAPE
-static int raid5_reshape(mddev_t *mddev, int raid_disks)
+static int raid5_check_reshape(mddev_t *mddev)
 {
        raid5_conf_t *conf = mddev_to_conf(mddev);
        int err;
-       mdk_rdev_t *rdev;
-       struct list_head *rtmp;
-       int spares = 0;
-       int added_devices = 0;
 
-       if (mddev->degraded ||
-           test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
-               return -EBUSY;
-       if (conf->raid_disks > raid_disks)
-               return -EINVAL; /* Cannot shrink array yet */
-       if (conf->raid_disks == raid_disks)
+       if (mddev->delta_disks < 0 ||
+           mddev->new_level != mddev->level)
+               return -EINVAL; /* Cannot shrink array or change level yet */
+       if (mddev->delta_disks == 0)
                return 0; /* nothing to do */
 
        /* Can only proceed if there are plenty of stripe_heads.
         * If the chunk size is greater, user-space should request more
         * stripe_heads first.
         */
-       if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes) {
+       if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes ||
+           (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) {
                printk(KERN_WARNING "raid5: reshape: not enough stripes.  Needed %lu\n",
                       (mddev->chunk_size / STRIPE_SIZE)*4);
                return -ENOSPC;
        }
 
+       err = resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
+       if (err)
+               return err;
+
+       /* looks like we might be able to manage this */
+       return 0;
+}
+
+static int raid5_start_reshape(mddev_t *mddev)
+{
+       raid5_conf_t *conf = mddev_to_conf(mddev);
+       mdk_rdev_t *rdev;
+       struct list_head *rtmp;
+       int spares = 0;
+       int added_devices = 0;
+
+       if (mddev->degraded ||
+           test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+               return -EBUSY;
+
        ITERATE_RDEV(mddev, rdev, rtmp)
                if (rdev->raid_disk < 0 &&
                    !test_bit(Faulty, &rdev->flags))
                        spares++;
-       if (conf->raid_disks + spares < raid_disks-1)
+
+       if (spares < mddev->delta_disks-1)
                /* Not enough devices even to make a degraded array
                 * of that size
                 */
                return -EINVAL;
 
-       err = resize_stripes(conf, raid_disks);
-       if (err)
-               return err;
-
        atomic_set(&conf->reshape_stripes, 0);
        spin_lock_irq(&conf->device_lock);
        conf->previous_raid_disks = conf->raid_disks;
-       conf->raid_disks = raid_disks;
+       conf->raid_disks += mddev->delta_disks;
        conf->expand_progress = 0;
        conf->expand_lo = 0;
        spin_unlock_irq(&conf->device_lock);
                                break;
                }
 
-       mddev->degraded = (raid_disks - conf->previous_raid_disks) - added_devices;
-       mddev->new_chunk = mddev->chunk_size;
-       mddev->new_layout = mddev->layout;
-       mddev->new_level = mddev->level;
-       mddev->raid_disks = raid_disks;
-       mddev->delta_disks = raid_disks - conf->previous_raid_disks;
+       mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices;
+       mddev->raid_disks = conf->raid_disks;
        mddev->reshape_position = 0;
        mddev->sb_dirty = 1;
 
                mddev->recovery = 0;
                spin_lock_irq(&conf->device_lock);
                mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks;
-               mddev->delta_disks = 0;
                conf->expand_progress = MaxSector;
                spin_unlock_irq(&conf->device_lock);
                return -EAGAIN;
        .sync_request   = sync_request,
        .resize         = raid5_resize,
 #ifdef CONFIG_MD_RAID5_RESHAPE
-       .reshape        = raid5_reshape,
+       .check_reshape  = raid5_check_reshape,
+       .start_reshape  = raid5_start_reshape,
 #endif
        .quiesce        = raid5_quiesce,
 };