Commit 88ce4930 authored by NeilBrown's avatar NeilBrown

md/raid5: allow layout and chunksize to be changed on active array.

If an array has 3 or more devices, we allow the chunksize or layout
to be changed and when a reshape starts, we use these as the 'new'
values.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent 7a661381
...@@ -4397,9 +4397,7 @@ static int run(mddev_t *mddev) ...@@ -4397,9 +4397,7 @@ static int run(mddev_t *mddev)
int old_disks; int old_disks;
int max_degraded = (mddev->level == 6 ? 2 : 1); int max_degraded = (mddev->level == 6 ? 2 : 1);
if (mddev->new_level != mddev->level || if (mddev->new_level != mddev->level) {
mddev->new_layout != mddev->layout ||
mddev->new_chunk != mddev->chunk_size) {
printk(KERN_ERR "raid5: %s: unsupported reshape " printk(KERN_ERR "raid5: %s: unsupported reshape "
"required - aborting.\n", "required - aborting.\n",
mdname(mddev)); mdname(mddev));
...@@ -4784,8 +4782,10 @@ static int raid5_check_reshape(mddev_t *mddev) ...@@ -4784,8 +4782,10 @@ static int raid5_check_reshape(mddev_t *mddev)
{ {
raid5_conf_t *conf = mddev_to_conf(mddev); raid5_conf_t *conf = mddev_to_conf(mddev);
if (mddev->delta_disks == 0) if (mddev->delta_disks == 0 &&
return 0; /* nothing to do */ mddev->new_layout == mddev->layout &&
mddev->new_chunk == mddev->chunk_size)
return -EINVAL; /* nothing to do */
if (mddev->bitmap) if (mddev->bitmap)
/* Cannot grow a bitmap yet */ /* Cannot grow a bitmap yet */
return -EBUSY; return -EBUSY;
...@@ -4860,6 +4860,10 @@ static int raid5_start_reshape(mddev_t *mddev) ...@@ -4860,6 +4860,10 @@ static int raid5_start_reshape(mddev_t *mddev)
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 += mddev->delta_disks; conf->raid_disks += mddev->delta_disks;
conf->prev_chunk = conf->chunk_size;
conf->chunk_size = mddev->new_chunk;
conf->prev_algo = conf->algorithm;
conf->algorithm = mddev->new_layout;
if (mddev->delta_disks < 0) if (mddev->delta_disks < 0)
conf->reshape_progress = raid5_size(mddev, 0, 0); conf->reshape_progress = raid5_size(mddev, 0, 0);
else else
...@@ -4952,6 +4956,7 @@ static void end_reshape(raid5_conf_t *conf) ...@@ -4952,6 +4956,7 @@ static void end_reshape(raid5_conf_t *conf)
static void raid5_finish_reshape(mddev_t *mddev) static void raid5_finish_reshape(mddev_t *mddev)
{ {
struct block_device *bdev; struct block_device *bdev;
raid5_conf_t *conf = mddev_to_conf(mddev);
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
...@@ -4970,7 +4975,6 @@ static void raid5_finish_reshape(mddev_t *mddev) ...@@ -4970,7 +4975,6 @@ static void raid5_finish_reshape(mddev_t *mddev)
} }
} else { } else {
int d; int d;
raid5_conf_t *conf = mddev_to_conf(mddev);
mddev->degraded = conf->raid_disks; mddev->degraded = conf->raid_disks;
for (d = 0; d < conf->raid_disks ; d++) for (d = 0; d < conf->raid_disks ; d++)
if (conf->disks[d].rdev && if (conf->disks[d].rdev &&
...@@ -4982,6 +4986,8 @@ static void raid5_finish_reshape(mddev_t *mddev) ...@@ -4982,6 +4986,8 @@ static void raid5_finish_reshape(mddev_t *mddev)
d++) d++)
raid5_remove_disk(mddev, d); raid5_remove_disk(mddev, d);
} }
mddev->layout = conf->algorithm;
mddev->chunk_size = conf->chunk_size;
mddev->reshape_position = MaxSector; mddev->reshape_position = MaxSector;
mddev->delta_disks = 0; mddev->delta_disks = 0;
} }
...@@ -5080,11 +5086,10 @@ static void *raid5_takeover_raid6(mddev_t *mddev) ...@@ -5080,11 +5086,10 @@ static void *raid5_takeover_raid6(mddev_t *mddev)
static int raid5_reconfig(mddev_t *mddev, int new_layout, int new_chunk) static int raid5_reconfig(mddev_t *mddev, int new_layout, int new_chunk)
{ {
/* Currently the layout and chunk size can only be changed /* For a 2-drive array, the layout and chunk size can be changed
* for a 2-drive raid array, as in that case no data shuffling * immediately as not restriping is needed.
* is required. * For larger arrays we record the new value - after validation
* Later we might validate these and set new_* so a reshape * to be used by a reshape pass.
* can complete the change.
*/ */
raid5_conf_t *conf = mddev_to_conf(mddev); raid5_conf_t *conf = mddev_to_conf(mddev);
...@@ -5103,19 +5108,49 @@ static int raid5_reconfig(mddev_t *mddev, int new_layout, int new_chunk) ...@@ -5103,19 +5108,49 @@ static int raid5_reconfig(mddev_t *mddev, int new_layout, int new_chunk)
/* They look valid */ /* They look valid */
if (mddev->raid_disks != 2) if (mddev->raid_disks == 2) {
return -EINVAL;
if (new_layout >= 0) { if (new_layout >= 0) {
conf->algorithm = new_layout; conf->algorithm = new_layout;
mddev->layout = mddev->new_layout = new_layout; mddev->layout = mddev->new_layout = new_layout;
}
if (new_chunk > 0) {
conf->chunk_size = new_chunk;
mddev->chunk_size = mddev->new_chunk = new_chunk;
}
set_bit(MD_CHANGE_DEVS, &mddev->flags);
md_wakeup_thread(mddev->thread);
} else {
if (new_layout >= 0)
mddev->new_layout = new_layout;
if (new_chunk > 0)
mddev->new_chunk = new_chunk;
} }
return 0;
}
static int raid6_reconfig(mddev_t *mddev, int new_layout, int new_chunk)
{
if (new_layout >= 0 && !algorithm_valid_raid6(new_layout))
return -EINVAL;
if (new_chunk > 0) { if (new_chunk > 0) {
conf->chunk_size = new_chunk; if (new_chunk & (new_chunk-1))
mddev->chunk_size = mddev->new_chunk = new_chunk; /* not a power of 2 */
return -EINVAL;
if (new_chunk < PAGE_SIZE)
return -EINVAL;
if (mddev->array_sectors & ((new_chunk>>9)-1))
/* not factor of array size */
return -EINVAL;
} }
set_bit(MD_CHANGE_DEVS, &mddev->flags);
md_wakeup_thread(mddev->thread); /* They look valid */
if (new_layout >= 0)
mddev->new_layout = new_layout;
if (new_chunk > 0)
mddev->new_chunk = new_chunk;
return 0; return 0;
} }
...@@ -5216,6 +5251,7 @@ static struct mdk_personality raid6_personality = ...@@ -5216,6 +5251,7 @@ static struct mdk_personality raid6_personality =
#endif #endif
.quiesce = raid5_quiesce, .quiesce = raid5_quiesce,
.takeover = raid6_takeover, .takeover = raid6_takeover,
.reconfig = raid6_reconfig,
}; };
static struct mdk_personality raid5_personality = static struct mdk_personality raid5_personality =
{ {
......
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