Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

io_uring: don't use retry based buffered reads for non-async bdev

Some block devices, like dm, bubble back -EAGAIN through the completion
handler. We check for this in io_read(), but don't honor it for when
we have copied the iov. Return -EAGAIN for this case before retrying,
to force punt to io-wq.

Fixes: bcf5a06304d6 ("io_uring: support true async buffered reads, if file provides it")
Reported-by: Zorro Lang <zlang@redhat.com>
Tested-by: Zorro Lang <zlang@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

+5 -1
+5 -1
fs/io_uring.c
··· 3130 3130 struct iov_iter __iter, *iter = &__iter; 3131 3131 ssize_t io_size, ret, ret2; 3132 3132 size_t iov_count; 3133 + bool no_async; 3133 3134 3134 3135 if (req->io) 3135 3136 iter = &req->io->rw.iter; ··· 3148 3147 kiocb->ki_flags &= ~IOCB_NOWAIT; 3149 3148 3150 3149 /* If the file doesn't support async, just async punt */ 3151 - if (force_nonblock && !io_file_supports_async(req->file, READ)) 3150 + no_async = force_nonblock && !io_file_supports_async(req->file, READ); 3151 + if (no_async) 3152 3152 goto copy_iov; 3153 3153 3154 3154 ret = rw_verify_area(READ, req->file, io_kiocb_ppos(kiocb), iov_count); ··· 3193 3191 ret = ret2; 3194 3192 goto out_free; 3195 3193 } 3194 + if (no_async) 3195 + return -EAGAIN; 3196 3196 /* it's copied and will be cleaned with ->io */ 3197 3197 iovec = NULL; 3198 3198 /* now use our persistent iterator, if we aren't already */