diff mbox series

[PATCHv2] block: fix leaking minors of hidden disks

Message ID 20221007193825.4058951-1-kbusch@meta.com (mailing list archive)
State New, archived
Headers show
Series [PATCHv2] block: fix leaking minors of hidden disks | expand

Commit Message

Keith Busch Oct. 7, 2022, 7:38 p.m. UTC
From: Keith Busch <kbusch@kernel.org>

The major/minor of a hidden gendisk is not propagated to the block
device. This is required to suppress it from being visible. For these
disks, we need to handle freeing the dynamic minor directly when it's
released since bdev_free_inode() won't be able to.

Cc: Christoph Hellwig <hch@lst.de>
Reported-by: Daniel Wagner <dwagner@suse.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
---
v1->v2:

  Actually check that the disk is hidden before assuming the minor needs
  to be freed.

 block/genhd.c | 2 ++
 1 file changed, 2 insertions(+)

Comments

Daniel Wagner Oct. 10, 2022, 6:43 a.m. UTC | #1
On Fri, Oct 07, 2022 at 12:38:25PM -0700, Keith Busch wrote:
> From: Keith Busch <kbusch@kernel.org>
> 
> The major/minor of a hidden gendisk is not propagated to the block
> device. This is required to suppress it from being visible. For these
> disks, we need to handle freeing the dynamic minor directly when it's
> released since bdev_free_inode() won't be able to.
> 
> Cc: Christoph Hellwig <hch@lst.de>
> Reported-by: Daniel Wagner <dwagner@suse.de>
> Signed-off-by: Keith Busch <kbusch@kernel.org>

Thanks for the quick fix!

Tested-by: Daniel Wagner <dwagner@suse.de>

# ls -l /dev/nvme*
crw------- 1 root root  10, 124 Oct 10 08:39 /dev/nvme-fabrics
crw------- 1 root root 243,   0 Oct 10 08:38 /dev/nvme0
brw-rw---- 1 root disk 259,   0 Oct 10 08:38 /dev/nvme0n1
crw------- 1 root root 243,   2 Oct 10 08:41 /dev/nvme2
brw-rw---- 1 root disk 259,   2 Oct 10 08:41 /dev/nvme2n1
brw-rw---- 1 root disk 259,   3 Oct 10 08:41 /dev/nvme2n1p1
brw-rw---- 1 root disk 259,   5 Oct 10 08:41 /dev/nvme2n2
brw-rw---- 1 root disk 259,   7 Oct 10 08:41 /dev/nvme2n3
brw-rw---- 1 root disk 259,   9 Oct 10 08:41 /dev/nvme2n4
crw------- 1 root root 243,   3 Oct 10 08:41 /dev/nvme3
crw------- 1 root root 243,   4 Oct 10 08:41 /dev/nvme4
crw------- 1 root root 243,   5 Oct 10 08:41 /dev/nvme5
# nvme disconnect-all
# nvme connect-all
# ls -l /dev/nvme*
crw------- 1 root root  10, 124 Oct 10 08:39 /dev/nvme-fabrics
crw------- 1 root root 243,   0 Oct 10 08:38 /dev/nvme0
brw-rw---- 1 root disk 259,   0 Oct 10 08:38 /dev/nvme0n1
crw------- 1 root root 243,   2 Oct 10 08:41 /dev/nvme2
brw-rw---- 1 root disk 259,   2 Oct 10 08:41 /dev/nvme2n1
brw-rw---- 1 root disk 259,   3 Oct 10 08:41 /dev/nvme2n1p1
brw-rw---- 1 root disk 259,   5 Oct 10 08:41 /dev/nvme2n2
brw-rw---- 1 root disk 259,   7 Oct 10 08:41 /dev/nvme2n3
brw-rw---- 1 root disk 259,   9 Oct 10 08:41 /dev/nvme2n4
crw------- 1 root root 243,   3 Oct 10 08:41 /dev/nvme3
crw------- 1 root root 243,   4 Oct 10 08:41 /dev/nvme4
crw------- 1 root root 243,   5 Oct 10 08:41 /dev/nvme5
Chaitanya Kulkarni Oct. 10, 2022, 6:51 a.m. UTC | #2
On 10/7/22 12:38, Keith Busch wrote:
> From: Keith Busch <kbusch@kernel.org>
> 
> The major/minor of a hidden gendisk is not propagated to the block
> device. This is required to suppress it from being visible. For these
> disks, we need to handle freeing the dynamic minor directly when it's
> released since bdev_free_inode() won't be able to.
> 
> Cc: Christoph Hellwig <hch@lst.de>
> Reported-by: Daniel Wagner <dwagner@suse.de>
> Signed-off-by: Keith Busch <kbusch@kernel.org>
> ---
> v1->v2:
> 
>    Actually check that the disk is hidden before assuming the minor needs
>    to be freed.
> 
>   block/genhd.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/block/genhd.c b/block/genhd.c
> index 514395361d7c..0afcdbb7575c 100644
> --- a/block/genhd.c
> +++ b/block/genhd.c
> @@ -1166,6 +1166,8 @@ static void disk_release(struct device *dev)
>   	if (test_bit(GD_ADDED, &disk->state) && disk->fops->free_disk)
>   		disk->fops->free_disk(disk);
>   
> +	if ((disk->flags & GENHD_FL_HIDDEN) && disk->major == BLOCK_EXT_MAJOR)
> +		blk_free_ext_minor(disk->first_minor);
>   	iput(disk->part0->bd_inode);	/* frees the disk */
>   }
>   


