]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
io_uring/rw: fix missing ERESTARTSYS conversion in read paths
authorYitang Yang <yi1tang.yang@gmail.com>
Wed, 22 Jul 2026 12:45:51 +0000 (20:45 +0800)
committerJens Axboe <axboe@kernel.dk>
Wed, 22 Jul 2026 13:36:25 +0000 (07:36 -0600)
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: a08d195b586a ("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>
io_uring/rw.c

index 63b6519e498cd7f9bbb2ef36f422a29d8b3f85c5..95038cfda61538677c001e23536f7630f51df9d5 100644 (file)
@@ -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 {