aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2017-09-11 18:43:57 -0400
committerJens Axboe <axboe@kernel.dk>2017-09-11 18:43:57 -0400
commit157f377beb710e84bd8bc7a3c4475c0674ebebd7 (patch)
tree4ae9a47f15aab3a6c77d380bdefda5272912ded4
parentbe1c704329a51cbcf019f971c5d2023c0226d9cd (diff)
block: directly insert blk-mq request from blk_insert_cloned_request()
A NULL pointer crash was reported for the case of having the BFQ IO scheduler attached to the underlying blk-mq paths of a DM multipath device. The crash occured in blk_mq_sched_insert_request()'s call to e->type->ops.mq.insert_requests(). Paolo Valente correctly summarized why the crash occured with: "the call chain (dm_mq_queue_rq -> map_request -> setup_clone -> blk_rq_prep_clone) creates a cloned request without invoking e->type->ops.mq.prepare_request for the target elevator e. The cloned request is therefore not initialized for the scheduler, but it is however inserted into the scheduler by blk_mq_sched_insert_request." All said, a request-based DM multipath device's IO scheduler should be the only one used -- when the original requests are issued to the underlying paths as cloned requests they are inserted directly in the underlying dispatch queue(s) rather than through an additional elevator. But commit bd166ef18 ("blk-mq-sched: add framework for MQ capable IO schedulers") switched blk_insert_cloned_request() from using blk_mq_insert_request() to blk_mq_sched_insert_request(). Which incorrectly added elevator machinery into a call chain that isn't supposed to have any. To fix this introduce a blk-mq private blk_mq_request_bypass_insert() that blk_insert_cloned_request() calls to insert the request without involving any elevator that may be attached to the cloned request's request_queue. Fixes: bd166ef183c2 ("blk-mq-sched: add framework for MQ capable IO schedulers") Cc: stable@vger.kernel.org Reported-by: Bart Van Assche <Bart.VanAssche@wdc.com> Tested-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--block/blk-core.c7
-rw-r--r--block/blk-mq.c16
-rw-r--r--block/blk-mq.h1
3 files changed, 23 insertions, 1 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index d709c0e3a2ac..aebe676225e6 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -2342,7 +2342,12 @@ blk_status_t blk_insert_cloned_request(struct request_queue *q, struct request *
2342 if (q->mq_ops) { 2342 if (q->mq_ops) {
2343 if (blk_queue_io_stat(q)) 2343 if (blk_queue_io_stat(q))
2344 blk_account_io_start(rq, true); 2344 blk_account_io_start(rq, true);
2345 blk_mq_sched_insert_request(rq, false, true, false, false); 2345 /*
2346 * Since we have a scheduler attached on the top device,
2347 * bypass a potential scheduler on the bottom device for
2348 * insert.
2349 */
2350 blk_mq_request_bypass_insert(rq);
2346 return BLK_STS_OK; 2351 return BLK_STS_OK;
2347 } 2352 }
2348 2353
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 3f18cff80050..98a18609755e 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1401,6 +1401,22 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
1401 blk_mq_hctx_mark_pending(hctx, ctx); 1401 blk_mq_hctx_mark_pending(hctx, ctx);
1402} 1402}
1403 1403
1404/*
1405 * Should only be used carefully, when the caller knows we want to
1406 * bypass a potential IO scheduler on the target device.
1407 */
1408void blk_mq_request_bypass_insert(struct request *rq)
1409{
1410 struct blk_mq_ctx *ctx = rq->mq_ctx;
1411 struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, ctx->cpu);
1412
1413 spin_lock(&hctx->lock);
1414 list_add_tail(&rq->queuelist, &hctx->dispatch);
1415 spin_unlock(&hctx->lock);
1416
1417 blk_mq_run_hw_queue(hctx, false);
1418}
1419
1404void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, 1420void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
1405 struct list_head *list) 1421 struct list_head *list)
1406 1422
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 98252b79b80b..ef15b3414da5 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -54,6 +54,7 @@ int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
54 */ 54 */
55void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, 55void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
56 bool at_head); 56 bool at_head);
57void blk_mq_request_bypass_insert(struct request *rq);
57void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, 58void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
58 struct list_head *list); 59 struct list_head *list);
59 60