Linux block layer
 help / color / mirror / Atom feed
* [PATCH 1/2] block: Add post_release() operation
@ 2026-09-09 10:48 Tetsuo Handa
  2026-09-09 10:49 ` [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped Tetsuo Handa
                   ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Tetsuo Handa @ 2026-09-09 10:48 UTC (permalink / raw)
  To: Jens Axboe, Bart Van Assche, Christoph Hellwig
  Cc: Al Viro, Andrew Morton, Brian Foster, Damien Le Moal,
	Hillf Danton, Markus Elfring, Ming Lei, Qu Wenruo, Tao Cui,
	kernel test robot, linux-block, rust-for-linux

Add post_release() block device operation which provides a hook for
performing synchronous cleanup without disk->open_mutex held, which is
needed by the loop devices.

Real-world container engines, test suites, and system utilities rely on
fput() from __loop_clr_fd() being completed when lo_release() returns.
But changes which went to the v7.1 merge window broke an assumption that
there is no outstanding I/O when __loop_clr_fd() is called, causing NULL
pointer dereference problem in lo_rw_aio().

In order to fix this regression, we want to allow __loop_clr_fd() to flush
outstanding I/O. But calling drain_workqueue() from __loop_clr_fd() with
disk->open_mutex held causes lockdep warnings. We need a mechanism which
can flush outstanding I/O without disk->open_mutex held.

This post_release() operation is intended for performing only idempotent
actions such as flush_work(), for nothing prevents multiple threads from
concurrently calling this operation. That is, the loop device schedules
a work_struct for calling __loop_clr_fd() from lo_release() where
disk->open_mutex is held, and waits for completion of that work_struct
using post_release() operation where disk->open_mutex is not held.

Also, this post_release() operation is called from only bdev_release()
path. This is because loop_configure() is not yet called (there is nothing
to clear) if something went wrong between an initialization lo_open() and
an error-unwinding lo_release() within the bdev_open() path.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 block/bdev.c                     | 2 ++
 include/linux/blkdev.h           | 6 ++++++
 rust/kernel/block/mq/gen_disk.rs | 1 +
 3 files changed, 9 insertions(+)

diff --git a/block/bdev.c b/block/bdev.c
index cd8323083740..7ce5acaacf43 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -1188,6 +1188,8 @@ void bdev_release(struct file *bdev_file)
 	else
 		blkdev_put_whole(bdev);
 	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);
 put_no_open:
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 4f7905c3412b..f05dba1b5962 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1605,6 +1605,12 @@ struct block_device_operations {
 	 * driver.
 	 */
 	int (*alternative_gpt_sector)(struct gendisk *disk, sector_t *sector);
+	/*
+	 * Called after disk->open_mutex is released in the bdev_release() path.
+	 * Used by loop devices that need to perform synchronization without
+	 * holding disk->open_mutex. This operation has to be idempotent.
+	 */
+	void (*post_release)(struct gendisk *disk);
 };
 
 #ifdef CONFIG_COMPAT
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
index fc97dd873974..2ff77ef49781 100644
--- a/rust/kernel/block/mq/gen_disk.rs
+++ b/rust/kernel/block/mq/gen_disk.rs
@@ -129,6 +129,7 @@ pub fn build<T: Operations>(
             submit_bio: None,
             open: None,
             release: None,
+            post_release: None,
             ioctl: None,
             compat_ioctl: None,
             check_events: None,
-- 
2.55.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread
* [PATCH 0/2] loop: Fix teardown
@ 2026-09-16 19:51 Bart Van Assche
  2026-09-16 19:51 ` [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped Bart Van Assche
  0 siblings, 1 reply; 22+ messages in thread
From: Bart Van Assche @ 2026-09-16 19:51 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, Christoph Hellwig, Tetsuo Handa, Nilay Shroff,
	Bart Van Assche

Hi Jens,

My attempts to help Tetsuo with fixing the issues in his loop driver patch
series have not been successful so far. Hence this patch series. (See also
https://lore.kernel.org/linux-block/60bf7af2-b84e-4056-9195-a26ad51ada46@I-love.SAKURA.ne.jp/).

When tearing down an autoclear loop device upon release, the loop driver
must drain in-flight I/O and flush workqueues to prevent NULL pointer
dereferences in lo_rw_aio() and related I/O paths.

However, the .release() block device callback is invoked while holding
disk->open_mutex. Freezing the request queue or draining workqueues under
disk->open_mutex causes lock inversion and circular locking dependencies
(e.g., when worker threads or I/O completion paths also acquire open_mutex
or interact with request queue synchronization).

This patch series resolves the lock inversion by:
1. Adding a .post_release() block device operation that is called
   synchronously from bdev_release() immediately after disk->open_mutex
   is released.
2. Migrating __loop_clr_fd() to .post_release(), allowing loop device
   teardown and queue freezing to happen outside of disk->open_mutex.

Please consider applying this patch series.

Thanks,

Bart.

Bart Van Assche (2):
  block: Add post_release() operation
  loop: Perform __loop_clr_fd() after disk->open_mutex is dropped

 block/bdev.c                     |  3 ++
 drivers/block/loop.c             | 51 +++++++++++++++++++++++---------
 include/linux/blkdev.h           |  5 ++++
 rust/kernel/block/mq/gen_disk.rs |  1 +
 4 files changed, 46 insertions(+), 14 deletions(-)


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2026-09-18  0:59 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 10:48 [PATCH 1/2] block: Add post_release() operation Tetsuo Handa
2026-09-09 10:49 ` [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped Tetsuo Handa
2026-09-09 19:33   ` Bart Van Assche
2026-09-10  9:44     ` Tetsuo Handa
2026-09-11 20:03       ` Bart Van Assche
2026-09-11 22:18         ` Tetsuo Handa
2026-09-12  1:02           ` Bart Van Assche
2026-09-12  1:22             ` Tetsuo Handa
2026-09-15 17:36               ` Bart Van Assche
2026-09-15 22:38                 ` Tetsuo Handa
2026-09-17 22:18                   ` Tetsuo Handa
2026-09-18  0:59                     ` Bart Van Assche
2026-09-10 11:53 ` [PATCH 1/2] block: Add post_release() operation Gary Guo
2026-09-10 12:14   ` Tetsuo Handa
2026-09-11 19:54 ` Bart Van Assche
2026-09-11 22:34   ` Tetsuo Handa
2026-09-12  0:31     ` Bart Van Assche
2026-09-12  1:43       ` Tetsuo Handa
  -- strict thread matches above, loose matches on Subject: below --
2026-09-16 19:51 [PATCH 0/2] loop: Fix teardown Bart Van Assche
2026-09-16 19:51 ` [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped Bart Van Assche
2026-09-16 22:47   ` Tetsuo Handa
2026-09-16 23:05     ` Bart Van Assche
2026-09-17  0:16       ` Tetsuo Handa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox