diff mbox series

[14/23,SRU,OEM-5.14] block: hold a request_queue reference for the lifetime of struct gendisk

Message ID 20220128032610.392273-15-koba.ko@canonical.com
State Accepted
Headers show
Series USB port lost function after unplugging usb drive | expand

Commit Message

Koba Ko Jan. 28, 2022, 3:26 a.m. UTC
From: Christoph Hellwig <hch@lst.de>

BugLink: https://bugs.launchpad.net/bugs/1958850 

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>
(cherry picked from commit 61a35cfc26334fe1c8e970ca8fafeae2daae257d)
Signed-off-by: Koba Ko <koba.ko@canonical.com>
---
 block/genhd.c         | 28 +++++++++++++++-------------
 include/linux/genhd.h |  1 -
 2 files changed, 15 insertions(+), 14 deletions(-)
diff mbox series

Patch

diff --git a/block/genhd.c b/block/genhd.c
index 5972ed8bb0c36..82485742c282c 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -548,15 +548,6 @@  static void __device_add_disk(struct device *parent, struct gendisk *disk,
 	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);
 }
@@ -1103,9 +1094,15 @@  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);
-	bdput(disk->part0);	/* frees the disk */
+	blk_put_queue(disk->queue);
+	iput(disk->part0->bd_inode);	/* frees the disk */
+}
+
+static int block_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+
+	return add_uevent_var(env, "DISKSEQ=%llu", disk->diskseq);
 }
 struct class block_class = {
 	.name		= "block",
@@ -1268,9 +1265,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)
@@ -1305,6 +1305,8 @@  struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,
 	bdi_put(disk->bdi);
 out_free_disk:
 	kfree(disk);
+out_put_queue:
+	blk_put_queue(q);
 	return NULL;
 }
 EXPORT_SYMBOL(__alloc_disk_node);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 167b547ded75e..522bc090e2945 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -153,7 +153,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 */