#include "blk-mq.h"
 #include "blk-mq-sched.h"
 #include "blk-pm.h"
-#include "blk-rq-qos.h"
 
 struct dentry *blk_debugfs_root;
 
 }
 EXPORT_SYMBOL(blk_put_queue);
 
-void blk_set_queue_dying(struct request_queue *q)
+void blk_queue_start_drain(struct request_queue *q)
 {
-       blk_queue_flag_set(QUEUE_FLAG_DYING, q);
-
        /*
         * When queue DYING flag is set, we need to block new req
         * entering queue, so we call blk_freeze_queue_start() to
         * prevent I/O from crossing blk_queue_enter().
         */
        blk_freeze_queue_start(q);
-
        if (queue_is_mq(q))
                blk_mq_wake_waiters(q);
-
        /* Make blk_queue_enter() reexamine the DYING flag. */
        wake_up_all(&q->mq_freeze_wq);
 }
+
+void blk_set_queue_dying(struct request_queue *q)
+{
+       blk_queue_flag_set(QUEUE_FLAG_DYING, q);
+       blk_queue_start_drain(q);
+}
 EXPORT_SYMBOL_GPL(blk_set_queue_dying);
 
 /**
         */
        blk_freeze_queue(q);
 
-       rq_qos_exit(q);
-
        blk_queue_flag_set(QUEUE_FLAG_DEAD, q);
 
-       /* for synchronous bio-based driver finish in-flight integrity i/o */
-       blk_flush_integrity();
-
        blk_sync_queue(q);
        if (queue_is_mq(q))
                blk_mq_exit_queue(q);
 
 static inline int bio_queue_enter(struct bio *bio)
 {
-       struct request_queue *q = bio->bi_bdev->bd_disk->queue;
+       struct gendisk *disk = bio->bi_bdev->bd_disk;
+       struct request_queue *q = disk->queue;
 
        while (!blk_try_enter_queue(q, false)) {
                if (bio->bi_opf & REQ_NOWAIT) {
-                       if (blk_queue_dying(q))
+                       if (test_bit(GD_DEAD, &disk->state))
                                goto dead;
                        bio_wouldblock_error(bio);
                        return -EBUSY;
                wait_event(q->mq_freeze_wq,
                           (!q->mq_freeze_depth &&
                            blk_pm_resume_queue(false, q)) ||
-                          blk_queue_dying(q));
-               if (blk_queue_dying(q))
+                          test_bit(GD_DEAD, &disk->state));
+               if (test_bit(GD_DEAD, &disk->state))
                        goto dead;
        }
 
 
 #include <linux/badblocks.h>
 
 #include "blk.h"
+#include "blk-rq-qos.h"
 
 static struct kobject *block_depr;
 
  */
 void del_gendisk(struct gendisk *disk)
 {
+       struct request_queue *q = disk->queue;
+
        might_sleep();
 
        if (WARN_ON_ONCE(!disk_live(disk) && !(disk->flags & GENHD_FL_HIDDEN)))
        fsync_bdev(disk->part0);
        __invalidate_device(disk->part0, true);
 
+       /*
+        * Fail any new I/O.
+        */
+       set_bit(GD_DEAD, &disk->state);
        set_capacity(disk, 0);
 
+       /*
+        * 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_mq_unfreeze_queue(q);
+
        if (!(disk->flags & GENHD_FL_HIDDEN)) {
                sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");