Skip to content

Commit

Permalink
block: fix __blkdev_get() for removable devices
Browse files Browse the repository at this point in the history
Commit 0762b8b moved disk_get_part()
in front of recursive get on the whole disk, which caused removable
devices to try disk_get_part() before rescanning after a new media is
inserted, which might fail legit open attempts or give the old
partition.

This patch fixes the problem by moving disk_get_part() after
__blkdev_get() on the whole disk.

This problem was spotted by Borislav Petkov.

Signed-off-by: Tejun Heo <tj@kernel.org>
Tested-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
  • Loading branch information
Tejun Heo authored and Jens Axboe committed Nov 6, 2008
1 parent 561920a commit 89f9749
Showing 1 changed file with 11 additions and 12 deletions.
23 changes: 11 additions & 12 deletions fs/block_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,6 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part);
static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
{
struct gendisk *disk;
struct hd_struct *part = NULL;
int ret;
int partno;
int perm = 0;
Expand All @@ -1004,24 +1003,25 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
return ret;
}

ret = -ENXIO;

lock_kernel();

ret = -ENXIO;
disk = get_gendisk(bdev->bd_dev, &partno);
if (!disk)
goto out_unlock_kernel;
part = disk_get_part(disk, partno);
if (!part)
goto out_unlock_kernel;

mutex_lock_nested(&bdev->bd_mutex, for_part);
if (!bdev->bd_openers) {
bdev->bd_disk = disk;
bdev->bd_part = part;
bdev->bd_contains = bdev;
if (!partno) {
struct backing_dev_info *bdi;

ret = -ENXIO;
bdev->bd_part = disk_get_part(disk, partno);
if (!bdev->bd_part)
goto out_clear;

if (disk->fops->open) {
ret = disk->fops->open(bdev, mode);
if (ret)
Expand Down Expand Up @@ -1049,18 +1049,17 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
bdev->bd_contains = whole;
bdev->bd_inode->i_data.backing_dev_info =
whole->bd_inode->i_data.backing_dev_info;
bdev->bd_part = disk_get_part(disk, partno);
if (!(disk->flags & GENHD_FL_UP) ||
!part || !part->nr_sects) {
!bdev->bd_part || !bdev->bd_part->nr_sects) {
ret = -ENXIO;
goto out_clear;
}
bd_set_size(bdev, (loff_t)part->nr_sects << 9);
bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
}
} else {
disk_put_part(part);
put_disk(disk);
module_put(disk->fops->owner);
part = NULL;
disk = NULL;
if (bdev->bd_contains == bdev) {
if (bdev->bd_disk->fops->open) {
Expand All @@ -1080,6 +1079,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
return 0;

out_clear:
disk_put_part(bdev->bd_part);
bdev->bd_disk = NULL;
bdev->bd_part = NULL;
bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
Expand All @@ -1091,7 +1091,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
out_unlock_kernel:
unlock_kernel();

disk_put_part(part);
if (disk)
module_put(disk->fops->owner);
put_disk(disk);
Expand Down

0 comments on commit 89f9749

Please sign in to comment.