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,1189 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: run various file registration 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 <limits.h>
13
+ #include <sys/resource.h>
14
+
15
+ #include "helpers.h"
16
+ #include "liburing.h"
17
+
18
+ static int no_update = 0;
19
+
20
+ static void close_files(int *files, int nr_files, int add)
21
+ {
22
+ char fname[32];
23
+ int i;
24
+
25
+ for (i = 0; i < nr_files; i++) {
26
+ if (files)
27
+ close(files[i]);
28
+ if (!add)
29
+ sprintf(fname, ".reg.%d", i);
30
+ else
31
+ sprintf(fname, ".add.%d", i + add);
32
+ unlink(fname);
33
+ }
34
+ if (files)
35
+ free(files);
36
+ }
37
+
38
+ static int *open_files(int nr_files, int extra, int add)
39
+ {
40
+ char fname[32];
41
+ int *files;
42
+ int i;
43
+
44
+ files = t_calloc(nr_files + extra, sizeof(int));
45
+
46
+ for (i = 0; i < nr_files; i++) {
47
+ if (!add)
48
+ sprintf(fname, ".reg.%d", i);
49
+ else
50
+ sprintf(fname, ".add.%d", i + add);
51
+ files[i] = open(fname, O_RDWR | O_CREAT, 0644);
52
+ if (files[i] < 0) {
53
+ perror("open");
54
+ free(files);
55
+ files = NULL;
56
+ break;
57
+ }
58
+ }
59
+ if (extra) {
60
+ for (i = nr_files; i < nr_files + extra; i++)
61
+ files[i] = -1;
62
+ }
63
+
64
+ return files;
65
+ }
66
+
67
+ static int test_shrink(struct io_uring *ring)
68
+ {
69
+ int ret, off, fd;
70
+ int *files;
71
+
72
+ files = open_files(50, 0, 0);
73
+ ret = io_uring_register_files(ring, files, 50);
74
+ if (ret) {
75
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
76
+ goto err;
77
+ }
78
+
79
+ off = 0;
80
+ do {
81
+ fd = -1;
82
+ ret = io_uring_register_files_update(ring, off, &fd, 1);
83
+ if (ret != 1) {
84
+ if (off == 50 && ret == -EINVAL)
85
+ break;
86
+ fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
87
+ break;
88
+ }
89
+ off++;
90
+ } while (1);
91
+
92
+ ret = io_uring_unregister_files(ring);
93
+ if (ret) {
94
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
95
+ goto err;
96
+ }
97
+
98
+ close_files(files, 50, 0);
99
+ return 0;
100
+ err:
101
+ close_files(files, 50, 0);
102
+ return 1;
103
+ }
104
+
105
+
106
+ static int test_grow(struct io_uring *ring)
107
+ {
108
+ int ret, off;
109
+ int *files, *fds = NULL;
110
+
111
+ files = open_files(50, 250, 0);
112
+ ret = io_uring_register_files(ring, files, 300);
113
+ if (ret) {
114
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
115
+ goto err;
116
+ }
117
+
118
+ off = 50;
119
+ do {
120
+ fds = open_files(1, 0, off);
121
+ ret = io_uring_register_files_update(ring, off, fds, 1);
122
+ if (ret != 1) {
123
+ if (off == 300 && ret == -EINVAL)
124
+ break;
125
+ fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
126
+ break;
127
+ }
128
+ if (off >= 300) {
129
+ fprintf(stderr, "%s: Succeeded beyond end-of-list?\n", __FUNCTION__);
130
+ goto err;
131
+ }
132
+ off++;
133
+ } while (1);
134
+
135
+ ret = io_uring_unregister_files(ring);
136
+ if (ret) {
137
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
138
+ goto err;
139
+ }
140
+
141
+ close_files(files, 100, 0);
142
+ close_files(NULL, 251, 50);
143
+ return 0;
144
+ err:
145
+ close_files(files, 100, 0);
146
+ close_files(NULL, 251, 50);
147
+ return 1;
148
+ }
149
+
150
+ static int test_replace_all(struct io_uring *ring)
151
+ {
152
+ int *files, *fds = NULL;
153
+ int ret, i;
154
+
155
+ files = open_files(100, 0, 0);
156
+ ret = io_uring_register_files(ring, files, 100);
157
+ if (ret) {
158
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
159
+ goto err;
160
+ }
161
+
162
+ fds = t_malloc(100 * sizeof(int));
163
+ for (i = 0; i < 100; i++)
164
+ fds[i] = -1;
165
+
166
+ ret = io_uring_register_files_update(ring, 0, fds, 100);
167
+ if (ret != 100) {
168
+ fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
169
+ goto err;
170
+ }
171
+
172
+ ret = io_uring_unregister_files(ring);
173
+ if (ret) {
174
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
175
+ goto err;
176
+ }
177
+
178
+ close_files(files, 100, 0);
179
+ if (fds)
180
+ free(fds);
181
+ return 0;
182
+ err:
183
+ close_files(files, 100, 0);
184
+ if (fds)
185
+ free(fds);
186
+ return 1;
187
+ }
188
+
189
+ static int test_replace(struct io_uring *ring)
190
+ {
191
+ int *files, *fds = NULL;
192
+ int ret;
193
+
194
+ files = open_files(100, 0, 0);
195
+ ret = io_uring_register_files(ring, files, 100);
196
+ if (ret) {
197
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
198
+ goto err;
199
+ }
200
+
201
+ fds = open_files(10, 0, 1);
202
+ ret = io_uring_register_files_update(ring, 90, fds, 10);
203
+ if (ret != 10) {
204
+ fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
205
+ goto err;
206
+ }
207
+
208
+ ret = io_uring_unregister_files(ring);
209
+ if (ret) {
210
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
211
+ goto err;
212
+ }
213
+
214
+ close_files(files, 100, 0);
215
+ if (fds)
216
+ close_files(fds, 10, 1);
217
+ return 0;
218
+ err:
219
+ close_files(files, 100, 0);
220
+ if (fds)
221
+ close_files(fds, 10, 1);
222
+ return 1;
223
+ }
224
+
225
+ static int test_removals(struct io_uring *ring)
226
+ {
227
+ int *files, *fds = NULL;
228
+ int ret, i;
229
+
230
+ files = open_files(100, 0, 0);
231
+ ret = io_uring_register_files(ring, files, 100);
232
+ if (ret) {
233
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
234
+ goto err;
235
+ }
236
+
237
+ fds = t_calloc(10, sizeof(int));
238
+ for (i = 0; i < 10; i++)
239
+ fds[i] = -1;
240
+
241
+ ret = io_uring_register_files_update(ring, 50, fds, 10);
242
+ if (ret != 10) {
243
+ fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
244
+ goto err;
245
+ }
246
+
247
+ ret = io_uring_unregister_files(ring);
248
+ if (ret) {
249
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
250
+ goto err;
251
+ }
252
+
253
+ close_files(files, 100, 0);
254
+ if (fds)
255
+ free(fds);
256
+ return 0;
257
+ err:
258
+ close_files(files, 100, 0);
259
+ if (fds)
260
+ free(fds);
261
+ return 1;
262
+ }
263
+
264
+ static int test_additions(struct io_uring *ring)
265
+ {
266
+ int *files, *fds = NULL;
267
+ int ret;
268
+
269
+ files = open_files(100, 100, 0);
270
+ ret = io_uring_register_files(ring, files, 200);
271
+ if (ret) {
272
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
273
+ goto err;
274
+ }
275
+
276
+ fds = open_files(2, 0, 1);
277
+ ret = io_uring_register_files_update(ring, 100, fds, 2);
278
+ if (ret != 2) {
279
+ fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
280
+ goto err;
281
+ }
282
+
283
+ ret = io_uring_unregister_files(ring);
284
+ if (ret) {
285
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
286
+ goto err;
287
+ }
288
+
289
+ close_files(files, 100, 0);
290
+ if (fds)
291
+ close_files(fds, 2, 1);
292
+ return 0;
293
+ err:
294
+ close_files(files, 100, 0);
295
+ if (fds)
296
+ close_files(fds, 2, 1);
297
+ return 1;
298
+ }
299
+
300
+ static int test_sparse(struct io_uring *ring)
301
+ {
302
+ int *files;
303
+ int ret;
304
+
305
+ files = open_files(100, 100, 0);
306
+ ret = io_uring_register_files(ring, files, 200);
307
+ if (ret) {
308
+ if (ret == -EBADF || ret == -EINVAL) {
309
+ fprintf(stdout, "Sparse files not supported, skipping\n");
310
+ no_update = 1;
311
+ goto done;
312
+ }
313
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
314
+ goto err;
315
+ }
316
+ ret = io_uring_unregister_files(ring);
317
+ if (ret) {
318
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
319
+ goto err;
320
+ }
321
+ done:
322
+ close_files(files, 100, 0);
323
+ return 0;
324
+ err:
325
+ close_files(files, 100, 0);
326
+ return 1;
327
+ }
328
+
329
+ static int test_basic_many(struct io_uring *ring)
330
+ {
331
+ int *files;
332
+ int ret;
333
+
334
+ files = open_files(768, 0, 0);
335
+ ret = io_uring_register_files(ring, files, 768);
336
+ if (ret) {
337
+ fprintf(stderr, "%s: register %d\n", __FUNCTION__, ret);
338
+ goto err;
339
+ }
340
+ ret = io_uring_unregister_files(ring);
341
+ if (ret) {
342
+ fprintf(stderr, "%s: unregister %d\n", __FUNCTION__, ret);
343
+ goto err;
344
+ }
345
+ close_files(files, 768, 0);
346
+ return 0;
347
+ err:
348
+ close_files(files, 768, 0);
349
+ return 1;
350
+ }
351
+
352
+ static int test_basic(struct io_uring *ring, int fail)
353
+ {
354
+ int *files;
355
+ int ret, i;
356
+ int nr_files = fail ? 10 : 100;
357
+
358
+ files = open_files(nr_files, fail ? 90 : 0, 0);
359
+ if (fail) {
360
+ for (i = nr_files; i < nr_files + 90; i++)
361
+ files[i] = -2;
362
+ }
363
+ ret = io_uring_register_files(ring, files, 100);
364
+ if (ret) {
365
+ if (fail) {
366
+ if (ret == -EBADF || ret == -EFAULT)
367
+ return 0;
368
+ }
369
+ fprintf(stderr, "%s: register %d\n", __FUNCTION__, ret);
370
+ goto err;
371
+ }
372
+ if (fail) {
373
+ fprintf(stderr, "Registration succeeded, but expected fail\n");
374
+ goto err;
375
+ }
376
+ ret = io_uring_unregister_files(ring);
377
+ if (ret) {
378
+ fprintf(stderr, "%s: unregister %d\n", __FUNCTION__, ret);
379
+ goto err;
380
+ }
381
+ close_files(files, nr_files, 0);
382
+ return 0;
383
+ err:
384
+ close_files(files, nr_files, 0);
385
+ return 1;
386
+ }
387
+
388
+ /*
389
+ * Register 0 files, but reserve space for 10. Then add one file.
390
+ */
391
+ static int test_zero(struct io_uring *ring)
392
+ {
393
+ int *files, *fds = NULL;
394
+ int ret;
395
+
396
+ files = open_files(0, 10, 0);
397
+ ret = io_uring_register_files(ring, files, 10);
398
+ if (ret) {
399
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
400
+ goto err;
401
+ }
402
+
403
+ fds = open_files(1, 0, 1);
404
+ ret = io_uring_register_files_update(ring, 0, fds, 1);
405
+ if (ret != 1) {
406
+ fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
407
+ goto err;
408
+ }
409
+
410
+ ret = io_uring_unregister_files(ring);
411
+ if (ret) {
412
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
413
+ goto err;
414
+ }
415
+
416
+ if (fds)
417
+ close_files(fds, 1, 1);
418
+ free(files);
419
+ return 0;
420
+ err:
421
+ if (fds)
422
+ close_files(fds, 1, 1);
423
+ free(files);
424
+ return 1;
425
+ }
426
+
427
+ static int test_fixed_read_write(struct io_uring *ring, int index)
428
+ {
429
+ struct io_uring_sqe *sqe;
430
+ struct io_uring_cqe *cqe;
431
+ struct iovec iov[2];
432
+ int ret;
433
+
434
+ iov[0].iov_base = t_malloc(4096);
435
+ iov[0].iov_len = 4096;
436
+ memset(iov[0].iov_base, 0x5a, 4096);
437
+
438
+ iov[1].iov_base = t_malloc(4096);
439
+ iov[1].iov_len = 4096;
440
+
441
+ sqe = io_uring_get_sqe(ring);
442
+ if (!sqe) {
443
+ fprintf(stderr, "%s: failed to get sqe\n", __FUNCTION__);
444
+ return 1;
445
+ }
446
+ io_uring_prep_writev(sqe, index, &iov[0], 1, 0);
447
+ sqe->flags |= IOSQE_FIXED_FILE;
448
+ sqe->user_data = 1;
449
+
450
+ ret = io_uring_submit(ring);
451
+ if (ret != 1) {
452
+ fprintf(stderr, "%s: got %d, wanted 1\n", __FUNCTION__, ret);
453
+ return 1;
454
+ }
455
+
456
+ ret = io_uring_wait_cqe(ring, &cqe);
457
+ if (ret < 0) {
458
+ fprintf(stderr, "%s: io_uring_wait_cqe=%d\n", __FUNCTION__, ret);
459
+ return 1;
460
+ }
461
+ if (cqe->res != 4096) {
462
+ fprintf(stderr, "%s: write cqe->res=%d\n", __FUNCTION__, cqe->res);
463
+ return 1;
464
+ }
465
+ io_uring_cqe_seen(ring, cqe);
466
+
467
+ sqe = io_uring_get_sqe(ring);
468
+ if (!sqe) {
469
+ fprintf(stderr, "%s: failed to get sqe\n", __FUNCTION__);
470
+ return 1;
471
+ }
472
+ io_uring_prep_readv(sqe, index, &iov[1], 1, 0);
473
+ sqe->flags |= IOSQE_FIXED_FILE;
474
+ sqe->user_data = 2;
475
+
476
+ ret = io_uring_submit(ring);
477
+ if (ret != 1) {
478
+ fprintf(stderr, "%s: got %d, wanted 1\n", __FUNCTION__, ret);
479
+ return 1;
480
+ }
481
+
482
+ ret = io_uring_wait_cqe(ring, &cqe);
483
+ if (ret < 0) {
484
+ fprintf(stderr, "%s: io_uring_wait_cqe=%d\n", __FUNCTION__, ret);
485
+ return 1;
486
+ }
487
+ if (cqe->res != 4096) {
488
+ fprintf(stderr, "%s: read cqe->res=%d\n", __FUNCTION__, cqe->res);
489
+ return 1;
490
+ }
491
+ io_uring_cqe_seen(ring, cqe);
492
+
493
+ if (memcmp(iov[1].iov_base, iov[0].iov_base, 4096)) {
494
+ fprintf(stderr, "%s: data mismatch\n", __FUNCTION__);
495
+ return 1;
496
+ }
497
+
498
+ free(iov[0].iov_base);
499
+ free(iov[1].iov_base);
500
+ return 0;
501
+ }
502
+
503
+ static void adjust_nfiles(int want_files)
504
+ {
505
+ struct rlimit rlim;
506
+
507
+ if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
508
+ return;
509
+ if (rlim.rlim_cur >= want_files)
510
+ return;
511
+ rlim.rlim_cur = want_files;
512
+ setrlimit(RLIMIT_NOFILE, &rlim);
513
+ }
514
+
515
+ /*
516
+ * Register 8K of sparse files, update one at a random spot, then do some
517
+ * file IO to verify it works.
518
+ */
519
+ static int test_huge(struct io_uring *ring)
520
+ {
521
+ int *files;
522
+ int ret;
523
+
524
+ adjust_nfiles(16384);
525
+
526
+ files = open_files(0, 8192, 0);
527
+ ret = io_uring_register_files(ring, files, 8192);
528
+ if (ret) {
529
+ /* huge sets not supported */
530
+ if (ret == -EMFILE) {
531
+ fprintf(stdout, "%s: No huge file set support, skipping\n", __FUNCTION__);
532
+ goto out;
533
+ }
534
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
535
+ goto err;
536
+ }
537
+
538
+ files[7193] = open(".reg.7193", O_RDWR | O_CREAT, 0644);
539
+ if (files[7193] < 0) {
540
+ fprintf(stderr, "%s: open=%d\n", __FUNCTION__, errno);
541
+ goto err;
542
+ }
543
+
544
+ ret = io_uring_register_files_update(ring, 7193, &files[7193], 1);
545
+ if (ret != 1) {
546
+ fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
547
+ goto err;
548
+ }
549
+
550
+ if (test_fixed_read_write(ring, 7193))
551
+ goto err;
552
+
553
+ ret = io_uring_unregister_files(ring);
554
+ if (ret) {
555
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
556
+ goto err;
557
+ }
558
+
559
+ if (files[7193] != -1) {
560
+ close(files[7193]);
561
+ unlink(".reg.7193");
562
+ }
563
+ out:
564
+ free(files);
565
+ return 0;
566
+ err:
567
+ if (files[7193] != -1) {
568
+ close(files[7193]);
569
+ unlink(".reg.7193");
570
+ }
571
+ free(files);
572
+ return 1;
573
+ }
574
+
575
+ static int test_skip(struct io_uring *ring)
576
+ {
577
+ int *files;
578
+ int ret;
579
+
580
+ files = open_files(100, 0, 0);
581
+ ret = io_uring_register_files(ring, files, 100);
582
+ if (ret) {
583
+ fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret);
584
+ goto err;
585
+ }
586
+
587
+ files[90] = IORING_REGISTER_FILES_SKIP;
588
+ ret = io_uring_register_files_update(ring, 90, &files[90], 1);
589
+ if (ret != 1) {
590
+ if (ret == -EBADF) {
591
+ fprintf(stdout, "Skipping files not supported\n");
592
+ goto done;
593
+ }
594
+ fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
595
+ goto err;
596
+ }
597
+
598
+ /* verify can still use file index 90 */
599
+ if (test_fixed_read_write(ring, 90))
600
+ goto err;
601
+
602
+ ret = io_uring_unregister_files(ring);
603
+ if (ret) {
604
+ fprintf(stderr, "%s: unregister ret=%d\n", __FUNCTION__, ret);
605
+ goto err;
606
+ }
607
+
608
+ done:
609
+ close_files(files, 100, 0);
610
+ return 0;
611
+ err:
612
+ close_files(files, 100, 0);
613
+ return 1;
614
+ }
615
+
616
+ static int test_sparse_updates(void)
617
+ {
618
+ struct io_uring ring;
619
+ int ret, i, *fds, newfd;
620
+
621
+ ret = io_uring_queue_init(8, &ring, 0);
622
+ if (ret) {
623
+ fprintf(stderr, "queue_init: %d\n", ret);
624
+ return ret;
625
+ }
626
+
627
+ fds = t_malloc(256 * sizeof(int));
628
+ for (i = 0; i < 256; i++)
629
+ fds[i] = -1;
630
+
631
+ ret = io_uring_register_files(&ring, fds, 256);
632
+ if (ret) {
633
+ fprintf(stderr, "file_register: %d\n", ret);
634
+ return ret;
635
+ }
636
+
637
+ newfd = 1;
638
+ for (i = 0; i < 256; i++) {
639
+ ret = io_uring_register_files_update(&ring, i, &newfd, 1);
640
+ if (ret != 1) {
641
+ fprintf(stderr, "file_update: %d\n", ret);
642
+ return ret;
643
+ }
644
+ }
645
+ io_uring_unregister_files(&ring);
646
+
647
+ for (i = 0; i < 256; i++)
648
+ fds[i] = 1;
649
+
650
+ ret = io_uring_register_files(&ring, fds, 256);
651
+ if (ret) {
652
+ fprintf(stderr, "file_register: %d\n", ret);
653
+ return ret;
654
+ }
655
+
656
+ newfd = -1;
657
+ for (i = 0; i < 256; i++) {
658
+ ret = io_uring_register_files_update(&ring, i, &newfd, 1);
659
+ if (ret != 1) {
660
+ fprintf(stderr, "file_update: %d\n", ret);
661
+ return ret;
662
+ }
663
+ }
664
+ io_uring_unregister_files(&ring);
665
+
666
+ io_uring_queue_exit(&ring);
667
+ return 0;
668
+ }
669
+
670
+ static int test_fixed_removal_ordering(void)
671
+ {
672
+ char buffer[128];
673
+ struct io_uring ring;
674
+ struct io_uring_sqe *sqe;
675
+ struct io_uring_cqe *cqe;
676
+ struct __kernel_timespec ts;
677
+ int ret, fd, i, fds[2];
678
+
679
+ ret = io_uring_queue_init(8, &ring, 0);
680
+ if (ret < 0) {
681
+ fprintf(stderr, "failed to init io_uring: %s\n", strerror(-ret));
682
+ return ret;
683
+ }
684
+ if (pipe(fds)) {
685
+ perror("pipe");
686
+ return -1;
687
+ }
688
+ ret = io_uring_register_files(&ring, fds, 2);
689
+ if (ret) {
690
+ fprintf(stderr, "file_register: %d\n", ret);
691
+ return ret;
692
+ }
693
+ /* ring should have fds referenced, can close them */
694
+ close(fds[0]);
695
+ close(fds[1]);
696
+
697
+ sqe = io_uring_get_sqe(&ring);
698
+ if (!sqe) {
699
+ fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
700
+ return 1;
701
+ }
702
+ /* outwait file recycling delay */
703
+ ts.tv_sec = 3;
704
+ ts.tv_nsec = 0;
705
+ io_uring_prep_timeout(sqe, &ts, 0, 0);
706
+ sqe->flags |= IOSQE_IO_LINK | IOSQE_IO_HARDLINK;
707
+ sqe->user_data = 1;
708
+
709
+ sqe = io_uring_get_sqe(&ring);
710
+ if (!sqe) {
711
+ printf("get sqe failed\n");
712
+ return -1;
713
+ }
714
+ io_uring_prep_write(sqe, 1, buffer, sizeof(buffer), 0);
715
+ sqe->flags |= IOSQE_FIXED_FILE;
716
+ sqe->user_data = 2;
717
+
718
+ ret = io_uring_submit(&ring);
719
+ if (ret != 2) {
720
+ fprintf(stderr, "%s: got %d, wanted 2\n", __FUNCTION__, ret);
721
+ return -1;
722
+ }
723
+
724
+ /* remove unused pipe end */
725
+ fd = -1;
726
+ ret = io_uring_register_files_update(&ring, 0, &fd, 1);
727
+ if (ret != 1) {
728
+ fprintf(stderr, "update off=0 failed\n");
729
+ return -1;
730
+ }
731
+
732
+ /* remove used pipe end */
733
+ fd = -1;
734
+ ret = io_uring_register_files_update(&ring, 1, &fd, 1);
735
+ if (ret != 1) {
736
+ fprintf(stderr, "update off=1 failed\n");
737
+ return -1;
738
+ }
739
+
740
+ for (i = 0; i < 2; ++i) {
741
+ ret = io_uring_wait_cqe(&ring, &cqe);
742
+ if (ret < 0) {
743
+ fprintf(stderr, "%s: io_uring_wait_cqe=%d\n", __FUNCTION__, ret);
744
+ return 1;
745
+ }
746
+ io_uring_cqe_seen(&ring, cqe);
747
+ }
748
+
749
+ io_uring_queue_exit(&ring);
750
+ return 0;
751
+ }
752
+
753
+ /* mix files requiring SCM-accounting and not in a single register */
754
+ static int test_mixed_af_unix(void)
755
+ {
756
+ struct io_uring ring;
757
+ int i, ret, fds[2];
758
+ int reg_fds[32];
759
+ int sp[2];
760
+
761
+ ret = io_uring_queue_init(8, &ring, 0);
762
+ if (ret < 0) {
763
+ fprintf(stderr, "failed to init io_uring: %s\n", strerror(-ret));
764
+ return ret;
765
+ }
766
+ if (pipe(fds)) {
767
+ perror("pipe");
768
+ return -1;
769
+ }
770
+ if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) != 0) {
771
+ perror("Failed to create Unix-domain socket pair\n");
772
+ return 1;
773
+ }
774
+
775
+ for (i = 0; i < 16; i++) {
776
+ reg_fds[i * 2] = fds[0];
777
+ reg_fds[i * 2 + 1] = sp[0];
778
+ }
779
+
780
+ ret = io_uring_register_files(&ring, reg_fds, 32);
781
+ if (ret) {
782
+ fprintf(stderr, "file_register: %d\n", ret);
783
+ return ret;
784
+ }
785
+
786
+ close(fds[0]);
787
+ close(fds[1]);
788
+ close(sp[0]);
789
+ close(sp[1]);
790
+ io_uring_queue_exit(&ring);
791
+ return 0;
792
+ }
793
+
794
+ static int test_partial_register_fail(void)
795
+ {
796
+ char buffer[128];
797
+ struct io_uring ring;
798
+ int ret, fds[2];
799
+ int reg_fds[5];
800
+
801
+ ret = io_uring_queue_init(8, &ring, 0);
802
+ if (ret < 0) {
803
+ fprintf(stderr, "failed to init io_uring: %s\n", strerror(-ret));
804
+ return ret;
805
+ }
806
+ if (pipe(fds)) {
807
+ perror("pipe");
808
+ return -1;
809
+ }
810
+
811
+ /*
812
+ * Expect register to fail as it doesn't support io_uring fds, shouldn't
813
+ * leave any fds referenced afterwards.
814
+ */
815
+ reg_fds[0] = fds[0];
816
+ reg_fds[1] = fds[1];
817
+ reg_fds[2] = -1;
818
+ reg_fds[3] = ring.ring_fd;
819
+ reg_fds[4] = -1;
820
+ ret = io_uring_register_files(&ring, reg_fds, 5);
821
+ if (!ret) {
822
+ fprintf(stderr, "file_register unexpectedly succeeded\n");
823
+ return 1;
824
+ }
825
+
826
+ /* ring should have fds referenced, can close them */
827
+ close(fds[1]);
828
+
829
+ /* confirm that fds[1] is actually close and to ref'ed by io_uring */
830
+ ret = read(fds[0], buffer, 10);
831
+ if (ret < 0)
832
+ perror("read");
833
+ close(fds[0]);
834
+ io_uring_queue_exit(&ring);
835
+ return 0;
836
+ }
837
+
838
+ static int file_update_alloc(struct io_uring *ring, int *fd)
839
+ {
840
+ struct io_uring_sqe *sqe;
841
+ struct io_uring_cqe *cqe;
842
+ int ret;
843
+
844
+ sqe = io_uring_get_sqe(ring);
845
+ io_uring_prep_files_update(sqe, fd, 1, IORING_FILE_INDEX_ALLOC);
846
+
847
+ ret = io_uring_submit(ring);
848
+ if (ret != 1) {
849
+ fprintf(stderr, "%s: got %d, wanted 1\n", __FUNCTION__, ret);
850
+ return -1;
851
+ }
852
+
853
+ ret = io_uring_wait_cqe(ring, &cqe);
854
+ if (ret < 0) {
855
+ fprintf(stderr, "%s: io_uring_wait_cqe=%d\n", __FUNCTION__, ret);
856
+ return -1;
857
+ }
858
+ ret = cqe->res;
859
+ io_uring_cqe_seen(ring, cqe);
860
+ return ret;
861
+ }
862
+
863
+ static int test_out_of_range_file_ranges(struct io_uring *ring)
864
+ {
865
+ int ret;
866
+
867
+ ret = io_uring_register_file_alloc_range(ring, 8, 3);
868
+ if (ret != -EINVAL) {
869
+ fprintf(stderr, "overlapping range %i\n", ret);
870
+ return 1;
871
+ }
872
+
873
+ ret = io_uring_register_file_alloc_range(ring, 10, 1);
874
+ if (ret != -EINVAL) {
875
+ fprintf(stderr, "out of range index %i\n", ret);
876
+ return 1;
877
+ }
878
+
879
+ ret = io_uring_register_file_alloc_range(ring, 7, ~1U);
880
+ if (ret != -EOVERFLOW) {
881
+ fprintf(stderr, "overflow %i\n", ret);
882
+ return 1;
883
+ }
884
+
885
+ return 0;
886
+ }
887
+
888
+ static int test_overallocating_file_range(struct io_uring *ring, int fds[2])
889
+ {
890
+ int roff = 7, rlen = 2;
891
+ int ret, i, fd;
892
+
893
+ ret = io_uring_register_file_alloc_range(ring, roff, rlen);
894
+ if (ret) {
895
+ fprintf(stderr, "io_uring_register_file_alloc_range %i\n", ret);
896
+ return 1;
897
+ }
898
+
899
+ for (i = 0; i < rlen; i++) {
900
+ fd = fds[0];
901
+ ret = file_update_alloc(ring, &fd);
902
+ if (ret != 1) {
903
+ fprintf(stderr, "file_update_alloc\n");
904
+ return 1;
905
+ }
906
+
907
+ if (fd < roff || fd >= roff + rlen) {
908
+ fprintf(stderr, "invalid off result %i\n", fd);
909
+ return 1;
910
+ }
911
+ }
912
+
913
+ fd = fds[0];
914
+ ret = file_update_alloc(ring, &fd);
915
+ if (ret != -ENFILE) {
916
+ fprintf(stderr, "overallocated %i, off %i\n", ret, fd);
917
+ return 1;
918
+ }
919
+
920
+ return 0;
921
+ }
922
+
923
+ static int test_zero_range_alloc(struct io_uring *ring, int fds[2])
924
+ {
925
+ int ret, fd;
926
+
927
+ ret = io_uring_register_file_alloc_range(ring, 7, 0);
928
+ if (ret) {
929
+ fprintf(stderr, "io_uring_register_file_alloc_range failed %i\n", ret);
930
+ return 1;
931
+ }
932
+
933
+ fd = fds[0];
934
+ ret = file_update_alloc(ring, &fd);
935
+ if (ret != -ENFILE) {
936
+ fprintf(stderr, "zero alloc %i\n", ret);
937
+ return 1;
938
+ }
939
+ return 0;
940
+ }
941
+
942
+ static int test_defer_taskrun(void)
943
+ {
944
+ struct io_uring_sqe *sqe;
945
+ struct io_uring ring;
946
+ int ret, fds[2];
947
+ char buff = 'x';
948
+
949
+ ret = io_uring_queue_init(8, &ring,
950
+ IORING_SETUP_DEFER_TASKRUN | IORING_SETUP_SINGLE_ISSUER);
951
+ if (ret) {
952
+ fprintf(stderr, "ring init\n");
953
+ return 1;
954
+ }
955
+
956
+ ret = pipe(fds);
957
+ if (ret) {
958
+ fprintf(stderr, "bad pipes\n");
959
+ return 1;
960
+ }
961
+
962
+ ret = io_uring_register_files(&ring, &fds[0], 2);
963
+ if (ret) {
964
+ fprintf(stderr, "bad register %d\n", ret);
965
+ return 1;
966
+ }
967
+
968
+ sqe = io_uring_get_sqe(&ring);
969
+ io_uring_prep_read(sqe, 0, &buff, 1, 0);
970
+ sqe->flags |= IOSQE_FIXED_FILE;
971
+ ret = io_uring_submit(&ring);
972
+ if (ret != 1) {
973
+ fprintf(stderr, "bad submit\n");
974
+ return 1;
975
+ }
976
+
977
+ ret = write(fds[1], &buff, 1);
978
+ if (ret != 1) {
979
+ fprintf(stderr, "bad pipe write\n");
980
+ return 1;
981
+ }
982
+
983
+ ret = io_uring_unregister_files(&ring);
984
+ if (ret) {
985
+ fprintf(stderr, "bad unregister %d\n", ret);
986
+ return 1;
987
+ }
988
+
989
+ close(fds[0]);
990
+ close(fds[1]);
991
+ io_uring_queue_exit(&ring);
992
+ return 0;
993
+ }
994
+
995
+ static int test_file_alloc_ranges(void)
996
+ {
997
+ struct io_uring ring;
998
+ int ret, pipe_fds[2];
999
+
1000
+ if (pipe(pipe_fds)) {
1001
+ fprintf(stderr, "pipes\n");
1002
+ return 1;
1003
+ }
1004
+ ret = io_uring_queue_init(8, &ring, 0);
1005
+ if (ret) {
1006
+ fprintf(stderr, "queue_init: %d\n", ret);
1007
+ return 1;
1008
+ }
1009
+
1010
+ ret = io_uring_register_files_sparse(&ring, 10);
1011
+ if (ret == -EINVAL) {
1012
+ not_supported:
1013
+ close(pipe_fds[0]);
1014
+ close(pipe_fds[1]);
1015
+ io_uring_queue_exit(&ring);
1016
+ printf("file alloc ranges are not supported, skip\n");
1017
+ return 0;
1018
+ } else if (ret) {
1019
+ fprintf(stderr, "io_uring_register_files_sparse %i\n", ret);
1020
+ return ret;
1021
+ }
1022
+
1023
+ ret = io_uring_register_file_alloc_range(&ring, 0, 1);
1024
+ if (ret) {
1025
+ if (ret == -EINVAL)
1026
+ goto not_supported;
1027
+ fprintf(stderr, "io_uring_register_file_alloc_range %i\n", ret);
1028
+ return 1;
1029
+ }
1030
+
1031
+ ret = test_overallocating_file_range(&ring, pipe_fds);
1032
+ if (ret) {
1033
+ fprintf(stderr, "test_overallocating_file_range() failed\n");
1034
+ return 1;
1035
+ }
1036
+
1037
+ ret = test_out_of_range_file_ranges(&ring);
1038
+ if (ret) {
1039
+ fprintf(stderr, "test_out_of_range_file_ranges() failed\n");
1040
+ return 1;
1041
+ }
1042
+
1043
+ ret = test_zero_range_alloc(&ring, pipe_fds);
1044
+ if (ret) {
1045
+ fprintf(stderr, "test_zero_range_alloc() failed\n");
1046
+ return 1;
1047
+ }
1048
+
1049
+ close(pipe_fds[0]);
1050
+ close(pipe_fds[1]);
1051
+ io_uring_queue_exit(&ring);
1052
+ return 0;
1053
+ }
1054
+
1055
+ int main(int argc, char *argv[])
1056
+ {
1057
+ struct io_uring ring;
1058
+ int ret;
1059
+
1060
+ if (argc > 1)
1061
+ return T_EXIT_SKIP;
1062
+
1063
+ ret = io_uring_queue_init(8, &ring, 0);
1064
+ if (ret) {
1065
+ fprintf(stderr, "ring setup failed\n");
1066
+ return T_EXIT_FAIL;
1067
+ }
1068
+
1069
+ ret = test_basic(&ring, 0);
1070
+ if (ret) {
1071
+ fprintf(stderr, "test_basic failed\n");
1072
+ return T_EXIT_FAIL;
1073
+ }
1074
+
1075
+ ret = test_basic(&ring, 1);
1076
+ if (ret) {
1077
+ fprintf(stderr, "test_basic failed\n");
1078
+ return T_EXIT_FAIL;
1079
+ }
1080
+
1081
+ ret = test_basic_many(&ring);
1082
+ if (ret) {
1083
+ fprintf(stderr, "test_basic_many failed\n");
1084
+ return T_EXIT_FAIL;
1085
+ }
1086
+
1087
+ ret = test_sparse(&ring);
1088
+ if (ret) {
1089
+ fprintf(stderr, "test_sparse failed\n");
1090
+ return T_EXIT_FAIL;
1091
+ }
1092
+
1093
+ if (no_update)
1094
+ return T_EXIT_SKIP;
1095
+
1096
+ ret = test_additions(&ring);
1097
+ if (ret) {
1098
+ fprintf(stderr, "test_additions failed\n");
1099
+ return T_EXIT_FAIL;
1100
+ }
1101
+
1102
+ ret = test_removals(&ring);
1103
+ if (ret) {
1104
+ fprintf(stderr, "test_removals failed\n");
1105
+ return T_EXIT_FAIL;
1106
+ }
1107
+
1108
+ ret = test_replace(&ring);
1109
+ if (ret) {
1110
+ fprintf(stderr, "test_replace failed\n");
1111
+ return T_EXIT_FAIL;
1112
+ }
1113
+
1114
+ ret = test_replace_all(&ring);
1115
+ if (ret) {
1116
+ fprintf(stderr, "test_replace_all failed\n");
1117
+ return T_EXIT_FAIL;
1118
+ }
1119
+
1120
+ ret = test_grow(&ring);
1121
+ if (ret) {
1122
+ fprintf(stderr, "test_grow failed\n");
1123
+ return T_EXIT_FAIL;
1124
+ }
1125
+
1126
+ ret = test_shrink(&ring);
1127
+ if (ret) {
1128
+ fprintf(stderr, "test_shrink failed\n");
1129
+ return T_EXIT_FAIL;
1130
+ }
1131
+
1132
+ ret = test_zero(&ring);
1133
+ if (ret) {
1134
+ fprintf(stderr, "test_zero failed\n");
1135
+ return T_EXIT_FAIL;
1136
+ }
1137
+
1138
+ ret = test_huge(&ring);
1139
+ if (ret) {
1140
+ fprintf(stderr, "test_huge failed\n");
1141
+ return T_EXIT_FAIL;
1142
+ }
1143
+
1144
+ ret = test_skip(&ring);
1145
+ if (ret) {
1146
+ fprintf(stderr, "test_skip failed\n");
1147
+ return T_EXIT_FAIL;
1148
+ }
1149
+
1150
+ ret = test_sparse_updates();
1151
+ if (ret) {
1152
+ fprintf(stderr, "test_sparse_updates failed\n");
1153
+ return T_EXIT_FAIL;
1154
+ }
1155
+
1156
+ ret = test_fixed_removal_ordering();
1157
+ if (ret) {
1158
+ fprintf(stderr, "test_fixed_removal_ordering failed\n");
1159
+ return T_EXIT_FAIL;
1160
+ }
1161
+
1162
+ ret = test_mixed_af_unix();
1163
+ if (ret) {
1164
+ fprintf(stderr, "test_mixed_af_unix failed\n");
1165
+ return T_EXIT_FAIL;
1166
+ }
1167
+
1168
+ ret = test_partial_register_fail();
1169
+ if (ret) {
1170
+ fprintf(stderr, "test_partial_register_fail failed\n");
1171
+ return T_EXIT_FAIL;
1172
+ }
1173
+
1174
+ ret = test_file_alloc_ranges();
1175
+ if (ret) {
1176
+ fprintf(stderr, "test_partial_register_fail failed\n");
1177
+ return T_EXIT_FAIL;
1178
+ }
1179
+
1180
+ if (t_probe_defer_taskrun()) {
1181
+ ret = test_defer_taskrun();
1182
+ if (ret) {
1183
+ fprintf(stderr, "test_defer_taskrun failed\n");
1184
+ return T_EXIT_FAIL;
1185
+ }
1186
+ }
1187
+
1188
+ return T_EXIT_PASS;
1189
+ }