md: move suspend_hi/lo handling into core md code
authorNeilBrown <neilb@suse.com>
Tue, 17 Oct 2017 02:46:43 +0000 (13:46 +1100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Jul 2018 13:30:50 +0000 (15:30 +0200)
commit b3143b9a38d5039bcd1f2d1c94039651bfba8043 upstream.

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: NeilBrown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
Signed-off-by: Jack Wang <jinpu.wang@profitbricks.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid5.c

index ac27fe2..06ad5d7 100644 (file)
@@ -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();
@@ -4849,10 +4864,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);
@@ -4892,10 +4908,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);
index e4e01d3..bd5976a 100644 (file)
@@ -1298,11 +1298,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
@@ -1313,12 +1311,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) ||
-                            !md_cluster_ops->area_resyncing(mddev, WRITE,
+                       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);
index de1ef62..30c1dc1 100644 (file)
@@ -5686,28 +5686,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