Commit 322c4293ecc58110 ("loop: make autoclear operation asynchronous") silenced a circular locking dependency warning by moving autoclear operation to WQ context. Then, it was reported that WQ context is too late to run autoclear operation; some userspace programs (e.g. xfstest) assume that the autoclear operation already completed by the moment close() returns to user mode so that they can immediately call umount() of a partition containing a backing file which the autoclear operation should have closed. Then, Jan Kara found that fundamental problem is that waiting for I/O completion (from blk_mq_freeze_queue() or flush_workqueue()) with disk->open_mutex held has possibility of deadlock. Then, I found that since disk->open_mutex => lo->lo_mutex dependency is recorded by lo_open() and lo_release(), and blk_mq_freeze_queue() by e.g. loop_set_status() waits for I/O completion with lo->lo_mutex held, from locking dependency chain perspective we need to avoid holding lo->lo_mutex from lo_open() and lo_release(). And we can avoid holding lo->lo_mutex from lo_open(), for we can instead use a spinlock dedicated for Lo_deleting check. But we cannot avoid holding lo->lo_mutex from lo_release(), for WQ context was too late to run autoclear operation. We need to make whole lo_release() operation start without disk->open_mutex and complete before returning to user mode. One of approaches that can meet such requirement is to use the task_work context. Thus, export task_work_add() for the loop driver. Cc: Jan Kara <jack@xxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Signed-off-by: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> --- kernel/task_work.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/task_work.c b/kernel/task_work.c index 1698fbe6f0e1..2a1644189182 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -60,6 +60,7 @@ int task_work_add(struct task_struct *task, struct callback_head *work, return 0; } +EXPORT_SYMBOL_GPL(task_work_add); /** * task_work_cancel_match - cancel a pending work added by task_work_add() -- 2.32.0