uringmachine 0.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.
Files changed (307) hide show
  1. checksums.yaml +7 -0
  2. data/.github/dependabot.yml +12 -0
  3. data/.github/workflows/test.yml +35 -0
  4. data/.gitignore +59 -0
  5. data/.gitmodules +3 -0
  6. data/CHANGELOG.md +7 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +21 -0
  9. data/README.md +11 -0
  10. data/Rakefile +39 -0
  11. data/TODO.md +0 -0
  12. data/examples/echo_server.rb +52 -0
  13. data/examples/event_loop.rb +69 -0
  14. data/examples/fibers.rb +105 -0
  15. data/examples/http_server.rb +56 -0
  16. data/examples/http_server_multishot.rb +57 -0
  17. data/examples/http_server_simpler.rb +34 -0
  18. data/ext/um/extconf.rb +71 -0
  19. data/ext/um/iou.h +101 -0
  20. data/ext/um/op_ctx.c +138 -0
  21. data/ext/um/ring.c +755 -0
  22. data/ext/um/um.c +267 -0
  23. data/ext/um/um.h +97 -0
  24. data/ext/um/um_class.c +175 -0
  25. data/ext/um/um_ext.c +11 -0
  26. data/ext/um/um_op.c +87 -0
  27. data/ext/um/um_utils.c +23 -0
  28. data/lib/uringmachine/version.rb +3 -0
  29. data/lib/uringmachine.rb +8 -0
  30. data/test/helper.rb +70 -0
  31. data/test/test_iou.rb +876 -0
  32. data/test/test_um.rb +168 -0
  33. data/uringmachine.gemspec +27 -0
  34. data/vendor/liburing/.github/actions/codespell/stopwords +7 -0
  35. data/vendor/liburing/.github/pull_request_template.md +86 -0
  36. data/vendor/liburing/.github/workflows/build.yml +137 -0
  37. data/vendor/liburing/.github/workflows/codespell.yml +25 -0
  38. data/vendor/liburing/.github/workflows/shellcheck.yml +20 -0
  39. data/vendor/liburing/.gitignore +41 -0
  40. data/vendor/liburing/CHANGELOG +111 -0
  41. data/vendor/liburing/CITATION.cff +11 -0
  42. data/vendor/liburing/COPYING +502 -0
  43. data/vendor/liburing/COPYING.GPL +339 -0
  44. data/vendor/liburing/LICENSE +20 -0
  45. data/vendor/liburing/Makefile +96 -0
  46. data/vendor/liburing/Makefile.common +7 -0
  47. data/vendor/liburing/Makefile.quiet +11 -0
  48. data/vendor/liburing/README +106 -0
  49. data/vendor/liburing/SECURITY.md +6 -0
  50. data/vendor/liburing/configure +624 -0
  51. data/vendor/liburing/debian/README.Debian +7 -0
  52. data/vendor/liburing/debian/changelog +38 -0
  53. data/vendor/liburing/debian/control +39 -0
  54. data/vendor/liburing/debian/copyright +49 -0
  55. data/vendor/liburing/debian/liburing-dev.install +4 -0
  56. data/vendor/liburing/debian/liburing-dev.manpages +5 -0
  57. data/vendor/liburing/debian/liburing2.install +1 -0
  58. data/vendor/liburing/debian/liburing2.symbols +56 -0
  59. data/vendor/liburing/debian/patches/series +1 -0
  60. data/vendor/liburing/debian/rules +29 -0
  61. data/vendor/liburing/debian/source/format +1 -0
  62. data/vendor/liburing/debian/source/local-options +2 -0
  63. data/vendor/liburing/debian/source/options +1 -0
  64. data/vendor/liburing/debian/watch +3 -0
  65. data/vendor/liburing/examples/Makefile +53 -0
  66. data/vendor/liburing/examples/helpers.c +62 -0
  67. data/vendor/liburing/examples/helpers.h +7 -0
  68. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  69. data/vendor/liburing/examples/io_uring-cp.c +282 -0
  70. data/vendor/liburing/examples/io_uring-test.c +112 -0
  71. data/vendor/liburing/examples/io_uring-udp.c +403 -0
  72. data/vendor/liburing/examples/link-cp.c +193 -0
  73. data/vendor/liburing/examples/napi-busy-poll-client.c +509 -0
  74. data/vendor/liburing/examples/napi-busy-poll-server.c +450 -0
  75. data/vendor/liburing/examples/poll-bench.c +101 -0
  76. data/vendor/liburing/examples/proxy.c +2461 -0
  77. data/vendor/liburing/examples/proxy.h +102 -0
  78. data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
  79. data/vendor/liburing/examples/send-zerocopy.c +658 -0
  80. data/vendor/liburing/examples/ucontext-cp.c +258 -0
  81. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  82. data/vendor/liburing/liburing.pc.in +12 -0
  83. data/vendor/liburing/liburing.spec +66 -0
  84. data/vendor/liburing/make-debs.sh +55 -0
  85. data/vendor/liburing/src/Makefile +129 -0
  86. data/vendor/liburing/src/arch/aarch64/lib.h +47 -0
  87. data/vendor/liburing/src/arch/aarch64/syscall.h +91 -0
  88. data/vendor/liburing/src/arch/generic/lib.h +17 -0
  89. data/vendor/liburing/src/arch/generic/syscall.h +100 -0
  90. data/vendor/liburing/src/arch/riscv64/lib.h +48 -0
  91. data/vendor/liburing/src/arch/riscv64/syscall.h +100 -0
  92. data/vendor/liburing/src/arch/syscall-defs.h +94 -0
  93. data/vendor/liburing/src/arch/x86/lib.h +11 -0
  94. data/vendor/liburing/src/arch/x86/syscall.h +296 -0
  95. data/vendor/liburing/src/ffi.c +15 -0
  96. data/vendor/liburing/src/include/liburing/barrier.h +81 -0
  97. data/vendor/liburing/src/include/liburing/io_uring.h +818 -0
  98. data/vendor/liburing/src/include/liburing.h +1602 -0
  99. data/vendor/liburing/src/int_flags.h +11 -0
  100. data/vendor/liburing/src/lib.h +52 -0
  101. data/vendor/liburing/src/liburing-ffi.map +211 -0
  102. data/vendor/liburing/src/liburing.map +104 -0
  103. data/vendor/liburing/src/nolibc.c +55 -0
  104. data/vendor/liburing/src/queue.c +468 -0
  105. data/vendor/liburing/src/register.c +374 -0
  106. data/vendor/liburing/src/setup.c +689 -0
  107. data/vendor/liburing/src/setup.h +9 -0
  108. data/vendor/liburing/src/syscall.c +29 -0
  109. data/vendor/liburing/src/syscall.h +53 -0
  110. data/vendor/liburing/src/version.c +21 -0
  111. data/vendor/liburing/test/232c93d07b74.c +305 -0
  112. data/vendor/liburing/test/35fa71a030ca.c +329 -0
  113. data/vendor/liburing/test/500f9fbadef8.c +91 -0
  114. data/vendor/liburing/test/7ad0e4b2f83c.c +94 -0
  115. data/vendor/liburing/test/8a9973408177.c +107 -0
  116. data/vendor/liburing/test/917257daa0fe.c +54 -0
  117. data/vendor/liburing/test/Makefile +297 -0
  118. data/vendor/liburing/test/a0908ae19763.c +59 -0
  119. data/vendor/liburing/test/a4c0b3decb33.c +181 -0
  120. data/vendor/liburing/test/accept-link.c +255 -0
  121. data/vendor/liburing/test/accept-non-empty.c +256 -0
  122. data/vendor/liburing/test/accept-reuse.c +163 -0
  123. data/vendor/liburing/test/accept-test.c +83 -0
  124. data/vendor/liburing/test/accept.c +919 -0
  125. data/vendor/liburing/test/across-fork.c +284 -0
  126. data/vendor/liburing/test/b19062a56726.c +54 -0
  127. data/vendor/liburing/test/b5837bd5311d.c +78 -0
  128. data/vendor/liburing/test/bind-listen.c +408 -0
  129. data/vendor/liburing/test/buf-ring-nommap.c +123 -0
  130. data/vendor/liburing/test/buf-ring-put.c +83 -0
  131. data/vendor/liburing/test/buf-ring.c +473 -0
  132. data/vendor/liburing/test/ce593a6c480a.c +139 -0
  133. data/vendor/liburing/test/close-opath.c +123 -0
  134. data/vendor/liburing/test/config +14 -0
  135. data/vendor/liburing/test/connect-rep.c +204 -0
  136. data/vendor/liburing/test/connect.c +442 -0
  137. data/vendor/liburing/test/coredump.c +60 -0
  138. data/vendor/liburing/test/cq-full.c +97 -0
  139. data/vendor/liburing/test/cq-overflow.c +530 -0
  140. data/vendor/liburing/test/cq-peek-batch.c +103 -0
  141. data/vendor/liburing/test/cq-ready.c +95 -0
  142. data/vendor/liburing/test/cq-size.c +65 -0
  143. data/vendor/liburing/test/d4ae271dfaae.c +96 -0
  144. data/vendor/liburing/test/d77a67ed5f27.c +65 -0
  145. data/vendor/liburing/test/defer-taskrun.c +391 -0
  146. data/vendor/liburing/test/defer-tw-timeout.c +173 -0
  147. data/vendor/liburing/test/defer.c +319 -0
  148. data/vendor/liburing/test/double-poll-crash.c +195 -0
  149. data/vendor/liburing/test/drop-submit.c +94 -0
  150. data/vendor/liburing/test/eeed8b54e0df.c +120 -0
  151. data/vendor/liburing/test/empty-eownerdead.c +45 -0
  152. data/vendor/liburing/test/eploop.c +74 -0
  153. data/vendor/liburing/test/eventfd-disable.c +179 -0
  154. data/vendor/liburing/test/eventfd-reg.c +77 -0
  155. data/vendor/liburing/test/eventfd-ring.c +98 -0
  156. data/vendor/liburing/test/eventfd.c +113 -0
  157. data/vendor/liburing/test/evloop.c +73 -0
  158. data/vendor/liburing/test/exec-target.c +6 -0
  159. data/vendor/liburing/test/exit-no-cleanup.c +117 -0
  160. data/vendor/liburing/test/fadvise.c +202 -0
  161. data/vendor/liburing/test/fallocate.c +265 -0
  162. data/vendor/liburing/test/fc2a85cb02ef.c +132 -0
  163. data/vendor/liburing/test/fd-install.c +500 -0
  164. data/vendor/liburing/test/fd-pass.c +237 -0
  165. data/vendor/liburing/test/fdinfo.c +419 -0
  166. data/vendor/liburing/test/file-register.c +1189 -0
  167. data/vendor/liburing/test/file-update.c +231 -0
  168. data/vendor/liburing/test/file-verify.c +654 -0
  169. data/vendor/liburing/test/files-exit-hang-poll.c +114 -0
  170. data/vendor/liburing/test/files-exit-hang-timeout.c +137 -0
  171. data/vendor/liburing/test/fixed-buf-iter.c +115 -0
  172. data/vendor/liburing/test/fixed-buf-merge.c +101 -0
  173. data/vendor/liburing/test/fixed-hugepage.c +411 -0
  174. data/vendor/liburing/test/fixed-link.c +90 -0
  175. data/vendor/liburing/test/fixed-reuse.c +160 -0
  176. data/vendor/liburing/test/fpos.c +255 -0
  177. data/vendor/liburing/test/fsnotify.c +118 -0
  178. data/vendor/liburing/test/fsync.c +224 -0
  179. data/vendor/liburing/test/futex.c +571 -0
  180. data/vendor/liburing/test/hardlink.c +170 -0
  181. data/vendor/liburing/test/helpers.c +318 -0
  182. data/vendor/liburing/test/helpers.h +108 -0
  183. data/vendor/liburing/test/ignore-single-mmap.c +48 -0
  184. data/vendor/liburing/test/init-mem.c +164 -0
  185. data/vendor/liburing/test/io-cancel.c +561 -0
  186. data/vendor/liburing/test/io_uring_enter.c +264 -0
  187. data/vendor/liburing/test/io_uring_passthrough.c +482 -0
  188. data/vendor/liburing/test/io_uring_register.c +503 -0
  189. data/vendor/liburing/test/io_uring_setup.c +110 -0
  190. data/vendor/liburing/test/iopoll-leak.c +85 -0
  191. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  192. data/vendor/liburing/test/iopoll.c +465 -0
  193. data/vendor/liburing/test/lfs-openat-write.c +119 -0
  194. data/vendor/liburing/test/lfs-openat.c +273 -0
  195. data/vendor/liburing/test/link-timeout.c +1108 -0
  196. data/vendor/liburing/test/link.c +497 -0
  197. data/vendor/liburing/test/link_drain.c +255 -0
  198. data/vendor/liburing/test/madvise.c +195 -0
  199. data/vendor/liburing/test/min-timeout-wait.c +354 -0
  200. data/vendor/liburing/test/min-timeout.c +233 -0
  201. data/vendor/liburing/test/mkdir.c +112 -0
  202. data/vendor/liburing/test/msg-ring-fd.c +331 -0
  203. data/vendor/liburing/test/msg-ring-flags.c +212 -0
  204. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  205. data/vendor/liburing/test/msg-ring.c +467 -0
  206. data/vendor/liburing/test/multicqes_drain.c +429 -0
  207. data/vendor/liburing/test/napi-test.c +215 -0
  208. data/vendor/liburing/test/napi-test.sh +48 -0
  209. data/vendor/liburing/test/no-mmap-inval.c +42 -0
  210. data/vendor/liburing/test/nolibc.c +62 -0
  211. data/vendor/liburing/test/nop-all-sizes.c +99 -0
  212. data/vendor/liburing/test/nop.c +177 -0
  213. data/vendor/liburing/test/nvme.h +169 -0
  214. data/vendor/liburing/test/ooo-file-unreg.c +82 -0
  215. data/vendor/liburing/test/open-close.c +261 -0
  216. data/vendor/liburing/test/open-direct-link.c +188 -0
  217. data/vendor/liburing/test/open-direct-pick.c +180 -0
  218. data/vendor/liburing/test/openat2.c +312 -0
  219. data/vendor/liburing/test/personality.c +204 -0
  220. data/vendor/liburing/test/pipe-bug.c +95 -0
  221. data/vendor/liburing/test/pipe-eof.c +83 -0
  222. data/vendor/liburing/test/pipe-reuse.c +105 -0
  223. data/vendor/liburing/test/poll-cancel-all.c +496 -0
  224. data/vendor/liburing/test/poll-cancel-ton.c +135 -0
  225. data/vendor/liburing/test/poll-cancel.c +228 -0
  226. data/vendor/liburing/test/poll-link.c +221 -0
  227. data/vendor/liburing/test/poll-many.c +230 -0
  228. data/vendor/liburing/test/poll-mshot-overflow.c +265 -0
  229. data/vendor/liburing/test/poll-mshot-update.c +323 -0
  230. data/vendor/liburing/test/poll-race-mshot.c +276 -0
  231. data/vendor/liburing/test/poll-race.c +105 -0
  232. data/vendor/liburing/test/poll-ring.c +48 -0
  233. data/vendor/liburing/test/poll-v-poll.c +353 -0
  234. data/vendor/liburing/test/poll.c +327 -0
  235. data/vendor/liburing/test/probe.c +135 -0
  236. data/vendor/liburing/test/read-before-exit.c +129 -0
  237. data/vendor/liburing/test/read-mshot-empty.c +153 -0
  238. data/vendor/liburing/test/read-mshot.c +404 -0
  239. data/vendor/liburing/test/read-write.c +1013 -0
  240. data/vendor/liburing/test/recv-msgall-stream.c +398 -0
  241. data/vendor/liburing/test/recv-msgall.c +263 -0
  242. data/vendor/liburing/test/recv-multishot.c +602 -0
  243. data/vendor/liburing/test/recvsend_bundle.c +691 -0
  244. data/vendor/liburing/test/reg-fd-only.c +131 -0
  245. data/vendor/liburing/test/reg-hint.c +56 -0
  246. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  247. data/vendor/liburing/test/regbuf-merge.c +91 -0
  248. data/vendor/liburing/test/register-restrictions.c +633 -0
  249. data/vendor/liburing/test/rename.c +132 -0
  250. data/vendor/liburing/test/ring-leak.c +283 -0
  251. data/vendor/liburing/test/ring-leak2.c +249 -0
  252. data/vendor/liburing/test/ringbuf-read.c +196 -0
  253. data/vendor/liburing/test/ringbuf-status.c +242 -0
  254. data/vendor/liburing/test/rsrc_tags.c +461 -0
  255. data/vendor/liburing/test/runtests-loop.sh +16 -0
  256. data/vendor/liburing/test/runtests-quiet.sh +11 -0
  257. data/vendor/liburing/test/runtests.sh +168 -0
  258. data/vendor/liburing/test/rw_merge_test.c +98 -0
  259. data/vendor/liburing/test/self.c +91 -0
  260. data/vendor/liburing/test/send-zerocopy.c +971 -0
  261. data/vendor/liburing/test/send_recv.c +412 -0
  262. data/vendor/liburing/test/send_recvmsg.c +444 -0
  263. data/vendor/liburing/test/shared-wq.c +84 -0
  264. data/vendor/liburing/test/short-read.c +75 -0
  265. data/vendor/liburing/test/shutdown.c +165 -0
  266. data/vendor/liburing/test/sigfd-deadlock.c +88 -0
  267. data/vendor/liburing/test/single-issuer.c +169 -0
  268. data/vendor/liburing/test/skip-cqe.c +428 -0
  269. data/vendor/liburing/test/socket-getsetsock-cmd.c +346 -0
  270. data/vendor/liburing/test/socket-io-cmd.c +237 -0
  271. data/vendor/liburing/test/socket-rw-eagain.c +149 -0
  272. data/vendor/liburing/test/socket-rw-offset.c +149 -0
  273. data/vendor/liburing/test/socket-rw.c +137 -0
  274. data/vendor/liburing/test/socket.c +408 -0
  275. data/vendor/liburing/test/splice.c +512 -0
  276. data/vendor/liburing/test/sq-full-cpp.cc +45 -0
  277. data/vendor/liburing/test/sq-full.c +45 -0
  278. data/vendor/liburing/test/sq-poll-dup.c +211 -0
  279. data/vendor/liburing/test/sq-poll-kthread.c +169 -0
  280. data/vendor/liburing/test/sq-poll-share.c +138 -0
  281. data/vendor/liburing/test/sq-space_left.c +159 -0
  282. data/vendor/liburing/test/sqpoll-disable-exit.c +196 -0
  283. data/vendor/liburing/test/sqpoll-exec.c +132 -0
  284. data/vendor/liburing/test/sqpoll-exit-hang.c +78 -0
  285. data/vendor/liburing/test/sqpoll-sleep.c +69 -0
  286. data/vendor/liburing/test/statx.c +172 -0
  287. data/vendor/liburing/test/stdout.c +232 -0
  288. data/vendor/liburing/test/submit-and-wait.c +108 -0
  289. data/vendor/liburing/test/submit-link-fail.c +156 -0
  290. data/vendor/liburing/test/submit-reuse.c +237 -0
  291. data/vendor/liburing/test/symlink.c +117 -0
  292. data/vendor/liburing/test/sync-cancel.c +235 -0
  293. data/vendor/liburing/test/teardowns.c +58 -0
  294. data/vendor/liburing/test/test.h +36 -0
  295. data/vendor/liburing/test/thread-exit.c +143 -0
  296. data/vendor/liburing/test/timeout-new.c +256 -0
  297. data/vendor/liburing/test/timeout.c +1798 -0
  298. data/vendor/liburing/test/truncate.c +186 -0
  299. data/vendor/liburing/test/tty-write-dpoll.c +60 -0
  300. data/vendor/liburing/test/unlink.c +112 -0
  301. data/vendor/liburing/test/version.c +25 -0
  302. data/vendor/liburing/test/wait-timeout.c +287 -0
  303. data/vendor/liburing/test/waitid.c +373 -0
  304. data/vendor/liburing/test/wakeup-hang.c +162 -0
  305. data/vendor/liburing/test/wq-aff.c +146 -0
  306. data/vendor/liburing/test/xattr.c +442 -0
  307. metadata +412 -0
