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@xxxxxxxxx> Fixes: 322c4293ecc58110 ("loop: make autoclear operation asynchronous") Signed-off-by: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> --- block/bdev.c | 2 ++ include/linux/blkdev.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/block/bdev.c b/block/bdev.c index 8bf93a19041b..0cb638d81a27 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -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); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index c80cfaefc0a8..b252b1d87471 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -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 -- 2.32.0