[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: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
b578d55fdd
commit
63c70c4f3a
@@ -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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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 =
|
|||||||
.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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
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 =
|
|||||||
.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
|
|||||||
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
|
||||||
|
|||||||
Reference in New Issue
Block a user