Re: [PATCH 1/2] block: prevent block device lookups at the beginning of del_gendisk

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 12, 2021 at 06:50:49PM +0200, Christoph Hellwig wrote:
> As an aritfact of how gendisk lookup used to work in earlier kernels,
> GENHD_FL_UP is only cleared very late in del_gendisk, and instead a
> global lock is used to prevent opens from actually succeeding.  Clear
> the flag, and remove the bdev inode from the inode hash earlier to
> ensure lookups fail from the very beginning of del_gendisk, and remove
> the now not needed bdev_lookup_sem.
> 
> Signed-off-by: Christoph Hellwig <hch@xxxxxx>
> ---
>  block/genhd.c         | 19 ++-----------------
>  fs/block_dev.c        |  9 +--------
>  include/linux/genhd.h |  2 --
>  3 files changed, 3 insertions(+), 27 deletions(-)
> 
> diff --git a/block/genhd.c b/block/genhd.c
> index 39ca97b0edc6..1693e520ec7d 100644
> --- a/block/genhd.c
> +++ b/block/genhd.c
> @@ -29,8 +29,6 @@
>  
>  static struct kobject *block_depr;
>  
> -DECLARE_RWSEM(bdev_lookup_sem);
> -
>  /* for extended dynamic devt allocation, currently only one major is used */
>  #define NR_EXT_DEVT		(1 << MINORBITS)
>  static DEFINE_IDA(ext_devt_ida);
> @@ -609,28 +607,15 @@ void del_gendisk(struct gendisk *disk)
>  	blk_integrity_del(disk);
>  	disk_del_events(disk);
>  
> -	/*
> -	 * Block lookups of the disk until all bdevs are unhashed and the
> -	 * disk is marked as dead (GENHD_FL_UP cleared).
> -	 */
> -	down_write(&bdev_lookup_sem);
> -
>  	mutex_lock(&disk->part0->bd_mutex);
> +	disk->flags &= ~GENHD_FL_UP;
> +	remove_inode_hash(disk->part0->bd_inode);
>  	blk_drop_partitions(disk);
>  	mutex_unlock(&disk->part0->bd_mutex);

Both bdget() and checking FL_UP is done without holding ->bd_mutex, so
del_gendisk() may be run after checking FL_UP is completed in blkdev_get_no_open(),
then new opener is still allowed even after the bdev is invalidated.

Given this patch is for 5.13, I'd suggest to not move remove_inode_hash()
inside the lock block, which isn't necessary, and it is enough to move
clearing FL_UP with the following change together:

diff --git a/fs/block_dev.c b/fs/block_dev.c
index b8abccd03e5d..31a6d54edf6d 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1298,6 +1298,9 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode)
 	struct gendisk *disk = bdev->bd_disk;
 	int ret = 0;
 
+	if (!(disk->flags & GENHD_FL_UP))
+		return -ENXIO;
+
 	if (!bdev->bd_openers) {
 		if (!bdev_is_partition(bdev)) {
 			ret = 0;
@@ -1332,8 +1335,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode)
 			whole->bd_part_count++;
 			mutex_unlock(&whole->bd_mutex);
 
-			if (!(disk->flags & GENHD_FL_UP) ||
-			    !bdev_nr_sectors(bdev)) {
+			if (!bdev_nr_sectors(bdev)) {
 				__blkdev_put(whole, mode, 1);
 				bdput(whole);
 				return -ENXIO;


Thanks,
Ming




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux