On 10/01/14 18:54, Jens Axboe wrote:
> Lets get rid of the blk_mq_tag struct and just have it be an u32 or
> something. We could potentially typedef it, but I'd prefer to just have
> it be an unsigned 32-bit int.
>
> Probably also need some init time safety checks that 16-bits is enough
> to hold BLK_MQ_MAX_DEPTH. Just in case that is ever bumped, or the queue
> prefixing changes.
>
> And I think we need to name this better. Your comment correctly
> describes that this generates a unique tag queue wide, but the name of
> the function implies that we just return the request tag. Most drivers
> wont use this. Perhaps add a queue flag that tells us that we should
> generate these tags and have it setup ala:
>
> u32 blk_mq_unique_rq_tag(struct request *rq)
> {
> struct request_queue *q = rq->q;
> u32 tag = rq->tag & ((1 << 16) - 1);
> struct blk_mq_hw_ctx *hctx;
>
> hctx = q->mq_ops->map_queue(q, rq->mq_ctx->cpu);
> return tag | (hctx->queue_num << 16);
> }
>
> u32 blk_mq_rq_tag(struct request *rq)
> {
> struct request_queue *q = rq->q;
>
> if (q->mq_ops &&
> test_bit(QUEUE_FLAG_UNIQUE_TAGS, &q->queue_flags))
> return blk_mq_unique_rq_tag(rq);
>
> return rq->tag;
> }
Would it be acceptable to let blk_mq_rq_tag() always return the
hardware context number and the per-hctx tag ? Block and SCSI LLD
drivers that do not need the hardware context number can still use
rq->tag. Drivers that need both can use blk_mq_rq_tag(). That way we do
not have to introduce a new queue flag. How about the patch below
(which is still missing a BLK_MQ_MAX_DEPTH check):
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
index c1b9242..8cfbc7b 100644
--- a/block/blk-mq-tag.c
+++ b/block/blk-mq-tag.c
@@ -595,6 +595,30 @@ int blk_mq_tag_update_depth(struct blk_mq_tags *tags,
unsigned int tdepth)
return 0;
}
+/**
+ * blk_mq_rq_tag() - return a tag that is unique queue-wide
+ *
+ * The tag field in struct request is unique per hardware queue but not
+ * queue-wide. Hence this function.
+ *
+ * Note: When called for a non-multiqueue request queue, the hardware context
+ * index is set to zero.
+ */
+u32 blk_mq_rq_tag(struct request *rq)
+{
+ struct request_queue *q = rq->q;
+ struct blk_mq_hw_ctx *hctx;
+ int hwq = 0;
+
+ if (q->mq_ops) {
+ hctx = q->mq_ops->map_queue(q, rq->mq_ctx->cpu);
+ hwq = hctx->queue_num;
+ }
+
+ return blk_mq_build_rq_tag(hwq, rq->tag);
+}
+EXPORT_SYMBOL(blk_mq_rq_tag);
+
ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page)
{
char *orig_page = page;
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index eac4f31..c5be535 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -166,6 +166,19 @@ bool blk_mq_can_queue(struct blk_mq_hw_ctx *);
struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
gfp_t gfp, bool reserved);
struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag);
+u32 blk_mq_rq_tag(struct request *rq);
+static inline u32 blk_mq_build_rq_tag(int hwq, int tag)
+{
+ return (hwq << 16) | (tag & ((1 << 16) - 1));
+}
+static inline u16 blk_mq_rq_tag_to_hwq(u32 rq_tag)
+{
+ return rq_tag >> 16;
+}
+static inline u16 blk_mq_rq_tag_to_tag(u32 rq_tag)
+{
+ return rq_tag & ((1 << 16) - 1);
+}
struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int
ctx_index);
struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_tag_set *,
unsigned int, int);
--
1.8.4.5
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html