]> Git Repo - linux.git/blobdiff - block/genhd.c
Merge tag 'for-5.18/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / block / genhd.c
index 1ed46a6f94f5c83f52936cf96383e3d95a20e0bf..c9a4fc90d3e9018a4eaf691ad7cbe8433461b7ab 100644 (file)
 #include <linux/pm_runtime.h>
 #include <linux/badblocks.h>
 #include <linux/part_stat.h>
+#include "blk-throttle.h"
 
 #include "blk.h"
 #include "blk-mq-sched.h"
 #include "blk-rq-qos.h"
+#include "blk-cgroup.h"
 
 static struct kobject *block_depr;
 
@@ -556,6 +558,20 @@ out_free_ext_minor:
 }
 EXPORT_SYMBOL(device_add_disk);
 
+/**
+ * blk_mark_disk_dead - mark a disk as dead
+ * @disk: disk to mark as dead
+ *
+ * Mark as disk as dead (e.g. surprise removed) and don't accept any new I/O
+ * to this disk.
+ */
+void blk_mark_disk_dead(struct gendisk *disk)
+{
+       set_bit(GD_DEAD, &disk->state);
+       blk_queue_start_drain(disk->queue);
+}
+EXPORT_SYMBOL_GPL(blk_mark_disk_dead);
+
 /**
  * del_gendisk - remove the gendisk
  * @disk: the struct gendisk to remove
@@ -630,7 +646,8 @@ void del_gendisk(struct gendisk *disk)
 
        blk_mq_freeze_queue_wait(q);
 
-       rq_qos_exit(q);
+       blk_throtl_cancel_bios(disk->queue);
+
        blk_sync_queue(q);
        blk_flush_integrity();
        /*
@@ -923,12 +940,17 @@ ssize_t part_stat_show(struct device *dev,
        struct disk_stats stat;
        unsigned int inflight;
 
-       part_stat_read_all(bdev, &stat);
        if (queue_is_mq(q))
                inflight = blk_mq_in_flight(q, bdev);
        else
                inflight = part_in_flight(bdev);
 
+       if (inflight) {
+               part_stat_lock();
+               update_io_ticks(bdev, jiffies, true);
+               part_stat_unlock();
+       }
+       part_stat_read_all(bdev, &stat);
        return sprintf(buf,
                "%8lu %8lu %8llu %8u "
                "%8lu %8lu %8llu %8u "
@@ -1096,6 +1118,31 @@ static const struct attribute_group *disk_attr_groups[] = {
        NULL
 };
 
+static void disk_release_mq(struct request_queue *q)
+{
+       blk_mq_cancel_work_sync(q);
+
+       /*
+        * There can't be any non non-passthrough bios in flight here, but
+        * requests stay around longer, including passthrough ones so we
+        * still need to freeze the queue here.
+        */
+       blk_mq_freeze_queue(q);
+
+       /*
+        * Since the I/O scheduler exit code may access cgroup information,
+        * perform I/O scheduler exit before disassociating from the block
+        * cgroup controller.
+        */
+       if (q->elevator) {
+               mutex_lock(&q->sysfs_lock);
+               elevator_exit(q);
+               mutex_unlock(&q->sysfs_lock);
+       }
+       rq_qos_exit(q);
+       __blk_mq_unfreeze_queue(q, true);
+}
+
 /**
  * disk_release - releases all allocated resources of the gendisk
  * @dev: the device representing this disk
@@ -1117,11 +1164,15 @@ static void disk_release(struct device *dev)
        might_sleep();
        WARN_ON_ONCE(disk_live(disk));
 
-       blk_mq_cancel_work_sync(disk->queue);
+       if (queue_is_mq(disk->queue))
+               disk_release_mq(disk->queue);
+
+       blkcg_exit_queue(disk->queue);
 
        disk_release_events(disk);
        kfree(disk->random);
        xa_destroy(&disk->part_tbl);
+
        disk->queue->disk = NULL;
        blk_put_queue(disk->queue);
 
@@ -1188,12 +1239,17 @@ static int diskstats_show(struct seq_file *seqf, void *v)
        xa_for_each(&gp->part_tbl, idx, hd) {
                if (bdev_is_partition(hd) && !bdev_nr_sectors(hd))
                        continue;
-               part_stat_read_all(hd, &stat);
                if (queue_is_mq(gp->queue))
                        inflight = blk_mq_in_flight(gp->queue, hd);
                else
                        inflight = part_in_flight(hd);
 
+               if (inflight) {
+                       part_stat_lock();
+                       update_io_ticks(hd, jiffies, true);
+                       part_stat_unlock();
+               }
+               part_stat_read_all(hd, &stat);
                seq_printf(seqf, "%4d %7d %pg "
                           "%lu %lu %lu %u "
                           "%lu %lu %lu %u "
@@ -1322,6 +1378,9 @@ struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,
        if (xa_insert(&disk->part_tbl, 0, disk->part0, GFP_KERNEL))
                goto out_destroy_part_tbl;
 
+       if (blkcg_init_queue(q))
+               goto out_erase_part0;
+
        rand_initialize_disk(disk);
        disk_to_dev(disk)->class = &block_class;
        disk_to_dev(disk)->type = &disk_type;
@@ -1334,6 +1393,8 @@ struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,
 #endif
        return disk;
 
+out_erase_part0:
+       xa_erase(&disk->part_tbl, 0);
 out_destroy_part_tbl:
        xa_destroy(&disk->part_tbl);
        disk->part0->bd_disk = NULL;
This page took 0.035735 seconds and 4 git commands to generate.