diff options
author | Jens Axboe <axboe@fb.com> | 2017-01-26 20:32:32 +0100 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-01-27 16:20:32 +0100 |
commit | 99cf1dc580f0766825395aae4f60ec1d8438f011 (patch) | |
tree | aba73ea31e8835977afc3c7291af3233afed7113 /block/blk-mq.c | |
parent | blk-mq: fix potential race in queue restart and driver tag allocation (diff) | |
download | linux-99cf1dc580f0766825395aae4f60ec1d8438f011.tar.xz linux-99cf1dc580f0766825395aae4f60ec1d8438f011.zip |
blk-mq: release driver tag on a requeue event
We don't want to hold on to this resource when we have a scheduler
attached.
Signed-off-by: Jens Axboe <axboe@fb.com>
Reviewed-by: Omar Sandoval <osandov@fb.com>
Tested-by: Hannes Reinecke <hare@suse.com>
Diffstat (limited to '')
-rw-r--r-- | block/blk-mq.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c index fd80101c7591..711883384585 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -879,6 +879,21 @@ done: return false; } +static void blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx, + struct request *rq) +{ + if (rq->tag == -1 || rq->internal_tag == -1) + return; + + blk_mq_put_tag(hctx, hctx->tags, rq->mq_ctx, rq->tag); + rq->tag = -1; + + if (rq->rq_flags & RQF_MQ_INFLIGHT) { + rq->rq_flags &= ~RQF_MQ_INFLIGHT; + atomic_dec(&hctx->nr_active); + } +} + /* * If we fail getting a driver tag because all the driver tags are already * assigned and on the dispatch list, BUT the first entry does not have a @@ -951,6 +966,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list) queued++; break; case BLK_MQ_RQ_QUEUE_BUSY: + blk_mq_put_driver_tag(hctx, rq); list_add(&rq->queuelist, list); __blk_mq_requeue_request(rq); break; |