diff options
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 5147bdd3b8e1..257b00e98428 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1102,6 +1102,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1102 | if (!bdev->bd_part) | 1102 | if (!bdev->bd_part) |
1103 | goto out_clear; | 1103 | goto out_clear; |
1104 | 1104 | ||
1105 | ret = 0; | ||
1105 | if (disk->fops->open) { | 1106 | if (disk->fops->open) { |
1106 | ret = disk->fops->open(bdev, mode); | 1107 | ret = disk->fops->open(bdev, mode); |
1107 | if (ret == -ERESTARTSYS) { | 1108 | if (ret == -ERESTARTSYS) { |
@@ -1118,9 +1119,18 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1118 | put_disk(disk); | 1119 | put_disk(disk); |
1119 | goto restart; | 1120 | goto restart; |
1120 | } | 1121 | } |
1121 | if (ret) | ||
1122 | goto out_clear; | ||
1123 | } | 1122 | } |
1123 | /* | ||
1124 | * If the device is invalidated, rescan partition | ||
1125 | * if open succeeded or failed with -ENOMEDIUM. | ||
1126 | * The latter is necessary to prevent ghost | ||
1127 | * partitions on a removed medium. | ||
1128 | */ | ||
1129 | if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) | ||
1130 | rescan_partitions(disk, bdev); | ||
1131 | if (ret) | ||
1132 | goto out_clear; | ||
1133 | |||
1124 | if (!bdev->bd_openers) { | 1134 | if (!bdev->bd_openers) { |
1125 | bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); | 1135 | bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); |
1126 | bdi = blk_get_backing_dev_info(bdev); | 1136 | bdi = blk_get_backing_dev_info(bdev); |
@@ -1128,8 +1138,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1128 | bdi = &default_backing_dev_info; | 1138 | bdi = &default_backing_dev_info; |
1129 | bdev_inode_switch_bdi(bdev->bd_inode, bdi); | 1139 | bdev_inode_switch_bdi(bdev->bd_inode, bdi); |
1130 | } | 1140 | } |
1131 | if (bdev->bd_invalidated) | ||
1132 | rescan_partitions(disk, bdev); | ||
1133 | } else { | 1141 | } else { |
1134 | struct block_device *whole; | 1142 | struct block_device *whole; |
1135 | whole = bdget_disk(disk, 0); | 1143 | whole = bdget_disk(disk, 0); |
@@ -1153,13 +1161,14 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1153 | } | 1161 | } |
1154 | } else { | 1162 | } else { |
1155 | if (bdev->bd_contains == bdev) { | 1163 | if (bdev->bd_contains == bdev) { |
1156 | if (bdev->bd_disk->fops->open) { | 1164 | ret = 0; |
1165 | if (bdev->bd_disk->fops->open) | ||
1157 | ret = bdev->bd_disk->fops->open(bdev, mode); | 1166 | ret = bdev->bd_disk->fops->open(bdev, mode); |
1158 | if (ret) | 1167 | /* the same as first opener case, read comment there */ |
1159 | goto out_unlock_bdev; | 1168 | if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) |
1160 | } | ||
1161 | if (bdev->bd_invalidated) | ||
1162 | rescan_partitions(bdev->bd_disk, bdev); | 1169 | rescan_partitions(bdev->bd_disk, bdev); |
1170 | if (ret) | ||
1171 | goto out_unlock_bdev; | ||
1163 | } | 1172 | } |
1164 | /* only one opener holds refs to the module and disk */ | 1173 | /* only one opener holds refs to the module and disk */ |
1165 | module_put(disk->fops->owner); | 1174 | module_put(disk->fops->owner); |