mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
io_uring/rw: fix missing ERESTARTSYS conversion in read paths
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().
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>
This commit is contained in:
parent
3afc64c61c
commit
ab05caca12
|
|
@ -615,6 +615,24 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res)
|
|||
smp_store_release(&req->iopoll_completed, 1);
|
||||
}
|
||||
|
||||
static inline ssize_t io_fixup_restart_res(ssize_t ret)
|
||||
{
|
||||
switch (ret) {
|
||||
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.
|
||||
*/
|
||||
return -EINTR;
|
||||
default:
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void io_rw_done(struct io_kiocb *req, ssize_t ret)
|
||||
{
|
||||
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
|
||||
|
|
@ -624,21 +642,8 @@ static inline void io_rw_done(struct io_kiocb *req, ssize_t ret)
|
|||
return;
|
||||
|
||||
/* transform internal restart error codes */
|
||||
if (unlikely(ret < 0)) {
|
||||
switch (ret) {
|
||||
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.
|
||||
*/
|
||||
ret = -EINTR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (unlikely(ret < 0))
|
||||
ret = io_fixup_restart_res(ret);
|
||||
|
||||
if (req->flags & REQ_F_IOPOLL)
|
||||
io_complete_rw_iopoll(&rw->kiocb, ret);
|
||||
|
|
@ -1034,7 +1039,8 @@ int io_read(struct io_kiocb *req, unsigned int issue_flags)
|
|||
|
||||
if (req->flags & REQ_F_BUFFERS_COMMIT)
|
||||
io_kbuf_recycle(req, sel.buf_list, issue_flags);
|
||||
return ret;
|
||||
|
||||
return io_fixup_restart_res(ret);
|
||||
}
|
||||
|
||||
int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
|
||||
|
|
@ -1068,8 +1074,10 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
|
|||
return IOU_RETRY;
|
||||
} else if (ret <= 0) {
|
||||
io_kbuf_recycle(req, sel.buf_list, issue_flags);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
ret = io_fixup_restart_res(ret);
|
||||
req_set_fail(req);
|
||||
}
|
||||
} else if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
|
||||
cflags = io_put_kbuf(req, ret, sel.buf_list);
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user