uringmachine 0.3 → 0.5

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.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -1
  3. data/CHANGELOG.md +23 -0
  4. data/README.md +128 -0
  5. data/TODO.md +14 -0
  6. data/examples/bm_snooze.rb +89 -0
  7. data/examples/bm_write.rb +56 -0
  8. data/examples/dns_client.rb +12 -0
  9. data/examples/echo_server.rb +18 -40
  10. data/examples/http_server.rb +42 -43
  11. data/examples/inout.rb +19 -0
  12. data/examples/nc.rb +36 -0
  13. data/examples/server_client.rb +64 -0
  14. data/examples/snooze.rb +44 -0
  15. data/examples/write_dev_null.rb +16 -0
  16. data/ext/um/extconf.rb +24 -23
  17. data/ext/um/um.c +524 -278
  18. data/ext/um/um.h +146 -44
  19. data/ext/um/um_buffer.c +49 -0
  20. data/ext/um/um_class.c +217 -106
  21. data/ext/um/um_const.c +213 -0
  22. data/ext/um/um_ext.c +4 -0
  23. data/ext/um/um_mutex_class.c +47 -0
  24. data/ext/um/um_op.c +86 -114
  25. data/ext/um/um_queue_class.c +58 -0
  26. data/ext/um/um_sync.c +273 -0
  27. data/ext/um/um_utils.c +49 -4
  28. data/lib/uringmachine/dns_resolver.rb +84 -0
  29. data/lib/uringmachine/version.rb +1 -1
  30. data/lib/uringmachine.rb +28 -0
  31. data/supressions/ruby.supp +71 -0
  32. data/test/helper.rb +8 -0
  33. data/test/test_um.rb +685 -46
  34. data/vendor/liburing/.github/workflows/build.yml +29 -1
  35. data/vendor/liburing/.gitignore +6 -0
  36. data/vendor/liburing/CHANGELOG +16 -0
  37. data/vendor/liburing/CONTRIBUTING.md +165 -0
  38. data/vendor/liburing/configure +64 -0
  39. data/vendor/liburing/examples/Makefile +9 -1
  40. data/vendor/liburing/examples/kdigest.c +405 -0
  41. data/vendor/liburing/examples/proxy.c +75 -8
  42. data/vendor/liburing/examples/reg-wait.c +159 -0
  43. data/vendor/liburing/liburing.pc.in +1 -1
  44. data/vendor/liburing/liburing.spec +1 -1
  45. data/vendor/liburing/src/Makefile +16 -2
  46. data/vendor/liburing/src/include/liburing/io_uring.h +77 -0
  47. data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
  48. data/vendor/liburing/src/include/liburing.h +59 -6
  49. data/vendor/liburing/src/int_flags.h +10 -3
  50. data/vendor/liburing/src/liburing-ffi.map +16 -0
  51. data/vendor/liburing/src/liburing.map +10 -0
  52. data/vendor/liburing/src/queue.c +28 -16
  53. data/vendor/liburing/src/register.c +106 -1
  54. data/vendor/liburing/src/sanitize.c +176 -0
  55. data/vendor/liburing/src/setup.c +47 -19
  56. data/vendor/liburing/src/setup.h +6 -0
  57. data/vendor/liburing/test/35fa71a030ca.c +7 -0
  58. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  59. data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
  60. data/vendor/liburing/test/917257daa0fe.c +7 -0
  61. data/vendor/liburing/test/Makefile +38 -4
  62. data/vendor/liburing/test/a0908ae19763.c +7 -0
  63. data/vendor/liburing/test/a4c0b3decb33.c +7 -0
  64. data/vendor/liburing/test/accept.c +14 -4
  65. data/vendor/liburing/test/b19062a56726.c +7 -0
  66. data/vendor/liburing/test/bind-listen.c +2 -2
  67. data/vendor/liburing/test/buf-ring-nommap.c +10 -3
  68. data/vendor/liburing/test/buf-ring.c +2 -0
  69. data/vendor/liburing/test/cmd-discard.c +427 -0
  70. data/vendor/liburing/test/coredump.c +7 -0
  71. data/vendor/liburing/test/cq-overflow.c +13 -1
  72. data/vendor/liburing/test/d4ae271dfaae.c +11 -3
  73. data/vendor/liburing/test/defer-taskrun.c +2 -2
  74. data/vendor/liburing/test/defer-tw-timeout.c +4 -1
  75. data/vendor/liburing/test/defer.c +2 -2
  76. data/vendor/liburing/test/double-poll-crash.c +1 -1
  77. data/vendor/liburing/test/eeed8b54e0df.c +2 -0
  78. data/vendor/liburing/test/eventfd.c +0 -1
  79. data/vendor/liburing/test/exit-no-cleanup.c +11 -0
  80. data/vendor/liburing/test/fadvise.c +9 -26
  81. data/vendor/liburing/test/fdinfo.c +9 -1
  82. data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
  83. data/vendor/liburing/test/file-exit-unreg.c +48 -0
  84. data/vendor/liburing/test/file-register.c +14 -2
  85. data/vendor/liburing/test/file-update.c +1 -1
  86. data/vendor/liburing/test/file-verify.c +27 -16
  87. data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
  88. data/vendor/liburing/test/fixed-buf-iter.c +3 -1
  89. data/vendor/liburing/test/fixed-hugepage.c +12 -1
  90. data/vendor/liburing/test/fsnotify.c +1 -0
  91. data/vendor/liburing/test/futex.c +16 -4
  92. data/vendor/liburing/test/helpers.c +47 -0
  93. data/vendor/liburing/test/helpers.h +6 -0
  94. data/vendor/liburing/test/init-mem.c +5 -3
  95. data/vendor/liburing/test/io-cancel.c +0 -24
  96. data/vendor/liburing/test/io_uring_passthrough.c +4 -0
  97. data/vendor/liburing/test/io_uring_register.c +38 -8
  98. data/vendor/liburing/test/iopoll-leak.c +4 -0
  99. data/vendor/liburing/test/iopoll-overflow.c +1 -1
  100. data/vendor/liburing/test/iopoll.c +3 -3
  101. data/vendor/liburing/test/kallsyms.c +203 -0
  102. data/vendor/liburing/test/link-timeout.c +159 -0
  103. data/vendor/liburing/test/linked-defer-close.c +224 -0
  104. data/vendor/liburing/test/madvise.c +12 -25
  105. data/vendor/liburing/test/min-timeout-wait.c +0 -25
  106. data/vendor/liburing/test/min-timeout.c +0 -25
  107. data/vendor/liburing/test/mkdir.c +6 -0
  108. data/vendor/liburing/test/msg-ring.c +8 -2
  109. data/vendor/liburing/test/napi-test.c +16 -3
  110. data/vendor/liburing/test/no-mmap-inval.c +3 -1
  111. data/vendor/liburing/test/nop.c +44 -0
  112. data/vendor/liburing/test/ooo-file-unreg.c +1 -1
  113. data/vendor/liburing/test/open-close.c +40 -0
  114. data/vendor/liburing/test/openat2.c +37 -14
  115. data/vendor/liburing/test/poll-many.c +13 -7
  116. data/vendor/liburing/test/poll-mshot-update.c +17 -10
  117. data/vendor/liburing/test/poll-v-poll.c +6 -3
  118. data/vendor/liburing/test/pollfree.c +148 -0
  119. data/vendor/liburing/test/read-mshot-empty.c +158 -153
  120. data/vendor/liburing/test/read-mshot-stdin.c +121 -0
  121. data/vendor/liburing/test/read-mshot.c +282 -27
  122. data/vendor/liburing/test/read-write.c +78 -13
  123. data/vendor/liburing/test/recv-msgall-stream.c +3 -0
  124. data/vendor/liburing/test/recv-msgall.c +5 -0
  125. data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
  126. data/vendor/liburing/test/recvsend_bundle.c +94 -31
  127. data/vendor/liburing/test/reg-fd-only.c +15 -5
  128. data/vendor/liburing/test/reg-wait.c +251 -0
  129. data/vendor/liburing/test/regbuf-clone.c +645 -0
  130. data/vendor/liburing/test/regbuf-merge.c +7 -0
  131. data/vendor/liburing/test/register-restrictions.c +86 -85
  132. data/vendor/liburing/test/rename.c +59 -1
  133. data/vendor/liburing/test/resize-rings.c +643 -0
  134. data/vendor/liburing/test/ringbuf-read.c +5 -0
  135. data/vendor/liburing/test/ringbuf-status.c +5 -1
  136. data/vendor/liburing/test/rsrc_tags.c +1 -1
  137. data/vendor/liburing/test/runtests.sh +16 -1
  138. data/vendor/liburing/test/send-zerocopy.c +59 -0
  139. data/vendor/liburing/test/short-read.c +1 -0
  140. data/vendor/liburing/test/socket.c +43 -0
  141. data/vendor/liburing/test/splice.c +3 -1
  142. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  143. data/vendor/liburing/test/sq-poll-share.c +2 -0
  144. data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
  145. data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
  146. data/vendor/liburing/test/sqpoll-sleep.c +40 -33
  147. data/vendor/liburing/test/sqwait.c +136 -0
  148. data/vendor/liburing/test/statx.c +89 -0
  149. data/vendor/liburing/test/stdout.c +2 -0
  150. data/vendor/liburing/test/submit-and-wait.c +1 -25
  151. data/vendor/liburing/test/submit-reuse.c +4 -26
  152. data/vendor/liburing/test/symlink.c +12 -1
  153. data/vendor/liburing/test/sync-cancel.c +56 -22
  154. data/vendor/liburing/test/thread-exit.c +5 -0
  155. data/vendor/liburing/test/timeout-new.c +1 -26
  156. data/vendor/liburing/test/timeout.c +25 -34
  157. data/vendor/liburing/test/unlink.c +94 -1
  158. data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
  159. data/vendor/liburing/test/waitid.c +62 -8
  160. data/vendor/liburing/test/wq-aff.c +35 -0
  161. data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
  162. data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
  163. metadata +37 -6
  164. data/examples/event_loop.rb +0 -69
  165. data/examples/fibers.rb +0 -105
  166. data/examples/http_server_multishot.rb +0 -57
  167. data/examples/http_server_simpler.rb +0 -34
