[PATCH] Always invalidate cleared loop block devices

From: Ayan George
Date: Thu Jul 14 2011 - 14:16:58 EST


The API for loop_clr_fd() is confusing -- the second argument (bdev)
isn't necessesary as struct loop_device contains a pointer to the block
device it is assocated with.

There is a cases where loop_clr_fd() is called with NULL for bdev
which prevents the block device from ever being invalidated with
invalidate_bdev() and prevents a uevent from being emitted.

This patch removes the bdev argument from loop_clr_fd(), unconditionally
invalidates lo->lo_device when cleared, and unconditionally emits a
uevent for removed loops.

Launchpad bug for reference:

BugLink: https://bugs.launchpad.net/bugs/548546

Signed-off-by: Ayan George <ayan.george@xxxxxxxxxxxxx>
---
drivers/block/loop.c | 24 ++++++++++++++----------
1 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 76c8da7..a40e12b 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -987,11 +987,13 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
return err;
}

-static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
+static int loop_clr_fd(struct loop_device *lo)
{
struct file *filp = lo->lo_backing_file;
gfp_t gfp = lo->old_gfp_mask;

+ struct block_device *bdev = lo->lo_device;
+
if (lo->lo_state != Lo_bound)
return -ENXIO;

@@ -1022,15 +1024,17 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
memset(lo->lo_file_name, 0, LO_NAME_SIZE);
- if (bdev)
- invalidate_bdev(bdev);
+
+ invalidate_bdev(bdev);
+
set_capacity(lo->lo_disk, 0);
loop_sysfs_exit(lo);
- if (bdev) {
- bd_set_size(bdev, 0);
- /* let user-space know about this change */
- kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
- }
+
+ bd_set_size(bdev, 0);
+
+ /* let user-space know about this change */
+ kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
+
mapping_set_gfp_mask(filp->f_mapping, gfp);
lo->lo_state = Lo_unbound;
/* This is safe: open() is still holding a reference. */
@@ -1298,7 +1302,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
break;
case LOOP_CLR_FD:
/* loop_clr_fd would have unlocked lo_ctl_mutex on success */
- err = loop_clr_fd(lo, bdev);
+ err = loop_clr_fd(lo);
if (!err)
goto out_unlocked;
break;
@@ -1509,7 +1513,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
* In autoclear mode, stop the loop thread
* and remove configuration after last close.
*/
- err = loop_clr_fd(lo, NULL);
+ err = loop_clr_fd(lo);
if (!err)
goto out_unlocked;
} else {
--
1.7.4.1


--------------080706050103020705080803--
--
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/