Looks good.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>

-ck
Christoph Hellwig Oct. 10, 2022, 7:36 a.m. UTC | #3
On Fri, Oct 07, 2022 at 12:38:25PM -0700, Keith Busch wrote:
> From: Keith Busch <kbusch@kernel.org>
> 
> The major/minor of a hidden gendisk is not propagated to the block
> device. This is required to suppress it from being visible. For these
> disks, we need to handle freeing the dynamic minor directly when it's
> released since bdev_free_inode() won't be able to.

This now leads to a different lifetime.  I think the proper fix is
the one below (untested):

diff --git a/block/genhd.c b/block/genhd.c
index d36fabf0abc1f..1752ce356484e 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -507,6 +507,8 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
 		 */
 		dev_set_uevent_suppress(ddev, 0);
 		disk_uevent(disk, KOBJ_ADD);
+	} else {
+		disk->part0->bd_dev = ddev->devt;
 	}
 
 	disk_update_readahead(disk);
Daniel Wagner Oct. 10, 2022, 8:02 a.m. UTC | #4
On Mon, Oct 10, 2022 at 12:36:26AM -0700, Christoph Hellwig wrote:
> On Fri, Oct 07, 2022 at 12:38:25PM -0700, Keith Busch wrote:
> > From: Keith Busch <kbusch@kernel.org>
> > 
> > The major/minor of a hidden gendisk is not propagated to the block
> > device. This is required to suppress it from being visible. For these
> > disks, we need to handle freeing the dynamic minor directly when it's
> > released since bdev_free_inode() won't be able to.
> 
> This now leads to a different lifetime.  I think the proper fix is
> the one below (untested):
> 
> diff --git a/block/genhd.c b/block/genhd.c
> index d36fabf0abc1f..1752ce356484e 100644
> --- a/block/genhd.c
> +++ b/block/genhd.c
> @@ -507,6 +507,8 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
>  		 */
>  		dev_set_uevent_suppress(ddev, 0);
>  		disk_uevent(disk, KOBJ_ADD);
> +	} else {
> +		disk->part0->bd_dev = ddev->devt;
>  	}
>  
>  	disk_update_readahead(disk);

Doesn't give me the same consistent result as with Keith's version:

# ls -l /dev/nvme*
crw------- 1 root root  10, 124 Oct 10 10:00 /dev/nvme-fabrics
crw------- 1 root root 243,   0 Oct 10 09:58 /dev/nvme0
brw-rw---- 1 root disk 259,   0 Oct 10 09:58 /dev/nvme0n1
crw------- 1 root root 243,   2 Oct 10 10:00 /dev/nvme2
brw-rw---- 1 root disk 259,   2 Oct 10 10:00 /dev/nvme2n1
brw-rw---- 1 root disk 259,   3 Oct 10 10:00 /dev/nvme2n1p1
brw-rw---- 1 root disk 259,   5 Oct 10 10:00 /dev/nvme2n2
brw-rw---- 1 root disk 259,   7 Oct 10 10:00 /dev/nvme2n3
brw-rw---- 1 root disk 259,   9 Oct 10 10:00 /dev/nvme2n4
crw------- 1 root root 243,   3 Oct 10 10:00 /dev/nvme3
crw------- 1 root root 243,   4 Oct 10 10:00 /dev/nvme4
crw------- 1 root root 243,   5 Oct 10 10:00 /dev/nvme5
# nvme disconnect-all
# nvme connect-all
# ls -l /dev/nvme*
crw------- 1 root root  10, 124 Oct 10 10:00 /dev/nvme-fabrics
crw------- 1 root root 243,   0 Oct 10 09:58 /dev/nvme0
brw-rw---- 1 root disk 259,   0 Oct 10 09:58 /dev/nvme0n1
crw------- 1 root root 243,   2 Oct 10 10:00 /dev/nvme2
brw-rw---- 1 root disk 259,   3 Oct 10 10:00 /dev/nvme2n1
brw-rw---- 1 root disk 259,   5 Oct 10 10:00 /dev/nvme2n1p1
brw-rw---- 1 root disk 259,   9 Oct 10 10:00 /dev/nvme2n2
brw-rw---- 1 root disk 259,  23 Oct 10 10:00 /dev/nvme2n3
brw-rw---- 1 root disk 259,  25 Oct 10 10:00 /dev/nvme2n4
crw------- 1 root root 243,   3 Oct 10 10:00 /dev/nvme3
crw------- 1 root root 243,   4 Oct 10 10:00 /dev/nvme4
crw------- 1 root root 243,   5 Oct 10 10:00 /dev/nvme5
Christoph Hellwig Oct. 10, 2022, 8:19 a.m. UTC | #5
On Mon, Oct 10, 2022 at 10:02:18AM +0200, Daniel Wagner wrote:
> Doesn't give me the same consistent result as with Keith's version:

