Skip to content

Commit 4493233

Browse files
isilenceaxboe
authored andcommitted
io_uring: hook all linked requests via link_list
Links are created by chaining requests through req->list with an exception that head uses req->link_list. (e.g. link_list->list->list) Because of that, io_req_link_next() needs complex splicing to advance. Link them all through list_list. Also, it seems to be simpler and more consistent IMHO. Signed-off-by: Pavel Begunkov <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 2e6e1fd commit 4493233

File tree

1 file changed

+20
-22
lines changed

1 file changed

+20
-22
lines changed

fs/io_uring.c

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,6 @@ static bool io_link_cancel_timeout(struct io_kiocb *req)
916916
static void io_req_link_next(struct io_kiocb *req, struct io_kiocb **nxtptr)
917917
{
918918
struct io_ring_ctx *ctx = req->ctx;
919-
struct io_kiocb *nxt;
920919
bool wake_ev = false;
921920

922921
/* Already got next link */
@@ -928,24 +927,21 @@ static void io_req_link_next(struct io_kiocb *req, struct io_kiocb **nxtptr)
928927
* potentially happen if the chain is messed up, check to be on the
929928
* safe side.
930929
*/
931-
nxt = list_first_entry_or_null(&req->link_list, struct io_kiocb, list);
932-
while (nxt) {
933-
list_del_init(&nxt->list);
930+
while (!list_empty(&req->link_list)) {
931+
struct io_kiocb *nxt = list_first_entry(&req->link_list,
932+
struct io_kiocb, link_list);
934933

935-
if ((req->flags & REQ_F_LINK_TIMEOUT) &&
936-
(nxt->flags & REQ_F_TIMEOUT)) {
934+
if (unlikely((req->flags & REQ_F_LINK_TIMEOUT) &&
935+
(nxt->flags & REQ_F_TIMEOUT))) {
936+
list_del_init(&nxt->link_list);
937937
wake_ev |= io_link_cancel_timeout(nxt);
938-
nxt = list_first_entry_or_null(&req->link_list,
939-
struct io_kiocb, list);
940938
req->flags &= ~REQ_F_LINK_TIMEOUT;
941939
continue;
942940
}
943-
if (!list_empty(&req->link_list)) {
944-
INIT_LIST_HEAD(&nxt->link_list);
945-
list_splice(&req->link_list, &nxt->link_list);
946-
nxt->flags |= REQ_F_LINK;
947-
}
948941

942+
list_del_init(&req->link_list);
943+
if (!list_empty(&nxt->link_list))
944+
nxt->flags |= REQ_F_LINK;
949945
*nxtptr = nxt;
950946
break;
951947
}
@@ -961,15 +957,15 @@ static void io_req_link_next(struct io_kiocb *req, struct io_kiocb **nxtptr)
961957
static void io_fail_links(struct io_kiocb *req)
962958
{
963959
struct io_ring_ctx *ctx = req->ctx;
964-
struct io_kiocb *link;
965960
unsigned long flags;
966961

967962
spin_lock_irqsave(&ctx->completion_lock, flags);
968963

969964
while (!list_empty(&req->link_list)) {
970-
link = list_first_entry(&req->link_list, struct io_kiocb, list);
971-
list_del_init(&link->list);
965+
struct io_kiocb *link = list_first_entry(&req->link_list,
966+
struct io_kiocb, link_list);
972967

968+
list_del_init(&link->link_list);
973969
trace_io_uring_fail_link(req, link);
974970

975971
if ((req->flags & REQ_F_LINK_TIMEOUT) &&
@@ -3170,10 +3166,11 @@ static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer)
31703166
* We don't expect the list to be empty, that will only happen if we
31713167
* race with the completion of the linked work.
31723168
*/
3173-
if (!list_empty(&req->list)) {
3174-
prev = list_entry(req->list.prev, struct io_kiocb, link_list);
3169+
if (!list_empty(&req->link_list)) {
3170+
prev = list_entry(req->link_list.prev, struct io_kiocb,
3171+
link_list);
31753172
if (refcount_inc_not_zero(&prev->refs)) {
3176-
list_del_init(&req->list);
3173+
list_del_init(&req->link_list);
31773174
prev->flags &= ~REQ_F_LINK_TIMEOUT;
31783175
} else
31793176
prev = NULL;
@@ -3203,7 +3200,7 @@ static void io_queue_linked_timeout(struct io_kiocb *req)
32033200
* we got a chance to setup the timer
32043201
*/
32053202
spin_lock_irq(&ctx->completion_lock);
3206-
if (!list_empty(&req->list)) {
3203+
if (!list_empty(&req->link_list)) {
32073204
struct io_timeout_data *data = &req->io->timeout;
32083205

32093206
data->timer.function = io_link_timeout_fn;
@@ -3223,7 +3220,8 @@ static struct io_kiocb *io_prep_linked_timeout(struct io_kiocb *req)
32233220
if (!(req->flags & REQ_F_LINK))
32243221
return NULL;
32253222

3226-
nxt = list_first_entry_or_null(&req->link_list, struct io_kiocb, list);
3223+
nxt = list_first_entry_or_null(&req->link_list, struct io_kiocb,
3224+
link_list);
32273225
if (!nxt || nxt->sqe->opcode != IORING_OP_LINK_TIMEOUT)
32283226
return NULL;
32293227

@@ -3364,7 +3362,7 @@ static bool io_submit_sqe(struct io_kiocb *req, struct io_submit_state *state,
33643362
goto err_req;
33653363
}
33663364
trace_io_uring_link(ctx, req, prev);
3367-
list_add_tail(&req->list, &prev->link_list);
3365+
list_add_tail(&req->link_list, &prev->link_list);
33683366
} else if (req->sqe->flags & IOSQE_IO_LINK) {
33693367
req->flags |= REQ_F_LINK;
33703368

0 commit comments

Comments
 (0)