aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2006-05-05 12:57:52 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-05-05 12:57:52 -0400
commit56cf6504fc1c0c221b82cebc16a444b684140fb7 (patch)
tree95c74c06397dfe29081afb7a38ad6f1810e0704b /block
parentd98550e334715b2d9e45f8f0f4e1608720108640 (diff)
[BLOCK] Fix oops on removal of SD/MMC card
The block layer keeps a reference (driverfs_dev) to the struct device associated with the block device, and uses it internally for generating uevents in block_uevent. Block device uevents include umounting the partition, which can occur after the backing device has been removed. Unfortunately, this reference is not counted. This means that if the struct device is removed from the device tree, the block layers reference will become stale. Guard against this by holding a reference to the struct device in add_disk(), and only drop the reference when we're releasing the gendisk kobject - in other words when we can be sure that no further uevents will be generated for this block device. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'block')
-rw-r--r--block/genhd.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/block/genhd.c b/block/genhd.c
index 5a8d3bf02f17..d96572589621 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -182,6 +182,7 @@ static int exact_lock(dev_t dev, void *data)
182 */ 182 */
183void add_disk(struct gendisk *disk) 183void add_disk(struct gendisk *disk)
184{ 184{
185 get_device(disk->driverfs_dev);
185 disk->flags |= GENHD_FL_UP; 186 disk->flags |= GENHD_FL_UP;
186 blk_register_region(MKDEV(disk->major, disk->first_minor), 187 blk_register_region(MKDEV(disk->major, disk->first_minor),
187 disk->minors, NULL, exact_match, exact_lock, disk); 188 disk->minors, NULL, exact_match, exact_lock, disk);
@@ -427,6 +428,7 @@ static struct attribute * default_attrs[] = {
427static void disk_release(struct kobject * kobj) 428static void disk_release(struct kobject * kobj)
428{ 429{
429 struct gendisk *disk = to_disk(kobj); 430 struct gendisk *disk = to_disk(kobj);
431 put_device(disk->driverfs_dev);
430 kfree(disk->random); 432 kfree(disk->random);
431 kfree(disk->part); 433 kfree(disk->part);
432 free_disk_stats(disk); 434 free_disk_stats(disk);