Commit 63c70c4f authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

[PATCH] md: Split reshape handler in check_reshape and start_reshape

check_reshape checks validity and does things that can be done instantly -
like adding devices to raid1.  start_reshape initiates a restriping process to
convert the whole array.
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b578d55f
...@@ -2594,7 +2594,7 @@ static int do_md_run(mddev_t * mddev) ...@@ -2594,7 +2594,7 @@ static int do_md_run(mddev_t * mddev)
strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
if (mddev->reshape_position != MaxSector && if (mddev->reshape_position != MaxSector &&
pers->reshape == NULL) { pers->start_reshape == NULL) {
/* This personality cannot handle reshaping... */ /* This personality cannot handle reshaping... */
mddev->pers = NULL; mddev->pers = NULL;
module_put(pers->owner); module_put(pers->owner);
...@@ -3556,14 +3556,16 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks) ...@@ -3556,14 +3556,16 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks)
{ {
int rv; int rv;
/* change the number of raid disks */ /* change the number of raid disks */
if (mddev->pers->reshape == NULL) if (mddev->pers->check_reshape == NULL)
return -EINVAL; return -EINVAL;
if (raid_disks <= 0 || if (raid_disks <= 0 ||
raid_disks >= mddev->max_disks) raid_disks >= mddev->max_disks)
return -EINVAL; return -EINVAL;
if (mddev->sync_thread) if (mddev->sync_thread || mddev->reshape_position != MaxSector)
return -EBUSY; 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 rv;
} }
......
...@@ -1976,7 +1976,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors) ...@@ -1976,7 +1976,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
return 0; return 0;
} }
static int raid1_reshape(mddev_t *mddev, int raid_disks) static int raid1_reshape(mddev_t *mddev)
{ {
/* We need to: /* We need to:
* 1/ resize the r1bio_pool * 1/ resize the r1bio_pool
...@@ -1993,10 +1993,22 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) ...@@ -1993,10 +1993,22 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
struct pool_info *newpoolinfo; struct pool_info *newpoolinfo;
mirror_info_t *newmirrors; mirror_info_t *newmirrors;
conf_t *conf = mddev_to_conf(mddev); conf_t *conf = mddev_to_conf(mddev);
int cnt; int cnt, raid_disks;
int d, d2; 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) { if (raid_disks < conf->raid_disks) {
cnt=0; cnt=0;
for (d= 0; d < conf->raid_disks; d++) for (d= 0; d < conf->raid_disks; d++)
...@@ -2043,6 +2055,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) ...@@ -2043,6 +2055,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
mddev->degraded += (raid_disks - conf->raid_disks); mddev->degraded += (raid_disks - conf->raid_disks);
conf->raid_disks = mddev->raid_disks = 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 */ conf->last_used = 0; /* just make sure it is in-range */
lower_barrier(conf); lower_barrier(conf);
...@@ -2084,7 +2097,7 @@ static struct mdk_personality raid1_personality = ...@@ -2084,7 +2097,7 @@ static struct mdk_personality raid1_personality =
.spare_active = raid1_spare_active, .spare_active = raid1_spare_active,
.sync_request = sync_request, .sync_request = sync_request,
.resize = raid1_resize, .resize = raid1_resize,
.reshape = raid1_reshape, .check_reshape = raid1_reshape,
.quiesce = raid1_quiesce, .quiesce = raid1_quiesce,
}; };
......
...@@ -2590,21 +2590,15 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) ...@@ -2590,21 +2590,15 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
} }
#ifdef CONFIG_MD_RAID5_RESHAPE #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); raid5_conf_t *conf = mddev_to_conf(mddev);
int err; int err;
mdk_rdev_t *rdev;
struct list_head *rtmp;
int spares = 0;
int added_devices = 0;
if (mddev->degraded || if (mddev->delta_disks < 0 ||
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) mddev->new_level != mddev->level)
return -EBUSY; return -EINVAL; /* Cannot shrink array or change level yet */
if (conf->raid_disks > raid_disks) if (mddev->delta_disks == 0)
return -EINVAL; /* Cannot shrink array yet */
if (conf->raid_disks == raid_disks)
return 0; /* nothing to do */ return 0; /* nothing to do */
/* Can only proceed if there are plenty of stripe_heads. /* Can only proceed if there are plenty of stripe_heads.
...@@ -2615,30 +2609,48 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) ...@@ -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 * If the chunk size is greater, user-space should request more
* stripe_heads first. * 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", printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n",
(mddev->chunk_size / STRIPE_SIZE)*4); (mddev->chunk_size / STRIPE_SIZE)*4);
return -ENOSPC; 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) ITERATE_RDEV(mddev, rdev, rtmp)
if (rdev->raid_disk < 0 && if (rdev->raid_disk < 0 &&
!test_bit(Faulty, &rdev->flags)) !test_bit(Faulty, &rdev->flags))
spares++; spares++;
if (conf->raid_disks + spares < raid_disks-1)
if (spares < mddev->delta_disks-1)
/* Not enough devices even to make a degraded array /* Not enough devices even to make a degraded array
* of that size * of that size
*/ */
return -EINVAL; return -EINVAL;
err = resize_stripes(conf, raid_disks);
if (err)
return err;
atomic_set(&conf->reshape_stripes, 0); atomic_set(&conf->reshape_stripes, 0);
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
conf->previous_raid_disks = conf->raid_disks; conf->previous_raid_disks = conf->raid_disks;
conf->raid_disks = raid_disks; conf->raid_disks += mddev->delta_disks;
conf->expand_progress = 0; conf->expand_progress = 0;
conf->expand_lo = 0; conf->expand_lo = 0;
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
...@@ -2660,12 +2672,8 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) ...@@ -2660,12 +2672,8 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks)
break; break;
} }
mddev->degraded = (raid_disks - conf->previous_raid_disks) - added_devices; mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices;
mddev->new_chunk = mddev->chunk_size; mddev->raid_disks = conf->raid_disks;
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->reshape_position = 0; mddev->reshape_position = 0;
mddev->sb_dirty = 1; mddev->sb_dirty = 1;
...@@ -2679,7 +2687,6 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks) ...@@ -2679,7 +2687,6 @@ static int raid5_reshape(mddev_t *mddev, int raid_disks)
mddev->recovery = 0; mddev->recovery = 0;
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks; mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks;
mddev->delta_disks = 0;
conf->expand_progress = MaxSector; conf->expand_progress = MaxSector;
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
return -EAGAIN; return -EAGAIN;
...@@ -2752,7 +2759,8 @@ static struct mdk_personality raid5_personality = ...@@ -2752,7 +2759,8 @@ static struct mdk_personality raid5_personality =
.sync_request = sync_request, .sync_request = sync_request,
.resize = raid5_resize, .resize = raid5_resize,
#ifdef CONFIG_MD_RAID5_RESHAPE #ifdef CONFIG_MD_RAID5_RESHAPE
.reshape = raid5_reshape, .check_reshape = raid5_check_reshape,
.start_reshape = raid5_start_reshape,
#endif #endif
.quiesce = raid5_quiesce, .quiesce = raid5_quiesce,
}; };
......
...@@ -261,7 +261,8 @@ struct mdk_personality ...@@ -261,7 +261,8 @@ struct mdk_personality
int (*spare_active) (mddev_t *mddev); int (*spare_active) (mddev_t *mddev);
sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster); sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
int (*resize) (mddev_t *mddev, sector_t sectors); int (*resize) (mddev_t *mddev, sector_t sectors);
int (*reshape) (mddev_t *mddev, int raid_disks); int (*check_reshape) (mddev_t *mddev);
int (*start_reshape) (mddev_t *mddev);
int (*reconfig) (mddev_t *mddev, int layout, int chunk_size); int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
/* quiesce moves between quiescence states /* quiesce moves between quiescence states
* 0 - fully active * 0 - fully active
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment