uringmachine 0.4 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +2 -1
- data/CHANGELOG.md +16 -0
- data/README.md +44 -1
- data/TODO.md +12 -3
- data/examples/bm_snooze.rb +89 -0
- data/examples/bm_sqlite.rb +89 -0
- data/examples/bm_write.rb +56 -0
- data/examples/dns_client.rb +12 -0
- data/examples/http_server.rb +42 -43
- data/examples/pg.rb +85 -0
- data/examples/server_client.rb +64 -0
- data/examples/snooze.rb +44 -0
- data/examples/stream.rb +85 -0
- data/examples/write_dev_null.rb +16 -0
- data/ext/um/extconf.rb +81 -14
- data/ext/um/um.c +468 -414
- data/ext/um/um.h +149 -40
- data/ext/um/um_async_op.c +40 -0
- data/ext/um/um_async_op_class.c +136 -0
- data/ext/um/um_buffer.c +49 -0
- data/ext/um/um_class.c +176 -44
- data/ext/um/um_const.c +174 -9
- data/ext/um/um_ext.c +8 -0
- data/ext/um/um_mutex_class.c +47 -0
- data/ext/um/um_op.c +89 -111
- data/ext/um/um_queue_class.c +58 -0
- data/ext/um/um_ssl.c +850 -0
- data/ext/um/um_ssl.h +22 -0
- data/ext/um/um_ssl_class.c +138 -0
- data/ext/um/um_sync.c +273 -0
- data/ext/um/um_utils.c +1 -1
- data/lib/uringmachine/dns_resolver.rb +84 -0
- data/lib/uringmachine/ssl/context_builder.rb +96 -0
- data/lib/uringmachine/ssl.rb +394 -0
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +27 -3
- data/supressions/ruby.supp +71 -0
- data/test/helper.rb +6 -0
- data/test/test_async_op.rb +119 -0
- data/test/test_ssl.rb +155 -0
- data/test/test_um.rb +464 -47
- data/uringmachine.gemspec +3 -2
- data/vendor/liburing/.gitignore +5 -0
- data/vendor/liburing/CHANGELOG +1 -0
- data/vendor/liburing/configure +32 -0
- data/vendor/liburing/examples/Makefile +1 -0
- data/vendor/liburing/examples/reg-wait.c +159 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/include/liburing/io_uring.h +48 -2
- data/vendor/liburing/src/include/liburing.h +28 -2
- data/vendor/liburing/src/int_flags.h +10 -3
- data/vendor/liburing/src/liburing-ffi.map +13 -2
- data/vendor/liburing/src/liburing.map +9 -0
- data/vendor/liburing/src/queue.c +25 -16
- data/vendor/liburing/src/register.c +73 -4
- data/vendor/liburing/src/setup.c +46 -18
- data/vendor/liburing/src/setup.h +6 -0
- data/vendor/liburing/test/Makefile +7 -0
- data/vendor/liburing/test/cmd-discard.c +427 -0
- data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
- data/vendor/liburing/test/file-exit-unreg.c +48 -0
- data/vendor/liburing/test/io_uring_passthrough.c +2 -0
- data/vendor/liburing/test/io_uring_register.c +13 -2
- data/vendor/liburing/test/napi-test.c +1 -1
- data/vendor/liburing/test/no-mmap-inval.c +1 -1
- data/vendor/liburing/test/read-mshot-empty.c +2 -0
- data/vendor/liburing/test/read-mshot-stdin.c +121 -0
- data/vendor/liburing/test/read-mshot.c +6 -0
- data/vendor/liburing/test/recvsend_bundle.c +2 -2
- data/vendor/liburing/test/reg-fd-only.c +1 -1
- data/vendor/liburing/test/reg-wait.c +251 -0
- data/vendor/liburing/test/regbuf-clone.c +458 -0
- data/vendor/liburing/test/resize-rings.c +643 -0
- data/vendor/liburing/test/rsrc_tags.c +1 -1
- data/vendor/liburing/test/sqpoll-sleep.c +39 -8
- data/vendor/liburing/test/sqwait.c +136 -0
- data/vendor/liburing/test/sync-cancel.c +8 -1
- data/vendor/liburing/test/timeout.c +13 -8
- metadata +52 -8
- data/examples/http_server_multishot.rb +0 -57
- data/examples/http_server_simpler.rb +0 -34
@@ -8,6 +8,10 @@
|
|
8
8
|
#include <unistd.h>
|
9
9
|
#include <stdlib.h>
|
10
10
|
#include <sys/uio.h>
|
11
|
+
#include <string.h>
|
12
|
+
#include <limits.h>
|
13
|
+
#include <sys/mman.h>
|
14
|
+
#include <linux/mman.h>
|
11
15
|
|
12
16
|
#include "liburing.h"
|
13
17
|
#include "helpers.h"
|
@@ -15,6 +19,295 @@
|
|
15
19
|
#define NR_VECS 64
|
16
20
|
#define BUF_SIZE 8192
|
17
21
|
|
22
|
+
static int no_buf_clone;
|
23
|
+
static int no_buf_offset;
|
24
|
+
|
25
|
+
static void fdinfo_read(struct io_uring *ring)
|
26
|
+
{
|
27
|
+
char fd_name[128];
|
28
|
+
char *buf;
|
29
|
+
int fd;
|
30
|
+
|
31
|
+
buf = malloc(4096);
|
32
|
+
|
33
|
+
sprintf(fd_name, "/proc/self/fdinfo/%d", ring->ring_fd);
|
34
|
+
fd = open(fd_name, O_RDONLY);
|
35
|
+
if (fd < 0) {
|
36
|
+
perror("open");
|
37
|
+
return;
|
38
|
+
}
|
39
|
+
|
40
|
+
do {
|
41
|
+
int ret = read(fd, buf, 4096);
|
42
|
+
|
43
|
+
if (ret < 0) {
|
44
|
+
perror("fdinfo read");
|
45
|
+
break;
|
46
|
+
} else if (ret == 4096) {
|
47
|
+
continue;
|
48
|
+
}
|
49
|
+
break;
|
50
|
+
} while (1);
|
51
|
+
|
52
|
+
close(fd);
|
53
|
+
free(buf);
|
54
|
+
}
|
55
|
+
|
56
|
+
static int use_buf(struct io_uring *ring, void *addr, int index)
|
57
|
+
{
|
58
|
+
struct io_uring_sqe *sqe;
|
59
|
+
struct io_uring_cqe *cqe;
|
60
|
+
char src_buf[32];
|
61
|
+
int fds[2], ret;
|
62
|
+
|
63
|
+
fdinfo_read(ring);
|
64
|
+
|
65
|
+
if (pipe(fds) < 0)
|
66
|
+
return -errno;
|
67
|
+
|
68
|
+
memset(src_buf, 0xbb, sizeof(src_buf));
|
69
|
+
|
70
|
+
sqe = io_uring_get_sqe(ring);
|
71
|
+
io_uring_prep_read_fixed(sqe, fds[0], addr, sizeof(src_buf), 0, index);
|
72
|
+
io_uring_submit(ring);
|
73
|
+
|
74
|
+
ret = write(fds[1], src_buf, sizeof(src_buf));
|
75
|
+
if (ret < 0)
|
76
|
+
return -errno;
|
77
|
+
|
78
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
79
|
+
if (ret) {
|
80
|
+
fprintf(stderr, "wait_cqe: %d\n", ret);
|
81
|
+
return ret;
|
82
|
+
}
|
83
|
+
|
84
|
+
ret = cqe->res;
|
85
|
+
io_uring_cqe_seen(ring, cqe);
|
86
|
+
if (ret < 0)
|
87
|
+
return ret;
|
88
|
+
close(fds[0]);
|
89
|
+
close(fds[1]);
|
90
|
+
return 0;
|
91
|
+
}
|
92
|
+
|
93
|
+
static int test_offsets(void)
|
94
|
+
{
|
95
|
+
struct iovec vecs[NR_VECS];
|
96
|
+
struct io_uring src, dst;
|
97
|
+
unsigned int i, offset, nr;
|
98
|
+
int ret;
|
99
|
+
|
100
|
+
ret = io_uring_queue_init(1, &src, 0);
|
101
|
+
if (ret) {
|
102
|
+
fprintf(stderr, "ring_init: %d\n", ret);
|
103
|
+
return T_EXIT_FAIL;
|
104
|
+
}
|
105
|
+
ret = io_uring_queue_init(1, &dst, 0);
|
106
|
+
if (ret) {
|
107
|
+
fprintf(stderr, "ring_init: %d\n", ret);
|
108
|
+
return T_EXIT_FAIL;
|
109
|
+
}
|
110
|
+
|
111
|
+
for (i = 0; i < NR_VECS; i++) {
|
112
|
+
if (posix_memalign(&vecs[i].iov_base, 4096, BUF_SIZE))
|
113
|
+
return T_EXIT_FAIL;
|
114
|
+
vecs[i].iov_len = BUF_SIZE;
|
115
|
+
}
|
116
|
+
|
117
|
+
ret = io_uring_register_buffers(&src, vecs, NR_VECS);
|
118
|
+
if (ret < 0) {
|
119
|
+
if (ret == -ENOMEM)
|
120
|
+
return T_EXIT_SKIP;
|
121
|
+
return T_EXIT_FAIL;
|
122
|
+
}
|
123
|
+
|
124
|
+
/* clone half the buffers, src offset 0, but ask for too many */
|
125
|
+
offset = NR_VECS / 2;
|
126
|
+
nr = NR_VECS;
|
127
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, 0, offset, nr, 0);
|
128
|
+
if (ret != -EOVERFLOW) {
|
129
|
+
if (ret == -EINVAL) {
|
130
|
+
no_buf_offset = 1;
|
131
|
+
return T_EXIT_SKIP;
|
132
|
+
}
|
133
|
+
fprintf(stderr, "Offset and too big total failed: %d\n", ret);
|
134
|
+
return T_EXIT_FAIL;
|
135
|
+
}
|
136
|
+
|
137
|
+
/* ask for too many buffers */
|
138
|
+
nr = NR_VECS + 1;
|
139
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, 0, 0, nr, 0);
|
140
|
+
if (ret != -EINVAL) {
|
141
|
+
fprintf(stderr, "Too many buffers total failed: %d\n", ret);
|
142
|
+
return T_EXIT_FAIL;
|
143
|
+
}
|
144
|
+
|
145
|
+
/* clone half the buffers into start of src offset */
|
146
|
+
nr = NR_VECS / 2;
|
147
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, 0, nr, nr, 0);
|
148
|
+
if (ret) {
|
149
|
+
fprintf(stderr, "Half clone with offset failed: %d\n", ret);
|
150
|
+
return T_EXIT_FAIL;
|
151
|
+
}
|
152
|
+
|
153
|
+
/* 'nr' offset should be 0 on the src side */
|
154
|
+
ret = use_buf(&dst, vecs[nr].iov_base, 0);
|
155
|
+
if (ret) {
|
156
|
+
fprintf(stderr, "1 use_buf=%d\n", ret);
|
157
|
+
return T_EXIT_FAIL;
|
158
|
+
}
|
159
|
+
|
160
|
+
ret = io_uring_unregister_buffers(&dst);
|
161
|
+
if (ret) {
|
162
|
+
fprintf(stderr, "Failed to unregister partial dst: %d\n", ret);
|
163
|
+
return T_EXIT_FAIL;
|
164
|
+
}
|
165
|
+
|
166
|
+
ret = use_buf(&dst, vecs[0].iov_base, 0);
|
167
|
+
if (ret != -EFAULT) {
|
168
|
+
fprintf(stderr, "2 use_buf=%d\n", ret);
|
169
|
+
return T_EXIT_FAIL;
|
170
|
+
}
|
171
|
+
|
172
|
+
/* clone half the buffers into middle of src offset */
|
173
|
+
nr = NR_VECS / 2;
|
174
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, nr, nr, nr, 0);
|
175
|
+
if (ret) {
|
176
|
+
fprintf(stderr, "Half buffers and middle offset failed: %d\n", ret);
|
177
|
+
return T_EXIT_FAIL;
|
178
|
+
}
|
179
|
+
|
180
|
+
ret = use_buf(&dst, vecs[0].iov_base, 0);
|
181
|
+
if (ret != -EFAULT) {
|
182
|
+
fprintf(stderr, "3 use_buf=%d\n", ret);
|
183
|
+
return T_EXIT_FAIL;
|
184
|
+
}
|
185
|
+
|
186
|
+
ret = use_buf(&dst, vecs[nr].iov_base, nr);
|
187
|
+
if (ret) {
|
188
|
+
fprintf(stderr, "4 use_buf=%d\n", ret);
|
189
|
+
return T_EXIT_FAIL;
|
190
|
+
}
|
191
|
+
|
192
|
+
ret = io_uring_unregister_buffers(&dst);
|
193
|
+
if (ret) {
|
194
|
+
fprintf(stderr, "Failed to unregister partial dst: %d\n", ret);
|
195
|
+
return T_EXIT_FAIL;
|
196
|
+
}
|
197
|
+
|
198
|
+
/* clone buffers, but specify overflowing dst offset */
|
199
|
+
offset = UINT_MAX - 32;
|
200
|
+
nr = NR_VECS;
|
201
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, 0, offset, nr, 0);
|
202
|
+
if (ret != -EOVERFLOW) {
|
203
|
+
fprintf(stderr, "Overflow dst offset failed: %d\n", ret);
|
204
|
+
return T_EXIT_FAIL;
|
205
|
+
}
|
206
|
+
|
207
|
+
/* clone half the buffers into middle of src offset */
|
208
|
+
nr = NR_VECS / 2;
|
209
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, nr, nr, nr, 0);
|
210
|
+
if (ret) {
|
211
|
+
fprintf(stderr, "Clone half middle src offset failed: %d\n", ret);
|
212
|
+
return T_EXIT_FAIL;
|
213
|
+
}
|
214
|
+
|
215
|
+
ret = use_buf(&dst, vecs[nr].iov_base, nr);
|
216
|
+
if (ret) {
|
217
|
+
fprintf(stderr, "5 use_buf=%d\n", ret);
|
218
|
+
return T_EXIT_FAIL;
|
219
|
+
}
|
220
|
+
|
221
|
+
ret = use_buf(&dst, vecs[0].iov_base, 0);
|
222
|
+
if (ret != -EFAULT) {
|
223
|
+
fprintf(stderr, "5 use_buf=%d\n", ret);
|
224
|
+
return T_EXIT_FAIL;
|
225
|
+
}
|
226
|
+
|
227
|
+
/* should get -EBUSY now, REPLACE not set */
|
228
|
+
nr = NR_VECS / 2;
|
229
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, nr, nr, nr, 0);
|
230
|
+
if (ret != -EBUSY) {
|
231
|
+
fprintf(stderr, "Replace buffers failed: %d\n", ret);
|
232
|
+
return T_EXIT_FAIL;
|
233
|
+
}
|
234
|
+
|
235
|
+
/* now replace the initial 0..n in dst (which are dummy nodes) */
|
236
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, 0, 0, nr, IORING_REGISTER_DST_REPLACE);
|
237
|
+
if (ret) {
|
238
|
+
fprintf(stderr, "Buffer replace failed: %d\n", ret);
|
239
|
+
return T_EXIT_FAIL;
|
240
|
+
}
|
241
|
+
|
242
|
+
ret = use_buf(&dst, vecs[0].iov_base, 0);
|
243
|
+
if (ret) {
|
244
|
+
fprintf(stderr, "6 use_buf=%d\n", ret);
|
245
|
+
return T_EXIT_FAIL;
|
246
|
+
}
|
247
|
+
|
248
|
+
ret = io_uring_unregister_buffers(&dst);
|
249
|
+
if (ret) {
|
250
|
+
fprintf(stderr, "Failed to unregister partial dst: %d\n", ret);
|
251
|
+
return T_EXIT_FAIL;
|
252
|
+
}
|
253
|
+
|
254
|
+
ret = io_uring_register_buffers_sparse(&dst, NR_VECS);
|
255
|
+
if (ret) {
|
256
|
+
fprintf(stderr, "Register sparse buffers failed: %d\n", ret);
|
257
|
+
return T_EXIT_FAIL;
|
258
|
+
}
|
259
|
+
|
260
|
+
/* dst has a full sparse table, replace first NR_VECS / 2 with bufs */
|
261
|
+
nr = NR_VECS / 2;
|
262
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, 0, 0, nr, 0);
|
263
|
+
if (ret != -EBUSY) {
|
264
|
+
fprintf(stderr, "Buffer replace failed: %d\n", ret);
|
265
|
+
return T_EXIT_FAIL;
|
266
|
+
}
|
267
|
+
|
268
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, 0, 0, nr, IORING_REGISTER_DST_REPLACE);
|
269
|
+
if (ret) {
|
270
|
+
fprintf(stderr, "Buffer replace failed: %d\n", ret);
|
271
|
+
return T_EXIT_FAIL;
|
272
|
+
}
|
273
|
+
|
274
|
+
ret = use_buf(&dst, vecs[0].iov_base, 0);
|
275
|
+
if (ret) {
|
276
|
+
fprintf(stderr, "7 use_buf=%d\n", ret);
|
277
|
+
return T_EXIT_FAIL;
|
278
|
+
}
|
279
|
+
|
280
|
+
/* now expand existing dst table, from to NR_VECS + NR_VECS / 2 */
|
281
|
+
nr = NR_VECS;
|
282
|
+
offset = NR_VECS / 2;
|
283
|
+
ret = io_uring_clone_buffers_offset(&dst, &src, offset, 0, nr, IORING_REGISTER_DST_REPLACE);
|
284
|
+
if (ret) {
|
285
|
+
fprintf(stderr, "Buffer replace failed: %d\n", ret);
|
286
|
+
return T_EXIT_FAIL;
|
287
|
+
}
|
288
|
+
|
289
|
+
ret = use_buf(&dst, vecs[0].iov_base, 0);
|
290
|
+
if (ret) {
|
291
|
+
fprintf(stderr, "8 use_buf=%d\n", ret);
|
292
|
+
return T_EXIT_FAIL;
|
293
|
+
}
|
294
|
+
|
295
|
+
offset = NR_VECS + (NR_VECS / 2) - 1;
|
296
|
+
ret = use_buf(&dst, vecs[NR_VECS - 1].iov_base, offset);
|
297
|
+
if (ret) {
|
298
|
+
fprintf(stderr, "8b use_buf=%d\n", ret);
|
299
|
+
return T_EXIT_FAIL;
|
300
|
+
}
|
301
|
+
|
302
|
+
ret = use_buf(&dst, vecs[NR_VECS / 2].iov_base, NR_VECS);
|
303
|
+
if (ret) {
|
304
|
+
fprintf(stderr, "9 use_buf=%d\n", ret);
|
305
|
+
return T_EXIT_FAIL;
|
306
|
+
}
|
307
|
+
|
308
|
+
return T_EXIT_PASS;
|
309
|
+
}
|
310
|
+
|
18
311
|
static int test(int reg_src, int reg_dst)
|
19
312
|
{
|
20
313
|
struct iovec vecs[NR_VECS];
|
@@ -54,6 +347,7 @@ static int test(int reg_src, int reg_dst)
|
|
54
347
|
ret = io_uring_clone_buffers(&dst, &src);
|
55
348
|
if (ret == -EINVAL) {
|
56
349
|
/* no buffer copy support */
|
350
|
+
no_buf_clone = true;
|
57
351
|
return T_EXIT_SKIP;
|
58
352
|
} else if (ret != -ENXIO) {
|
59
353
|
fprintf(stderr, "empty copy: %d\n", ret);
|
@@ -73,6 +367,18 @@ static int test(int reg_src, int reg_dst)
|
|
73
367
|
return T_EXIT_FAIL;
|
74
368
|
}
|
75
369
|
|
370
|
+
ret = use_buf(&src, vecs[0].iov_base, 0);
|
371
|
+
if (ret) {
|
372
|
+
fprintf(stderr, "use_buf=%d\n", ret);
|
373
|
+
return T_EXIT_FAIL;
|
374
|
+
}
|
375
|
+
|
376
|
+
ret = use_buf(&dst, vecs[0].iov_base, 0);
|
377
|
+
if (ret != -EFAULT) {
|
378
|
+
fprintf(stderr, "use_buf=%d\n", ret);
|
379
|
+
return T_EXIT_FAIL;
|
380
|
+
}
|
381
|
+
|
76
382
|
/* copy should work now */
|
77
383
|
ret = io_uring_clone_buffers(&dst, &src);
|
78
384
|
if (ret) {
|
@@ -80,6 +386,12 @@ static int test(int reg_src, int reg_dst)
|
|
80
386
|
return T_EXIT_FAIL;
|
81
387
|
}
|
82
388
|
|
389
|
+
ret = use_buf(&dst, vecs[NR_VECS / 2].iov_base, NR_VECS / 2);
|
390
|
+
if (ret) {
|
391
|
+
fprintf(stderr, "use_buf=%d\n", ret);
|
392
|
+
return T_EXIT_FAIL;
|
393
|
+
}
|
394
|
+
|
83
395
|
/* try copy again, should get -EBUSY */
|
84
396
|
ret = io_uring_clone_buffers(&dst, &src);
|
85
397
|
if (ret != -EBUSY) {
|
@@ -93,18 +405,36 @@ static int test(int reg_src, int reg_dst)
|
|
93
405
|
return T_EXIT_FAIL;
|
94
406
|
}
|
95
407
|
|
408
|
+
ret = use_buf(&dst, vecs[NR_VECS / 2].iov_base, NR_VECS / 2);
|
409
|
+
if (ret != -EFAULT) {
|
410
|
+
fprintf(stderr, "use_buf=%d\n", ret);
|
411
|
+
return T_EXIT_FAIL;
|
412
|
+
}
|
413
|
+
|
96
414
|
ret = io_uring_unregister_buffers(&dst);
|
97
415
|
if (ret != -ENXIO) {
|
98
416
|
fprintf(stderr, "dst unregister empty buffers: %d\n", ret);
|
99
417
|
return T_EXIT_FAIL;
|
100
418
|
}
|
101
419
|
|
420
|
+
ret = use_buf(&src, vecs[NR_VECS / 2].iov_base, NR_VECS / 2);
|
421
|
+
if (ret) {
|
422
|
+
fprintf(stderr, "use_buf=%d\n", ret);
|
423
|
+
return T_EXIT_FAIL;
|
424
|
+
}
|
425
|
+
|
102
426
|
ret = io_uring_unregister_buffers(&src);
|
103
427
|
if (ret) {
|
104
428
|
fprintf(stderr, "src unregister buffers: %d\n", ret);
|
105
429
|
return T_EXIT_FAIL;
|
106
430
|
}
|
107
431
|
|
432
|
+
ret = use_buf(&src, vecs[NR_VECS / 2].iov_base, NR_VECS / 2);
|
433
|
+
if (ret != -EFAULT) {
|
434
|
+
fprintf(stderr, "use_buf=%d\n", ret);
|
435
|
+
return T_EXIT_FAIL;
|
436
|
+
}
|
437
|
+
|
108
438
|
ret = io_uring_register_buffers(&dst, vecs, NR_VECS);
|
109
439
|
if (ret < 0) {
|
110
440
|
fprintf(stderr, "register buffers dst; %d\n", ret);
|
@@ -144,6 +474,108 @@ static int test(int reg_src, int reg_dst)
|
|
144
474
|
return T_EXIT_PASS;
|
145
475
|
}
|
146
476
|
|
477
|
+
static int test_dummy(void)
|
478
|
+
{
|
479
|
+
struct iovec vec = { };
|
480
|
+
struct io_uring src, dst;
|
481
|
+
int ret;
|
482
|
+
|
483
|
+
ret = io_uring_queue_init(1, &src, 0);
|
484
|
+
if (ret) {
|
485
|
+
fprintf(stderr, "ring_init: %d\n", ret);
|
486
|
+
return T_EXIT_FAIL;
|
487
|
+
}
|
488
|
+
ret = io_uring_queue_init(1, &dst, 0);
|
489
|
+
if (ret) {
|
490
|
+
fprintf(stderr, "ring_init: %d\n", ret);
|
491
|
+
return T_EXIT_FAIL;
|
492
|
+
}
|
493
|
+
|
494
|
+
ret = io_uring_register_buffers(&src, &vec, 1);
|
495
|
+
if (ret < 0) {
|
496
|
+
fprintf(stderr, "failed to register dummy buffer: %d\n", ret);
|
497
|
+
return T_EXIT_FAIL;
|
498
|
+
}
|
499
|
+
|
500
|
+
ret = io_uring_clone_buffers(&dst, &src);
|
501
|
+
if (ret) {
|
502
|
+
fprintf(stderr, "clone dummy buf: %d\n", ret);
|
503
|
+
return T_EXIT_FAIL;
|
504
|
+
}
|
505
|
+
|
506
|
+
ret = io_uring_unregister_buffers(&src);
|
507
|
+
if (ret) {
|
508
|
+
fprintf(stderr, "rsc unregister buffers: %d\n", ret);
|
509
|
+
return T_EXIT_FAIL;
|
510
|
+
}
|
511
|
+
|
512
|
+
ret = io_uring_unregister_buffers(&dst);
|
513
|
+
if (ret) {
|
514
|
+
fprintf(stderr, "dst unregister buffers: %d\n", ret);
|
515
|
+
return T_EXIT_FAIL;
|
516
|
+
}
|
517
|
+
|
518
|
+
io_uring_queue_exit(&src);
|
519
|
+
io_uring_queue_exit(&dst);
|
520
|
+
|
521
|
+
return T_EXIT_PASS;
|
522
|
+
}
|
523
|
+
|
524
|
+
/*
|
525
|
+
* Register sparse buffer table, then try updating that with a few huge
|
526
|
+
* page entries.
|
527
|
+
*/
|
528
|
+
static int test_merge(void)
|
529
|
+
{
|
530
|
+
int ret, res = T_EXIT_SKIP;
|
531
|
+
struct iovec vecs[8];
|
532
|
+
struct io_uring ring;
|
533
|
+
__u64 tags[2];
|
534
|
+
void *p1;
|
535
|
+
|
536
|
+
p1 = mmap(NULL, 2*1024*1024, PROT_READ|PROT_WRITE,
|
537
|
+
MAP_PRIVATE|MAP_HUGETLB | MAP_HUGE_2MB | MAP_ANONYMOUS,
|
538
|
+
-1, 0);
|
539
|
+
if (p1 == MAP_FAILED)
|
540
|
+
return T_EXIT_SKIP;
|
541
|
+
|
542
|
+
ret = io_uring_queue_init(1, &ring, 0);
|
543
|
+
if (ret) {
|
544
|
+
fprintf(stderr, "ring_init: %d\n", ret);
|
545
|
+
return T_EXIT_FAIL;
|
546
|
+
}
|
547
|
+
|
548
|
+
memset(vecs, 0, sizeof(vecs));
|
549
|
+
|
550
|
+
ret = io_uring_register_buffers(&ring, vecs, 8);
|
551
|
+
if (ret < 0) {
|
552
|
+
if (ret == -EINVAL)
|
553
|
+
goto skip;
|
554
|
+
fprintf(stderr, "failed to register initial buffers: %d\n", ret);
|
555
|
+
return T_EXIT_FAIL;
|
556
|
+
}
|
557
|
+
|
558
|
+
vecs[0].iov_base = p1;
|
559
|
+
vecs[0].iov_len = 4096;
|
560
|
+
vecs[1].iov_base = p1 + 4096;
|
561
|
+
vecs[1].iov_len = 4096;
|
562
|
+
|
563
|
+
tags[0] = 1;
|
564
|
+
tags[1] = 2;
|
565
|
+
ret = io_uring_register_buffers_update_tag(&ring, 4, vecs, tags, 2);
|
566
|
+
if (ret < 0) {
|
567
|
+
if (ret == -EINVAL)
|
568
|
+
goto skip;
|
569
|
+
fprintf(stderr, "failed to register merge buffers: %d\n", ret);
|
570
|
+
return T_EXIT_FAIL;
|
571
|
+
}
|
572
|
+
res = T_EXIT_PASS;
|
573
|
+
skip:
|
574
|
+
munmap(p1, 2*1024*1024);
|
575
|
+
io_uring_queue_exit(&ring);
|
576
|
+
return res;
|
577
|
+
}
|
578
|
+
|
147
579
|
int main(int argc, char *argv[])
|
148
580
|
{
|
149
581
|
int ret;
|
@@ -151,6 +583,12 @@ int main(int argc, char *argv[])
|
|
151
583
|
if (argc > 1)
|
152
584
|
return T_EXIT_SKIP;
|
153
585
|
|
586
|
+
ret = test_merge();
|
587
|
+
if (ret == T_EXIT_FAIL) {
|
588
|
+
fprintf(stderr, "test_merge failed\n");
|
589
|
+
return T_EXIT_FAIL;
|
590
|
+
}
|
591
|
+
|
154
592
|
ret = test(0, 0);
|
155
593
|
if (ret == T_EXIT_SKIP) {
|
156
594
|
return T_EXIT_SKIP;
|
@@ -158,6 +596,8 @@ int main(int argc, char *argv[])
|
|
158
596
|
fprintf(stderr, "test 0 0 failed\n");
|
159
597
|
return T_EXIT_FAIL;
|
160
598
|
}
|
599
|
+
if (no_buf_clone)
|
600
|
+
return T_EXIT_SKIP;
|
161
601
|
|
162
602
|
ret = test(0, 1);
|
163
603
|
if (ret == T_EXIT_SKIP) {
|
@@ -183,5 +623,23 @@ int main(int argc, char *argv[])
|
|
183
623
|
return T_EXIT_FAIL;
|
184
624
|
}
|
185
625
|
|
626
|
+
ret = test_dummy();
|
627
|
+
if (ret == T_EXIT_SKIP) {
|
628
|
+
return T_EXIT_SKIP;
|
629
|
+
} else if (ret != T_EXIT_PASS) {
|
630
|
+
fprintf(stderr, "test_dummy failed\n");
|
631
|
+
return T_EXIT_FAIL;
|
632
|
+
}
|
633
|
+
|
634
|
+
ret = test_offsets();
|
635
|
+
if (ret == T_EXIT_SKIP) {
|
636
|
+
return T_EXIT_PASS;
|
637
|
+
} else if (ret != T_EXIT_PASS) {
|
638
|
+
fprintf(stderr, "test_offset failed\n");
|
639
|
+
return T_EXIT_FAIL;
|
640
|
+
}
|
641
|
+
if (no_buf_offset)
|
642
|
+
return T_EXIT_PASS;
|
643
|
+
|
186
644
|
return T_EXIT_PASS;
|
187
645
|
}
|