aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-03-31 00:24:23 -0400
committerNeilBrown <neilb@suse.de>2009-03-31 00:24:23 -0400
commit88ce4930e2b80378d45506ce2c3bb5820e156e85 (patch)
tree75847293ede7cd396b5470c0d1c4f50dc79ff031 /drivers/md/raid5.c
parent7a6613810785872b7c028fba22fc0bae1c91733d (diff)
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: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r--drivers/md/raid5.c76
1 files changed, 56 insertions, 20 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index f7fb2b87ad89..4fdc6d02b447 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4397,9 +4397,7 @@ static int run(mddev_t *mddev)
4397 int old_disks; 4397 int old_disks;
4398 int max_degraded = (mddev->level == 6 ? 2 : 1); 4398 int max_degraded = (mddev->level == 6 ? 2 : 1);
4399 4399
4400 if (mddev->new_level != mddev->level || 4400 if (mddev->new_level != mddev->level) {
4401 mddev->new_layout != mddev->layout ||
4402 mddev->new_chunk != mddev->chunk_size) {
4403 printk(KERN_ERR "raid5: %s: unsupported reshape " 4401 printk(KERN_ERR "raid5: %s: unsupported reshape "
4404 "required - aborting.\n", 4402 "required - aborting.\n",
4405 mdname(mddev)); 4403 mdname(mddev));
@@ -4784,8 +4782,10 @@ static int raid5_check_reshape(mddev_t *mddev)
4784{ 4782{
4785 raid5_conf_t *conf = mddev_to_conf(mddev); 4783 raid5_conf_t *conf = mddev_to_conf(mddev);
4786 4784
4787 if (mddev->delta_disks == 0) 4785 if (mddev->delta_disks == 0 &&
4788 return 0; /* nothing to do */ 4786 mddev->new_layout == mddev->layout &&
4787 mddev->new_chunk == mddev->chunk_size)
4788 return -EINVAL; /* nothing to do */
4789 if (mddev->bitmap) 4789 if (mddev->bitmap)
4790 /* Cannot grow a bitmap yet */ 4790 /* Cannot grow a bitmap yet */
4791 return -EBUSY; 4791 return -EBUSY;
@@ -4860,6 +4860,10 @@ static int raid5_start_reshape(mddev_t *mddev)
4860 spin_lock_irq(&conf->device_lock); 4860 spin_lock_irq(&conf->device_lock);
4861 conf->previous_raid_disks = conf->raid_disks; 4861 conf->previous_raid_disks = conf->raid_disks;
4862 conf->raid_disks += mddev->delta_disks; 4862 conf->raid_disks += mddev->delta_disks;
4863 conf->prev_chunk = conf->chunk_size;
4864 conf->chunk_size = mddev->new_chunk;
4865 conf->prev_algo = conf->algorithm;
4866 conf->algorithm = mddev->new_layout;
4863 if (mddev->delta_disks < 0) 4867 if (mddev->delta_disks < 0)
4864 conf->reshape_progress = raid5_size(mddev, 0, 0); 4868 conf->reshape_progress = raid5_size(mddev, 0, 0);
4865 else 4869 else
@@ -4952,6 +4956,7 @@ static void end_reshape(raid5_conf_t *conf)
4952static void raid5_finish_reshape(mddev_t *mddev) 4956static void raid5_finish_reshape(mddev_t *mddev)
4953{ 4957{
4954 struct block_device *bdev; 4958 struct block_device *bdev;
4959 raid5_conf_t *conf = mddev_to_conf(mddev);
4955 4960
4956 if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { 4961 if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
4957 4962
@@ -4970,7 +4975,6 @@ static void raid5_finish_reshape(mddev_t *mddev)
4970 } 4975 }
4971 } else { 4976 } else {
4972 int d; 4977 int d;
4973 raid5_conf_t *conf = mddev_to_conf(mddev);
4974 mddev->degraded = conf->raid_disks; 4978 mddev->degraded = conf->raid_disks;
4975 for (d = 0; d < conf->raid_disks ; d++) 4979 for (d = 0; d < conf->raid_disks ; d++)
4976 if (conf->disks[d].rdev && 4980 if (conf->disks[d].rdev &&
@@ -4982,6 +4986,8 @@ static void raid5_finish_reshape(mddev_t *mddev)
4982 d++) 4986 d++)
4983 raid5_remove_disk(mddev, d); 4987 raid5_remove_disk(mddev, d);
4984 } 4988 }
4989 mddev->layout = conf->algorithm;
4990 mddev->chunk_size = conf->chunk_size;
4985 mddev->reshape_position = MaxSector; 4991 mddev->reshape_position = MaxSector;
4986 mddev->delta_disks = 0; 4992 mddev->delta_disks = 0;
4987 } 4993 }
@@ -5080,11 +5086,10 @@ static void *raid5_takeover_raid6(mddev_t *mddev)
5080 5086
5081static int raid5_reconfig(mddev_t *mddev, int new_layout, int new_chunk) 5087static int raid5_reconfig(mddev_t *mddev, int new_layout, int new_chunk)
5082{ 5088{
5083 /* Currently the layout and chunk size can only be changed 5089 /* For a 2-drive array, the layout and chunk size can be changed
5084 * for a 2-drive raid array, as in that case no data shuffling 5090 * immediately as not restriping is needed.
5085 * is required. 5091 * For larger arrays we record the new value - after validation
5086 * Later we might validate these and set new_* so a reshape 5092 * to be used by a reshape pass.
5087 * can complete the change.
5088 */ 5093 */
5089 raid5_conf_t *conf = mddev_to_conf(mddev); 5094 raid5_conf_t *conf = mddev_to_conf(mddev);
5090 5095
@@ -5103,19 +5108,49 @@ static int raid5_reconfig(mddev_t *mddev, int new_layout, int new_chunk)
5103 5108
5104 /* They look valid */ 5109 /* They look valid */
5105 5110
5106 if (mddev->raid_disks != 2) 5111 if (mddev->raid_disks == 2) {
5107 return -EINVAL;
5108 5112
5109 if (new_layout >= 0) { 5113 if (new_layout >= 0) {
5110 conf->algorithm = new_layout; 5114 conf->algorithm = new_layout;
5111 mddev->layout = mddev->new_layout = new_layout; 5115 mddev->layout = mddev->new_layout = new_layout;
5116 }
5117 if (new_chunk > 0) {
5118 conf->chunk_size = new_chunk;
5119 mddev->chunk_size = mddev->new_chunk = new_chunk;
5120 }
5121 set_bit(MD_CHANGE_DEVS, &mddev->flags);
5122 md_wakeup_thread(mddev->thread);
5123 } else {
5124 if (new_layout >= 0)
5125 mddev->new_layout = new_layout;
5126 if (new_chunk > 0)
5127 mddev->new_chunk = new_chunk;
5112 } 5128 }
5129 return 0;
5130}
5131
5132static int raid6_reconfig(mddev_t *mddev, int new_layout, int new_chunk)
5133{
5134 if (new_layout >= 0 && !algorithm_valid_raid6(new_layout))
5135 return -EINVAL;
5113 if (new_chunk > 0) { 5136 if (new_chunk > 0) {
5114 conf->chunk_size = new_chunk; 5137 if (new_chunk & (new_chunk-1))
5115 mddev->chunk_size = mddev->new_chunk = new_chunk; 5138 /* not a power of 2 */
5139 return -EINVAL;
5140 if (new_chunk < PAGE_SIZE)
5141 return -EINVAL;
5142 if (mddev->array_sectors & ((new_chunk>>9)-1))
5143 /* not factor of array size */
5144 return -EINVAL;
5116 } 5145 }
5117 set_bit(MD_CHANGE_DEVS, &mddev->flags); 5146
5118 md_wakeup_thread(mddev->thread); 5147 /* They look valid */
5148
5149 if (new_layout >= 0)
5150 mddev->new_layout = new_layout;
5151 if (new_chunk > 0)
5152 mddev->new_chunk = new_chunk;
5153
5119 return 0; 5154 return 0;
5120} 5155}
5121 5156
@@ -5216,6 +5251,7 @@ static struct mdk_personality raid6_personality =
5216#endif 5251#endif
5217 .quiesce = raid5_quiesce, 5252 .quiesce = raid5_quiesce,
5218 .takeover = raid6_takeover, 5253 .takeover = raid6_takeover,
5254 .reconfig = raid6_reconfig,
5219}; 5255};
5220static struct mdk_personality raid5_personality = 5256static struct mdk_personality raid5_personality =
5221{ 5257{