Commit d263ed99 authored by Jianchao Wang's avatar Jianchao Wang Committed by Jens Axboe

blk-mq: count the hctx as active before allocating tag

Currently, we count the hctx as active after allocate driver tag
successfully. If a previously inactive hctx try to get tag first
time, it may fails and need to wait. However, due to the stale tag
->active_queues, the other shared-tags users are still able to
occupy all driver tags while there is someone waiting for tag.
Consequently, even if the previously inactive hctx is waked up, it
still may not be able to get a tag and could be starved.

To fix it, we count the hctx as active before try to allocate driver
tag, then when it is waiting the tag, the other shared-tag users
will reserve budget for it.
Reviewed-by: default avatarMing Lei <ming.lei@redhat.com>
Signed-off-by: default avatarJianchao Wang <jianchao.w.wang@oracle.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent d6c02a9b
...@@ -23,6 +23,9 @@ bool blk_mq_has_free_tags(struct blk_mq_tags *tags) ...@@ -23,6 +23,9 @@ bool blk_mq_has_free_tags(struct blk_mq_tags *tags)
/* /*
* If a previously inactive queue goes active, bump the active user count. * If a previously inactive queue goes active, bump the active user count.
* We need to do this before try to allocate driver tag, then even if fail
* to get tag when first time, the other shared-tag users could reserve
* budget for it.
*/ */
bool __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) bool __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
{ {
......
...@@ -285,7 +285,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, ...@@ -285,7 +285,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
rq->tag = -1; rq->tag = -1;
rq->internal_tag = tag; rq->internal_tag = tag;
} else { } else {
if (blk_mq_tag_busy(data->hctx)) { if (data->hctx->flags & BLK_MQ_F_TAG_SHARED) {
rq_flags = RQF_MQ_INFLIGHT; rq_flags = RQF_MQ_INFLIGHT;
atomic_inc(&data->hctx->nr_active); atomic_inc(&data->hctx->nr_active);
} }
...@@ -367,6 +367,8 @@ static struct request *blk_mq_get_request(struct request_queue *q, ...@@ -367,6 +367,8 @@ static struct request *blk_mq_get_request(struct request_queue *q,
if (!op_is_flush(op) && e->type->ops.mq.limit_depth && if (!op_is_flush(op) && e->type->ops.mq.limit_depth &&
!(data->flags & BLK_MQ_REQ_RESERVED)) !(data->flags & BLK_MQ_REQ_RESERVED))
e->type->ops.mq.limit_depth(op, data); e->type->ops.mq.limit_depth(op, data);
} else {
blk_mq_tag_busy(data->hctx);
} }
tag = blk_mq_get_tag(data); tag = blk_mq_get_tag(data);
...@@ -971,6 +973,7 @@ bool blk_mq_get_driver_tag(struct request *rq) ...@@ -971,6 +973,7 @@ bool blk_mq_get_driver_tag(struct request *rq)
.hctx = blk_mq_map_queue(rq->q, rq->mq_ctx->cpu), .hctx = blk_mq_map_queue(rq->q, rq->mq_ctx->cpu),
.flags = BLK_MQ_REQ_NOWAIT, .flags = BLK_MQ_REQ_NOWAIT,
}; };
bool shared;
if (rq->tag != -1) if (rq->tag != -1)
goto done; goto done;
...@@ -978,9 +981,10 @@ bool blk_mq_get_driver_tag(struct request *rq) ...@@ -978,9 +981,10 @@ bool blk_mq_get_driver_tag(struct request *rq)
if (blk_mq_tag_is_reserved(data.hctx->sched_tags, rq->internal_tag)) if (blk_mq_tag_is_reserved(data.hctx->sched_tags, rq->internal_tag))
data.flags |= BLK_MQ_REQ_RESERVED; data.flags |= BLK_MQ_REQ_RESERVED;
shared = blk_mq_tag_busy(data.hctx);
rq->tag = blk_mq_get_tag(&data); rq->tag = blk_mq_get_tag(&data);
if (rq->tag >= 0) { if (rq->tag >= 0) {
if (blk_mq_tag_busy(data.hctx)) { if (shared) {
rq->rq_flags |= RQF_MQ_INFLIGHT; rq->rq_flags |= RQF_MQ_INFLIGHT;
atomic_inc(&data.hctx->nr_active); atomic_inc(&data.hctx->nr_active);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment