Skip to content

Commit 80bd4a7

Browse files
Christoph Hellwigaxboe
authored andcommitted
blk-mq: move the srcu_struct used for quiescing to the tagset
All I/O submissions have fairly similar latencies, and a tagset-wide quiesce is a fairly common operation. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Keith Busch <[email protected]> Reviewed-by: Ming Lei <[email protected]> Reviewed-by: Chao Leng <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Reviewed-by: Chaitanya Kulkarni <[email protected]> Link: https://lore.kernel.org/r/[email protected] [axboe: fix whitespace] Signed-off-by: Jens Axboe <[email protected]>
1 parent 8537380 commit 80bd4a7

File tree

8 files changed

+45
-62
lines changed

8 files changed

+45
-62
lines changed

block/blk-core.c

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ DEFINE_IDA(blk_queue_ida);
6565
* For queue allocation
6666
*/
6767
struct kmem_cache *blk_requestq_cachep;
68-
struct kmem_cache *blk_requestq_srcu_cachep;
6968

7069
/*
7170
* Controlling structure to kblockd
@@ -373,26 +372,20 @@ static void blk_timeout_work(struct work_struct *work)
373372
{
374373
}
375374

376-
struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu)
375+
struct request_queue *blk_alloc_queue(int node_id)
377376
{
378377
struct request_queue *q;
379378

380-
q = kmem_cache_alloc_node(blk_get_queue_kmem_cache(alloc_srcu),
381-
GFP_KERNEL | __GFP_ZERO, node_id);
379+
q = kmem_cache_alloc_node(blk_requestq_cachep, GFP_KERNEL | __GFP_ZERO,
380+
node_id);
382381
if (!q)
383382
return NULL;
384383

385-
if (alloc_srcu) {
386-
blk_queue_flag_set(QUEUE_FLAG_HAS_SRCU, q);
387-
if (init_srcu_struct(q->srcu) != 0)
388-
goto fail_q;
389-
}
390-
391384
q->last_merge = NULL;
392385

393386
q->id = ida_alloc(&blk_queue_ida, GFP_KERNEL);
394387
if (q->id < 0)
395-
goto fail_srcu;
388+
goto fail_q;
396389

397390
q->stats = blk_alloc_queue_stats();
398391
if (!q->stats)
@@ -435,11 +428,8 @@ struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu)
435428
blk_free_queue_stats(q->stats);
436429
fail_id:
437430
ida_free(&blk_queue_ida, q->id);
438-
fail_srcu:
439-
if (alloc_srcu)
440-
cleanup_srcu_struct(q->srcu);
441431
fail_q:
442-
kmem_cache_free(blk_get_queue_kmem_cache(alloc_srcu), q);
432+
kmem_cache_free(blk_requestq_cachep, q);
443433
return NULL;
444434
}
445435

@@ -1172,9 +1162,6 @@ int __init blk_dev_init(void)
11721162
sizeof_field(struct request, cmd_flags));
11731163
BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
11741164
sizeof_field(struct bio, bi_opf));
1175-
BUILD_BUG_ON(ALIGN(offsetof(struct request_queue, srcu),
1176-
__alignof__(struct request_queue)) !=
1177-
sizeof(struct request_queue));
11781165

11791166
/* used for unplugging and affects IO latency/throughput - HIGHPRI */
11801167
kblockd_workqueue = alloc_workqueue("kblockd",
@@ -1185,10 +1172,6 @@ int __init blk_dev_init(void)
11851172
blk_requestq_cachep = kmem_cache_create("request_queue",
11861173
sizeof(struct request_queue), 0, SLAB_PANIC, NULL);
11871174

1188-
blk_requestq_srcu_cachep = kmem_cache_create("request_queue_srcu",
1189-
sizeof(struct request_queue) +
1190-
sizeof(struct srcu_struct), 0, SLAB_PANIC, NULL);
1191-
11921175
blk_debugfs_root = debugfs_create_dir("block", NULL);
11931176

11941177
return 0;

block/blk-mq.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_nowait);
261261
*/
262262
void blk_mq_wait_quiesce_done(struct request_queue *q)
263263
{
264-
if (blk_queue_has_srcu(q))
265-
synchronize_srcu(q->srcu);
264+
if (q->tag_set->flags & BLK_MQ_F_BLOCKING)
265+
synchronize_srcu(q->tag_set->srcu);
266266
else
267267
synchronize_rcu();
268268
}
@@ -4003,7 +4003,7 @@ static struct request_queue *blk_mq_init_queue_data(struct blk_mq_tag_set *set,
40034003
struct request_queue *q;
40044004
int ret;
40054005

4006-
q = blk_alloc_queue(set->numa_node, set->flags & BLK_MQ_F_BLOCKING);
4006+
q = blk_alloc_queue(set->numa_node);
40074007
if (!q)
40084008
return ERR_PTR(-ENOMEM);
40094009
q->queuedata = queuedata;
@@ -4168,9 +4168,6 @@ static void blk_mq_update_poll_flag(struct request_queue *q)
41684168
int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
41694169
struct request_queue *q)
41704170
{
4171-
WARN_ON_ONCE(blk_queue_has_srcu(q) !=
4172-
!!(set->flags & BLK_MQ_F_BLOCKING));
4173-
41744171
/* mark the queue as mq asap */
41754172
q->mq_ops = set->ops;
41764173

@@ -4429,8 +4426,18 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
44294426
if (set->nr_maps == 1 && set->nr_hw_queues > nr_cpu_ids)
44304427
set->nr_hw_queues = nr_cpu_ids;
44314428

4432-
if (blk_mq_alloc_tag_set_tags(set, set->nr_hw_queues) < 0)
4433-
return -ENOMEM;
4429+
if (set->flags & BLK_MQ_F_BLOCKING) {
4430+
set->srcu = kmalloc(sizeof(*set->srcu), GFP_KERNEL);
4431+
if (!set->srcu)
4432+
return -ENOMEM;
4433+
ret = init_srcu_struct(set->srcu);
4434+
if (ret)
4435+
goto out_free_srcu;
4436+
}
4437+
4438+
ret = blk_mq_alloc_tag_set_tags(set, set->nr_hw_queues);
4439+
if (ret)
4440+
goto out_cleanup_srcu;
44344441

44354442
ret = -ENOMEM;
44364443
for (i = 0; i < set->nr_maps; i++) {
@@ -4460,6 +4467,12 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
44604467
}
44614468
kfree(set->tags);
44624469
set->tags = NULL;
4470+
out_cleanup_srcu:
4471+
if (set->flags & BLK_MQ_F_BLOCKING)
4472+
cleanup_srcu_struct(set->srcu);
4473+
out_free_srcu:
4474+
if (set->flags & BLK_MQ_F_BLOCKING)
4475+
kfree(set->srcu);
44634476
return ret;
44644477
}
44654478
EXPORT_SYMBOL(blk_mq_alloc_tag_set);
@@ -4499,6 +4512,10 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
44994512

