diff options
author | NeilBrown <neilb@suse.de> | 2009-03-31 00:21:40 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-03-31 00:21:40 -0400 |
commit | 7a6613810785872b7c028fba22fc0bae1c91733d (patch) | |
tree | b716e9278d42e83c82888d82671062d64fbf0bea /drivers/md/raid5.c | |
parent | e183eaedd53807e33f02ee80573e2833890e1f21 (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.c | 34 |
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 */ |