Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+23 −6
Original line number Diff line number Diff line
@@ -266,16 +266,31 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
 * 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.
 */
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)
{
check_suspended:
	rcu_read_lock();
	if (mddev->suspended) {
	if (is_suspended(mddev, bio)) {
		DEFINE_WAIT(__wait);
		for (;;) {
			prepare_to_wait(&mddev->sb_wait, &__wait,
					TASK_UNINTERRUPTIBLE);
			if (!mddev->suspended)
			if (!is_suspended(mddev, bio))
				break;
			rcu_read_unlock();
			schedule();
@@ -4845,10 +4860,11 @@ suspend_lo_store(struct mddev *mddev, const char *buf, size_t len)
		goto unlock;
	old = mddev->suspend_lo;
	mddev->suspend_lo = new;
	if (new >= old)
	if (new >= old) {
		/* Shrinking suspended region */
		wake_up(&mddev->sb_wait);
		mddev->pers->quiesce(mddev, 2);
	else {
	} else {
		/* Expanding suspended region - need to wait */
		mddev->pers->quiesce(mddev, 1);
		mddev->pers->quiesce(mddev, 0);
@@ -4888,10 +4904,11 @@ suspend_hi_store(struct mddev *mddev, const char *buf, size_t len)
		goto unlock;
	old = mddev->suspend_hi;
	mddev->suspend_hi = new;
	if (new <= old)
	if (new <= old) {
		/* Shrinking suspended region */
		wake_up(&mddev->sb_wait);
		mddev->pers->quiesce(mddev, 2);
	else {
	} else {
		/* Expanding suspended region - need to wait */
		mddev->pers->quiesce(mddev, 1);
		mddev->pers->quiesce(mddev, 0);
+5 −9
Original line number Diff line number Diff line
@@ -1310,11 +1310,9 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
	 */


	if ((bio_end_sector(bio) > mddev->suspend_lo &&
	    bio->bi_iter.bi_sector < mddev->suspend_hi) ||
	    (mddev_is_clustered(mddev) &&
	if (mddev_is_clustered(mddev) &&
	     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
@@ -1325,12 +1323,10 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
			sigset_t full, old;
			prepare_to_wait(&conf->wait_barrier,
					&w, TASK_INTERRUPTIBLE);
			if ((bio_end_sector(bio) <= mddev->suspend_lo ||
			     bio->bi_iter.bi_sector >= mddev->suspend_hi) &&
			    (!mddev_is_clustered(mddev) ||
			if (!mddev_is_clustered(mddev) ||
			    !md_cluster_ops->area_resyncing(mddev, WRITE,
							bio->bi_iter.bi_sector,
							bio_end_sector(bio))))
							bio_end_sector(bio)))
				break;
			sigfillset(&full);
			sigprocmask(SIG_BLOCK, &full, &old);
+0 −22
Original line number Diff line number Diff line
@@ -5685,28 +5685,6 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
				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) ||
			    !add_stripe_bio(sh, bi, dd_idx, rw, previous)) {
				/* Stripe is busy expanding or