1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Test that we don't recursively generate completion events if an io_uring
4 * has an eventfd registered that triggers on completions, and we add a poll
5 * request with multishot on the eventfd. Older kernels will stop on overflow,
6 * newer kernels will detect this earlier and abort correctly.
7 */
8 #include <errno.h>
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <sys/eventfd.h>
13 #include <sys/types.h>
14 #include <poll.h>
15 #include <assert.h>
16 #include "liburing.h"
17 #include "helpers.h"
18
main(int argc,char * argv[])19 int main(int argc, char *argv[])
20 {
21 struct io_uring ring;
22 struct io_uring_sqe *sqe;
23 struct io_uring_cqe *cqe;
24 int ret, efd, i;
25
26 if (argc > 1)
27 return T_EXIT_SKIP;
28
29 ret = io_uring_queue_init(8, &ring, 0);
30 if (ret) {
31 fprintf(stderr, "Ring init failed: %d\n", ret);
32 return T_EXIT_FAIL;
33 }
34
35 efd = eventfd(0, 0);
36 if (efd < 0) {
37 perror("eventfd");
38 return T_EXIT_FAIL;
39 }
40
41 ret = io_uring_register_eventfd(&ring, efd);
42 if (ret) {
43 fprintf(stderr, "Ring eventfd register failed: %d\n", ret);
44 return T_EXIT_FAIL;
45 }
46
47 sqe = io_uring_get_sqe(&ring);
48 io_uring_prep_poll_multishot(sqe, efd, POLLIN);
49 sqe->user_data = 1;
50 io_uring_submit(&ring);
51
52 sqe = io_uring_get_sqe(&ring);
53 sqe->user_data = 2;
54 io_uring_prep_nop(sqe);
55 io_uring_submit(&ring);
56
57 for (i = 0; i < 2; i++) {
58 ret = io_uring_wait_cqe(&ring, &cqe);
59 if (ret) {
60 fprintf(stderr, "wait_cqe ret = %d\n", ret);
61 break;
62 }
63 io_uring_cqe_seen(&ring, cqe);
64 }
65
66 ret = io_uring_peek_cqe(&ring, &cqe);
67 if (!ret) {
68 fprintf(stderr, "Generated too many events\n");
69 return T_EXIT_FAIL;
70 }
71
72 return T_EXIT_PASS;
73 }
74