aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-03-09 13:54:27 -0500
committerTejun Heo <tj@kernel.org>2011-03-09 13:54:27 -0500
commit69e02c59a7d962dced8047401b81a8d897e1702e (patch)
treec1dc1ef45a7f2e8cda6189eb441320bd637e877b
parent6936217cc7e58573026bdba25b1bfb778e8f2267 (diff)
block: Don't check events while open is in progress
Not all block drivers clear events immediately after reporting. Some do so in ->revalidate_disk() or other steps during ->open(). There is a slim chance event poll may happen between the clearing event check from check_disk_change() and the actual clearing of the events which would result in spurious events. Block event checks while block device open is in progress. There is no need to kick explicit event check afterwards as events are always checked during open. -v2: The original patch could have called disk_unblock_events() with an already released or %NULL @disk causing oops. Fixed by making sure references are put after disk_unblock_events() is called. It also makes the error path of __blkdev_get() a bit simpler. This problem was reported by Jens. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Jens Axboe <axboe@kernel.dk> Cc: Kay Sievers <kay.sievers@vrfy.org>
-rw-r--r--fs/block_dev.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 7dd2c658d42..d42cad2757a 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1087,6 +1087,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
1087 if (!disk) 1087 if (!disk)
1088 goto out; 1088 goto out;
1089 1089
1090 disk_block_events(disk);
1090 mutex_lock_nested(&bdev->bd_mutex, for_part); 1091 mutex_lock_nested(&bdev->bd_mutex, for_part);
1091 if (!bdev->bd_openers) { 1092 if (!bdev->bd_openers) {
1092 bdev->bd_disk = disk; 1093 bdev->bd_disk = disk;
@@ -1108,10 +1109,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
1108 */ 1109 */
1109 disk_put_part(bdev->bd_part); 1110 disk_put_part(bdev->bd_part);
1110 bdev->bd_part = NULL; 1111 bdev->bd_part = NULL;
1111 module_put(disk->fops->owner);
1112 put_disk(disk);
1113 bdev->bd_disk = NULL; 1112 bdev->bd_disk = NULL;
1114 mutex_unlock(&bdev->bd_mutex); 1113 mutex_unlock(&bdev->bd_mutex);
1114 disk_unblock_events(disk);
1115 module_put(disk->fops->owner);
1116 put_disk(disk);
1115 goto restart; 1117 goto restart;
1116 } 1118 }
1117 if (ret) 1119 if (ret)
@@ -1148,9 +1150,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
1148 bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9); 1150 bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
1149 } 1151 }
1150 } else { 1152 } else {
1151 module_put(disk->fops->owner);
1152 put_disk(disk);
1153 disk = NULL;
1154 if (bdev->bd_contains == bdev) { 1153 if (bdev->bd_contains == bdev) {
1155 if (bdev->bd_disk->fops->open) { 1154 if (bdev->bd_disk->fops->open) {
1156 ret = bdev->bd_disk->fops->open(bdev, mode); 1155 ret = bdev->bd_disk->fops->open(bdev, mode);
@@ -1160,11 +1159,15 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
1160 if (bdev->bd_invalidated) 1159 if (bdev->bd_invalidated)
1161 rescan_partitions(bdev->bd_disk, bdev); 1160 rescan_partitions(bdev->bd_disk, bdev);
1162 } 1161 }
1162 /* only one opener holds refs to the module and disk */
1163 module_put(disk->fops->owner);
1164 put_disk(disk);
1163 } 1165 }
1164 bdev->bd_openers++; 1166 bdev->bd_openers++;
1165 if (for_part) 1167 if (for_part)
1166 bdev->bd_part_count++; 1168 bdev->bd_part_count++;
1167 mutex_unlock(&bdev->bd_mutex); 1169 mutex_unlock(&bdev->bd_mutex);
1170 disk_unblock_events(disk);
1168 return 0; 1171 return 0;
1169 1172
1170 out_clear: 1173 out_clear:
@@ -1177,9 +1180,9 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
1177 bdev->bd_contains = NULL; 1180 bdev->bd_contains = NULL;
1178 out_unlock_bdev: 1181 out_unlock_bdev:
1179 mutex_unlock(&bdev->bd_mutex); 1182 mutex_unlock(&bdev->bd_mutex);
1183 disk_unblock_events(disk);
1180 out: 1184 out:
1181 if (disk) 1185 module_put(disk->fops->owner);
1182 module_put(disk->fops->owner);
1183 put_disk(disk); 1186 put_disk(disk);
1184 bdput(bdev); 1187 bdput(bdev);
1185 1188