]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
loop: use kiocb helpers to fix lockdep warning
authorMing Lei <ming.lei@redhat.com>
Wed, 16 Jul 2025 11:48:08 +0000 (19:48 +0800)
committerJens Axboe <axboe@kernel.dk>
Wed, 16 Jul 2025 12:33:44 +0000 (06:33 -0600)
The lockdep tool can report a circular lock dependency warning in the loop
driver's AIO read/write path:

```
[ 6540.587728] kworker/u96:5/72779 is trying to acquire lock:
[ 6540.593856] ff110001b5968440 (sb_writers#9){.+.+}-{0:0}, at: loop_process_work+0x11a/0xf70 [loop]
[ 6540.603786]
[ 6540.603786] but task is already holding lock:
[ 6540.610291] ff110001b5968440 (sb_writers#9){.+.+}-{0:0}, at: loop_process_work+0x11a/0xf70 [loop]
[ 6540.620210]
[ 6540.620210] other info that might help us debug this:
[ 6540.627499]  Possible unsafe locking scenario:
[ 6540.627499]
[ 6540.634110]        CPU0
[ 6540.636841]        ----
[ 6540.639574]   lock(sb_writers#9);
[ 6540.643281]   lock(sb_writers#9);
[ 6540.646988]
[ 6540.646988]  *** DEADLOCK ***
```

This patch fixes the issue by using the AIO-specific helpers
`kiocb_start_write()` and `kiocb_end_write()`. These functions are
designed to be used with a `kiocb` and manage write sequencing
correctly for asynchronous I/O without introducing the problematic
lock dependency.

The `kiocb` is already part of the `loop_cmd` struct, so this change
also simplifies the completion function `lo_rw_aio_do_completion()` by
using the `iocb` from the `cmd` struct directly, instead of retrieving
the loop device from the request queue.

Fixes: 39d86db34e41 ("loop: add file_start_write() and file_end_write()")
Cc: Changhui Zhong <czhong@redhat.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20250716114808.3159657-1-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/loop.c

index 500840e4a74efc16c213522787ba8c1079f09380..8d994cae3b83baca154c780dcc4e056c41072852 100644 (file)
@@ -308,14 +308,13 @@ end_io:
 static void lo_rw_aio_do_completion(struct loop_cmd *cmd)
 {
        struct request *rq = blk_mq_rq_from_pdu(cmd);
-       struct loop_device *lo = rq->q->queuedata;
 
        if (!atomic_dec_and_test(&cmd->ref))
                return;
        kfree(cmd->bvec);
        cmd->bvec = NULL;
        if (req_op(rq) == REQ_OP_WRITE)
-               file_end_write(lo->lo_backing_file);
+               kiocb_end_write(&cmd->iocb);
        if (likely(!blk_should_fake_timeout(rq->q)))
                blk_mq_complete_request(rq);
 }
@@ -391,7 +390,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
        }
 
        if (rw == ITER_SOURCE) {
-               file_start_write(lo->lo_backing_file);
+               kiocb_start_write(&cmd->iocb);
                ret = file->f_op->write_iter(&cmd->iocb, &iter);
        } else
                ret = file->f_op->read_iter(&cmd->iocb, &iter);