Skip to content

Commit efcf593

Browse files
Ming Leiaxboe
authored andcommitted
block: avoid to touch unloaded module instance when opening bdev
disk->fops->owner is grabbed in blkdev_get_no_open() after the disk kobject refcount is increased. This way can't make sure that disk->fops->owner is still alive since del_gendisk() still can move on if the kobject refcount of disk is grabbed by open() and disk->fops->open() isn't called yet. Fixes the issue by moving try_module_get() into blkdev_get_by_dev() with ->open_mutex() held, then we can drain the in-progress open() in del_gendisk(). Meantime new open() won't succeed because disk becomes not alive. This way is reasonable because blkdev_get_no_open() needn't to touch disk->fops or defined callbacks. Cc: Christoph Hellwig <[email protected]> Cc: [email protected] Signed-off-by: Ming Lei <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 2b504bd commit efcf593

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

block/bdev.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -753,8 +753,7 @@ struct block_device *blkdev_get_no_open(dev_t dev)
753753

754754
if (!bdev)
755755
return NULL;
756-
if ((bdev->bd_disk->flags & GENHD_FL_HIDDEN) ||
757-
!try_module_get(bdev->bd_disk->fops->owner)) {
756+
if ((bdev->bd_disk->flags & GENHD_FL_HIDDEN)) {
758757
put_device(&bdev->bd_device);
759758
return NULL;
760759
}
@@ -764,7 +763,6 @@ struct block_device *blkdev_get_no_open(dev_t dev)
764763

765764
void blkdev_put_no_open(struct block_device *bdev)
766765
{
767-
module_put(bdev->bd_disk->fops->owner);
768766
put_device(&bdev->bd_device);
769767
}
770768

@@ -820,12 +818,14 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
820818
ret = -ENXIO;
821819
if (!disk_live(disk))
822820
goto abort_claiming;
821+
if (!try_module_get(disk->fops->owner))
822+
goto abort_claiming;
823823
if (bdev_is_partition(bdev))
824824
ret = blkdev_get_part(bdev, mode);
825825
else
826826
ret = blkdev_get_whole(bdev, mode);
827827
if (ret)
828-
goto abort_claiming;
828+
goto put_module;
829829
if (mode & FMODE_EXCL) {
830830
bd_finish_claiming(bdev, holder);
831831

@@ -847,7 +847,8 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
847847
if (unblock_events)
848848
disk_unblock_events(disk);
849849
return bdev;
850-
850+
put_module:
851+
module_put(disk->fops->owner);
851852
abort_claiming:
852853
if (mode & FMODE_EXCL)
853854
bd_abort_claiming(bdev, holder);
@@ -956,6 +957,7 @@ void blkdev_put(struct block_device *bdev, fmode_t mode)
956957
blkdev_put_whole(bdev, mode);
957958
mutex_unlock(&disk->open_mutex);
958959

960+
module_put(disk->fops->owner);
959961
blkdev_put_no_open(bdev);
960962
}
961963
EXPORT_SYMBOL(blkdev_put);

0 commit comments

Comments
 (0)