block: hold a request_queue reference for the lifetime of struct gendisk alloc_disk
authorChristoph Hellwig <hch@lst.de>
Tue, 10 Aug 2021 08:08:47 +0000 (10:08 +0200)
committerChristoph Hellwig <hch@lst.de>
Tue, 10 Aug 2021 13:04:00 +0000 (15:04 +0200)
Acquire the queue ref dropped in disk_release in __blk_alloc_disk so any
allocate gendisk always has a queue reference.

Signed-off-by: Christoph Hellwig <hch@lst.de>
block/genhd.c
include/linux/genhd.h

index 283cf0c649e1b4c465335252f852e58c35c4cb34..18600f682edbcd86f671036aa6c3ffb09caeed99 100644 (file)
@@ -544,16 +544,6 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk,
        register_disk(parent, disk, groups);
        if (register_queue)
                blk_register_queue(disk);
-
-       /*
-        * Take an extra ref on queue which will be put on disk_release()
-        * so that it sticks around as long as @disk is there.
-        */
-       if (blk_get_queue(disk->queue))
-               set_bit(GD_QUEUE_REF, &disk->state);
-       else
-               WARN_ON_ONCE(1);
-
        disk_add_events(disk);
        blk_integrity_add(disk);
 }
@@ -1096,8 +1086,7 @@ static void disk_release(struct device *dev)
        disk_release_events(disk);
        kfree(disk->random);
        xa_destroy(&disk->part_tbl);
-       if (test_bit(GD_QUEUE_REF, &disk->state) && disk->queue)
-               blk_put_queue(disk->queue);
+       blk_put_queue(disk->queue);
        iput(disk->part0->bd_inode);    /* frees the disk */
 }
 
@@ -1268,9 +1257,12 @@ struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,
 {
        struct gendisk *disk;
 
+       if (!blk_get_queue(q))
+               return NULL;
+
        disk = kzalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
        if (!disk)
-               return NULL;
+               goto out_put_queue;
 
        disk->part0 = bdev_alloc(disk, 0);
        if (!disk->part0)
@@ -1297,6 +1289,8 @@ out_destroy_part_tbl:
        iput(disk->part0->bd_inode);
 out_free_disk:
        kfree(disk);
+out_put_queue:
+       blk_put_queue(q);
        return NULL;
 }
 EXPORT_SYMBOL(__alloc_disk_node);
index 875be3bc8afb28ed95170679a9ba9032ee159e07..e94147613d01c0951f1d07e64e15cfd1bcde21ff 100644 (file)
@@ -149,7 +149,6 @@ struct gendisk {
        unsigned long state;
 #define GD_NEED_PART_SCAN              0
 #define GD_READ_ONLY                   1
-#define GD_QUEUE_REF                   2
 
        struct mutex open_mutex;        /* open/close mutex */
        unsigned open_partitions;       /* number of open partitions */