diff mbox series

[1/2] block: Add post_release() operation

Message ID 08d703d1-8b32-ec9b-2b50-54b8376d3d40@i-love.sakura.ne.jp (mailing list archive)
State New, archived
Headers show
Series [1/2] block: Add post_release() operation | expand

Commit Message

Tetsuo Handa Dec. 22, 2021, 12:02 p.m. UTC
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(+)
diff mbox series

Patch

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