diff options
Diffstat (limited to 'test/timeout.c')
-rw-r--r-- | test/timeout.c | 190 |
1 files changed, 185 insertions, 5 deletions
diff --git a/test/timeout.c b/test/timeout.c index a28d599..2fd4736 100644 --- a/test/timeout.c +++ b/test/timeout.c @@ -10,6 +10,9 @@ #include <string.h> #include <fcntl.h> #include <sys/time.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <sys/stat.h> #include "liburing.h" #include "../src/syscall.h" @@ -180,7 +183,8 @@ err: return 1; } -static int test_single_timeout_wait(struct io_uring *ring) +static int test_single_timeout_wait(struct io_uring *ring, + struct io_uring_params *p) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -195,6 +199,15 @@ static int test_single_timeout_wait(struct io_uring *ring) io_uring_prep_nop(sqe); io_uring_sqe_set_data(sqe, (void *) 1); + /* no implied submit for newer kernels */ + if (p->features & IORING_FEAT_EXT_ARG) { + ret = io_uring_submit(ring); + if (ret != 2) { + fprintf(stderr, "%s: submit %d\n", __FUNCTION__, ret); + return 1; + } + } + msec_to_ts(&ts, 1000); i = 0; @@ -550,8 +563,8 @@ static int test_multi_timeout(struct io_uring *ring) gettimeofday(&tv, NULL); for (i = 0; i < 2; i++) { - unsigned int time; - __u64 user_data; + unsigned int time = 0; + __u64 user_data = 0; ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { @@ -1161,16 +1174,171 @@ err: return 1; } +static int fill_exec_target(char *dst, char *path) +{ + struct stat sb; + + /* + * Should either be ./exec-target.t or test/exec-target.t + */ + sprintf(dst, "%s", path); + return stat(dst, &sb); +} + +static int test_timeout_link_cancel(void) +{ + struct io_uring ring; + struct io_uring_cqe *cqe; + char prog_path[PATH_MAX]; + pid_t p; + int ret, i, wstatus; + + if (fill_exec_target(prog_path, "./exec-target.t") && + fill_exec_target(prog_path, "test/exec-target.t")) { + fprintf(stdout, "Can't find exec-target, skipping\n"); + return 0; + } + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring create failed: %d\n", ret); + return 1; + } + + p = fork(); + if (p == -1) { + fprintf(stderr, "fork() failed\n"); + return 1; + } + + if (p == 0) { + struct io_uring_sqe *sqe; + struct __kernel_timespec ts; + + msec_to_ts(&ts, 10000); + sqe = io_uring_get_sqe(&ring); + io_uring_prep_timeout(sqe, &ts, 0, 0); + sqe->flags |= IOSQE_IO_LINK; + sqe->user_data = 0; + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_nop(sqe); + sqe->user_data = 1; + + ret = io_uring_submit(&ring); + if (ret != 2) { + fprintf(stderr, "%s: got %d, wanted 1\n", __FUNCTION__, ret); + exit(1); + } + + /* trigger full cancellation */ + ret = execl(prog_path, prog_path, NULL); + if (ret) { + fprintf(stderr, "exec failed %i\n", errno); + exit(1); + } + exit(0); + } + + if (waitpid(p, &wstatus, 0) == (pid_t)-1) { + perror("waitpid()"); + return 1; + } + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) { + fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus)); + return 1; + } + + for (i = 0; i < 2; ++i) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe=%d\n", ret); + return 1; + } + if (cqe->res != -ECANCELED) { + fprintf(stderr, "invalid result, user_data: %i res: %i\n", + (int)cqe->user_data, cqe->res); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + } + + io_uring_queue_exit(&ring); + return 0; +} + + +static int test_not_failing_links(void) +{ + struct io_uring ring; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct __kernel_timespec ts; + int ret; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring create failed: %d\n", ret); + return 1; + } + + msec_to_ts(&ts, 1); + sqe = io_uring_get_sqe(&ring); + io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_ETIME_SUCCESS); + sqe->user_data = 1; + sqe->flags |= IOSQE_IO_LINK; + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_nop(sqe); + sqe->user_data = 2; + + ret = io_uring_submit(&ring); + if (ret != 2) { + fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret); + return 1; + } + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0) { + fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret); + return 1; + } else if (cqe->user_data == 1 && cqe->res == -EINVAL) { + fprintf(stderr, "ETIME_SUCCESS is not supported, skip\n"); + goto done; + } else if (cqe->res != -ETIME || cqe->user_data != 1) { + fprintf(stderr, "timeout failed %i %i\n", cqe->res, + (int)cqe->user_data); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0) { + fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret); + return 1; + } else if (cqe->res || cqe->user_data != 2) { + fprintf(stderr, "nop failed %i %i\n", cqe->res, + (int)cqe->user_data); + return 1; + } +done: + io_uring_cqe_seen(&ring, cqe); + io_uring_queue_exit(&ring); + return 0; +} + + int main(int argc, char *argv[]) { struct io_uring ring, sqpoll_ring; bool has_timeout_update, sqpoll; + struct io_uring_params p = { }; int ret; if (argc > 1) return 0; - ret = io_uring_queue_init(8, &ring, 0); + ret = io_uring_queue_init_params(8, &ring, &p); if (ret) { fprintf(stderr, "ring setup failed\n"); return 1; @@ -1252,7 +1420,7 @@ int main(int argc, char *argv[]) return ret; } - ret = test_single_timeout_wait(&ring); + ret = test_single_timeout_wait(&ring, &p); if (ret) { fprintf(stderr, "test_single_timeout_wait failed\n"); return ret; @@ -1337,6 +1505,18 @@ int main(int argc, char *argv[]) return ret; } + ret = test_timeout_link_cancel(); + if (ret) { + fprintf(stderr, "test_timeout_link_cancel failed\n"); + return ret; + } + + ret = test_not_failing_links(); + if (ret) { + fprintf(stderr, "test_not_failing_links failed\n"); + return ret; + } + if (sqpoll) io_uring_queue_exit(&sqpoll_ring); return 0; |