iou 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (297) hide show
  1. checksums.yaml +7 -0
  2. data/.github/dependabot.yml +12 -0
  3. data/.gitignore +59 -0
  4. data/.gitmodules +3 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +21 -0
  7. data/README.md +106 -0
  8. data/Rakefile +39 -0
  9. data/TODO.md +4 -0
  10. data/examples/echo_server.rb +52 -0
  11. data/examples/event_loop.rb +69 -0
  12. data/examples/http_server.rb +56 -0
  13. data/examples/http_server_multishot.rb +59 -0
  14. data/ext/iou/extconf.rb +71 -0
  15. data/ext/iou/iou.c +729 -0
  16. data/ext/iou/iou.h +66 -0
  17. data/ext/iou/iou_ext.c +9 -0
  18. data/ext/iou/op_spec_data.c +61 -0
  19. data/iou.gemspec +27 -0
  20. data/lib/iou/version.rb +5 -0
  21. data/lib/iou.rb +3 -0
  22. data/test/helper.rb +59 -0
  23. data/test/test_iou.rb +794 -0
  24. data/vendor/liburing/.github/actions/codespell/stopwords +7 -0
  25. data/vendor/liburing/.github/pull_request_template.md +86 -0
  26. data/vendor/liburing/.github/workflows/build.yml +137 -0
  27. data/vendor/liburing/.github/workflows/codespell.yml +25 -0
  28. data/vendor/liburing/.github/workflows/shellcheck.yml +20 -0
  29. data/vendor/liburing/.gitignore +41 -0
  30. data/vendor/liburing/CHANGELOG +111 -0
  31. data/vendor/liburing/CITATION.cff +11 -0
  32. data/vendor/liburing/COPYING +502 -0
  33. data/vendor/liburing/COPYING.GPL +339 -0
  34. data/vendor/liburing/LICENSE +20 -0
  35. data/vendor/liburing/Makefile +96 -0
  36. data/vendor/liburing/Makefile.common +7 -0
  37. data/vendor/liburing/Makefile.quiet +11 -0
  38. data/vendor/liburing/README +106 -0
  39. data/vendor/liburing/SECURITY.md +6 -0
  40. data/vendor/liburing/configure +624 -0
  41. data/vendor/liburing/debian/README.Debian +7 -0
  42. data/vendor/liburing/debian/changelog +38 -0
  43. data/vendor/liburing/debian/control +39 -0
  44. data/vendor/liburing/debian/copyright +49 -0
  45. data/vendor/liburing/debian/liburing-dev.install +4 -0
  46. data/vendor/liburing/debian/liburing-dev.manpages +5 -0
  47. data/vendor/liburing/debian/liburing2.install +1 -0
  48. data/vendor/liburing/debian/liburing2.symbols +56 -0
  49. data/vendor/liburing/debian/patches/series +1 -0
  50. data/vendor/liburing/debian/rules +29 -0
  51. data/vendor/liburing/debian/source/format +1 -0
  52. data/vendor/liburing/debian/source/local-options +2 -0
  53. data/vendor/liburing/debian/source/options +1 -0
  54. data/vendor/liburing/debian/watch +3 -0
  55. data/vendor/liburing/examples/Makefile +53 -0
  56. data/vendor/liburing/examples/helpers.c +62 -0
  57. data/vendor/liburing/examples/helpers.h +7 -0
  58. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  59. data/vendor/liburing/examples/io_uring-cp.c +282 -0
  60. data/vendor/liburing/examples/io_uring-test.c +112 -0
  61. data/vendor/liburing/examples/io_uring-udp.c +403 -0
  62. data/vendor/liburing/examples/link-cp.c +193 -0
  63. data/vendor/liburing/examples/napi-busy-poll-client.c +509 -0
  64. data/vendor/liburing/examples/napi-busy-poll-server.c +450 -0
  65. data/vendor/liburing/examples/poll-bench.c +101 -0
  66. data/vendor/liburing/examples/proxy.c +2461 -0
  67. data/vendor/liburing/examples/proxy.h +102 -0
  68. data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
  69. data/vendor/liburing/examples/send-zerocopy.c +658 -0
  70. data/vendor/liburing/examples/ucontext-cp.c +258 -0
  71. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  72. data/vendor/liburing/liburing.pc.in +12 -0
  73. data/vendor/liburing/liburing.spec +66 -0
  74. data/vendor/liburing/make-debs.sh +55 -0
  75. data/vendor/liburing/src/Makefile +129 -0
  76. data/vendor/liburing/src/arch/aarch64/lib.h +47 -0
  77. data/vendor/liburing/src/arch/aarch64/syscall.h +91 -0
  78. data/vendor/liburing/src/arch/generic/lib.h +17 -0
  79. data/vendor/liburing/src/arch/generic/syscall.h +100 -0
  80. data/vendor/liburing/src/arch/riscv64/lib.h +48 -0
  81. data/vendor/liburing/src/arch/riscv64/syscall.h +100 -0
  82. data/vendor/liburing/src/arch/syscall-defs.h +94 -0
  83. data/vendor/liburing/src/arch/x86/lib.h +11 -0
  84. data/vendor/liburing/src/arch/x86/syscall.h +296 -0
  85. data/vendor/liburing/src/ffi.c +15 -0
  86. data/vendor/liburing/src/include/liburing/barrier.h +81 -0
  87. data/vendor/liburing/src/include/liburing/io_uring.h +818 -0
  88. data/vendor/liburing/src/include/liburing.h +1602 -0
  89. data/vendor/liburing/src/int_flags.h +11 -0
  90. data/vendor/liburing/src/lib.h +52 -0
  91. data/vendor/liburing/src/liburing-ffi.map +211 -0
  92. data/vendor/liburing/src/liburing.map +104 -0
  93. data/vendor/liburing/src/nolibc.c +55 -0
  94. data/vendor/liburing/src/queue.c +468 -0
  95. data/vendor/liburing/src/register.c +374 -0
  96. data/vendor/liburing/src/setup.c +689 -0
  97. data/vendor/liburing/src/setup.h +9 -0
  98. data/vendor/liburing/src/syscall.c +29 -0
  99. data/vendor/liburing/src/syscall.h +53 -0
  100. data/vendor/liburing/src/version.c +21 -0
  101. data/vendor/liburing/test/232c93d07b74.c +305 -0
  102. data/vendor/liburing/test/35fa71a030ca.c +329 -0
  103. data/vendor/liburing/test/500f9fbadef8.c +91 -0
  104. data/vendor/liburing/test/7ad0e4b2f83c.c +94 -0
  105. data/vendor/liburing/test/8a9973408177.c +107 -0
  106. data/vendor/liburing/test/917257daa0fe.c +54 -0
  107. data/vendor/liburing/test/Makefile +297 -0
  108. data/vendor/liburing/test/a0908ae19763.c +59 -0
  109. data/vendor/liburing/test/a4c0b3decb33.c +181 -0
  110. data/vendor/liburing/test/accept-link.c +255 -0
  111. data/vendor/liburing/test/accept-non-empty.c +256 -0
  112. data/vendor/liburing/test/accept-reuse.c +163 -0
  113. data/vendor/liburing/test/accept-test.c +83 -0
  114. data/vendor/liburing/test/accept.c +919 -0
  115. data/vendor/liburing/test/across-fork.c +284 -0
  116. data/vendor/liburing/test/b19062a56726.c +54 -0
  117. data/vendor/liburing/test/b5837bd5311d.c +78 -0
  118. data/vendor/liburing/test/bind-listen.c +408 -0
  119. data/vendor/liburing/test/buf-ring-nommap.c +123 -0
  120. data/vendor/liburing/test/buf-ring-put.c +83 -0
  121. data/vendor/liburing/test/buf-ring.c +473 -0
  122. data/vendor/liburing/test/ce593a6c480a.c +139 -0
  123. data/vendor/liburing/test/close-opath.c +123 -0
  124. data/vendor/liburing/test/config +14 -0
  125. data/vendor/liburing/test/connect-rep.c +204 -0
  126. data/vendor/liburing/test/connect.c +442 -0
  127. data/vendor/liburing/test/coredump.c +60 -0
  128. data/vendor/liburing/test/cq-full.c +97 -0
  129. data/vendor/liburing/test/cq-overflow.c +530 -0
  130. data/vendor/liburing/test/cq-peek-batch.c +103 -0
  131. data/vendor/liburing/test/cq-ready.c +95 -0
  132. data/vendor/liburing/test/cq-size.c +65 -0
  133. data/vendor/liburing/test/d4ae271dfaae.c +96 -0
  134. data/vendor/liburing/test/d77a67ed5f27.c +65 -0
  135. data/vendor/liburing/test/defer-taskrun.c +391 -0
  136. data/vendor/liburing/test/defer-tw-timeout.c +173 -0
  137. data/vendor/liburing/test/defer.c +319 -0
  138. data/vendor/liburing/test/double-poll-crash.c +195 -0
  139. data/vendor/liburing/test/drop-submit.c +94 -0
  140. data/vendor/liburing/test/eeed8b54e0df.c +120 -0
  141. data/vendor/liburing/test/empty-eownerdead.c +45 -0
  142. data/vendor/liburing/test/eploop.c +74 -0
  143. data/vendor/liburing/test/eventfd-disable.c +179 -0
  144. data/vendor/liburing/test/eventfd-reg.c +77 -0
  145. data/vendor/liburing/test/eventfd-ring.c +98 -0
  146. data/vendor/liburing/test/eventfd.c +113 -0
  147. data/vendor/liburing/test/evloop.c +73 -0
  148. data/vendor/liburing/test/exec-target.c +6 -0
  149. data/vendor/liburing/test/exit-no-cleanup.c +117 -0
  150. data/vendor/liburing/test/fadvise.c +202 -0
  151. data/vendor/liburing/test/fallocate.c +265 -0
  152. data/vendor/liburing/test/fc2a85cb02ef.c +132 -0
  153. data/vendor/liburing/test/fd-install.c +500 -0
  154. data/vendor/liburing/test/fd-pass.c +237 -0
  155. data/vendor/liburing/test/fdinfo.c +419 -0
  156. data/vendor/liburing/test/file-register.c +1189 -0
  157. data/vendor/liburing/test/file-update.c +231 -0
  158. data/vendor/liburing/test/file-verify.c +654 -0
  159. data/vendor/liburing/test/files-exit-hang-poll.c +114 -0
  160. data/vendor/liburing/test/files-exit-hang-timeout.c +137 -0
  161. data/vendor/liburing/test/fixed-buf-iter.c +115 -0
  162. data/vendor/liburing/test/fixed-buf-merge.c +101 -0
  163. data/vendor/liburing/test/fixed-hugepage.c +411 -0
  164. data/vendor/liburing/test/fixed-link.c +90 -0
  165. data/vendor/liburing/test/fixed-reuse.c +160 -0
  166. data/vendor/liburing/test/fpos.c +255 -0
  167. data/vendor/liburing/test/fsnotify.c +118 -0
  168. data/vendor/liburing/test/fsync.c +224 -0
  169. data/vendor/liburing/test/futex.c +571 -0
  170. data/vendor/liburing/test/hardlink.c +170 -0
  171. data/vendor/liburing/test/helpers.c +318 -0
  172. data/vendor/liburing/test/helpers.h +108 -0
  173. data/vendor/liburing/test/ignore-single-mmap.c +48 -0
  174. data/vendor/liburing/test/init-mem.c +164 -0
  175. data/vendor/liburing/test/io-cancel.c +561 -0
  176. data/vendor/liburing/test/io_uring_enter.c +264 -0
  177. data/vendor/liburing/test/io_uring_passthrough.c +482 -0
  178. data/vendor/liburing/test/io_uring_register.c +503 -0
  179. data/vendor/liburing/test/io_uring_setup.c +110 -0
  180. data/vendor/liburing/test/iopoll-leak.c +85 -0
  181. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  182. data/vendor/liburing/test/iopoll.c +465 -0
  183. data/vendor/liburing/test/lfs-openat-write.c +119 -0
  184. data/vendor/liburing/test/lfs-openat.c +273 -0
  185. data/vendor/liburing/test/link-timeout.c +1108 -0
  186. data/vendor/liburing/test/link.c +497 -0
  187. data/vendor/liburing/test/link_drain.c +255 -0
  188. data/vendor/liburing/test/madvise.c +195 -0
  189. data/vendor/liburing/test/min-timeout-wait.c +354 -0
  190. data/vendor/liburing/test/min-timeout.c +233 -0
  191. data/vendor/liburing/test/mkdir.c +112 -0
  192. data/vendor/liburing/test/msg-ring-fd.c +331 -0
  193. data/vendor/liburing/test/msg-ring-flags.c +212 -0
  194. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  195. data/vendor/liburing/test/msg-ring.c +467 -0
  196. data/vendor/liburing/test/multicqes_drain.c +429 -0
  197. data/vendor/liburing/test/napi-test.c +215 -0
  198. data/vendor/liburing/test/napi-test.sh +48 -0
  199. data/vendor/liburing/test/no-mmap-inval.c +42 -0
  200. data/vendor/liburing/test/nolibc.c +62 -0
  201. data/vendor/liburing/test/nop-all-sizes.c +99 -0
  202. data/vendor/liburing/test/nop.c +177 -0
  203. data/vendor/liburing/test/nvme.h +169 -0
  204. data/vendor/liburing/test/ooo-file-unreg.c +82 -0
  205. data/vendor/liburing/test/open-close.c +261 -0
  206. data/vendor/liburing/test/open-direct-link.c +188 -0
  207. data/vendor/liburing/test/open-direct-pick.c +180 -0
  208. data/vendor/liburing/test/openat2.c +312 -0
  209. data/vendor/liburing/test/personality.c +204 -0
  210. data/vendor/liburing/test/pipe-bug.c +95 -0
  211. data/vendor/liburing/test/pipe-eof.c +83 -0
  212. data/vendor/liburing/test/pipe-reuse.c +105 -0
  213. data/vendor/liburing/test/poll-cancel-all.c +496 -0
  214. data/vendor/liburing/test/poll-cancel-ton.c +135 -0
  215. data/vendor/liburing/test/poll-cancel.c +228 -0
  216. data/vendor/liburing/test/poll-link.c +221 -0
  217. data/vendor/liburing/test/poll-many.c +230 -0
  218. data/vendor/liburing/test/poll-mshot-overflow.c +265 -0
  219. data/vendor/liburing/test/poll-mshot-update.c +323 -0
  220. data/vendor/liburing/test/poll-race-mshot.c +276 -0
  221. data/vendor/liburing/test/poll-race.c +105 -0
  222. data/vendor/liburing/test/poll-ring.c +48 -0
  223. data/vendor/liburing/test/poll-v-poll.c +353 -0
  224. data/vendor/liburing/test/poll.c +327 -0
  225. data/vendor/liburing/test/probe.c +135 -0
  226. data/vendor/liburing/test/read-before-exit.c +129 -0
  227. data/vendor/liburing/test/read-mshot-empty.c +153 -0
  228. data/vendor/liburing/test/read-mshot.c +404 -0
  229. data/vendor/liburing/test/read-write.c +1013 -0
  230. data/vendor/liburing/test/recv-msgall-stream.c +398 -0
  231. data/vendor/liburing/test/recv-msgall.c +263 -0
  232. data/vendor/liburing/test/recv-multishot.c +602 -0
  233. data/vendor/liburing/test/recvsend_bundle.c +691 -0
  234. data/vendor/liburing/test/reg-fd-only.c +131 -0
  235. data/vendor/liburing/test/reg-hint.c +56 -0
  236. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  237. data/vendor/liburing/test/regbuf-merge.c +91 -0
  238. data/vendor/liburing/test/register-restrictions.c +633 -0
  239. data/vendor/liburing/test/rename.c +132 -0
  240. data/vendor/liburing/test/ring-leak.c +283 -0
  241. data/vendor/liburing/test/ring-leak2.c +249 -0
  242. data/vendor/liburing/test/ringbuf-read.c +196 -0
  243. data/vendor/liburing/test/ringbuf-status.c +242 -0
  244. data/vendor/liburing/test/rsrc_tags.c +461 -0
  245. data/vendor/liburing/test/runtests-loop.sh +16 -0
  246. data/vendor/liburing/test/runtests-quiet.sh +11 -0
  247. data/vendor/liburing/test/runtests.sh +168 -0
  248. data/vendor/liburing/test/rw_merge_test.c +98 -0
  249. data/vendor/liburing/test/self.c +91 -0
  250. data/vendor/liburing/test/send-zerocopy.c +971 -0
  251. data/vendor/liburing/test/send_recv.c +412 -0
  252. data/vendor/liburing/test/send_recvmsg.c +444 -0
  253. data/vendor/liburing/test/shared-wq.c +84 -0
  254. data/vendor/liburing/test/short-read.c +75 -0
  255. data/vendor/liburing/test/shutdown.c +165 -0
  256. data/vendor/liburing/test/sigfd-deadlock.c +88 -0
  257. data/vendor/liburing/test/single-issuer.c +169 -0
  258. data/vendor/liburing/test/skip-cqe.c +428 -0
  259. data/vendor/liburing/test/socket-getsetsock-cmd.c +346 -0
  260. data/vendor/liburing/test/socket-io-cmd.c +237 -0
  261. data/vendor/liburing/test/socket-rw-eagain.c +149 -0
  262. data/vendor/liburing/test/socket-rw-offset.c +149 -0
  263. data/vendor/liburing/test/socket-rw.c +137 -0
  264. data/vendor/liburing/test/socket.c +408 -0
  265. data/vendor/liburing/test/splice.c +512 -0
  266. data/vendor/liburing/test/sq-full-cpp.cc +45 -0
  267. data/vendor/liburing/test/sq-full.c +45 -0
  268. data/vendor/liburing/test/sq-poll-dup.c +211 -0
  269. data/vendor/liburing/test/sq-poll-kthread.c +169 -0
  270. data/vendor/liburing/test/sq-poll-share.c +138 -0
  271. data/vendor/liburing/test/sq-space_left.c +159 -0
  272. data/vendor/liburing/test/sqpoll-disable-exit.c +196 -0
  273. data/vendor/liburing/test/sqpoll-exec.c +132 -0
  274. data/vendor/liburing/test/sqpoll-exit-hang.c +78 -0
  275. data/vendor/liburing/test/sqpoll-sleep.c +69 -0
  276. data/vendor/liburing/test/statx.c +172 -0
  277. data/vendor/liburing/test/stdout.c +232 -0
  278. data/vendor/liburing/test/submit-and-wait.c +108 -0
  279. data/vendor/liburing/test/submit-link-fail.c +156 -0
  280. data/vendor/liburing/test/submit-reuse.c +237 -0
  281. data/vendor/liburing/test/symlink.c +117 -0
  282. data/vendor/liburing/test/sync-cancel.c +235 -0
  283. data/vendor/liburing/test/teardowns.c +58 -0
  284. data/vendor/liburing/test/test.h +36 -0
  285. data/vendor/liburing/test/thread-exit.c +143 -0
  286. data/vendor/liburing/test/timeout-new.c +256 -0
  287. data/vendor/liburing/test/timeout.c +1798 -0
  288. data/vendor/liburing/test/truncate.c +186 -0
  289. data/vendor/liburing/test/tty-write-dpoll.c +60 -0
  290. data/vendor/liburing/test/unlink.c +112 -0
  291. data/vendor/liburing/test/version.c +25 -0
  292. data/vendor/liburing/test/wait-timeout.c +287 -0
  293. data/vendor/liburing/test/waitid.c +373 -0
  294. data/vendor/liburing/test/wakeup-hang.c +162 -0
  295. data/vendor/liburing/test/wq-aff.c +146 -0
  296. data/vendor/liburing/test/xattr.c +442 -0
  297. metadata +402 -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
+ }