Prepare for replacing srcu with percpu-refcount for implementing queue quiesce. The following patch needs to avoid duplicated quiesce action for BLK_MQ_F_BLOCKING, so use test_and_{clear|test}_bit to set/clear QUEUE_FLAG_QUIESCED. Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> Cc: Sagi Grimberg <sagi@xxxxxxxxxxx> Cc: Bart Van Assche <bvanassche@xxxxxxx> Cc: Johannes Thumshirn <Johannes.Thumshirn@xxxxxxx> Cc: Chao Leng <lengchao@xxxxxxxxxx> Reviewed-by: Hannes Reinecke <hare@xxxxxxx> Tested-by: Sagi Grimberg <sagi@xxxxxxxxxxx> Reviewed-by: Keith Busch <kbusch@xxxxxxxxxx> --- block/blk-core.c | 13 +++++++++++++ block/blk-mq.c | 11 ++++++++--- block/blk.h | 2 ++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index ca3f0f00c943..34fae3986e79 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -107,6 +107,19 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q) } EXPORT_SYMBOL_GPL(blk_queue_flag_test_and_set); +/** + * blk_queue_flag_test_and_clear - atomically test and clear a queue flag + * @flag: flag to be clear + * @q: request queue + * + * Returns the previous value of @flag - 0 if the flag was not set and 1 if + * the flag was set. + */ +bool blk_queue_flag_test_and_clear(unsigned int flag, struct request_queue *q) +{ + return test_and_clear_bit(flag, &q->queue_flags); +} + void blk_rq_init(struct request_queue *q, struct request *rq) { memset(rq, 0, sizeof(*rq)); diff --git a/block/blk-mq.c b/block/blk-mq.c index e04b759add75..c7d424e76781 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -199,13 +199,18 @@ void blk_mq_unfreeze_queue(struct request_queue *q) } EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue); +static bool __blk_mq_quiesce_queue_nowait(struct request_queue *q) +{ + return blk_queue_flag_test_and_set(QUEUE_FLAG_QUIESCED, q); +} + /* * FIXME: replace the scsi_internal_device_*block_nowait() calls in the * mpt3sas driver such that this function can be removed. */ void blk_mq_quiesce_queue_nowait(struct request_queue *q) { - blk_queue_flag_set(QUEUE_FLAG_QUIESCED, q); + __blk_mq_quiesce_queue_nowait(q); } EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_nowait); @@ -224,7 +229,7 @@ void blk_mq_quiesce_queue(struct request_queue *q) unsigned int i; bool rcu = false; - blk_mq_quiesce_queue_nowait(q); + __blk_mq_quiesce_queue_nowait(q); queue_for_each_hw_ctx(q, hctx, i) { if (hctx->flags & BLK_MQ_F_BLOCKING) @@ -246,7 +251,7 @@ EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue); */ void blk_mq_unquiesce_queue(struct request_queue *q) { - blk_queue_flag_clear(QUEUE_FLAG_QUIESCED, q); + blk_queue_flag_test_and_clear(QUEUE_FLAG_QUIESCED, q); /* dispatch requests which are inserted during quiescing */ blk_mq_run_hw_queues(q, true); diff --git a/block/blk.h b/block/blk.h index c08762e10b04..312a060ea2a2 100644 --- a/block/blk.h +++ b/block/blk.h @@ -448,4 +448,6 @@ int bio_add_hw_page(struct request_queue *q, struct bio *bio, struct page *page, unsigned int len, unsigned int offset, unsigned int max_sectors, bool *same_page); +bool blk_queue_flag_test_and_clear(unsigned int flag, struct request_queue *q); + #endif /* BLK_INTERNAL_H */ -- 2.25.2