Commit b3143b9a authored by NeilBrown's avatar NeilBrown Committed by Shaohua Li

md: move suspend_hi/lo handling into core md code

responding to ->suspend_lo and ->suspend_hi is similar
to responding to ->suspended.  It is best to wait in
the common core code without incrementing ->active_io.
This allows mddev_suspend()/mddev_resume() to work while
requests are waiting for suspend_lo/hi to change.
This is will be important after a subsequent patch
which uses mddev_suspend() to synchronize updating for
suspend_lo/hi.

So move the code for testing suspend_lo/hi out of raid1.c
and raid5.c, and place it in md.c
Signed-off-by: default avatarNeilBrown <neilb@suse.com>
Signed-off-by: default avatarShaohua Li <shli@fb.com>
parent 52a0d49d
...@@ -266,16 +266,31 @@ static DEFINE_SPINLOCK(all_mddevs_lock); ...@@ -266,16 +266,31 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
* call has finished, the bio has been linked into some internal structure * call has finished, the bio has been linked into some internal structure
* and so is visible to ->quiesce(), so we don't need the refcount any more. * and so is visible to ->quiesce(), so we don't need the refcount any more.
*/ */
static bool is_suspended(struct mddev *mddev, struct bio *bio)
{
if (mddev->suspended)
return true;
if (bio_data_dir(bio) != WRITE)
return false;
if (mddev->suspend_lo >= mddev->suspend_hi)
return false;
if (bio->bi_iter.bi_sector >= mddev->suspend_hi)
return false;
if (bio_end_sector(bio) < mddev->suspend_lo)
return false;
return true;
}
void md_handle_request(struct mddev *mddev, struct bio *bio) void md_handle_request(struct mddev *mddev, struct bio *bio)
{ {
check_suspended: check_suspended:
rcu_read_lock(); rcu_read_lock();
if (mddev->suspended) { if (is_suspended(mddev, bio)) {
DEFINE_WAIT(__wait); DEFINE_WAIT(__wait);
for (;;) { for (;;) {
prepare_to_wait(&mddev->sb_wait, &__wait, prepare_to_wait(&mddev->sb_wait, &__wait,
TASK_UNINTERRUPTIBLE); TASK_UNINTERRUPTIBLE);
if (!mddev->suspended) if (!is_suspended(mddev, bio))
break; break;
rcu_read_unlock(); rcu_read_unlock();
schedule(); schedule();
...@@ -4845,10 +4860,11 @@ suspend_lo_store(struct mddev *mddev, const char *buf, size_t len) ...@@ -4845,10 +4860,11 @@ suspend_lo_store(struct mddev *mddev, const char *buf, size_t len)
goto unlock; goto unlock;
old = mddev->suspend_lo; old = mddev->suspend_lo;
mddev->suspend_lo = new; mddev->suspend_lo = new;
if (new >= old) if (new >= old) {
/* Shrinking suspended region */ /* Shrinking suspended region */
wake_up(&mddev->sb_wait);
mddev->pers->quiesce(mddev, 2); mddev->pers->quiesce(mddev, 2);
else { } else {
/* Expanding suspended region - need to wait */ /* Expanding suspended region - need to wait */
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 1);
mddev->pers->quiesce(mddev, 0); mddev->pers->quiesce(mddev, 0);
...@@ -4888,10 +4904,11 @@ suspend_hi_store(struct mddev *mddev, const char *buf, size_t len) ...@@ -4888,10 +4904,11 @@ suspend_hi_store(struct mddev *mddev, const char *buf, size_t len)
goto unlock; goto unlock;
old = mddev->suspend_hi; old = mddev->suspend_hi;
mddev->suspend_hi = new; mddev->suspend_hi = new;
if (new <= old) if (new <= old) {
/* Shrinking suspended region */ /* Shrinking suspended region */
wake_up(&mddev->sb_wait);
mddev->pers->quiesce(mddev, 2); mddev->pers->quiesce(mddev, 2);
else { } else {
/* Expanding suspended region - need to wait */ /* Expanding suspended region - need to wait */
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 1);
mddev->pers->quiesce(mddev, 0); mddev->pers->quiesce(mddev, 0);
......
...@@ -1310,11 +1310,9 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, ...@@ -1310,11 +1310,9 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
*/ */
if ((bio_end_sector(bio) > mddev->suspend_lo && if (mddev_is_clustered(mddev) &&
bio->bi_iter.bi_sector < mddev->suspend_hi) ||
(mddev_is_clustered(mddev) &&
md_cluster_ops->area_resyncing(mddev, WRITE, md_cluster_ops->area_resyncing(mddev, WRITE,
bio->bi_iter.bi_sector, bio_end_sector(bio)))) { bio->bi_iter.bi_sector, bio_end_sector(bio))) {
/* /*
* As the suspend_* range is controlled by userspace, we want * As the suspend_* range is controlled by userspace, we want
...@@ -1325,12 +1323,10 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, ...@@ -1325,12 +1323,10 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
sigset_t full, old; sigset_t full, old;
prepare_to_wait(&conf->wait_barrier, prepare_to_wait(&conf->wait_barrier,
&w, TASK_INTERRUPTIBLE); &w, TASK_INTERRUPTIBLE);
if ((bio_end_sector(bio) <= mddev->suspend_lo || if (!mddev_is_clustered(mddev) ||
bio->bi_iter.bi_sector >= mddev->suspend_hi) && !md_cluster_ops->area_resyncing(mddev, WRITE,
(!mddev_is_clustered(mddev) ||
!md_cluster_ops->area_resyncing(mddev, WRITE,
bio->bi_iter.bi_sector, bio->bi_iter.bi_sector,
bio_end_sector(bio)))) bio_end_sector(bio)))
break; break;
sigfillset(&full); sigfillset(&full);
sigprocmask(SIG_BLOCK, &full, &old); sigprocmask(SIG_BLOCK, &full, &old);
......
...@@ -5685,28 +5685,6 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi) ...@@ -5685,28 +5685,6 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
goto retry; goto retry;
} }
if (rw == WRITE &&
logical_sector >= mddev->suspend_lo &&
logical_sector < mddev->suspend_hi) {
raid5_release_stripe(sh);
/* As the suspend_* range is controlled by
* userspace, we want an interruptible
* wait.
*/
prepare_to_wait(&conf->wait_for_overlap,
&w, TASK_INTERRUPTIBLE);
if (logical_sector >= mddev->suspend_lo &&
logical_sector < mddev->suspend_hi) {
sigset_t full, old;
sigfillset(&full);
sigprocmask(SIG_BLOCK, &full, &old);
schedule();
sigprocmask(SIG_SETMASK, &old, NULL);
do_prepare = true;
}
goto retry;
}
if (test_bit(STRIPE_EXPANDING, &sh->state) || if (test_bit(STRIPE_EXPANDING, &sh->state) ||
!add_stripe_bio(sh, bi, dd_idx, rw, previous)) { !add_stripe_bio(sh, bi, dd_idx, rw, previous)) {
/* Stripe is busy expanding or /* Stripe is busy expanding or
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment