public inbox for [email protected]
 help / color / mirror / Atom feed
From: Jeffle Xu <[email protected]>
To: [email protected], [email protected]
Cc: [email protected], [email protected], [email protected],
	[email protected], [email protected],
	[email protected], [email protected]
Subject: [PATCH v4 11/12] block: sub-fastpath for bio-based polling
Date: Sat, 20 Feb 2021 19:06:36 +0800	[thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>

Offer one sub-fastpath for bio-based polling when bio submitted to dm
device gets split and enqueued into multiple hw queues, while the IO
submission process has not been migrated to another CPU.

In this case, the IO submission routine will return the CPU number on
which the IO submission happened as the returned cookie, while the
polling routine will only iterate and poll on hw queues that this CPU
number maps, instead of iterating *all* hw queues.

This optimization can dramatically reduce cache ping-pong and thus
improve the polling performance, when multiple hw queues in polling mode
per device could be reserved when there are multiple polling processes.

It will fall back to iterating all hw queues in polling mode, once the
process has ever been migrated to another CPU during the IO submission
phase.

Signed-off-by: Jeffle Xu <[email protected]>
---
 block/blk-core.c          | 24 ++++++++++++++--
 include/linux/blk_types.h | 60 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 82349e3c2a24..e13219908ef8 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -959,7 +959,10 @@ static blk_qc_t __submit_bio(struct bio *bio)
  *
  * Return:
  *   - BLK_QC_T_NONE, no need for IO polling.
- *   - BLK_QC_T_BIO_POLL_ALL, @bio gets split and enqueued into multi hw queues.
+ *   - When @bio gets split and enqueued into multi hw queues, return the
+ *     corresponding CPU number with BLK_QC_T_BIO_POLL_CPU flag set when the
+ *     current process has not been migrated to another CPU,
+ *     BLK_QC_T_BIO_POLL_ALL otherwise.
  *   - Otherwise, @bio is not split, returning the pointer to the corresponding
  *     hw queue that the bio enqueued into as the returned cookie.
  */
@@ -968,13 +971,17 @@ static blk_qc_t __submit_bio_noacct(struct bio *bio)
 	struct bio_list bio_list_on_stack[2];
 	blk_qc_t ret = BLK_QC_T_NONE;
 	struct request_queue *top_q = bio->bi_disk->queue;
-	bool poll_on = test_bit(QUEUE_FLAG_POLL, &top_q->queue_flags);
+	bool orig_poll_on, poll_on;
+	u64 old_nr_migrations;
 
 	BUG_ON(bio->bi_next);
 
 	bio_list_init(&bio_list_on_stack[0]);
 	current->bio_list = bio_list_on_stack;
 
+	orig_poll_on = poll_on = test_bit(QUEUE_FLAG_POLL, &top_q->queue_flags);
+	old_nr_migrations = READ_ONCE(current->se.nr_migrations);
+
 	do {
 		blk_qc_t cookie;
 		struct request_queue *q = bio->bi_disk->queue;
@@ -1002,7 +1009,7 @@ static blk_qc_t __submit_bio_noacct(struct bio *bio)
 				ret = cookie;
 			} else if (ret != cookie) {
 				/* bio gets split and enqueued to multi hctxs */
-				ret = BLK_QC_T_BIO_POLL_ALL;
+				ret = blk_qc_t_get();
 				poll_on = false;
 			}
 		}
@@ -1029,6 +1036,17 @@ static blk_qc_t __submit_bio_noacct(struct bio *bio)
 
 	current->bio_list = NULL;
 
+	/*
+	 * For cases when bio gets split and enqueued into multi hctxs, return
+	 * the corresponding CPU number when current process has not been
+	 * migrated to another CPU. Return BLK_QC_T_BIO_POLL_ALL otherwise,
+	 * falling back to iterating and polling on all hw queues, since split
+	 * bios are submitted to different CPUs in this case.
+	 */
+	if (orig_poll_on != poll_on &&
+	    old_nr_migrations != READ_ONCE(current->se.nr_migrations))
+		ret = BLK_QC_T_BIO_POLL_ALL;
+
 	return ret;
 }
 
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 6f27446ebada..f8d34f02378d 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -557,12 +557,68 @@ static inline bool blk_qc_t_is_internal(blk_qc_t cookie)
 	return (cookie & BLK_QC_T_INTERNAL) != 0;
 }
 
