This new test checks if the mechanism to enable/disable notifications through eventfd when a request is completed works correctly. Signed-off-by: Stefano Garzarella <sgarzare@xxxxxxxxxx> --- .gitignore | 1 + test/Makefile | 4 +- test/eventfd-disable.c | 148 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 test/eventfd-disable.c diff --git a/.gitignore b/.gitignore index 9784f0b..7f01e6e 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ /test/defer /test/eeed8b54e0df-test /test/eventfd +/test/eventfd-disable /test/eventfd-ring /test/fadvise /test/fallocate diff --git a/test/Makefile b/test/Makefile index ff4d4b8..a46e45d 100644 --- a/test/Makefile +++ b/test/Makefile @@ -21,7 +21,7 @@ all_targets += poll poll-cancel ring-leak fsync io_uring_setup io_uring_register file-update accept-reuse poll-v-poll fadvise madvise \ short-read openat2 probe shared-wq personality eventfd \ send_recv eventfd-ring across-fork sq-poll-kthread splice \ - lfs-openat lfs-openat-write + lfs-openat lfs-openat-write eventfd-disable include ../Makefile.quiet @@ -53,7 +53,7 @@ test_srcs := poll.c poll-cancel.c ring-leak.c fsync.c io_uring_setup.c \ file-update.c accept-reuse.c poll-v-poll.c fadvise.c \ madvise.c short-read.c openat2.c probe.c shared-wq.c \ personality.c eventfd.c eventfd-ring.c across-fork.c sq-poll-kthread.c \ - splice.c lfs-openat.c lfs-openat-write.c + splice.c lfs-openat.c lfs-openat-write.c eventfd-disable.c ifdef CONFIG_HAVE_STATX test_srcs += statx.c diff --git a/test/eventfd-disable.c b/test/eventfd-disable.c new file mode 100644 index 0000000..d4fb14e --- /dev/null +++ b/test/eventfd-disable.c @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: test disable/enable notifications through eventfd + * + */ +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/poll.h> +#include <sys/eventfd.h> + +#include "liburing.h" + +int main(int argc, char *argv[]) +{ + struct io_uring_params p = {}; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + uint64_t ptr; + struct iovec vec = { + .iov_base = &ptr, + .iov_len = sizeof(ptr) + }; + int ret, evfd, i; + + ret = io_uring_queue_init_params(64, &ring, &p); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + evfd = eventfd(0, EFD_CLOEXEC); + if (evfd < 0) { + perror("eventfd"); + return 1; + } + + ret = io_uring_register_eventfd(&ring, evfd); + if (ret) { + fprintf(stderr, "failed to register evfd: %d\n", ret); + return 1; + } + + if (!io_uring_cq_eventfd_enabled(&ring)) { + fprintf(stderr, "eventfd disabled\n"); + return 1; + } + + ret = io_uring_cq_eventfd_enable(&ring, false); + if (ret) { + fprintf(stdout, "Skipping, CQ flags not available!\n"); + return 0; + } + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_readv(sqe, evfd, &vec, 1, 0); + sqe->user_data = 1; + + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "submit: %d\n", ret); + return 1; + } + + for (i = 0; i < 63; i++) { + sqe = io_uring_get_sqe(&ring); + io_uring_prep_nop(sqe); + sqe->user_data = 2; + } + + ret = io_uring_submit(&ring); + if (ret != 63) { + fprintf(stderr, "submit: %d\n", ret); + return 1; + } + + for (i = 0; i < 63; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait: %d\n", ret); + return 1; + } + + switch (cqe->user_data) { + case 1: /* eventfd */ + fprintf(stderr, "eventfd unexpected: %d\n", (int)ptr); + return 1; + case 2: + if (cqe->res) { + fprintf(stderr, "nop: %d\n", cqe->res); + return 1; + } + break; + } + io_uring_cqe_seen(&ring, cqe); + } + + ret = io_uring_cq_eventfd_enable(&ring, true); + if (ret) { + fprintf(stderr, "io_uring_cq_eventfd_enable: %d\n", ret); + return 1; + } + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_nop(sqe); + sqe->user_data = 2; + + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "submit: %d\n", ret); + return 1; + } + + for (i = 0; i < 2; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait: %d\n", ret); + return 1; + } + + switch (cqe->user_data) { + case 1: /* eventfd */ + if (cqe->res != sizeof(ptr)) { + fprintf(stderr, "read res: %d\n", cqe->res); + return 1; + } + + if (ptr != 1) { + fprintf(stderr, "eventfd: %d\n", (int)ptr); + return 1; + } + break; + case 2: + if (cqe->res) { + fprintf(stderr, "nop: %d\n", cqe->res); + return 1; + } + break; + } + io_uring_cqe_seen(&ring, cqe); + } + + return 0; +} -- 2.25.4