• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test waiting for more events than what will be posted with
4  *		a timeout with DEFER_TASKRUN. All kernels should time out,
5  *		but a non-buggy kernel will end up with one CQE available
6  *		for reaping. Buggy kernels will not have processed the
7  *		task_work and will have 0 events.
8  *
9  */
10 #include <errno.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <pthread.h>
16 
17 #include "liburing.h"
18 #include "helpers.h"
19 
20 struct d {
21 	int fd;
22 };
23 
thread_fn(void * data)24 static void *thread_fn(void *data)
25 {
26 	struct d *d = data;
27 	int ret;
28 
29 	usleep(100000);
30 	ret = write(d->fd, "Hello", 5);
31 	if (ret < 0)
32 		perror("write");
33 	return NULL;
34 }
35 
test_poll(struct io_uring * ring)36 static int test_poll(struct io_uring *ring)
37 {
38 	struct io_uring_cqe *cqe;
39 	struct io_uring_sqe *sqe;
40 	struct __kernel_timespec ts;
41 	int ret, fds[2], i;
42 	pthread_t thread;
43 	char buf[32];
44 	struct d d;
45 	void *tret;
46 
47 	if (pipe(fds) < 0) {
48 		perror("pipe");
49 		return 1;
50 	}
51 	d.fd = fds[1];
52 
53 	sqe = io_uring_get_sqe(ring);
54 	io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0);
55 
56 	pthread_create(&thread, NULL, thread_fn, &d);
57 
58 	ts.tv_sec = 1;
59 	ts.tv_nsec = 0;
60 
61 	ret = io_uring_submit_and_wait_timeout(ring, &cqe, 2, &ts, NULL);
62 	if (ret != 1) {
63 		fprintf(stderr, "unexpected wait ret %d\n", ret);
64 		return T_EXIT_FAIL;
65 	}
66 
67 	for (i = 0; i < 2; i++) {
68 		ret = io_uring_peek_cqe(ring, &cqe);
69 		if (ret)
70 			break;
71 		io_uring_cqe_seen(ring, cqe);
72 	}
73 
74 	if (i != 1) {
75 		fprintf(stderr, "Got %d request, expected 1\n", i);
76 		return T_EXIT_FAIL;
77 	}
78 
79 	pthread_join(thread, &tret);
80 	return T_EXIT_PASS;
81 }
82 
test_file(struct io_uring * ring,char * __fname)83 static int test_file(struct io_uring *ring, char *__fname)
84 {
85 	struct io_uring_cqe *cqe;
86 	struct io_uring_sqe *sqe;
87 	struct __kernel_timespec ts;
88 	char filename[64], *fname;
89 	int fd, ret, i;
90 	void *buf;
91 
92 	if (!__fname) {
93 		fname = filename;
94 		sprintf(fname, ".defer-tw-timeout.%d", getpid());
95 		t_create_file(fname, 128*1024);
96 	} else {
97 		fname = __fname;
98 	}
99 
100 	fd = open(fname, O_RDONLY | O_DIRECT);
101 	if (fd < 0) {
102 		if (errno == EINVAL || errno == EPERM || errno == EACCES) {
103 			if (!__fname)
104 				unlink(fname);
105 			return T_EXIT_SKIP;
106 		}
107 		perror("open");
108 		if (!__fname)
109 			unlink(fname);
110 		return T_EXIT_FAIL;
111 	}
112 
113 	if (!__fname)
114 		unlink(fname);
115 
116 	if (posix_memalign(&buf, 4096, 4096)) {
117 		close(fd);
118 		return T_EXIT_FAIL;
119 	}
120 
121 	sqe = io_uring_get_sqe(ring);
122 	io_uring_prep_read(sqe, fd, buf, 4096, 0);
123 
124 	ts.tv_sec = 1;
125 	ts.tv_nsec = 0;
126 
127 	ret = io_uring_submit_and_wait_timeout(ring, &cqe, 2, &ts, NULL);
128 	if (ret != 1) {
129 		fprintf(stderr, "unexpected wait ret %d\n", ret);
130 		close(fd);
131 		free(buf);
132 		return T_EXIT_FAIL;
133 	}
134 
135 	for (i = 0; i < 2; i++) {
136 		ret = io_uring_peek_cqe(ring, &cqe);
137 		if (ret)
138 			break;
139 		io_uring_cqe_seen(ring, cqe);
140 	}
141 
142 	if (i != 1) {
143 		fprintf(stderr, "Got %d request, expected 1\n", i);
144 		close(fd);
145 		free(buf);
146 		return T_EXIT_FAIL;
147 	}
148 
149 	close(fd);
150 	free(buf);
151 	return T_EXIT_PASS;
152 }
153 
main(int argc,char * argv[])154 int main(int argc, char *argv[])
155 {
156 	struct io_uring ring;
157 	char *fname = NULL;
158 	int ret;
159 
160 	ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN);
161 	if (ret == -EINVAL)
162 		return T_EXIT_SKIP;
163 
164 	if (argc > 1)
165 		fname = argv[1];
166 
167 	ret = test_file(&ring, fname);
168 	if (ret != T_EXIT_PASS)
169 		return ret;
170 
171 	ret = test_poll(&ring);
172 	if (ret != T_EXIT_PASS)
173 		return ret;
174 
175 	return T_EXIT_PASS;
176 }
177