aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c67
-rw-r--r--drivers/md/md.h1
-rw-r--r--drivers/md/raid5.c23
-rw-r--r--include/linux/raid/md_p.h7
4 files changed, 84 insertions, 14 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 2b30ffdb81b2..44bb1d52dd4c 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -607,6 +607,7 @@ void mddev_init(struct mddev *mddev)
607 init_waitqueue_head(&mddev->sb_wait); 607 init_waitqueue_head(&mddev->sb_wait);
608 init_waitqueue_head(&mddev->recovery_wait); 608 init_waitqueue_head(&mddev->recovery_wait);
609 mddev->reshape_position = MaxSector; 609 mddev->reshape_position = MaxSector;
610 mddev->reshape_backwards = 0;
610 mddev->resync_min = 0; 611 mddev->resync_min = 0;
611 mddev->resync_max = MaxSector; 612 mddev->resync_max = MaxSector;
612 mddev->level = LEVEL_NONE; 613 mddev->level = LEVEL_NONE;
@@ -1185,6 +1186,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
1185 mddev->events = ev1; 1186 mddev->events = ev1;
1186 mddev->bitmap_info.offset = 0; 1187 mddev->bitmap_info.offset = 0;
1187 mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; 1188 mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9;
1189 mddev->reshape_backwards = 0;
1188 1190
1189 if (mddev->minor_version >= 91) { 1191 if (mddev->minor_version >= 91) {
1190 mddev->reshape_position = sb->reshape_position; 1192 mddev->reshape_position = sb->reshape_position;
@@ -1192,6 +1194,8 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
1192 mddev->new_level = sb->new_level; 1194 mddev->new_level = sb->new_level;
1193 mddev->new_layout = sb->new_layout; 1195 mddev->new_layout = sb->new_layout;
1194 mddev->new_chunk_sectors = sb->new_chunk >> 9; 1196 mddev->new_chunk_sectors = sb->new_chunk >> 9;
1197 if (mddev->delta_disks < 0)
1198 mddev->reshape_backwards = 1;
1195 } else { 1199 } else {
1196 mddev->reshape_position = MaxSector; 1200 mddev->reshape_position = MaxSector;
1197 mddev->delta_disks = 0; 1201 mddev->delta_disks = 0;
@@ -1645,7 +1649,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
1645 mddev->events = ev1; 1649 mddev->events = ev1;
1646 mddev->bitmap_info.offset = 0; 1650 mddev->bitmap_info.offset = 0;
1647 mddev->bitmap_info.default_offset = 1024 >> 9; 1651 mddev->bitmap_info.default_offset = 1024 >> 9;
1648 1652 mddev->reshape_backwards = 0;
1653
1649 mddev->recovery_cp = le64_to_cpu(sb->resync_offset); 1654 mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
1650 memcpy(mddev->uuid, sb->set_uuid, 16); 1655 memcpy(mddev->uuid, sb->set_uuid, 16);
1651 1656
@@ -1662,6 +1667,11 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
1662 mddev->new_level = le32_to_cpu(sb->new_level); 1667 mddev->new_level = le32_to_cpu(sb->new_level);
1663 mddev->new_layout = le32_to_cpu(sb->new_layout); 1668 mddev->new_layout = le32_to_cpu(sb->new_layout);
1664 mddev->new_chunk_sectors = le32_to_cpu(sb->new_chunk); 1669 mddev->new_chunk_sectors = le32_to_cpu(sb->new_chunk);
1670 if (mddev->delta_disks < 0 ||
1671 (mddev->delta_disks == 0 &&
1672 (le32_to_cpu(sb->feature_map)
1673 & MD_FEATURE_RESHAPE_BACKWARDS)))
1674 mddev->reshape_backwards = 1;
1665 } else { 1675 } else {
1666 mddev->reshape_position = MaxSector; 1676 mddev->reshape_position = MaxSector;
1667 mddev->delta_disks = 0; 1677 mddev->delta_disks = 0;
@@ -1781,6 +1791,10 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
1781 sb->delta_disks = cpu_to_le32(mddev->delta_disks); 1791 sb->delta_disks = cpu_to_le32(mddev->delta_disks);
1782 sb->new_level = cpu_to_le32(mddev->new_level); 1792 sb->new_level = cpu_to_le32(mddev->new_level);
1783 sb->new_chunk = cpu_to_le32(mddev->new_chunk_sectors); 1793 sb->new_chunk = cpu_to_le32(mddev->new_chunk_sectors);
1794 if (mddev->delta_disks == 0 &&
1795 mddev->reshape_backwards)
1796 sb->feature_map
1797 |= cpu_to_le32(MD_FEATURE_RESHAPE_BACKWARDS);
1784 } 1798 }
1785 1799
1786 if (rdev->badblocks.count == 0) 1800 if (rdev->badblocks.count == 0)
@@ -3419,6 +3433,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
3419 mddev->new_chunk_sectors = mddev->chunk_sectors; 3433 mddev->new_chunk_sectors = mddev->chunk_sectors;
3420 mddev->raid_disks -= mddev->delta_disks; 3434 mddev->raid_disks -= mddev->delta_disks;
3421 mddev->delta_disks = 0; 3435 mddev->delta_disks = 0;
3436 mddev->reshape_backwards = 0;
3422 module_put(pers->owner); 3437 module_put(pers->owner);
3423 printk(KERN_WARNING "md: %s: %s would not accept array\n", 3438 printk(KERN_WARNING "md: %s: %s would not accept array\n",
3424 mdname(mddev), clevel); 3439 mdname(mddev), clevel);
@@ -3492,6 +3507,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
3492 mddev->layout = mddev->new_layout; 3507 mddev->layout = mddev->new_layout;
3493 mddev->chunk_sectors = mddev->new_chunk_sectors; 3508 mddev->chunk_sectors = mddev->new_chunk_sectors;
3494 mddev->delta_disks = 0; 3509 mddev->delta_disks = 0;
3510 mddev->reshape_backwards = 0;
3495 mddev->degraded = 0; 3511 mddev->degraded = 0;
3496 if (mddev->pers->sync_request == NULL) { 3512 if (mddev->pers->sync_request == NULL) {
3497 /* this is now an array without redundancy, so 3513 /* this is now an array without redundancy, so
@@ -3585,6 +3601,7 @@ raid_disks_store(struct mddev *mddev, const char *buf, size_t len)
3585 int olddisks = mddev->raid_disks - mddev->delta_disks; 3601 int olddisks = mddev->raid_disks - mddev->delta_disks;
3586 mddev->delta_disks = n - olddisks; 3602 mddev->delta_disks = n - olddisks;
3587 mddev->raid_disks = n; 3603 mddev->raid_disks = n;
3604 mddev->reshape_backwards = (mddev->delta_disks < 0);
3588 } else 3605 } else
3589 mddev->raid_disks = n; 3606 mddev->raid_disks = n;
3590 return rv ? rv : len; 3607 return rv ? rv : len;
@@ -4436,6 +4453,7 @@ reshape_position_store(struct mddev *mddev, const char *buf, size_t len)
4436 return -EINVAL; 4453 return -EINVAL;
4437 mddev->reshape_position = new; 4454 mddev->reshape_position = new;
4438 mddev->delta_disks = 0; 4455 mddev->delta_disks = 0;
4456 mddev->reshape_backwards = 0;
4439 mddev->new_level = mddev->level; 4457 mddev->new_level = mddev->level;
4440 mddev->new_layout = mddev->layout; 4458 mddev->new_layout = mddev->layout;
4441 mddev->new_chunk_sectors = mddev->chunk_sectors; 4459 mddev->new_chunk_sectors = mddev->chunk_sectors;
@@ -4447,6 +4465,42 @@ __ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show,
4447 reshape_position_store); 4465 reshape_position_store);
4448 4466
4449static ssize_t 4467static ssize_t
4468reshape_direction_show(struct mddev *mddev, char *page)
4469{
4470 return sprintf(page, "%s\n",
4471 mddev->reshape_backwards ? "backwards" : "forwards");
4472}
4473
4474static ssize_t
4475reshape_direction_store(struct mddev *mddev, const char *buf, size_t len)
4476{
4477 int backwards = 0;
4478 if (cmd_match(buf, "forwards"))
4479 backwards = 0;
4480 else if (cmd_match(buf, "backwards"))
4481 backwards = 1;
4482 else
4483 return -EINVAL;
4484 if (mddev->reshape_backwards == backwards)
4485 return len;
4486
4487 /* check if we are allowed to change */
4488 if (mddev->delta_disks)
4489 return -EBUSY;
4490
4491 if (mddev->persistent &&
4492 mddev->major_version == 0)
4493 return -EINVAL;
4494
4495 mddev->reshape_backwards = backwards;
4496 return len;
4497}
4498
4499static struct md_sysfs_entry md_reshape_direction =
4500__ATTR(reshape_direction, S_IRUGO|S_IWUSR, reshape_direction_show,
4501 reshape_direction_store);
4502
4503static ssize_t
4450array_size_show(struct mddev *mddev, char *page) 4504array_size_show(struct mddev *mddev, char *page)
4451{ 4505{
4452 if (mddev->external_size) 4506 if (mddev->external_size)
@@ -4501,6 +4555,7 @@ static struct attribute *md_default_attrs[] = {
4501 &md_safe_delay.attr, 4555 &md_safe_delay.attr,
4502 &md_array_state.attr, 4556 &md_array_state.attr,
4503 &md_reshape_position.attr, 4557 &md_reshape_position.attr,
4558 &md_reshape_direction.attr,
4504 &md_array_size.attr, 4559 &md_array_size.attr,
4505 &max_corr_read_errors.attr, 4560 &max_corr_read_errors.attr,
4506 NULL, 4561 NULL,
@@ -5064,6 +5119,7 @@ static void md_clean(struct mddev *mddev)
5064 mddev->events = 0; 5119 mddev->events = 0;
5065 mddev->can_decrease_events = 0; 5120 mddev->can_decrease_events = 0;
5066 mddev->delta_disks = 0; 5121 mddev->delta_disks = 0;
5122 mddev->reshape_backwards = 0;
5067 mddev->new_level = LEVEL_NONE; 5123 mddev->new_level = LEVEL_NONE;
5068 mddev->new_layout = 0; 5124 mddev->new_layout = 0;
5069 mddev->new_chunk_sectors = 0; 5125 mddev->new_chunk_sectors = 0;
@@ -5888,6 +5944,7 @@ static int set_array_info(struct mddev * mddev, mdu_array_info_t *info)
5888 mddev->new_chunk_sectors = mddev->chunk_sectors; 5944 mddev->new_chunk_sectors = mddev->chunk_sectors;
5889 mddev->new_layout = mddev->layout; 5945 mddev->new_layout = mddev->layout;
5890 mddev->delta_disks = 0; 5946 mddev->delta_disks = 0;
5947 mddev->reshape_backwards = 0;
5891 5948
5892 return 0; 5949 return 0;
5893} 5950}
@@ -5953,10 +6010,16 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks)
5953 if (mddev->sync_thread || mddev->reshape_position != MaxSector) 6010 if (mddev->sync_thread || mddev->reshape_position != MaxSector)
5954 return -EBUSY; 6011 return -EBUSY;
5955 mddev->delta_disks = raid_disks - mddev->raid_disks; 6012 mddev->delta_disks = raid_disks - mddev->raid_disks;
6013 if (mddev->delta_disks < 0)
6014 mddev->reshape_backwards = 1;
6015 else if (mddev->delta_disks > 0)
6016 mddev->reshape_backwards = 0;
5956 6017
5957 rv = mddev->pers->check_reshape(mddev); 6018 rv = mddev->pers->check_reshape(mddev);
5958 if (rv < 0) 6019 if (rv < 0) {
5959 mddev->delta_disks = 0; 6020 mddev->delta_disks = 0;
6021 mddev->reshape_backwards = 0;
6022 }
5960 return rv; 6023 return rv;
5961} 6024}
5962 6025
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 1c2063ccf48e..d51c0ca37777 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -262,6 +262,7 @@ struct mddev {
262 sector_t reshape_position; 262 sector_t reshape_position;
263 int delta_disks, new_level, new_layout; 263 int delta_disks, new_level, new_layout;
264 int new_chunk_sectors; 264 int new_chunk_sectors;
265 int reshape_backwards;
265 266
266 atomic_t plug_cnt; /* If device is expecting 267 atomic_t plug_cnt; /* If device is expecting
267 * more bios soon. 268 * more bios soon.
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index f351422938e0..0abbd3447cfb 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3970,13 +3970,13 @@ static void make_request(struct mddev *mddev, struct bio * bi)
3970 * to check again. 3970 * to check again.
3971 */ 3971 */
3972 spin_lock_irq(&conf->device_lock); 3972 spin_lock_irq(&conf->device_lock);
3973 if (mddev->delta_disks < 0 3973 if (mddev->reshape_backwards
3974 ? logical_sector < conf->reshape_progress 3974 ? logical_sector < conf->reshape_progress
3975 : logical_sector >= conf->reshape_progress) { 3975 : logical_sector >= conf->reshape_progress) {
3976 disks = conf->previous_raid_disks; 3976 disks = conf->previous_raid_disks;
3977 previous = 1; 3977 previous = 1;
3978 } else { 3978 } else {
3979 if (mddev->delta_disks < 0 3979 if (mddev->reshape_backwards
3980 ? logical_sector < conf->reshape_safe 3980 ? logical_sector < conf->reshape_safe
3981 : logical_sector >= conf->reshape_safe) { 3981 : logical_sector >= conf->reshape_safe) {
3982 spin_unlock_irq(&conf->device_lock); 3982 spin_unlock_irq(&conf->device_lock);
@@ -4009,7 +4009,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
4009 */ 4009 */
4010 int must_retry = 0; 4010 int must_retry = 0;
4011 spin_lock_irq(&conf->device_lock); 4011 spin_lock_irq(&conf->device_lock);
4012 if (mddev->delta_disks < 0 4012 if (mddev->reshape_backwards
4013 ? logical_sector >= conf->reshape_progress 4013 ? logical_sector >= conf->reshape_progress
4014 : logical_sector < conf->reshape_progress) 4014 : logical_sector < conf->reshape_progress)
4015 /* mismatch, need to try again */ 4015 /* mismatch, need to try again */
@@ -4108,11 +4108,11 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
4108 4108
4109 if (sector_nr == 0) { 4109 if (sector_nr == 0) {
4110 /* If restarting in the middle, skip the initial sectors */ 4110 /* If restarting in the middle, skip the initial sectors */
4111 if (mddev->delta_disks < 0 && 4111 if (mddev->reshape_backwards &&
4112 conf->reshape_progress < raid5_size(mddev, 0, 0)) { 4112 conf->reshape_progress < raid5_size(mddev, 0, 0)) {
4113 sector_nr = raid5_size(mddev, 0, 0) 4113 sector_nr = raid5_size(mddev, 0, 0)
4114 - conf->reshape_progress; 4114 - conf->reshape_progress;
4115 } else if (mddev->delta_disks >= 0 && 4115 } else if (!mddev->reshape_backwards &&
4116 conf->reshape_progress > 0) 4116 conf->reshape_progress > 0)
4117 sector_nr = conf->reshape_progress; 4117 sector_nr = conf->reshape_progress;
4118 sector_div(sector_nr, new_data_disks); 4118 sector_div(sector_nr, new_data_disks);
@@ -4147,7 +4147,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
4147 sector_div(readpos, data_disks); 4147 sector_div(readpos, data_disks);
4148 safepos = conf->reshape_safe; 4148 safepos = conf->reshape_safe;
4149 sector_div(safepos, data_disks); 4149 sector_div(safepos, data_disks);
4150 if (mddev->delta_disks < 0) { 4150 if (mddev->reshape_backwards) {
4151 writepos -= min_t(sector_t, reshape_sectors, writepos); 4151 writepos -= min_t(sector_t, reshape_sectors, writepos);
4152 readpos += reshape_sectors; 4152 readpos += reshape_sectors;
4153 safepos += reshape_sectors; 4153 safepos += reshape_sectors;
@@ -4174,7 +4174,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
4174 * Maybe that number should be configurable, but I'm not sure it is 4174 * Maybe that number should be configurable, but I'm not sure it is
4175 * worth it.... maybe it could be a multiple of safemode_delay??? 4175 * worth it.... maybe it could be a multiple of safemode_delay???
4176 */ 4176 */
4177 if ((mddev->delta_disks < 0 4177 if ((mddev->reshape_backwards
4178 ? (safepos > writepos && readpos < writepos) 4178 ? (safepos > writepos && readpos < writepos)
4179 : (safepos < writepos && readpos > writepos)) || 4179 : (safepos < writepos && readpos > writepos)) ||
4180 time_after(jiffies, conf->reshape_checkpoint + 10*HZ)) { 4180 time_after(jiffies, conf->reshape_checkpoint + 10*HZ)) {
@@ -4195,7 +4195,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
4195 sysfs_notify(&mddev->kobj, NULL, "sync_completed"); 4195 sysfs_notify(&mddev->kobj, NULL, "sync_completed");
4196 } 4196 }
4197 4197
4198 if (mddev->delta_disks < 0) { 4198 if (mddev->reshape_backwards) {
4199 BUG_ON(conf->reshape_progress == 0); 4199 BUG_ON(conf->reshape_progress == 0);
4200 stripe_addr = writepos; 4200 stripe_addr = writepos;
4201 BUG_ON((mddev->dev_sectors & 4201 BUG_ON((mddev->dev_sectors &
@@ -4239,7 +4239,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
4239 list_add(&sh->lru, &stripes); 4239 list_add(&sh->lru, &stripes);
4240 } 4240 }
4241 spin_lock_irq(&conf->device_lock); 4241 spin_lock_irq(&conf->device_lock);
4242 if (mddev->delta_disks < 0) 4242 if (mddev->reshape_backwards)
4243 conf->reshape_progress -= reshape_sectors * new_data_disks; 4243 conf->reshape_progress -= reshape_sectors * new_data_disks;
4244 else 4244 else
4245 conf->reshape_progress += reshape_sectors * new_data_disks; 4245 conf->reshape_progress += reshape_sectors * new_data_disks;
@@ -5008,7 +5008,7 @@ static int run(struct mddev *mddev)
5008 mdname(mddev)); 5008 mdname(mddev));
5009 return -EINVAL; 5009 return -EINVAL;
5010 } 5010 }
5011 } else if (mddev->delta_disks < 0 5011 } else if (mddev->reshape_backwards
5012 ? (here_new * mddev->new_chunk_sectors <= 5012 ? (here_new * mddev->new_chunk_sectors <=
5013 here_old * mddev->chunk_sectors) 5013 here_old * mddev->chunk_sectors)
5014 : (here_new * mddev->new_chunk_sectors >= 5014 : (here_new * mddev->new_chunk_sectors >=
@@ -5535,7 +5535,7 @@ static int raid5_start_reshape(struct mddev *mddev)
5535 conf->chunk_sectors = mddev->new_chunk_sectors; 5535 conf->chunk_sectors = mddev->new_chunk_sectors;
5536 conf->prev_algo = conf->algorithm; 5536 conf->prev_algo = conf->algorithm;
5537 conf->algorithm = mddev->new_layout; 5537 conf->algorithm = mddev->new_layout;
5538 if (mddev->delta_disks < 0) 5538 if (mddev->reshape_backwards)
5539 conf->reshape_progress = raid5_size(mddev, 0, 0); 5539 conf->reshape_progress = raid5_size(mddev, 0, 0);
5540 else 5540 else
5541 conf->reshape_progress = 0; 5541 conf->reshape_progress = 0;
@@ -5663,6 +5663,7 @@ static void raid5_finish_reshape(struct mddev *mddev)
5663 mddev->chunk_sectors = conf->chunk_sectors; 5663 mddev->chunk_sectors = conf->chunk_sectors;
5664 mddev->reshape_position = MaxSector; 5664 mddev->reshape_position = MaxSector;
5665 mddev->delta_disks = 0; 5665 mddev->delta_disks = 0;
5666 mddev->reshape_backwards = 0;
5666 } 5667 }
5667} 5668}
5668 5669
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index 8c0a3adc5df5..07e05f92d050 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -281,10 +281,15 @@ struct mdp_superblock_1 {
281 * active device with same 'role'. 281 * active device with same 'role'.
282 * 'recovery_offset' is also set. 282 * 'recovery_offset' is also set.
283 */ 283 */
284#define MD_FEATURE_RESHAPE_BACKWARDS 32 /* Reshape doesn't change number
285 * of devices, but is going
286 * backwards anyway.
287 */
284#define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \ 288#define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \
285 |MD_FEATURE_RECOVERY_OFFSET \ 289 |MD_FEATURE_RECOVERY_OFFSET \
286 |MD_FEATURE_RESHAPE_ACTIVE \ 290 |MD_FEATURE_RESHAPE_ACTIVE \
287 |MD_FEATURE_BAD_BLOCKS \ 291 |MD_FEATURE_BAD_BLOCKS \
288 |MD_FEATURE_REPLACEMENT) 292 |MD_FEATURE_REPLACEMENT \
293 |MD_FEATURE_RESHAPE_BACKWARDS)
289 294
290#endif 295#endif