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,643 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test sq/cq ring resizing
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
+ #include "helpers.h"
16
+
17
+ #define NVECS 128
18
+
19
+ #define min(a, b) ((a) < (b) ? (a) : (b))
20
+
21
+ struct data {
22
+ pthread_t thread;
23
+ int fd;
24
+ int nr_writes;
25
+ int failed;
26
+ };
27
+
28
+ static void *thread_fn(void *__data)
29
+ {
30
+ struct data *d = __data;
31
+ char buffer[8];
32
+ int to_write = d->nr_writes;
33
+
34
+ memset(buffer, 0x5a, sizeof(buffer));
35
+ usleep(10000);
36
+ while (to_write) {
37
+ int ret = write(d->fd, buffer, sizeof(buffer));
38
+
39
+ if (ret < 0) {
40
+ perror("write");
41
+ d->failed = 1;
42
+ break;
43
+ } else if (ret != sizeof(buffer)) {
44
+ printf("short write %d\n", ret);
45
+ }
46
+ to_write--;
47
+ usleep(5);
48
+ }
49
+ return NULL;
50
+ }
51
+
52
+ static int test_pipes(struct io_uring *ring, int async)
53
+ {
54
+ struct io_uring_params p = { };
55
+ struct io_uring_sqe *sqe;
56
+ struct io_uring_cqe *cqe;
57
+ unsigned long ud = 0;
58
+ struct data d = { };
59
+ int ret, i, fds[2], to_read;
60
+ char buffer[8];
61
+ void *tret;
62
+
63
+ p.sq_entries = 128;
64
+ p.cq_entries = 128;
65
+ ret = io_uring_resize_rings(ring, &p);
66
+ if (ret < 0) {
67
+ fprintf(stderr, "Failed to resize ring: %d\n", ret);
68
+ return T_EXIT_FAIL;
69
+ }
70
+
71
+ if (pipe(fds) < 0) {
72
+ perror("pipe");
73
+ return T_EXIT_FAIL;
74
+ }
75
+
76
+ /*
77
+ * Put NVECS inflight, then resize while waiting. Repeat until
78
+ * 'to_read' has been read.
79
+ */
80
+ d.nr_writes = 4096;
81
+ d.fd = fds[1];
82
+ p.sq_entries = 64;
83
+ p.cq_entries = 256;
84
+
85
+ pthread_create(&d.thread, NULL, thread_fn, &d);
86
+
87
+ to_read = d.nr_writes - 128;
88
+ while (to_read && !d.failed) {
89
+ unsigned long start_ud = -1UL, end_ud;
90
+ int to_wait;
91
+
92
+ to_wait = NVECS;
93
+ if (to_wait > to_read)
94
+ to_wait = to_read;
95
+
96
+ for (i = 0; i < to_wait; i++) {
97
+ sqe = io_uring_get_sqe(ring);
98
+ /* resized smaller */
99
+ if (!sqe)
100
+ break;
101
+ io_uring_prep_read(sqe, fds[0], buffer, sizeof(buffer), 0);
102
+ if (async)
103
+ sqe->flags |= IOSQE_ASYNC;
104
+ if (start_ud == -1UL)
105
+ start_ud = ud;
106
+ sqe->user_data = ++ud;
107
+ to_read--;
108
+ }
109
+ end_ud = ud;
110
+ ret = io_uring_submit(ring);
111
+ if (ret != i) {
112
+ fprintf(stderr, "submitted; %d\n", ret);
113
+ return T_EXIT_FAIL;
114
+ }
115
+
116
+ to_wait = i;
117
+ for (i = 0; i < to_wait; i++) {
118
+ if (i == 0) {
119
+ ret = io_uring_resize_rings(ring, &p);
120
+ if (ret < 0) {
121
+ if (ret != -EOVERFLOW) {
122
+ fprintf(stderr, "resize failed: %d\n", ret);
123
+ return T_EXIT_FAIL;
124
+ }
125
+ }
126
+ p.sq_entries = 32;
127
+ p.cq_entries = 128;
128
+ }
129
+ if (d.failed)
130
+ break;
131
+ ret = io_uring_wait_cqe(ring, &cqe);
132
+ if (ret) {
133
+ fprintf(stderr, "wait cqe: %d\n", ret);
134
+ return T_EXIT_FAIL;
135
+ }
136
+ if (cqe->res < 0) {
137
+ fprintf(stderr, "cqe res %d\n", cqe->res);
138
+ return T_EXIT_FAIL;
139
+ }
140
+ if (cqe->user_data < start_ud ||
141
+ cqe->user_data > end_ud) {
142
+ fprintf(stderr, "use_data out-of-range: <%lu-%lu>: %lu\n",
143
+ start_ud, end_ud, (long) cqe->user_data);
144
+ return T_EXIT_FAIL;
145
+ }
146
+ io_uring_cqe_seen(ring, cqe);
147
+ if (!(i % 17)) {
148
+ ret = io_uring_resize_rings(ring, &p);
149
+ if (ret < 0) {
150
+ if (ret == -EOVERFLOW)
151
+ continue;
152
+ fprintf(stderr, "resize failed: %d\n", ret);
153
+ return T_EXIT_FAIL;
154
+ }
155
+ if (p.sq_entries == 32)
156
+ p.sq_entries = 64;
157
+ else if (p.sq_entries == 64)
158
+ p.sq_entries = 16;
159
+ else
160
+ p.sq_entries = 32;
161
+ if (p.cq_entries == 128)
162
+ p.cq_entries = 256;
163
+ else
164
+ p.cq_entries = 128;
165
+ }
166
+ }
167
+ }
168
+
169
+ pthread_join(d.thread, &tret);
170
+ close(fds[0]);
171
+ close(fds[0]);
172
+ return 0;
173
+ }
174
+
175
+ static int test_reads(struct io_uring *ring, int fd, int async)
176
+ {
177
+ struct io_uring_params p = { };
178
+ struct io_uring_sqe *sqe;
179
+ struct io_uring_cqe *cqe;
180
+ struct iovec vecs[NVECS];
181
+ unsigned long to_read;
182
+ unsigned long ud = 0;
183
+ unsigned long offset;
184
+ int ret, i;
185
+
186
+ if (fd == -1)
187
+ return T_EXIT_SKIP;
188
+
189
+ p.sq_entries = 128;
190
+ p.cq_entries = 128;
191
+ ret = io_uring_resize_rings(ring, &p);
192
+ if (ret < 0) {
193
+ fprintf(stderr, "Failed to resize ring: %d\n", ret);
194
+ return T_EXIT_FAIL;
195
+ }
196
+
197
+ for (i = 0; i < NVECS; i++) {
198
+ if (posix_memalign(&vecs[i].iov_base, 4096, 4096))
199
+ return T_EXIT_FAIL;
200
+ vecs[i].iov_len = 4096;
201
+ }
202
+
203
+ /*
204
+ * Put NVECS inflight, then resize while waiting. Repeat until
205
+ * 'to_read' has been read.
206
+ */
207
+ to_read = 64*1024*1024;
208
+ p.sq_entries = 64;
209
+ p.cq_entries = 256;
210
+ offset = 0;
211
+ while (to_read) {
212
+ unsigned long start_ud = -1UL, end_ud;
213
+ int to_wait;
214
+
215
+ for (i = 0; i < NVECS; i++) {
216
+ sqe = io_uring_get_sqe(ring);
217
+ /* resized smaller */
218
+ if (!sqe)
219
+ break;
220
+ io_uring_prep_read(sqe, fd, vecs[i].iov_base,
221
+ vecs[i].iov_len, offset);
222
+ if (async)
223
+ sqe->flags |= IOSQE_ASYNC;
224
+ offset += 8192;
225
+ if (start_ud == -1UL)
226
+ start_ud = ud;
227
+ sqe->user_data = ++ud;
228
+ }
229
+ end_ud = ud;
230
+ ret = io_uring_submit(ring);
231
+ if (ret != i) {
232
+ fprintf(stderr, "submitted; %d\n", ret);
233
+ return T_EXIT_FAIL;
234
+ }
235
+
236
+ to_wait = i;
237
+ for (i = 0; i < to_wait; i++) {
238
+ if (i == 0) {
239
+ ret = io_uring_resize_rings(ring, &p);
240
+ if (ret < 0) {
241
+ if (ret != -EOVERFLOW) {
242
+ fprintf(stderr, "resize failed: %d\n", ret);
243
+ return T_EXIT_FAIL;
244
+ }
245
+ }
246
+ p.sq_entries = 32;
247
+ p.cq_entries = 128;
248
+ }
249
+ ret = io_uring_wait_cqe(ring, &cqe);
250
+ if (ret) {
251
+ fprintf(stderr, "wait cqe: %d\n", ret);
252
+ return T_EXIT_FAIL;
253
+ }
254
+ if (cqe->res < 0) {
255
+ fprintf(stderr, "cqe res %d\n", cqe->res);
256
+ return T_EXIT_FAIL;
257
+ }
258
+ if (cqe->user_data < start_ud ||
259
+ cqe->user_data > end_ud) {
260
+ fprintf(stderr, "use_data out-of-range: <%lu-%lu>: %lu\n",
261
+ start_ud, end_ud, (long) cqe->user_data);
262
+ return T_EXIT_FAIL;
263
+ }
264
+ io_uring_cqe_seen(ring, cqe);
265
+ if (to_read)
266
+ to_read -= min(to_read, 4096);
267
+ if (!(i % 17)) {
268
+ ret = io_uring_resize_rings(ring, &p);
269
+ if (ret < 0) {
270
+ if (ret == -EOVERFLOW)
271
+ continue;
272
+ fprintf(stderr, "resize failed: %d\n", ret);
273
+ return T_EXIT_FAIL;
274
+ }
275
+ if (p.sq_entries == 32)
276
+ p.sq_entries = 64;
277
+ else if (p.sq_entries == 64)
278
+ p.sq_entries = 16;
279
+ else
280
+ p.sq_entries = 32;
281
+ if (p.cq_entries == 128)
282
+ p.cq_entries = 256;
283
+ else
284
+ p.cq_entries = 128;
285
+ }
286
+ }
287
+ }
288
+
289
+ return 0;
290
+ }
291
+
292
+ static int test_basic(struct io_uring *ring, int async)
293
+ {
294
+ struct io_uring_params p = { };
295
+ struct io_uring_sqe *sqe;
296
+ struct io_uring_cqe *cqe;
297
+ int i, ret;
298
+
299
+ sqe = io_uring_get_sqe(ring);
300
+ io_uring_prep_nop(sqe);
301
+ if (async)
302
+ sqe->flags |= IOSQE_ASYNC;
303
+ sqe->user_data = 1;
304
+ io_uring_submit(ring);
305
+
306
+ p.sq_entries = 32;
307
+ p.cq_entries = 64;
308
+ ret = io_uring_resize_rings(ring, &p);
309
+ if (ret == -EINVAL)
310
+ return T_EXIT_SKIP;
311
+
312
+ sqe = io_uring_get_sqe(ring);
313
+ io_uring_prep_nop(sqe);
314
+ if (async)
315
+ sqe->flags |= IOSQE_ASYNC;
316
+ sqe->user_data = 2;
317
+ io_uring_submit(ring);
318
+
319
+ for (i = 0; i < 2; i++) {
320
+ ret = io_uring_wait_cqe(ring, &cqe);
321
+ if (ret) {
322
+ fprintf(stderr, "wait cqe %d\n", ret);
323
+ return T_EXIT_FAIL;
324
+ }
325
+ if (cqe->user_data != i + 1) {
326
+ fprintf(stderr, "bad user_data %ld\n", (long) cqe->user_data);
327
+ return T_EXIT_FAIL;
328
+ }
329
+ io_uring_cqe_seen(ring, cqe);
330
+ }
331
+
332
+ return T_EXIT_PASS;
333
+ }
334
+
335
+ static int test_all_copy(struct io_uring *ring)
336
+ {
337
+ struct io_uring_params p = { };
338
+ struct io_uring_sqe *sqe;
339
+ struct io_uring_cqe *cqe;
340
+ unsigned head;
341
+ int i, ret;
342
+
343
+ p.sq_entries = 32;
344
+ p.cq_entries = 64;
345
+ ret = io_uring_resize_rings(ring, &p);
346
+ if (ret) {
347
+ fprintf(stderr, "resize failed: %d\n", ret);
348
+ return T_EXIT_FAIL;
349
+ }
350
+
351
+ for (i = 0; i < 32; i++) {
352
+ sqe = io_uring_get_sqe(ring);
353
+ io_uring_prep_nop(sqe);
354
+ sqe->user_data = i + 1;
355
+ }
356
+
357
+ io_uring_submit(ring);
358
+
359
+ memset(&p, 0, sizeof(p));
360
+ p.sq_entries = 64;
361
+ p.cq_entries = 128;
362
+ ret = io_uring_resize_rings(ring, &p);
363
+ if (ret) {
364
+ fprintf(stderr, "resize failed: %d\n", ret);
365
+ return T_EXIT_FAIL;
366
+ }
367
+
368
+ i = 1;
369
+ io_uring_for_each_cqe(ring, head, cqe) {
370
+ if (cqe->user_data != i) {
371
+ fprintf(stderr, "Found cqe at wrong offset\n");
372
+ return T_EXIT_FAIL;
373
+ }
374
+ i++;
375
+ }
376
+ io_uring_cq_advance(ring, 32);
377
+ return T_EXIT_PASS;
378
+ }
379
+
380
+ static int test_overflow(struct io_uring *ring)
381
+ {
382
+ struct io_uring_params p = { };
383
+ struct io_uring_sqe *sqe;
384
+ int i, ret;
385
+
386
+ p.sq_entries = 32;
387
+ p.cq_entries = 64;
388
+ ret = io_uring_resize_rings(ring, &p);
389
+ if (ret) {
390
+ fprintf(stderr, "resize failed: %d\n", ret);
391
+ return T_EXIT_FAIL;
392
+ }
393
+
394
+ for (i = 0; i < 32; i++) {
395
+ sqe = io_uring_get_sqe(ring);
396
+ io_uring_prep_nop(sqe);
397
+ sqe->user_data = i + 1;
398
+ }
399
+
400
+ io_uring_submit(ring);
401
+
402
+ /* have 32 CQEs pending, resize to CQ size 32 which should work */
403
+ memset(&p, 0, sizeof(p));
404
+ p.sq_entries = 32;
405
+ p.cq_entries = 32;
406
+ ret = io_uring_resize_rings(ring, &p);
407
+ if (ret) {
408
+ fprintf(stderr, "resize failed: %d\n", ret);
409
+ return T_EXIT_FAIL;
410
+ }
411
+
412
+ /* now resize to CQ size 16, which should fail with -EOVERFLOW */
413
+ memset(&p, 0, sizeof(p));
414
+ p.sq_entries = 8;
415
+ p.cq_entries = 16;
416
+ ret = io_uring_resize_rings(ring, &p);
417
+ if (ret != -EOVERFLOW) {
418
+ fprintf(stderr, "Expected overflow, got %d\n", ret);
419
+ return T_EXIT_FAIL;
420
+ }
421
+
422
+ io_uring_cq_advance(ring, 32);
423
+ return T_EXIT_PASS;
424
+ }
425
+
426
+ static int test_same_resize(int flags)
427
+ {
428
+ struct io_uring_params p = { };
429
+ struct io_uring_sqe *sqe;
430
+ struct io_uring_cqe *cqe;
431
+ struct io_uring ring;
432
+ int i, ret;
433
+
434
+ ret = io_uring_queue_init(32, &ring, flags);
435
+ if (ret)
436
+ return T_EXIT_FAIL;
437
+
438
+ p.sq_entries = 32;
439
+ p.cq_entries = 64;
440
+ ret = io_uring_resize_rings(&ring, &p);
441
+ if (ret) {
442
+ fprintf(stderr, "resize failed: %d\n", ret);
443
+ return T_EXIT_FAIL;
444
+ }
445
+
446
+ for (i = 0; i < 32; i++) {
447
+ sqe = io_uring_get_sqe(&ring);
448
+ io_uring_prep_nop(sqe);
449
+ sqe->user_data = i + 1;
450
+ }
451
+
452
+ io_uring_submit(&ring);
453
+
454
+ for (i = 0; i < 32; i++) {
455
+ ret = io_uring_wait_cqe(&ring, &cqe);
456
+ if (ret) {
457
+ fprintf(stderr, "wait_cqe: %d\n", ret);
458
+ return T_EXIT_FAIL;
459
+ }
460
+ if (cqe->user_data != i + 1) {
461
+ fprintf(stderr, "Found cqe at wrong offset\n");
462
+ return T_EXIT_FAIL;
463
+ }
464
+ io_uring_cqe_seen(&ring, cqe);
465
+ }
466
+
467
+ io_uring_queue_exit(&ring);
468
+ return T_EXIT_PASS;
469
+ }
470
+
471
+ static int mmap_child(struct io_uring *__ring, struct io_uring_params *__p)
472
+ {
473
+ struct io_uring ring = *__ring;
474
+ struct timeval tv;
475
+ int ret;
476
+
477
+ gettimeofday(&tv, NULL);
478
+ do {
479
+ struct io_uring_params p = *__p;
480
+ void *sq_ptr, *cq_ptr;
481
+
482
+ ret = io_uring_queue_mmap(__ring->ring_fd, &p, &ring);
483
+ if (ret)
484
+ continue;
485
+
486
+ sq_ptr = ring.sq.ring_ptr + 2 * sizeof(__u32);
487
+ cq_ptr = ring.cq.ring_ptr + 2 * sizeof(__u32);
488
+ memset(sq_ptr, 0x5a, ring.sq.ring_sz - 2 * sizeof(__u32));
489
+ memset(cq_ptr, 0xa5, ring.cq.ring_sz - 2 * sizeof(__u32));
490
+ io_uring_unmap_rings(&ring.sq, &ring.cq);
491
+ } while (mtime_since_now(&tv) < 2500);
492
+
493
+ exit(T_EXIT_PASS);
494
+ }
495
+
496
+ static int test_mmap_race(struct io_uring *ring, struct io_uring_params *__p)
497
+ {
498
+ unsigned long useless_sum;
499
+ int i, w, nr_children;
500
+ struct timeval tv;
501
+ pid_t pid;
502
+
503
+ nr_children = sysconf(_SC_NPROCESSORS_ONLN);
504
+ if (nr_children < 0)
505
+ nr_children = 4;
506
+
507
+ for (i = 0; i < nr_children; i++) {
508
+ pid = fork();
509
+ if (!pid) {
510
+ mmap_child(ring, __p);
511
+ return T_EXIT_PASS;
512
+ }
513
+ }
514
+
515
+ useless_sum = 0;
516
+ gettimeofday(&tv, NULL);
517
+ do {
518
+ struct io_uring_params p = { .sq_entries = 32, };
519
+ void *ptr;
520
+
521
+ io_uring_resize_rings(ring, &p);
522
+
523
+ ptr = memchr(ring->sq.ring_ptr, 0x5a, ring->sq.ring_sz);
524
+ if (ptr)
525
+ useless_sum += ptr - ring->sq.ring_ptr;
526
+
527
+ ptr = memchr(ring->cq.ring_ptr, 0xa5, ring->cq.ring_sz);
528
+ if (ptr)
529
+ useless_sum += ptr - ring->cq.ring_ptr;
530
+
531
+ p.sq_entries = 128;
532
+ io_uring_resize_rings(ring, &p);
533
+ } while (mtime_since_now(&tv) < 2500);
534
+
535
+ for (i = 0; i < nr_children; i++)
536
+ wait(&w);
537
+
538
+ if (useless_sum)
539
+ return T_EXIT_PASS;
540
+ return T_EXIT_PASS;
541
+ }
542
+
543
+ static int test(int flags, int fd, int async)
544
+ {
545
+ struct io_uring_params p = {
546
+ .flags = flags,
547
+ };
548
+ struct io_uring ring;
549
+ int ret;
550
+
551
+ ret = io_uring_queue_init_params(8, &ring, &p);
552
+ if (ret < 0) {
553
+ fprintf(stderr, "ring setup failed: %d\n", ret);
554
+ return T_EXIT_FAIL;
555
+ }
556
+
557
+ ret = test_basic(&ring, async);
558
+ if (ret == T_EXIT_SKIP) {
559
+ return T_EXIT_SKIP;
560
+ } else if (ret == T_EXIT_FAIL) {
561
+ fprintf(stderr, "test_basic %x failed\n", flags);
562
+ return T_EXIT_FAIL;
563
+ }
564
+
565
+ ret = test_reads(&ring, fd, async);
566
+ if (ret == T_EXIT_FAIL) {
567
+ fprintf(stderr, "test_reads %x failed\n", flags);
568
+ return T_EXIT_FAIL;
569
+ }
570
+
571
+ ret = test_pipes(&ring, async);
572
+ if (ret == T_EXIT_FAIL) {
573
+ fprintf(stderr, "test_pipes %x failed\n", flags);
574
+ return T_EXIT_FAIL;
575
+ }
576
+
577
+ if (async)
578
+ return T_EXIT_PASS;
579
+
580
+ ret = test_all_copy(&ring);
581
+ if (ret == T_EXIT_FAIL) {
582
+ fprintf(stderr, "test_all_copy %x failed\n", flags);
583
+ return T_EXIT_FAIL;
584
+ }
585
+
586
+ ret = test_overflow(&ring);
587
+ if (ret == T_EXIT_FAIL) {
588
+ fprintf(stderr, "test_overflow %x failed\n", flags);
589
+ return T_EXIT_FAIL;
590
+ }
591
+
592
+ ret = test_same_resize(flags);
593
+ if (ret == T_EXIT_FAIL) {
594
+ fprintf(stderr, "test_same_resize %x failed\n", flags);
595
+ return T_EXIT_FAIL;
596
+ }
597
+
598
+ /* must go at the end, insert more tests above this one */
599
+ ret = test_mmap_race(&ring, &p);
600
+ if (ret == T_EXIT_FAIL) {
601
+ fprintf(stderr, "test_mmap_race %x failed\n", flags);
602
+ return T_EXIT_FAIL;
603
+ }
604
+
605
+ io_uring_queue_exit(&ring);
606
+ return T_EXIT_PASS;
607
+ }
608
+
609
+ int main(int argc, char *argv[])
610
+ {
611
+ int ret, fd = -1;
612
+
613
+ if (argc > 1)
614
+ fd = open("/dev/nvme0n1", O_RDONLY | O_DIRECT);
615
+
616
+ ret = test(0, fd, 0);
617
+ if (ret == T_EXIT_SKIP)
618
+ return T_EXIT_SKIP;
619
+ else if (ret == T_EXIT_FAIL)
620
+ return T_EXIT_FAIL;
621
+
622
+ ret = test(0, fd, 1);
623
+ if (ret == T_EXIT_FAIL)
624
+ return T_EXIT_FAIL;
625
+
626
+ ret = test(IORING_SETUP_SQPOLL, fd, 0);
627
+ if (ret == T_EXIT_FAIL)
628
+ return T_EXIT_FAIL;
629
+
630
+ ret = test(IORING_SETUP_SQPOLL, fd, 1);
631
+ if (ret == T_EXIT_FAIL)
632
+ return T_EXIT_FAIL;
633
+
634
+ ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, fd, 0);
635
+ if (ret == T_EXIT_FAIL)
636
+ return T_EXIT_FAIL;
637
+
638
+ ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, fd, 1);
639
+ if (ret == T_EXIT_FAIL)
640
+ return T_EXIT_FAIL;
641
+
642
+ return T_EXIT_PASS;
643
+ }
@@ -59,6 +59,8 @@ static int test(const char *filename, int dio, int async)
59
59
  fd = open(filename, O_RDONLY);
