@@ -948,6 +948,8 @@ void blkdev_put(struct block_device *bdev, fmode_t mode)
else
blkdev_put_whole(bdev, mode);
mutex_unlock(&disk->open_mutex);
+ if (bdev->bd_disk->fops->post_release)
+ bdev->bd_disk->fops->post_release(bdev->bd_disk);
module_put(disk->fops->owner);
blkdev_put_no_open(bdev);
@@ -1227,6 +1227,11 @@ struct block_device_operations {
* driver.
*/
int (*alternative_gpt_sector)(struct gendisk *disk, sector_t *sector);
+ /*
+ * Special callback for doing post-release callback without
+ * disk->open_mutex held. Used by loop driver.
+ */
+ void (*post_release)(struct gendisk *disk);
};
#ifdef CONFIG_COMPAT
Add post_release() block device callback which allows release() block device callback to schedule an extra cleanup operation while holding disk->open_mutex and let post_release() callback synchronously perform that operation without holding disk->open_mutex. The loop driver needs this callback for synchronously performing autoclear operation, for some userspace programs (e.g. xfstest) depend on that the autoclear operation already completes by the moment lo_release() from close() returns to userspace and immediately call umount() of a partition containing a backing file which the autoclear operation will close(), but temporarily dropping disk->open_mutex inside lo_release() in order to avoid circular locking dependency is considered as a bad approach. Note that unlike release() callback, post_release() callback is called every time blkdev_put() is called. That is, the release() callback is responsible for making it possible for post_release() callback to tell whether post_release() callback has something to do. Reported-by: kernel test robot <oliver.sang@intel.com> Fixes: 322c4293ecc58110 ("loop: make autoclear operation asynchronous") Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> --- block/bdev.c | 2 ++ include/linux/blkdev.h | 5 +++++ 2 files changed, 7 insertions(+)