1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker * Description: test io_uring link io with drain io
4*25da2beaSAndroid Build Coastguard Worker *
5*25da2beaSAndroid Build Coastguard Worker */
6*25da2beaSAndroid Build Coastguard Worker #include <errno.h>
7*25da2beaSAndroid Build Coastguard Worker #include <stdio.h>
8*25da2beaSAndroid Build Coastguard Worker #include <unistd.h>
9*25da2beaSAndroid Build Coastguard Worker #include <stdlib.h>
10*25da2beaSAndroid Build Coastguard Worker #include <string.h>
11*25da2beaSAndroid Build Coastguard Worker #include <fcntl.h>
12*25da2beaSAndroid Build Coastguard Worker
13*25da2beaSAndroid Build Coastguard Worker #include "helpers.h"
14*25da2beaSAndroid Build Coastguard Worker #include "liburing.h"
15*25da2beaSAndroid Build Coastguard Worker
test_link_drain_one(struct io_uring * ring)16*25da2beaSAndroid Build Coastguard Worker static int test_link_drain_one(struct io_uring *ring)
17*25da2beaSAndroid Build Coastguard Worker {
18*25da2beaSAndroid Build Coastguard Worker struct io_uring_cqe *cqe;
19*25da2beaSAndroid Build Coastguard Worker struct io_uring_sqe *sqe[5];
20*25da2beaSAndroid Build Coastguard Worker struct iovec iovecs;
21*25da2beaSAndroid Build Coastguard Worker int i, fd, ret;
22*25da2beaSAndroid Build Coastguard Worker off_t off = 0;
23*25da2beaSAndroid Build Coastguard Worker char data[5] = {0};
24*25da2beaSAndroid Build Coastguard Worker char expect[5] = {0, 1, 2, 3, 4};
25*25da2beaSAndroid Build Coastguard Worker
26*25da2beaSAndroid Build Coastguard Worker fd = open("testfile", O_WRONLY | O_CREAT, 0644);
27*25da2beaSAndroid Build Coastguard Worker if (fd < 0) {
28*25da2beaSAndroid Build Coastguard Worker perror("open");
29*25da2beaSAndroid Build Coastguard Worker return 1;
30*25da2beaSAndroid Build Coastguard Worker }
31*25da2beaSAndroid Build Coastguard Worker
32*25da2beaSAndroid Build Coastguard Worker iovecs.iov_base = t_malloc(4096);
33*25da2beaSAndroid Build Coastguard Worker iovecs.iov_len = 4096;
34*25da2beaSAndroid Build Coastguard Worker
35*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 5; i++) {
36*25da2beaSAndroid Build Coastguard Worker sqe[i] = io_uring_get_sqe(ring);
37*25da2beaSAndroid Build Coastguard Worker if (!sqe[i]) {
38*25da2beaSAndroid Build Coastguard Worker printf("get sqe failed\n");
39*25da2beaSAndroid Build Coastguard Worker goto err;
40*25da2beaSAndroid Build Coastguard Worker }
41*25da2beaSAndroid Build Coastguard Worker }
42*25da2beaSAndroid Build Coastguard Worker
43*25da2beaSAndroid Build Coastguard Worker /* normal heavy io */
44*25da2beaSAndroid Build Coastguard Worker io_uring_prep_writev(sqe[0], fd, &iovecs, 1, off);
45*25da2beaSAndroid Build Coastguard Worker sqe[0]->user_data = 0;
46*25da2beaSAndroid Build Coastguard Worker
47*25da2beaSAndroid Build Coastguard Worker /* link io */
48*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[1]);
49*25da2beaSAndroid Build Coastguard Worker sqe[1]->flags |= IOSQE_IO_LINK;
50*25da2beaSAndroid Build Coastguard Worker sqe[1]->user_data = 1;
51*25da2beaSAndroid Build Coastguard Worker
52*25da2beaSAndroid Build Coastguard Worker /* link drain io */
53*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[2]);
54*25da2beaSAndroid Build Coastguard Worker sqe[2]->flags |= (IOSQE_IO_LINK | IOSQE_IO_DRAIN);
55*25da2beaSAndroid Build Coastguard Worker sqe[2]->user_data = 2;
56*25da2beaSAndroid Build Coastguard Worker
57*25da2beaSAndroid Build Coastguard Worker /* link io */
58*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[3]);
59*25da2beaSAndroid Build Coastguard Worker sqe[3]->user_data = 3;
60*25da2beaSAndroid Build Coastguard Worker
61*25da2beaSAndroid Build Coastguard Worker /* normal nop io */
62*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[4]);
63*25da2beaSAndroid Build Coastguard Worker sqe[4]->user_data = 4;
64*25da2beaSAndroid Build Coastguard Worker
65*25da2beaSAndroid Build Coastguard Worker ret = io_uring_submit(ring);
66*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
67*25da2beaSAndroid Build Coastguard Worker printf("sqe submit failed\n");
68*25da2beaSAndroid Build Coastguard Worker goto err;
69*25da2beaSAndroid Build Coastguard Worker } else if (ret < 5) {
70*25da2beaSAndroid Build Coastguard Worker printf("Submitted only %d\n", ret);
71*25da2beaSAndroid Build Coastguard Worker goto err;
72*25da2beaSAndroid Build Coastguard Worker }
73*25da2beaSAndroid Build Coastguard Worker
74*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 5; i++) {
75*25da2beaSAndroid Build Coastguard Worker ret = io_uring_wait_cqe(ring, &cqe);
76*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
77*25da2beaSAndroid Build Coastguard Worker printf("child: wait completion %d\n", ret);
78*25da2beaSAndroid Build Coastguard Worker goto err;
79*25da2beaSAndroid Build Coastguard Worker }
80*25da2beaSAndroid Build Coastguard Worker
81*25da2beaSAndroid Build Coastguard Worker data[i] = cqe->user_data;
82*25da2beaSAndroid Build Coastguard Worker io_uring_cqe_seen(ring, cqe);
83*25da2beaSAndroid Build Coastguard Worker }
84*25da2beaSAndroid Build Coastguard Worker
85*25da2beaSAndroid Build Coastguard Worker if (memcmp(data, expect, 5) != 0)
86*25da2beaSAndroid Build Coastguard Worker goto err;
87*25da2beaSAndroid Build Coastguard Worker
88*25da2beaSAndroid Build Coastguard Worker free(iovecs.iov_base);
89*25da2beaSAndroid Build Coastguard Worker close(fd);
90*25da2beaSAndroid Build Coastguard Worker unlink("testfile");
91*25da2beaSAndroid Build Coastguard Worker return 0;
92*25da2beaSAndroid Build Coastguard Worker err:
93*25da2beaSAndroid Build Coastguard Worker free(iovecs.iov_base);
94*25da2beaSAndroid Build Coastguard Worker close(fd);
95*25da2beaSAndroid Build Coastguard Worker unlink("testfile");
96*25da2beaSAndroid Build Coastguard Worker return 1;
97*25da2beaSAndroid Build Coastguard Worker }
98*25da2beaSAndroid Build Coastguard Worker
test_link_drain_multi(struct io_uring * ring)99*25da2beaSAndroid Build Coastguard Worker int test_link_drain_multi(struct io_uring *ring)
100*25da2beaSAndroid Build Coastguard Worker {
101*25da2beaSAndroid Build Coastguard Worker struct io_uring_cqe *cqe;
102*25da2beaSAndroid Build Coastguard Worker struct io_uring_sqe *sqe[9];
103*25da2beaSAndroid Build Coastguard Worker struct iovec iovecs;
104*25da2beaSAndroid Build Coastguard Worker int i, fd, ret;
105*25da2beaSAndroid Build Coastguard Worker off_t off = 0;
106*25da2beaSAndroid Build Coastguard Worker char data[9] = {0};
107*25da2beaSAndroid Build Coastguard Worker char expect[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
108*25da2beaSAndroid Build Coastguard Worker
109*25da2beaSAndroid Build Coastguard Worker fd = open("testfile", O_WRONLY | O_CREAT, 0644);
110*25da2beaSAndroid Build Coastguard Worker if (fd < 0) {
111*25da2beaSAndroid Build Coastguard Worker perror("open");
112*25da2beaSAndroid Build Coastguard Worker return 1;
113*25da2beaSAndroid Build Coastguard Worker }
114*25da2beaSAndroid Build Coastguard Worker unlink("testfile");
115*25da2beaSAndroid Build Coastguard Worker
116*25da2beaSAndroid Build Coastguard Worker iovecs.iov_base = t_malloc(4096);
117*25da2beaSAndroid Build Coastguard Worker iovecs.iov_len = 4096;
118*25da2beaSAndroid Build Coastguard Worker
119*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 9; i++) {
120*25da2beaSAndroid Build Coastguard Worker sqe[i] = io_uring_get_sqe(ring);
121*25da2beaSAndroid Build Coastguard Worker if (!sqe[i]) {
122*25da2beaSAndroid Build Coastguard Worker printf("get sqe failed\n");
123*25da2beaSAndroid Build Coastguard Worker goto err;
124*25da2beaSAndroid Build Coastguard Worker }
125*25da2beaSAndroid Build Coastguard Worker }
126*25da2beaSAndroid Build Coastguard Worker
127*25da2beaSAndroid Build Coastguard Worker /* normal heavy io */
128*25da2beaSAndroid Build Coastguard Worker io_uring_prep_writev(sqe[0], fd, &iovecs, 1, off);
129*25da2beaSAndroid Build Coastguard Worker sqe[0]->user_data = 0;
130*25da2beaSAndroid Build Coastguard Worker
131*25da2beaSAndroid Build Coastguard Worker /* link1 io head */
132*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[1]);
133*25da2beaSAndroid Build Coastguard Worker sqe[1]->flags |= IOSQE_IO_LINK;
134*25da2beaSAndroid Build Coastguard Worker sqe[1]->user_data = 1;
135*25da2beaSAndroid Build Coastguard Worker
136*25da2beaSAndroid Build Coastguard Worker /* link1 drain io */
137*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[2]);
138*25da2beaSAndroid Build Coastguard Worker sqe[2]->flags |= (IOSQE_IO_LINK | IOSQE_IO_DRAIN);
139*25da2beaSAndroid Build Coastguard Worker sqe[2]->user_data = 2;
140*25da2beaSAndroid Build Coastguard Worker
141*25da2beaSAndroid Build Coastguard Worker /* link1 io end*/
142*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[3]);
143*25da2beaSAndroid Build Coastguard Worker sqe[3]->user_data = 3;
144*25da2beaSAndroid Build Coastguard Worker
145*25da2beaSAndroid Build Coastguard Worker /* link2 io head */
146*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[4]);
147*25da2beaSAndroid Build Coastguard Worker sqe[4]->flags |= IOSQE_IO_LINK;
148*25da2beaSAndroid Build Coastguard Worker sqe[4]->user_data = 4;
149*25da2beaSAndroid Build Coastguard Worker
150*25da2beaSAndroid Build Coastguard Worker /* link2 io */
151*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[5]);
152*25da2beaSAndroid Build Coastguard Worker sqe[5]->flags |= IOSQE_IO_LINK;
153*25da2beaSAndroid Build Coastguard Worker sqe[5]->user_data = 5;
154*25da2beaSAndroid Build Coastguard Worker
155*25da2beaSAndroid Build Coastguard Worker /* link2 drain io */
156*25da2beaSAndroid Build Coastguard Worker io_uring_prep_writev(sqe[6], fd, &iovecs, 1, off);
157*25da2beaSAndroid Build Coastguard Worker sqe[6]->flags |= (IOSQE_IO_LINK | IOSQE_IO_DRAIN);
158*25da2beaSAndroid Build Coastguard Worker sqe[6]->user_data = 6;
159*25da2beaSAndroid Build Coastguard Worker
160*25da2beaSAndroid Build Coastguard Worker /* link2 io end */
161*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[7]);
162*25da2beaSAndroid Build Coastguard Worker sqe[7]->user_data = 7;
163*25da2beaSAndroid Build Coastguard Worker
164*25da2beaSAndroid Build Coastguard Worker /* normal io */
165*25da2beaSAndroid Build Coastguard Worker io_uring_prep_nop(sqe[8]);
166*25da2beaSAndroid Build Coastguard Worker sqe[8]->user_data = 8;
167*25da2beaSAndroid Build Coastguard Worker
168*25da2beaSAndroid Build Coastguard Worker ret = io_uring_submit(ring);
169*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
170*25da2beaSAndroid Build Coastguard Worker printf("sqe submit failed\n");
171*25da2beaSAndroid Build Coastguard Worker goto err;
172*25da2beaSAndroid Build Coastguard Worker } else if (ret < 9) {
173*25da2beaSAndroid Build Coastguard Worker printf("Submitted only %d\n", ret);
174*25da2beaSAndroid Build Coastguard Worker goto err;
175*25da2beaSAndroid Build Coastguard Worker }
176*25da2beaSAndroid Build Coastguard Worker
177*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 9; i++) {
178*25da2beaSAndroid Build Coastguard Worker ret = io_uring_wait_cqe(ring, &cqe);
179*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
180*25da2beaSAndroid Build Coastguard Worker printf("child: wait completion %d\n", ret);
181*25da2beaSAndroid Build Coastguard Worker goto err;
182*25da2beaSAndroid Build Coastguard Worker }
183*25da2beaSAndroid Build Coastguard Worker
184*25da2beaSAndroid Build Coastguard Worker data[i] = cqe->user_data;
185*25da2beaSAndroid Build Coastguard Worker io_uring_cqe_seen(ring, cqe);
186*25da2beaSAndroid Build Coastguard Worker }
187*25da2beaSAndroid Build Coastguard Worker
188*25da2beaSAndroid Build Coastguard Worker if (memcmp(data, expect, 9) != 0)
189*25da2beaSAndroid Build Coastguard Worker goto err;
190*25da2beaSAndroid Build Coastguard Worker
191*25da2beaSAndroid Build Coastguard Worker free(iovecs.iov_base);
192*25da2beaSAndroid Build Coastguard Worker close(fd);
193*25da2beaSAndroid Build Coastguard Worker return 0;
194*25da2beaSAndroid Build Coastguard Worker err:
195*25da2beaSAndroid Build Coastguard Worker free(iovecs.iov_base);
196*25da2beaSAndroid Build Coastguard Worker close(fd);
197*25da2beaSAndroid Build Coastguard Worker return 1;
198*25da2beaSAndroid Build Coastguard Worker
199*25da2beaSAndroid Build Coastguard Worker }
200*25da2beaSAndroid Build Coastguard Worker
main(int argc,char * argv[])201*25da2beaSAndroid Build Coastguard Worker int main(int argc, char *argv[])
202*25da2beaSAndroid Build Coastguard Worker {
203*25da2beaSAndroid Build Coastguard Worker struct io_uring ring;
204*25da2beaSAndroid Build Coastguard Worker int i, ret;
205*25da2beaSAndroid Build Coastguard Worker
206*25da2beaSAndroid Build Coastguard Worker if (argc > 1)
207*25da2beaSAndroid Build Coastguard Worker return 0;
208*25da2beaSAndroid Build Coastguard Worker
209*25da2beaSAndroid Build Coastguard Worker ret = io_uring_queue_init(100, &ring, 0);
210*25da2beaSAndroid Build Coastguard Worker if (ret) {
211*25da2beaSAndroid Build Coastguard Worker printf("ring setup failed\n");
212*25da2beaSAndroid Build Coastguard Worker return 1;
213*25da2beaSAndroid Build Coastguard Worker }
214*25da2beaSAndroid Build Coastguard Worker
215*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 1000; i++) {
216*25da2beaSAndroid Build Coastguard Worker ret = test_link_drain_one(&ring);
217*25da2beaSAndroid Build Coastguard Worker if (ret) {
218*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "test_link_drain_one failed\n");
219*25da2beaSAndroid Build Coastguard Worker break;
220*25da2beaSAndroid Build Coastguard Worker }
221*25da2beaSAndroid Build Coastguard Worker ret = test_link_drain_multi(&ring);
222*25da2beaSAndroid Build Coastguard Worker if (ret) {
223*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "test_link_drain_multi failed\n");
224*25da2beaSAndroid Build Coastguard Worker break;
225*25da2beaSAndroid Build Coastguard Worker }
226*25da2beaSAndroid Build Coastguard Worker }
227*25da2beaSAndroid Build Coastguard Worker
228*25da2beaSAndroid Build Coastguard Worker return ret;
229*25da2beaSAndroid Build Coastguard Worker }
230