xref: /aosp_15_r20/external/liburing/test/read-write.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker  * Description: basic read/write tests with buffered, O_DIRECT, and SQPOLL
4*25da2beaSAndroid Build Coastguard Worker  */
5*25da2beaSAndroid Build Coastguard Worker #include <errno.h>
6*25da2beaSAndroid Build Coastguard Worker #include <stdio.h>
7*25da2beaSAndroid Build Coastguard Worker #include <unistd.h>
8*25da2beaSAndroid Build Coastguard Worker #include <stdlib.h>
9*25da2beaSAndroid Build Coastguard Worker #include <string.h>
10*25da2beaSAndroid Build Coastguard Worker #include <fcntl.h>
11*25da2beaSAndroid Build Coastguard Worker #include <sys/types.h>
12*25da2beaSAndroid Build Coastguard Worker #include <poll.h>
13*25da2beaSAndroid Build Coastguard Worker #include <sys/eventfd.h>
14*25da2beaSAndroid Build Coastguard Worker #include <sys/resource.h>
15*25da2beaSAndroid Build Coastguard Worker 
16*25da2beaSAndroid Build Coastguard Worker #include "helpers.h"
17*25da2beaSAndroid Build Coastguard Worker #include "liburing.h"
18*25da2beaSAndroid Build Coastguard Worker 
19*25da2beaSAndroid Build Coastguard Worker #define FILE_SIZE	(256 * 1024)
20*25da2beaSAndroid Build Coastguard Worker #define BS		8192
21*25da2beaSAndroid Build Coastguard Worker #define BUFFERS		(FILE_SIZE / BS)
22*25da2beaSAndroid Build Coastguard Worker 
23*25da2beaSAndroid Build Coastguard Worker static struct iovec *vecs;
24*25da2beaSAndroid Build Coastguard Worker static int no_read;
25*25da2beaSAndroid Build Coastguard Worker static int no_buf_select;
26*25da2beaSAndroid Build Coastguard Worker static int warned;
27*25da2beaSAndroid Build Coastguard Worker 
create_nonaligned_buffers(void)28*25da2beaSAndroid Build Coastguard Worker static int create_nonaligned_buffers(void)
29*25da2beaSAndroid Build Coastguard Worker {
30*25da2beaSAndroid Build Coastguard Worker 	int i;
31*25da2beaSAndroid Build Coastguard Worker 
32*25da2beaSAndroid Build Coastguard Worker 	vecs = t_malloc(BUFFERS * sizeof(struct iovec));
33*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUFFERS; i++) {
34*25da2beaSAndroid Build Coastguard Worker 		char *p = t_malloc(3 * BS);
35*25da2beaSAndroid Build Coastguard Worker 
36*25da2beaSAndroid Build Coastguard Worker 		if (!p)
37*25da2beaSAndroid Build Coastguard Worker 			return 1;
38*25da2beaSAndroid Build Coastguard Worker 		vecs[i].iov_base = p + (rand() % BS);
39*25da2beaSAndroid Build Coastguard Worker 		vecs[i].iov_len = 1 + (rand() % BS);
40*25da2beaSAndroid Build Coastguard Worker 	}
41*25da2beaSAndroid Build Coastguard Worker 
42*25da2beaSAndroid Build Coastguard Worker 	return 0;
43*25da2beaSAndroid Build Coastguard Worker }
44*25da2beaSAndroid Build Coastguard Worker 
__test_io(const char * file,struct io_uring * ring,int write,int buffered,int sqthread,int fixed,int nonvec,int buf_select,int seq,int exp_len)45*25da2beaSAndroid Build Coastguard Worker static int __test_io(const char *file, struct io_uring *ring, int write,
46*25da2beaSAndroid Build Coastguard Worker 		     int buffered, int sqthread, int fixed, int nonvec,
47*25da2beaSAndroid Build Coastguard Worker 		     int buf_select, int seq, int exp_len)
48*25da2beaSAndroid Build Coastguard Worker {
49*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
50*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
51*25da2beaSAndroid Build Coastguard Worker 	int open_flags;
52*25da2beaSAndroid Build Coastguard Worker 	int i, fd = -1, ret;
53*25da2beaSAndroid Build Coastguard Worker 	off_t offset;
54*25da2beaSAndroid Build Coastguard Worker 
55*25da2beaSAndroid Build Coastguard Worker #ifdef VERBOSE
56*25da2beaSAndroid Build Coastguard Worker 	fprintf(stdout, "%s: start %d/%d/%d/%d/%d: ", __FUNCTION__, write,
57*25da2beaSAndroid Build Coastguard Worker 							buffered, sqthread,
58*25da2beaSAndroid Build Coastguard Worker 							fixed, nonvec);
59*25da2beaSAndroid Build Coastguard Worker #endif
60*25da2beaSAndroid Build Coastguard Worker 	if (write)
61*25da2beaSAndroid Build Coastguard Worker 		open_flags = O_WRONLY;
62*25da2beaSAndroid Build Coastguard Worker 	else
63*25da2beaSAndroid Build Coastguard Worker 		open_flags = O_RDONLY;
64*25da2beaSAndroid Build Coastguard Worker 	if (!buffered)
65*25da2beaSAndroid Build Coastguard Worker 		open_flags |= O_DIRECT;
66*25da2beaSAndroid Build Coastguard Worker 
67*25da2beaSAndroid Build Coastguard Worker 	if (fixed) {
68*25da2beaSAndroid Build Coastguard Worker 		ret = t_register_buffers(ring, vecs, BUFFERS);
69*25da2beaSAndroid Build Coastguard Worker 		if (ret == T_SETUP_SKIP)
70*25da2beaSAndroid Build Coastguard Worker 			return 0;
71*25da2beaSAndroid Build Coastguard Worker 		if (ret != T_SETUP_OK) {
72*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "buffer reg failed: %d\n", ret);
73*25da2beaSAndroid Build Coastguard Worker 			goto err;
74*25da2beaSAndroid Build Coastguard Worker 		}
75*25da2beaSAndroid Build Coastguard Worker 	}
76*25da2beaSAndroid Build Coastguard Worker 
77*25da2beaSAndroid Build Coastguard Worker 	fd = open(file, open_flags);
78*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
79*25da2beaSAndroid Build Coastguard Worker 		perror("file open");
80*25da2beaSAndroid Build Coastguard Worker 		goto err;
81*25da2beaSAndroid Build Coastguard Worker 	}
82*25da2beaSAndroid Build Coastguard Worker 
83*25da2beaSAndroid Build Coastguard Worker 	if (sqthread) {
84*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_register_files(ring, &fd, 1);
85*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
86*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "file reg failed: %d\n", ret);
87*25da2beaSAndroid Build Coastguard Worker 			goto err;
88*25da2beaSAndroid Build Coastguard Worker 		}
89*25da2beaSAndroid Build Coastguard Worker 	}
90*25da2beaSAndroid Build Coastguard Worker 
91*25da2beaSAndroid Build Coastguard Worker 	offset = 0;
92*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUFFERS; i++) {
93*25da2beaSAndroid Build Coastguard Worker 		sqe = io_uring_get_sqe(ring);
94*25da2beaSAndroid Build Coastguard Worker 		if (!sqe) {
95*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "sqe get failed\n");
96*25da2beaSAndroid Build Coastguard Worker 			goto err;
97*25da2beaSAndroid Build Coastguard Worker 		}
98*25da2beaSAndroid Build Coastguard Worker 		if (!seq)
99*25da2beaSAndroid Build Coastguard Worker 			offset = BS * (rand() % BUFFERS);
100*25da2beaSAndroid Build Coastguard Worker 		if (write) {
101*25da2beaSAndroid Build Coastguard Worker 			int do_fixed = fixed;
102*25da2beaSAndroid Build Coastguard Worker 			int use_fd = fd;
103*25da2beaSAndroid Build Coastguard Worker 
104*25da2beaSAndroid Build Coastguard Worker 			if (sqthread)
105*25da2beaSAndroid Build Coastguard Worker 				use_fd = 0;
106*25da2beaSAndroid Build Coastguard Worker 			if (fixed && (i & 1))
107*25da2beaSAndroid Build Coastguard Worker 				do_fixed = 0;
108*25da2beaSAndroid Build Coastguard Worker 			if (do_fixed) {
109*25da2beaSAndroid Build Coastguard Worker 				io_uring_prep_write_fixed(sqe, use_fd, vecs[i].iov_base,
110*25da2beaSAndroid Build Coastguard Worker 								vecs[i].iov_len,
111*25da2beaSAndroid Build Coastguard Worker 								offset, i);
112*25da2beaSAndroid Build Coastguard Worker 			} else if (nonvec) {
113*25da2beaSAndroid Build Coastguard Worker 				io_uring_prep_write(sqe, use_fd, vecs[i].iov_base,
114*25da2beaSAndroid Build Coastguard Worker 							vecs[i].iov_len, offset);
115*25da2beaSAndroid Build Coastguard Worker 			} else {
116*25da2beaSAndroid Build Coastguard Worker 				io_uring_prep_writev(sqe, use_fd, &vecs[i], 1,
117*25da2beaSAndroid Build Coastguard Worker 								offset);
118*25da2beaSAndroid Build Coastguard Worker 			}
119*25da2beaSAndroid Build Coastguard Worker 		} else {
120*25da2beaSAndroid Build Coastguard Worker 			int do_fixed = fixed;
121*25da2beaSAndroid Build Coastguard Worker 			int use_fd = fd;
122*25da2beaSAndroid Build Coastguard Worker 
123*25da2beaSAndroid Build Coastguard Worker 			if (sqthread)
124*25da2beaSAndroid Build Coastguard Worker 				use_fd = 0;
125*25da2beaSAndroid Build Coastguard Worker 			if (fixed && (i & 1))
126*25da2beaSAndroid Build Coastguard Worker 				do_fixed = 0;
127*25da2beaSAndroid Build Coastguard Worker 			if (do_fixed) {
128*25da2beaSAndroid Build Coastguard Worker 				io_uring_prep_read_fixed(sqe, use_fd, vecs[i].iov_base,
129*25da2beaSAndroid Build Coastguard Worker 								vecs[i].iov_len,
130*25da2beaSAndroid Build Coastguard Worker 								offset, i);
131*25da2beaSAndroid Build Coastguard Worker 			} else if (nonvec) {
132*25da2beaSAndroid Build Coastguard Worker 				io_uring_prep_read(sqe, use_fd, vecs[i].iov_base,
133*25da2beaSAndroid Build Coastguard Worker 							vecs[i].iov_len, offset);
134*25da2beaSAndroid Build Coastguard Worker 			} else {
135*25da2beaSAndroid Build Coastguard Worker 				io_uring_prep_readv(sqe, use_fd, &vecs[i], 1,
136*25da2beaSAndroid Build Coastguard Worker 								offset);
137*25da2beaSAndroid Build Coastguard Worker 			}
138*25da2beaSAndroid Build Coastguard Worker 
139*25da2beaSAndroid Build Coastguard Worker 		}
140*25da2beaSAndroid Build Coastguard Worker 		sqe->user_data = i;
141*25da2beaSAndroid Build Coastguard Worker 		if (sqthread)
142*25da2beaSAndroid Build Coastguard Worker 			sqe->flags |= IOSQE_FIXED_FILE;
143*25da2beaSAndroid Build Coastguard Worker 		if (buf_select) {
144*25da2beaSAndroid Build Coastguard Worker 			if (nonvec)
145*25da2beaSAndroid Build Coastguard Worker 				sqe->addr = 0;
146*25da2beaSAndroid Build Coastguard Worker 			sqe->flags |= IOSQE_BUFFER_SELECT;
147*25da2beaSAndroid Build Coastguard Worker 			sqe->buf_group = buf_select;
148*25da2beaSAndroid Build Coastguard Worker 		}
149*25da2beaSAndroid Build Coastguard Worker 		if (seq)
150*25da2beaSAndroid Build Coastguard Worker 			offset += BS;
151*25da2beaSAndroid Build Coastguard Worker 	}
152*25da2beaSAndroid Build Coastguard Worker 
153*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(ring);
154*25da2beaSAndroid Build Coastguard Worker 	if (ret != BUFFERS) {
155*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit got %d, wanted %d\n", ret, BUFFERS);
156*25da2beaSAndroid Build Coastguard Worker 		goto err;
157*25da2beaSAndroid Build Coastguard Worker 	}
158*25da2beaSAndroid Build Coastguard Worker 
159*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUFFERS; i++) {
160*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(ring, &cqe);
161*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
162*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait_cqe=%d\n", ret);
163*25da2beaSAndroid Build Coastguard Worker 			goto err;
164*25da2beaSAndroid Build Coastguard Worker 		}
165*25da2beaSAndroid Build Coastguard Worker 		if (cqe->res == -EINVAL && nonvec) {
166*25da2beaSAndroid Build Coastguard Worker 			if (!warned) {
167*25da2beaSAndroid Build Coastguard Worker 				fprintf(stdout, "Non-vectored IO not "
168*25da2beaSAndroid Build Coastguard Worker 					"supported, skipping\n");
169*25da2beaSAndroid Build Coastguard Worker 				warned = 1;
170*25da2beaSAndroid Build Coastguard Worker 				no_read = 1;
171*25da2beaSAndroid Build Coastguard Worker 			}
172*25da2beaSAndroid Build Coastguard Worker 		} else if (exp_len == -1) {
173*25da2beaSAndroid Build Coastguard Worker 			int iov_len = vecs[cqe->user_data].iov_len;
174*25da2beaSAndroid Build Coastguard Worker 
175*25da2beaSAndroid Build Coastguard Worker 			if (cqe->res != iov_len) {
176*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "cqe res %d, wanted %d\n",
177*25da2beaSAndroid Build Coastguard Worker 					cqe->res, iov_len);
178*25da2beaSAndroid Build Coastguard Worker 				goto err;
179*25da2beaSAndroid Build Coastguard Worker 			}
180*25da2beaSAndroid Build Coastguard Worker 		} else if (cqe->res != exp_len) {
181*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "cqe res %d, wanted %d\n", cqe->res, exp_len);
182*25da2beaSAndroid Build Coastguard Worker 			goto err;
183*25da2beaSAndroid Build Coastguard Worker 		}
184*25da2beaSAndroid Build Coastguard Worker 		if (buf_select && exp_len == BS) {
185*25da2beaSAndroid Build Coastguard Worker 			int bid = cqe->flags >> 16;
186*25da2beaSAndroid Build Coastguard Worker 			unsigned char *ptr = vecs[bid].iov_base;
187*25da2beaSAndroid Build Coastguard Worker 			int j;
188*25da2beaSAndroid Build Coastguard Worker 
189*25da2beaSAndroid Build Coastguard Worker 			for (j = 0; j < BS; j++) {
190*25da2beaSAndroid Build Coastguard Worker 				if (ptr[j] == cqe->user_data)
191*25da2beaSAndroid Build Coastguard Worker 					continue;
192*25da2beaSAndroid Build Coastguard Worker 
193*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "Data mismatch! bid=%d, "
194*25da2beaSAndroid Build Coastguard Worker 						"wanted=%d, got=%d\n", bid,
195*25da2beaSAndroid Build Coastguard Worker 						(int)cqe->user_data, ptr[j]);
196*25da2beaSAndroid Build Coastguard Worker 				return 1;
197*25da2beaSAndroid Build Coastguard Worker 			}
198*25da2beaSAndroid Build Coastguard Worker 		}
199*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(ring, cqe);
200*25da2beaSAndroid Build Coastguard Worker 	}
201*25da2beaSAndroid Build Coastguard Worker 
202*25da2beaSAndroid Build Coastguard Worker 	if (fixed) {
203*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_unregister_buffers(ring);
204*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
205*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "buffer unreg failed: %d\n", ret);
206*25da2beaSAndroid Build Coastguard Worker 			goto err;
207*25da2beaSAndroid Build Coastguard Worker 		}
208*25da2beaSAndroid Build Coastguard Worker 	}
209*25da2beaSAndroid Build Coastguard Worker 	if (sqthread) {
210*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_unregister_files(ring);
211*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
212*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "file unreg failed: %d\n", ret);
213*25da2beaSAndroid Build Coastguard Worker 			goto err;
214*25da2beaSAndroid Build Coastguard Worker 		}
215*25da2beaSAndroid Build Coastguard Worker 	}
216*25da2beaSAndroid Build Coastguard Worker 
217*25da2beaSAndroid Build Coastguard Worker 	close(fd);
218*25da2beaSAndroid Build Coastguard Worker #ifdef VERBOSE
219*25da2beaSAndroid Build Coastguard Worker 	fprintf(stdout, "PASS\n");
220*25da2beaSAndroid Build Coastguard Worker #endif
221*25da2beaSAndroid Build Coastguard Worker 	return 0;
222*25da2beaSAndroid Build Coastguard Worker err:
223*25da2beaSAndroid Build Coastguard Worker #ifdef VERBOSE
224*25da2beaSAndroid Build Coastguard Worker 	fprintf(stderr, "FAILED\n");
225*25da2beaSAndroid Build Coastguard Worker #endif
226*25da2beaSAndroid Build Coastguard Worker 	if (fd != -1)
227*25da2beaSAndroid Build Coastguard Worker 		close(fd);
228*25da2beaSAndroid Build Coastguard Worker 	return 1;
229*25da2beaSAndroid Build Coastguard Worker }
test_io(const char * file,int write,int buffered,int sqthread,int fixed,int nonvec,int exp_len)230*25da2beaSAndroid Build Coastguard Worker static int test_io(const char *file, int write, int buffered, int sqthread,
231*25da2beaSAndroid Build Coastguard Worker 		   int fixed, int nonvec, int exp_len)
232*25da2beaSAndroid Build Coastguard Worker {
233*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
234*25da2beaSAndroid Build Coastguard Worker 	int ret, ring_flags = 0;
235*25da2beaSAndroid Build Coastguard Worker 
236*25da2beaSAndroid Build Coastguard Worker 	if (sqthread)
237*25da2beaSAndroid Build Coastguard Worker 		ring_flags = IORING_SETUP_SQPOLL;
238*25da2beaSAndroid Build Coastguard Worker 
239*25da2beaSAndroid Build Coastguard Worker 	ret = t_create_ring(64, &ring, ring_flags);
240*25da2beaSAndroid Build Coastguard Worker 	if (ret == T_SETUP_SKIP)
241*25da2beaSAndroid Build Coastguard Worker 		return 0;
242*25da2beaSAndroid Build Coastguard Worker 	if (ret != T_SETUP_OK) {
243*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "ring create failed: %d\n", ret);
244*25da2beaSAndroid Build Coastguard Worker 		return 1;
245*25da2beaSAndroid Build Coastguard Worker 	}
246*25da2beaSAndroid Build Coastguard Worker 
247*25da2beaSAndroid Build Coastguard Worker 	ret = __test_io(file, &ring, write, buffered, sqthread, fixed, nonvec,
248*25da2beaSAndroid Build Coastguard Worker 			0, 0, exp_len);
249*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
250*25da2beaSAndroid Build Coastguard Worker 	return ret;
251*25da2beaSAndroid Build Coastguard Worker }
252*25da2beaSAndroid Build Coastguard Worker 
read_poll_link(const char * file)253*25da2beaSAndroid Build Coastguard Worker static int read_poll_link(const char *file)
254*25da2beaSAndroid Build Coastguard Worker {
255*25da2beaSAndroid Build Coastguard Worker 	struct __kernel_timespec ts;
256*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
257*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
258*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
259*25da2beaSAndroid Build Coastguard Worker 	int i, fd, ret, fds[2];
260*25da2beaSAndroid Build Coastguard Worker 
261*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(8, &ring, 0);
262*25da2beaSAndroid Build Coastguard Worker 	if (ret)
263*25da2beaSAndroid Build Coastguard Worker 		return ret;
264*25da2beaSAndroid Build Coastguard Worker 
265*25da2beaSAndroid Build Coastguard Worker 	fd = open(file, O_WRONLY);
266*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
267*25da2beaSAndroid Build Coastguard Worker 		perror("open");
268*25da2beaSAndroid Build Coastguard Worker 		return 1;
269*25da2beaSAndroid Build Coastguard Worker 	}
270*25da2beaSAndroid Build Coastguard Worker 
271*25da2beaSAndroid Build Coastguard Worker 	if (pipe(fds)) {
272*25da2beaSAndroid Build Coastguard Worker 		perror("pipe");
273*25da2beaSAndroid Build Coastguard Worker 		return 1;
274*25da2beaSAndroid Build Coastguard Worker 	}
275*25da2beaSAndroid Build Coastguard Worker 
276*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(&ring);
277*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_writev(sqe, fd, &vecs[0], 1, 0);
278*25da2beaSAndroid Build Coastguard Worker 	sqe->flags |= IOSQE_IO_LINK;
279*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 1;
280*25da2beaSAndroid Build Coastguard Worker 
281*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(&ring);
282*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_poll_add(sqe, fds[0], POLLIN);
283*25da2beaSAndroid Build Coastguard Worker 	sqe->flags |= IOSQE_IO_LINK;
284*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 2;
285*25da2beaSAndroid Build Coastguard Worker 
286*25da2beaSAndroid Build Coastguard Worker 	ts.tv_sec = 1;
287*25da2beaSAndroid Build Coastguard Worker 	ts.tv_nsec = 0;
288*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(&ring);
289*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_link_timeout(sqe, &ts, 0);
290*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 3;
291*25da2beaSAndroid Build Coastguard Worker 
292*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(&ring);
293*25da2beaSAndroid Build Coastguard Worker 	if (ret != 3) {
294*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submitted %d\n", ret);
295*25da2beaSAndroid Build Coastguard Worker 		return 1;
296*25da2beaSAndroid Build Coastguard Worker 	}
297*25da2beaSAndroid Build Coastguard Worker 
298*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < 3; i++) {
299*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(&ring, &cqe);
300*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
301*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait_cqe=%d\n", ret);
302*25da2beaSAndroid Build Coastguard Worker 			return 1;
303*25da2beaSAndroid Build Coastguard Worker 		}
304*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(&ring, cqe);
305*25da2beaSAndroid Build Coastguard Worker 	}
306*25da2beaSAndroid Build Coastguard Worker 
307*25da2beaSAndroid Build Coastguard Worker 	return 0;
308*25da2beaSAndroid Build Coastguard Worker }
309*25da2beaSAndroid Build Coastguard Worker 
has_nonvec_read(void)310*25da2beaSAndroid Build Coastguard Worker static int has_nonvec_read(void)
311*25da2beaSAndroid Build Coastguard Worker {
312*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_probe *p;
313*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
314*25da2beaSAndroid Build Coastguard Worker 	int ret;
315*25da2beaSAndroid Build Coastguard Worker 
316*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(1, &ring, 0);
317*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
318*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "queue init failed: %d\n", ret);
319*25da2beaSAndroid Build Coastguard Worker 		exit(ret);
320*25da2beaSAndroid Build Coastguard Worker 	}
321*25da2beaSAndroid Build Coastguard Worker 
322*25da2beaSAndroid Build Coastguard Worker 	p = t_calloc(1, sizeof(*p) + 256 * sizeof(struct io_uring_probe_op));
323*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_register_probe(&ring, p, 256);
324*25da2beaSAndroid Build Coastguard Worker 	/* if we don't have PROBE_REGISTER, we don't have OP_READ/WRITE */
325*25da2beaSAndroid Build Coastguard Worker 	if (ret == -EINVAL) {
326*25da2beaSAndroid Build Coastguard Worker out:
327*25da2beaSAndroid Build Coastguard Worker 		io_uring_queue_exit(&ring);
328*25da2beaSAndroid Build Coastguard Worker 		return 0;
329*25da2beaSAndroid Build Coastguard Worker 	} else if (ret) {
330*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "register_probe: %d\n", ret);
331*25da2beaSAndroid Build Coastguard Worker 		goto out;
332*25da2beaSAndroid Build Coastguard Worker 	}
333*25da2beaSAndroid Build Coastguard Worker 
334*25da2beaSAndroid Build Coastguard Worker 	if (p->ops_len <= IORING_OP_READ)
335*25da2beaSAndroid Build Coastguard Worker 		goto out;
336*25da2beaSAndroid Build Coastguard Worker 	if (!(p->ops[IORING_OP_READ].flags & IO_URING_OP_SUPPORTED))
337*25da2beaSAndroid Build Coastguard Worker 		goto out;
338*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
339*25da2beaSAndroid Build Coastguard Worker 	return 1;
340*25da2beaSAndroid Build Coastguard Worker }
341*25da2beaSAndroid Build Coastguard Worker 
test_eventfd_read(void)342*25da2beaSAndroid Build Coastguard Worker static int test_eventfd_read(void)
343*25da2beaSAndroid Build Coastguard Worker {
344*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
345*25da2beaSAndroid Build Coastguard Worker 	int fd, ret;
346*25da2beaSAndroid Build Coastguard Worker 	eventfd_t event;
347*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
348*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
349*25da2beaSAndroid Build Coastguard Worker 
350*25da2beaSAndroid Build Coastguard Worker 	if (no_read)
351*25da2beaSAndroid Build Coastguard Worker 		return 0;
352*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(8, &ring, 0);
353*25da2beaSAndroid Build Coastguard Worker 	if (ret)
354*25da2beaSAndroid Build Coastguard Worker 		return ret;
355*25da2beaSAndroid Build Coastguard Worker 
356*25da2beaSAndroid Build Coastguard Worker 	fd = eventfd(1, 0);
357*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
358*25da2beaSAndroid Build Coastguard Worker 		perror("eventfd");
359*25da2beaSAndroid Build Coastguard Worker 		return 1;
360*25da2beaSAndroid Build Coastguard Worker 	}
361*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(&ring);
362*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_read(sqe, fd, &event, sizeof(eventfd_t), 0);
363*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(&ring);
364*25da2beaSAndroid Build Coastguard Worker 	if (ret != 1) {
365*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submitted %d\n", ret);
366*25da2beaSAndroid Build Coastguard Worker 		return 1;
367*25da2beaSAndroid Build Coastguard Worker 	}
368*25da2beaSAndroid Build Coastguard Worker 	eventfd_write(fd, 1);
369*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_wait_cqe(&ring, &cqe);
370*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
371*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "wait_cqe=%d\n", ret);
372*25da2beaSAndroid Build Coastguard Worker 		return 1;
373*25da2beaSAndroid Build Coastguard Worker 	}
374*25da2beaSAndroid Build Coastguard Worker 	if (cqe->res == -EINVAL) {
375*25da2beaSAndroid Build Coastguard Worker 		fprintf(stdout, "eventfd IO not supported, skipping\n");
376*25da2beaSAndroid Build Coastguard Worker 	} else if (cqe->res != sizeof(eventfd_t)) {
377*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "cqe res %d, wanted %d\n", cqe->res,
378*25da2beaSAndroid Build Coastguard Worker 						(int) sizeof(eventfd_t));
379*25da2beaSAndroid Build Coastguard Worker 		return 1;
380*25da2beaSAndroid Build Coastguard Worker 	}
381*25da2beaSAndroid Build Coastguard Worker 	io_uring_cqe_seen(&ring, cqe);
382*25da2beaSAndroid Build Coastguard Worker 	return 0;
383*25da2beaSAndroid Build Coastguard Worker }
384*25da2beaSAndroid Build Coastguard Worker 
test_buf_select_short(const char * filename,int nonvec)385*25da2beaSAndroid Build Coastguard Worker static int test_buf_select_short(const char *filename, int nonvec)
386*25da2beaSAndroid Build Coastguard Worker {
387*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
388*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
389*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
390*25da2beaSAndroid Build Coastguard Worker 	int ret, i, exp_len;
391*25da2beaSAndroid Build Coastguard Worker 
392*25da2beaSAndroid Build Coastguard Worker 	if (no_buf_select)
393*25da2beaSAndroid Build Coastguard Worker 		return 0;
394*25da2beaSAndroid Build Coastguard Worker 
395*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(64, &ring, 0);
396*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
397*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "ring create failed: %d\n", ret);
398*25da2beaSAndroid Build Coastguard Worker 		return 1;
399*25da2beaSAndroid Build Coastguard Worker 	}
400*25da2beaSAndroid Build Coastguard Worker 
401*25da2beaSAndroid Build Coastguard Worker 	exp_len = 0;
402*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUFFERS; i++) {
403*25da2beaSAndroid Build Coastguard Worker 		sqe = io_uring_get_sqe(&ring);
404*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_provide_buffers(sqe, vecs[i].iov_base,
405*25da2beaSAndroid Build Coastguard Worker 						vecs[i].iov_len / 2, 1, 1, i);
406*25da2beaSAndroid Build Coastguard Worker 		if (!exp_len)
407*25da2beaSAndroid Build Coastguard Worker 			exp_len = vecs[i].iov_len / 2;
408*25da2beaSAndroid Build Coastguard Worker 	}
409*25da2beaSAndroid Build Coastguard Worker 
410*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(&ring);
411*25da2beaSAndroid Build Coastguard Worker 	if (ret != BUFFERS) {
412*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit: %d\n", ret);
413*25da2beaSAndroid Build Coastguard Worker 		return -1;
414*25da2beaSAndroid Build Coastguard Worker 	}
415*25da2beaSAndroid Build Coastguard Worker 
416*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUFFERS; i++) {
417*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(&ring, &cqe);
418*25da2beaSAndroid Build Coastguard Worker 		if (cqe->res < 0) {
419*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "cqe->res=%d\n", cqe->res);
420*25da2beaSAndroid Build Coastguard Worker 			return 1;
421*25da2beaSAndroid Build Coastguard Worker 		}
422*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(&ring, cqe);
423*25da2beaSAndroid Build Coastguard Worker 	}
424*25da2beaSAndroid Build Coastguard Worker 
425*25da2beaSAndroid Build Coastguard Worker 	ret = __test_io(filename, &ring, 0, 0, 0, 0, nonvec, 1, 1, exp_len);
426*25da2beaSAndroid Build Coastguard Worker 
427*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
428*25da2beaSAndroid Build Coastguard Worker 	return ret;
429*25da2beaSAndroid Build Coastguard Worker }
430*25da2beaSAndroid Build Coastguard Worker 
provide_buffers_iovec(struct io_uring * ring,int bgid)431*25da2beaSAndroid Build Coastguard Worker static int provide_buffers_iovec(struct io_uring *ring, int bgid)
432*25da2beaSAndroid Build Coastguard Worker {
433*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
434*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
435*25da2beaSAndroid Build Coastguard Worker 	int i, ret;
436*25da2beaSAndroid Build Coastguard Worker 
437*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUFFERS; i++) {
438*25da2beaSAndroid Build Coastguard Worker 		sqe = io_uring_get_sqe(ring);
439*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_provide_buffers(sqe, vecs[i].iov_base,
440*25da2beaSAndroid Build Coastguard Worker 						vecs[i].iov_len, 1, bgid, i);
441*25da2beaSAndroid Build Coastguard Worker 	}
442*25da2beaSAndroid Build Coastguard Worker 
443*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(ring);
444*25da2beaSAndroid Build Coastguard Worker 	if (ret != BUFFERS) {
445*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit: %d\n", ret);
446*25da2beaSAndroid Build Coastguard Worker 		return -1;
447*25da2beaSAndroid Build Coastguard Worker 	}
448*25da2beaSAndroid Build Coastguard Worker 
449*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUFFERS; i++) {
450*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(ring, &cqe);
451*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
452*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait_cqe=%d\n", ret);
453*25da2beaSAndroid Build Coastguard Worker 			return 1;
454*25da2beaSAndroid Build Coastguard Worker 		}
455*25da2beaSAndroid Build Coastguard Worker 		if (cqe->res < 0) {
456*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "cqe->res=%d\n", cqe->res);
457*25da2beaSAndroid Build Coastguard Worker 			return 1;
458*25da2beaSAndroid Build Coastguard Worker 		}
459*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(ring, cqe);
460*25da2beaSAndroid Build Coastguard Worker 	}
461*25da2beaSAndroid Build Coastguard Worker 
462*25da2beaSAndroid Build Coastguard Worker 	return 0;
463*25da2beaSAndroid Build Coastguard Worker }
464*25da2beaSAndroid Build Coastguard Worker 
test_buf_select(const char * filename,int nonvec)465*25da2beaSAndroid Build Coastguard Worker static int test_buf_select(const char *filename, int nonvec)
466*25da2beaSAndroid Build Coastguard Worker {
467*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_probe *p;
468*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
469*25da2beaSAndroid Build Coastguard Worker 	int ret, i;
470*25da2beaSAndroid Build Coastguard Worker 
471*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(64, &ring, 0);
472*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
473*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "ring create failed: %d\n", ret);
474*25da2beaSAndroid Build Coastguard Worker 		return 1;
475*25da2beaSAndroid Build Coastguard Worker 	}
476*25da2beaSAndroid Build Coastguard Worker 
477*25da2beaSAndroid Build Coastguard Worker 	p = io_uring_get_probe_ring(&ring);
478*25da2beaSAndroid Build Coastguard Worker 	if (!p || !io_uring_opcode_supported(p, IORING_OP_PROVIDE_BUFFERS)) {
479*25da2beaSAndroid Build Coastguard Worker 		no_buf_select = 1;
480*25da2beaSAndroid Build Coastguard Worker 		fprintf(stdout, "Buffer select not supported, skipping\n");
481*25da2beaSAndroid Build Coastguard Worker 		return 0;
482*25da2beaSAndroid Build Coastguard Worker 	}
483*25da2beaSAndroid Build Coastguard Worker 	io_uring_free_probe(p);
484*25da2beaSAndroid Build Coastguard Worker 
485*25da2beaSAndroid Build Coastguard Worker 	/*
486*25da2beaSAndroid Build Coastguard Worker 	 * Write out data with known pattern
487*25da2beaSAndroid Build Coastguard Worker 	 */
488*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUFFERS; i++)
489*25da2beaSAndroid Build Coastguard Worker 		memset(vecs[i].iov_base, i, vecs[i].iov_len);
490*25da2beaSAndroid Build Coastguard Worker 
491*25da2beaSAndroid Build Coastguard Worker 	ret = __test_io(filename, &ring, 1, 0, 0, 0, 0, 0, 1, BS);
492*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
493*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "failed writing data\n");
494*25da2beaSAndroid Build Coastguard Worker 		return 1;
495*25da2beaSAndroid Build Coastguard Worker 	}
496*25da2beaSAndroid Build Coastguard Worker 
497*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUFFERS; i++)
498*25da2beaSAndroid Build Coastguard Worker 		memset(vecs[i].iov_base, 0x55, vecs[i].iov_len);
499*25da2beaSAndroid Build Coastguard Worker 
500*25da2beaSAndroid Build Coastguard Worker 	ret = provide_buffers_iovec(&ring, 1);
501*25da2beaSAndroid Build Coastguard Worker 	if (ret)
502*25da2beaSAndroid Build Coastguard Worker 		return ret;
503*25da2beaSAndroid Build Coastguard Worker 
504*25da2beaSAndroid Build Coastguard Worker 	ret = __test_io(filename, &ring, 0, 0, 0, 0, nonvec, 1, 1, BS);
505*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
506*25da2beaSAndroid Build Coastguard Worker 	return ret;
507*25da2beaSAndroid Build Coastguard Worker }
508*25da2beaSAndroid Build Coastguard Worker 
test_rem_buf(int batch,int sqe_flags)509*25da2beaSAndroid Build Coastguard Worker static int test_rem_buf(int batch, int sqe_flags)
510*25da2beaSAndroid Build Coastguard Worker {
511*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
512*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
513*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
514*25da2beaSAndroid Build Coastguard Worker 	int left, ret, nr = 0;
515*25da2beaSAndroid Build Coastguard Worker 	int bgid = 1;
516*25da2beaSAndroid Build Coastguard Worker 
517*25da2beaSAndroid Build Coastguard Worker 	if (no_buf_select)
518*25da2beaSAndroid Build Coastguard Worker 		return 0;
519*25da2beaSAndroid Build Coastguard Worker 
520*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(64, &ring, 0);
521*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
522*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "ring create failed: %d\n", ret);
523*25da2beaSAndroid Build Coastguard Worker 		return 1;
524*25da2beaSAndroid Build Coastguard Worker 	}
525*25da2beaSAndroid Build Coastguard Worker 
526*25da2beaSAndroid Build Coastguard Worker 	ret = provide_buffers_iovec(&ring, bgid);
527*25da2beaSAndroid Build Coastguard Worker 	if (ret)
528*25da2beaSAndroid Build Coastguard Worker 		return ret;
529*25da2beaSAndroid Build Coastguard Worker 
530*25da2beaSAndroid Build Coastguard Worker 	left = BUFFERS;
531*25da2beaSAndroid Build Coastguard Worker 	while (left) {
532*25da2beaSAndroid Build Coastguard Worker 		int to_rem = (left < batch) ? left : batch;
533*25da2beaSAndroid Build Coastguard Worker 
534*25da2beaSAndroid Build Coastguard Worker 		left -= to_rem;
535*25da2beaSAndroid Build Coastguard Worker 		sqe = io_uring_get_sqe(&ring);
536*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_remove_buffers(sqe, to_rem, bgid);
537*25da2beaSAndroid Build Coastguard Worker 		sqe->user_data = to_rem;
538*25da2beaSAndroid Build Coastguard Worker 		sqe->flags |= sqe_flags;
539*25da2beaSAndroid Build Coastguard Worker 		++nr;
540*25da2beaSAndroid Build Coastguard Worker 	}
541*25da2beaSAndroid Build Coastguard Worker 
542*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(&ring);
543*25da2beaSAndroid Build Coastguard Worker 	if (ret != nr) {
544*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit: %d\n", ret);
545*25da2beaSAndroid Build Coastguard Worker 		return -1;
546*25da2beaSAndroid Build Coastguard Worker 	}
547*25da2beaSAndroid Build Coastguard Worker 
548*25da2beaSAndroid Build Coastguard Worker 	for (; nr > 0; nr--) {
549*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(&ring, &cqe);
550*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
551*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait_cqe=%d\n", ret);
552*25da2beaSAndroid Build Coastguard Worker 			return 1;
553*25da2beaSAndroid Build Coastguard Worker 		}
554*25da2beaSAndroid Build Coastguard Worker 		if (cqe->res != cqe->user_data) {
555*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "cqe->res=%d\n", cqe->res);
556*25da2beaSAndroid Build Coastguard Worker 			return 1;
557*25da2beaSAndroid Build Coastguard Worker 		}
558*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(&ring, cqe);
559*25da2beaSAndroid Build Coastguard Worker 	}
560*25da2beaSAndroid Build Coastguard Worker 
561*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
562*25da2beaSAndroid Build Coastguard Worker 	return ret;
563*25da2beaSAndroid Build Coastguard Worker }
564*25da2beaSAndroid Build Coastguard Worker 
test_io_link(const char * file)565*25da2beaSAndroid Build Coastguard Worker static int test_io_link(const char *file)
566*25da2beaSAndroid Build Coastguard Worker {
567*25da2beaSAndroid Build Coastguard Worker 	const int nr_links = 100;
568*25da2beaSAndroid Build Coastguard Worker 	const int link_len = 100;
569*25da2beaSAndroid Build Coastguard Worker 	const int nr_sqes = nr_links * link_len;
570*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
571*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
572*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
573*25da2beaSAndroid Build Coastguard Worker 	int i, j, fd, ret;
574*25da2beaSAndroid Build Coastguard Worker 
575*25da2beaSAndroid Build Coastguard Worker 	fd = open(file, O_WRONLY);
576*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
577*25da2beaSAndroid Build Coastguard Worker 		perror("file open");
578*25da2beaSAndroid Build Coastguard Worker 		goto err;
579*25da2beaSAndroid Build Coastguard Worker 	}
580*25da2beaSAndroid Build Coastguard Worker 
581*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(nr_sqes, &ring, 0);
582*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
583*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "ring create failed: %d\n", ret);
584*25da2beaSAndroid Build Coastguard Worker 		goto err;
585*25da2beaSAndroid Build Coastguard Worker 	}
586*25da2beaSAndroid Build Coastguard Worker 
587*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < nr_links; ++i) {
588*25da2beaSAndroid Build Coastguard Worker 		for (j = 0; j < link_len; ++j) {
589*25da2beaSAndroid Build Coastguard Worker 			sqe = io_uring_get_sqe(&ring);
590*25da2beaSAndroid Build Coastguard Worker 			if (!sqe) {
591*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "sqe get failed\n");
592*25da2beaSAndroid Build Coastguard Worker 				goto err;
593*25da2beaSAndroid Build Coastguard Worker 			}
594*25da2beaSAndroid Build Coastguard Worker 			io_uring_prep_writev(sqe, fd, &vecs[0], 1, 0);
595*25da2beaSAndroid Build Coastguard Worker 			sqe->flags |= IOSQE_ASYNC;
596*25da2beaSAndroid Build Coastguard Worker 			if (j != link_len - 1)
597*25da2beaSAndroid Build Coastguard Worker 				sqe->flags |= IOSQE_IO_LINK;
598*25da2beaSAndroid Build Coastguard Worker 		}
599*25da2beaSAndroid Build Coastguard Worker 	}
600*25da2beaSAndroid Build Coastguard Worker 
601*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(&ring);
602*25da2beaSAndroid Build Coastguard Worker 	if (ret != nr_sqes) {
603*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_peek_cqe(&ring, &cqe);
604*25da2beaSAndroid Build Coastguard Worker 		if (!ret && cqe->res == -EINVAL) {
605*25da2beaSAndroid Build Coastguard Worker 			fprintf(stdout, "IOSQE_ASYNC not supported, skipped\n");
606*25da2beaSAndroid Build Coastguard Worker 			goto out;
607*25da2beaSAndroid Build Coastguard Worker 		}
608*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit got %d, wanted %d\n", ret, nr_sqes);
609*25da2beaSAndroid Build Coastguard Worker 		goto err;
610*25da2beaSAndroid Build Coastguard Worker 	}
611*25da2beaSAndroid Build Coastguard Worker 
612*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < nr_sqes; i++) {
613*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(&ring, &cqe);
614*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
615*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait_cqe=%d\n", ret);
616*25da2beaSAndroid Build Coastguard Worker 			goto err;
617*25da2beaSAndroid Build Coastguard Worker 		}
618*25da2beaSAndroid Build Coastguard Worker 		if (cqe->res == -EINVAL) {
619*25da2beaSAndroid Build Coastguard Worker 			if (!warned) {
620*25da2beaSAndroid Build Coastguard Worker 				fprintf(stdout, "Non-vectored IO not "
621*25da2beaSAndroid Build Coastguard Worker 					"supported, skipping\n");
622*25da2beaSAndroid Build Coastguard Worker 				warned = 1;
623*25da2beaSAndroid Build Coastguard Worker 				no_read = 1;
624*25da2beaSAndroid Build Coastguard Worker 			}
625*25da2beaSAndroid Build Coastguard Worker 		} else if (cqe->res != BS) {
626*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "cqe res %d, wanted %d\n", cqe->res, BS);
627*25da2beaSAndroid Build Coastguard Worker 			goto err;
628*25da2beaSAndroid Build Coastguard Worker 		}
629*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(&ring, cqe);
630*25da2beaSAndroid Build Coastguard Worker 	}
631*25da2beaSAndroid Build Coastguard Worker 
632*25da2beaSAndroid Build Coastguard Worker out:
633*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
634*25da2beaSAndroid Build Coastguard Worker 	close(fd);
635*25da2beaSAndroid Build Coastguard Worker 	return 0;
636*25da2beaSAndroid Build Coastguard Worker err:
637*25da2beaSAndroid Build Coastguard Worker 	if (fd != -1)
638*25da2beaSAndroid Build Coastguard Worker 		close(fd);
639*25da2beaSAndroid Build Coastguard Worker 	return 1;
640*25da2beaSAndroid Build Coastguard Worker }
641*25da2beaSAndroid Build Coastguard Worker 
test_write_efbig(void)642*25da2beaSAndroid Build Coastguard Worker static int test_write_efbig(void)
643*25da2beaSAndroid Build Coastguard Worker {
644*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
645*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
646*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
647*25da2beaSAndroid Build Coastguard Worker 	struct rlimit rlim, old_rlim;
648*25da2beaSAndroid Build Coastguard Worker 	int i, fd, ret;
649*25da2beaSAndroid Build Coastguard Worker 	loff_t off;
650*25da2beaSAndroid Build Coastguard Worker 
651*25da2beaSAndroid Build Coastguard Worker 	if (geteuid()) {
652*25da2beaSAndroid Build Coastguard Worker 		fprintf(stdout, "Not root, skipping %s\n", __FUNCTION__);
653*25da2beaSAndroid Build Coastguard Worker 		return 0;
654*25da2beaSAndroid Build Coastguard Worker 	}
655*25da2beaSAndroid Build Coastguard Worker 
656*25da2beaSAndroid Build Coastguard Worker 	if (getrlimit(RLIMIT_FSIZE, &old_rlim) < 0) {
657*25da2beaSAndroid Build Coastguard Worker 		perror("getrlimit");
658*25da2beaSAndroid Build Coastguard Worker 		return 1;
659*25da2beaSAndroid Build Coastguard Worker 	}
660*25da2beaSAndroid Build Coastguard Worker 	rlim = old_rlim;
661*25da2beaSAndroid Build Coastguard Worker 	rlim.rlim_cur = 128 * 1024;
662*25da2beaSAndroid Build Coastguard Worker 	rlim.rlim_max = 128 * 1024;
663*25da2beaSAndroid Build Coastguard Worker 	if (setrlimit(RLIMIT_FSIZE, &rlim) < 0) {
664*25da2beaSAndroid Build Coastguard Worker 		perror("setrlimit");
665*25da2beaSAndroid Build Coastguard Worker 		return 1;
666*25da2beaSAndroid Build Coastguard Worker 	}
667*25da2beaSAndroid Build Coastguard Worker 
668*25da2beaSAndroid Build Coastguard Worker 	fd = open(".efbig", O_WRONLY | O_CREAT, 0644);
669*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
670*25da2beaSAndroid Build Coastguard Worker 		perror("file open");
671*25da2beaSAndroid Build Coastguard Worker 		goto err;
672*25da2beaSAndroid Build Coastguard Worker 	}
673*25da2beaSAndroid Build Coastguard Worker 	unlink(".efbig");
674*25da2beaSAndroid Build Coastguard Worker 
675*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(32, &ring, 0);
676*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
677*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "ring create failed: %d\n", ret);
678*25da2beaSAndroid Build Coastguard Worker 		goto err;
679*25da2beaSAndroid Build Coastguard Worker 	}
680*25da2beaSAndroid Build Coastguard Worker 
681*25da2beaSAndroid Build Coastguard Worker 	off = 0;
682*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < 32; i++) {
683*25da2beaSAndroid Build Coastguard Worker 		sqe = io_uring_get_sqe(&ring);
684*25da2beaSAndroid Build Coastguard Worker 		if (!sqe) {
685*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "sqe get failed\n");
686*25da2beaSAndroid Build Coastguard Worker 			goto err;
687*25da2beaSAndroid Build Coastguard Worker 		}
688*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_writev(sqe, fd, &vecs[i], 1, off);
689*25da2beaSAndroid Build Coastguard Worker 		off += BS;
690*25da2beaSAndroid Build Coastguard Worker 	}
691*25da2beaSAndroid Build Coastguard Worker 
692*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(&ring);
693*25da2beaSAndroid Build Coastguard Worker 	if (ret != 32) {
694*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit got %d, wanted %d\n", ret, 32);
695*25da2beaSAndroid Build Coastguard Worker 		goto err;
696*25da2beaSAndroid Build Coastguard Worker 	}
697*25da2beaSAndroid Build Coastguard Worker 
698*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < 32; i++) {
699*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(&ring, &cqe);
700*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
701*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait_cqe=%d\n", ret);
702*25da2beaSAndroid Build Coastguard Worker 			goto err;
703*25da2beaSAndroid Build Coastguard Worker 		}
704*25da2beaSAndroid Build Coastguard Worker 		if (i < 16) {
705*25da2beaSAndroid Build Coastguard Worker 			if (cqe->res != BS) {
706*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "bad write: %d\n", cqe->res);
707*25da2beaSAndroid Build Coastguard Worker 				goto err;
708*25da2beaSAndroid Build Coastguard Worker 			}
709*25da2beaSAndroid Build Coastguard Worker 		} else {
710*25da2beaSAndroid Build Coastguard Worker 			if (cqe->res != -EFBIG) {
711*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "Expected -EFBIG: %d\n", cqe->res);
712*25da2beaSAndroid Build Coastguard Worker 				goto err;
713*25da2beaSAndroid Build Coastguard Worker 			}
714*25da2beaSAndroid Build Coastguard Worker 		}
715*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(&ring, cqe);
716*25da2beaSAndroid Build Coastguard Worker 	}
717*25da2beaSAndroid Build Coastguard Worker 
718*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
719*25da2beaSAndroid Build Coastguard Worker 	close(fd);
720*25da2beaSAndroid Build Coastguard Worker 	unlink(".efbig");
721*25da2beaSAndroid Build Coastguard Worker 
722*25da2beaSAndroid Build Coastguard Worker 	if (setrlimit(RLIMIT_FSIZE, &old_rlim) < 0) {
723*25da2beaSAndroid Build Coastguard Worker 		perror("setrlimit");
724*25da2beaSAndroid Build Coastguard Worker 		return 1;
725*25da2beaSAndroid Build Coastguard Worker 	}
726*25da2beaSAndroid Build Coastguard Worker 	return 0;
727*25da2beaSAndroid Build Coastguard Worker err:
728*25da2beaSAndroid Build Coastguard Worker 	if (fd != -1)
729*25da2beaSAndroid Build Coastguard Worker 		close(fd);
730*25da2beaSAndroid Build Coastguard Worker 	return 1;
731*25da2beaSAndroid Build Coastguard Worker }
732*25da2beaSAndroid Build Coastguard Worker 
main(int argc,char * argv[])733*25da2beaSAndroid Build Coastguard Worker int main(int argc, char *argv[])
734*25da2beaSAndroid Build Coastguard Worker {
735*25da2beaSAndroid Build Coastguard Worker 	int i, ret, nr;
736*25da2beaSAndroid Build Coastguard Worker 	char buf[256];
737*25da2beaSAndroid Build Coastguard Worker 	char *fname;
738*25da2beaSAndroid Build Coastguard Worker 
739*25da2beaSAndroid Build Coastguard Worker 	if (argc > 1) {
740*25da2beaSAndroid Build Coastguard Worker 		fname = argv[1];
741*25da2beaSAndroid Build Coastguard Worker 	} else {
742*25da2beaSAndroid Build Coastguard Worker 		srand((unsigned)time(NULL));
743*25da2beaSAndroid Build Coastguard Worker 		snprintf(buf, sizeof(buf), ".basic-rw-%u-%u",
744*25da2beaSAndroid Build Coastguard Worker 			(unsigned)rand(), (unsigned)getpid());
745*25da2beaSAndroid Build Coastguard Worker 		fname = buf;
746*25da2beaSAndroid Build Coastguard Worker 		t_create_file(fname, FILE_SIZE);
747*25da2beaSAndroid Build Coastguard Worker 	}
748*25da2beaSAndroid Build Coastguard Worker 
749*25da2beaSAndroid Build Coastguard Worker 	vecs = t_create_buffers(BUFFERS, BS);
750*25da2beaSAndroid Build Coastguard Worker 
751*25da2beaSAndroid Build Coastguard Worker 	/* if we don't have nonvec read, skip testing that */
752*25da2beaSAndroid Build Coastguard Worker 	nr = has_nonvec_read() ? 32 : 16;
753*25da2beaSAndroid Build Coastguard Worker 
754*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < nr; i++) {
755*25da2beaSAndroid Build Coastguard Worker 		int write = (i & 1) != 0;
756*25da2beaSAndroid Build Coastguard Worker 		int buffered = (i & 2) != 0;
757*25da2beaSAndroid Build Coastguard Worker 		int sqthread = (i & 4) != 0;
758*25da2beaSAndroid Build Coastguard Worker 		int fixed = (i & 8) != 0;
759*25da2beaSAndroid Build Coastguard Worker 		int nonvec = (i & 16) != 0;
760*25da2beaSAndroid Build Coastguard Worker 
761*25da2beaSAndroid Build Coastguard Worker 		ret = test_io(fname, write, buffered, sqthread, fixed, nonvec,
762*25da2beaSAndroid Build Coastguard Worker 			      BS);
763*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
764*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "test_io failed %d/%d/%d/%d/%d\n",
765*25da2beaSAndroid Build Coastguard Worker 				write, buffered, sqthread, fixed, nonvec);
766*25da2beaSAndroid Build Coastguard Worker 			goto err;
767*25da2beaSAndroid Build Coastguard Worker 		}
768*25da2beaSAndroid Build Coastguard Worker 	}
769*25da2beaSAndroid Build Coastguard Worker 
770*25da2beaSAndroid Build Coastguard Worker 	ret = test_buf_select(fname, 1);
771*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
772*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_buf_select nonvec failed\n");
773*25da2beaSAndroid Build Coastguard Worker 		goto err;
774*25da2beaSAndroid Build Coastguard Worker 	}
775*25da2beaSAndroid Build Coastguard Worker 
776*25da2beaSAndroid Build Coastguard Worker 	ret = test_buf_select(fname, 0);
777*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
778*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_buf_select vec failed\n");
779*25da2beaSAndroid Build Coastguard Worker 		goto err;
780*25da2beaSAndroid Build Coastguard Worker 	}
781*25da2beaSAndroid Build Coastguard Worker 
782*25da2beaSAndroid Build Coastguard Worker 	ret = test_buf_select_short(fname, 1);
783*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
784*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_buf_select_short nonvec failed\n");
785*25da2beaSAndroid Build Coastguard Worker 		goto err;
786*25da2beaSAndroid Build Coastguard Worker 	}
787*25da2beaSAndroid Build Coastguard Worker 
788*25da2beaSAndroid Build Coastguard Worker 	ret = test_buf_select_short(fname, 0);
789*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
790*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_buf_select_short vec failed\n");
791*25da2beaSAndroid Build Coastguard Worker 		goto err;
792*25da2beaSAndroid Build Coastguard Worker 	}
793*25da2beaSAndroid Build Coastguard Worker 
794*25da2beaSAndroid Build Coastguard Worker 	ret = test_eventfd_read();
795*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
796*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_eventfd_read failed\n");
797*25da2beaSAndroid Build Coastguard Worker 		goto err;
798*25da2beaSAndroid Build Coastguard Worker 	}
799*25da2beaSAndroid Build Coastguard Worker 
800*25da2beaSAndroid Build Coastguard Worker 	ret = read_poll_link(fname);
801*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
802*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "read_poll_link failed\n");
803*25da2beaSAndroid Build Coastguard Worker 		goto err;
804*25da2beaSAndroid Build Coastguard Worker 	}
805*25da2beaSAndroid Build Coastguard Worker 
806*25da2beaSAndroid Build Coastguard Worker 	ret = test_io_link(fname);
807*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
808*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_io_link failed\n");
809*25da2beaSAndroid Build Coastguard Worker 		goto err;
810*25da2beaSAndroid Build Coastguard Worker 	}
811*25da2beaSAndroid Build Coastguard Worker 
812*25da2beaSAndroid Build Coastguard Worker 	ret = test_write_efbig();
813*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
814*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_write_efbig failed\n");
815*25da2beaSAndroid Build Coastguard Worker 		goto err;
816*25da2beaSAndroid Build Coastguard Worker 	}
817*25da2beaSAndroid Build Coastguard Worker 
818*25da2beaSAndroid Build Coastguard Worker 	ret = test_rem_buf(1, 0);
819*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
820*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_rem_buf by 1 failed\n");
821*25da2beaSAndroid Build Coastguard Worker 		goto err;
822*25da2beaSAndroid Build Coastguard Worker 	}
823*25da2beaSAndroid Build Coastguard Worker 
824*25da2beaSAndroid Build Coastguard Worker 	ret = test_rem_buf(10, 0);
825*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
826*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_rem_buf by 10 failed\n");
827*25da2beaSAndroid Build Coastguard Worker 		goto err;
828*25da2beaSAndroid Build Coastguard Worker 	}
829*25da2beaSAndroid Build Coastguard Worker 
830*25da2beaSAndroid Build Coastguard Worker 	ret = test_rem_buf(2, IOSQE_IO_LINK);
831*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
832*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_rem_buf link failed\n");
833*25da2beaSAndroid Build Coastguard Worker 		goto err;
834*25da2beaSAndroid Build Coastguard Worker 	}
835*25da2beaSAndroid Build Coastguard Worker 
836*25da2beaSAndroid Build Coastguard Worker 	ret = test_rem_buf(2, IOSQE_ASYNC);
837*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
838*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_rem_buf async failed\n");
839*25da2beaSAndroid Build Coastguard Worker 		goto err;
840*25da2beaSAndroid Build Coastguard Worker 	}
841*25da2beaSAndroid Build Coastguard Worker 
842*25da2beaSAndroid Build Coastguard Worker 	srand((unsigned)time(NULL));
843*25da2beaSAndroid Build Coastguard Worker 	if (create_nonaligned_buffers()) {
844*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "file creation failed\n");
845*25da2beaSAndroid Build Coastguard Worker 		goto err;
846*25da2beaSAndroid Build Coastguard Worker 	}
847*25da2beaSAndroid Build Coastguard Worker 
848*25da2beaSAndroid Build Coastguard Worker 	/* test fixed bufs with non-aligned len/offset */
849*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < nr; i++) {
850*25da2beaSAndroid Build Coastguard Worker 		int write = (i & 1) != 0;
851*25da2beaSAndroid Build Coastguard Worker 		int buffered = (i & 2) != 0;
852*25da2beaSAndroid Build Coastguard Worker 		int sqthread = (i & 4) != 0;
853*25da2beaSAndroid Build Coastguard Worker 		int fixed = (i & 8) != 0;
854*25da2beaSAndroid Build Coastguard Worker 		int nonvec = (i & 16) != 0;
855*25da2beaSAndroid Build Coastguard Worker 
856*25da2beaSAndroid Build Coastguard Worker 		/* direct IO requires alignment, skip it */
857*25da2beaSAndroid Build Coastguard Worker 		if (!buffered || !fixed || nonvec)
858*25da2beaSAndroid Build Coastguard Worker 			continue;
859*25da2beaSAndroid Build Coastguard Worker 
860*25da2beaSAndroid Build Coastguard Worker 		ret = test_io(fname, write, buffered, sqthread, fixed, nonvec,
861*25da2beaSAndroid Build Coastguard Worker 			      -1);
862*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
863*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "test_io failed %d/%d/%d/%d/%d\n",
864*25da2beaSAndroid Build Coastguard Worker 				write, buffered, sqthread, fixed, nonvec);
865*25da2beaSAndroid Build Coastguard Worker 			goto err;
866*25da2beaSAndroid Build Coastguard Worker 		}
867*25da2beaSAndroid Build Coastguard Worker 	}
868*25da2beaSAndroid Build Coastguard Worker 
869*25da2beaSAndroid Build Coastguard Worker 	if (fname != argv[1])
870*25da2beaSAndroid Build Coastguard Worker 		unlink(fname);
871*25da2beaSAndroid Build Coastguard Worker 	return 0;
872*25da2beaSAndroid Build Coastguard Worker err:
873*25da2beaSAndroid Build Coastguard Worker 	if (fname != argv[1])
874*25da2beaSAndroid Build Coastguard Worker 		unlink(fname);
875*25da2beaSAndroid Build Coastguard Worker 	return 1;
876*25da2beaSAndroid Build Coastguard Worker }
877