Skip to content

Commit 4503b76

Browse files
committed
io_uring: catch -EIO from buffered issue request failure
-EIO bubbles up like -EAGAIN if we fail to allocate a request at the lower level. Play it safe and treat it like -EAGAIN in terms of sync retry, to avoid passing back an errant -EIO. Catch some of these early for block based file, as non-mq devices generally do not support NOWAIT. That saves us some overhead by not first trying, then retrying from async context. We can go straight to async punt instead. Signed-off-by: Jens Axboe <[email protected]>
1 parent ac8691c commit 4503b76

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

fs/io_uring.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,6 +2088,15 @@ static struct file *__io_file_get(struct io_submit_state *state, int fd)
20882088
return state->file;
20892089
}
20902090

2091+
static bool io_bdev_nowait(struct block_device *bdev)
2092+
{
2093+
#ifdef CONFIG_BLOCK
2094+
return !bdev || queue_is_mq(bdev_get_queue(bdev));
2095+
#else
2096+
return true;
2097+
#endif
2098+
}
2099+
20912100
/*
20922101
* If we tracked the file through the SCM inflight mechanism, we could support
20932102
* any file. For now, just ensure that anything potentially problematic is done
@@ -2097,10 +2106,19 @@ static bool io_file_supports_async(struct file *file, int rw)
20972106
{
20982107
umode_t mode = file_inode(file)->i_mode;
20992108

2100-
if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISSOCK(mode))
2101-
return true;
2102-
if (S_ISREG(mode) && file->f_op != &io_uring_fops)
2109+
if (S_ISBLK(mode)) {
2110+
if (io_bdev_nowait(file->f_inode->i_bdev))
2111+
return true;
2112+
return false;
2113+
}
2114+
if (S_ISCHR(mode) || S_ISSOCK(mode))
21032115
return true;
2116+
if (S_ISREG(mode)) {
2117+
if (io_bdev_nowait(file->f_inode->i_sb->s_bdev) &&
2118+
file->f_op != &io_uring_fops)
2119+
return true;
2120+
return false;
2121+
}
21042122

21052123
/* any ->read/write should understand O_NONBLOCK */
21062124
if (file->f_flags & O_NONBLOCK)
@@ -2650,15 +2668,15 @@ static int io_read(struct io_kiocb *req, bool force_nonblock)
26502668
iov_count = iov_iter_count(&iter);
26512669
ret = rw_verify_area(READ, req->file, &kiocb->ki_pos, iov_count);
26522670
if (!ret) {
2653-
ssize_t ret2;
2671+
ssize_t ret2 = 0;
26542672

26552673
if (req->file->f_op->read_iter)
26562674
ret2 = call_read_iter(req->file, kiocb, &iter);
26572675
else
26582676
ret2 = loop_rw_iter(READ, req->file, kiocb, &iter);
26592677

26602678
/* Catch -EAGAIN return for forced non-blocking submission */
2661-
if (!force_nonblock || ret2 != -EAGAIN) {
2679+
if (!force_nonblock || (ret2 != -EAGAIN && ret2 != -EIO)) {
26622680
kiocb_done(kiocb, ret2);
26632681
} else {
26642682
copy_iov:

0 commit comments

Comments
 (0)