Skip to content

Commit f26cdc8

Browse files
Keith Buschaxboe
authored andcommitted
blk-mq: Shared tag enhancements
Storage controllers may expose multiple block devices that share hardware resources managed by blk-mq. This patch enhances the shared tags so a low-level driver can access the shared resources not tied to the unshared h/w contexts. This way the LLD can dynamically add and delete disks and request queues without having to track all the request_queue hctx's to iterate outstanding tags. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Jens Axboe <axboe@fb.com>
1 parent e548ca4 commit f26cdc8

File tree

4 files changed

+53
-2
lines changed

4 files changed

+53
-2
lines changed

block/blk-mq-tag.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,39 @@ static void bt_for_each(struct blk_mq_hw_ctx *hctx,
438438
}
439439
}
440440

441+
static void bt_tags_for_each(struct blk_mq_tags *tags,
442+
struct blk_mq_bitmap_tags *bt, unsigned int off,
443+
busy_tag_iter_fn *fn, void *data, bool reserved)
444+
{
445+
struct request *rq;
446+
int bit, i;
447+
448+
if (!tags->rqs)
449+
return;
450+
for (i = 0; i < bt->map_nr; i++) {
451+
struct blk_align_bitmap *bm = &bt->map[i];
452+
453+
for (bit = find_first_bit(&bm->word, bm->depth);
454+
bit < bm->depth;
455+
bit = find_next_bit(&bm->word, bm->depth, bit + 1)) {
456+
rq = blk_mq_tag_to_rq(tags, off + bit);
457+
fn(rq, data, reserved);
458+
}
459+
460+
off += (1 << bt->bits_per_word);
461+
}
462+
}
463+
464+
void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
465+
void *priv)
466+
{
467+
if (tags->nr_reserved_tags)
468+
bt_tags_for_each(tags, &tags->breserved_tags, 0, fn, priv, true);
469+
bt_tags_for_each(tags, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv,
470+
false);
471+
}
472+
EXPORT_SYMBOL(blk_mq_all_tag_busy_iter);
473+
441474
void blk_mq_tag_busy_iter(struct blk_mq_hw_ctx *hctx, busy_iter_fn *fn,
442475
void *priv)
443476
{
@@ -580,6 +613,11 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags,
580613
if (!tags)
581614
return NULL;
582615

616+
if (!zalloc_cpumask_var(&tags->cpumask, GFP_KERNEL)) {
617+
kfree(tags);
618+
return NULL;
619+
}
620+
583621
tags->nr_tags = total_tags;
584622
tags->nr_reserved_tags = reserved_tags;
585623

block/blk-mq-tag.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct blk_mq_tags {
4444
struct list_head page_list;
4545

4646
int alloc_policy;
47+
cpumask_var_t cpumask;
4748
};
4849

4950

block/blk-mq.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,7 +1525,6 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
15251525
i++;
15261526
}
15271527
}
1528-
15291528
return tags;
15301529

15311530
fail:
@@ -1821,6 +1820,7 @@ static void blk_mq_map_swqueue(struct request_queue *q)
18211820

18221821
hctx = q->mq_ops->map_queue(q, i);
18231822
cpumask_set_cpu(i, hctx->cpumask);
1823+
cpumask_set_cpu(i, hctx->tags->cpumask);
18241824
ctx->index_hw = hctx->nr_ctx;
18251825
hctx->ctxs[hctx->nr_ctx++] = ctx;
18261826
}
@@ -2187,6 +2187,12 @@ static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
21872187
return 0;
21882188
}
21892189

2190+
struct cpumask *blk_mq_tags_cpumask(struct blk_mq_tags *tags)
2191+
{
2192+
return tags->cpumask;
2193+
}
2194+
EXPORT_SYMBOL_GPL(blk_mq_tags_cpumask);
2195+
21902196
/*
21912197
* Alloc a tag set to be associated with one or more request queues.
21922198
* May fail with EINVAL for various error conditions. May adjust the
@@ -2248,8 +2254,10 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
22482254
int i;
22492255

22502256
for (i = 0; i < set->nr_hw_queues; i++) {
2251-
if (set->tags[i])
2257+
if (set->tags[i]) {
22522258
blk_mq_free_rq_map(set, set->tags[i], i);
2259+
free_cpumask_var(set->tags[i]->cpumask);
2260+
}
22532261
}
22542262

22552263
kfree(set->tags);

include/linux/blk-mq.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ typedef void (exit_request_fn)(void *, struct request *, unsigned int,
9696

9797
typedef void (busy_iter_fn)(struct blk_mq_hw_ctx *, struct request *, void *,
9898
bool);
99+
typedef void (busy_tag_iter_fn)(struct request *, void *, bool);
99100

100101
struct blk_mq_ops {
101102
/*
@@ -182,6 +183,7 @@ bool blk_mq_can_queue(struct blk_mq_hw_ctx *);
182183
struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
183184
gfp_t gfp, bool reserved);
184185
struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag);
186+
struct cpumask *blk_mq_tags_cpumask(struct blk_mq_tags *tags);
185187

186188
enum {
187189
BLK_MQ_UNIQUE_TAG_BITS = 16,
@@ -224,6 +226,8 @@ void blk_mq_run_hw_queues(struct request_queue *q, bool async);
224226
void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs);
225227
void blk_mq_tag_busy_iter(struct blk_mq_hw_ctx *hctx, busy_iter_fn *fn,
226228
void *priv);
229+
void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
230+
void *priv);
227231
void blk_mq_freeze_queue(struct request_queue *q);
228232
void blk_mq_unfreeze_queue(struct request_queue *q);
229233
void blk_mq_freeze_queue_start(struct request_queue *q);

0 commit comments

Comments
 (0)