block: drain queue after disk is removed from sysfs
authorMing Lei <ming.lei@redhat.com>
Tue, 26 Oct 2021 10:12:04 +0000 (18:12 +0800)
committerJens Axboe <axboe@kernel.dk>
Tue, 26 Oct 2021 14:44:38 +0000 (08:44 -0600)
Before removing disk from sysfs, userspace still may change queue via
sysfs, such as switching elevator or setting wbt latency, both may
reinitialize wbt, then the warning in blk_free_queue_stats() will be
triggered since rq_qos_exit() is moved to del_gendisk().

Fixes the issue by moving draining queue & tearing down after disk is
removed from sysfs, at that time no one can come into queue's
store()/show().

Reported-by: Yi Zhang <yi.zhang@redhat.com>
Tested-by: Yi Zhang <yi.zhang@redhat.com>
Fixes: 8e141f9eb803 ("block: drain file system I/O on del_gendisk")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20211026101204.2897166-1-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/genhd.c

index b498585..ab12ae6 100644 (file)
@@ -588,16 +588,6 @@ void del_gendisk(struct gendisk *disk)
         * Prevent new I/O from crossing bio_queue_enter().
         */
        blk_queue_start_drain(q);
-       blk_mq_freeze_queue_wait(q);
-
-       rq_qos_exit(q);
-       blk_sync_queue(q);
-       blk_flush_integrity();
-       /*
-        * Allow using passthrough request again after the queue is torn down.
-        */
-       blk_queue_flag_clear(QUEUE_FLAG_INIT_DONE, q);
-       __blk_mq_unfreeze_queue(q, true);
 
        if (!(disk->flags & GENHD_FL_HIDDEN)) {
                sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
@@ -620,6 +610,18 @@ void del_gendisk(struct gendisk *disk)
                sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
        pm_runtime_set_memalloc_noio(disk_to_dev(disk), false);
        device_del(disk_to_dev(disk));
+
+       blk_mq_freeze_queue_wait(q);
+
+       rq_qos_exit(q);
+       blk_sync_queue(q);
+       blk_flush_integrity();
+       /*
+        * Allow using passthrough request again after the queue is torn down.
+        */
+       blk_queue_flag_clear(QUEUE_FLAG_INIT_DONE, q);
+       __blk_mq_unfreeze_queue(q, true);
+
 }
 EXPORT_SYMBOL(del_gendisk);