path: root/block/blk-mq-tag.h
diff options
authorJens Axboe <>2014-05-13 15:10:52 -0600
committerJens Axboe <>2014-05-13 15:10:52 -0600
commit0d2602ca30e410e84e8bdf05c84ed5688e0a5a44 (patch)
treea456339b9271a400a63aa6defddc85d3eebb95f8 /block/blk-mq-tag.h
parent1f236ab22ce3bc5d4f975aa116966c0ea7ec2013 (diff)
blk-mq: improve support for shared tags maps
This adds support for active queue tracking, meaning that the blk-mq tagging maintains a count of active users of a tag set. This allows us to maintain a notion of fairness between users, so that we can distribute the tag depth evenly without starving some users while allowing others to try unfair deep queues. If sharing of a tag set is detected, each hardware queue will track the depth of its own queue. And if this exceeds the total depth divided by the number of active queues, the user is actively throttled down. The active queue count is done lazily to avoid bouncing that data between submitter and completer. Each hardware queue gets marked active when it allocates its first tag, and gets marked inactive when 1) the last tag is cleared, and 2) the queue timeout grace period has passed. Signed-off-by: Jens Axboe <>
Diffstat (limited to 'block/blk-mq-tag.h')
1 files changed, 24 insertions, 3 deletions
diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h
index 7aa9f0665489..0f5ec8b50ef3 100644
--- a/block/blk-mq-tag.h
+++ b/block/blk-mq-tag.h
@@ -38,6 +38,8 @@ struct blk_mq_tags {
unsigned int nr_tags;
unsigned int nr_reserved_tags;
+ atomic_t active_queues;
struct blk_mq_bitmap_tags bitmap_tags;
struct blk_mq_bitmap_tags breserved_tags;
@@ -49,9 +51,9 @@ struct blk_mq_tags {
extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, unsigned int reserved_tags, int node);
extern void blk_mq_free_tags(struct blk_mq_tags *tags);
-extern unsigned int blk_mq_get_tag(struct blk_mq_tags *tags, struct blk_mq_hw_ctx *hctx, unsigned int *last_tag, gfp_t gfp, bool reserved);
-extern void blk_mq_wait_for_tags(struct blk_mq_tags *tags, struct blk_mq_hw_ctx *hctx, bool reserved);
-extern void blk_mq_put_tag(struct blk_mq_tags *tags, unsigned int tag, unsigned int *last_tag);
+extern unsigned int blk_mq_get_tag(struct blk_mq_hw_ctx *hctx, unsigned int *last_tag, gfp_t gfp, bool reserved);
+extern void blk_mq_wait_for_tags(struct blk_mq_hw_ctx *hctx, bool reserved);
+extern void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, unsigned int tag, unsigned int *last_tag);
extern void blk_mq_tag_busy_iter(struct blk_mq_tags *tags, void (*fn)(void *data, unsigned long *), void *data);
extern bool blk_mq_has_free_tags(struct blk_mq_tags *tags);
extern ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page);
@@ -68,4 +70,23 @@ enum {
+extern bool __blk_mq_tag_busy(struct blk_mq_hw_ctx *);
+extern void __blk_mq_tag_idle(struct blk_mq_hw_ctx *);
+static inline bool blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
+ if (!(hctx->flags & BLK_MQ_F_TAG_SHARED))
+ return false;
+ return __blk_mq_tag_busy(hctx);
+static inline void blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx)
+ if (!(hctx->flags & BLK_MQ_F_TAG_SHARED))
+ return;
+ __blk_mq_tag_idle(hctx);