diff options
author | NeilBrown <neilb@suse.de> | 2009-08-02 20:59:58 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-08-02 20:59:58 -0400 |
commit | 64bd660b51b2da92e99a5e97349f6558349f11c5 (patch) | |
tree | d35be79528dc8730b908e9d78357454ff22aee72 /drivers/md/raid5.c | |
parent | e516402c0d4fc02be4af9fa8c18954d4f9deb44e (diff) |
md: allow raid5_quiesce to work properly when reshape is happening.
The ->quiesce method is not supposed to stop resync/recovery/reshape,
just normal IO.
But in raid5 we don't have a way to know which stripes are being
used for normal IO and which for resync etc, so we need to wait for
all stripes to be idle to be sure that all writes have completed.
However reshape keeps at least some stripe busy for an extended period
of time, so a call to raid5_quiesce can block for several seconds
needlessly.
So arrange for reshape etc to pause briefly while raid5_quiesce is
trying to quiesce the array so that the active_stripes count can
drop to zero.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 659151e5eda4..2dc35b4c20ac 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3999,6 +3999,9 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
3999 | return 0; | 3999 | return 0; |
4000 | } | 4000 | } |
4001 | 4001 | ||
4002 | /* Allow raid5_quiesce to complete */ | ||
4003 | wait_event(conf->wait_for_overlap, conf->quiesce != 2); | ||
4004 | |||
4002 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) | 4005 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) |
4003 | return reshape_request(mddev, sector_nr, skipped); | 4006 | return reshape_request(mddev, sector_nr, skipped); |
4004 | 4007 | ||
@@ -5104,12 +5107,18 @@ static void raid5_quiesce(mddev_t *mddev, int state) | |||
5104 | 5107 | ||
5105 | case 1: /* stop all writes */ | 5108 | case 1: /* stop all writes */ |
5106 | spin_lock_irq(&conf->device_lock); | 5109 | spin_lock_irq(&conf->device_lock); |
5107 | conf->quiesce = 1; | 5110 | /* '2' tells resync/reshape to pause so that all |
5111 | * active stripes can drain | ||
5112 | */ | ||
5113 | conf->quiesce = 2; | ||
5108 | wait_event_lock_irq(conf->wait_for_stripe, | 5114 | wait_event_lock_irq(conf->wait_for_stripe, |
5109 | atomic_read(&conf->active_stripes) == 0 && | 5115 | atomic_read(&conf->active_stripes) == 0 && |
5110 | atomic_read(&conf->active_aligned_reads) == 0, | 5116 | atomic_read(&conf->active_aligned_reads) == 0, |
5111 | conf->device_lock, /* nothing */); | 5117 | conf->device_lock, /* nothing */); |
5118 | conf->quiesce = 1; | ||
5112 | spin_unlock_irq(&conf->device_lock); | 5119 | spin_unlock_irq(&conf->device_lock); |
5120 | /* allow reshape to continue */ | ||
5121 | wake_up(&conf->wait_for_overlap); | ||
5113 | break; | 5122 | break; |
5114 | 5123 | ||
5115 | case 0: /* re-enable writes */ | 5124 | case 0: /* re-enable writes */ |