diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index 2cafcf11ee8b..3cc14fc76546 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -682,3 +682,51 @@ u32 blk_mq_unique_tag(struct request *rq) (rq->tag & BLK_MQ_UNIQUE_TAG_MASK); } EXPORT_SYMBOL(blk_mq_unique_tag); + +/* Same with blk_mq_unique_tag, but one persistent tag is included */ +u32 blk_mq_unique_static_tag(struct request *rq) +{ + bool use_sched = rq->q->elevator; + u32 tag; + + if (rq == rq->mq_hctx->fq->flush_rq) { + if (use_sched) + tag = rq->mq_hctx->sched_tags->nr_tags; + else + tag = rq->mq_hctx->tags->nr_tags; + } else { + tag = use_sched ? rq->internal_tag : rq->tag; + } + + return (rq->mq_hctx->queue_num << BLK_MQ_UNIQUE_TAG_BITS) | + (tag & BLK_MQ_UNIQUE_TAG_MASK); +} +EXPORT_SYMBOL(blk_mq_unique_static_tag); + +static struct request * +__blk_mq_static_tag_to_rq(const struct blk_mq_hw_ctx *hctx, + const struct blk_mq_tags *tags, u32 tag) +{ + if (tag < tags->nr_tags) + return tags->static_rqs[tag]; + else if (tag == tags->nr_tags) + return hctx->fq->flush_rq; + else + return NULL; +} + +struct request *blk_mq_static_tag_to_req(struct request_queue *q, u32 uniq_tag) +{ + unsigned long hwq = blk_mq_unique_tag_to_hwq(uniq_tag); + u32 tag = blk_mq_unique_tag_to_tag(uniq_tag); + const struct blk_mq_hw_ctx *hctx= xa_load(&q->hctx_table, hwq); + + if (!hctx) + return NULL; + + if (q->elevator) + return __blk_mq_static_tag_to_rq(hctx, hctx->sched_tags, tag); + + return __blk_mq_static_tag_to_rq(hctx, hctx->tags, tag); +} +EXPORT_SYMBOL(blk_mq_static_tag_to_req); diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index b852050d8a96..5be324233c9f 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -201,7 +201,7 @@ static void nbd_requeue_cmd(struct nbd_cmd *cmd) static u64 nbd_cmd_handle(struct nbd_cmd *cmd) { struct request *req = blk_mq_rq_from_pdu(cmd); - u32 tag = blk_mq_unique_tag(req); + u32 tag = blk_mq_unique_static_tag(req); u64 cookie = cmd->cmd_cookie; return (cookie << NBD_COOKIE_BITS) | tag; @@ -818,10 +818,7 @@ static struct nbd_cmd *nbd_handle_reply(struct nbd_device *nbd, int index, handle = be64_to_cpu(reply->cookie); tag = nbd_handle_to_tag(handle); - hwq = blk_mq_unique_tag_to_hwq(tag); - if (hwq < nbd->tag_set.nr_hw_queues) - req = blk_mq_tag_to_rq(nbd->tag_set.tags[hwq], - blk_mq_unique_tag_to_tag(tag)); + req = blk_mq_static_tag_to_req(nbd->disk->queue, tag); if (!req || !blk_mq_request_started(req)) { dev_err(disk_to_dev(nbd->disk), "Unexpected reply (%d) %p\n", tag, req); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 4fecf46ef681..9c4ef3f16a77 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -793,6 +793,8 @@ enum { }; u32 blk_mq_unique_tag(struct request *rq); +u32 blk_mq_unique_static_tag(struct request *rq); +struct request *blk_mq_static_tag_to_req(struct request_queue *q, u32 tag); static inline u16 blk_mq_unique_tag_to_hwq(u32 unique_tag) {