That's because it is broken..  Try this version:

diff --git a/block/genhd.c b/block/genhd.c
index 514395361d7c5..2296ad422523a 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -507,6 +507,8 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
 		 */
 		dev_set_uevent_suppress(ddev, 0);
 		disk_uevent(disk, KOBJ_ADD);
+	} else {
+		disk->part0->bd_dev = MKDEV(disk->major, disk->first_minor);
 	}
 
 	disk_update_readahead(disk);
Daniel Wagner Oct. 10, 2022, 8:49 a.m. UTC | #6
On Mon, Oct 10, 2022 at 10:19:02AM +0200, Christoph Hellwig wrote:
> On Mon, Oct 10, 2022 at 10:02:18AM +0200, Daniel Wagner wrote:
> > Doesn't give me the same consistent result as with Keith's version:
> 
> That's because it is broken..  Try this version:

This version works.

Tested-by: Daniel Wagner <dwagner@suse.de>

# ls -l /dev/nvme*
crw------- 1 root root  10, 124 Oct 10 10:47 /dev/nvme-fabrics
crw------- 1 root root 243,   0 Oct 10 10:46 /dev/nvme0
brw-rw---- 1 root disk 259,   0 Oct 10 10:46 /dev/nvme0n1
crw------- 1 root root 243,   2 Oct 10 10:48 /dev/nvme2
brw-rw---- 1 root disk 259,   2 Oct 10 10:48 /dev/nvme2n1
brw-rw---- 1 root disk 259,   3 Oct 10 10:48 /dev/nvme2n1p1
brw-rw---- 1 root disk 259,   5 Oct 10 10:48 /dev/nvme2n2
brw-rw---- 1 root disk 259,   7 Oct 10 10:48 /dev/nvme2n3
brw-rw---- 1 root disk 259,   9 Oct 10 10:48 /dev/nvme2n4
crw------- 1 root root 243,   3 Oct 10 10:48 /dev/nvme3
crw------- 1 root root 243,   4 Oct 10 10:48 /dev/nvme4
crw------- 1 root root 243,   5 Oct 10 10:48 /dev/nvme5
# nvme disconnect-all
# nvme connect-all
# ls -l /dev/nvme*
crw------- 1 root root  10, 124 Oct 10 10:47 /dev/nvme-fabrics
crw------- 1 root root 243,   0 Oct 10 10:46 /dev/nvme0
brw-rw---- 1 root disk 259,   0 Oct 10 10:46 /dev/nvme0n1
crw------- 1 root root 243,   2 Oct 10 10:48 /dev/nvme2
brw-rw---- 1 root disk 259,   2 Oct 10 10:48 /dev/nvme2n1
brw-rw---- 1 root disk 259,   3 Oct 10 10:48 /dev/nvme2n1p1
brw-rw---- 1 root disk 259,   5 Oct 10 10:48 /dev/nvme2n2
brw-rw---- 1 root disk 259,   7 Oct 10 10:48 /dev/nvme2n3
brw-rw---- 1 root disk 259,   9 Oct 10 10:48 /dev/nvme2n4
crw------- 1 root root 243,   3 Oct 10 10:48 /dev/nvme3
crw------- 1 root root 243,   4 Oct 10 10:48 /dev/nvme4
crw------- 1 root root 243,   5 Oct 10 10:48 /dev/nvme5
diff mbox series

Patch

diff --git a/block/genhd.c b/block/genhd.c
index 514395361d7c..0afcdbb7575c 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1166,6 +1166,8 @@  static void disk_release(struct device *dev)
 	if (test_bit(GD_ADDED, &disk->state) && disk->fops->free_disk)
 		disk->fops->free_disk(disk);
 
+	if ((disk->flags & GENHD_FL_HIDDEN) && disk->major == BLOCK_EXT_MAJOR)
+		blk_free_ext_minor(disk->first_minor);
 	iput(disk->part0->bd_inode);	/* frees the disk */
 }