diff options
Diffstat (limited to 'drivers/md/raid5.c')
| -rw-r--r-- | drivers/md/raid5.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2b521ee67dfa..b8a2c5dc67ba 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -3785,7 +3785,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped | |||
| 3785 | conf->reshape_progress < raid5_size(mddev, 0, 0)) { | 3785 | conf->reshape_progress < raid5_size(mddev, 0, 0)) { |
| 3786 | sector_nr = raid5_size(mddev, 0, 0) | 3786 | sector_nr = raid5_size(mddev, 0, 0) |
| 3787 | - conf->reshape_progress; | 3787 | - conf->reshape_progress; |
| 3788 | } else if (mddev->delta_disks > 0 && | 3788 | } else if (mddev->delta_disks >= 0 && |
| 3789 | conf->reshape_progress > 0) | 3789 | conf->reshape_progress > 0) |
| 3790 | sector_nr = conf->reshape_progress; | 3790 | sector_nr = conf->reshape_progress; |
| 3791 | sector_div(sector_nr, new_data_disks); | 3791 | sector_div(sector_nr, new_data_disks); |
| @@ -4509,7 +4509,26 @@ static int run(mddev_t *mddev) | |||
| 4509 | (old_disks-max_degraded)); | 4509 | (old_disks-max_degraded)); |
| 4510 | /* here_old is the first stripe that we might need to read | 4510 | /* here_old is the first stripe that we might need to read |
| 4511 | * from */ | 4511 | * from */ |
| 4512 | if (here_new >= here_old) { | 4512 | if (mddev->delta_disks == 0) { |
| 4513 | /* We cannot be sure it is safe to start an in-place | ||
| 4514 | * reshape. It is only safe if user-space if monitoring | ||
| 4515 | * and taking constant backups. | ||
| 4516 | * mdadm always starts a situation like this in | ||
| 4517 | * readonly mode so it can take control before | ||
| 4518 | * allowing any writes. So just check for that. | ||
| 4519 | */ | ||
| 4520 | if ((here_new * mddev->new_chunk_sectors != | ||
| 4521 | here_old * mddev->chunk_sectors) || | ||
| 4522 | mddev->ro == 0) { | ||
| 4523 | printk(KERN_ERR "raid5: in-place reshape must be started" | ||
| 4524 | " in read-only mode - aborting\n"); | ||
| 4525 | return -EINVAL; | ||
| 4526 | } | ||
| 4527 | } else if (mddev->delta_disks < 0 | ||
| 4528 | ? (here_new * mddev->new_chunk_sectors <= | ||
| 4529 | here_old * mddev->chunk_sectors) | ||
| 4530 | : (here_new * mddev->new_chunk_sectors >= | ||
| 4531 | here_old * mddev->chunk_sectors)) { | ||
| 4513 | /* Reading from the same stripe as writing to - bad */ | 4532 | /* Reading from the same stripe as writing to - bad */ |
| 4514 | printk(KERN_ERR "raid5: reshape_position too early for " | 4533 | printk(KERN_ERR "raid5: reshape_position too early for " |
| 4515 | "auto-recovery - aborting.\n"); | 4534 | "auto-recovery - aborting.\n"); |
| @@ -5078,8 +5097,15 @@ static void raid5_finish_reshape(mddev_t *mddev) | |||
| 5078 | mddev->degraded--; | 5097 | mddev->degraded--; |
| 5079 | for (d = conf->raid_disks ; | 5098 | for (d = conf->raid_disks ; |
| 5080 | d < conf->raid_disks - mddev->delta_disks; | 5099 | d < conf->raid_disks - mddev->delta_disks; |
| 5081 | d++) | 5100 | d++) { |
| 5082 | raid5_remove_disk(mddev, d); | 5101 | mdk_rdev_t *rdev = conf->disks[d].rdev; |
| 5102 | if (rdev && raid5_remove_disk(mddev, d) == 0) { | ||
| 5103 | char nm[20]; | ||
| 5104 | sprintf(nm, "rd%d", rdev->raid_disk); | ||
| 5105 | sysfs_remove_link(&mddev->kobj, nm); | ||
| 5106 | rdev->raid_disk = -1; | ||
| 5107 | } | ||
| 5108 | } | ||
| 5083 | } | 5109 | } |
| 5084 | mddev->layout = conf->algorithm; | 5110 | mddev->layout = conf->algorithm; |
| 5085 | mddev->chunk_sectors = conf->chunk_sectors; | 5111 | mddev->chunk_sectors = conf->chunk_sectors; |
