io_uring: consider any io_read/write -EAGAIN as final
authorJens Axboe <axboe@kernel.dk>
Thu, 20 Feb 2020 16:56:08 +0000 (09:56 -0700)
committerJens Axboe <axboe@kernel.dk>
Mon, 2 Mar 2020 21:04:24 +0000 (14:04 -0700)
If the -EAGAIN happens because of a static condition, then a poll
or later retry won't fix it. We must call it again from blocking
condition. Play it safe and ensure that any -EAGAIN condition from read
or write must retry from async context.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c

index 6a595c1..64b4519 100644 (file)
@@ -2234,7 +2234,7 @@ static int io_read(struct io_kiocb *req, struct io_kiocb **nxt,
 
        /* Ensure we clear previously set non-block flag */
        if (!force_nonblock)
-               req->rw.kiocb.ki_flags &= ~IOCB_NOWAIT;
+               kiocb->ki_flags &= ~IOCB_NOWAIT;
 
        req->result = 0;
        io_size = ret;
@@ -2245,10 +2245,8 @@ static int io_read(struct io_kiocb *req, struct io_kiocb **nxt,
         * If the file doesn't support async, mark it as REQ_F_MUST_PUNT so
         * we know to async punt it even if it was opened O_NONBLOCK
         */
-       if (force_nonblock && !io_file_supports_async(req->file)) {
-               req->flags |= REQ_F_MUST_PUNT;
+       if (force_nonblock && !io_file_supports_async(req->file))
                goto copy_iov;
-       }
 
        iov_count = iov_iter_count(&iter);
        ret = rw_verify_area(READ, req->file, &kiocb->ki_pos, iov_count);
@@ -2269,6 +2267,9 @@ copy_iov:
                                                inline_vecs, &iter);
                        if (ret)
                                goto out_free;
+                       /* any defer here is final, must blocking retry */
+                       if (!(req->flags & REQ_F_NOWAIT))
+                               req->flags |= REQ_F_MUST_PUNT;
                        return -EAGAIN;
                }
        }
@@ -2334,10 +2335,8 @@ static int io_write(struct io_kiocb *req, struct io_kiocb **nxt,
         * If the file doesn't support async, mark it as REQ_F_MUST_PUNT so
         * we know to async punt it even if it was opened O_NONBLOCK
         */
-       if (force_nonblock && !io_file_supports_async(req->file)) {
-               req->flags |= REQ_F_MUST_PUNT;
+       if (force_nonblock && !io_file_supports_async(req->file))
                goto copy_iov;
-       }
 
        /* file path doesn't support NOWAIT for non-direct_IO */
        if (force_nonblock && !(kiocb->ki_flags & IOCB_DIRECT) &&
@@ -2382,6 +2381,8 @@ copy_iov:
                                                inline_vecs, &iter);
                        if (ret)
                                goto out_free;
+                       /* any defer here is final, must blocking retry */
+                       req->flags |= REQ_F_MUST_PUNT;
                        return -EAGAIN;
                }
        }