Skip to content

Commit

Permalink
io_uring: retry in case of short read on block device
Browse files Browse the repository at this point in the history
ANBZ: torvalds#190

commit 7db3043 upstream.

In case of buffered reading from block device, when short read happens,
we should retry to read more, otherwise the IO will be completed
partially, for example, the following fio expects to read 2MB, but it
can only read 1M or less bytes:

    fio --name=onessd --filename=/dev/nvme0n1 --filesize=2M \
	--rw=randread --bs=2M --direct=0 --overwrite=0 --numjobs=1 \
	--iodepth=1 --time_based=0 --runtime=2 --ioengine=io_uring \
	--registerfiles --fixedbufs --gtod_reduce=1 --group_reporting

Fix the issue by allowing short read retry for block device, which sets
FMODE_BUF_RASYNC really.

Fixes: 9a17334 ("io_uring: fix short read retries for non-reg files")
Cc: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/20210821150751.1290434-1-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Reviewed-by: Xiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
Reviewed-by: Hao Xu <haoxu@linux.alibaba.com>
Tested-by: Hao Xu <haoxu@linux.alibaba.com>
  • Loading branch information
Ming Lei authored and josephhz committed Dec 31, 2021
1 parent 566241c commit cc51b69
Showing 1 changed file with 7 additions and 1 deletion.
8 changes: 7 additions & 1 deletion fs/io_uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -3056,6 +3056,12 @@ static int io_iter_do_read(struct io_kiocb *req, struct iov_iter *iter)
return -EINVAL;
}

static bool need_read_all(struct io_kiocb *req)
{
return req->flags & REQ_F_ISREG ||
S_ISBLK(file_inode(req->file)->i_mode);
}

static int io_read(struct io_kiocb *req, bool force_nonblock)
{
struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
Expand Down Expand Up @@ -3109,7 +3115,7 @@ static int io_read(struct io_kiocb *req, bool force_nonblock)

/* read it all, or we did blocking attempt. no retry. */
if (!iov_iter_count(iter) || !force_nonblock ||
(req->file->f_flags & O_NONBLOCK) || !(req->flags & REQ_F_ISREG))
(req->file->f_flags & O_NONBLOCK) || !need_read_all(req))
goto done;

io_size -= ret;
Expand Down

0 comments on commit cc51b69

Please sign in to comment.