aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-08-02 20:59:58 -0400
committerNeilBrown <neilb@suse.de>2009-08-02 20:59:58 -0400
commit64bd660b51b2da92e99a5e97349f6558349f11c5 (patch)
treed35be79528dc8730b908e9d78357454ff22aee72 /drivers/md/raid5.c
parente516402c0d4fc02be4af9fa8c18954d4f9deb44e (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.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 659151e5eda..2dc35b4c20a 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 */