mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
io_uring/rw: fix missing ERESTARTSYS conversion in read paths
commitab05caca12upstream. 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:
committed by
Greg Kroah-Hartman
parent
cafa53d327
commit
80f7dac8c9
+19
-9
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user