Skip to content

Commit e155b0c

Browse files
John Garryaxboe
authored andcommitted
blk-mq: Use shared tags for shared sbitmap support
Currently we use separate sbitmap pairs and active_queues atomic_t for shared sbitmap support. However a full sets of static requests are used per HW queue, which is quite wasteful, considering that the total number of requests usable at any given time across all HW queues is limited by the shared sbitmap depth. As such, it is considerably more memory efficient in the case of shared sbitmap to allocate a set of static rqs per tag set or request queue, and not per HW queue. So replace the sbitmap pairs and active_queues atomic_t with a shared tags per tagset and request queue, which will hold a set of shared static rqs. Since there is now no valid HW queue index to be passed to the blk_mq_ops .init and .exit_request callbacks, pass an invalid index token. This changes the semantics of the APIs, such that the callback would need to validate the HW queue index before using it. Currently no user of shared sbitmap actually uses the HW queue index (as would be expected). Signed-off-by: John Garry <[email protected]> Reviewed-by: Ming Lei <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 645db34 commit e155b0c

File tree

7 files changed

+125
-152
lines changed

7 files changed

+125
-152
lines changed

block/blk-mq-sched.c

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,11 @@ static int blk_mq_sched_alloc_map_and_rqs(struct request_queue *q,
519519
struct blk_mq_hw_ctx *hctx,
520520
unsigned int hctx_idx)
521521
{
522+
if (blk_mq_is_sbitmap_shared(q->tag_set->flags)) {
523+
hctx->sched_tags = q->shared_sbitmap_tags;
524+
return 0;
525+
}
526+
522527
hctx->sched_tags = blk_mq_alloc_map_and_rqs(q->tag_set, hctx_idx,
523528
q->nr_requests);
524529

@@ -527,61 +532,54 @@ static int blk_mq_sched_alloc_map_and_rqs(struct request_queue *q,
527532
return 0;
528533
}
529534

535+
static void blk_mq_exit_sched_shared_sbitmap(struct request_queue *queue)
536+
{
537+
blk_mq_free_rq_map(queue->shared_sbitmap_tags);
538+
queue->shared_sbitmap_tags = NULL;
539+
}
540+
530541
/* called in queue's release handler, tagset has gone away */
531-
static void blk_mq_sched_tags_teardown(struct request_queue *q)
542+
static void blk_mq_sched_tags_teardown(struct request_queue *q, unsigned int flags)
532543
{
533544
struct blk_mq_hw_ctx *hctx;
534545
int i;
535546

536547
queue_for_each_hw_ctx(q, hctx, i) {
537548
if (hctx->sched_tags) {
538-
blk_mq_free_rq_map(hctx->sched_tags, hctx->flags);
549+
if (!blk_mq_is_sbitmap_shared(q->tag_set->flags))
550+
blk_mq_free_rq_map(hctx->sched_tags);
539551
hctx->sched_tags = NULL;
540552
}
541553
}
554+
555+
if (blk_mq_is_sbitmap_shared(flags))
556+
blk_mq_exit_sched_shared_sbitmap(q);
542557
}
543558

544559
static int blk_mq_init_sched_shared_sbitmap(struct request_queue *queue)
545560
{
546561
struct blk_mq_tag_set *set = queue->tag_set;
547-
int alloc_policy = BLK_MQ_FLAG_TO_ALLOC_POLICY(set->flags);
548-
struct blk_mq_hw_ctx *hctx;
549-
int ret, i;
550562

551563
/*
552564
* Set initial depth at max so that we don't need to reallocate for
553565
* updating nr_requests.
554566
*/
555-
ret = blk_mq_init_bitmaps(&queue->sched_bitmap_tags,
556-
&queue->sched_breserved_tags,
557-
MAX_SCHED_RQ, set->reserved_tags,
558-
set->numa_node, alloc_policy);
559-
if (ret)
560-
return ret;
561-
562-
queue_for_each_hw_ctx(queue, hctx, i) {
563-
hctx->sched_tags->bitmap_tags =
564-
&queue->sched_bitmap_tags;
565-
hctx->sched_tags->breserved_tags =
566-
&queue->sched_breserved_tags;
567-
}
567+
queue->shared_sbitmap_tags = blk_mq_alloc_map_and_rqs(set,
568+
BLK_MQ_NO_HCTX_IDX,
569+
MAX_SCHED_RQ);
570+
if (!queue->shared_sbitmap_tags)
571+
return -ENOMEM;
568572

569573
blk_mq_tag_update_sched_shared_sbitmap(queue);
570574

571575
return 0;
572576
}
573577

574-
static void blk_mq_exit_sched_shared_sbitmap(struct request_queue *queue)
575-
{
576-
sbitmap_queue_free(&queue->sched_bitmap_tags);
577-
sbitmap_queue_free(&queue->sched_breserved_tags);
578-
}
579-
580578
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
581579
{
580+
unsigned int i, flags = q->tag_set->flags;
582581
struct blk_mq_hw_ctx *hctx;
583582
struct elevator_queue *eq;
584-
unsigned int i;
585583
int ret;
586584

587585
if (!e) {
@@ -598,21 +596,21 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
598596
q->nr_requests = 2 * min_t(unsigned int, q->tag_set->queue_depth,
599597
BLKDEV_DEFAULT_RQ);
600598

601-
queue_for_each_hw_ctx(q, hctx, i) {
602-
ret = blk_mq_sched_alloc_map_and_rqs(q, hctx, i);
599+
if (blk_mq_is_sbitmap_shared(flags)) {
600+
ret = blk_mq_init_sched_shared_sbitmap(q);
603601
if (ret)
604-
goto err_free_map_and_rqs;
602+
return ret;
605603
}
606604

607-
if (blk_mq_is_sbitmap_shared(q->tag_set->flags)) {
608-
ret = blk_mq_init_sched_shared_sbitmap(q);
605+
queue_for_each_hw_ctx(q, hctx, i) {
606+
ret = blk_mq_sched_alloc_map_and_rqs(q, hctx, i);
609607
if (ret)
610608
goto err_free_map_and_rqs;
611609
}
612610

613611
ret = e->ops.init_sched(q, e);
614612
if (ret)
615-
goto err_free_sbitmap;
613+
goto err_free_map_and_rqs;
616614

617615
blk_mq_debugfs_register_sched(q);
618616

@@ -632,12 +630,10 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
632630

633631
return 0;
634632

635-
err_free_sbitmap:
636-
if (blk_mq_is_sbitmap_shared(q->tag_set->flags))
637-
blk_mq_exit_sched_shared_sbitmap(q);
638633
err_free_map_and_rqs:
639634
blk_mq_sched_free_rqs(q);
640-
blk_mq_sched_tags_teardown(q);
635+
blk_mq_sched_tags_teardown(q, flags);
636+
641637
q->elevator = NULL;
642638
return ret;
643639
}
@@ -651,9 +647,15 @@ void blk_mq_sched_free_rqs(struct request_queue *q)
651647
struct blk_mq_hw_ctx *hctx;
652648
int i;
653649

654-
queue_for_each_hw_ctx(q, hctx, i) {
655-
if (hctx->sched_tags)
656-
blk_mq_free_rqs(q->tag_set, hctx->sched_tags, i);
650+
if (blk_mq_is_sbitmap_shared(q->tag_set->flags)) {
651+
blk_mq_free_rqs(q->tag_set, q->shared_sbitmap_tags,
652+
BLK_MQ_NO_HCTX_IDX);
653+
} else {
654+
queue_for_each_hw_ctx(q, hctx, i) {
655+
if (hctx->sched_tags)
656+
blk_mq_free_rqs(q->tag_set,
657+
hctx->sched_tags, i);
658+
}
657659
}
658660
}
659661

@@ -674,8 +676,6 @@ void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e)
674676
blk_mq_debugfs_unregister_sched(q);
675677
if (e->type->ops.exit_sched)
676678
e->type->ops.exit_sched(e);
677-
blk_mq_sched_tags_teardown(q);
678-
if (blk_mq_is_sbitmap_shared(flags))
679-
blk_mq_exit_sched_shared_sbitmap(q);
679+
blk_mq_sched_tags_teardown(q, flags);
680680
q->elevator = NULL;
681681
}

block/blk-mq-tag.c

Lines changed: 19 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,10 @@ bool __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
2626
{
2727
if (blk_mq_is_sbitmap_shared(hctx->flags)) {
2828
struct request_queue *q = hctx->queue;
29-
struct blk_mq_tag_set *set = q->tag_set;
3029

3130
if (!test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags) &&
3231
!test_and_set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags))
33-
atomic_inc(&set->active_queues_shared_sbitmap);
32+
atomic_inc(&hctx->tags->active_queues);
3433
} else {
3534
if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state) &&
3635
!test_and_set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
@@ -57,14 +56,14 @@ void blk_mq_tag_wakeup_all(struct blk_mq_tags *tags, bool include_reserve)
5756
void __blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx)
5857
{
5958
struct blk_mq_tags *tags = hctx->tags;
60-
struct request_queue *q = hctx->queue;
61-
struct blk_mq_tag_set *set = q->tag_set;
6259

6360
if (blk_mq_is_sbitmap_shared(hctx->flags)) {
61+
struct request_queue *q = hctx->queue;
62+
6463
if (!test_and_clear_bit(QUEUE_FLAG_HCTX_ACTIVE,
6564
&q->queue_flags))
6665
return;
67-
atomic_dec(&set->active_queues_shared_sbitmap);
66+
atomic_dec(&tags->active_queues);
6867
} else {
6968
if (!test_and_clear_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
7069
return;
@@ -510,38 +509,10 @@ static int blk_mq_init_bitmap_tags(struct blk_mq_tags *tags,
510509
return 0;
511510
}
512511

513-
int blk_mq_init_shared_sbitmap(struct blk_mq_tag_set *set)
514-
{
515-
int alloc_policy = BLK_MQ_FLAG_TO_ALLOC_POLICY(set->flags);
516-
int i, ret;
517-
518-
ret = blk_mq_init_bitmaps(&set->__bitmap_tags, &set->__breserved_tags,
519-
set->queue_depth, set->reserved_tags,
520-
set->numa_node, alloc_policy);
521-
if (ret)
522-
return ret;
523-
524-
for (i = 0; i < set->nr_hw_queues; i++) {
525-
struct blk_mq_tags *tags = set->tags[i];
526-
527-
tags->bitmap_tags = &set->__bitmap_tags;
528-
tags->breserved_tags = &set->__breserved_tags;
529-
}
530-
531-
return 0;
532-
}
533-
534-
void blk_mq_exit_shared_sbitmap(struct blk_mq_tag_set *set)
535-
{
536-
sbitmap_queue_free(&set->__bitmap_tags);
537-
sbitmap_queue_free(&set->__breserved_tags);
538-
}
539-
540512
struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags,
541513
unsigned int reserved_tags,
542-
int node, unsigned int flags)
514+
int node, int alloc_policy)
543515
{
544-
int alloc_policy = BLK_MQ_FLAG_TO_ALLOC_POLICY(flags);
545516
struct blk_mq_tags *tags;
546517

547518
if (total_tags > BLK_MQ_TAG_MAX) {
@@ -557,22 +528,17 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags,
557528
tags->nr_reserved_tags = reserved_tags;
558529
spin_lock_init(&tags->lock);
559530

560-
if (blk_mq_is_sbitmap_shared(flags))
561-
return tags;
562-
563531
if (blk_mq_init_bitmap_tags(tags, node, alloc_policy) < 0) {
564532
kfree(tags);
565533
return NULL;
566534
}
567535
return tags;
568536
}
569537

570-
void blk_mq_free_tags(struct blk_mq_tags *tags, unsigned int flags)
538+
void blk_mq_free_tags(struct blk_mq_tags *tags)
571539
{
572-
if (!blk_mq_is_sbitmap_shared(flags)) {
573-
sbitmap_queue_free(tags->bitmap_tags);
574-
sbitmap_queue_free(tags->breserved_tags);
575-
}
540+
sbitmap_queue_free(tags->bitmap_tags);
541+
sbitmap_queue_free(tags->breserved_tags);
576542
kfree(tags);
577543
}
578544

@@ -603,6 +569,13 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx,
603569
if (tdepth > MAX_SCHED_RQ)
604570
return -EINVAL;
605571

572+
/*
573+
* Only the sbitmap needs resizing since we allocated the max
574+
* initially.
575+
*/
576+
if (blk_mq_is_sbitmap_shared(set->flags))
577+
return 0;
578+
606579
new = blk_mq_alloc_map_and_rqs(set, hctx->queue_num, tdepth);
607580
if (!new)
608581
return -ENOMEM;
@@ -623,12 +596,14 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx,
623596

624597
void blk_mq_tag_resize_shared_sbitmap(struct blk_mq_tag_set *set, unsigned int size)
625598
{
626-
sbitmap_queue_resize(&set->__bitmap_tags, size - set->reserved_tags);
599+
struct blk_mq_tags *tags = set->shared_sbitmap_tags;
600+
601+
sbitmap_queue_resize(&tags->__bitmap_tags, size - set->reserved_tags);
627602
}
628603

629604
void blk_mq_tag_update_sched_shared_sbitmap(struct request_queue *q)
630605
{
631-
sbitmap_queue_resize(&q->sched_bitmap_tags,
606+
sbitmap_queue_resize(q->shared_sbitmap_tags->bitmap_tags,
632607
q->nr_requests - q->tag_set->reserved_tags);
633608
}
634609

block/blk-mq-tag.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,14 @@ struct blk_mq_tags {
3232

3333
extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags,
3434
unsigned int reserved_tags,
35-
int node, unsigned int flags);
36-
extern void blk_mq_free_tags(struct blk_mq_tags *tags, unsigned int flags);
35+
int node, int alloc_policy);
36+
extern void blk_mq_free_tags(struct blk_mq_tags *tags);
3737
extern int blk_mq_init_bitmaps(struct sbitmap_queue *bitmap_tags,
3838
struct sbitmap_queue *breserved_tags,
3939
unsigned int queue_depth,
4040
unsigned int reserved,
4141
int node, int alloc_policy);
4242

43-
extern int blk_mq_init_shared_sbitmap(struct blk_mq_tag_set *set);
44-
extern void blk_mq_exit_shared_sbitmap(struct blk_mq_tag_set *set);
4543
extern unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data);
4644
extern void blk_mq_put_tag(struct blk_mq_tags *tags, struct blk_mq_ctx *ctx,
4745
unsigned int tag);

0 commit comments

Comments
 (0)