liburing icon indicating copy to clipboard operation
liburing copied to clipboard

SQE timeout with IORING_TIMEOUT_ETIME_SUCCESS set return a CQE with res field equal to -ETIME

Open buracchi opened this issue 1 year ago • 4 comments

From the io_uring_prep_timeout man page:

IORING_TIMEOUT_ETIME_SUCCESS Consider an expired timeout a success in terms of the posted completion. Normally a timeout that triggers would return in a -ETIME CQE res value.

The following example

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <liburing.h>

int main() {
    struct io_uring ring;
    io_uring_queue_init(1, &ring, 0);
    
    struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
    io_uring_prep_timeout(sqe, &(struct __kernel_timespec) {.tv_sec = 1}, 0, IORING_TIMEOUT_ETIME_SUCCESS);
    io_uring_submit(&ring);
    
    struct io_uring_cqe *cqe;
    io_uring_wait_cqe(&ring, &cqe);
    if (cqe->res < 0) {
        printf("Timeout failed. %s.\n", strerror(-cqe->res));
        return EXIT_FAILURE;
    }
    io_uring_cqe_seen(&ring, cqe);
    
    io_uring_queue_exit(&ring);
    return EXIT_SUCCESS;
}

Produces the output:

Timeout failed. Timer expired.

Running on kernels

  • 6.6.36.3-microsoft-standard-WSL2
  • 6.5.0-1022-azure

buracchi avatar Aug 13 '24 12:08 buracchi

The man page is wrong. What the flag means is that dependent links for this SQE will not get failed in case of -ETIME, the request itself will still be posting -ETIME as the result code.

axboe avatar Aug 13 '24 12:08 axboe

The man page is wrong, it's supposed to return -ETIME even with IORING_TIMEOUT_ETIME_SUCCESS. The flag has never been changing the return code, the only effect is that it doesn't break links. E.g.

sqe = io_uring_get_sqe();
prep_timeout(sqe, flags = 0);
sqe->flags |= IOSQE_LINK;

sqe = io_uring_get_sqe();
prep_read(sqe);

Here the read would never be executed, you'd usually get something like cqe1.res = -ETIME, cqe2.res = -ECANCELED. If you pass IORING_TIMEOUT_ETIME_SUCCESS, however, you would expect the read to be actually run.

isilence avatar Aug 13 '24 12:08 isilence

The man page is wrong, it's supposed to return -ETIME even with IORING_TIMEOUT_ETIME_SUCCESS. The flag has never been changing the return code, the only effect is that it doesn't break links. E.g.

sqe = io_uring_get_sqe();
prep_timeout(sqe, flags = 0);
sqe->flags |= IOSQE_LINK;

sqe = io_uring_get_sqe();
prep_read(sqe);

Here the read would never be executed, you'd usually get something like cqe1.res = -ETIME, cqe2.res = -ECANCELED. If you pass IORING_TIMEOUT_ETIME_SUCCESS, however, you would expect the read to be actually run.

Using io_uring_prep_link_timeout to Control Dependent Task Timeout vs. prep_timeout -> (linked) -> read op

What's the difference between using io_uring_prep_link_timeout to control the timeout of a dependent task and using prep_timeout -> (linked) -> read op?

I found that io_uring_prep_link_timeout is not always able to cancel the dependent task.

rowe0x avatar Aug 20 '24 00:08 rowe0x

Here the read would never be executed, you'd usually get something like cqe1.res = -ETIME, cqe2.res = -ECANCELED. If you pass IORING_TIMEOUT_ETIME_SUCCESS, however, you would expect the read to be actually run.

Using io_uring_prep_link_timeout to Control Dependent Task Timeout vs. prep_timeout -> (linked) -> read op

What do you mean by "Control Dependent Task Timeout"? I can assume "Dependent Task" is a linked request, but even then I don't understand what it means.

What's the difference between using io_uring_prep_link_timeout to control the timeout of a dependent task and using prep_timeout -> (linked) -> read op?

I found that io_uring_prep_link_timeout is not always able to cancel the dependent task.

The only situation it can legally happen is if the timeout fired when the request it's linked to has already been completed but not yet removed. Something like this:

CPU1                |   CPU2
execute_request();  |
complete_request()  |
  post_cqe();       |
                    |   linked timeout triggered
  cancel_timeout()  |

And it's perfectly ok. Apps can think as if the request got completed before timeout. If you see any other cases, let us know.

isilence avatar Aug 21 '24 00:08 isilence