From: Ming Lei <ming.lei@redhat.com>
To: Jens Axboe <axboe@kernel.dk>
Cc: linux-block@vger.kernel.org,
Jeffle Xu <jefflexu@linux.alibaba.com>,
Mike Snitzer <snitzer@redhat.com>,
dm-devel@redhat.com, Hannes Reinecke <hare@suse.de>,
Ming Lei <ming.lei@redhat.com>
Subject: [PATCH V6 07/12] block: create io poll context for submission and poll task
Date: Thu, 22 Apr 2021 20:20:33 +0800 [thread overview]
Message-ID: <20210422122038.2192933-8-ming.lei@redhat.com> (raw)
In-Reply-To: <20210422122038.2192933-1-ming.lei@redhat.com>
Create per-task io poll context for both IO submission and poll task
if the queue is bio based and supports polling.
This io polling context includes two queues:
1) submission queue(sq) for storing HIPRI bio, written by submission task
and read by poll task.
2) polling queue(pq) for holding data moved from sq, only used in poll
context for running bio polling.
Following patches will support bio based io polling.
Reviewed-by: Jeffle Xu <jefflexu@linux.alibaba.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
block/blk-core.c | 24 +++++++++-------
block/blk-ioc.c | 1 +
block/blk-poll.c | 51 +++++++++++++++++++++++++++++++++
block/blk.h | 60 +++++++++++++++++++++++++++++++++++++++
include/linux/iocontext.h | 2 ++
5 files changed, 127 insertions(+), 11 deletions(-)
diff --git a/block/blk-core.c b/block/blk-core.c
index d44a8b934608..5830ef4d733e 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -868,8 +868,19 @@ static noinline_for_stack bool submit_bio_checks(struct bio *bio)
}
}
- if (!blk_queue_poll(q))
- bio->bi_opf &= ~REQ_HIPRI;
+ /*
+ * Various block parts want %current->io_context, so allocate it up
+ * front rather than dealing with lots of pain to allocate it only
+ * where needed. This may fail and the block layer knows how to live
+ * with it.
+ */
+ if (unlikely(!current->io_context))
+ create_task_io_context(current, GFP_ATOMIC, q->node);
+
+ if ((bio->bi_opf & REQ_HIPRI) && blk_queue_support_bio_poll(q))
+ blk_create_io_poll_context(q);
+
+ blk_poll_prepare(q, bio);
switch (bio_op(bio)) {
case REQ_OP_DISCARD:
@@ -908,15 +919,6 @@ static noinline_for_stack bool submit_bio_checks(struct bio *bio)
break;
}
- /*
- * Various block parts want %current->io_context, so allocate it up
- * front rather than dealing with lots of pain to allocate it only
- * where needed. This may fail and the block layer knows how to live
- * with it.
- */
- if (unlikely(!current->io_context))
- create_task_io_context(current, GFP_ATOMIC, q->node);
-
if (blk_throtl_bio(bio)) {
blkcg_bio_issue_init(bio);
return false;
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index b0cde18c4b8c..5574c398eff6 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -19,6 +19,7 @@ static struct kmem_cache *iocontext_cachep;
static inline void free_io_context(struct io_context *ioc)
{
+ kfree(ioc->data);
kmem_cache_free(iocontext_cachep, ioc);
}
diff --git a/block/blk-poll.c b/block/blk-poll.c
index 0a38c25bcee5..8e4bec55293e 100644
--- a/block/blk-poll.c
+++ b/block/blk-poll.c
@@ -4,11 +4,14 @@
#include <linux/blkdev.h>
#include <linux/sched.h>
#include <linux/hrtimer.h>
+#include <linux/bio.h>
#include <linux/blk-mq.h>
#include "blk.h"
#include "blk-mq.h"
+static int blk_bio_poll(struct request_queue *q, blk_qc_t cookie, bool spin);
+
/* Enable polling stats and return whether they were already enabled. */
static bool blk_poll_stats_enable(struct request_queue *q)
{
@@ -165,6 +168,9 @@ int blk_poll(struct request_queue *q, blk_qc_t cookie, bool spin)
if (current->plug)
blk_flush_plug_list(current->plug, false);
+ if (!queue_is_mq(q))
+ return blk_bio_poll(q, cookie, spin);
+
hctx = q->queue_hw_ctx[blk_qc_t_to_queue_num(cookie)];
/*
@@ -204,3 +210,48 @@ int blk_poll(struct request_queue *q, blk_qc_t cookie, bool spin)
return 0;
}
EXPORT_SYMBOL_GPL(blk_poll);
+
+/* bio base io polling */
+static int blk_bio_poll(struct request_queue *q, blk_qc_t cookie, bool spin)
+{
+ /*
+ * Create poll queue for storing poll bio and its cookie from
+ * submission queue
+ */
+ blk_create_io_poll_context(q);
+
+ return 0;
+}
+
+static inline unsigned int bio_grp_list_size(unsigned int nr_grps)
+{
+ return sizeof(struct bio_grp_list) + nr_grps *
+ sizeof(struct bio_grp_list_data);
+}
+
+static void bio_poll_ctx_init(struct blk_bio_poll_ctx *pc)
+{
+ pc->sq = (void *)pc + sizeof(*pc);
+ pc->sq->max_nr_grps = BLK_BIO_POLL_SQ_SZ;
+
+ pc->pq = (void *)pc->sq + bio_grp_list_size(BLK_BIO_POLL_SQ_SZ);
+ pc->pq->max_nr_grps = BLK_BIO_POLL_PQ_SZ;
+
+ spin_lock_init(&pc->sq_lock);
+ spin_lock_init(&pc->pq_lock);
+}
+
+void bio_poll_ctx_alloc(struct io_context *ioc)
+{
+ struct blk_bio_poll_ctx *pc;
+ unsigned int size = sizeof(*pc) +
+ bio_grp_list_size(BLK_BIO_POLL_SQ_SZ) +
+ bio_grp_list_size(BLK_BIO_POLL_PQ_SZ);
+
+ pc = kzalloc(GFP_ATOMIC, size);
+ if (pc) {
+ bio_poll_ctx_init(pc);
+ if (cmpxchg(&ioc->data, NULL, (void *)pc))
+ kfree(pc);
+ }
+}
diff --git a/block/blk.h b/block/blk.h
index d88b0823738c..bc6d63ae36b7 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -352,4 +352,64 @@ int bio_add_hw_page(struct request_queue *q, struct bio *bio,
struct page *page, unsigned int len, unsigned int offset,
unsigned int max_sectors, bool *same_page);
+/* Grouping bios that share same data into one list */
+struct bio_grp_list_data {
+ void *grp_data;
+
+ /* all bios in this list share same 'grp_data' */
+ struct bio_list list;
+};
+
+struct bio_grp_list {
+ unsigned int max_nr_grps, nr_grps;
+ struct bio_grp_list_data head[0];
+};
+
+struct blk_bio_poll_ctx {
+ spinlock_t sq_lock;
+ struct bio_grp_list *sq;
+
+ spinlock_t pq_lock;
+ struct bio_grp_list *pq;
+};
+
+#define BLK_BIO_POLL_SQ_SZ 16U
+#define BLK_BIO_POLL_PQ_SZ (BLK_BIO_POLL_SQ_SZ * 2)
+
+void bio_poll_ctx_alloc(struct io_context *ioc);
+
+static inline bool blk_queue_support_bio_poll(struct request_queue *q)
+{
+ return !queue_is_mq(q) && blk_queue_poll(q);
+}
+
+static inline struct blk_bio_poll_ctx *blk_get_bio_poll_ctx(void)
+{
+ struct io_context *ioc = current->io_context;
+
+ return ioc ? ioc->data : NULL;
+}
+
+static inline void blk_poll_prepare(struct request_queue *q,
+ struct bio *bio)
+{
+ if (!(bio->bi_opf & REQ_HIPRI))
+ return;
+
+ if (!blk_queue_poll(q) || (!queue_is_mq(q) && !blk_get_bio_poll_ctx()))
+ bio->bi_opf &= ~REQ_HIPRI;
+}
+
+static inline void blk_create_io_poll_context(struct request_queue *q)
+{
+ struct io_context *ioc;
+
+ if (unlikely(!current->io_context))
+ create_task_io_context(current, GFP_ATOMIC, q->node);
+
+ ioc = current->io_context;
+ if (unlikely(ioc && !ioc->data))
+ bio_poll_ctx_alloc(ioc);
+}
+
#endif /* BLK_INTERNAL_H */
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index 0a9dc40b7be8..f9a467571356 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -110,6 +110,8 @@ struct io_context {
struct io_cq __rcu *icq_hint;
struct hlist_head icq_list;
+ void *data;
+
struct work_struct release_work;
};
--
2.29.2
next prev parent reply other threads:[~2021-04-22 12:22 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-22 12:20 [PATCH V6 00/12] block: support bio based io polling Ming Lei
2021-04-22 12:20 ` [PATCH V6 01/12] block: add helper of blk_queue_poll Ming Lei
2021-04-22 12:20 ` [PATCH V6 02/12] block: define 'struct bvec_iter' as packed Ming Lei
2021-04-22 13:18 ` Hannes Reinecke
2021-04-22 12:20 ` [PATCH V6 03/12] block: add one helper to free io_context Ming Lei
2021-04-22 12:20 ` [PATCH V6 04/12] block: move block polling code into one dedicated source file Ming Lei
2021-04-22 13:19 ` Hannes Reinecke
2021-04-26 7:12 ` Hannes Reinecke
2021-04-22 12:20 ` [PATCH V6 05/12] block: extract one helper function polling hw queue Ming Lei
2021-04-22 12:20 ` [PATCH V6 06/12] block: prepare for supporting bio_list via other link Ming Lei
2021-04-22 12:20 ` Ming Lei [this message]
2021-04-22 12:20 ` [PATCH V6 08/12] block: add req flag of REQ_POLL_CTX Ming Lei
2021-04-22 12:20 ` [PATCH V6 09/12] block: use per-task poll context to implement bio based io polling Ming Lei
2021-04-26 7:17 ` Hannes Reinecke
2021-04-22 12:20 ` [PATCH V6 10/12] block: limit hw queues to be polled in each blk_poll() Ming Lei
2021-04-26 7:19 ` Hannes Reinecke
2021-04-26 8:00 ` Ming Lei
2021-04-26 9:05 ` Hannes Reinecke
2021-04-22 12:20 ` [PATCH V6 11/12] block: allow to control FLAG_POLL via sysfs for bio poll capable queue Ming Lei
2021-04-26 7:20 ` Hannes Reinecke
2021-04-22 12:20 ` [PATCH V6 12/12] dm: support IO polling for bio-based dm device Ming Lei
2021-04-23 1:32 ` JeffleXu
2021-04-23 2:39 ` Ming Lei
2021-04-23 2:38 ` [PATCH V7 " Ming Lei
2021-05-17 6:16 ` [PATCH V6 00/12] block: support bio based io polling JeffleXu
2021-05-17 7:13 ` Ming Lei
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 \
--in-reply-to=20210422122038.2192933-8-ming.lei@redhat.com \
--to=ming.lei@redhat.com \
--cc=axboe@kernel.dk \
--cc=dm-devel@redhat.com \
--cc=hare@suse.de \
--cc=jefflexu@linux.alibaba.com \
--cc=linux-block@vger.kernel.org \
--cc=snitzer@redhat.com \
/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