aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2021-08-16 15:19:09 +0200
committerJens Axboe <axboe@kernel.dk>2021-08-23 12:54:31 -0600
commit61a35cfc26334fe1c8e970ca8fafeae2daae257d (patch)
tree73d024e0f1f89f96495780aaea0c2305b5f3412b /block
parent4a1fa41d304c7129328d4d5c7f31715b95e23b29 (diff)
block: hold a request_queue reference for the lifetime of struct gendisk
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> Link: https://lore.kernel.org/r/20210816131910.615153-9-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/genhd.c19
1 files changed, 7 insertions, 12 deletions
diff --git a/block/genhd.c b/block/genhd.c
index f18122ee2778..6294517cebe6 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -551,15 +551,6 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
register_disk(parent, disk, groups);
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);
}
@@ -1087,8 +1078,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 */
}
@@ -1259,9 +1249,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->bdi = bdi_alloc(node_id);
if (!disk->bdi)
@@ -1296,6 +1289,8 @@ out_free_bdi:
bdi_put(disk->bdi);
out_free_disk:
kfree(disk);
+out_put_queue:
+ blk_put_queue(q);
return NULL;
}
EXPORT_SYMBOL(__alloc_disk_node);