#include #include #include #include #include #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; }