axboe / liburing

Library providing helpers for the Linux kernel io_uring support
MIT License
2.86k stars 402 forks source link

` io_uring_prep_link_timeout` may return undocumented error -ENOENT #1208

Closed buracchi closed 2 months ago

buracchi commented 2 months ago

When using io_uring_prep_link_timeout the resulting CQE may have the res field set to -ENOENT. This return value is not documented in the io_uring_prep_link_timeout(3) man page and understanding what the error code is trying to convey is non-trivial.

The following example

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

#include <liburing.h>

int main() {
    enum { NOP, TIMEOUT };
    struct io_uring ring;
    io_uring_queue_init(2, &ring, 0);

    struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
    io_uring_prep_nop(sqe);
    io_uring_sqe_set_data(sqe, (void *)NOP);
    io_uring_sqe_set_flags(sqe, IOSQE_IO_LINK);
    sqe = io_uring_get_sqe(&ring);
    io_uring_prep_link_timeout(sqe, &(struct __kernel_timespec) {.tv_nsec = 1}, 0);
    io_uring_sqe_set_data(sqe, (void *)TIMEOUT);
    io_uring_submit(&ring);

    struct io_uring_cqe *cqe;
    for (int i = 0; i < 2; i++) {
        io_uring_wait_cqe(&ring, &cqe);
        printf("Get %s\n", io_uring_cqe_get_data(cqe) == (void *)NOP ? "NOP" : "TIMEOUT");
        if (cqe->res < 0) {
            printf("%s%s\n", strerror(-cqe->res), -cqe->res == ENOENT ? " (ENOENT)" : "");
            return EXIT_FAILURE;
        }
    io_uring_cqe_seen(&ring, cqe);
    }
    io_uring_queue_exit(&ring);
    return EXIT_SUCCESS;
}

Produces the output:

Get NOP Get TIMEOUT No such file or directory (ENOENT)

Running on kernels

axboe commented 2 months ago

Yep that can trigger, when the previous request has already completed, like in your case. I'll augment the man page.

buracchi commented 2 months ago

When the previous request has already completed shouldn't it trigger a -ECANCELED? I've noticed this behavior happening even if the linked request is still pending. It seems related to "small" timeout values.

axboe commented 2 months ago

-ECANCELED would mean that it canceled the previous request. But yes, if the timeout is small, races are more likely to happen, that's just unavoidable, and then you may see either one.