xref: /aosp_15_r20/external/liburing/test/msg-ring.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test ring messaging command
4  *
5  */
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <pthread.h>
13 
14 #include "liburing.h"
15 
16 static int no_msg;
17 
test_own(struct io_uring * ring)18 static int test_own(struct io_uring *ring)
19 {
20 	struct io_uring_cqe *cqe;
21 	struct io_uring_sqe *sqe;
22 	int ret, i;
23 
24 	sqe = io_uring_get_sqe(ring);
25 	if (!sqe) {
26 		fprintf(stderr, "get sqe failed\n");
27 		goto err;
28 	}
29 
30 	io_uring_prep_msg_ring(sqe, ring->ring_fd, 0x10, 0x1234, 0);
31 	sqe->user_data = 1;
32 
33 	ret = io_uring_submit(ring);
34 	if (ret <= 0) {
35 		fprintf(stderr, "sqe submit failed: %d\n", ret);
36 		goto err;
37 	}
38 
39 	for (i = 0; i < 2; i++) {
40 		ret = io_uring_wait_cqe(ring, &cqe);
41 		if (ret < 0) {
42 			fprintf(stderr, "wait completion %d\n", ret);
43 			goto err;
44 		}
45 		switch (cqe->user_data) {
46 		case 1:
47 			if (cqe->res == -EINVAL || cqe->res == -EOPNOTSUPP) {
48 				no_msg = 1;
49 				return 0;
50 			}
51 			if (cqe->res != 0) {
52 				fprintf(stderr, "cqe res %d\n", cqe->res);
53 				return -1;
54 			}
55 			break;
56 		case 0x1234:
57 			if (cqe->res != 0x10) {
58 				fprintf(stderr, "invalid len %x\n", cqe->res);
59 				return -1;
60 			}
61 			break;
62 		default:
63 			fprintf(stderr, "Invalid user_data\n");
64 			return -1;
65 		}
66 		io_uring_cqe_seen(ring, cqe);
67 	}
68 
69 	return 0;
70 err:
71 	return 1;
72 }
73 
wait_cqe_fn(void * data)74 static void *wait_cqe_fn(void *data)
75 {
76 	struct io_uring *ring = data;
77 	struct io_uring_cqe *cqe;
78 	int ret;
79 
80 	ret = io_uring_wait_cqe(ring, &cqe);
81 	if (ret) {
82 		fprintf(stderr, "wait cqe %d\n", ret);
83 		goto err;
84 	}
85 
86 	if (cqe->user_data != 0x5aa5) {
87 		fprintf(stderr, "user_data %llx\n", (long long) cqe->user_data);
88 		goto err;
89 	}
90 	if (cqe->res != 0x20) {
91 		fprintf(stderr, "len %x\n", cqe->res);
92 		goto err;
93 	}
94 
95 	return NULL;
96 err:
97 	return (void *) (unsigned long) 1;
98 }
99 
test_remote(struct io_uring * ring,struct io_uring * target)100 static int test_remote(struct io_uring *ring, struct io_uring *target)
101 {
102 	struct io_uring_cqe *cqe;
103 	struct io_uring_sqe *sqe;
104 	int ret;
105 
106 	sqe = io_uring_get_sqe(ring);
107 	if (!sqe) {
108 		fprintf(stderr, "get sqe failed\n");
109 		goto err;
110 	}
111 
112 	io_uring_prep_msg_ring(sqe, target->ring_fd, 0x20, 0x5aa5, 0);
113 	sqe->user_data = 1;
114 
115 	ret = io_uring_submit(ring);
116 	if (ret <= 0) {
117 		fprintf(stderr, "sqe submit failed: %d\n", ret);
118 		goto err;
119 	}
120 
121 	ret = io_uring_wait_cqe(ring, &cqe);
122 	if (ret < 0) {
123 		fprintf(stderr, "wait completion %d\n", ret);
124 		goto err;
125 	}
126 	if (cqe->res != 0) {
127 		fprintf(stderr, "cqe res %d\n", cqe->res);
128 		return -1;
129 	}
130 	if (cqe->user_data != 1) {
131 		fprintf(stderr, "user_data %llx\n", (long long) cqe->user_data);
132 		return -1;
133 	}
134 
135 	io_uring_cqe_seen(ring, cqe);
136 	return 0;
137 err:
138 	return 1;
139 }
140 
test_invalid(struct io_uring * ring)141 static int test_invalid(struct io_uring *ring)
142 {
143 	struct io_uring_cqe *cqe;
144 	struct io_uring_sqe *sqe;
145 	int ret;
146 
147 	sqe = io_uring_get_sqe(ring);
148 	if (!sqe) {
149 		fprintf(stderr, "get sqe failed\n");
150 		goto err;
151 	}
152 
153 	io_uring_prep_msg_ring(sqe, 1, 0, 0x8989, 0);
154 	sqe->user_data = 1;
155 
156 	ret = io_uring_submit(ring);
157 	if (ret <= 0) {
158 		fprintf(stderr, "sqe submit failed: %d\n", ret);
159 		goto err;
160 	}
161 
162 	ret = io_uring_wait_cqe(ring, &cqe);
163 	if (ret < 0) {
164 		fprintf(stderr, "wait completion %d\n", ret);
165 		goto err;
166 	}
167 	if (cqe->res != -EBADFD) {
168 		fprintf(stderr, "cqe res %d\n", cqe->res);
169 		return -1;
170 	}
171 
172 	io_uring_cqe_seen(ring, cqe);
173 	return 0;
174 err:
175 	return 1;
176 }
177 
main(int argc,char * argv[])178 int main(int argc, char *argv[])
179 {
180 	struct io_uring ring, ring2, pring;
181 	pthread_t thread;
182 	void *tret;
183 	int ret;
184 
185 	if (argc > 1)
186 		return 0;
187 
188 	ret = io_uring_queue_init(8, &ring, 0);
189 	if (ret) {
190 		fprintf(stderr, "ring setup failed: %d\n", ret);
191 		return 1;
192 	}
193 	ret = io_uring_queue_init(8, &ring2, 0);
194 	if (ret) {
195 		fprintf(stderr, "ring setup failed: %d\n", ret);
196 		return 1;
197 	}
198 	ret = io_uring_queue_init(8, &pring, IORING_SETUP_IOPOLL);
199 	if (ret) {
200 		fprintf(stderr, "ring setup failed: %d\n", ret);
201 		return 1;
202 	}
203 
204 	ret = test_own(&ring);
205 	if (ret) {
206 		fprintf(stderr, "test_own failed\n");
207 		return ret;
208 	}
209 	if (no_msg) {
210 		fprintf(stdout, "Skipped\n");
211 		return 0;
212 	}
213 	ret = test_own(&pring);
214 	if (ret) {
215 		fprintf(stderr, "test_own iopoll failed\n");
216 		return ret;
217 	}
218 
219 	ret = test_invalid(&ring);
220 	if (ret) {
221 		fprintf(stderr, "test_invalid failed\n");
222 		return ret;
223 	}
224 
225 	pthread_create(&thread, NULL, wait_cqe_fn, &ring2);
226 
227 	ret = test_remote(&ring, &ring2);
228 	if (ret) {
229 		fprintf(stderr, "test_remote failed\n");
230 		return ret;
231 	}
232 
233 	pthread_join(thread, &tret);
234 
235 	return 0;
236 }
237