diff options
author | Tejun Heo <tj@kernel.org> | 2008-11-05 04:21:06 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-11-06 02:41:56 -0500 |
commit | 89f97496e81d2112b5e41416fe3020688c443818 (patch) | |
tree | e78122150d550bf644ca1a96916a5880823d3e04 /fs | |
parent | 561920a0d2bb6d63343e83acfd784c0a77bd28d1 (diff) |
block: fix __blkdev_get() for removable devices
Commit 0762b8bde9729f10f8e6249809660ff2ec3ad735 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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/block_dev.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 88a776fa0ef6..db831efbdbbd 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -986,7 +986,6 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part); | |||
986 | static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | 986 | static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) |
987 | { | 987 | { |
988 | struct gendisk *disk; | 988 | struct gendisk *disk; |
989 | struct hd_struct *part = NULL; | ||
990 | int ret; | 989 | int ret; |
991 | int partno; | 990 | int partno; |
992 | int perm = 0; | 991 | int perm = 0; |
@@ -1004,24 +1003,25 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1004 | return ret; | 1003 | return ret; |
1005 | } | 1004 | } |
1006 | 1005 | ||
1007 | ret = -ENXIO; | ||
1008 | |||
1009 | lock_kernel(); | 1006 | lock_kernel(); |
1010 | 1007 | ||
1008 | ret = -ENXIO; | ||
1011 | disk = get_gendisk(bdev->bd_dev, &partno); | 1009 | disk = get_gendisk(bdev->bd_dev, &partno); |
1012 | if (!disk) | 1010 | if (!disk) |
1013 | goto out_unlock_kernel; | 1011 | goto out_unlock_kernel; |
1014 | part = disk_get_part(disk, partno); | ||
1015 | if (!part) | ||
1016 | goto out_unlock_kernel; | ||
1017 | 1012 | ||
1018 | mutex_lock_nested(&bdev->bd_mutex, for_part); | 1013 | mutex_lock_nested(&bdev->bd_mutex, for_part); |
1019 | if (!bdev->bd_openers) { | 1014 | if (!bdev->bd_openers) { |
1020 | bdev->bd_disk = disk; | 1015 | bdev->bd_disk = disk; |
1021 | bdev->bd_part = part; | ||
1022 | bdev->bd_contains = bdev; | 1016 | bdev->bd_contains = bdev; |
1023 | if (!partno) { | 1017 | if (!partno) { |
1024 | struct backing_dev_info *bdi; | 1018 | struct backing_dev_info *bdi; |
1019 | |||
1020 | ret = -ENXIO; | ||
1021 | bdev->bd_part = disk_get_part(disk, partno); | ||
1022 | if (!bdev->bd_part) | ||
1023 | goto out_clear; | ||
1024 | |||
1025 | if (disk->fops->open) { | 1025 | if (disk->fops->open) { |
1026 | ret = disk->fops->open(bdev, mode); | 1026 | ret = disk->fops->open(bdev, mode); |
1027 | if (ret) | 1027 | if (ret) |
@@ -1049,18 +1049,17 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1049 | bdev->bd_contains = whole; | 1049 | bdev->bd_contains = whole; |
1050 | bdev->bd_inode->i_data.backing_dev_info = | 1050 | bdev->bd_inode->i_data.backing_dev_info = |
1051 | whole->bd_inode->i_data.backing_dev_info; | 1051 | whole->bd_inode->i_data.backing_dev_info; |
1052 | bdev->bd_part = disk_get_part(disk, partno); | ||
1052 | if (!(disk->flags & GENHD_FL_UP) || | 1053 | if (!(disk->flags & GENHD_FL_UP) || |
1053 | !part || !part->nr_sects) { | 1054 | !bdev->bd_part || !bdev->bd_part->nr_sects) { |
1054 | ret = -ENXIO; | 1055 | ret = -ENXIO; |
1055 | goto out_clear; | 1056 | goto out_clear; |
1056 | } | 1057 | } |
1057 | bd_set_size(bdev, (loff_t)part->nr_sects << 9); | 1058 | bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9); |
1058 | } | 1059 | } |
1059 | } else { | 1060 | } else { |
1060 | disk_put_part(part); | ||
1061 | put_disk(disk); | 1061 | put_disk(disk); |
1062 | module_put(disk->fops->owner); | 1062 | module_put(disk->fops->owner); |
1063 | part = NULL; | ||
1064 | disk = NULL; | 1063 | disk = NULL; |
1065 | if (bdev->bd_contains == bdev) { | 1064 | if (bdev->bd_contains == bdev) { |
1066 | if (bdev->bd_disk->fops->open) { | 1065 | if (bdev->bd_disk->fops->open) { |
@@ -1080,6 +1079,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1080 | return 0; | 1079 | return 0; |
1081 | 1080 | ||
1082 | out_clear: | 1081 | out_clear: |
1082 | disk_put_part(bdev->bd_part); | ||
1083 | bdev->bd_disk = NULL; | 1083 | bdev->bd_disk = NULL; |
1084 | bdev->bd_part = NULL; | 1084 | bdev->bd_part = NULL; |
1085 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | 1085 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; |
@@ -1091,7 +1091,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1091 | out_unlock_kernel: | 1091 | out_unlock_kernel: |
1092 | unlock_kernel(); | 1092 | unlock_kernel(); |
1093 | 1093 | ||
1094 | disk_put_part(part); | ||
1095 | if (disk) | 1094 | if (disk) |
1096 | module_put(disk->fops->owner); | 1095 | module_put(disk->fops->owner); |
1097 | put_disk(disk); | 1096 | put_disk(disk); |