>From c783ba6a26eff42d3cb0061e4fcb8ee8a16b3e67 Mon Sep 17 00:00:00 2001 From: Ayan George Date: Thu, 14 Jul 2011 14:16:58 -0400 Subject: [PATCH] Always invalidate cleared loop block devices 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 --- 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