xref: /aosp_15_r20/external/liburing/test/link_drain.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
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