Hi, I'm trying to read multiple files with io_uring and getting stuck, because the link and drain flags don't seem to do what they are documented to do. Kernel is v5.17 and liburing is compiled from the git tree at 7a3a27b6a384 ("add tests for nonblocking accept sockets"). Without those flags the attached example works some of the time, but that's probably accidental since ordering is not ensured. Adding the drain or link flags make it even worse (fail in casese that the unordered one didn't). What am I missing? Thanks, Miklos
#include <stdio.h> #include <fcntl.h> #include <string.h> #include <stdlib.h> #include <err.h> #include "liburing.h" #define CHECK_NEGERR(_expr) \ ({ typeof(_expr) _ret = (_expr); if (_ret < 0) { errno = -_ret; err(1, #_expr); } _ret; }) #define CHECK_NULL(_expr) \ ({ typeof(_expr) _ret = (_expr); if (_ret == NULL) { errx(1, #_expr " returned NULL"); } _ret; }) int main(int argc, char *argv[]) { struct io_uring ring; int ret, o, i, j, x, num, slot; struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; char *s, **bufs; int *fds; const size_t bufsize = 131072; const int ops_per_file = 2; if (argc < 2) errx(1, "usage: %s file [...]", argv[0]); num = argc - 1; bufs = CHECK_NULL(calloc(num, sizeof(bufs[0]))); fds = CHECK_NULL(calloc(num, sizeof(fds[0]))); for (i = 0; i < num; i++) { bufs[i] = CHECK_NULL(malloc(bufsize)); fds[i] = -1; } ret = CHECK_NEGERR(io_uring_queue_init(num * ops_per_file, &ring, 0)); ret = CHECK_NEGERR(io_uring_register_files(&ring, fds, num)); for (i = 0; i < num; i++) { slot = i; sqe = CHECK_NULL(io_uring_get_sqe(&ring)); sqe->user_data = i * ops_per_file; io_uring_prep_openat_direct(sqe, AT_FDCWD, argv[i + 1], O_RDONLY, 0, slot); // sqe->flags |= IOSQE_IO_DRAIN; // sqe->flags |= IOSQE_IO_LINK; sqe = CHECK_NULL(io_uring_get_sqe(&ring)); sqe->user_data = i * ops_per_file + 1; io_uring_prep_read(sqe, slot, bufs[i], bufsize, 0); sqe->flags |= IOSQE_FIXED_FILE; // sqe->flags |= IOSQE_IO_DRAIN; // sqe->flags |= IOSQE_IO_LINK; } ret = CHECK_NEGERR(io_uring_submit(&ring)); if (ret != num * ops_per_file) warnx("io_uring_submit submitted less: %d\n", ret); for (j = ret; j; j--) { CHECK_NEGERR(io_uring_wait_cqe(&ring, &cqe)); x = cqe->user_data % ops_per_file; i = cqe->user_data / ops_per_file; printf("%i/%i [%s] = ", i, x, argv[i + 1]); ret = cqe->res; if (ret < 0) { printf("ERROR: %s (%i)\n", strerror(-ret), ret); } else if (x == 1) { s = bufs[i]; for (o = 0; o < ret; o += strlen(s + o) + 1) printf("\"%.*s\" ", ret - o, s + o); printf("(len=%i)\n", ret); } else if (x == 0) { printf("SUCCESS open\n"); } else { printf("SUCCESS ???\n"); } io_uring_cqe_seen(&ring, cqe); } io_uring_queue_exit(&ring); return 0; }