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