diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index 323bbca53a17d0efbd26824e5509cece9b27b8dc..ce7f7188625eb396bf143e51b75b828971095e33 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -9,6 +9,7 @@ #include #include +#include #include "blk.h" #include "blk-mq.h" #include "blk-mq-tag.h" @@ -328,6 +329,36 @@ void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, } EXPORT_SYMBOL(blk_mq_tagset_busy_iter); +static void blk_mq_tagset_count_completed_rqs(struct request *rq, + void *data, bool reserved) +{ + unsigned *count = data; + + if (blk_mq_request_completed(rq)) + (*count)++; +} + +/** + * blk_mq_tagset_wait_completed_request - wait until all completed req's + * complete funtion is run + * @tagset: Tag set to drain completed request + * + * Note: This function has to be run after all IO queues are shutdown + */ +void blk_mq_tagset_wait_completed_request(struct blk_mq_tag_set *tagset) +{ + while (true) { + unsigned count = 0; + + blk_mq_tagset_busy_iter(tagset, + blk_mq_tagset_count_completed_rqs, &count); + if (!count) + break; + msleep(5); + } +} +EXPORT_SYMBOL(blk_mq_tagset_wait_completed_request); + static void __blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn, void *priv, bool inflight) { diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index b414cad68024b3bb4131b859a4a4c4d3ff012d48..d26edab21d5c52a6dceea8af8a1814daa9c27348 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -316,6 +316,7 @@ void blk_mq_run_hw_queues(struct request_queue *q, bool async); void blk_mq_delay_run_hw_queues(struct request_queue *q, unsigned long msecs); void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, busy_tag_iter_fn *fn, void *priv); +void blk_mq_tagset_wait_completed_request(struct blk_mq_tag_set *tagset); void blk_mq_freeze_queue(struct request_queue *q); void blk_mq_unfreeze_queue(struct request_queue *q); void blk_freeze_queue_start(struct request_queue *q);