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,500 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test installing a direct descriptor into the regular
4
+ * file table
5
+ *
6
+ */
7
+ #include <errno.h>
8
+ #include <stdio.h>
9
+ #include <unistd.h>
10
+ #include <stdlib.h>
11
+ #include <string.h>
12
+ #include <fcntl.h>
13
+
14
+ #include "liburing.h"
15
+ #include "helpers.h"
16
+
17
+ static int no_fd_install;
18
+
19
+ /* test that O_CLOEXEC is accepted, and others are not */
20
+ static int test_flags(struct io_uring *ring, int async)
21
+ {
22
+ struct io_uring_sqe *sqe;
23
+ struct io_uring_cqe *cqe;
24
+ int ret, fds[2], fd;
25
+
26
+ if (pipe(fds) < 0) {
27
+ perror("pipe");
28
+ return T_EXIT_FAIL;
29
+ }
30
+
31
+ ret = io_uring_register_files(ring, &fds[0], 1);
32
+ if (ret) {
33
+ fprintf(stderr, "failed register files %d\n", ret);
34
+ return T_EXIT_FAIL;
35
+ }
36
+
37
+ /* check that setting an invalid flag fails */
38
+ sqe = io_uring_get_sqe(ring);
39
+ io_uring_prep_fixed_fd_install(sqe, 0, 1U << 17);
40
+ io_uring_submit(ring);
41
+
42
+ ret = io_uring_wait_cqe(ring, &cqe);
43
+ if (ret) {
44
+ fprintf(stderr, "wait cqe %d\n", ret);
45
+ return T_EXIT_FAIL;
46
+ }
47
+ if (cqe->res != -EINVAL) {
48
+ fprintf(stderr, "unexpected cqe res %d\n", cqe->res);
49
+ return T_EXIT_FAIL;
50
+ }
51
+ io_uring_cqe_seen(ring, cqe);
52
+
53
+ /* check that IORING_FIXED_FD_NO_CLOEXEC is accepted */
54
+ sqe = io_uring_get_sqe(ring);
55
+ io_uring_prep_fixed_fd_install(sqe, 0, IORING_FIXED_FD_NO_CLOEXEC);
56
+ if (async)
57
+ sqe->flags |= IOSQE_ASYNC;
58
+ io_uring_submit(ring);
59
+
60
+ ret = io_uring_wait_cqe(ring, &cqe);
61
+ if (ret) {
62
+ fprintf(stderr, "wait cqe %d\n", ret);
63
+ return T_EXIT_FAIL;
64
+ }
65
+ if (cqe->res < 0) {
66
+ fprintf(stderr, "unexpected cqe res %d\n", cqe->res);
67
+ return T_EXIT_FAIL;
68
+ }
69
+ fd = cqe->res;
70
+ io_uring_cqe_seen(ring, cqe);
71
+
72
+ close(fds[0]);
73
+ close(fds[1]);
74
+ close(fd);
75
+ io_uring_unregister_files(ring);
76
+
77
+ return T_EXIT_PASS;
78
+ }
79
+
80
+ static int test_linked(struct io_uring *ring)
81
+ {
82
+ struct io_uring_sqe *sqe;
83
+ struct io_uring_cqe *cqe;
84
+ int ret, fds[2], fd, i;
85
+
86
+ if (pipe(fds) < 0) {
87
+ perror("pipe");
88
+ return T_EXIT_FAIL;
89
+ }
90
+
91
+ ret = io_uring_register_files(ring, &fds[0], 1);
92
+ if (ret) {
93
+ fprintf(stderr, "failed register files %d\n", ret);
94
+ return T_EXIT_FAIL;
95
+ }
96
+
97
+ sqe = io_uring_get_sqe(ring);
98
+ io_uring_prep_nop(sqe);
99
+ sqe->flags |= IOSQE_IO_LINK;
100
+ sqe->user_data = 1;
101
+
102
+ sqe = io_uring_get_sqe(ring);
103
+ io_uring_prep_fixed_fd_install(sqe, 0, 0);
104
+ sqe->user_data = 2;
105
+
106
+ ret = io_uring_submit(ring);
107
+ if (ret != 2) {
108
+ fprintf(stderr, "submit: %d\n", ret);
109
+ return T_EXIT_FAIL;
110
+ }
111
+
112
+ fd = -1;
113
+ for (i = 0; i < 2; i++) {
114
+ ret = io_uring_wait_cqe(ring, &cqe);
115
+ if (ret) {
116
+ fprintf(stderr, "wait cqe %d\n", ret);
117
+ return T_EXIT_FAIL;
118
+ }
119
+ if (cqe->res < 0) {
120
+ fprintf(stderr, "unexpected cqe res %d\n", cqe->res);
121
+ return T_EXIT_FAIL;
122
+ }
123
+ if (cqe->user_data == 2)
124
+ fd = cqe->res;
125
+ io_uring_cqe_seen(ring, cqe);
126
+ }
127
+
128
+ close(fds[0]);
129
+ close(fds[1]);
130
+ if (fd != -1)
131
+ close(fd);
132
+ io_uring_unregister_files(ring);
133
+ return T_EXIT_PASS;
134
+ }
135
+
136
+ /* test not setting IOSQE_FIXED_FILE */
137
+ static int test_not_fixed(struct io_uring *ring)
138
+ {
139
+ struct io_uring_sqe *sqe;
140
+ struct io_uring_cqe *cqe;
141
+ int ret, fds[2];
142
+
143
+ if (pipe(fds) < 0) {
144
+ perror("pipe");
145
+ return T_EXIT_FAIL;
146
+ }
147
+
148
+ ret = io_uring_register_files(ring, &fds[0], 1);
149
+ if (ret) {
150
+ fprintf(stderr, "failed register files %d\n", ret);
151
+ return T_EXIT_FAIL;
152
+ }
153
+
154
+ sqe = io_uring_get_sqe(ring);
155
+ io_uring_prep_fixed_fd_install(sqe, 0, 0);
156
+ sqe->flags &= ~IOSQE_FIXED_FILE;
157
+ io_uring_submit(ring);
158
+
159
+ ret = io_uring_wait_cqe(ring, &cqe);
160
+ if (ret) {
161
+ fprintf(stderr, "wait cqe %d\n", ret);
162
+ return T_EXIT_FAIL;
163
+ }
164
+ if (cqe->res != -EBADF) {
165
+ fprintf(stderr, "unexpected cqe res %d\n", cqe->res);
166
+ return T_EXIT_FAIL;
167
+ }
168
+
169
+ io_uring_cqe_seen(ring, cqe);
170
+
171
+ close(fds[0]);
172
+ close(fds[1]);
173
+ io_uring_unregister_files(ring);
174
+
175
+ return T_EXIT_PASS;
176
+ }
177
+
178
+ /* test invalid direct descriptor indexes */
179
+ static int test_bad_fd(struct io_uring *ring, int some_fd)
180
+ {
181
+ struct io_uring_sqe *sqe;
182
+ struct io_uring_cqe *cqe;
183
+ int ret;
184
+
185
+ sqe = io_uring_get_sqe(ring);
186
+ io_uring_prep_fixed_fd_install(sqe, some_fd, 0);
187
+ io_uring_submit(ring);
188
+
189
+ ret = io_uring_wait_cqe(ring, &cqe);
190
+ if (ret) {
191
+ fprintf(stderr, "wait cqe %d\n", ret);
192
+ return T_EXIT_FAIL;
193
+ }
194
+ if (cqe->res != -EBADF) {
195
+ fprintf(stderr, "unexpected cqe res %d\n", cqe->res);
196
+ return T_EXIT_FAIL;
197
+ }
198
+
199
+ io_uring_cqe_seen(ring, cqe);
200
+ return T_EXIT_PASS;
201
+ }
202
+
203
+ /* test basic functionality of shifting a direct descriptor to a normal file */
204
+ static int test_working(struct io_uring *ring)
205
+ {
206
+ struct io_uring_sqe *sqe;
207
+ struct io_uring_cqe *cqe;
208
+ int ret, fds[2];
209
+ char buf[32];
210
+
211
+ if (pipe(fds) < 0) {
212
+ perror("pipe");
213
+ return T_EXIT_FAIL;
214
+ }
215
+
216
+ /* register read side */
217
+ ret = io_uring_register_files(ring, &fds[0], 1);
218
+ if (ret) {
219
+ fprintf(stderr, "failed register files %d\n", ret);
220
+ return T_EXIT_FAIL;
221
+ }
222
+
223
+ /* close normal descriptor */
224
+ close(fds[0]);
225
+
226
+ /* normal read should fail */
227
+ ret = read(fds[0], buf, 1);
228
+ if (ret != -1) {
229
+ fprintf(stderr, "unexpected read ret %d\n", ret);
230
+ return T_EXIT_FAIL;
231
+ }
232
+ if (errno != EBADF) {
233
+ fprintf(stderr, "unexpected read failure %d\n", errno);
234
+ return T_EXIT_FAIL;
235
+ }
236
+
237
+ /* verify we can read the data */
238
+ sqe = io_uring_get_sqe(ring);
239
+ io_uring_prep_read(sqe, 0, buf, sizeof(buf), 0);
240
+ sqe->flags |= IOSQE_FIXED_FILE;
241
+ io_uring_submit(ring);
242
+
243
+ /* put some data in the pipe */
244
+ ret = write(fds[1], "Hello", 5);
245
+ if (ret < 0) {
246
+ perror("write");
247
+ return T_EXIT_FAIL;
248
+ } else if (ret != 5) {
249
+ fprintf(stderr, "short write %d\n", ret);
250
+ return T_EXIT_FAIL;
251
+ }
252
+
253
+ ret = io_uring_wait_cqe(ring, &cqe);
254
+ if (ret) {
255
+ fprintf(stderr, "wait cqe %d\n", ret);
256
+ return T_EXIT_FAIL;
257
+ }
258
+ if (cqe->res != 5) {
259
+ fprintf(stderr, "weird pipe read ret %d\n", cqe->res);
260
+ return T_EXIT_FAIL;
261
+ }
262
+ io_uring_cqe_seen(ring, cqe);
263
+
264
+ /* fixed pipe read worked, now re-install as a regular fd */
265
+ sqe = io_uring_get_sqe(ring);
266
+ io_uring_prep_fixed_fd_install(sqe, 0, 0);
267
+ io_uring_submit(ring);
268
+
269
+ ret = io_uring_wait_cqe(ring, &cqe);
270
+ if (ret) {
271
+ fprintf(stderr, "wait cqe %d\n", ret);
272
+ return T_EXIT_FAIL;
273
+ }
274
+ if (cqe->res == -EINVAL) {
275
+ no_fd_install = 1;
276
+ return T_EXIT_SKIP;
277
+ }
278
+ if (cqe->res < 0) {
279
+ fprintf(stderr, "failed install fd: %d\n", cqe->res);
280
+ return T_EXIT_FAIL;
281
+ }
282
+ /* stash new pipe read side fd in old spot */
283
+ fds[0] = cqe->res;
284
+ io_uring_cqe_seen(ring, cqe);
285
+
286
+ ret = write(fds[1], "Hello", 5);
287
+ if (ret < 0) {
288
+ perror("write");
289
+ return T_EXIT_FAIL;
290
+ } else if (ret != 5) {
291
+ fprintf(stderr, "short write %d\n", ret);
292
+ return T_EXIT_FAIL;
293
+ }
294
+
295
+ /* normal pipe read should now work with new fd */
296
+ ret = read(fds[0], buf, sizeof(buf));
297
+ if (ret != 5) {
298
+ fprintf(stderr, "unexpected read ret %d\n", ret);
299
+ return T_EXIT_FAIL;
300
+ }
301
+
302
+ /* close fixed file */
303
+ sqe = io_uring_get_sqe(ring);
304
+ io_uring_prep_close_direct(sqe, 0);
305
+ io_uring_submit(ring);
306
+
307
+ ret = io_uring_wait_cqe(ring, &cqe);
308
+ if (ret) {
309
+ fprintf(stderr, "wait cqe %d\n", ret);
310
+ return T_EXIT_FAIL;
311
+ }
312
+ if (cqe->res) {
313
+ fprintf(stderr, "close fixed fd %d\n", cqe->res);
314
+ return T_EXIT_FAIL;
315
+ }
316
+ io_uring_cqe_seen(ring, cqe);
317
+
318
+ ret = write(fds[1], "Hello", 5);
319
+ if (ret < 0) {
320
+ perror("write");
321
+ return T_EXIT_FAIL;
322
+ } else if (ret != 5) {
323
+ fprintf(stderr, "short write %d\n", ret);
324
+ return T_EXIT_FAIL;
325
+ }
326
+
327
+ /* normal pipe read should still work with new fd */
328
+ ret = read(fds[0], buf, sizeof(buf));
329
+ if (ret != 5) {
330
+ fprintf(stderr, "unexpected read ret %d\n", ret);
331
+ return T_EXIT_FAIL;
332
+ }
333
+
334
+ /* fixed fd pipe read should now fail */
335
+ sqe = io_uring_get_sqe(ring);
336
+ io_uring_prep_read(sqe, 0, buf, sizeof(buf), 0);
337
+ sqe->flags = IOSQE_FIXED_FILE;
338
+ io_uring_submit(ring);
339
+
340
+ /* put some data in the pipe */
341
+ ret = write(fds[1], "Hello", 5);
342
+ if (ret < 0) {
343
+ perror("write");
344
+ return T_EXIT_FAIL;
345
+ } else if (ret != 5) {
346
+ fprintf(stderr, "short write %d\n", ret);
347
+ return T_EXIT_FAIL;
348
+ }
349
+
350
+ ret = io_uring_wait_cqe(ring, &cqe);
351
+ if (ret) {
352
+ fprintf(stderr, "wait cqe %d\n", ret);
353
+ return T_EXIT_FAIL;
354
+ }
355
+ if (cqe->res != -EBADF) {
356
+ fprintf(stderr, "weird pipe read ret %d\n", cqe->res);
357
+ return T_EXIT_FAIL;
358
+ }
359
+ io_uring_cqe_seen(ring, cqe);
360
+
361
+ close(fds[0]);
362
+ close(fds[1]);
363
+ io_uring_unregister_files(ring);
364
+ return T_EXIT_PASS;
365
+ }
366
+
367
+ static int test_creds(struct io_uring *ring, int async)
368
+ {
369
+ struct io_uring_sqe *sqe;
370
+ struct io_uring_cqe *cqe;
371
+ int cred_id, ret, fds[2];
372
+
373
+ if (pipe(fds) < 0) {
374
+ perror("pipe");
375
+ return T_EXIT_FAIL;
376
+ }
377
+
378
+ ret = io_uring_register_files(ring, &fds[0], 1);
379
+ if (ret) {
380
+ fprintf(stderr, "failed register files %d\n", ret);
381
+ return T_EXIT_FAIL;
382
+ }
383
+
384
+ cred_id = io_uring_register_personality(ring);
385
+ if (cred_id < 0) {
386
+ fprintf(stderr, "Failed registering creds: %d\n", cred_id);
387
+ return T_EXIT_FAIL;
388
+ }
389
+
390
+ /* check that asking for creds fails */
391
+ sqe = io_uring_get_sqe(ring);
392
+ io_uring_prep_fixed_fd_install(sqe, 0, 0);
393
+ if (async)
394
+ sqe->flags |= IOSQE_ASYNC;
395
+ sqe->personality = cred_id;
396
+ io_uring_submit(ring);
397
+
398
+ ret = io_uring_wait_cqe(ring, &cqe);
399
+ if (ret) {
400
+ fprintf(stderr, "wait cqe %d\n", ret);
401
+ return T_EXIT_FAIL;
402
+ }
403
+ if (cqe->res > 0) {
404
+ fprintf(stderr, "install succeeded with creds\n");
405
+ return T_EXIT_FAIL;
406
+ }
407
+ if (cqe->res != -EPERM) {
408
+ fprintf(stderr, "unexpected cqe res %d\n", cqe->res);
409
+ return T_EXIT_FAIL;
410
+ }
411
+ io_uring_cqe_seen(ring, cqe);
412
+
413
+ close(fds[0]);
414
+ close(fds[1]);
415
+ io_uring_unregister_files(ring);
416
+ io_uring_unregister_personality(ring, cred_id);
417
+ return T_EXIT_PASS;
418
+ }
419
+
420
+ int main(int argc, char *argv[])
421
+ {
422
+ struct io_uring ring;
423
+ int ret;
424
+
425
+ if (argc > 1)
426
+ return T_EXIT_SKIP;
427
+
428
+ ret = io_uring_queue_init(4, &ring, 0);
429
+ if (ret) {
430
+ fprintf(stderr, "ring setup failed: %d\n", ret);
431
+ return T_EXIT_FAIL;
432
+ }
433
+
434
+ ret = test_working(&ring);
435
+ if (ret != T_EXIT_PASS) {
436
+ if (ret == T_EXIT_FAIL)
437
+ fprintf(stderr, "test_working failed\n");
438
+ return ret;
439
+ }
440
+ if (no_fd_install)
441
+ return T_EXIT_SKIP;
442
+
443
+ ret = test_bad_fd(&ring, 0);
444
+ if (ret != T_EXIT_PASS) {
445
+ if (ret == T_EXIT_FAIL)
446
+ fprintf(stderr, "test_bad_fd 0 failed\n");
447
+ return ret;
448
+ }
449
+
450
+ ret = test_bad_fd(&ring, 500);
451
+ if (ret != T_EXIT_PASS) {
452
+ if (ret == T_EXIT_FAIL)
453
+ fprintf(stderr, "test_bad_fd 500 failed\n");
454
+ return ret;
455
+ }
456
+
457
+ ret = test_not_fixed(&ring);
458
+ if (ret != T_EXIT_PASS) {
459
+ if (ret == T_EXIT_FAIL)
460
+ fprintf(stderr, "test_not_fixed failed\n");
461
+ return ret;
462
+ }
463
+
464
+ ret = test_flags(&ring, 0);
465
+ if (ret != T_EXIT_PASS) {
466
+ if (ret == T_EXIT_FAIL)
467
+ fprintf(stderr, "test_flags 0 failed\n");
468
+ return ret;
469
+ }
470
+
471
+ ret = test_flags(&ring, 1);
472
+ if (ret != T_EXIT_PASS) {
473
+ if (ret == T_EXIT_FAIL)
474
+ fprintf(stderr, "test_flags 1 failed\n");
475
+ return ret;
476
+ }
477
+
478
+ ret = test_creds(&ring, 0);
479
+ if (ret != T_EXIT_PASS) {
480
+ if (ret == T_EXIT_FAIL)
481
+ fprintf(stderr, "test_creds 0 failed\n");
482
+ return ret;
483
+ }
484
+
485
+ ret = test_creds(&ring, 1);
486
+ if (ret != T_EXIT_PASS) {
487
+ if (ret == T_EXIT_FAIL)
488
+ fprintf(stderr, "test_creds 1 failed\n");
489
+ return ret;
490
+ }
491
+
492
+ ret = test_linked(&ring);
493
+ if (ret != T_EXIT_PASS) {
494
+ if (ret == T_EXIT_FAIL)
495
+ fprintf(stderr, "test_linked failed\n");
496
+ return ret;
497
+ }
498
+
499
+ return T_EXIT_PASS;
500
+ }
@@ -0,0 +1,237 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: run various fixed file fd passing 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
+
13
+ #include "liburing.h"
14
+ #include "helpers.h"
15
+
16
+ #define FSIZE 128
17
+ #define PAT 0x9a
18
+ #define USER_DATA 0x89
19
+
20
+ static int no_fd_pass;
21
+
22
+ static int verify_fixed_read(struct io_uring *ring, int fixed_fd, int fail)
23
+ {
24
+ struct io_uring_sqe *sqe;
25
+ struct io_uring_cqe *cqe;
26
+ unsigned char buf[FSIZE];
27
+ int i;
28
+
29
+ sqe = io_uring_get_sqe(ring);
30
+ io_uring_prep_read(sqe, fixed_fd, buf, FSIZE, 0);
31
+ sqe->flags |= IOSQE_FIXED_FILE;
32
+ io_uring_submit(ring);
33
+
34
+ io_uring_wait_cqe(ring, &cqe);
35
+ if (cqe->res != FSIZE) {
36
+ if (fail && cqe->res == -EBADF)
37
+ return 0;
38
+ fprintf(stderr, "Read: %d\n", cqe->res);
39
+ return 1;
40
+ }
41
+ io_uring_cqe_seen(ring, cqe);
42
+
43
+ for (i = 0; i < FSIZE; i++) {
44
+ if (buf[i] != PAT) {
45
+ fprintf(stderr, "got %x, wanted %x\n", buf[i], PAT);
46
+ return 1;
47
+ }
48
+ }
49
+
50
+ return 0;
51
+ }
52
+
53
+ static int test(const char *filename, int source_fd, int target_fd)
54
+ {
55
+ struct io_uring sring, dring;
56
+ struct io_uring_sqe *sqe;
57
+ struct io_uring_cqe *cqe;
58
+ int ret;
59
+
60
+ ret = io_uring_queue_init(8, &sring, 0);
61
+ if (ret) {
62
+ fprintf(stderr, "ring setup failed: %d\n", ret);
63
+ return T_EXIT_FAIL;
64
+ }
65
+ ret = io_uring_queue_init(8, &dring, 0);
66
+ if (ret) {
67
+ fprintf(stderr, "ring setup failed: %d\n", ret);
68
+ return T_EXIT_FAIL;
69
+ }
70
+
71
+ ret = io_uring_register_files_sparse(&sring, 8);
72
+ if (ret) {
73
+ if (ret == -EINVAL)
74
+ return T_EXIT_SKIP;
75
+ fprintf(stderr, "register files failed %d\n", ret);
76
+ return T_EXIT_FAIL;
77
+ }
78
+ ret = io_uring_register_files_sparse(&dring, 8);
79
+ if (ret) {
80
+ fprintf(stderr, "register files failed %d\n", ret);
81
+ return T_EXIT_FAIL;
82
+ }
83
+ if (target_fd == IORING_FILE_INDEX_ALLOC) {
84
+ /* we want to test installing into a non-zero slot */
85
+ ret = io_uring_register_file_alloc_range(&dring, 1, 1);
86
+ if (ret) {
87
+ fprintf(stderr, "io_uring_register_file_alloc_range %d\n", ret);
88
+ return T_EXIT_FAIL;
89
+ }
90
+ }
91
+
92
+ /* open direct descriptor */
93
+ sqe = io_uring_get_sqe(&sring);
94
+ io_uring_prep_openat_direct(sqe, AT_FDCWD, filename, 0, 0644, source_fd);
95
+ io_uring_submit(&sring);
96
+ ret = io_uring_wait_cqe(&sring, &cqe);
97
+ if (ret) {
98
+ fprintf(stderr, "wait cqe failed %d\n", ret);
99
+ return T_EXIT_FAIL;
100
+ }
101
+ if (cqe->res) {
102
+ fprintf(stderr, "cqe res %d\n", cqe->res);
103
+ return T_EXIT_FAIL;
104
+ }
105
+ io_uring_cqe_seen(&sring, cqe);
106
+
107
+ /* verify data is sane for source ring */
108
+ if (verify_fixed_read(&sring, source_fd, 0))
109
+ return T_EXIT_FAIL;
110
+
111
+ /* send direct descriptor to destination ring */
112
+ sqe = io_uring_get_sqe(&sring);
113
+ if (target_fd == IORING_FILE_INDEX_ALLOC) {
114
+ io_uring_prep_msg_ring_fd_alloc(sqe, dring.ring_fd, source_fd,
115
+ USER_DATA, 0);
116
+ } else {
117
+
118
+ io_uring_prep_msg_ring_fd(sqe, dring.ring_fd, source_fd,
119
+ target_fd, USER_DATA, 0);
120
+ }
121
+ io_uring_submit(&sring);
122
+
123
+ ret = io_uring_wait_cqe(&sring, &cqe);
124
+ if (ret) {
125
+ fprintf(stderr, "wait cqe failed %d\n", ret);
126
+ return T_EXIT_FAIL;
127
+ }
128
+ if (cqe->res < 0) {
129
+ if (cqe->res == -EINVAL && !no_fd_pass) {
130
+ no_fd_pass = 1;
131
+ return T_EXIT_SKIP;
132
+ }
133
+ fprintf(stderr, "msg_ring failed %d\n", cqe->res);
134
+ return T_EXIT_FAIL;
135
+ }
136
+ io_uring_cqe_seen(&sring, cqe);
137
+
138
+ /* get posted completion for the passing */
139
+ ret = io_uring_wait_cqe(&dring, &cqe);
140
+ if (ret) {
141
+ fprintf(stderr, "wait cqe failed %d\n", ret);
142
+ return T_EXIT_FAIL;
143
+ }
144
+ if (cqe->user_data != USER_DATA) {
145
+ fprintf(stderr, "bad user_data %ld\n", (long) cqe->res);
146
+ return T_EXIT_FAIL;
147
+ }
148
+ if (cqe->res < 0) {
149
+ fprintf(stderr, "bad result %i\n", cqe->res);
150
+ return T_EXIT_FAIL;
151
+ }
152
+ if (target_fd == IORING_FILE_INDEX_ALLOC) {
153
+ if (cqe->res != 1) {
154
+ fprintf(stderr, "invalid allocated index %i\n", cqe->res);
155
+ return T_EXIT_FAIL;
156
+ }
157
+ target_fd = cqe->res;
158
+ }
159
+ io_uring_cqe_seen(&dring, cqe);
160
+
161
+ /* now verify we can read the sane data from the destination ring */
162
+ if (verify_fixed_read(&dring, target_fd, 0))
163
+ return T_EXIT_FAIL;
164
+
165
+ /* close descriptor in source ring */
166
+ sqe = io_uring_get_sqe(&sring);
167
+ io_uring_prep_close_direct(sqe, source_fd);
168
+ io_uring_submit(&sring);
169
+
170
+ ret = io_uring_wait_cqe(&sring, &cqe);
171
+ if (ret) {
172
+ fprintf(stderr, "wait cqe failed %d\n", ret);
173
+ return T_EXIT_FAIL;
174
+ }
175
+ if (cqe->res) {
176
+ fprintf(stderr, "direct close failed %d\n", cqe->res);
177
+ return T_EXIT_FAIL;
178
+ }
179
+ io_uring_cqe_seen(&sring, cqe);
180
+
181
+ /* check that source ring fails after close */
182
+ if (verify_fixed_read(&sring, source_fd, 1))
183
+ return T_EXIT_FAIL;
184
+
185
+ /* check we can still read from destination ring */
186
+ if (verify_fixed_read(&dring, target_fd, 0))
187
+ return T_EXIT_FAIL;
188
+
189
+ io_uring_queue_exit(&sring);
190
+ io_uring_queue_exit(&dring);
191
+ return T_EXIT_PASS;
192
+ }
193
+
194
+ int main(int argc, char *argv[])
195
+ {
196
+ char fname[80];
197
+ int ret;
198
+
199
+ if (argc > 1)
200
+ return T_EXIT_SKIP;
201
+
202
+ sprintf(fname, ".fd-pass.%d", getpid());
203
+ t_create_file_pattern(fname, FSIZE, PAT);
204
+
205
+ ret = test(fname, 0, 1);
206
+ if (ret == T_EXIT_FAIL) {
207
+ fprintf(stderr, "test failed 0 1\n");
208
+ ret = T_EXIT_FAIL;
209
+ }
210
+
211
+ ret = test(fname, 0, 2);
212
+ if (ret == T_EXIT_FAIL) {
213
+ fprintf(stderr, "test failed 0 2\n");
214
+ ret = T_EXIT_FAIL;
215
+ }
216
+
217
+ ret = test(fname, 1, 1);
218
+ if (ret == T_EXIT_FAIL) {
219
+ fprintf(stderr, "test failed 1 1\n");
220
+ ret = T_EXIT_FAIL;
221
+ }
222
+
223
+ ret = test(fname, 1, 0);
224
+ if (ret == T_EXIT_FAIL) {
225
+ fprintf(stderr, "test failed 1 0\n");
226
+ ret = T_EXIT_FAIL;
227
+ }
228
+
229
+ ret = test(fname, 1, IORING_FILE_INDEX_ALLOC);
230
+ if (ret == T_EXIT_FAIL) {
231
+ fprintf(stderr, "test failed 1 ALLOC\n");
232
+ ret = T_EXIT_FAIL;
233
+ }
234
+
235
+ unlink(fname);
236
+ return ret;
237
+ }