Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <hch@lst.de>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20210514131842.1600568-2-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
6c60ff04 9a66e6bd

+6 -22
+1 -10
block/genhd.c
··· 29 29 30 30 static struct kobject *block_depr; 31 31 32 - DECLARE_RWSEM(bdev_lookup_sem); 33 - 34 32 /* for extended dynamic devt allocation, currently only one major is used */ 35 33 #define NR_EXT_DEVT (1 << MINORBITS) 36 34 static DEFINE_IDA(ext_devt_ida); ··· 607 609 blk_integrity_del(disk); 608 610 disk_del_events(disk); 609 611 610 - /* 611 - * Block lookups of the disk until all bdevs are unhashed and the 612 - * disk is marked as dead (GENHD_FL_UP cleared). 613 - */ 614 - down_write(&bdev_lookup_sem); 615 - 616 612 mutex_lock(&disk->part0->bd_mutex); 613 + disk->flags &= ~GENHD_FL_UP; 617 614 blk_drop_partitions(disk); 618 615 mutex_unlock(&disk->part0->bd_mutex); 619 616 ··· 622 629 remove_inode_hash(disk->part0->bd_inode); 623 630 624 631 set_capacity(disk, 0); 625 - disk->flags &= ~GENHD_FL_UP; 626 - up_write(&bdev_lookup_sem); 627 632 628 633 if (!(disk->flags & GENHD_FL_HIDDEN)) { 629 634 sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
+5 -10
fs/block_dev.c
··· 1298 1298 struct gendisk *disk = bdev->bd_disk; 1299 1299 int ret = 0; 1300 1300 1301 + if (!(disk->flags & GENHD_FL_UP)) 1302 + return -ENXIO; 1303 + 1301 1304 if (!bdev->bd_openers) { 1302 1305 if (!bdev_is_partition(bdev)) { 1303 1306 ret = 0; ··· 1335 1332 whole->bd_part_count++; 1336 1333 mutex_unlock(&whole->bd_mutex); 1337 1334 1338 - if (!(disk->flags & GENHD_FL_UP) || 1339 - !bdev_nr_sectors(bdev)) { 1335 + if (!bdev_nr_sectors(bdev)) { 1340 1336 __blkdev_put(whole, mode, 1); 1341 1337 bdput(whole); 1342 1338 return -ENXIO; ··· 1366 1364 struct block_device *bdev; 1367 1365 struct gendisk *disk; 1368 1366 1369 - down_read(&bdev_lookup_sem); 1370 1367 bdev = bdget(dev); 1371 1368 if (!bdev) { 1372 - up_read(&bdev_lookup_sem); 1373 1369 blk_request_module(dev); 1374 - down_read(&bdev_lookup_sem); 1375 - 1376 1370 bdev = bdget(dev); 1377 1371 if (!bdev) 1378 - goto unlock; 1372 + return NULL; 1379 1373 } 1380 1374 1381 1375 disk = bdev->bd_disk; ··· 1381 1383 goto put_disk; 1382 1384 if (!try_module_get(bdev->bd_disk->fops->owner)) 1383 1385 goto put_disk; 1384 - up_read(&bdev_lookup_sem); 1385 1386 return bdev; 1386 1387 put_disk: 1387 1388 put_disk(disk); 1388 1389 bdput: 1389 1390 bdput(bdev); 1390 - unlock: 1391 - up_read(&bdev_lookup_sem); 1392 1391 return NULL; 1393 1392 } 1394 1393
-2
include/linux/genhd.h
··· 306 306 } 307 307 #endif /* CONFIG_SYSFS */ 308 308 309 - extern struct rw_semaphore bdev_lookup_sem; 310 - 311 309 dev_t blk_lookup_devt(const char *name, int partno); 312 310 void blk_request_module(dev_t devt); 313 311 #ifdef CONFIG_BLOCK