xref: /aosp_15_r20/external/liburing/test/ringbuf-read.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker  * Description: ring mapped provided buffers with reads
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 "liburing.h"
14*25da2beaSAndroid Build Coastguard Worker #include "helpers.h"
15*25da2beaSAndroid Build Coastguard Worker 
16*25da2beaSAndroid Build Coastguard Worker #define BUF_SIZE	4096
17*25da2beaSAndroid Build Coastguard Worker #define NR_BUFS		64
18*25da2beaSAndroid Build Coastguard Worker #define FSIZE		(BUF_SIZE * NR_BUFS)
19*25da2beaSAndroid Build Coastguard Worker 
20*25da2beaSAndroid Build Coastguard Worker #define BR_MASK		(NR_BUFS - 1)
21*25da2beaSAndroid Build Coastguard Worker 
22*25da2beaSAndroid Build Coastguard Worker static int no_buf_ring;
23*25da2beaSAndroid Build Coastguard Worker 
verify_buffer(char * buf,char val)24*25da2beaSAndroid Build Coastguard Worker static int verify_buffer(char *buf, char val)
25*25da2beaSAndroid Build Coastguard Worker {
26*25da2beaSAndroid Build Coastguard Worker 	int i;
27*25da2beaSAndroid Build Coastguard Worker 
28*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < BUF_SIZE; i++) {
29*25da2beaSAndroid Build Coastguard Worker 		if (buf[i] != val) {
30*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "got %d, wanted %d\n", buf[i], val);
31*25da2beaSAndroid Build Coastguard Worker 			return 1;
32*25da2beaSAndroid Build Coastguard Worker 		}
33*25da2beaSAndroid Build Coastguard Worker 	}
34*25da2beaSAndroid Build Coastguard Worker 
35*25da2beaSAndroid Build Coastguard Worker 	return 0;
36*25da2beaSAndroid Build Coastguard Worker }
37*25da2beaSAndroid Build Coastguard Worker 
test(const char * filename,int dio,int async)38*25da2beaSAndroid Build Coastguard Worker static int test(const char *filename, int dio, int async)
39*25da2beaSAndroid Build Coastguard Worker {
40*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_buf_reg reg = { };
41*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
42*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
43*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
44*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_buf_ring *br;
45*25da2beaSAndroid Build Coastguard Worker 	int ret, fd, i;
46*25da2beaSAndroid Build Coastguard Worker 	char *buf;
47*25da2beaSAndroid Build Coastguard Worker 	void *ptr;
48*25da2beaSAndroid Build Coastguard Worker 
49*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(NR_BUFS, &ring, 0);
50*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
51*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "ring setup failed: %d\n", ret);
52*25da2beaSAndroid Build Coastguard Worker 		return 1;
53*25da2beaSAndroid Build Coastguard Worker 	}
54*25da2beaSAndroid Build Coastguard Worker 
55*25da2beaSAndroid Build Coastguard Worker 	if (dio)
56*25da2beaSAndroid Build Coastguard Worker 		fd = open(filename, O_DIRECT | O_RDONLY);
57*25da2beaSAndroid Build Coastguard Worker 	else
58*25da2beaSAndroid Build Coastguard Worker 		fd = open(filename, O_RDONLY);
59*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
60*25da2beaSAndroid Build Coastguard Worker 		perror("open");
61*25da2beaSAndroid Build Coastguard Worker 		return 1;
62*25da2beaSAndroid Build Coastguard Worker 	}
63*25da2beaSAndroid Build Coastguard Worker 
64*25da2beaSAndroid Build Coastguard Worker 	posix_fadvise(fd, 0, FSIZE, POSIX_FADV_DONTNEED);
65*25da2beaSAndroid Build Coastguard Worker 
66*25da2beaSAndroid Build Coastguard Worker 	if (posix_memalign((void **) &buf, 4096, FSIZE))
67*25da2beaSAndroid Build Coastguard Worker 		return 1;
68*25da2beaSAndroid Build Coastguard Worker 	if (posix_memalign((void **) &br, 4096, 4096))
69*25da2beaSAndroid Build Coastguard Worker 		return 1;
70*25da2beaSAndroid Build Coastguard Worker 
71*25da2beaSAndroid Build Coastguard Worker 	reg.ring_addr = (unsigned long) br;
72*25da2beaSAndroid Build Coastguard Worker 	reg.ring_entries = NR_BUFS;
73*25da2beaSAndroid Build Coastguard Worker 	reg.bgid = 1;
74*25da2beaSAndroid Build Coastguard Worker 
75*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_register_buf_ring(&ring, &reg, 0);
76*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
77*25da2beaSAndroid Build Coastguard Worker 		if (ret == -EINVAL) {
78*25da2beaSAndroid Build Coastguard Worker 			no_buf_ring = 1;
79*25da2beaSAndroid Build Coastguard Worker 			return 0;
80*25da2beaSAndroid Build Coastguard Worker 		}
81*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Buffer ring register failed %d\n", ret);
82*25da2beaSAndroid Build Coastguard Worker 		return 1;
83*25da2beaSAndroid Build Coastguard Worker 	}
84*25da2beaSAndroid Build Coastguard Worker 
85*25da2beaSAndroid Build Coastguard Worker 	ptr = buf;
86*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < NR_BUFS; i++) {
87*25da2beaSAndroid Build Coastguard Worker 		io_uring_buf_ring_add(br, ptr, BUF_SIZE, i + 1, BR_MASK, i);
88*25da2beaSAndroid Build Coastguard Worker 		ptr += BUF_SIZE;
89*25da2beaSAndroid Build Coastguard Worker 	}
90*25da2beaSAndroid Build Coastguard Worker 	io_uring_buf_ring_advance(br, NR_BUFS);
91*25da2beaSAndroid Build Coastguard Worker 
92*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < NR_BUFS; i++) {
93*25da2beaSAndroid Build Coastguard Worker 		sqe = io_uring_get_sqe(&ring);
94*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_read(sqe, fd, NULL, BUF_SIZE, i * BUF_SIZE);
95*25da2beaSAndroid Build Coastguard Worker 		sqe->buf_group = 1;
96*25da2beaSAndroid Build Coastguard Worker 		sqe->flags |= IOSQE_BUFFER_SELECT;
97*25da2beaSAndroid Build Coastguard Worker 		if (async && !(i & 1))
98*25da2beaSAndroid Build Coastguard Worker 			sqe->flags |= IOSQE_ASYNC;
99*25da2beaSAndroid Build Coastguard Worker 		sqe->user_data = i + 1;
100*25da2beaSAndroid Build Coastguard Worker 	}
101*25da2beaSAndroid Build Coastguard Worker 
102*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(&ring);
103*25da2beaSAndroid Build Coastguard Worker 	if (ret != NR_BUFS) {
104*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit: %d\n", ret);
105*25da2beaSAndroid Build Coastguard Worker 		return 1;
106*25da2beaSAndroid Build Coastguard Worker 	}
107*25da2beaSAndroid Build Coastguard Worker 
108*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < NR_BUFS; i++) {
109*25da2beaSAndroid Build Coastguard Worker 		int bid, ud;
110*25da2beaSAndroid Build Coastguard Worker 
111*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(&ring, &cqe);
112*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
113*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait cqe failed %d\n", ret);
114*25da2beaSAndroid Build Coastguard Worker 			return 1;
115*25da2beaSAndroid Build Coastguard Worker 		}
116*25da2beaSAndroid Build Coastguard Worker 		if (cqe->res != BUF_SIZE) {
117*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "cqe res %d\n", cqe->res);
118*25da2beaSAndroid Build Coastguard Worker 			return 1;
119*25da2beaSAndroid Build Coastguard Worker 		}
120*25da2beaSAndroid Build Coastguard Worker 		if (!(cqe->flags & IORING_CQE_F_BUFFER)) {
121*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "no buffer selected\n");
122*25da2beaSAndroid Build Coastguard Worker 			return 1;
123*25da2beaSAndroid Build Coastguard Worker 		}
124*25da2beaSAndroid Build Coastguard Worker 		bid = cqe->flags >> IORING_CQE_BUFFER_SHIFT;
125*25da2beaSAndroid Build Coastguard Worker 		ud = cqe->user_data;
126*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(&ring, cqe);
127*25da2beaSAndroid Build Coastguard Worker 		if (verify_buffer(buf + ((bid - 1) * BUF_SIZE), ud))
128*25da2beaSAndroid Build Coastguard Worker 			return 1;
129*25da2beaSAndroid Build Coastguard Worker 	}
130*25da2beaSAndroid Build Coastguard Worker 
131*25da2beaSAndroid Build Coastguard Worker 	return 0;
132*25da2beaSAndroid Build Coastguard Worker }
133*25da2beaSAndroid Build Coastguard Worker 
main(int argc,char * argv[])134*25da2beaSAndroid Build Coastguard Worker int main(int argc, char *argv[])
135*25da2beaSAndroid Build Coastguard Worker {
136*25da2beaSAndroid Build Coastguard Worker 	char buf[BUF_SIZE];
137*25da2beaSAndroid Build Coastguard Worker 	char fname[80];
138*25da2beaSAndroid Build Coastguard Worker 	int ret, fd, i, do_unlink;
139*25da2beaSAndroid Build Coastguard Worker 
140*25da2beaSAndroid Build Coastguard Worker 	if (argc > 1) {
141*25da2beaSAndroid Build Coastguard Worker 		strcpy(fname, argv[1]);
142*25da2beaSAndroid Build Coastguard Worker 		do_unlink = 0;
143*25da2beaSAndroid Build Coastguard Worker 	} else {
144*25da2beaSAndroid Build Coastguard Worker 		sprintf(fname, ".ringbuf-read.%d", getpid());
145*25da2beaSAndroid Build Coastguard Worker 		t_create_file(fname, FSIZE);
146*25da2beaSAndroid Build Coastguard Worker 		do_unlink = 1;
147*25da2beaSAndroid Build Coastguard Worker 	}
148*25da2beaSAndroid Build Coastguard Worker 
149*25da2beaSAndroid Build Coastguard Worker 	fd = open(fname, O_WRONLY);
150*25da2beaSAndroid Build Coastguard Worker 	if (fd < 0) {
151*25da2beaSAndroid Build Coastguard Worker 		perror("open");
152*25da2beaSAndroid Build Coastguard Worker 		goto err;
153*25da2beaSAndroid Build Coastguard Worker 	}
154*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < NR_BUFS; i++) {
155*25da2beaSAndroid Build Coastguard Worker 		memset(buf, i + 1, BUF_SIZE);
156*25da2beaSAndroid Build Coastguard Worker 		ret = write(fd, buf, BUF_SIZE);
157*25da2beaSAndroid Build Coastguard Worker 		if (ret != BUF_SIZE) {
158*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "bad file prep write\n");
159*25da2beaSAndroid Build Coastguard Worker 			goto err;
160*25da2beaSAndroid Build Coastguard Worker 		}
161*25da2beaSAndroid Build Coastguard Worker 	}
162*25da2beaSAndroid Build Coastguard Worker 	close(fd);
163*25da2beaSAndroid Build Coastguard Worker 
164*25da2beaSAndroid Build Coastguard Worker 	ret = test(fname, 1, 0);
165*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
166*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "dio test failed\n");
167*25da2beaSAndroid Build Coastguard Worker 		return ret;
168*25da2beaSAndroid Build Coastguard Worker 	}
169*25da2beaSAndroid Build Coastguard Worker 	if (no_buf_ring)
170*25da2beaSAndroid Build Coastguard Worker 		return 0;
171*25da2beaSAndroid Build Coastguard Worker 
172*25da2beaSAndroid Build Coastguard Worker 	ret = test(fname, 0, 0);
173*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
174*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "buffered test failed\n");
175*25da2beaSAndroid Build Coastguard Worker 		return ret;
176*25da2beaSAndroid Build Coastguard Worker 	}
177*25da2beaSAndroid Build Coastguard Worker 
178*25da2beaSAndroid Build Coastguard Worker 	ret = test(fname, 1, 1);
179*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
180*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "dio async test failed\n");
181*25da2beaSAndroid Build Coastguard Worker 		return ret;
182*25da2beaSAndroid Build Coastguard Worker 	}
183*25da2beaSAndroid Build Coastguard Worker 
184*25da2beaSAndroid Build Coastguard Worker 	ret = test(fname, 0, 1);
185*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
186*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "buffered async test failed\n");
187*25da2beaSAndroid Build Coastguard Worker 		return ret;
188*25da2beaSAndroid Build Coastguard Worker 	}
189*25da2beaSAndroid Build Coastguard Worker 
190*25da2beaSAndroid Build Coastguard Worker 	return 0;
191*25da2beaSAndroid Build Coastguard Worker err:
192*25da2beaSAndroid Build Coastguard Worker 	if (do_unlink)
193*25da2beaSAndroid Build Coastguard Worker 		unlink(fname);
194*25da2beaSAndroid Build Coastguard Worker 	return 1;
195*25da2beaSAndroid Build Coastguard Worker }
196