@@ -0,0 +1,97 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test CQ ring overflow
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
+
13
+ #include "liburing.h"
14
+ #include "helpers.h"
15
+
16
+ static int queue_n_nops(struct io_uring *ring, int n)
17
+ {
18
+ struct io_uring_sqe *sqe;
19
+ int i, ret;
20
+
21
+ for (i = 0; i < n; i++) {
22
+ sqe = io_uring_get_sqe(ring);
23
+ if (!sqe) {
24
+ printf("get sqe failed\n");
25
+ goto err;
26
+ }
27
+
28
+ io_uring_prep_nop(sqe);
29
+ }
30
+
31
+ ret = io_uring_submit(ring);
32
+ if (ret < n) {
33
+ printf("Submitted only %d\n", ret);
34
+ goto err;
35
+ } else if (ret < 0) {
36
+ printf("sqe submit failed: %d\n", ret);
37
+ goto err;
38
+ }
39
+
40
+ return 0;
41
+ err:
42
+ return 1;
43
+ }
44
+
45
+ int main(int argc, char *argv[])
46
+ {
47
+ struct io_uring_cqe *cqe;
48
+ struct io_uring_params p;
49
+ struct io_uring ring;
50
+ int i, ret;
51
+
52
+ if (argc > 1)
53
+ return T_EXIT_SKIP;
54
+
55
+ memset(&p, 0, sizeof(p));
56
+ ret = io_uring_queue_init_params(4, &ring, &p);
57
+ if (ret) {
58
+ printf("ring setup failed\n");
59
+ return T_EXIT_FAIL;
60
+
61
+ }
62
+
63
+ if (queue_n_nops(&ring, 4))
64
+ goto err;
65
+ if (queue_n_nops(&ring, 4))
66
+ goto err;
67
+ if (queue_n_nops(&ring, 4))
68
+ goto err;
69
+
70
+ i = 0;
71
+ do {
72
+ ret = io_uring_peek_cqe(&ring, &cqe);
73
+ if (ret < 0) {
74
+ if (ret == -EAGAIN)
75
+ break;
76
+ printf("wait completion %d\n", ret);
77
+ goto err;
78
+ }
79
+ io_uring_cqe_seen(&ring, cqe);
80
+ if (!cqe)
81
+ break;
82
+ i++;
83
+ } while (1);
84
+
85
+ if (i < 8 ||
86
+ ((*ring.cq.koverflow != 4) && !(p.features & IORING_FEAT_NODROP))) {
87
+ printf("CQ overflow fail: %d completions, %u overflow\n", i,
88
+ *ring.cq.koverflow);
89
+ goto err;
90
+ }
91
+
92
+ io_uring_queue_exit(&ring);
93
+ return T_EXIT_PASS;
94
+ err:
95
+ io_uring_queue_exit(&ring);
96
+ return T_EXIT_FAIL;
97
+ }
@@ -0,0 +1,530 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: run various CQ ring overflow tests
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 <assert.h>
13
+
14
+ #include "helpers.h"
15
+ #include "liburing.h"
16
+
17
+ #define FILE_SIZE (256 * 1024)
18
+ #define BS 4096
19
+ #define BUFFERS (FILE_SIZE / BS)
20
+
21
+ static struct iovec *vecs;
22
+
23
+ #define ENTRIES 8
24
+
25
+ /*
26
+ * io_uring has rare cases where CQEs are lost.
27
+ * This happens when there is no space in the CQ ring, and also there is no
28
+ * GFP_ATOMIC memory available. In reality this probably means that the process
29
+ * is about to be killed as many other things might start failing, but we still
30
+ * want to test that liburing and the kernel deal with this properly. The fault
31
+ * injection framework allows us to test this scenario. Unfortunately this
32
+ * requires some system wide changes and so we do not enable this by default.
33
+ * The tests in this file should work in both cases (where overflows are queued
34
+ * and where they are dropped) on recent kernels.
35
+ *
36
+ * In order to test dropped CQEs you should enable fault injection in the kernel
37
+ * config:
38
+ *
39
+ * CONFIG_FAULT_INJECTION=y
40
+ * CONFIG_FAILSLAB=y
41
+ * CONFIG_FAULT_INJECTION_DEBUG_FS=y
42
+ *
43
+ * and then run the test as follows:
44
+ * echo Y > /sys/kernel/debug/failslab/task-filter
45
+ * echo 100 > /sys/kernel/debug/failslab/probability
46
+ * echo 0 > /sys/kernel/debug/failslab/verbose
47
+ * echo 100000 > /sys/kernel/debug/failslab/times
48
+ * bash -c "echo 1 > /proc/self/make-it-fail && exec ./cq-overflow.t"
49
+ */
50
+
51
+ static int test_io(const char *file, unsigned long usecs, unsigned *drops,
52
+ int fault)
53
+ {
54
+ struct io_uring_sqe *sqe;
55
+ struct io_uring_cqe *cqe;
56
+ struct io_uring_params p;
57
+ unsigned reaped, total;
58
+ struct io_uring ring;
59
+ int nodrop, i, fd, ret;
60
+ bool cqe_dropped = false;
61
+
62
+ fd = open(file, O_RDONLY | O_DIRECT);
63
+ if (fd < 0) {
64
+ if (errno == EINVAL)
65
+ return T_EXIT_SKIP;
66
+ perror("file open");
67
+ return T_EXIT_FAIL;
68
+ }
69
+
70
+ memset(&p, 0, sizeof(p));
71
+ ret = io_uring_queue_init_params(ENTRIES, &ring, &p);
72
+ if (ret) {
73
+ close(fd);
74
+ fprintf(stderr, "ring create failed: %d\n", ret);
75
+ return T_EXIT_FAIL;
76
+ }
77
+ nodrop = 0;
78
+ if (p.features & IORING_FEAT_NODROP)
79
+ nodrop = 1;
80
+
81
+ total = 0;
82
+ for (i = 0; i < BUFFERS / 2; i++) {
83
+ off_t offset;
84
+
85
+ sqe = io_uring_get_sqe(&ring);
86
+ if (!sqe) {
87
+ fprintf(stderr, "sqe get failed\n");
88
+ goto err;
89
+ }
90
+ offset = BS * (rand() % BUFFERS);
91
+ if (fault && i == ENTRIES + 4)
92
+ vecs[i].iov_base = NULL;
93
+ io_uring_prep_readv(sqe, fd, &vecs[i], 1, offset);
94
+
95
+ ret = io_uring_submit(&ring);
96
+ if (nodrop && ret == -EBUSY) {
97
+ *drops = 1;
98
+ total = i;
99
+ break;
100
+ } else if (ret != 1) {
101
+ fprintf(stderr, "submit got %d, wanted %d\n", ret, 1);
102
+ total = i;
103
+ break;
104
+ }
105
+ total++;
106
+ }
107
+
108
+ if (*drops)
109
+ goto reap_it;
110
+
111
+ usleep(usecs);
112
+
113
+ for (i = total; i < BUFFERS; i++) {
114
+ off_t offset;
115
+
116
+ sqe = io_uring_get_sqe(&ring);
117
+ if (!sqe) {
118
+ fprintf(stderr, "sqe get failed\n");
119
+ goto err;
120
+ }
121
+ offset = BS * (rand() % BUFFERS);
122
+ io_uring_prep_readv(sqe, fd, &vecs[i], 1, offset);
123
+
124
+ ret = io_uring_submit(&ring);
125
+ if (nodrop && ret == -EBUSY) {
126
+ *drops = 1;
127
+ break;
128
+ } else if (ret != 1) {
129
+ fprintf(stderr, "submit got %d, wanted %d\n", ret, 1);
130
+ break;
131
+ }
132
+ total++;
133
+ }
134
+
135
+ reap_it:
136
+ reaped = 0;
137
+ do {
138
+ if (nodrop && !cqe_dropped) {
139
+ /* nodrop should never lose events unless cqe_dropped */
140
+ if (reaped == total)
141
+ break;
142
+ } else {
143
+ if (reaped + *ring.cq.koverflow == total)
144
+ break;
145
+ }
146
+ ret = io_uring_wait_cqe(&ring, &cqe);
147
+ if (nodrop && ret == -EBADR) {
148
+ cqe_dropped = true;
149
+ continue;
150
+ } else if (ret) {
151
+ fprintf(stderr, "wait_cqe=%d\n", ret);
152
+ goto err;
153
+ }
154
+ if (cqe->res != BS) {
155
+ if (!(fault && cqe->res == -EFAULT)) {
156
+ fprintf(stderr, "cqe res %d, wanted %d\n",
157
+ cqe->res, BS);
158
+ goto err;
159
+ }
160
+ }
161
+ io_uring_cqe_seen(&ring, cqe);
162
+ reaped++;
163
+ } while (1);
164
+
165
+ if (!io_uring_peek_cqe(&ring, &cqe)) {
166
+ fprintf(stderr, "found unexpected completion\n");
167
+ goto err;
168
+ }
169
+
170
+ if (!nodrop || cqe_dropped) {
171
+ *drops = *ring.cq.koverflow;
172
+ } else if (*ring.cq.koverflow) {
173
+ fprintf(stderr, "Found %u overflows\n", *ring.cq.koverflow);
174
+ goto err;
175
+ }
176
+
177
+ io_uring_queue_exit(&ring);
178
+ close(fd);
179
+ return T_EXIT_PASS;
180
+ err:
181
+ if (fd != -1)
182
+ close(fd);
183
+ io_uring_queue_exit(&ring);
184
+ return T_EXIT_SKIP;
185
+ }
186
+
187
+ static int reap_events(struct io_uring *ring, unsigned nr_events, int do_wait)
188
+ {
189
+ struct io_uring_cqe *cqe;
190
+ int i, ret = 0, seq = 0;
191
+ unsigned int start_overflow = *ring->cq.koverflow;
192
+ bool dropped = false;
193
+
194
+ for (i = 0; i < nr_events; i++) {
195
+ if (do_wait)
196
+ ret = io_uring_wait_cqe(ring, &cqe);
197
+ else
198
+ ret = io_uring_peek_cqe(ring, &cqe);
199
+ if (do_wait && ret == -EBADR) {
200
+ unsigned int this_drop = *ring->cq.koverflow -
201
+ start_overflow;
202
+
203
+ dropped = true;
204
+ start_overflow = *ring->cq.koverflow;
205
+ assert(this_drop > 0);
206
+ i += (this_drop - 1);
207
+ continue;
208
+ } else if (ret) {
209
+ if (ret != -EAGAIN)
210
+ fprintf(stderr, "cqe peek failed: %d\n", ret);
211
+ break;
212
+ }
213
+ if (!dropped && cqe->user_data != seq) {
214
+ fprintf(stderr, "cqe sequence out-of-order\n");
215
+ fprintf(stderr, "got %d, wanted %d\n", (int) cqe->user_data,
216
+ seq);
217
+ return -EINVAL;
218
+ }
219
+ seq++;
220
+ io_uring_cqe_seen(ring, cqe);
221
+ }
222
+
223
+ return i ? i : ret;
224
+ }
225
+
226
+ /*
227
+ * Submit some NOPs and watch if the overflow is correct
228
+ */
229
+ static int test_overflow(void)
230
+ {
231
+ struct io_uring ring;
232
+ struct io_uring_params p;
233
+ struct io_uring_sqe *sqe;
234
+ unsigned pending;
235
+ int ret, i, j;
236
+
237
+ memset(&p, 0, sizeof(p));
238
+ ret = io_uring_queue_init_params(4, &ring, &p);
239
+ if (ret) {
240
+ fprintf(stderr, "io_uring_queue_init failed %d\n", ret);
241
+ return 1;
242
+ }
243
+
244
+ /* submit 4x4 SQEs, should overflow the ring by 8 */
245
+ pending = 0;
246
+ for (i = 0; i < 4; i++) {
247
+ for (j = 0; j < 4; j++) {
248
+ sqe = io_uring_get_sqe(&ring);
249
+ if (!sqe) {
250
+ fprintf(stderr, "get sqe failed\n");
251
+ goto err;
252
+ }
253
+
254
+ io_uring_prep_nop(sqe);
255
+ sqe->user_data = (i * 4) + j;
256
+ }
257
+
258
+ ret = io_uring_submit(&ring);
259
+ if (ret == 4) {
260
+ pending += 4;
261
+ continue;
262
+ }
263
+ if (p.features & IORING_FEAT_NODROP) {
264
+ if (ret == -EBUSY)
265
+ break;
266
+ }
267
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
268
+ goto err;
269
+ }
270
+
271
+ /* we should now have 8 completions ready */
272
+ ret = reap_events(&ring, pending, 0);
273
+ if (ret < 0)
274
+ goto err;
275
+
276
+ if (!(p.features & IORING_FEAT_NODROP)) {
277
+ if (*ring.cq.koverflow != 8) {
278
+ fprintf(stderr, "cq ring overflow %d, expected 8\n",
279
+ *ring.cq.koverflow);
280
+ goto err;
281
+ }
282
+ }
283
+ io_uring_queue_exit(&ring);
284
+ return 0;
285
+ err:
286
+ io_uring_queue_exit(&ring);
287
+ return 1;
288
+ }
289
+
290
+
291
+ static void submit_one_nop(struct io_uring *ring, int ud)
292
+ {
293
+ struct io_uring_sqe *sqe;
294
+ int ret;
295
+
296
+ sqe = io_uring_get_sqe(ring);
297
+ assert(sqe);
298
+ io_uring_prep_nop(sqe);
299
+ sqe->user_data = ud;
300
+ ret = io_uring_submit(ring);
301
+ assert(ret == 1);
302
+ }
303
+
304
+ /*
305
+ * Create an overflow condition and ensure that SQEs are still processed
306
+ */
307
+ static int test_overflow_handling(bool batch, int cqe_multiple, bool poll,
308
+ bool defer)
309
+ {
310
+ struct io_uring ring;
311
+ struct io_uring_params p;
312
+ int ret, i, j, ud, cqe_count;
313
+ unsigned int count;
314
+ int const N = 8;
315
+ int const LOOPS = 128;
316
+ int const QUEUE_LENGTH = 1024;
317
+ int completions[N];
318
+ int queue[QUEUE_LENGTH];
319
+ int queued = 0;
320
+ int outstanding = 0;
321
+ bool cqe_dropped = false;
322
+
323
+ memset(&completions, 0, sizeof(int) * N);
324
+ memset(&p, 0, sizeof(p));
325
+ p.cq_entries = 2 * cqe_multiple;
326
+ p.flags |= IORING_SETUP_CQSIZE;
327
+
328
+ if (poll)
329
+ p.flags |= IORING_SETUP_IOPOLL;
330
+
331
+ if (defer)
332
+ p.flags |= IORING_SETUP_SINGLE_ISSUER |
333
+ IORING_SETUP_DEFER_TASKRUN;
334
+
335
+ ret = io_uring_queue_init_params(2, &ring, &p);
336
+ if (ret) {
337
+ fprintf(stderr, "io_uring_queue_init failed %d\n", ret);
338
+ return 1;
339
+ }
340
+
341
+ assert(p.cq_entries < N);
342
+ /* submit N SQEs, some should overflow */
343
+ for (i = 0; i < N; i++) {
344
+ submit_one_nop(&ring, i);
345
+ outstanding++;
346
+ }
347
+
348
+ for (i = 0; i < LOOPS; i++) {
349
+ struct io_uring_cqe *cqes[N];
350
+
351
+ if (io_uring_cq_has_overflow(&ring)) {
352
+ /*
353
+ * Flush any overflowed CQEs and process those. Actively
354
+ * flush these to make sure CQEs arrive in vague order
355
+ * of being sent.
356
+ */
357
+ ret = io_uring_get_events(&ring);
358
+ if (ret != 0) {
359
+ fprintf(stderr,
360
+ "io_uring_get_events returned %d\n",
361
+ ret);
362
+ goto err;
363
+ }
364
+ } else if (!cqe_dropped) {
365
+ for (j = 0; j < queued; j++) {
366
+ submit_one_nop(&ring, queue[j]);
367
+ outstanding++;
368
+ }
369
+ queued = 0;
370
+ }
371
+
372
+ /* We have lost some random cqes, stop if no remaining. */
373
+ if (cqe_dropped && outstanding == *ring.cq.koverflow)
374
+ break;
375
+
376
+ ret = io_uring_wait_cqe(&ring, &cqes[0]);
377
+ if (ret == -EBADR) {
378
+ cqe_dropped = true;
379
+ fprintf(stderr, "CQE dropped\n");
380
+ continue;
381
+ } else if (ret != 0) {
382
+ fprintf(stderr, "io_uring_wait_cqes failed %d\n", ret);
383
+ goto err;
384
+ }
385
+ cqe_count = 1;
386
+ if (batch) {
387
+ ret = io_uring_peek_batch_cqe(&ring, &cqes[0], 2);
388
+ if (ret < 0) {
389
+ fprintf(stderr,
390
+ "io_uring_peek_batch_cqe failed %d\n",
391
+ ret);
392
+ goto err;
393
+ }
394
+ cqe_count = ret;
395
+ }
396
+ for (j = 0; j < cqe_count; j++) {
397
+ assert(cqes[j]->user_data < N);
398
+ ud = cqes[j]->user_data;
399
+ completions[ud]++;
400
+ assert(queued < QUEUE_LENGTH);
401
+ queue[queued++] = (int)ud;
402
+ }
403
+ io_uring_cq_advance(&ring, cqe_count);
404
+ outstanding -= cqe_count;
405
+ }
406
+
407
+ /* See if there were any drops by flushing the CQ ring *and* overflow */
408
+ do {
409
+ struct io_uring_cqe *cqe;
410
+
411
+ ret = io_uring_get_events(&ring);
412
+ if (ret < 0) {
413
+ if (ret == -EBADR) {
414
+ fprintf(stderr, "CQE dropped\n");
415
+ cqe_dropped = true;
416
+ break;
417
+ }
418
+ goto err;
419
+ }
420
+ if (outstanding && !io_uring_cq_ready(&ring))
421
+ ret = io_uring_wait_cqe_timeout(&ring, &cqe, NULL);
422
+
423
+ if (ret && ret != -ETIME) {
424
+ if (ret == -EBADR) {
425
+ fprintf(stderr, "CQE dropped\n");
426
+ cqe_dropped = true;
427
+ break;
428
+ }
429
+ fprintf(stderr, "wait_cqe_timeout = %d\n", ret);
430
+ goto err;
431
+ }
432
+ count = io_uring_cq_ready(&ring);
433
+ io_uring_cq_advance(&ring, count);
434
+ outstanding -= count;
435
+ } while (count);
436
+
437
+ io_uring_queue_exit(&ring);
438
+
439
+ /* Make sure that completions come back in the same order they were
440
+ * sent. If they come back unfairly then this will concentrate on a
441
+ * couple of indices.
442
+ */
443
+ for (i = 1; !cqe_dropped && i < N; i++) {
444
+ if (abs(completions[i] - completions[i - 1]) > 1) {
445
+ fprintf(stderr, "bad completion size %d %d\n",
446
+ completions[i], completions[i - 1]);
447
+ goto err;
448
+ }
449
+ }
450
+ return 0;
451
+ err:
452
+ io_uring_queue_exit(&ring);
453
+ return 1;
454
+ }
455
+
456
+ int main(int argc, char *argv[])
457
+ {
458
+ const char *fname = ".cq-overflow";
459
+ unsigned iters, drops;
460
+ unsigned long usecs;
461
+ int ret;
462
+ int i;
463
+ bool can_defer;
464
+
465
+ if (argc > 1)
466
+ return T_EXIT_SKIP;
467
+
468
+ can_defer = t_probe_defer_taskrun();
469
+ for (i = 0; i < 16; i++) {
470
+ bool batch = i & 1;
471
+ int mult = (i & 2) ? 1 : 2;
472
+ bool poll = i & 4;
473
+ bool defer = i & 8;
474
+
475
+ if (defer && !can_defer)
476
+ continue;
477
+
478
+ ret = test_overflow_handling(batch, mult, poll, defer);
479
+ if (ret) {
480
+ fprintf(stderr, "test_overflow_handling("
481
+ "batch=%d, mult=%d, poll=%d, defer=%d) failed\n",
482
+ batch, mult, poll, defer);
483
+ goto err;
484
+ }
485
+ }
486
+
487
+ ret = test_overflow();
488
+ if (ret) {
489
+ fprintf(stderr, "test_overflow failed\n");
490
+ return ret;
491
+ }
492
+
493
+ t_create_file(fname, FILE_SIZE);
494
+
495
+ vecs = t_create_buffers(BUFFERS, BS);
496
+
497
+ iters = 0;
498
+ usecs = 1000;
499
+ do {
500
+ drops = 0;
501
+
502
+ ret = test_io(fname, usecs, &drops, 0);
503
+ if (ret == T_EXIT_SKIP)
504
+ break;
505
+ else if (ret != T_EXIT_PASS) {
506
+ fprintf(stderr, "test_io nofault failed\n");
507
+ goto err;
508
+ }
509
+ if (drops)
510
+ break;
511
+ usecs = (usecs * 12) / 10;
512
+ iters++;
513
+ } while (iters < 40);
514
+
515
+ if (test_io(fname, usecs, &drops, 0) == T_EXIT_FAIL) {
516
+ fprintf(stderr, "test_io nofault failed\n");
517
+ goto err;
518
+ }
519
+
520
+ if (test_io(fname, usecs, &drops, 1) == T_EXIT_FAIL) {
521
+ fprintf(stderr, "test_io fault failed\n");
522
+ goto err;
523
+ }
524
+
525
+ unlink(fname);
526
+ return T_EXIT_PASS;
527
+ err:
528
+ unlink(fname);
529
+ return T_EXIT_FAIL;
530
+ }
@@ -0,0 +1,103 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test CQ peek-batch
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
+
13
+ #include "liburing.h"
14
+ #include "helpers.h"
15
+
16
+ static int queue_n_nops(struct io_uring *ring, int n, int offset)
17
+ {
18
+ struct io_uring_sqe *sqe;
19
+ int i, ret;
20
+
21
+ for (i = 0; i < n; i++) {
22
+ sqe = io_uring_get_sqe(ring);
23
+ if (!sqe) {
24
+ printf("get sqe failed\n");
25
+ goto err;
26
+ }
27
+
28
+ io_uring_prep_nop(sqe);
29
+ sqe->user_data = i + offset;
30
+ }
31
+
32
+ ret = io_uring_submit(ring);
33
+ if (ret < n) {
34
+ printf("Submitted only %d\n", ret);
35
+ goto err;
36
+ } else if (ret < 0) {
37
+ printf("sqe submit failed: %d\n", ret);
38
+ goto err;
39
+ }
40
+
41
+ return 0;
42
+ err:
43
+ return 1;
44
+ }
45
+
46
+ #define CHECK_BATCH(ring, got, cqes, count, expected) do {\
47
+ got = io_uring_peek_batch_cqe((ring), cqes, count);\
48
+ if (got != expected) {\
49
+ printf("Got %d CQs, expected %d\n", got, expected);\
50
+ goto err;\
51
+ }\
52
+ } while(0)
53
+
54
+ int main(int argc, char *argv[])
55
+ {
56
+ struct io_uring_cqe *cqes[8];
57
+ struct io_uring ring;
58
+ int ret, i;
59
+ unsigned got;
60
+
61
+ if (argc > 1)
62
+ return T_EXIT_SKIP;
63
+
64
+ ret = io_uring_queue_init(4, &ring, 0);
65
+ if (ret) {
66
+ printf("ring setup failed\n");
67
+ return T_EXIT_FAIL;
68
+
69
+ }
70
+
71
+ CHECK_BATCH(&ring, got, cqes, 4, 0);
72
+ if (queue_n_nops(&ring, 4, 0))
73
+ goto err;
74
+
75
+ CHECK_BATCH(&ring, got, cqes, 4, 4);
76
+ for (i=0;i<4;i++) {
77
+ if (i != cqes[i]->user_data) {
78
+ printf("Got user_data %" PRIu64 ", expected %d\n",
79
+ (uint64_t) cqes[i]->user_data, i);
80
+ goto err;
81
+ }
82
+ }
83
+
84
+ if (queue_n_nops(&ring, 4, 4))
85
+ goto err;
86
+
87
+ io_uring_cq_advance(&ring, 4);
88
+ CHECK_BATCH(&ring, got, cqes, 4, 4);
89
+ for (i=0;i<4;i++) {
90
+ if (i + 4 != cqes[i]->user_data) {
91
+ printf("Got user_data %" PRIu64 ", expected %d\n",
92
+ (uint64_t) cqes[i]->user_data, i + 4);
93
+ goto err;
94
+ }
95
+ }
96
+
97
+ io_uring_cq_advance(&ring, 8);
98
+ io_uring_queue_exit(&ring);
99
+ return T_EXIT_PASS;
100
+ err:
101
+ io_uring_queue_exit(&ring);
102
+ return T_EXIT_FAIL;
103
+ }