aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-03-31 00:21:40 -0400
committerNeilBrown <neilb@suse.de>2009-03-31 00:21:40 -0400
commit7a6613810785872b7c028fba22fc0bae1c91733d (patch)
treeb716e9278d42e83c82888d82671062d64fbf0bea /drivers/md/raid5.c
parente183eaedd53807e33f02ee80573e2833890e1f21 (diff)
md/raid5: reshape using largest of old and new chunk size
This ensures that even when old and new stripes are overlapping, we will try to read all of the old before having to write any of the new. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r--drivers/md/raid5.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 80ec9a6d8a18..f7fb2b87ad89 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3738,6 +3738,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
3738 int dd_idx; 3738 int dd_idx;
3739 sector_t writepos, safepos, gap; 3739 sector_t writepos, safepos, gap;
3740 sector_t stripe_addr; 3740 sector_t stripe_addr;
3741 int reshape_sectors;
3741 3742
3742 if (sector_nr == 0) { 3743 if (sector_nr == 0) {
3743 /* If restarting in the middle, skip the initial sectors */ 3744 /* If restarting in the middle, skip the initial sectors */
@@ -3755,6 +3756,15 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
3755 } 3756 }
3756 } 3757 }
3757 3758
3759 /* We need to process a full chunk at a time.
3760 * If old and new chunk sizes differ, we need to process the
3761 * largest of these
3762 */
3763 if (mddev->new_chunk > mddev->chunk_size)
3764 reshape_sectors = mddev->new_chunk / 512;
3765 else
3766 reshape_sectors = mddev->chunk_size / 512;
3767
3758 /* we update the metadata when there is more than 3Meg 3768 /* we update the metadata when there is more than 3Meg
3759 * in the block range (that is rather arbitrary, should 3769 * in the block range (that is rather arbitrary, should
3760 * probably be time based) or when the data about to be 3770 * probably be time based) or when the data about to be
@@ -3768,12 +3778,12 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
3768 safepos = conf->reshape_safe; 3778 safepos = conf->reshape_safe;
3769 sector_div(safepos, data_disks); 3779 sector_div(safepos, data_disks);
3770 if (mddev->delta_disks < 0) { 3780 if (mddev->delta_disks < 0) {
3771 writepos -= conf->chunk_size/512; 3781 writepos -= reshape_sectors;
3772 safepos += conf->chunk_size/512; 3782 safepos += reshape_sectors;
3773 gap = conf->reshape_safe - conf->reshape_progress; 3783 gap = conf->reshape_safe - conf->reshape_progress;
3774 } else { 3784 } else {
3775 writepos += conf->chunk_size/512; 3785 writepos += reshape_sectors;
3776 safepos -= conf->chunk_size/512; 3786 safepos -= reshape_sectors;
3777 gap = conf->reshape_progress - conf->reshape_safe; 3787 gap = conf->reshape_progress - conf->reshape_safe;
3778 } 3788 }
3779 3789
@@ -3799,14 +3809,14 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
3799 BUG_ON(conf->reshape_progress == 0); 3809 BUG_ON(conf->reshape_progress == 0);
3800 stripe_addr = writepos; 3810 stripe_addr = writepos;
3801 BUG_ON((mddev->dev_sectors & 3811 BUG_ON((mddev->dev_sectors &
3802 ~((sector_t)conf->chunk_size / 512 - 1)) 3812 ~((sector_t)reshape_sectors - 1))
3803 - (conf->chunk_size / 512) - stripe_addr 3813 - reshape_sectors - stripe_addr
3804 != sector_nr); 3814 != sector_nr);
3805 } else { 3815 } else {
3806 BUG_ON(writepos != sector_nr + conf->chunk_size / 512); 3816 BUG_ON(writepos != sector_nr + reshape_sectors);
3807 stripe_addr = sector_nr; 3817 stripe_addr = sector_nr;
3808 } 3818 }
3809 for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) { 3819 for (i = 0; i < reshape_sectors; i += STRIPE_SECTORS) {
3810 int j; 3820 int j;
3811 int skipped = 0; 3821 int skipped = 0;
3812 sh = get_active_stripe(conf, stripe_addr+i, 0, 0); 3822 sh = get_active_stripe(conf, stripe_addr+i, 0, 0);
@@ -3839,9 +3849,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
3839 } 3849 }
3840 spin_lock_irq(&conf->device_lock); 3850 spin_lock_irq(&conf->device_lock);
3841 if (mddev->delta_disks < 0) 3851 if (mddev->delta_disks < 0)
3842 conf->reshape_progress -= i * new_data_disks; 3852 conf->reshape_progress -= reshape_sectors * new_data_disks;
3843 else 3853 else
3844 conf->reshape_progress += i * new_data_disks; 3854 conf->reshape_progress += reshape_sectors * new_data_disks;
3845 spin_unlock_irq(&conf->device_lock); 3855 spin_unlock_irq(&conf->device_lock);
3846 /* Ok, those stripe are ready. We can start scheduling 3856 /* Ok, those stripe are ready. We can start scheduling
3847 * reads on the source stripes. 3857 * reads on the source stripes.
@@ -3867,7 +3877,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
3867 /* If this takes us to the resync_max point where we have to pause, 3877 /* If this takes us to the resync_max point where we have to pause,
3868 * then we need to write out the superblock. 3878 * then we need to write out the superblock.
3869 */ 3879 */
3870 sector_nr += conf->chunk_size>>9; 3880 sector_nr += reshape_sectors;
3871 if (sector_nr >= mddev->resync_max) { 3881 if (sector_nr >= mddev->resync_max) {
3872 /* Cannot proceed until we've updated the superblock... */ 3882 /* Cannot proceed until we've updated the superblock... */
3873 wait_event(conf->wait_for_overlap, 3883 wait_event(conf->wait_for_overlap,
@@ -3883,7 +3893,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
3883 spin_unlock_irq(&conf->device_lock); 3893 spin_unlock_irq(&conf->device_lock);
3884 wake_up(&conf->wait_for_overlap); 3894 wake_up(&conf->wait_for_overlap);
3885 } 3895 }
3886 return conf->chunk_size>>9; 3896 return reshape_sectors;
3887} 3897}
3888 3898
3889/* FIXME go_faster isn't used */ 3899/* FIXME go_faster isn't used */