Skip to content

Commit 6c60ff0

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: prevent block device lookups at the beginning of del_gendisk
As an artifact of how gendisk lookup used to work in earlier kernels, GENHD_FL_UP is only cleared very late in del_gendisk, and a global lock is used to prevent opens from succeeding while del_gendisk is tearing down the gendisk. Switch to clearing the flag early and under bd_mutex so that callers can use bd_mutex to stabilize the flag, which removes the need for the global mutex. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Ming Lei <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 9a66e6b commit 6c60ff0

File tree

3 files changed

+6
-22
lines changed

3 files changed

+6
-22
lines changed

block/genhd.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929

3030
static struct kobject *block_depr;
3131

32-
DECLARE_RWSEM(bdev_lookup_sem);
33-
3432
/* for extended dynamic devt allocation, currently only one major is used */
3533
#define NR_EXT_DEVT (1 << MINORBITS)
3634
static DEFINE_IDA(ext_devt_ida);
@@ -609,13 +607,8 @@ void del_gendisk(struct gendisk *disk)
609607
blk_integrity_del(disk);
610608
disk_del_events(disk);
611609

612-
/*
613-
* Block lookups of the disk until all bdevs are unhashed and the
614-
* disk is marked as dead (GENHD_FL_UP cleared).
615-
*/
616-
down_write(&bdev_lookup_sem);
617-
618610
mutex_lock(&disk->part0->bd_mutex);
611+
disk->flags &= ~GENHD_FL_UP;
619612
blk_drop_partitions(disk);
620613
mutex_unlock(&disk->part0->bd_mutex);
621614

@@ -629,8 +622,6 @@ void del_gendisk(struct gendisk *disk)
629622
remove_inode_hash(disk->part0->bd_inode);
630623

631624
set_capacity(disk, 0);
632-
disk->flags &= ~GENHD_FL_UP;
633-
up_write(&bdev_lookup_sem);
634625

635626
if (!(disk->flags & GENHD_FL_HIDDEN)) {
636627
sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");

fs/block_dev.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,9 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode)
12981298
struct gendisk *disk = bdev->bd_disk;
12991299
int ret = 0;
13001300

1301+
if (!(disk->flags & GENHD_FL_UP))
1302+
return -ENXIO;
1303+
13011304
if (!bdev->bd_openers) {
13021305
if (!bdev_is_partition(bdev)) {
13031306
ret = 0;
@@ -1332,8 +1335,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode)
13321335
whole->bd_part_count++;
13331336
mutex_unlock(&whole->bd_mutex);
13341337

1335-
if (!(disk->flags & GENHD_FL_UP) ||
1336-
!bdev_nr_sectors(bdev)) {
1338+
if (!bdev_nr_sectors(bdev)) {
13371339
__blkdev_put(whole, mode, 1);
13381340
bdput(whole);
13391341
return -ENXIO;
@@ -1364,16 +1366,12 @@ struct block_device *blkdev_get_no_open(dev_t dev)
13641366
struct block_device *bdev;
13651367
struct gendisk *disk;
13661368

1367-
down_read(&bdev_lookup_sem);
13681369
bdev = bdget(dev);
13691370
if (!bdev) {
1370-
up_read(&bdev_lookup_sem);
13711371
blk_request_module(dev);
1372-
down_read(&bdev_lookup_sem);
1373-
13741372
bdev = bdget(dev);
13751373
if (!bdev)
1376-
goto unlock;
1374+
return NULL;
13771375
}
13781376

13791377
disk = bdev->bd_disk;
@@ -1383,14 +1381,11 @@ struct block_device *blkdev_get_no_open(dev_t dev)
13831381
goto put_disk;
13841382
if (!try_module_get(bdev->bd_disk->fops->owner))
13851383
goto put_disk;
1386-
up_read(&bdev_lookup_sem);
13871384
return bdev;
13881385
put_disk:
13891386
put_disk(disk);
13901387
bdput:
13911388
bdput(bdev);
1392-
unlock:
1393-
up_read(&bdev_lookup_sem);
13941389
return NULL;
13951390
}
13961391

include/linux/genhd.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,6 @@ static inline void bd_unlink_disk_holder(struct block_device *bdev,
306306
}
307307
#endif /* CONFIG_SYSFS */
308308

309-
extern struct rw_semaphore bdev_lookup_sem;
310-
311309
dev_t blk_lookup_devt(const char *name, int partno);
312310
void blk_request_module(dev_t devt);
313311
#ifdef CONFIG_BLOCK

0 commit comments

Comments
 (0)