1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker * Description: generic tests for io_uring drain io
4*25da2beaSAndroid Build Coastguard Worker *
5*25da2beaSAndroid Build Coastguard Worker * The main idea is to randomly generate different type of sqe to
6*25da2beaSAndroid Build Coastguard Worker * challenge the drain logic. There are some restrictions for the
7*25da2beaSAndroid Build Coastguard Worker * generated sqes, details in io_uring maillist:
8*25da2beaSAndroid Build Coastguard Worker * https://lore.kernel.org/io-uring/[email protected]/
9*25da2beaSAndroid Build Coastguard Worker *
10*25da2beaSAndroid Build Coastguard Worker */
11*25da2beaSAndroid Build Coastguard Worker #include <errno.h>
12*25da2beaSAndroid Build Coastguard Worker #include <stdio.h>
13*25da2beaSAndroid Build Coastguard Worker #include <unistd.h>
14*25da2beaSAndroid Build Coastguard Worker #include <stdlib.h>
15*25da2beaSAndroid Build Coastguard Worker #include <string.h>
16*25da2beaSAndroid Build Coastguard Worker #include <time.h>
17*25da2beaSAndroid Build Coastguard Worker #include <poll.h>
18*25da2beaSAndroid Build Coastguard Worker
19*25da2beaSAndroid Build Coastguard Worker #include "liburing.h"
20*25da2beaSAndroid Build Coastguard Worker
21*25da2beaSAndroid Build Coastguard Worker enum {
22*25da2beaSAndroid Build Coastguard Worker multi,
23*25da2beaSAndroid Build Coastguard Worker single,
24*25da2beaSAndroid Build Coastguard Worker nop,
25*25da2beaSAndroid Build Coastguard Worker cancel,
26*25da2beaSAndroid Build Coastguard Worker op_last,
27*25da2beaSAndroid Build Coastguard Worker };
28*25da2beaSAndroid Build Coastguard Worker
29*25da2beaSAndroid Build Coastguard Worker struct sqe_info {
30*25da2beaSAndroid Build Coastguard Worker __u8 op;
31*25da2beaSAndroid Build Coastguard Worker unsigned flags;
32*25da2beaSAndroid Build Coastguard Worker };
33*25da2beaSAndroid Build Coastguard Worker
34*25da2beaSAndroid Build Coastguard Worker #define max_entry 50
35*25da2beaSAndroid Build Coastguard Worker
36*25da2beaSAndroid Build Coastguard Worker /*
37*25da2beaSAndroid Build Coastguard Worker * sqe_flags: combination of sqe flags
38*25da2beaSAndroid Build Coastguard Worker * multi_sqes: record the user_data/index of all the multishot sqes
39*25da2beaSAndroid Build Coastguard Worker * cnt: how many entries there are in multi_sqes
40*25da2beaSAndroid Build Coastguard Worker * we can leverage multi_sqes array for cancellation: we randomly pick
41*25da2beaSAndroid Build Coastguard Worker * up an entry in multi_sqes when form a cancellation sqe.
42*25da2beaSAndroid Build Coastguard Worker * multi_cap: limitation of number of multishot sqes
43*25da2beaSAndroid Build Coastguard Worker */
44*25da2beaSAndroid Build Coastguard Worker const unsigned sqe_flags[4] = {0, IOSQE_IO_LINK, IOSQE_IO_DRAIN,
45*25da2beaSAndroid Build Coastguard Worker IOSQE_IO_LINK | IOSQE_IO_DRAIN};
46*25da2beaSAndroid Build Coastguard Worker int multi_sqes[max_entry], cnt = 0;
47*25da2beaSAndroid Build Coastguard Worker int multi_cap = max_entry / 5;
48*25da2beaSAndroid Build Coastguard Worker
write_pipe(int pipe,char * str)49*25da2beaSAndroid Build Coastguard Worker int write_pipe(int pipe, char *str)
50*25da2beaSAndroid Build Coastguard Worker {
51*25da2beaSAndroid Build Coastguard Worker int ret;
52*25da2beaSAndroid Build Coastguard Worker do {
53*25da2beaSAndroid Build Coastguard Worker errno = 0;
54*25da2beaSAndroid Build Coastguard Worker ret = write(pipe, str, 3);
55*25da2beaSAndroid Build Coastguard Worker } while (ret == -1 && errno == EINTR);
56*25da2beaSAndroid Build Coastguard Worker return ret;
57*25da2beaSAndroid Build Coastguard Worker }
58*25da2beaSAndroid Build Coastguard Worker
read_pipe(int pipe)59*25da2beaSAndroid Build Coastguard Worker void read_pipe(int pipe)
60*25da2beaSAndroid Build Coastguard Worker {
61*25da2beaSAndroid Build Coastguard Worker char str[4] = {0};
62*25da2beaSAndroid Build Coastguard Worker int ret;
63*25da2beaSAndroid Build Coastguard Worker
64*25da2beaSAndroid Build Coastguard Worker ret = read(pipe, &str, 3);
65*25da2beaSAndroid Build Coastguard Worker if (ret < 0)
66*25da2beaSAndroid Build Coastguard Worker perror("read");
67*25da2beaSAndroid Build Coastguard Worker }
68*25da2beaSAndroid Build Coastguard Worker
trigger_event(int p[])69*25da2beaSAndroid Build Coastguard Worker int trigger_event(int p[])
70*25da2beaSAndroid Build Coastguard Worker {
71*25da2beaSAndroid Build Coastguard Worker int ret;
72*25da2beaSAndroid Build Coastguard Worker if ((ret = write_pipe(p[1], "foo")) != 3) {
73*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "bad write return %d\n", ret);
74*25da2beaSAndroid Build Coastguard Worker return 1;
75*25da2beaSAndroid Build Coastguard Worker }
76*25da2beaSAndroid Build Coastguard Worker read_pipe(p[0]);
77*25da2beaSAndroid Build Coastguard Worker return 0;
78*25da2beaSAndroid Build Coastguard Worker }
79*25da2beaSAndroid Build Coastguard Worker
io_uring_sqe_prep(int op,struct io_uring_sqe * sqe,unsigned sqe_flags,int arg)80*25da2beaSAndroid Build Coastguard Worker void io_uring_sqe_prep(int op, struct io_uring_sqe *sqe, unsigned sqe_flags, int arg)
81*25da2beaSAndroid Build Coastguard Worker {
82*25da2beaSAndroid Build Coastguard Worker switch (op) {
83*25da2beaSAndroid Build Coastguard Worker case multi:
84*25da2beaSAndroid Build Coastguard Worker io_uring_prep_poll_add(sqe, arg, POLLIN);
85*25da2beaSAndroid Build Coastguard Worker sqe->len |= IORING_POLL_ADD_MULTI;
86*25da2beaSAndroid Build Coastguard Worker break;
87*25da2beaSAndroid Build Coastguard Worker case single:
88*25da2beaSAndroid Build Coastguard Worker io_uring_prep_poll_add(sqe, arg, POLLIN);
89*25da2beaSAndroid Build Coastguard Worker break;
90*25da2beaSAndroid Build Coastguard Worker case nop:
91*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe);
92*25da2beaSAndroid Build Coastguard Worker break;
93*25da2beaSAndroid Build Coastguard Worker case cancel:
94*25da2beaSAndroid Build Coastguard Worker io_uring_prep_poll_remove(sqe, arg);
95*25da2beaSAndroid Build Coastguard Worker break;
96*25da2beaSAndroid Build Coastguard Worker }
97*25da2beaSAndroid Build Coastguard Worker sqe->flags = sqe_flags;
98*25da2beaSAndroid Build Coastguard Worker }
99*25da2beaSAndroid Build Coastguard Worker
generate_flags(int sqe_op)100*25da2beaSAndroid Build Coastguard Worker __u8 generate_flags(int sqe_op)
101*25da2beaSAndroid Build Coastguard Worker {
102*25da2beaSAndroid Build Coastguard Worker __u8 flags = 0;
103*25da2beaSAndroid Build Coastguard Worker /*
104*25da2beaSAndroid Build Coastguard Worker * drain sqe must be put after multishot sqes cancelled
105*25da2beaSAndroid Build Coastguard Worker */
106*25da2beaSAndroid Build Coastguard Worker do {
107*25da2beaSAndroid Build Coastguard Worker flags = sqe_flags[rand() % 4];
108*25da2beaSAndroid Build Coastguard Worker } while ((flags & IOSQE_IO_DRAIN) && cnt);
109*25da2beaSAndroid Build Coastguard Worker
110*25da2beaSAndroid Build Coastguard Worker /*
111*25da2beaSAndroid Build Coastguard Worker * cancel req cannot have drain or link flag
112*25da2beaSAndroid Build Coastguard Worker */
113*25da2beaSAndroid Build Coastguard Worker if (sqe_op == cancel) {
114*25da2beaSAndroid Build Coastguard Worker flags &= ~(IOSQE_IO_DRAIN | IOSQE_IO_LINK);
115*25da2beaSAndroid Build Coastguard Worker }
116*25da2beaSAndroid Build Coastguard Worker /*
117*25da2beaSAndroid Build Coastguard Worker * avoid below case:
118*25da2beaSAndroid Build Coastguard Worker * sqe0(multishot, link)->sqe1(nop, link)->sqe2(nop)->sqe3(cancel_sqe0)
119*25da2beaSAndroid Build Coastguard Worker * sqe3 may excute before sqe0 so that sqe0 isn't cancelled
120*25da2beaSAndroid Build Coastguard Worker */
121*25da2beaSAndroid Build Coastguard Worker if (sqe_op == multi)
122*25da2beaSAndroid Build Coastguard Worker flags &= ~IOSQE_IO_LINK;
123*25da2beaSAndroid Build Coastguard Worker
124*25da2beaSAndroid Build Coastguard Worker return flags;
125*25da2beaSAndroid Build Coastguard Worker
126*25da2beaSAndroid Build Coastguard Worker }
127*25da2beaSAndroid Build Coastguard Worker
128*25da2beaSAndroid Build Coastguard Worker /*
129*25da2beaSAndroid Build Coastguard Worker * function to generate opcode of a sqe
130*25da2beaSAndroid Build Coastguard Worker * several restrictions here:
131*25da2beaSAndroid Build Coastguard Worker * - cancel all the previous multishot sqes as soon as possible when
132*25da2beaSAndroid Build Coastguard Worker * we reach high watermark.
133*25da2beaSAndroid Build Coastguard Worker * - ensure there is some multishot sqe when generating a cancel sqe
134*25da2beaSAndroid Build Coastguard Worker * - ensure a cancel/multshot sqe is not in a linkchain
135*25da2beaSAndroid Build Coastguard Worker * - ensure number of multishot sqes doesn't exceed multi_cap
136*25da2beaSAndroid Build Coastguard Worker * - don't generate multishot sqes after high watermark
137*25da2beaSAndroid Build Coastguard Worker */
generate_opcode(int i,int pre_flags)138*25da2beaSAndroid Build Coastguard Worker int generate_opcode(int i, int pre_flags)
139*25da2beaSAndroid Build Coastguard Worker {
140*25da2beaSAndroid Build Coastguard Worker int sqe_op;
141*25da2beaSAndroid Build Coastguard Worker int high_watermark = max_entry - max_entry / 5;
142*25da2beaSAndroid Build Coastguard Worker bool retry0 = false, retry1 = false, retry2 = false;
143*25da2beaSAndroid Build Coastguard Worker
144*25da2beaSAndroid Build Coastguard Worker if ((i >= high_watermark) && cnt) {
145*25da2beaSAndroid Build Coastguard Worker sqe_op = cancel;
146*25da2beaSAndroid Build Coastguard Worker } else {
147*25da2beaSAndroid Build Coastguard Worker do {
148*25da2beaSAndroid Build Coastguard Worker sqe_op = rand() % op_last;
149*25da2beaSAndroid Build Coastguard Worker retry0 = (sqe_op == cancel) && (!cnt || (pre_flags & IOSQE_IO_LINK));
150*25da2beaSAndroid Build Coastguard Worker retry1 = (sqe_op == multi) && ((multi_cap - 1 < 0) || i >= high_watermark);
151*25da2beaSAndroid Build Coastguard Worker retry2 = (sqe_op == multi) && (pre_flags & IOSQE_IO_LINK);
152*25da2beaSAndroid Build Coastguard Worker } while (retry0 || retry1 || retry2);
153*25da2beaSAndroid Build Coastguard Worker }
154*25da2beaSAndroid Build Coastguard Worker
155*25da2beaSAndroid Build Coastguard Worker if (sqe_op == multi)
156*25da2beaSAndroid Build Coastguard Worker multi_cap--;
157*25da2beaSAndroid Build Coastguard Worker return sqe_op;
158*25da2beaSAndroid Build Coastguard Worker }
159*25da2beaSAndroid Build Coastguard Worker
add_multishot_sqe(int index)160*25da2beaSAndroid Build Coastguard Worker static inline void add_multishot_sqe(int index)
161*25da2beaSAndroid Build Coastguard Worker {
162*25da2beaSAndroid Build Coastguard Worker multi_sqes[cnt++] = index;
163*25da2beaSAndroid Build Coastguard Worker }
164*25da2beaSAndroid Build Coastguard Worker
remove_multishot_sqe()165*25da2beaSAndroid Build Coastguard Worker int remove_multishot_sqe()
166*25da2beaSAndroid Build Coastguard Worker {
167*25da2beaSAndroid Build Coastguard Worker int ret;
168*25da2beaSAndroid Build Coastguard Worker
169*25da2beaSAndroid Build Coastguard Worker int rem_index = rand() % cnt;
170*25da2beaSAndroid Build Coastguard Worker ret = multi_sqes[rem_index];
171*25da2beaSAndroid Build Coastguard Worker multi_sqes[rem_index] = multi_sqes[cnt - 1];
172*25da2beaSAndroid Build Coastguard Worker cnt--;
173*25da2beaSAndroid Build Coastguard Worker
174*25da2beaSAndroid Build Coastguard Worker return ret;
175*25da2beaSAndroid Build Coastguard Worker }
176*25da2beaSAndroid Build Coastguard Worker
test_generic_drain(struct io_uring * ring)177*25da2beaSAndroid Build Coastguard Worker static int test_generic_drain(struct io_uring *ring)
178*25da2beaSAndroid Build Coastguard Worker {
179*25da2beaSAndroid Build Coastguard Worker struct io_uring_cqe *cqe;
180*25da2beaSAndroid Build Coastguard Worker struct io_uring_sqe *sqe[max_entry];
181*25da2beaSAndroid Build Coastguard Worker struct sqe_info si[max_entry];
182*25da2beaSAndroid Build Coastguard Worker int cqe_data[max_entry << 1], cqe_res[max_entry << 1];
183*25da2beaSAndroid Build Coastguard Worker int i, j, ret, arg = 0;
184*25da2beaSAndroid Build Coastguard Worker int pipes[max_entry][2];
185*25da2beaSAndroid Build Coastguard Worker int pre_flags = 0;
186*25da2beaSAndroid Build Coastguard Worker
187*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < max_entry; i++) {
188*25da2beaSAndroid Build Coastguard Worker if (pipe(pipes[i]) != 0) {
189*25da2beaSAndroid Build Coastguard Worker perror("pipe");
190*25da2beaSAndroid Build Coastguard Worker return 1;
191*25da2beaSAndroid Build Coastguard Worker }
192*25da2beaSAndroid Build Coastguard Worker }
193*25da2beaSAndroid Build Coastguard Worker
194*25da2beaSAndroid Build Coastguard Worker srand((unsigned)time(NULL));
195*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < max_entry; i++) {
196*25da2beaSAndroid Build Coastguard Worker sqe[i] = io_uring_get_sqe(ring);
197*25da2beaSAndroid Build Coastguard Worker if (!sqe[i]) {
198*25da2beaSAndroid Build Coastguard Worker printf("get sqe failed\n");
199*25da2beaSAndroid Build Coastguard Worker goto err;
200*25da2beaSAndroid Build Coastguard Worker }
201*25da2beaSAndroid Build Coastguard Worker
202*25da2beaSAndroid Build Coastguard Worker int sqe_op = generate_opcode(i, pre_flags);
203*25da2beaSAndroid Build Coastguard Worker __u8 flags = generate_flags(sqe_op);
204*25da2beaSAndroid Build Coastguard Worker
205*25da2beaSAndroid Build Coastguard Worker if (sqe_op == cancel)
206*25da2beaSAndroid Build Coastguard Worker arg = remove_multishot_sqe();
207*25da2beaSAndroid Build Coastguard Worker if (sqe_op == multi || sqe_op == single)
208*25da2beaSAndroid Build Coastguard Worker arg = pipes[i][0];
209*25da2beaSAndroid Build Coastguard Worker io_uring_sqe_prep(sqe_op, sqe[i], flags, arg);
210*25da2beaSAndroid Build Coastguard Worker sqe[i]->user_data = i;
211*25da2beaSAndroid Build Coastguard Worker si[i].op = sqe_op;
212*25da2beaSAndroid Build Coastguard Worker si[i].flags = flags;
213*25da2beaSAndroid Build Coastguard Worker pre_flags = flags;
214*25da2beaSAndroid Build Coastguard Worker if (sqe_op == multi)
215*25da2beaSAndroid Build Coastguard Worker add_multishot_sqe(i);
216*25da2beaSAndroid Build Coastguard Worker }
217*25da2beaSAndroid Build Coastguard Worker
218*25da2beaSAndroid Build Coastguard Worker ret = io_uring_submit(ring);
219*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
220*25da2beaSAndroid Build Coastguard Worker printf("sqe submit failed\n");
221*25da2beaSAndroid Build Coastguard Worker goto err;
222*25da2beaSAndroid Build Coastguard Worker } else if (ret < max_entry) {
223*25da2beaSAndroid Build Coastguard Worker printf("Submitted only %d\n", ret);
224*25da2beaSAndroid Build Coastguard Worker goto err;
225*25da2beaSAndroid Build Coastguard Worker }
226*25da2beaSAndroid Build Coastguard Worker
227*25da2beaSAndroid Build Coastguard Worker sleep(1);
228*25da2beaSAndroid Build Coastguard Worker // TODO: randomize event triggerring order
229*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < max_entry; i++) {
230*25da2beaSAndroid Build Coastguard Worker if (si[i].op != multi && si[i].op != single)
231*25da2beaSAndroid Build Coastguard Worker continue;
232*25da2beaSAndroid Build Coastguard Worker
233*25da2beaSAndroid Build Coastguard Worker if (trigger_event(pipes[i]))
234*25da2beaSAndroid Build Coastguard Worker goto err;
235*25da2beaSAndroid Build Coastguard Worker }
236*25da2beaSAndroid Build Coastguard Worker sleep(1);
237*25da2beaSAndroid Build Coastguard Worker i = 0;
238*25da2beaSAndroid Build Coastguard Worker while (!io_uring_peek_cqe(ring, &cqe)) {
239*25da2beaSAndroid Build Coastguard Worker cqe_data[i] = cqe->user_data;
240*25da2beaSAndroid Build Coastguard Worker cqe_res[i++] = cqe->res;
241*25da2beaSAndroid Build Coastguard Worker io_uring_cqe_seen(ring, cqe);
242*25da2beaSAndroid Build Coastguard Worker }
243*25da2beaSAndroid Build Coastguard Worker
244*25da2beaSAndroid Build Coastguard Worker /*
245*25da2beaSAndroid Build Coastguard Worker * compl_bits is a bit map to record completions.
246*25da2beaSAndroid Build Coastguard Worker * eg. sqe[0], sqe[1], sqe[2] fully completed
247*25da2beaSAndroid Build Coastguard Worker * then compl_bits is 000...00111b
248*25da2beaSAndroid Build Coastguard Worker *
249*25da2beaSAndroid Build Coastguard Worker */
250*25da2beaSAndroid Build Coastguard Worker unsigned long long compl_bits = 0;
251*25da2beaSAndroid Build Coastguard Worker for (j = 0; j < i; j++) {
252*25da2beaSAndroid Build Coastguard Worker int index = cqe_data[j];
253*25da2beaSAndroid Build Coastguard Worker if ((si[index].flags & IOSQE_IO_DRAIN) && index) {
254*25da2beaSAndroid Build Coastguard Worker if ((~compl_bits) & ((1ULL << index) - 1)) {
255*25da2beaSAndroid Build Coastguard Worker printf("drain failed\n");
256*25da2beaSAndroid Build Coastguard Worker goto err;
257*25da2beaSAndroid Build Coastguard Worker }
258*25da2beaSAndroid Build Coastguard Worker }
259*25da2beaSAndroid Build Coastguard Worker /*
260*25da2beaSAndroid Build Coastguard Worker * for multishot sqes, record them only when it is cancelled
261*25da2beaSAndroid Build Coastguard Worker */
262*25da2beaSAndroid Build Coastguard Worker if ((si[index].op != multi) || (cqe_res[j] == -ECANCELED))
263*25da2beaSAndroid Build Coastguard Worker compl_bits |= (1ULL << index);
264*25da2beaSAndroid Build Coastguard Worker }
265*25da2beaSAndroid Build Coastguard Worker
266*25da2beaSAndroid Build Coastguard Worker return 0;
267*25da2beaSAndroid Build Coastguard Worker err:
268*25da2beaSAndroid Build Coastguard Worker return 1;
269*25da2beaSAndroid Build Coastguard Worker }
270*25da2beaSAndroid Build Coastguard Worker
test_simple_drain(struct io_uring * ring)271*25da2beaSAndroid Build Coastguard Worker static int test_simple_drain(struct io_uring *ring)
272*25da2beaSAndroid Build Coastguard Worker {
273*25da2beaSAndroid Build Coastguard Worker struct io_uring_cqe *cqe;
274*25da2beaSAndroid Build Coastguard Worker struct io_uring_sqe *sqe[2];
275*25da2beaSAndroid Build Coastguard Worker int i, ret;
276*25da2beaSAndroid Build Coastguard Worker int pipe1[2], pipe2[2];
277*25da2beaSAndroid Build Coastguard Worker
278*25da2beaSAndroid Build Coastguard Worker if (pipe(pipe1) != 0 || pipe(pipe2) != 0) {
279*25da2beaSAndroid Build Coastguard Worker perror("pipe");
280*25da2beaSAndroid Build Coastguard Worker return 1;
281*25da2beaSAndroid Build Coastguard Worker }
282*25da2beaSAndroid Build Coastguard Worker
283*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 2; i++) {
284*25da2beaSAndroid Build Coastguard Worker sqe[i] = io_uring_get_sqe(ring);
285*25da2beaSAndroid Build Coastguard Worker if (!sqe[i]) {
286*25da2beaSAndroid Build Coastguard Worker printf("get sqe failed\n");
287*25da2beaSAndroid Build Coastguard Worker goto err;
288*25da2beaSAndroid Build Coastguard Worker }
289*25da2beaSAndroid Build Coastguard Worker }
290*25da2beaSAndroid Build Coastguard Worker
291*25da2beaSAndroid Build Coastguard Worker io_uring_prep_poll_multishot(sqe[0], pipe1[0], POLLIN);
292*25da2beaSAndroid Build Coastguard Worker sqe[0]->user_data = 0;
293*25da2beaSAndroid Build Coastguard Worker
294*25da2beaSAndroid Build Coastguard Worker io_uring_prep_poll_add(sqe[1], pipe2[0], POLLIN);
295*25da2beaSAndroid Build Coastguard Worker sqe[1]->user_data = 1;
296*25da2beaSAndroid Build Coastguard Worker
297*25da2beaSAndroid Build Coastguard Worker ret = io_uring_submit(ring);
298*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
299*25da2beaSAndroid Build Coastguard Worker printf("sqe submit failed\n");
300*25da2beaSAndroid Build Coastguard Worker goto err;
301*25da2beaSAndroid Build Coastguard Worker } else if (ret < 2) {
302*25da2beaSAndroid Build Coastguard Worker printf("Submitted only %d\n", ret);
303*25da2beaSAndroid Build Coastguard Worker goto err;
304*25da2beaSAndroid Build Coastguard Worker }
305*25da2beaSAndroid Build Coastguard Worker
306*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 2; i++) {
307*25da2beaSAndroid Build Coastguard Worker if (trigger_event(pipe1))
308*25da2beaSAndroid Build Coastguard Worker goto err;
309*25da2beaSAndroid Build Coastguard Worker }
310*25da2beaSAndroid Build Coastguard Worker if (trigger_event(pipe2))
311*25da2beaSAndroid Build Coastguard Worker goto err;
312*25da2beaSAndroid Build Coastguard Worker
313*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 2; i++) {
314*25da2beaSAndroid Build Coastguard Worker sqe[i] = io_uring_get_sqe(ring);
315*25da2beaSAndroid Build Coastguard Worker if (!sqe[i]) {
316*25da2beaSAndroid Build Coastguard Worker printf("get sqe failed\n");
317*25da2beaSAndroid Build Coastguard Worker goto err;
318*25da2beaSAndroid Build Coastguard Worker }
319*25da2beaSAndroid Build Coastguard Worker }
320*25da2beaSAndroid Build Coastguard Worker
321*25da2beaSAndroid Build Coastguard Worker io_uring_prep_poll_remove(sqe[0], 0);
322*25da2beaSAndroid Build Coastguard Worker sqe[0]->user_data = 2;
323*25da2beaSAndroid Build Coastguard Worker
324*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[1]);
325*25da2beaSAndroid Build Coastguard Worker sqe[1]->flags |= IOSQE_IO_DRAIN;
326*25da2beaSAndroid Build Coastguard Worker sqe[1]->user_data = 3;
327*25da2beaSAndroid Build Coastguard Worker
328*25da2beaSAndroid Build Coastguard Worker ret = io_uring_submit(ring);
329*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
330*25da2beaSAndroid Build Coastguard Worker printf("sqe submit failed\n");
331*25da2beaSAndroid Build Coastguard Worker goto err;
332*25da2beaSAndroid Build Coastguard Worker } else if (ret < 2) {
333*25da2beaSAndroid Build Coastguard Worker printf("Submitted only %d\n", ret);
334*25da2beaSAndroid Build Coastguard Worker goto err;
335*25da2beaSAndroid Build Coastguard Worker }
336*25da2beaSAndroid Build Coastguard Worker
337*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 6; i++) {
338*25da2beaSAndroid Build Coastguard Worker ret = io_uring_wait_cqe(ring, &cqe);
339*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
340*25da2beaSAndroid Build Coastguard Worker printf("wait completion %d\n", ret);
341*25da2beaSAndroid Build Coastguard Worker goto err;
342*25da2beaSAndroid Build Coastguard Worker }
343*25da2beaSAndroid Build Coastguard Worker if ((i == 5) && (cqe->user_data != 3))
344*25da2beaSAndroid Build Coastguard Worker goto err;
345*25da2beaSAndroid Build Coastguard Worker io_uring_cqe_seen(ring, cqe);
346*25da2beaSAndroid Build Coastguard Worker }
347*25da2beaSAndroid Build Coastguard Worker
348*25da2beaSAndroid Build Coastguard Worker close(pipe1[0]);
349*25da2beaSAndroid Build Coastguard Worker close(pipe1[1]);
350*25da2beaSAndroid Build Coastguard Worker close(pipe2[0]);
351*25da2beaSAndroid Build Coastguard Worker close(pipe2[1]);
352*25da2beaSAndroid Build Coastguard Worker return 0;
353*25da2beaSAndroid Build Coastguard Worker err:
354*25da2beaSAndroid Build Coastguard Worker return 1;
355*25da2beaSAndroid Build Coastguard Worker }
356*25da2beaSAndroid Build Coastguard Worker
main(int argc,char * argv[])357*25da2beaSAndroid Build Coastguard Worker int main(int argc, char *argv[])
358*25da2beaSAndroid Build Coastguard Worker {
359*25da2beaSAndroid Build Coastguard Worker struct io_uring ring;
360*25da2beaSAndroid Build Coastguard Worker int i, ret;
361*25da2beaSAndroid Build Coastguard Worker
362*25da2beaSAndroid Build Coastguard Worker if (argc > 1)
363*25da2beaSAndroid Build Coastguard Worker return 0;
364*25da2beaSAndroid Build Coastguard Worker
365*25da2beaSAndroid Build Coastguard Worker ret = io_uring_queue_init(1024, &ring, 0);
366*25da2beaSAndroid Build Coastguard Worker if (ret) {
367*25da2beaSAndroid Build Coastguard Worker printf("ring setup failed\n");
368*25da2beaSAndroid Build Coastguard Worker return 1;
369*25da2beaSAndroid Build Coastguard Worker }
370*25da2beaSAndroid Build Coastguard Worker
371*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 5; i++) {
372*25da2beaSAndroid Build Coastguard Worker ret = test_simple_drain(&ring);
373*25da2beaSAndroid Build Coastguard Worker if (ret) {
374*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "test_simple_drain failed\n");
375*25da2beaSAndroid Build Coastguard Worker break;
376*25da2beaSAndroid Build Coastguard Worker }
377*25da2beaSAndroid Build Coastguard Worker }
378*25da2beaSAndroid Build Coastguard Worker
379*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 5; i++) {
380*25da2beaSAndroid Build Coastguard Worker ret = test_generic_drain(&ring);
381*25da2beaSAndroid Build Coastguard Worker if (ret) {
382*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "test_generic_drain failed\n");
383*25da2beaSAndroid Build Coastguard Worker break;
384*25da2beaSAndroid Build Coastguard Worker }
385*25da2beaSAndroid Build Coastguard Worker }
386*25da2beaSAndroid Build Coastguard Worker return ret;
387*25da2beaSAndroid Build Coastguard Worker }
388