60
60
  }
61
61
  if (fd < 0) {
62
+ if (errno == EPERM || errno == EACCES)
63
+ return T_EXIT_SKIP;
62
64
  perror("open");
63
65
  return 1;
64
66
  }
@@ -123,6 +125,7 @@ static int test(const char *filename, int dio, int async)
123
125
  if (verify_buffer(buf + ((bid - 1) * BUF_SIZE), ud))
124
126
  return 1;
125
127
  }
128
+ free(buf);
126
129
 
127
130
  return 0;
128
131
  }
@@ -144,6 +147,8 @@ int main(int argc, char *argv[])
144
147
 
145
148
  fd = open(fname, O_WRONLY);
146
149
  if (fd < 0) {
150
+ if (errno == EPERM || errno == EACCES)
151
+ return T_EXIT_SKIP;
147
152
  perror("open");
148
153
  goto err;
149
154
  }
@@ -109,6 +109,7 @@ static int test(int invalid)
109
109
  if (!br) {
110
110
  if (ret == -EINVAL) {
111
111
  no_buf_ring = 1;
112
+ free(buf);
112
113
  return 0;
113
114
  }
114
115
  fprintf(stderr, "Buffer ring register failed %d\n", ret);
@@ -131,10 +132,13 @@ static int test(int invalid)
131
132
  if (ret) {
132
133
  if (ret == -EINVAL) {
133
134
  no_buf_ring_status = 1;
135
+ free(buf);
134
136
  return T_EXIT_SKIP;
135
137
  }
136
- if (invalid && ret == -ENOENT)
138
+ if (invalid && ret == -ENOENT) {
139
+ free(buf);
137
140
  return T_EXIT_PASS;
141
+ }
138
142
  fprintf(stderr, "buf_ring_head: %d\n", ret);
139
143
  return T_EXIT_FAIL;
140
144
  }
@@ -184,7 +184,7 @@ static int test_buffers_update(void)
184
184
 
185
185
  /* test that CQE is not emitted before we're done with a buffer */
186
186
  sqe = io_uring_get_sqe(&ring);
187
- io_uring_prep_read_fixed(sqe, pipes[0], tmp_buf, 10, 0, 0);
187
+ io_uring_prep_read_fixed(sqe, pipes[0], tmp_buf, 10, 0, 1);
188
188
  sqe->user_data = 100;
189
189
  ret = io_uring_submit(&ring);
190
190
  if (ret != 1) {