diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid5.c | 76 |
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) | |||
4952 | static void raid5_finish_reshape(mddev_t *mddev) | 4956 | static 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 | ||
5081 | static int raid5_reconfig(mddev_t *mddev, int new_layout, int new_chunk) | 5087 | static 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 | |||
5132 | static 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 | }; |
5220 | static struct mdk_personality raid5_personality = | 5256 | static struct mdk_personality raid5_personality = |
5221 | { | 5257 | { |