[PATCH 1/2] block: Avoid dead request queue too early removal
From: Jarkko Lavinen
Date: Wed Oct 21 2009 - 11:48:18 EST
If disk is removed while file system is still mounted, the disk
removal can release the dead request queue too early while
file system is still trying to sumit requests.
Signed-off-by: Jarkko Lavinen <jarkko.lavinen@xxxxxxxxx>
---
fs/block_dev.c | 24 ++++++++++++++++++++----
1 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 9cf4b92..91f2fc3 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1165,6 +1165,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
int ret;
int partno;
int perm = 0;
+ int q_ref = 0;
+ struct module *owner;
if (mode & FMODE_READ)
perm |= MAY_READ;
@@ -1187,6 +1189,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
if (!disk)
goto out_unlock_kernel;
+ if (blk_get_queue(disk->queue))
+ goto out_unlock_kernel;
+ else
+ q_ref = 1;
+
mutex_lock_nested(&bdev->bd_mutex, for_part);
if (!bdev->bd_openers) {
bdev->bd_disk = disk;
@@ -1248,8 +1255,10 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
}
} else {
+ owner = disk->fops->owner;
+ blk_put_queue(disk->queue);
put_disk(disk);
- module_put(disk->fops->owner);
+ module_put(owner);
disk = NULL;
if (bdev->bd_contains == bdev) {
if (bdev->bd_disk->fops->open) {
@@ -1281,9 +1290,15 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
out_unlock_kernel:
unlock_kernel();
- if (disk)
- module_put(disk->fops->owner);
- put_disk(disk);
+ if (disk) {
+ owner = disk->fops->owner;
+ if (q_ref)
+ blk_put_queue(disk->queue);
+
+ put_disk(disk);
+ module_put(owner);
+ }
+
bdput(bdev);
return ret;
@@ -1360,6 +1375,7 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
if (!bdev->bd_openers) {
struct module *owner = disk->fops->owner;
+ blk_put_queue(disk->queue);
put_disk(disk);
module_put(owner);
disk_put_part(bdev->bd_part);
--
1.6.3.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/