45004513
kfree(set->tags);
45014514
set->tags = NULL;
4515+
if (set->flags & BLK_MQ_F_BLOCKING) {
4516+
cleanup_srcu_struct(set->srcu);
4517+
kfree(set->srcu);
4518+
}
45024519
}
45034520
EXPORT_SYMBOL(blk_mq_free_tag_set);
45044521

block/blk-mq.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -377,17 +377,17 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
377377
/* run the code block in @dispatch_ops with rcu/srcu read lock held */
378378
#define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops) \
379379
do { \
380-
if (!blk_queue_has_srcu(q)) { \
381-
rcu_read_lock(); \
382-
(dispatch_ops); \
383-
rcu_read_unlock(); \
384-
} else { \
380+
if ((q)->tag_set->flags & BLK_MQ_F_BLOCKING) { \
385381
int srcu_idx; \
386382
\
387383
might_sleep_if(check_sleep); \
388-
srcu_idx = srcu_read_lock((q)->srcu); \
384+
srcu_idx = srcu_read_lock((q)->tag_set->srcu); \
389385
(dispatch_ops); \
390-
srcu_read_unlock((q)->srcu, srcu_idx); \
386+
srcu_read_unlock((q)->tag_set->srcu, srcu_idx); \
387+
} else { \
388+
rcu_read_lock(); \
389+
(dispatch_ops); \
390+
rcu_read_unlock(); \
391391
} \
392392
} while (0)
393393

block/blk-sysfs.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -742,10 +742,8 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
742742

743743
static void blk_free_queue_rcu(struct rcu_head *rcu_head)
744744
{
745-
struct request_queue *q = container_of(rcu_head, struct request_queue,
746-
rcu_head);
747-
748-
kmem_cache_free(blk_get_queue_kmem_cache(blk_queue_has_srcu(q)), q);
745+
kmem_cache_free(blk_requestq_cachep,
746+
container_of(rcu_head, struct request_queue, rcu_head));
749747
}
750748

751749
/**
@@ -782,9 +780,6 @@ static void blk_release_queue(struct kobject *kobj)
782780
if (queue_is_mq(q))
783781
blk_mq_release(q);
784782

785-
if (blk_queue_has_srcu(q))
786-
cleanup_srcu_struct(q->srcu);
787-
788783
ida_free(&blk_queue_ida, q->id);
789784
call_rcu(&q->rcu_head, blk_free_queue_rcu);
790785
}

block/blk.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ struct blk_flush_queue {
2727
};
2828

2929
extern struct kmem_cache *blk_requestq_cachep;
30-
extern struct kmem_cache *blk_requestq_srcu_cachep;
3130
extern struct kobj_type blk_queue_ktype;
3231
extern struct ida blk_queue_ida;
3332

@@ -429,13 +428,7 @@ int bio_add_hw_page(struct request_queue *q, struct bio *bio,
429428
struct page *page, unsigned int len, unsigned int offset,
430429
unsigned int max_sectors, bool *same_page);
431430

432-
static inline struct kmem_cache *blk_get_queue_kmem_cache(bool srcu)
433-
{
434-
if (srcu)
435-
return blk_requestq_srcu_cachep;
436-
return blk_requestq_cachep;
437-
}
438-
struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu);
431+
struct request_queue *blk_alloc_queue(int node_id);
439432

440433
int disk_scan_partitions(struct gendisk *disk, fmode_t mode);
441434

block/genhd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1414,7 +1414,7 @@ struct gendisk *__blk_alloc_disk(int node, struct lock_class_key *lkclass)
14141414
struct request_queue *q;
14151415
struct gendisk *disk;
14161416

1417-
q = blk_alloc_queue(node, false);
1417+
q = blk_alloc_queue(node);
14181418
if (!q)
14191419
return NULL;
14201420

include/linux/blk-mq.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/lockdep.h>
88
#include <linux/scatterlist.h>
99
#include <linux/prefetch.h>
10+
#include <linux/srcu.h>
1011

1112
struct blk_mq_tags;
1213
struct blk_flush_queue;
@@ -500,6 +501,8 @@ enum hctx_type {
500501
* @tag_list_lock: Serializes tag_list accesses.
501502
* @tag_list: List of the request queues that use this tag set. See also
502503
* request_queue.tag_set_list.
504+
* @srcu: Use as lock when type of the request queue is blocking
505+
* (BLK_MQ_F_BLOCKING).
503506
*/
504507
struct blk_mq_tag_set {
505508
struct blk_mq_queue_map map[HCTX_MAX_TYPES];
@@ -520,6 +523,7 @@ struct blk_mq_tag_set {
520523

521524
struct mutex tag_list_lock;
522525
struct list_head tag_list;
526+
struct srcu_struct *srcu;
523527
};
524528

525529
/**

include/linux/blkdev.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <linux/blkzoned.h>
2323
#include <linux/sched.h>
2424
#include <linux/sbitmap.h>
25-
#include <linux/srcu.h>
2625
#include <linux/uuid.h>
2726
#include <linux/xarray.h>
2827

@@ -543,18 +542,11 @@ struct request_queue {
543542
struct mutex debugfs_mutex;
544543

545544
bool mq_sysfs_init_done;
546-
547-
/**
548-
* @srcu: Sleepable RCU. Use as lock when type of the request queue
549-
* is blocking (BLK_MQ_F_BLOCKING). Must be the last member
550-
*/
551-
struct srcu_struct srcu[];
552545
};
553546

554547
/* Keep blk_queue_flag_name[] in sync with the definitions below */
555548
#define QUEUE_FLAG_STOPPED 0 /* queue is stopped */
556549
#define QUEUE_FLAG_DYING 1 /* queue being torn down */
557-
#define QUEUE_FLAG_HAS_SRCU 2 /* SRCU is allocated */
558550
#define QUEUE_FLAG_NOMERGES 3 /* disable merge attempts */
559551
#define QUEUE_FLAG_SAME_COMP 4 /* complete on same CPU-group */
560552
#define QUEUE_FLAG_FAIL_IO 5 /* fake timeout */
@@ -590,7 +582,6 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
590582

591583
#define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
592584
#define blk_queue_dying(q) test_bit(QUEUE_FLAG_DYING, &(q)->queue_flags)
593-
#define blk_queue_has_srcu(q) test_bit(QUEUE_FLAG_HAS_SRCU, &(q)->queue_flags)
594585
#define blk_queue_init_done(q) test_bit(QUEUE_FLAG_INIT_DONE, &(q)->queue_flags)
595586
#define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags)
596587
#define blk_queue_noxmerges(q) \

0 commit comments

Comments
 (0)