diff options
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 60 |
1 files changed, 34 insertions, 26 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 089a3260430..355dafb98aa 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2590,21 +2590,15 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) } #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. @@ -2615,30 +2609,48 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) * 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); @@ -2660,12 +2672,8 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) 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; @@ -2679,7 +2687,6 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) 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; @@ -2752,7 +2759,8 @@ static struct mdk_personality raid5_personality = .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, }; |