-/* Macros for blk_qc_t used for bio-based polling */
+/*
+ * Macros for blk_qc_t used for bio-based polling.
+ *
+ * 1. When @bio is not split, the returned cookie is actually the pointer to the
+ *    corresponding hw queue that the bio is enqueued into, thus the low two
+ *    bits could be reused as other flags.
+ *    +-----------------------------------------+
+ *    |        struct blk_mq_hw_ctx*        |0|0|
+ *    +-----------------------------------------+
+ *
+ * 2. When @bio gets split and enqueued into multi hw queues, and current
+ *    process has not been migrated to another CPU, the returned cookie actually
+ *    stores the corresponding CPU number on which the IO submission happened,
+ *    Also with BLK_QC_T_BIO_POLL_CPU flag set.
+ *    In this case, bio-based polling could only iterate and poll on hw queues
+ *    that this CPU number maps.
+ *    +-----------------------------------------+
+ *    |         CPU         |               |1| |
+ *    +-----------------------------------------+
+ *                                           ^
+ *                                           BLK_QC_T_BIO_POLL_CPU
+ *
+ * 3. When @bio gets split and enqueued into multi hw queues, and current
+ *    process has ever been migrated to another CPU, the returned cookie is just
+ *    BLK_QC_T_BIO_POLL_ALL flag.
+ *    In this case, bio-based polling should iterate and poll on all hw queues
+ *    in polling mode.
+ *    +-----------------------------------------+
+ *    |                                     | |1|
+ *    +-----------------------------------------+
+ *                                             ^
+ *                                             BLK_QC_T_BIO_POLL_ALL
+ *
+ * 4. Otherwise, return BLK_QC_T_NONE as the cookie.
+ *    No need for IO polling in this case.
+ *    +-----------------------------------------+
+ *    |               BLK_QC_T_NONE             |
+ *    +-----------------------------------------+
+ */
+
+/* The low two bits of cookie for bio-based polling are reused for flags. */
 #define BLK_QC_T_BIO_POLL_ALL	1U
+#define BLK_QC_T_BIO_POLL_CPU	2U
 
 static inline bool blk_qc_t_is_poll_multi(blk_qc_t cookie)
 {
-	return cookie & BLK_QC_T_BIO_POLL_ALL;
+	return cookie & (BLK_QC_T_BIO_POLL_ALL | BLK_QC_T_BIO_POLL_CPU);
+}
+
+static inline bool blk_qc_t_is_poll_cpu(blk_qc_t cookie)
+{
+	return cookie & BLK_QC_T_BIO_POLL_CPU;
+}
+
+static inline blk_qc_t blk_qc_t_get(void)
+{
+	return (raw_smp_processor_id() << BLK_QC_T_SHIFT) | BLK_QC_T_BIO_POLL_CPU;
+}
+
+static inline int blk_qc_t_to_cpu(blk_qc_t cookie)
+{
+	return cookie >> BLK_QC_T_SHIFT;
 }
 
 struct blk_rq_stat {
-- 
2.27.0


  parent reply	other threads:[~2021-02-20 11:07 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-20 11:06 [PATCH v4 00/12] dm: support IO polling Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 01/12] block: move definition of blk_qc_t to types.h Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 02/12] block: add queue_to_disk() to get gendisk from request_queue Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 03/12] block: add poll method to support bio-based IO polling Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 04/12] block: add poll_capable " Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 05/12] blk-mq: extract one helper function polling hw queue Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 06/12] blk-mq: add iterator for polling hw queues Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 07/12] blk-mq: add one helper function getting hw queue Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 08/12] dm: always return BLK_QC_T_NONE for bio-based device Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 09/12] nvme/pci: don't wait for locked polling queue Jeffle Xu
2021-02-20 11:06 ` [PATCH v4 10/12] block: fastpath for bio-based polling Jeffle Xu
2021-02-20 11:06 ` Jeffle Xu [this message]
2021-02-20 11:06 ` [PATCH v4 12/12] dm: support IO polling for bio-based dm device Jeffle Xu
2021-02-23  3:55 ` [PATCH v4 00/12] dm: support IO polling JeffleXu
2021-02-23 20:54   ` Mike Snitzer
2021-02-24  1:44     ` JeffleXu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox