On 06/11/2019 06:32, Jens Axboe wrote: > If a request fails, we need to ensure we set REQ_F_FAIL_LINK on it if > REQ_F_LINK is set. Any failure in the chain should break the chain. > > We were missing a few spots where this should be done. It might be nice > to generalize this somewhat at some point, as long as we factor in the > fact that failure looks different for each request type. > The completion path also starts to get complicated, especially non-uniform handling of links there. i.e. io_put_req() -> io_put_req_find_next() -> io_free_req() -> __io_free_req() Plus, io_free_req_many(), which can be used only in some cases. My compiler didn't even inlined it, so there are 4 CALLs. Though, still in TODO list. > Signed-off-by: Jens Axboe > > -- > > > diff --git a/fs/io_uring.c b/fs/io_uring.c > index bda27b52fd5b..4edc94aab17e 100644 > --- a/fs/io_uring.c > +++ b/fs/io_uring.c > @@ -1672,6 +1672,8 @@ static int io_send_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe, > } > > io_cqring_add_event(req->ctx, sqe->user_data, ret); > + if (ret < 0 && (req->flags & REQ_F_LINK)) > + req->flags |= REQ_F_FAIL_LINK; > io_put_req(req, nxt); > return 0; > } > @@ -1787,6 +1789,8 @@ static int io_poll_remove(struct io_kiocb *req, const struct io_uring_sqe *sqe) > spin_unlock_irq(&ctx->completion_lock); > > io_cqring_add_event(req->ctx, sqe->user_data, ret); > + if (ret < 0 && (req->flags & REQ_F_LINK)) > + req->flags |= REQ_F_FAIL_LINK; > io_put_req(req, NULL); > return 0; > } > @@ -1994,6 +1998,8 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer) > spin_unlock_irqrestore(&ctx->completion_lock, flags); > > io_cqring_ev_posted(ctx); > + if (req->flags & REQ_F_LINK) > + req->flags |= REQ_F_FAIL_LINK; > io_put_req(req, NULL); > return HRTIMER_NORESTART; > } > @@ -2035,6 +2041,8 @@ static int io_timeout_remove(struct io_kiocb *req, > io_commit_cqring(ctx); > spin_unlock_irq(&ctx->completion_lock); > io_cqring_ev_posted(ctx); > + if (req->flags & REQ_F_LINK) > + req->flags |= REQ_F_FAIL_LINK; > io_put_req(req, NULL); > return 0; > } > @@ -2328,6 +2336,8 @@ static void io_wq_submit_work(struct io_wq_work **workptr) > io_put_req(req, NULL); > > if (ret) { > + if (req->flags & REQ_F_LINK) > + req->flags |= REQ_F_FAIL_LINK; > io_cqring_add_event(ctx, sqe->user_data, ret); > io_put_req(req, NULL); > } > -- Pavel Begunkov