@@ -0,0 +1,645 @@
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
+ #include <string.h>
12
+ #include <limits.h>
13
+ #include <sys/mman.h>
14
+ #include <linux/mman.h>
15
+
16
+ #include "liburing.h"
17
+ #include "helpers.h"
18
+
19
+ #define NR_VECS 64
20
+ #define BUF_SIZE 8192
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
+
311
+ static int test(int reg_src, int reg_dst)
312
+ {
313
+ struct iovec vecs[NR_VECS];
314
+ struct io_uring src, dst;
315
+ int ret, i;
316
+
317
+ ret = io_uring_queue_init(1, &src, 0);
318
+ if (ret) {
319
+ fprintf(stderr, "ring_init: %d\n", ret);
320
+ return T_EXIT_FAIL;
321
+ }
322
+ ret = io_uring_queue_init(1, &dst, 0);
323
+ if (ret) {
324
+ fprintf(stderr, "ring_init: %d\n", ret);
325
+ return T_EXIT_FAIL;
326
+ }
327
+ if (reg_src) {
328
+ ret = io_uring_register_ring_fd(&src);
329
+ if (ret < 0) {
330
+ if (ret == -EINVAL)
331
+ return T_EXIT_SKIP;
332
+ fprintf(stderr, "register ring: %d\n", ret);
333
+ return T_EXIT_FAIL;
334
+ }
335
+ }
336
+ if (reg_dst) {
337
+ ret = io_uring_register_ring_fd(&dst);
338
+ if (ret < 0) {
339
+ if (ret == -EINVAL)
340
+ return T_EXIT_SKIP;
341
+ fprintf(stderr, "register ring: %d\n", ret);
342
+ return T_EXIT_FAIL;
343
+ }
344
+ }
345
+
346
+ /* test fail with no buffers in src */
347
+ ret = io_uring_clone_buffers(&dst, &src);
348
+ if (ret == -EINVAL) {
349
+ /* no buffer copy support */
350
+ no_buf_clone = true;
351
+ return T_EXIT_SKIP;
352
+ } else if (ret != -ENXIO) {
353
+ fprintf(stderr, "empty copy: %d\n", ret);
354
+ return T_EXIT_FAIL;
355
+ }
356
+
357
+ for (i = 0; i < NR_VECS; i++) {
358
+ if (posix_memalign(&vecs[i].iov_base, 4096, BUF_SIZE))
359
+ return T_EXIT_FAIL;
360
+ vecs[i].iov_len = BUF_SIZE;
361
+ }
362
+
363
+ ret = io_uring_register_buffers(&src, vecs, NR_VECS);
364
+ if (ret < 0) {
365
+ if (ret == -ENOMEM)
366
+ return T_EXIT_SKIP;
367
+ return T_EXIT_FAIL;
368
+ }
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
+
382
+ /* copy should work now */
383
+ ret = io_uring_clone_buffers(&dst, &src);
384
+ if (ret) {
385
+ fprintf(stderr, "buffer copy: %d\n", ret);
386
+ return T_EXIT_FAIL;
387
+ }
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
+
395
+ /* try copy again, should get -EBUSY */
396
+ ret = io_uring_clone_buffers(&dst, &src);
397
+ if (ret != -EBUSY) {
398
+ fprintf(stderr, "busy copy: %d\n", ret);
399
+ return T_EXIT_FAIL;
400
+ }
401
+
402
+ ret = io_uring_unregister_buffers(&dst);
403
+ if (ret) {
404
+ fprintf(stderr, "dst unregister buffers: %d\n", ret);
405
+ return T_EXIT_FAIL;
406
+ }
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
+
414
+ ret = io_uring_unregister_buffers(&dst);
415
+ if (ret != -ENXIO) {
416
+ fprintf(stderr, "dst unregister empty buffers: %d\n", ret);
417
+ return T_EXIT_FAIL;
418
+ }
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
+
426
+ ret = io_uring_unregister_buffers(&src);
427
+ if (ret) {
428
+ fprintf(stderr, "src unregister buffers: %d\n", ret);
429
+ return T_EXIT_FAIL;
430
+ }
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
+
438
+ ret = io_uring_register_buffers(&dst, vecs, NR_VECS);
439
+ if (ret < 0) {
440
+ fprintf(stderr, "register buffers dst; %d\n", ret);
441
+ return T_EXIT_FAIL;
442
+ }
443
+
444
+ ret = io_uring_clone_buffers(&src, &dst);
445
+ if (ret) {
446
+ fprintf(stderr, "buffer copy reverse: %d\n", ret);
447
+ return T_EXIT_FAIL;
448
+ }
449
+
450
+ ret = io_uring_unregister_buffers(&dst);
451
+ if (ret) {
452
+ fprintf(stderr, "dst unregister buffers: %d\n", ret);
453
+ return T_EXIT_FAIL;
454
+ }
455
+
456
+ ret = io_uring_unregister_buffers(&dst);
457
+ if (ret != -ENXIO) {
458
+ fprintf(stderr, "dst unregister empty buffers: %d\n", ret);
459
+ return T_EXIT_FAIL;
460
+ }
461
+
462
+ ret = io_uring_unregister_buffers(&src);
463
+ if (ret) {
464
+ fprintf(stderr, "src unregister buffers: %d\n", ret);
465
+ return T_EXIT_FAIL;
466
+ }
467
+
468
+ io_uring_queue_exit(&src);
469
+ io_uring_queue_exit(&dst);
470
+
471
+ for (i = 0; i < NR_VECS; i++)
472
+ free(vecs[i].iov_base);
473
+
474
+ return T_EXIT_PASS;
475
+ }
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
+
579
+ int main(int argc, char *argv[])
580
+ {
581
+ int ret;
582
+
583
+ if (argc > 1)
584
+ return T_EXIT_SKIP;
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
+
592
+ ret = test(0, 0);
593
+ if (ret == T_EXIT_SKIP) {
594
+ return T_EXIT_SKIP;
595
+ } else if (ret != T_EXIT_PASS) {
596
+ fprintf(stderr, "test 0 0 failed\n");
597
+ return T_EXIT_FAIL;
598
+ }
599
+ if (no_buf_clone)
600
+ return T_EXIT_SKIP;
601
+
602
+ ret = test(0, 1);
603
+ if (ret == T_EXIT_SKIP) {
604
+ return T_EXIT_SKIP;
605
+ } else if (ret != T_EXIT_PASS) {
606
+ fprintf(stderr, "test 0 1 failed\n");
607
+ return T_EXIT_FAIL;
608
+ }
609
+
610
+ ret = test(1, 0);
611
+ if (ret == T_EXIT_SKIP) {
612
+ return T_EXIT_SKIP;
613
+ } else if (ret != T_EXIT_PASS) {
614
+ fprintf(stderr, "test 1 0 failed\n");
615
+ return T_EXIT_FAIL;
616
+ }
617
+
618
+ ret = test(1, 1);
619
+ if (ret == T_EXIT_SKIP) {
620
+ return T_EXIT_SKIP;
621
+ } else if (ret != T_EXIT_PASS) {
622
+ fprintf(stderr, "test 1 1 failed\n");
623
+ return T_EXIT_FAIL;
624
+ }
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
+
644
+ return T_EXIT_PASS;
645
+ }
@@ -13,6 +13,7 @@
13
13
 
14
14
  #include "helpers.h"
15
15
 
16
+ #ifndef CONFIG_USE_SANITIZER
16
17
  #ifndef __NR_io_uring_register
17
18
  #define __NR_io_uring_register 427
18
19
  #endif
@@ -89,3 +90,9 @@ int main(int argc, char *argv[])
89
90
  syscall(__NR_io_uring_register, r[0], 0ul, 0x20002840ul, 2ul);
90
91
  return T_EXIT_PASS;
91
92
  }
93
+ #else
94
+ int main(int argc, char *argv[])
95
+ {
96
+ return T_EXIT_SKIP;
97
+ }
98
+ #endif