block: add request polling helper
authorKeith Busch <kbusch@kernel.org>
Mon, 12 Jun 2023 19:03:42 +0000 (12:03 -0700)
committerJens Axboe <axboe@kernel.dk>
Wed, 28 Jun 2023 22:09:41 +0000 (16:09 -0600)
Provide a direct request polling will for drivers. The interface does
not require a bio, and can skip the overhead associated with polling
those. The biggest gain from skipping the relatively expensive xarray
lookup unnecessary when you already have the request.

With this, the simple rq/qc conversion functions have only one caller
each, so open code this and remove the helpers.

Signed-off-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Kanchan Joshi <joshi.k@samsung.com>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20230612190343.2087040-2-kbusch@meta.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-mq.c
include/linux/blk-mq.h

index 98eb31ff914de665889b2f4734c12d6ead952263..5504719b970d597d8dd853aab85b495c251d9b28 100644 (file)
@@ -49,17 +49,8 @@ static void blk_mq_request_bypass_insert(struct request *rq,
                blk_insert_t flags);
 static void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                struct list_head *list);
-
-static inline struct blk_mq_hw_ctx *blk_qc_to_hctx(struct request_queue *q,
-               blk_qc_t qc)
-{
-       return xa_load(&q->hctx_table, qc);
-}
-
-static inline blk_qc_t blk_rq_to_qc(struct request *rq)
-{
-       return rq->mq_hctx->queue_num;
-}
+static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
+                        struct io_comp_batch *iob, unsigned int flags);
 
 /*
  * Check if any of the ctx, dispatch list or elevator
@@ -1248,7 +1239,7 @@ void blk_mq_start_request(struct request *rq)
                q->integrity.profile->prepare_fn(rq);
 #endif
        if (rq->bio && rq->bio->bi_opf & REQ_POLLED)
-               WRITE_ONCE(rq->bio->bi_cookie, blk_rq_to_qc(rq));
+               WRITE_ONCE(rq->bio->bi_cookie, rq->mq_hctx->queue_num);
 }
 EXPORT_SYMBOL(blk_mq_start_request);
 
@@ -1354,7 +1345,7 @@ EXPORT_SYMBOL_GPL(blk_rq_is_poll);
 static void blk_rq_poll_completion(struct request *rq, struct completion *wait)
 {
        do {
-               blk_mq_poll(rq->q, blk_rq_to_qc(rq), NULL, 0);
+               blk_hctx_poll(rq->q, rq->mq_hctx, NULL, 0);
                cond_resched();
        } while (!completion_done(wait));
 }
@@ -4749,10 +4740,9 @@ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
 }
 EXPORT_SYMBOL_GPL(blk_mq_update_nr_hw_queues);
 
-int blk_mq_poll(struct request_queue *q, blk_qc_t cookie, struct io_comp_batch *iob,
-               unsigned int flags)
+static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
+                        struct io_comp_batch *iob, unsigned int flags)
 {
-       struct blk_mq_hw_ctx *hctx = blk_qc_to_hctx(q, cookie);
        long state = get_current_state();
        int ret;
 
@@ -4777,6 +4767,32 @@ int blk_mq_poll(struct request_queue *q, blk_qc_t cookie, struct io_comp_batch *
        return 0;
 }
 
+int blk_mq_poll(struct request_queue *q, blk_qc_t cookie,
+               struct io_comp_batch *iob, unsigned int flags)
+{
+       struct blk_mq_hw_ctx *hctx = xa_load(&q->hctx_table, cookie);
+
+       return blk_hctx_poll(q, hctx, iob, flags);
+}
+
+int blk_rq_poll(struct request *rq, struct io_comp_batch *iob,
+               unsigned int poll_flags)
+{
+       struct request_queue *q = rq->q;
+       int ret;
+
+       if (!blk_rq_is_poll(rq))
+               return 0;
+       if (!percpu_ref_tryget(&q->q_usage_counter))
+               return 0;
+
+       ret = blk_hctx_poll(q, rq->mq_hctx, iob, poll_flags);
+       blk_queue_exit(q);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(blk_rq_poll);
+
 unsigned int blk_mq_rq_cpu(struct request *rq)
 {
        return rq->mq_ctx->cpu;
index aaed687a454c38e83a386e5ac20595e7a351ec0b..2b7fb8e87793caa7d1a7cf6b5be972ed2d959a2b 100644 (file)
@@ -715,6 +715,8 @@ int blk_mq_alloc_sq_tag_set(struct blk_mq_tag_set *set,
 void blk_mq_free_tag_set(struct blk_mq_tag_set *set);
 
 void blk_mq_free_request(struct request *rq);
+int blk_rq_poll(struct request *rq, struct io_comp_batch *iob,
+               unsigned int poll_flags);
 
 bool blk_mq_queue_inflight(struct request_queue *q);