blk-mq: blk_mq_try_issue_directly() should lookup hardware queue
authorJens Axboe <axboe@fb.com>
Fri, 11 Nov 2016 19:24:46 +0000 (12:24 -0700)
committerJens Axboe <axboe@fb.com>
Fri, 11 Nov 2016 19:24:46 +0000 (12:24 -0700)
A previous commit changed this to pass in the hardware queue, but
it was using the wrong hardware queue. Hence a request that was
allocated on one hardware queue ended up being issued on another
one, and that caused IO timeouts and oopses on some drivers. Since
the request holds hardware queue private resources, like a tag,
we can't just issue it on a different hardware queue.

Fixes: 2253efc850c4 ("blk-mq: Move more code into blk_mq_direct_issue_request()")
Signed-off-by: Jens Axboe <axboe@fb.com>
block/blk-mq.c

index d180c98..77110ae 100644 (file)
@@ -1291,11 +1291,11 @@ static struct request *blk_mq_map_request(struct request_queue *q,
        return rq;
 }
 
-static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
-                                     struct request *rq, blk_qc_t *cookie)
+static void blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie)
 {
        int ret;
        struct request_queue *q = rq->q;
+       struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, rq->mq_ctx->cpu);
        struct blk_mq_queue_data bd = {
                .rq = rq,
                .list = NULL,
@@ -1414,11 +1414,11 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
                if (!(data.hctx->flags & BLK_MQ_F_BLOCKING)) {
                        rcu_read_lock();
-                       blk_mq_try_issue_directly(data.hctx, old_rq, &cookie);
+                       blk_mq_try_issue_directly(old_rq, &cookie);
                        rcu_read_unlock();
                } else {
                        srcu_idx = srcu_read_lock(&data.hctx->queue_rq_srcu);
-                       blk_mq_try_issue_directly(data.hctx, old_rq, &cookie);
+                       blk_mq_try_issue_directly(old_rq, &cookie);
                        srcu_read_unlock(&data.hctx->queue_rq_srcu, srcu_idx);
                }
                goto done;