1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker * Based on a test case from Josef Grieb - test that we can exit without
4*25da2beaSAndroid Build Coastguard Worker * hanging if we have the task file table pinned by a request that is linked
5*25da2beaSAndroid Build Coastguard Worker * to another request that doesn't finish.
6*25da2beaSAndroid Build Coastguard Worker */
7*25da2beaSAndroid Build Coastguard Worker #include <errno.h>
8*25da2beaSAndroid Build Coastguard Worker #include <fcntl.h>
9*25da2beaSAndroid Build Coastguard Worker #include <netinet/in.h>
10*25da2beaSAndroid Build Coastguard Worker #include <stdio.h>
11*25da2beaSAndroid Build Coastguard Worker #include <stdlib.h>
12*25da2beaSAndroid Build Coastguard Worker #include <string.h>
13*25da2beaSAndroid Build Coastguard Worker #include <strings.h>
14*25da2beaSAndroid Build Coastguard Worker #include <sys/socket.h>
15*25da2beaSAndroid Build Coastguard Worker #include <unistd.h>
16*25da2beaSAndroid Build Coastguard Worker #include <poll.h>
17*25da2beaSAndroid Build Coastguard Worker #include "liburing.h"
18*25da2beaSAndroid Build Coastguard Worker
19*25da2beaSAndroid Build Coastguard Worker #define BACKLOG 512
20*25da2beaSAndroid Build Coastguard Worker
21*25da2beaSAndroid Build Coastguard Worker #define PORT 9100
22*25da2beaSAndroid Build Coastguard Worker
23*25da2beaSAndroid Build Coastguard Worker static struct io_uring ring;
24*25da2beaSAndroid Build Coastguard Worker
add_poll(struct io_uring * ring,int fd)25*25da2beaSAndroid Build Coastguard Worker static void add_poll(struct io_uring *ring, int fd)
26*25da2beaSAndroid Build Coastguard Worker {
27*25da2beaSAndroid Build Coastguard Worker struct io_uring_sqe *sqe;
28*25da2beaSAndroid Build Coastguard Worker
29*25da2beaSAndroid Build Coastguard Worker sqe = io_uring_get_sqe(ring);
30*25da2beaSAndroid Build Coastguard Worker io_uring_prep_poll_add(sqe, fd, POLLIN);
31*25da2beaSAndroid Build Coastguard Worker sqe->flags |= IOSQE_IO_LINK;
32*25da2beaSAndroid Build Coastguard Worker }
33*25da2beaSAndroid Build Coastguard Worker
add_accept(struct io_uring * ring,int fd)34*25da2beaSAndroid Build Coastguard Worker static void add_accept(struct io_uring *ring, int fd)
35*25da2beaSAndroid Build Coastguard Worker {
36*25da2beaSAndroid Build Coastguard Worker struct io_uring_sqe *sqe;
37*25da2beaSAndroid Build Coastguard Worker
38*25da2beaSAndroid Build Coastguard Worker sqe = io_uring_get_sqe(ring);
39*25da2beaSAndroid Build Coastguard Worker io_uring_prep_accept(sqe, fd, 0, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
40*25da2beaSAndroid Build Coastguard Worker }
41*25da2beaSAndroid Build Coastguard Worker
setup_io_uring(void)42*25da2beaSAndroid Build Coastguard Worker static int setup_io_uring(void)
43*25da2beaSAndroid Build Coastguard Worker {
44*25da2beaSAndroid Build Coastguard Worker int ret;
45*25da2beaSAndroid Build Coastguard Worker
46*25da2beaSAndroid Build Coastguard Worker ret = io_uring_queue_init(16, &ring, 0);
47*25da2beaSAndroid Build Coastguard Worker if (ret) {
48*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "Unable to setup io_uring: %s\n", strerror(-ret));
49*25da2beaSAndroid Build Coastguard Worker return 1;
50*25da2beaSAndroid Build Coastguard Worker }
51*25da2beaSAndroid Build Coastguard Worker
52*25da2beaSAndroid Build Coastguard Worker return 0;
53*25da2beaSAndroid Build Coastguard Worker }
54*25da2beaSAndroid Build Coastguard Worker
alarm_sig(int sig)55*25da2beaSAndroid Build Coastguard Worker static void alarm_sig(int sig)
56*25da2beaSAndroid Build Coastguard Worker {
57*25da2beaSAndroid Build Coastguard Worker exit(0);
58*25da2beaSAndroid Build Coastguard Worker }
59*25da2beaSAndroid Build Coastguard Worker
main(int argc,char * argv[])60*25da2beaSAndroid Build Coastguard Worker int main(int argc, char *argv[])
61*25da2beaSAndroid Build Coastguard Worker {
62*25da2beaSAndroid Build Coastguard Worker struct sockaddr_in serv_addr;
63*25da2beaSAndroid Build Coastguard Worker struct io_uring_cqe *cqe;
64*25da2beaSAndroid Build Coastguard Worker int ret, sock_listen_fd;
65*25da2beaSAndroid Build Coastguard Worker const int val = 1;
66*25da2beaSAndroid Build Coastguard Worker int i;
67*25da2beaSAndroid Build Coastguard Worker
68*25da2beaSAndroid Build Coastguard Worker if (argc > 1)
69*25da2beaSAndroid Build Coastguard Worker return 0;
70*25da2beaSAndroid Build Coastguard Worker
71*25da2beaSAndroid Build Coastguard Worker sock_listen_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
72*25da2beaSAndroid Build Coastguard Worker if (sock_listen_fd < 0) {
73*25da2beaSAndroid Build Coastguard Worker perror("socket");
74*25da2beaSAndroid Build Coastguard Worker return 1;
75*25da2beaSAndroid Build Coastguard Worker }
76*25da2beaSAndroid Build Coastguard Worker
77*25da2beaSAndroid Build Coastguard Worker setsockopt(sock_listen_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
78*25da2beaSAndroid Build Coastguard Worker
79*25da2beaSAndroid Build Coastguard Worker memset(&serv_addr, 0, sizeof(serv_addr));
80*25da2beaSAndroid Build Coastguard Worker serv_addr.sin_family = AF_INET;
81*25da2beaSAndroid Build Coastguard Worker serv_addr.sin_addr.s_addr = INADDR_ANY;
82*25da2beaSAndroid Build Coastguard Worker
83*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 100; i++) {
84*25da2beaSAndroid Build Coastguard Worker serv_addr.sin_port = htons(PORT + i);
85*25da2beaSAndroid Build Coastguard Worker
86*25da2beaSAndroid Build Coastguard Worker ret = bind(sock_listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
87*25da2beaSAndroid Build Coastguard Worker if (!ret)
88*25da2beaSAndroid Build Coastguard Worker break;
89*25da2beaSAndroid Build Coastguard Worker if (errno != EADDRINUSE) {
90*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "bind: %s\n", strerror(errno));
91*25da2beaSAndroid Build Coastguard Worker return 1;
92*25da2beaSAndroid Build Coastguard Worker }
93*25da2beaSAndroid Build Coastguard Worker if (i == 99) {
94*25da2beaSAndroid Build Coastguard Worker printf("Gave up on finding a port, skipping\n");
95*25da2beaSAndroid Build Coastguard Worker goto out;
96*25da2beaSAndroid Build Coastguard Worker }
97*25da2beaSAndroid Build Coastguard Worker }
98*25da2beaSAndroid Build Coastguard Worker
99*25da2beaSAndroid Build Coastguard Worker if (listen(sock_listen_fd, BACKLOG) < 0) {
100*25da2beaSAndroid Build Coastguard Worker perror("Error listening on socket\n");
101*25da2beaSAndroid Build Coastguard Worker return 1;
102*25da2beaSAndroid Build Coastguard Worker }
103*25da2beaSAndroid Build Coastguard Worker
104*25da2beaSAndroid Build Coastguard Worker if (setup_io_uring())
105*25da2beaSAndroid Build Coastguard Worker return 1;
106*25da2beaSAndroid Build Coastguard Worker
107*25da2beaSAndroid Build Coastguard Worker add_poll(&ring, sock_listen_fd);
108*25da2beaSAndroid Build Coastguard Worker add_accept(&ring, sock_listen_fd);
109*25da2beaSAndroid Build Coastguard Worker
110*25da2beaSAndroid Build Coastguard Worker ret = io_uring_submit(&ring);
111*25da2beaSAndroid Build Coastguard Worker if (ret != 2) {
112*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "submit=%d\n", ret);
113*25da2beaSAndroid Build Coastguard Worker return 1;
114*25da2beaSAndroid Build Coastguard Worker }
115*25da2beaSAndroid Build Coastguard Worker
116*25da2beaSAndroid Build Coastguard Worker signal(SIGALRM, alarm_sig);
117*25da2beaSAndroid Build Coastguard Worker alarm(1);
118*25da2beaSAndroid Build Coastguard Worker
119*25da2beaSAndroid Build Coastguard Worker ret = io_uring_wait_cqe(&ring, &cqe);
120*25da2beaSAndroid Build Coastguard Worker if (ret) {
121*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "wait_cqe=%d\n", ret);
122*25da2beaSAndroid Build Coastguard Worker return 1;
123*25da2beaSAndroid Build Coastguard Worker }
124*25da2beaSAndroid Build Coastguard Worker
125*25da2beaSAndroid Build Coastguard Worker out:
126*25da2beaSAndroid Build Coastguard Worker io_uring_queue_exit(&ring);
127*25da2beaSAndroid Build Coastguard Worker return 0;
128*25da2beaSAndroid Build Coastguard Worker }
129