md/raid10: prevent unnecessary calls to wake_up() in fast path
authorYu Kuai <yukuai3@huawei.com>
Fri, 16 Sep 2022 11:34:26 +0000 (19:34 +0800)
committerSong Liu <song@kernel.org>
Thu, 22 Sep 2022 07:05:05 +0000 (00:05 -0700)
Currently, wake_up() is called unconditionally in fast path such as
raid10_make_request(), which will cause lock contention under high
concurrency:

raid10_make_request
 wake_up
  __wake_up_common_lock
   spin_lock_irqsave

Improve performance by only call wake_up() if waitqueue is not empty
in allow_barrier() and raid10_make_request().

Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Guoqing Jiang <guoqing.jiang@linux.dev>
Signed-off-by: Song Liu <song@kernel.org>
drivers/md/raid10.c

index 834a34274976b24c595e39caf38b179d15ed66e4..461c8a79fb9933ebdbb358f0f025ff79215d8273 100644 (file)
@@ -274,6 +274,12 @@ static void put_buf(struct r10bio *r10_bio)
        lower_barrier(conf);
 }
 
+static void wake_up_barrier(struct r10conf *conf)
+{
+       if (wq_has_sleeper(&conf->wait_barrier))
+               wake_up(&conf->wait_barrier);
+}
+
 static void reschedule_retry(struct r10bio *r10_bio)
 {
        unsigned long flags;
@@ -1015,7 +1021,7 @@ static void allow_barrier(struct r10conf *conf)
 {
        if ((atomic_dec_and_test(&conf->nr_pending)) ||
                        (conf->array_freeze_pending))
-               wake_up(&conf->wait_barrier);
+               wake_up_barrier(conf);
 }
 
 static void freeze_array(struct r10conf *conf, int extra)
@@ -1891,7 +1897,7 @@ static bool raid10_make_request(struct mddev *mddev, struct bio *bio)
        __make_request(mddev, bio, sectors);
 
        /* In case raid10d snuck in to freeze_array */
-       wake_up(&conf->wait_barrier);
+       wake_up_barrier(conf);
        return true;
 }