Skip to content

Commit 414dd48

Browse files
lostandy26axboe
authored andcommitted
blk-mq: add tagset quiesce interface
Drivers that have shared tagsets may need to quiesce potentially a lot of request queues that all share a single tagset (e.g. nvme). Add an interface to quiesce all the queues on a given tagset. This interface is useful because it can speedup the quiesce by doing it in parallel. Because some queues should not need to be quiesced (e.g. the nvme connect_q) when quiescing the tagset, introduce a QUEUE_FLAG_SKIP_TAGSET_QUIESCE flag to allow this new interface to ski quiescing a particular queue. Signed-off-by: Chao Leng <[email protected]> [hch: simplify for the per-tag_set srcu_struct] Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Keith Busch <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Reviewed-by: Ming Lei <[email protected]> Reviewed-by: Chao Leng <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Reviewed-by: Chaitanya Kulkarni <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 483239c commit 414dd48

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

block/blk-mq.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,33 @@ void blk_mq_unquiesce_queue(struct request_queue *q)
315315
}
316316
EXPORT_SYMBOL_GPL(blk_mq_unquiesce_queue);
317317

318+
void blk_mq_quiesce_tagset(struct blk_mq_tag_set *set)
319+
{
320+
struct request_queue *q;
321+
322+
mutex_lock(&set->tag_list_lock);
323+
list_for_each_entry(q, &set->tag_list, tag_set_list) {
324+
if (!blk_queue_skip_tagset_quiesce(q))
325+
blk_mq_quiesce_queue_nowait(q);
326+
}
327+
blk_mq_wait_quiesce_done(set);
328+
mutex_unlock(&set->tag_list_lock);
329+
}
330+
EXPORT_SYMBOL_GPL(blk_mq_quiesce_tagset);
331+
332+
void blk_mq_unquiesce_tagset(struct blk_mq_tag_set *set)
333+
{
334+
struct request_queue *q;
335+
336+
mutex_lock(&set->tag_list_lock);
337+
list_for_each_entry(q, &set->tag_list, tag_set_list) {
338+
if (!blk_queue_skip_tagset_quiesce(q))
339+
blk_mq_unquiesce_queue(q);
340+
}
341+
mutex_unlock(&set->tag_list_lock);
342+
}
343+
EXPORT_SYMBOL_GPL(blk_mq_unquiesce_tagset);
344+
318345
void blk_mq_wake_waiters(struct request_queue *q)
319346
{
320347
struct blk_mq_hw_ctx *hctx;

include/linux/blk-mq.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,8 @@ void blk_mq_start_stopped_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
881881
void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async);
882882
void blk_mq_quiesce_queue(struct request_queue *q);
883883
void blk_mq_wait_quiesce_done(struct blk_mq_tag_set *set);
884+
void blk_mq_quiesce_tagset(struct blk_mq_tag_set *set);
885+
void blk_mq_unquiesce_tagset(struct blk_mq_tag_set *set);
884886
void blk_mq_unquiesce_queue(struct request_queue *q);
885887
void blk_mq_delay_run_hw_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs);
886888
void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);

include/linux/blkdev.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ struct request_queue {
571571
#define QUEUE_FLAG_HCTX_ACTIVE 28 /* at least one blk-mq hctx is active */
572572
#define QUEUE_FLAG_NOWAIT 29 /* device supports NOWAIT */
573573
#define QUEUE_FLAG_SQ_SCHED 30 /* single queue style io dispatch */
574+
#define QUEUE_FLAG_SKIP_TAGSET_QUIESCE 31 /* quiesce_tagset skip the queue*/
574575

575576
#define QUEUE_FLAG_MQ_DEFAULT ((1UL << QUEUE_FLAG_IO_STAT) | \
576577
(1UL << QUEUE_FLAG_SAME_COMP) | \
@@ -610,6 +611,8 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
610611
#define blk_queue_pm_only(q) atomic_read(&(q)->pm_only)
611612
#define blk_queue_registered(q) test_bit(QUEUE_FLAG_REGISTERED, &(q)->queue_flags)
612613
#define blk_queue_sq_sched(q) test_bit(QUEUE_FLAG_SQ_SCHED, &(q)->queue_flags)
614+
#define blk_queue_skip_tagset_quiesce(q) \
615+
test_bit(QUEUE_FLAG_SKIP_TAGSET_QUIESCE, &(q)->queue_flags)
613616

614617
extern void blk_set_pm_only(struct request_queue *q);
615618
extern void blk_clear_pm_only(struct request_queue *q);

0 commit comments

Comments
 (0)