io_uring/rw: fix missing ERESTARTSYS conversion in read paths

commit ab05caca12 upstream.

Both read and write may receive internal restart error codes from
the filesystem layer and should be converted to -EINTR. However,
when multishot read support was added, the error code normalization
was lost for both io_read() and io_read_mshot().

Extract the conversion into io_fixup_restart_res() and apply it
in all three locations: io_rw_done(), io_read(), and io_read_mshot().

[ 6.6 doesn't have multishot read, drop the io_read_mshot() hunk and
  adapt io_rw_done() to the older calling convention ]

Fixes: a08d195b58 ("io_uring/rw: split io_read() into a helper")
Cc: stable@vger.kernel.org
Signed-off-by: Yitang Yang <yi1tang.yang@gmail.com>
Link: https://patch.msgid.link/20260722124551.130563-1-yi1tang.yang@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Yitang Yang
2026-08-03 11:15:33 +02:00
committed by Greg Kroah-Hartman
parent cafa53d327
commit 80f7dac8c9
+19 -9
View File
@@ -140,27 +140,37 @@ void io_readv_writev_cleanup(struct io_kiocb *req)
kfree(io->free_iovec);
}
static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret)
static inline ssize_t io_fixup_restart_res(ssize_t ret)
{
switch (ret) {
case -EIOCBQUEUED:
break;
case -ERESTARTSYS:
case -ERESTARTNOINTR:
case -ERESTARTNOHAND:
case -ERESTART_RESTARTBLOCK:
/*
* We can't just restart the syscall, since previously
* submitted sqes may already be in progress. Just fail this
* IO with EINTR.
* submitted sqes may already be in progress. Just fail
* this IO with EINTR.
*/
ret = -EINTR;
fallthrough;
return -EINTR;
default:
kiocb->ki_complete(kiocb, ret);
return ret;
}
}
static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret)
{
/* IO was queued async, completion will happen later */
if (ret == -EIOCBQUEUED)
return;
/* transform internal restart error codes */
if (unlikely(ret < 0))
ret = io_fixup_restart_res(ret);
kiocb->ki_complete(kiocb, ret);
}
static inline loff_t *io_kiocb_update_pos(struct io_kiocb *req)
{
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
@@ -885,7 +895,7 @@ int io_read(struct io_kiocb *req, unsigned int issue_flags)
if (ret >= 0)
return kiocb_done(req, ret, issue_flags);
return ret;
return io_fixup_restart_res(ret);
}
static bool io_kiocb_start_write(struct io_kiocb *req, struct kiocb *kiocb)