Cancel three futex waits, and three waitids, that share a user_data with one IORING_ASYNC_CANCEL_ALL. The cancel completes with 3, the number of requests it canceled. Kernels that lack "io_uring/cancel: count all canceled futex and waitid requests on CANCEL_ALL" complete the cancel with 1. Signed-off-by: agxr --- test/futex.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ test/waitid.c | 26 +++++++++++++++++--------- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/test/futex.c b/test/futex.c index 4dc5a305..265f3675 100644 --- a/test/futex.c +++ b/test/futex.c @@ -474,6 +474,44 @@ static int test_invalid(void) return 0; } +static int test_cancel_all(void) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + unsigned int futex = 0; + int ret, i; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) + return ret; + + for (i = 0; i < 3; i++) { + sqe = io_uring_get_sqe(&ring); + io_uring_prep_futex_wait(sqe, &futex, 0, FUTEX_BITSET_MATCH_ANY, + FUTEX2_SIZE_U32, 0); + sqe->user_data = 1; + } + sqe = io_uring_get_sqe(&ring); + io_uring_prep_cancel64(sqe, 1, IORING_ASYNC_CANCEL_ALL); + sqe->user_data = 2; + io_uring_submit(&ring); + + for (i = 0; i < 4; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) + return ret; + if (cqe->user_data == 2 && cqe->res != 3) { + fprintf(stderr, "cancel all res %d\n", cqe->res); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + } + + io_uring_queue_exit(&ring); + return 0; +} + int main(int argc, char *argv[]) { int ret; @@ -579,5 +617,11 @@ int main(int argc, char *argv[]) return T_EXIT_FAIL; } + ret = test_cancel_all(); + if (ret) { + fprintf(stderr, "cancel_all failed\n"); + return T_EXIT_FAIL; + } + return T_EXIT_PASS; } diff --git a/test/waitid.c b/test/waitid.c index a8c3488f..371b5e5e 100644 --- a/test/waitid.c +++ b/test/waitid.c @@ -211,9 +211,9 @@ static int test_ready(struct io_uring *ring) } /* - * Test cancelation of pending waitid + * Test cancelation of nr pending waitids */ -static int test_cancel(struct io_uring *ring) +static int test_cancel(struct io_uring *ring, int nr) { struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; @@ -226,19 +226,21 @@ static int test_cancel(struct io_uring *ring) exit(0); } - sqe = io_uring_get_sqe(ring); - io_uring_prep_waitid(sqe, P_PID, pid, NULL, WEXITED, 0); - sqe->user_data = 1; + for (i = 0; i < nr; i++) { + sqe = io_uring_get_sqe(ring); + io_uring_prep_waitid(sqe, P_PID, pid, NULL, WEXITED, 0); + sqe->user_data = 1; + } io_uring_submit(ring); sqe = io_uring_get_sqe(ring); - io_uring_prep_cancel64(sqe, 1, 0); + io_uring_prep_cancel64(sqe, 1, nr > 1 ? IORING_ASYNC_CANCEL_ALL : 0); sqe->user_data = 2; io_uring_submit(ring); - for (i = 0; i < 2; i++) { + for (i = 0; i < nr + 1; i++) { ret = io_uring_wait_cqe(ring, &cqe); if (ret) { fprintf(stderr, "cqe wait: %d\n", ret); @@ -248,7 +250,7 @@ static int test_cancel(struct io_uring *ring) fprintf(stderr, "cqe res: %d\n", cqe->res); return T_EXIT_FAIL; } - if (cqe->user_data == 2 && cqe->res != 1) { + if (cqe->user_data == 2 && cqe->res != nr) { fprintf(stderr, "cqe res: %d\n", cqe->res); return T_EXIT_FAIL; } @@ -510,12 +512,18 @@ int main(int argc, char *argv[]) return T_EXIT_FAIL; } - ret = test_cancel(&ring); + ret = test_cancel(&ring, 1); if (ret == T_EXIT_FAIL) { fprintf(stderr, "test_cancel failed\n"); return T_EXIT_FAIL; } + ret = test_cancel(&ring, 3); + if (ret == T_EXIT_FAIL) { + fprintf(stderr, "test_cancel all failed\n"); + return T_EXIT_FAIL; + } + ret = test_invalid_infop(&ring); if (ret == T_EXIT_FAIL) { fprintf(stderr, "test_invalid_infop failed\n"); -- 2.56.0