• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test buffer cloning between rings
4  *
5  */
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <sys/uio.h>
11 
12 #include "liburing.h"
13 #include "helpers.h"
14 
15 #define NR_VECS		64
16 #define BUF_SIZE	8192
17 
18 static int no_buf_clone;
19 
test(int reg_src,int reg_dst)20 static int test(int reg_src, int reg_dst)
21 {
22 	struct iovec vecs[NR_VECS];
23 	struct io_uring src, dst;
24 	int ret, i;
25 
26 	ret = io_uring_queue_init(1, &src, 0);
27 	if (ret) {
28 		fprintf(stderr, "ring_init: %d\n", ret);
29 		return T_EXIT_FAIL;
30 	}
31 	ret = io_uring_queue_init(1, &dst, 0);
32 	if (ret) {
33 		fprintf(stderr, "ring_init: %d\n", ret);
34 		return T_EXIT_FAIL;
35 	}
36 	if (reg_src) {
37 		ret = io_uring_register_ring_fd(&src);
38 		if (ret < 0) {
39 			if (ret == -EINVAL)
40 				return T_EXIT_SKIP;
41 			fprintf(stderr, "register ring: %d\n", ret);
42 			return T_EXIT_FAIL;
43 		}
44 	}
45 	if (reg_dst) {
46 		ret = io_uring_register_ring_fd(&dst);
47 		if (ret < 0) {
48 			if (ret == -EINVAL)
49 				return T_EXIT_SKIP;
50 			fprintf(stderr, "register ring: %d\n", ret);
51 			return T_EXIT_FAIL;
52 		}
53 	}
54 
55 	/* test fail with no buffers in src */
56 	ret = io_uring_clone_buffers(&dst, &src);
57 	if (ret == -EINVAL) {
58 		/* no buffer copy support */
59 		no_buf_clone = true;
60 		return T_EXIT_SKIP;
61 	} else if (ret != -ENXIO) {
62 		fprintf(stderr, "empty copy: %d\n", ret);
63 		return T_EXIT_FAIL;
64 	}
65 
66 	for (i = 0; i < NR_VECS; i++) {
67 		if (posix_memalign(&vecs[i].iov_base, 4096, BUF_SIZE))
68 			return T_EXIT_FAIL;
69 		vecs[i].iov_len = BUF_SIZE;
70 	}
71 
72 	ret = io_uring_register_buffers(&src, vecs, NR_VECS);
73 	if (ret < 0) {
74 		if (ret == -ENOMEM)
75 			return T_EXIT_SKIP;
76 		return T_EXIT_FAIL;
77 	}
78 
79 	/* copy should work now */
80 	ret = io_uring_clone_buffers(&dst, &src);
81 	if (ret) {
82 		fprintf(stderr, "buffer copy: %d\n", ret);
83 		return T_EXIT_FAIL;
84 	}
85 
86 	/* try copy again, should get -EBUSY */
87 	ret = io_uring_clone_buffers(&dst, &src);
88 	if (ret != -EBUSY) {
89 		fprintf(stderr, "busy copy: %d\n", ret);
90 		return T_EXIT_FAIL;
91 	}
92 
93 	ret = io_uring_unregister_buffers(&dst);
94 	if (ret) {
95 		fprintf(stderr, "dst unregister buffers: %d\n", ret);
96 		return T_EXIT_FAIL;
97 	}
98 
99 	ret = io_uring_unregister_buffers(&dst);
100 	if (ret != -ENXIO) {
101 		fprintf(stderr, "dst unregister empty buffers: %d\n", ret);
102 		return T_EXIT_FAIL;
103 	}
104 
105 	ret = io_uring_unregister_buffers(&src);
106 	if (ret) {
107 		fprintf(stderr, "src unregister buffers: %d\n", ret);
108 		return T_EXIT_FAIL;
109 	}
110 
111 	ret = io_uring_register_buffers(&dst, vecs, NR_VECS);
112 	if (ret < 0) {
113 		fprintf(stderr, "register buffers dst; %d\n", ret);
114 		return T_EXIT_FAIL;
115 	}
116 
117 	ret = io_uring_clone_buffers(&src, &dst);
118 	if (ret) {
119 		fprintf(stderr, "buffer copy reverse: %d\n", ret);
120 		return T_EXIT_FAIL;
121 	}
122 
123 	ret = io_uring_unregister_buffers(&dst);
124 	if (ret) {
125 		fprintf(stderr, "dst unregister buffers: %d\n", ret);
126 		return T_EXIT_FAIL;
127 	}
128 
129 	ret = io_uring_unregister_buffers(&dst);
130 	if (ret != -ENXIO) {
131 		fprintf(stderr, "dst unregister empty buffers: %d\n", ret);
132 		return T_EXIT_FAIL;
133 	}
134 
135 	ret = io_uring_unregister_buffers(&src);
136 	if (ret) {
137 		fprintf(stderr, "src unregister buffers: %d\n", ret);
138 		return T_EXIT_FAIL;
139 	}
140 
141 	io_uring_queue_exit(&src);
142 	io_uring_queue_exit(&dst);
143 
144 	for (i = 0; i < NR_VECS; i++)
145 		free(vecs[i].iov_base);
146 
147 	return T_EXIT_PASS;
148 }
149 
test_dummy(void)150 static int test_dummy(void)
151 {
152 	struct iovec vec = { };
153 	struct io_uring src, dst;
154 	int ret;
155 
156 	ret = io_uring_queue_init(1, &src, 0);
157 	if (ret) {
158 		fprintf(stderr, "ring_init: %d\n", ret);
159 		return T_EXIT_FAIL;
160 	}
161 	ret = io_uring_queue_init(1, &dst, 0);
162 	if (ret) {
163 		fprintf(stderr, "ring_init: %d\n", ret);
164 		return T_EXIT_FAIL;
165 	}
166 
167 	ret = io_uring_register_buffers(&src, &vec, 1);
168 	if (ret < 0) {
169 		fprintf(stderr, "failed to register dummy buffer: %d\n", ret);
170 		return T_EXIT_FAIL;
171 	}
172 
173 	ret = io_uring_clone_buffers(&dst, &src);
174 	if (ret) {
175 		fprintf(stderr, "clone dummy buf: %d\n", ret);
176 		return T_EXIT_FAIL;
177 	}
178 
179 	ret = io_uring_unregister_buffers(&src);
180 	if (ret) {
181 		fprintf(stderr, "rsc unregister buffers: %d\n", ret);
182 		return T_EXIT_FAIL;
183 	}
184 
185 	ret = io_uring_unregister_buffers(&dst);
186 	if (ret) {
187 		fprintf(stderr, "dst unregister buffers: %d\n", ret);
188 		return T_EXIT_FAIL;
189 	}
190 
191 	io_uring_queue_exit(&src);
192 	io_uring_queue_exit(&dst);
193 
194 	return T_EXIT_PASS;
195 }
196 
main(int argc,char * argv[])197 int main(int argc, char *argv[])
198 {
199 	int ret;
200 
201 	if (argc > 1)
202 		return T_EXIT_SKIP;
203 
204 	ret = test(0, 0);
205 	if (ret == T_EXIT_SKIP) {
206 		return T_EXIT_SKIP;
207 	} else if (ret != T_EXIT_PASS) {
208 		fprintf(stderr, "test 0 0 failed\n");
209 		return T_EXIT_FAIL;
210 	}
211 	if (no_buf_clone)
212 		return T_EXIT_SKIP;
213 
214 	ret = test(0, 1);
215 	if (ret == T_EXIT_SKIP) {
216 		return T_EXIT_SKIP;
217 	} else if (ret != T_EXIT_PASS) {
218 		fprintf(stderr, "test 0 1 failed\n");
219 		return T_EXIT_FAIL;
220 	}
221 
222 	ret = test(1, 0);
223 	if (ret == T_EXIT_SKIP) {
224 		return T_EXIT_SKIP;
225 	} else if (ret != T_EXIT_PASS) {
226 		fprintf(stderr, "test 1 0 failed\n");
227 		return T_EXIT_FAIL;
228 	}
229 
230 	ret = test(1, 1);
231 	if (ret == T_EXIT_SKIP) {
232 		return T_EXIT_SKIP;
233 	} else if (ret != T_EXIT_PASS) {
234 		fprintf(stderr, "test 1 1 failed\n");
235 		return T_EXIT_FAIL;
236 	}
237 
238 	ret = test_dummy();
239 	if (ret == T_EXIT_SKIP) {
240 		return T_EXIT_SKIP;
241 	} else if (ret != T_EXIT_PASS) {
242 		fprintf(stderr, "test_dummy failed\n");
243 		return T_EXIT_FAIL;
244 	}
245 
246 	return T_EXIT_PASS;
247 }
248