zloop advertises REQ_NOWAIT support via BLK_FEAT_NOWAIT (set by default for all blk-mq devices), but violates REQ_NOWAIT semantics by using GFP_NOIO allocations which can block. BLK_FEAT_NOWAIT is advertised through this call chain: zloop_add() blk_mq_alloc_disk(&lim, ...) __blk_mq_alloc_disk() blk_mq_alloc_queue() lim->features |= BLK_FEAT_NOWAIT <-- Set by default for blk-mq However, the REQ_NOWAIT I/O path violates this contract. For io_uring inline submissions, the call chain is: 1. Userspace (io_uring setup): io_uring_setup(entries, ¶ms) fd = io_uring_register(IORING_REGISTER_FILES, &zloop_fd, 1) 2. Userspace (submit I/O with NOWAIT): sqe = io_uring_get_sqe(ring) io_uring_prep_write(sqe, zloop_fd, buf, len, offset) io_uring_submit(ring) <-- inline submission 3. io_uring core (inline path): io_submit_sqes() io_submit_sqe() io_queue_sqe() issue_flags = IO_URING_F_NONBLOCK <-- Sets inline/nowait mode io_issue_sqe() io_write() if (force_nonblock) <-- true for inline submission kiocb->ki_flags |= IOCB_NOWAIT 4. VFS layer: call_write_iter() blkdev_write_iter() -> propagates IOCB_NOWAIT to REQ_NOWAIT on bio __blkdev_direct_IO_simple() OR __blkdev_direct_IO() OR __blkdev_direct_IO_async() 5. Block layer: blk_mq_submit_bio() blk_mq_get_new_requests() __blk_mq_alloc_requests() blk_mq_rq_ctx_init() -> propagates REQ_NOWAIT to request->cmd_flags __blk_mq_try_issue_directly() OR blk_mq_sched_insert_request() blk_mq_run_hw_queue() __blk_mq_delay_run_hw_queue() __blk_mq_run_hw_queue() blk_mq_sched_dispatch_requests() 6. Zloop driver: zloop_queue_rq() zloop_rw() kmalloc_array(..., GFP_NOIO) <-- BLOCKS (REQ_NOWAIT violation) -> Should use GFP_NOWAIT when rq->cmd_flags & REQ_NOWAIT Fix by using GFP_NOWAIT when REQ_NOWAIT is set, and return -EAGAIN instead of -ENOMEM when NOWAIT allocation fails, allowing io_uring to retry the operation with blocking allowed. Signed-off-by: Chaitanya Kulkarni --- drivers/block/zloop.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index 92be9f0af00a..9295c4817bd4 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -372,6 +372,8 @@ static void zloop_rw(struct zloop_cmd *cmd) sector_t zone_end; int nr_bvec = 0; int ret; + bool nowait = rq->cmd_flags & REQ_NOWAIT; + gfp_t alloc_flags = nowait ? GFP_NOWAIT : GFP_NOIO; atomic_set(&cmd->ref, 2); cmd->sector = sector; @@ -443,9 +445,9 @@ static void zloop_rw(struct zloop_cmd *cmd) if (rq->bio != rq->biotail) { struct bio_vec *bvec; - cmd->bvec = kmalloc_array(nr_bvec, sizeof(*cmd->bvec), GFP_NOIO); + cmd->bvec = kmalloc_array(nr_bvec, sizeof(*cmd->bvec), alloc_flags); if (!cmd->bvec) { - ret = -EIO; + ret = nowait ? -EAGAIN : -ENOMEM; goto unlock; } -- 2.40.0