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,1602 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ #ifndef LIB_URING_H
3
+ #define LIB_URING_H
4
+
5
+ #include <sys/socket.h>
6
+ #include <sys/stat.h>
7
+ #include <sys/uio.h>
8
+ #include <errno.h>
9
+ #include <signal.h>
10
+ #include <stdbool.h>
11
+ #include <inttypes.h>
12
+ #include <time.h>
13
+ #include <fcntl.h>
14
+ #include <sched.h>
15
+ #include <linux/swab.h>
16
+ #include <sys/wait.h>
17
+ #include "liburing/compat.h"
18
+ #include "liburing/io_uring.h"
19
+ #include "liburing/io_uring_version.h"
20
+ #include "liburing/barrier.h"
21
+
22
+ #ifndef uring_unlikely
23
+ #define uring_unlikely(cond) __builtin_expect(!!(cond), 0)
24
+ #endif
25
+
26
+ #ifndef uring_likely
27
+ #define uring_likely(cond) __builtin_expect(!!(cond), 1)
28
+ #endif
29
+
30
+ #ifndef IOURINGINLINE
31
+ #define IOURINGINLINE static inline
32
+ #endif
33
+
34
+ #ifdef __alpha__
35
+ /*
36
+ * alpha and mips are the exceptions, all other architectures have
37
+ * common numbers for new system calls.
38
+ */
39
+ #ifndef __NR_io_uring_setup
40
+ #define __NR_io_uring_setup 535
41
+ #endif
42
+ #ifndef __NR_io_uring_enter
43
+ #define __NR_io_uring_enter 536
44
+ #endif
45
+ #ifndef __NR_io_uring_register
46
+ #define __NR_io_uring_register 537
47
+ #endif
48
+ #elif defined __mips__
49
+ #ifndef __NR_io_uring_setup
50
+ #define __NR_io_uring_setup (__NR_Linux + 425)
51
+ #endif
52
+ #ifndef __NR_io_uring_enter
53
+ #define __NR_io_uring_enter (__NR_Linux + 426)
54
+ #endif
55
+ #ifndef __NR_io_uring_register
56
+ #define __NR_io_uring_register (__NR_Linux + 427)
57
+ #endif
58
+ #else /* !__alpha__ and !__mips__ */
59
+ #ifndef __NR_io_uring_setup
60
+ #define __NR_io_uring_setup 425
61
+ #endif
62
+ #ifndef __NR_io_uring_enter
63
+ #define __NR_io_uring_enter 426
64
+ #endif
65
+ #ifndef __NR_io_uring_register
66
+ #define __NR_io_uring_register 427
67
+ #endif
68
+ #endif
69
+
70
+ #ifdef __cplusplus
71
+ extern "C" {
72
+ #endif
73
+
74
+ /*
75
+ * Library interface to io_uring
76
+ */
77
+ struct io_uring_sq {
78
+ unsigned *khead;
79
+ unsigned *ktail;
80
+ // Deprecated: use `ring_mask` instead of `*kring_mask`
81
+ unsigned *kring_mask;
82
+ // Deprecated: use `ring_entries` instead of `*kring_entries`
83
+ unsigned *kring_entries;
84
+ unsigned *kflags;
85
+ unsigned *kdropped;
86
+ unsigned *array;
87
+ struct io_uring_sqe *sqes;
88
+
89
+ unsigned sqe_head;
90
+ unsigned sqe_tail;
91
+
92
+ size_t ring_sz;
93
+ void *ring_ptr;
94
+
95
+ unsigned ring_mask;
96
+ unsigned ring_entries;
97
+
98
+ unsigned pad[2];
99
+ };
100
+
101
+ struct io_uring_cq {
102
+ unsigned *khead;
103
+ unsigned *ktail;
104
+ // Deprecated: use `ring_mask` instead of `*kring_mask`
105
+ unsigned *kring_mask;
106
+ // Deprecated: use `ring_entries` instead of `*kring_entries`
107
+ unsigned *kring_entries;
108
+ unsigned *kflags;
109
+ unsigned *koverflow;
110
+ struct io_uring_cqe *cqes;
111
+
112
+ size_t ring_sz;
113
+ void *ring_ptr;
114
+
115
+ unsigned ring_mask;
116
+ unsigned ring_entries;
117
+
118
+ unsigned pad[2];
119
+ };
120
+
121
+ struct io_uring {
122
+ struct io_uring_sq sq;
123
+ struct io_uring_cq cq;
124
+ unsigned flags;
125
+ int ring_fd;
126
+
127
+ unsigned features;
128
+ int enter_ring_fd;
129
+ __u8 int_flags;
130
+ __u8 pad[3];
131
+ unsigned pad2;
132
+ };
133
+
134
+ /*
135
+ * Library interface
136
+ */
137
+
138
+ /*
139
+ * return an allocated io_uring_probe structure, or NULL if probe fails (for
140
+ * example, if it is not available). The caller is responsible for freeing it
141
+ */
142
+ struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring);
143
+ /* same as io_uring_get_probe_ring, but takes care of ring init and teardown */
144
+ struct io_uring_probe *io_uring_get_probe(void);
145
+
146
+ /*
147
+ * frees a probe allocated through io_uring_get_probe() or
148
+ * io_uring_get_probe_ring()
149
+ */
150
+ void io_uring_free_probe(struct io_uring_probe *probe);
151
+
152
+ IOURINGINLINE int io_uring_opcode_supported(const struct io_uring_probe *p,
153
+ int op)
154
+ {
155
+ if (op > p->last_op)
156
+ return 0;
157
+ return (p->ops[op].flags & IO_URING_OP_SUPPORTED) != 0;
158
+ }
159
+
160
+ int io_uring_queue_init_mem(unsigned entries, struct io_uring *ring,
161
+ struct io_uring_params *p,
162
+ void *buf, size_t buf_size);
163
+ int io_uring_queue_init_params(unsigned entries, struct io_uring *ring,
164
+ struct io_uring_params *p);
165
+ int io_uring_queue_init(unsigned entries, struct io_uring *ring,
166
+ unsigned flags);
167
+ int io_uring_queue_mmap(int fd, struct io_uring_params *p,
168
+ struct io_uring *ring);
169
+ int io_uring_ring_dontfork(struct io_uring *ring);
170
+ void io_uring_queue_exit(struct io_uring *ring);
171
+ unsigned io_uring_peek_batch_cqe(struct io_uring *ring,
172
+ struct io_uring_cqe **cqes, unsigned count);
173
+ int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr,
174
+ unsigned wait_nr, struct __kernel_timespec *ts,
175
+ sigset_t *sigmask);
176
+ int io_uring_wait_cqes_min_timeout(struct io_uring *ring,
177
+ struct io_uring_cqe **cqe_ptr,
178
+ unsigned wait_nr,
179
+ struct __kernel_timespec *ts,
180
+ unsigned int min_ts_usec,
181
+ sigset_t *sigmask);
182
+ int io_uring_wait_cqe_timeout(struct io_uring *ring,
183
+ struct io_uring_cqe **cqe_ptr,
184
+ struct __kernel_timespec *ts);
185
+ int io_uring_submit(struct io_uring *ring);
186
+ int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr);
187
+ int io_uring_submit_and_wait_timeout(struct io_uring *ring,
188
+ struct io_uring_cqe **cqe_ptr,
189
+ unsigned wait_nr,
190
+ struct __kernel_timespec *ts,
191
+ sigset_t *sigmask);
192
+ int io_uring_submit_and_wait_min_timeout(struct io_uring *ring,
193
+ struct io_uring_cqe **cqe_ptr,
194
+ unsigned wait_nr,
195
+ struct __kernel_timespec *ts,
196
+ unsigned min_wait,
197
+ sigset_t *sigmask);
198
+
199
+ int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs,
200
+ unsigned nr_iovecs);
201
+ int io_uring_register_buffers_tags(struct io_uring *ring,
202
+ const struct iovec *iovecs,
203
+ const __u64 *tags, unsigned nr);
204
+ int io_uring_register_buffers_sparse(struct io_uring *ring, unsigned nr);
205
+ int io_uring_register_buffers_update_tag(struct io_uring *ring,
206
+ unsigned off,
207
+ const struct iovec *iovecs,
208
+ const __u64 *tags, unsigned nr);
209
+ int io_uring_unregister_buffers(struct io_uring *ring);
210
+
211
+ int io_uring_register_files(struct io_uring *ring, const int *files,
212
+ unsigned nr_files);
213
+ int io_uring_register_files_tags(struct io_uring *ring, const int *files,
214
+ const __u64 *tags, unsigned nr);
215
+ int io_uring_register_files_sparse(struct io_uring *ring, unsigned nr);
216
+ int io_uring_register_files_update_tag(struct io_uring *ring, unsigned off,
217
+ const int *files, const __u64 *tags,
218
+ unsigned nr_files);
219
+
220
+ int io_uring_unregister_files(struct io_uring *ring);
221
+ int io_uring_register_files_update(struct io_uring *ring, unsigned off,
222
+ const int *files, unsigned nr_files);
223
+ int io_uring_register_eventfd(struct io_uring *ring, int fd);
224
+ int io_uring_register_eventfd_async(struct io_uring *ring, int fd);
225
+ int io_uring_unregister_eventfd(struct io_uring *ring);
226
+ int io_uring_register_probe(struct io_uring *ring, struct io_uring_probe *p,
227
+ unsigned nr);
228
+ int io_uring_register_personality(struct io_uring *ring);
229
+ int io_uring_unregister_personality(struct io_uring *ring, int id);
230
+ int io_uring_register_restrictions(struct io_uring *ring,
231
+ struct io_uring_restriction *res,
232
+ unsigned int nr_res);
233
+ int io_uring_enable_rings(struct io_uring *ring);
234
+ int __io_uring_sqring_wait(struct io_uring *ring);
235
+ int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz,
236
+ const cpu_set_t *mask);
237
+ int io_uring_unregister_iowq_aff(struct io_uring *ring);
238
+ int io_uring_register_iowq_max_workers(struct io_uring *ring,
239
+ unsigned int *values);
240
+ int io_uring_register_ring_fd(struct io_uring *ring);
241
+ int io_uring_unregister_ring_fd(struct io_uring *ring);
242
+ int io_uring_close_ring_fd(struct io_uring *ring);
243
+ int io_uring_register_buf_ring(struct io_uring *ring,
244
+ struct io_uring_buf_reg *reg, unsigned int flags);
245
+ int io_uring_unregister_buf_ring(struct io_uring *ring, int bgid);
246
+ int io_uring_buf_ring_head(struct io_uring *ring, int buf_group, uint16_t *head);
247
+ int io_uring_register_sync_cancel(struct io_uring *ring,
248
+ struct io_uring_sync_cancel_reg *reg);
249
+
250
+ int io_uring_register_file_alloc_range(struct io_uring *ring,
251
+ unsigned off, unsigned len);
252
+
253
+ int io_uring_register_napi(struct io_uring *ring, struct io_uring_napi *napi);
254
+ int io_uring_unregister_napi(struct io_uring *ring, struct io_uring_napi *napi);
255
+
256
+ int io_uring_register_clock(struct io_uring *ring,
257
+ struct io_uring_clock_register *arg);
258
+
259
+ int io_uring_get_events(struct io_uring *ring);
260
+ int io_uring_submit_and_get_events(struct io_uring *ring);
261
+
262
+ /*
263
+ * io_uring syscalls.
264
+ */
265
+ int io_uring_enter(unsigned int fd, unsigned int to_submit,
266
+ unsigned int min_complete, unsigned int flags, sigset_t *sig);
267
+ int io_uring_enter2(unsigned int fd, unsigned int to_submit,
268
+ unsigned int min_complete, unsigned int flags,
269
+ sigset_t *sig, size_t sz);
270
+ int io_uring_setup(unsigned int entries, struct io_uring_params *p);
271
+ int io_uring_register(unsigned int fd, unsigned int opcode, const void *arg,
272
+ unsigned int nr_args);
273
+
274
+ /*
275
+ * Mapped buffer ring alloc/register + unregister/free helpers
276
+ */
277
+ struct io_uring_buf_ring *io_uring_setup_buf_ring(struct io_uring *ring,
278
+ unsigned int nentries,
279
+ int bgid, unsigned int flags,
280
+ int *ret);
281
+ int io_uring_free_buf_ring(struct io_uring *ring, struct io_uring_buf_ring *br,
282
+ unsigned int nentries, int bgid);
283
+
284
+ /*
285
+ * Helper for the peek/wait single cqe functions. Exported because of that,
286
+ * but probably shouldn't be used directly in an application.
287
+ */
288
+ int __io_uring_get_cqe(struct io_uring *ring,
289
+ struct io_uring_cqe **cqe_ptr, unsigned submit,
290
+ unsigned wait_nr, sigset_t *sigmask);
291
+
292
+ #define LIBURING_UDATA_TIMEOUT ((__u64) -1)
293
+
294
+ /*
295
+ * Calculates the step size for CQE iteration.
296
+ * For standard CQE's its 1, for big CQE's its two.
297
+ */
298
+ #define io_uring_cqe_shift(ring) \
299
+ (!!((ring)->flags & IORING_SETUP_CQE32))
300
+
301
+ #define io_uring_cqe_index(ring,ptr,mask) \
302
+ (((ptr) & (mask)) << io_uring_cqe_shift(ring))
303
+
304
+ #define io_uring_for_each_cqe(ring, head, cqe) \
305
+ /* \
306
+ * io_uring_smp_load_acquire() enforces the order of tail \
307
+ * and CQE reads. \
308
+ */ \
309
+ for (head = *(ring)->cq.khead; \
310
+ (cqe = (head != io_uring_smp_load_acquire((ring)->cq.ktail) ? \
311
+ &(ring)->cq.cqes[io_uring_cqe_index(ring, head, (ring)->cq.ring_mask)] : NULL)); \
312
+ head++) \
313
+
314
+ /*
315
+ * Must be called after io_uring_for_each_cqe()
316
+ */
317
+ IOURINGINLINE void io_uring_cq_advance(struct io_uring *ring, unsigned nr)
318
+ {
319
+ if (nr) {
320
+ struct io_uring_cq *cq = &ring->cq;
321
+
322
+ /*
323
+ * Ensure that the kernel only sees the new value of the head
324
+ * index after the CQEs have been read.
325
+ */
326
+ io_uring_smp_store_release(cq->khead, *cq->khead + nr);
327
+ }
328
+ }
329
+
330
+ /*
331
+ * Must be called after io_uring_{peek,wait}_cqe() after the cqe has
332
+ * been processed by the application.
333
+ */
334
+ IOURINGINLINE void io_uring_cqe_seen(struct io_uring *ring,
335
+ struct io_uring_cqe *cqe)
336
+ {
337
+ if (cqe)
338
+ io_uring_cq_advance(ring, 1);
339
+ }
340
+
341
+ /*
342
+ * Command prep helpers
343
+ */
344
+
345
+ /*
346
+ * Associate pointer @data with the sqe, for later retrieval from the cqe
347
+ * at command completion time with io_uring_cqe_get_data().
348
+ */
349
+ IOURINGINLINE void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data)
350
+ {
351
+ sqe->user_data = (unsigned long) data;
352
+ }
353
+
354
+ IOURINGINLINE void *io_uring_cqe_get_data(const struct io_uring_cqe *cqe)
355
+ {
356
+ return (void *) (uintptr_t) cqe->user_data;
357
+ }
358
+
359
+ /*
360
+ * Assign a 64-bit value to this sqe, which can get retrieved at completion
361
+ * time with io_uring_cqe_get_data64. Just like the non-64 variants, except
362
+ * these store a 64-bit type rather than a data pointer.
363
+ */
364
+ IOURINGINLINE void io_uring_sqe_set_data64(struct io_uring_sqe *sqe,
365
+ __u64 data)
366
+ {
367
+ sqe->user_data = data;
368
+ }
369
+
370
+ IOURINGINLINE __u64 io_uring_cqe_get_data64(const struct io_uring_cqe *cqe)
371
+ {
372
+ return cqe->user_data;
373
+ }
374
+
375
+ /*
376
+ * Tell the app the have the 64-bit variants of the get/set userdata
377
+ */
378
+ #define LIBURING_HAVE_DATA64
379
+
380
+ IOURINGINLINE void io_uring_sqe_set_flags(struct io_uring_sqe *sqe,
381
+ unsigned flags)
382
+ {
383
+ sqe->flags = (__u8) flags;
384
+ }
385
+
386
+ IOURINGINLINE void __io_uring_set_target_fixed_file(struct io_uring_sqe *sqe,
387
+ unsigned int file_index)
388
+ {
389
+ /* 0 means no fixed files, indexes should be encoded as "index + 1" */
390
+ sqe->file_index = file_index + 1;
391
+ }
392
+
393
+ IOURINGINLINE void io_uring_initialize_sqe(struct io_uring_sqe *sqe)
394
+ {
395
+ sqe->flags = 0;
396
+ sqe->ioprio = 0;
397
+ sqe->rw_flags = 0;
398
+ sqe->buf_index = 0;
399
+ sqe->personality = 0;
400
+ sqe->file_index = 0;
401
+ sqe->addr3 = 0;
402
+ sqe->__pad2[0] = 0;
403
+ }
404
+
405
+ IOURINGINLINE void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
406
+ const void *addr, unsigned len,
407
+ __u64 offset)
408
+ {
409
+ sqe->opcode = (__u8) op;
410
+ sqe->fd = fd;
411
+ sqe->off = offset;
412
+ sqe->addr = (unsigned long) addr;
413
+ sqe->len = len;
414
+ }
415
+
416
+ /*
417
+ * io_uring_prep_splice() - Either @fd_in or @fd_out must be a pipe.
418
+ *
419
+ * - If @fd_in refers to a pipe, @off_in is ignored and must be set to -1.
420
+ *
421
+ * - If @fd_in does not refer to a pipe and @off_in is -1, then @nbytes are read
422
+ * from @fd_in starting from the file offset, which is incremented by the
423
+ * number of bytes read.
424
+ *
425
+ * - If @fd_in does not refer to a pipe and @off_in is not -1, then the starting
426
+ * offset of @fd_in will be @off_in.
427
+ *
428
+ * This splice operation can be used to implement sendfile by splicing to an
429
+ * intermediate pipe first, then splice to the final destination.
430
+ * In fact, the implementation of sendfile in kernel uses splice internally.
431
+ *
432
+ * NOTE that even if fd_in or fd_out refers to a pipe, the splice operation
433
+ * can still fail with EINVAL if one of the fd doesn't explicitly support splice
434
+ * operation, e.g. reading from terminal is unsupported from kernel 5.7 to 5.11.
435
+ * Check issue #291 for more information.
436
+ */
437
+ IOURINGINLINE void io_uring_prep_splice(struct io_uring_sqe *sqe,
438
+ int fd_in, int64_t off_in,
439
+ int fd_out, int64_t off_out,
440
+ unsigned int nbytes,
441
+ unsigned int splice_flags)
442
+ {
443
+ io_uring_prep_rw(IORING_OP_SPLICE, sqe, fd_out, NULL, nbytes,
444
+ (__u64) off_out);
445
+ sqe->splice_off_in = (__u64) off_in;
446
+ sqe->splice_fd_in = fd_in;
447
+ sqe->splice_flags = splice_flags;
448
+ }
449
+
450
+ IOURINGINLINE void io_uring_prep_tee(struct io_uring_sqe *sqe,
451
+ int fd_in, int fd_out,
452
+ unsigned int nbytes,
453
+ unsigned int splice_flags)
454
+ {
455
+ io_uring_prep_rw(IORING_OP_TEE, sqe, fd_out, NULL, nbytes, 0);
456
+ sqe->splice_off_in = 0;
457
+ sqe->splice_fd_in = fd_in;
458
+ sqe->splice_flags = splice_flags;
459
+ }
460
+
461
+ IOURINGINLINE void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd,
462
+ const struct iovec *iovecs,
463
+ unsigned nr_vecs, __u64 offset)
464
+ {
465
+ io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset);
466
+ }
467
+
468
+ IOURINGINLINE void io_uring_prep_readv2(struct io_uring_sqe *sqe, int fd,
469
+ const struct iovec *iovecs,
470
+ unsigned nr_vecs, __u64 offset,
471
+ int flags)
472
+ {
473
+ io_uring_prep_readv(sqe, fd, iovecs, nr_vecs, offset);
474
+ sqe->rw_flags = flags;
475
+ }
476
+
477
+ IOURINGINLINE void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd,
478
+ void *buf, unsigned nbytes,
479
+ __u64 offset, int buf_index)
480
+ {
481
+ io_uring_prep_rw(IORING_OP_READ_FIXED, sqe, fd, buf, nbytes, offset);
482
+ sqe->buf_index = (__u16) buf_index;
483
+ }
484
+
485
+ IOURINGINLINE void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd,
486
+ const struct iovec *iovecs,
487
+ unsigned nr_vecs, __u64 offset)
488
+ {
489
+ io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset);
490
+ }
491
+
492
+ IOURINGINLINE void io_uring_prep_writev2(struct io_uring_sqe *sqe, int fd,
493
+ const struct iovec *iovecs,
494
+ unsigned nr_vecs, __u64 offset,
495
+ int flags)
496
+ {
497
+ io_uring_prep_writev(sqe, fd, iovecs, nr_vecs, offset);
498
+ sqe->rw_flags = flags;
499
+ }
500
+
501
+ IOURINGINLINE void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd,
502
+ const void *buf, unsigned nbytes,
503
+ __u64 offset, int buf_index)
504
+ {
505
+ io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset);
506
+ sqe->buf_index = (__u16) buf_index;
507
+ }
508
+
509
+ IOURINGINLINE void io_uring_prep_recvmsg(struct io_uring_sqe *sqe, int fd,
510
+ struct msghdr *msg, unsigned flags)
511
+ {
512
+ io_uring_prep_rw(IORING_OP_RECVMSG, sqe, fd, msg, 1, 0);
513
+ sqe->msg_flags = flags;
514
+ }
515
+
516
+ IOURINGINLINE void io_uring_prep_recvmsg_multishot(struct io_uring_sqe *sqe,
517
+ int fd, struct msghdr *msg,
518
+ unsigned flags)
519
+ {
520
+ io_uring_prep_recvmsg(sqe, fd, msg, flags);
521
+ sqe->ioprio |= IORING_RECV_MULTISHOT;
522
+ }
523
+
524
+ IOURINGINLINE void io_uring_prep_sendmsg(struct io_uring_sqe *sqe, int fd,
525
+ const struct msghdr *msg,
526
+ unsigned flags)
527
+ {
528
+ io_uring_prep_rw(IORING_OP_SENDMSG, sqe, fd, msg, 1, 0);
529
+ sqe->msg_flags = flags;
530
+ }
531
+
532
+ IOURINGINLINE unsigned __io_uring_prep_poll_mask(unsigned poll_mask)
533
+ {
534
+ #if __BYTE_ORDER == __BIG_ENDIAN
535
+ poll_mask = __swahw32(poll_mask);
536
+ #endif
537
+ return poll_mask;
538
+ }
539
+
540
+ IOURINGINLINE void io_uring_prep_poll_add(struct io_uring_sqe *sqe, int fd,
541
+ unsigned poll_mask)
542
+ {
543
+ io_uring_prep_rw(IORING_OP_POLL_ADD, sqe, fd, NULL, 0, 0);
544
+ sqe->poll32_events = __io_uring_prep_poll_mask(poll_mask);
545
+ }
546
+
547
+ IOURINGINLINE void io_uring_prep_poll_multishot(struct io_uring_sqe *sqe,
548
+ int fd, unsigned poll_mask)
549
+ {
550
+ io_uring_prep_poll_add(sqe, fd, poll_mask);
551
+ sqe->len = IORING_POLL_ADD_MULTI;
552
+ }
553
+
554
+ IOURINGINLINE void io_uring_prep_poll_remove(struct io_uring_sqe *sqe,
555
+ __u64 user_data)
556
+ {
557
+ io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, NULL, 0, 0);
558
+ sqe->addr = user_data;
559
+ }
560
+
561
+ IOURINGINLINE void io_uring_prep_poll_update(struct io_uring_sqe *sqe,
562
+ __u64 old_user_data,
563
+ __u64 new_user_data,
564
+ unsigned poll_mask, unsigned flags)
565
+ {
566
+ io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, NULL, flags,
567
+ new_user_data);
568
+ sqe->addr = old_user_data;
569
+ sqe->poll32_events = __io_uring_prep_poll_mask(poll_mask);
570
+ }
571
+
572
+ IOURINGINLINE void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd,
573
+ unsigned fsync_flags)
574
+ {
575
+ io_uring_prep_rw(IORING_OP_FSYNC, sqe, fd, NULL, 0, 0);
576
+ sqe->fsync_flags = fsync_flags;
577
+ }
578
+
579
+ IOURINGINLINE void io_uring_prep_nop(struct io_uring_sqe *sqe)
580
+ {
581
+ io_uring_prep_rw(IORING_OP_NOP, sqe, -1, NULL, 0, 0);
582
+ }
583
+
584
+ IOURINGINLINE void io_uring_prep_timeout(struct io_uring_sqe *sqe,
585
+ struct __kernel_timespec *ts,
586
+ unsigned count, unsigned flags)
587
+ {
588
+ io_uring_prep_rw(IORING_OP_TIMEOUT, sqe, -1, ts, 1, count);
589
+ sqe->timeout_flags = flags;
590
+ }
591
+
592
+ IOURINGINLINE void io_uring_prep_timeout_remove(struct io_uring_sqe *sqe,
593
+ __u64 user_data, unsigned flags)
594
+ {
595
+ io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, NULL, 0, 0);
596
+ sqe->addr = user_data;
597
+ sqe->timeout_flags = flags;
598
+ }
599
+
600
+ IOURINGINLINE void io_uring_prep_timeout_update(struct io_uring_sqe *sqe,
601
+ struct __kernel_timespec *ts,
602
+ __u64 user_data, unsigned flags)
603
+ {
604
+ io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, NULL, 0,
605
+ (uintptr_t) ts);
606
+ sqe->addr = user_data;
607
+ sqe->timeout_flags = flags | IORING_TIMEOUT_UPDATE;
608
+ }
609
+
610
+ IOURINGINLINE void io_uring_prep_accept(struct io_uring_sqe *sqe, int fd,
611
+ struct sockaddr *addr,
612
+ socklen_t *addrlen, int flags)
613
+ {
614
+ io_uring_prep_rw(IORING_OP_ACCEPT, sqe, fd, addr, 0,
615
+ (__u64) (unsigned long) addrlen);
616
+ sqe->accept_flags = (__u32) flags;
617
+ }
618
+
619
+ /* accept directly into the fixed file table */
620
+ IOURINGINLINE void io_uring_prep_accept_direct(struct io_uring_sqe *sqe, int fd,
621
+ struct sockaddr *addr,
622
+ socklen_t *addrlen, int flags,
623
+ unsigned int file_index)
624
+ {
625
+ io_uring_prep_accept(sqe, fd, addr, addrlen, flags);
626
+ /* offset by 1 for allocation */
627
+ if (file_index == IORING_FILE_INDEX_ALLOC)
628
+ file_index--;
629
+ __io_uring_set_target_fixed_file(sqe, file_index);
630
+ }
631
+
632
+ IOURINGINLINE void io_uring_prep_multishot_accept(struct io_uring_sqe *sqe,
633
+ int fd, struct sockaddr *addr,
634
+ socklen_t *addrlen, int flags)
635
+ {
636
+ io_uring_prep_accept(sqe, fd, addr, addrlen, flags);
637
+ sqe->ioprio |= IORING_ACCEPT_MULTISHOT;
638
+ }
639
+
640
+ /* multishot accept directly into the fixed file table */
641
+ IOURINGINLINE void io_uring_prep_multishot_accept_direct(struct io_uring_sqe *sqe,
642
+ int fd,
643
+ struct sockaddr *addr,
644
+ socklen_t *addrlen,
645
+ int flags)
646
+ {
647
+ io_uring_prep_multishot_accept(sqe, fd, addr, addrlen, flags);
648
+ __io_uring_set_target_fixed_file(sqe, IORING_FILE_INDEX_ALLOC - 1);
649
+ }
650
+
651
+ IOURINGINLINE void io_uring_prep_cancel64(struct io_uring_sqe *sqe,
652
+ __u64 user_data, int flags)
653
+ {
654
+ io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, -1, NULL, 0, 0);
655
+ sqe->addr = user_data;
656
+ sqe->cancel_flags = (__u32) flags;
657
+ }
658
+
659
+ IOURINGINLINE void io_uring_prep_cancel(struct io_uring_sqe *sqe,
660
+ void *user_data, int flags)
661
+ {
662
+ io_uring_prep_cancel64(sqe, (__u64) (uintptr_t) user_data, flags);
663
+ }
664
+
665
+ IOURINGINLINE void io_uring_prep_cancel_fd(struct io_uring_sqe *sqe, int fd,
666
+ unsigned int flags)
667
+ {
668
+ io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, fd, NULL, 0, 0);
669
+ sqe->cancel_flags = (__u32) flags | IORING_ASYNC_CANCEL_FD;
670
+ }
671
+
672
+ IOURINGINLINE void io_uring_prep_link_timeout(struct io_uring_sqe *sqe,
673
+ struct __kernel_timespec *ts,
674
+ unsigned flags)
675
+ {
676
+ io_uring_prep_rw(IORING_OP_LINK_TIMEOUT, sqe, -1, ts, 1, 0);
677
+ sqe->timeout_flags = flags;
678
+ }
679
+
680
+ IOURINGINLINE void io_uring_prep_connect(struct io_uring_sqe *sqe, int fd,
681
+ const struct sockaddr *addr,
682
+ socklen_t addrlen)
683
+ {
684
+ io_uring_prep_rw(IORING_OP_CONNECT, sqe, fd, addr, 0, addrlen);
685
+ }
686
+
687
+ IOURINGINLINE void io_uring_prep_bind(struct io_uring_sqe *sqe, int fd,
688
+ struct sockaddr *addr,
689
+ socklen_t addrlen)
690
+ {
691
+ io_uring_prep_rw(IORING_OP_BIND, sqe, fd, addr, 0, addrlen);
692
+ }
693
+
694
+ IOURINGINLINE void io_uring_prep_listen(struct io_uring_sqe *sqe, int fd,
695
+ int backlog)
696
+ {
697
+ io_uring_prep_rw(IORING_OP_LISTEN, sqe, fd, 0, backlog, 0);
698
+ }
699
+
700
+ IOURINGINLINE void io_uring_prep_files_update(struct io_uring_sqe *sqe,
701
+ int *fds, unsigned nr_fds,
702
+ int offset)
703
+ {
704
+ io_uring_prep_rw(IORING_OP_FILES_UPDATE, sqe, -1, fds, nr_fds,
705
+ (__u64) offset);
706
+ }
707
+
708
+ IOURINGINLINE void io_uring_prep_fallocate(struct io_uring_sqe *sqe, int fd,
709
+ int mode, __u64 offset, __u64 len)
710
+ {
711
+ io_uring_prep_rw(IORING_OP_FALLOCATE, sqe, fd,
712
+ 0, (unsigned int) mode, (__u64) offset);
713
+ sqe->addr = (__u64) len;
714
+ }
715
+
716
+ IOURINGINLINE void io_uring_prep_openat(struct io_uring_sqe *sqe, int dfd,
717
+ const char *path, int flags,
718
+ mode_t mode)
719
+ {
720
+ io_uring_prep_rw(IORING_OP_OPENAT, sqe, dfd, path, mode, 0);
721
+ sqe->open_flags = (__u32) flags;
722
+ }
723
+
724
+ /* open directly into the fixed file table */
725
+ IOURINGINLINE void io_uring_prep_openat_direct(struct io_uring_sqe *sqe,
726
+ int dfd, const char *path,
727
+ int flags, mode_t mode,
728
+ unsigned file_index)
729
+ {
730
+ io_uring_prep_openat(sqe, dfd, path, flags, mode);
731
+ /* offset by 1 for allocation */
732
+ if (file_index == IORING_FILE_INDEX_ALLOC)
733
+ file_index--;
734
+ __io_uring_set_target_fixed_file(sqe, file_index);
735
+ }
736
+
737
+ IOURINGINLINE void io_uring_prep_close(struct io_uring_sqe *sqe, int fd)
738
+ {
739
+ io_uring_prep_rw(IORING_OP_CLOSE, sqe, fd, NULL, 0, 0);
740
+ }
741
+
742
+ IOURINGINLINE void io_uring_prep_close_direct(struct io_uring_sqe *sqe,
743
+ unsigned file_index)
744
+ {
745
+ io_uring_prep_close(sqe, 0);
746
+ __io_uring_set_target_fixed_file(sqe, file_index);
747
+ }
748
+
749
+ IOURINGINLINE void io_uring_prep_read(struct io_uring_sqe *sqe, int fd,
750
+ void *buf, unsigned nbytes, __u64 offset)
751
+ {
752
+ io_uring_prep_rw(IORING_OP_READ, sqe, fd, buf, nbytes, offset);
753
+ }
754
+
755
+ IOURINGINLINE void io_uring_prep_read_multishot(struct io_uring_sqe *sqe,
756
+ int fd, unsigned nbytes,
757
+ __u64 offset, int buf_group)
758
+ {
759
+ io_uring_prep_rw(IORING_OP_READ_MULTISHOT, sqe, fd, NULL, nbytes,
760
+ offset);
761
+ sqe->buf_group = buf_group;
762
+ sqe->flags = IOSQE_BUFFER_SELECT;
763
+ }
764
+
765
+ IOURINGINLINE void io_uring_prep_write(struct io_uring_sqe *sqe, int fd,
766
+ const void *buf, unsigned nbytes,
767
+ __u64 offset)
768
+ {
769
+ io_uring_prep_rw(IORING_OP_WRITE, sqe, fd, buf, nbytes, offset);
770
+ }
771
+
772
+ struct statx;
773
+ IOURINGINLINE void io_uring_prep_statx(struct io_uring_sqe *sqe, int dfd,
774
+ const char *path, int flags,
775
+ unsigned mask, struct statx *statxbuf)
776
+ {
777
+ io_uring_prep_rw(IORING_OP_STATX, sqe, dfd, path, mask,
778
+ (__u64) (unsigned long) statxbuf);
779
+ sqe->statx_flags = (__u32) flags;
780
+ }
781
+
782
+ IOURINGINLINE void io_uring_prep_fadvise(struct io_uring_sqe *sqe, int fd,
783
+ __u64 offset, __u32 len, int advice)
784
+ {
785
+ io_uring_prep_rw(IORING_OP_FADVISE, sqe, fd, NULL, (__u32) len, offset);
786
+ sqe->fadvise_advice = (__u32) advice;
787
+ }
788
+
789
+ IOURINGINLINE void io_uring_prep_madvise(struct io_uring_sqe *sqe, void *addr,
790
+ __u32 length, int advice)
791
+ {
792
+ io_uring_prep_rw(IORING_OP_MADVISE, sqe, -1, addr, (__u32) length, 0);
793
+ sqe->fadvise_advice = (__u32) advice;
794
+ }
795
+
796
+ IOURINGINLINE void io_uring_prep_fadvise64(struct io_uring_sqe *sqe, int fd,
797
+ __u64 offset, off_t len, int advice)
798
+ {
799
+ io_uring_prep_rw(IORING_OP_FADVISE, sqe, fd, NULL, 0, offset);
800
+ sqe->addr = len;
801
+ sqe->fadvise_advice = (__u32) advice;
802
+ }
803
+
804
+ IOURINGINLINE void io_uring_prep_madvise64(struct io_uring_sqe *sqe, void *addr,
805
+ off_t length, int advice)
806
+ {
807
+ io_uring_prep_rw(IORING_OP_MADVISE, sqe, -1, addr, 0, length);
808
+ sqe->fadvise_advice = (__u32) advice;
809
+ }
810
+
811
+ IOURINGINLINE void io_uring_prep_send(struct io_uring_sqe *sqe, int sockfd,
812
+ const void *buf, size_t len, int flags)
813
+ {
814
+ io_uring_prep_rw(IORING_OP_SEND, sqe, sockfd, buf, (__u32) len, 0);
815
+ sqe->msg_flags = (__u32) flags;
816
+ }
817
+
818
+ IOURINGINLINE void io_uring_prep_send_bundle(struct io_uring_sqe *sqe,
819
+ int sockfd, size_t len, int flags)
820
+ {
821
+ io_uring_prep_send(sqe, sockfd, NULL, len, flags);
822
+ sqe->ioprio |= IORING_RECVSEND_BUNDLE;
823
+ }
824
+
825
+ IOURINGINLINE void io_uring_prep_send_set_addr(struct io_uring_sqe *sqe,
826
+ const struct sockaddr *dest_addr,
827
+ __u16 addr_len)
828
+ {
829
+ sqe->addr2 = (unsigned long)(const void *)dest_addr;
830
+ sqe->addr_len = addr_len;
831
+ }
832
+
833
+ IOURINGINLINE void io_uring_prep_sendto(struct io_uring_sqe *sqe, int sockfd,
834
+ const void *buf, size_t len, int flags,
835
+ const struct sockaddr *addr,
836
+ socklen_t addrlen)
837
+ {
838
+ io_uring_prep_send(sqe, sockfd, buf, len, flags);
839
+ io_uring_prep_send_set_addr(sqe, addr, addrlen);
840
+ }
841
+
842
+ IOURINGINLINE void io_uring_prep_send_zc(struct io_uring_sqe *sqe, int sockfd,
843
+ const void *buf, size_t len, int flags,
844
+ unsigned zc_flags)
845
+ {
846
+ io_uring_prep_rw(IORING_OP_SEND_ZC, sqe, sockfd, buf, (__u32) len, 0);
847
+ sqe->msg_flags = (__u32) flags;
848
+ sqe->ioprio = zc_flags;
849
+ }
850
+
851
+ IOURINGINLINE void io_uring_prep_send_zc_fixed(struct io_uring_sqe *sqe,
852
+ int sockfd, const void *buf,
853
+ size_t len, int flags,
854
+ unsigned zc_flags,
855
+ unsigned buf_index)
856
+ {
857
+ io_uring_prep_send_zc(sqe, sockfd, buf, len, flags, zc_flags);
858
+ sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
859
+ sqe->buf_index = buf_index;
860
+ }
861
+
862
+ IOURINGINLINE void io_uring_prep_sendmsg_zc(struct io_uring_sqe *sqe, int fd,
863
+ const struct msghdr *msg,
864
+ unsigned flags)
865
+ {
866
+ io_uring_prep_sendmsg(sqe, fd, msg, flags);
867
+ sqe->opcode = IORING_OP_SENDMSG_ZC;
868
+ }
869
+
870
+ IOURINGINLINE void io_uring_prep_recv(struct io_uring_sqe *sqe, int sockfd,
871
+ void *buf, size_t len, int flags)
872
+ {
873
+ io_uring_prep_rw(IORING_OP_RECV, sqe, sockfd, buf, (__u32) len, 0);
874
+ sqe->msg_flags = (__u32) flags;
875
+ }
876
+
877
+ IOURINGINLINE void io_uring_prep_recv_multishot(struct io_uring_sqe *sqe,
878
+ int sockfd, void *buf,
879
+ size_t len, int flags)
880
+ {
881
+ io_uring_prep_recv(sqe, sockfd, buf, len, flags);
882
+ sqe->ioprio |= IORING_RECV_MULTISHOT;
883
+ }
884
+
885
+ IOURINGINLINE struct io_uring_recvmsg_out *
886
+ io_uring_recvmsg_validate(void *buf, int buf_len, struct msghdr *msgh)
887
+ {
888
+ unsigned long header = msgh->msg_controllen + msgh->msg_namelen +
889
+ sizeof(struct io_uring_recvmsg_out);
890
+ if (buf_len < 0 || (unsigned long)buf_len < header)
891
+ return NULL;
892
+ return (struct io_uring_recvmsg_out *)buf;
893
+ }
894
+
895
+ IOURINGINLINE void *io_uring_recvmsg_name(struct io_uring_recvmsg_out *o)
896
+ {
897
+ return (void *) &o[1];
898
+ }
899
+
900
+ IOURINGINLINE struct cmsghdr *
901
+ io_uring_recvmsg_cmsg_firsthdr(struct io_uring_recvmsg_out *o,
902
+ struct msghdr *msgh)
903
+ {
904
+ if (o->controllen < sizeof(struct cmsghdr))
905
+ return NULL;
906
+
907
+ return (struct cmsghdr *)((unsigned char *) io_uring_recvmsg_name(o) +
908
+ msgh->msg_namelen);
909
+ }
910
+
911
+ IOURINGINLINE struct cmsghdr *
912
+ io_uring_recvmsg_cmsg_nexthdr(struct io_uring_recvmsg_out *o, struct msghdr *msgh,
913
+ struct cmsghdr *cmsg)
914
+ {
915
+ unsigned char *end;
916
+
917
+ if (cmsg->cmsg_len < sizeof(struct cmsghdr))
918
+ return NULL;
919
+ end = (unsigned char *) io_uring_recvmsg_cmsg_firsthdr(o, msgh) +
920
+ o->controllen;
921
+ cmsg = (struct cmsghdr *)((unsigned char *) cmsg +
922
+ CMSG_ALIGN(cmsg->cmsg_len));
923
+
924
+ if ((unsigned char *) (cmsg + 1) > end)
925
+ return NULL;
926
+ if (((unsigned char *) cmsg) + CMSG_ALIGN(cmsg->cmsg_len) > end)
927
+ return NULL;
928
+
929
+ return cmsg;
930
+ }
931
+
932
+ IOURINGINLINE void *io_uring_recvmsg_payload(struct io_uring_recvmsg_out *o,
933
+ struct msghdr *msgh)
934
+ {
935
+ return (void *)((unsigned char *)io_uring_recvmsg_name(o) +
936
+ msgh->msg_namelen + msgh->msg_controllen);
937
+ }
938
+
939
+ IOURINGINLINE unsigned int
940
+ io_uring_recvmsg_payload_length(struct io_uring_recvmsg_out *o,
941
+ int buf_len, struct msghdr *msgh)
942
+ {
943
+ unsigned long payload_start, payload_end;
944
+
945
+ payload_start = (unsigned long) io_uring_recvmsg_payload(o, msgh);
946
+ payload_end = (unsigned long) o + buf_len;
947
+ return (unsigned int) (payload_end - payload_start);
948
+ }
949
+
950
+ IOURINGINLINE void io_uring_prep_openat2(struct io_uring_sqe *sqe, int dfd,
951
+ const char *path, struct open_how *how)
952
+ {
953
+ io_uring_prep_rw(IORING_OP_OPENAT2, sqe, dfd, path, sizeof(*how),
954
+ (uint64_t) (uintptr_t) how);
955
+ }
956
+
957
+ /* open directly into the fixed file table */
958
+ IOURINGINLINE void io_uring_prep_openat2_direct(struct io_uring_sqe *sqe,
959
+ int dfd, const char *path,
960
+ struct open_how *how,
961
+ unsigned file_index)
962
+ {
963
+ io_uring_prep_openat2(sqe, dfd, path, how);
964
+ /* offset by 1 for allocation */
965
+ if (file_index == IORING_FILE_INDEX_ALLOC)
966
+ file_index--;
967
+ __io_uring_set_target_fixed_file(sqe, file_index);
968
+ }
969
+
970
+ struct epoll_event;
971
+ IOURINGINLINE void io_uring_prep_epoll_ctl(struct io_uring_sqe *sqe, int epfd,
972
+ int fd, int op,
973
+ struct epoll_event *ev)
974
+ {
975
+ io_uring_prep_rw(IORING_OP_EPOLL_CTL, sqe, epfd, ev,
976
+ (__u32) op, (__u32) fd);
977
+ }
978
+
979
+ IOURINGINLINE void io_uring_prep_provide_buffers(struct io_uring_sqe *sqe,
980
+ void *addr, int len, int nr,
981
+ int bgid, int bid)
982
+ {
983
+ io_uring_prep_rw(IORING_OP_PROVIDE_BUFFERS, sqe, nr, addr, (__u32) len,
984
+ (__u64) bid);
985
+ sqe->buf_group = (__u16) bgid;
986
+ }
987
+
988
+ IOURINGINLINE void io_uring_prep_remove_buffers(struct io_uring_sqe *sqe,
989
+ int nr, int bgid)
990
+ {
991
+ io_uring_prep_rw(IORING_OP_REMOVE_BUFFERS, sqe, nr, NULL, 0, 0);
992
+ sqe->buf_group = (__u16) bgid;
993
+ }
994
+
995
+ IOURINGINLINE void io_uring_prep_shutdown(struct io_uring_sqe *sqe, int fd,
996
+ int how)
997
+ {
998
+ io_uring_prep_rw(IORING_OP_SHUTDOWN, sqe, fd, NULL, (__u32) how, 0);
999
+ }
1000
+
1001
+ IOURINGINLINE void io_uring_prep_unlinkat(struct io_uring_sqe *sqe, int dfd,
1002
+ const char *path, int flags)
1003
+ {
1004
+ io_uring_prep_rw(IORING_OP_UNLINKAT, sqe, dfd, path, 0, 0);
1005
+ sqe->unlink_flags = (__u32) flags;
1006
+ }
1007
+
1008
+ IOURINGINLINE void io_uring_prep_unlink(struct io_uring_sqe *sqe,
1009
+ const char *path, int flags)
1010
+ {
1011
+ io_uring_prep_unlinkat(sqe, AT_FDCWD, path, flags);
1012
+ }
1013
+
1014
+ IOURINGINLINE void io_uring_prep_renameat(struct io_uring_sqe *sqe, int olddfd,
1015
+ const char *oldpath, int newdfd,
1016
+ const char *newpath, unsigned int flags)
1017
+ {
1018
+ io_uring_prep_rw(IORING_OP_RENAMEAT, sqe, olddfd, oldpath,
1019
+ (__u32) newdfd,
1020
+ (uint64_t) (uintptr_t) newpath);
1021
+ sqe->rename_flags = (__u32) flags;
1022
+ }
1023
+
1024
+ IOURINGINLINE void io_uring_prep_rename(struct io_uring_sqe *sqe,
1025
+ const char *oldpath,
1026
+ const char *newpath)
1027
+ {
1028
+ io_uring_prep_renameat(sqe, AT_FDCWD, oldpath, AT_FDCWD, newpath, 0);
1029
+ }
1030
+
1031
+ IOURINGINLINE void io_uring_prep_sync_file_range(struct io_uring_sqe *sqe,
1032
+ int fd, unsigned len,
1033
+ __u64 offset, int flags)
1034
+ {
1035
+ io_uring_prep_rw(IORING_OP_SYNC_FILE_RANGE, sqe, fd, NULL, len, offset);
1036
+ sqe->sync_range_flags = (__u32) flags;
1037
+ }
1038
+
1039
+ IOURINGINLINE void io_uring_prep_mkdirat(struct io_uring_sqe *sqe, int dfd,
1040
+ const char *path, mode_t mode)
1041
+ {
1042
+ io_uring_prep_rw(IORING_OP_MKDIRAT, sqe, dfd, path, mode, 0);
1043
+ }
1044
+
1045
+ IOURINGINLINE void io_uring_prep_mkdir(struct io_uring_sqe *sqe,
1046
+ const char *path, mode_t mode)
1047
+ {
1048
+ io_uring_prep_mkdirat(sqe, AT_FDCWD, path, mode);
1049
+ }
1050
+
1051
+ IOURINGINLINE void io_uring_prep_symlinkat(struct io_uring_sqe *sqe,
1052
+ const char *target, int newdirfd,
1053
+ const char *linkpath)
1054
+ {
1055
+ io_uring_prep_rw(IORING_OP_SYMLINKAT, sqe, newdirfd, target, 0,
1056
+ (uint64_t) (uintptr_t) linkpath);
1057
+ }
1058
+
1059
+ IOURINGINLINE void io_uring_prep_symlink(struct io_uring_sqe *sqe,
1060
+ const char *target,
1061
+ const char *linkpath)
1062
+ {
1063
+ io_uring_prep_symlinkat(sqe, target, AT_FDCWD, linkpath);
1064
+ }
1065
+
1066
+ IOURINGINLINE void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd,
1067
+ const char *oldpath, int newdfd,
1068
+ const char *newpath, int flags)
1069
+ {
1070
+ io_uring_prep_rw(IORING_OP_LINKAT, sqe, olddfd, oldpath, (__u32) newdfd,
1071
+ (uint64_t) (uintptr_t) newpath);
1072
+ sqe->hardlink_flags = (__u32) flags;
1073
+ }
1074
+
1075
+ IOURINGINLINE void io_uring_prep_link(struct io_uring_sqe *sqe,
1076
+ const char *oldpath, const char *newpath,
1077
+ int flags)
1078
+ {
1079
+ io_uring_prep_linkat(sqe, AT_FDCWD, oldpath, AT_FDCWD, newpath, flags);
1080
+ }
1081
+
1082
+ IOURINGINLINE void io_uring_prep_msg_ring_cqe_flags(struct io_uring_sqe *sqe,
1083
+ int fd, unsigned int len, __u64 data,
1084
+ unsigned int flags, unsigned int cqe_flags)
1085
+ {
1086
+ io_uring_prep_rw(IORING_OP_MSG_RING, sqe, fd, NULL, len, data);
1087
+ sqe->msg_ring_flags = IORING_MSG_RING_FLAGS_PASS | flags;
1088
+ sqe->file_index = cqe_flags;
1089
+ }
1090
+
1091
+ IOURINGINLINE void io_uring_prep_msg_ring(struct io_uring_sqe *sqe, int fd,
1092
+ unsigned int len, __u64 data,
1093
+ unsigned int flags)
1094
+ {
1095
+ io_uring_prep_rw(IORING_OP_MSG_RING, sqe, fd, NULL, len, data);
1096
+ sqe->msg_ring_flags = flags;
1097
+ }
1098
+
1099
+ IOURINGINLINE void io_uring_prep_msg_ring_fd(struct io_uring_sqe *sqe, int fd,
1100
+ int source_fd, int target_fd,
1101
+ __u64 data, unsigned int flags)
1102
+ {
1103
+ io_uring_prep_rw(IORING_OP_MSG_RING, sqe, fd,
1104
+ (void *) (uintptr_t) IORING_MSG_SEND_FD, 0, data);
1105
+ sqe->addr3 = source_fd;
1106
+ /* offset by 1 for allocation */
1107
+ if ((unsigned int) target_fd == IORING_FILE_INDEX_ALLOC)
1108
+ target_fd--;
1109
+ __io_uring_set_target_fixed_file(sqe, target_fd);
1110
+ sqe->msg_ring_flags = flags;
1111
+ }
1112
+
1113
+ IOURINGINLINE void io_uring_prep_msg_ring_fd_alloc(struct io_uring_sqe *sqe,
1114
+ int fd, int source_fd,
1115
+ __u64 data, unsigned int flags)
1116
+ {
1117
+ io_uring_prep_msg_ring_fd(sqe, fd, source_fd, IORING_FILE_INDEX_ALLOC,
1118
+ data, flags);
1119
+ }
1120
+
1121
+ IOURINGINLINE void io_uring_prep_getxattr(struct io_uring_sqe *sqe,
1122
+ const char *name, char *value,
1123
+ const char *path, unsigned int len)
1124
+ {
1125
+ io_uring_prep_rw(IORING_OP_GETXATTR, sqe, 0, name, len,
1126
+ (__u64) (uintptr_t) value);
1127
+ sqe->addr3 = (__u64) (uintptr_t) path;
1128
+ sqe->xattr_flags = 0;
1129
+ }
1130
+
1131
+ IOURINGINLINE void io_uring_prep_setxattr(struct io_uring_sqe *sqe,
1132
+ const char *name, const char *value,
1133
+ const char *path, int flags,
1134
+ unsigned int len)
1135
+ {
1136
+ io_uring_prep_rw(IORING_OP_SETXATTR, sqe, 0, name, len,
1137
+ (__u64) (uintptr_t) value);
1138
+ sqe->addr3 = (__u64) (uintptr_t) path;
1139
+ sqe->xattr_flags = flags;
1140
+ }
1141
+
1142
+ IOURINGINLINE void io_uring_prep_fgetxattr(struct io_uring_sqe *sqe,
1143
+ int fd, const char *name,
1144
+ char *value, unsigned int len)
1145
+ {
1146
+ io_uring_prep_rw(IORING_OP_FGETXATTR, sqe, fd, name, len,
1147
+ (__u64) (uintptr_t) value);
1148
+ sqe->xattr_flags = 0;
1149
+ }
1150
+
1151
+ IOURINGINLINE void io_uring_prep_fsetxattr(struct io_uring_sqe *sqe, int fd,
1152
+ const char *name, const char *value,
1153
+ int flags, unsigned int len)
1154
+ {
1155
+ io_uring_prep_rw(IORING_OP_FSETXATTR, sqe, fd, name, len,
1156
+ (__u64) (uintptr_t) value);
1157
+ sqe->xattr_flags = flags;
1158
+ }
1159
+
1160
+ IOURINGINLINE void io_uring_prep_socket(struct io_uring_sqe *sqe, int domain,
1161
+ int type, int protocol,
1162
+ unsigned int flags)
1163
+ {
1164
+ io_uring_prep_rw(IORING_OP_SOCKET, sqe, domain, NULL, protocol, type);
1165
+ sqe->rw_flags = flags;
1166
+ }
1167
+
1168
+ IOURINGINLINE void io_uring_prep_socket_direct(struct io_uring_sqe *sqe,
1169
+ int domain, int type,
1170
+ int protocol,
1171
+ unsigned file_index,
1172
+ unsigned int flags)
1173
+ {
1174
+ io_uring_prep_rw(IORING_OP_SOCKET, sqe, domain, NULL, protocol, type);
1175
+ sqe->rw_flags = flags;
1176
+ /* offset by 1 for allocation */
1177
+ if (file_index == IORING_FILE_INDEX_ALLOC)
1178
+ file_index--;
1179
+ __io_uring_set_target_fixed_file(sqe, file_index);
1180
+ }
1181
+
1182
+ IOURINGINLINE void io_uring_prep_socket_direct_alloc(struct io_uring_sqe *sqe,
1183
+ int domain, int type,
1184
+ int protocol,
1185
+ unsigned int flags)
1186
+ {
1187
+ io_uring_prep_rw(IORING_OP_SOCKET, sqe, domain, NULL, protocol, type);
1188
+ sqe->rw_flags = flags;
1189
+ __io_uring_set_target_fixed_file(sqe, IORING_FILE_INDEX_ALLOC - 1);
1190
+ }
1191
+
1192
+ /*
1193
+ * Prepare commands for sockets
1194
+ */
1195
+ IOURINGINLINE void io_uring_prep_cmd_sock(struct io_uring_sqe *sqe,
1196
+ int cmd_op,
1197
+ int fd,
1198
+ int level,
1199
+ int optname,
1200
+ void *optval,
1201
+ int optlen)
1202
+ {
1203
+ io_uring_prep_rw(IORING_OP_URING_CMD, sqe, fd, NULL, 0, 0);
1204
+ sqe->optval = (unsigned long) (uintptr_t) optval;
1205
+ sqe->optname = optname;
1206
+ sqe->optlen = optlen;
1207
+ sqe->cmd_op = cmd_op;
1208
+ sqe->level = level;
1209
+ }
1210
+
1211
+ IOURINGINLINE void io_uring_prep_waitid(struct io_uring_sqe *sqe,
1212
+ idtype_t idtype,
1213
+ id_t id,
1214
+ siginfo_t *infop,
1215
+ int options, unsigned int flags)
1216
+ {
1217
+ io_uring_prep_rw(IORING_OP_WAITID, sqe, id, NULL, (unsigned) idtype, 0);
1218
+ sqe->waitid_flags = flags;
1219
+ sqe->file_index = options;
1220
+ sqe->addr2 = (unsigned long) infop;
1221
+ }
1222
+
1223
+ IOURINGINLINE void io_uring_prep_futex_wake(struct io_uring_sqe *sqe,
1224
+ uint32_t *futex, uint64_t val,
1225
+ uint64_t mask, uint32_t futex_flags,
1226
+ unsigned int flags)
1227
+ {
1228
+ io_uring_prep_rw(IORING_OP_FUTEX_WAKE, sqe, futex_flags, futex, 0, val);
1229
+ sqe->futex_flags = flags;
1230
+ sqe->addr3 = mask;
1231
+ }
1232
+
1233
+ IOURINGINLINE void io_uring_prep_futex_wait(struct io_uring_sqe *sqe,
1234
+ uint32_t *futex, uint64_t val,
1235
+ uint64_t mask, uint32_t futex_flags,
1236
+ unsigned int flags)
1237
+ {
1238
+ io_uring_prep_rw(IORING_OP_FUTEX_WAIT, sqe, futex_flags, futex, 0, val);
1239
+ sqe->futex_flags = flags;
1240
+ sqe->addr3 = mask;
1241
+ }
1242
+
1243
+ struct futex_waitv;
1244
+ IOURINGINLINE void io_uring_prep_futex_waitv(struct io_uring_sqe *sqe,
1245
+ struct futex_waitv *futex,
1246
+ uint32_t nr_futex,
1247
+ unsigned int flags)
1248
+ {
1249
+ io_uring_prep_rw(IORING_OP_FUTEX_WAITV, sqe, 0, futex, nr_futex, 0);
1250
+ sqe->futex_flags = flags;
1251
+ }
1252
+
1253
+ IOURINGINLINE void io_uring_prep_fixed_fd_install(struct io_uring_sqe *sqe,
1254
+ int fd,
1255
+ unsigned int flags)
1256
+ {
1257
+ io_uring_prep_rw(IORING_OP_FIXED_FD_INSTALL, sqe, fd, NULL, 0, 0);
1258
+ sqe->flags = IOSQE_FIXED_FILE;
1259
+ sqe->install_fd_flags = flags;
1260
+ }
1261
+
1262
+ IOURINGINLINE void io_uring_prep_ftruncate(struct io_uring_sqe *sqe,
1263
+ int fd, loff_t len)
1264
+ {
1265
+ io_uring_prep_rw(IORING_OP_FTRUNCATE, sqe, fd, 0, 0, len);
1266
+ }
1267
+
1268
+ /*
1269
+ * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
1270
+ * the SQ ring
1271
+ */
1272
+ IOURINGINLINE unsigned io_uring_sq_ready(const struct io_uring *ring)
1273
+ {
1274
+ unsigned khead;
1275
+
1276
+ /*
1277
+ * Without a barrier, we could miss an update and think the SQ wasn't
1278
+ * ready. We don't need the load acquire for non-SQPOLL since then we
1279
+ * drive updates.
1280
+ */
1281
+ if (ring->flags & IORING_SETUP_SQPOLL)
1282
+ khead = io_uring_smp_load_acquire(ring->sq.khead);
1283
+ else
1284
+ khead = *ring->sq.khead;
1285
+
1286
+ /* always use real head, to avoid losing sync for short submit */
1287
+ return ring->sq.sqe_tail - khead;
1288
+ }
1289
+
1290
+ /*
1291
+ * Returns how much space is left in the SQ ring.
1292
+ */
1293
+ IOURINGINLINE unsigned io_uring_sq_space_left(const struct io_uring *ring)
1294
+ {
1295
+ return ring->sq.ring_entries - io_uring_sq_ready(ring);
1296
+ }
1297
+
1298
+ /*
1299
+ * Only applicable when using SQPOLL - allows the caller to wait for space
1300
+ * to free up in the SQ ring, which happens when the kernel side thread has
1301
+ * consumed one or more entries. If the SQ ring is currently non-full, no
1302
+ * action is taken. Note: may return -EINVAL if the kernel doesn't support
1303
+ * this feature.
1304
+ */
1305
+ IOURINGINLINE int io_uring_sqring_wait(struct io_uring *ring)
1306
+ {
1307
+ if (!(ring->flags & IORING_SETUP_SQPOLL))
1308
+ return 0;
1309
+ if (io_uring_sq_space_left(ring))
1310
+ return 0;
1311
+
1312
+ return __io_uring_sqring_wait(ring);
1313
+ }
1314
+
1315
+ /*
1316
+ * Returns how many unconsumed entries are ready in the CQ ring
1317
+ */
1318
+ IOURINGINLINE unsigned io_uring_cq_ready(const struct io_uring *ring)
1319
+ {
1320
+ return io_uring_smp_load_acquire(ring->cq.ktail) - *ring->cq.khead;
1321
+ }
1322
+
1323
+ /*
1324
+ * Returns true if there are overflow entries waiting to be flushed onto
1325
+ * the CQ ring
1326
+ */
1327
+ IOURINGINLINE bool io_uring_cq_has_overflow(const struct io_uring *ring)
1328
+ {
1329
+ return IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_CQ_OVERFLOW;
1330
+ }
1331
+
1332
+ /*
1333
+ * Returns true if the eventfd notification is currently enabled
1334
+ */
1335
+ IOURINGINLINE bool io_uring_cq_eventfd_enabled(const struct io_uring *ring)
1336
+ {
1337
+ if (!ring->cq.kflags)
1338
+ return true;
1339
+
1340
+ return !(*ring->cq.kflags & IORING_CQ_EVENTFD_DISABLED);
1341
+ }
1342
+
1343
+ /*
1344
+ * Toggle eventfd notification on or off, if an eventfd is registered with
1345
+ * the ring.
1346
+ */
1347
+ IOURINGINLINE int io_uring_cq_eventfd_toggle(struct io_uring *ring,
1348
+ bool enabled)
1349
+ {
1350
+ uint32_t flags;
1351
+
1352
+ if (!!enabled == io_uring_cq_eventfd_enabled(ring))
1353
+ return 0;
1354
+
1355
+ if (!ring->cq.kflags)
1356
+ return -EOPNOTSUPP;
1357
+
1358
+ flags = *ring->cq.kflags;
1359
+
1360
+ if (enabled)
1361
+ flags &= ~IORING_CQ_EVENTFD_DISABLED;
1362
+ else
1363
+ flags |= IORING_CQ_EVENTFD_DISABLED;
1364
+
1365
+ IO_URING_WRITE_ONCE(*ring->cq.kflags, flags);
1366
+
1367
+ return 0;
1368
+ }
1369
+
1370
+ /*
1371
+ * Return an IO completion, waiting for 'wait_nr' completions if one isn't
1372
+ * readily available. Returns 0 with cqe_ptr filled in on success, -errno on
1373
+ * failure.
1374
+ */
1375
+ IOURINGINLINE int io_uring_wait_cqe_nr(struct io_uring *ring,
1376
+ struct io_uring_cqe **cqe_ptr,
1377
+ unsigned wait_nr)
1378
+ {
1379
+ return __io_uring_get_cqe(ring, cqe_ptr, 0, wait_nr, NULL);
1380
+ }
1381
+
1382
+ /*
1383
+ * Internal helper, don't use directly in applications. Use one of the
1384
+ * "official" versions of this, io_uring_peek_cqe(), io_uring_wait_cqe(),
1385
+ * or io_uring_wait_cqes*().
1386
+ */
1387
+ IOURINGINLINE int __io_uring_peek_cqe(struct io_uring *ring,
1388
+ struct io_uring_cqe **cqe_ptr,
1389
+ unsigned *nr_available)
1390
+ {
1391
+ struct io_uring_cqe *cqe;
1392
+ int err = 0;
1393
+ unsigned available;
1394
+ unsigned mask = ring->cq.ring_mask;
1395
+ int shift = 0;
1396
+
1397
+ if (ring->flags & IORING_SETUP_CQE32)
1398
+ shift = 1;
1399
+
1400
+ do {
1401
+ unsigned tail = io_uring_smp_load_acquire(ring->cq.ktail);
1402
+ unsigned head = *ring->cq.khead;
1403
+
1404
+ cqe = NULL;
1405
+ available = tail - head;
1406
+ if (!available)
1407
+ break;
1408
+
1409
+ cqe = &ring->cq.cqes[(head & mask) << shift];
1410
+ if (!(ring->features & IORING_FEAT_EXT_ARG) &&
1411
+ cqe->user_data == LIBURING_UDATA_TIMEOUT) {
1412
+ if (cqe->res < 0)
1413
+ err = cqe->res;
1414
+ io_uring_cq_advance(ring, 1);
1415
+ if (!err)
1416
+ continue;
1417
+ cqe = NULL;
1418
+ }
1419
+
1420
+ break;
1421
+ } while (1);
1422
+
1423
+ *cqe_ptr = cqe;
1424
+ if (nr_available)
1425
+ *nr_available = available;
1426
+ return err;
1427
+ }
1428
+
1429
+ /*
1430
+ * Return an IO completion, if one is readily available. Returns 0 with
1431
+ * cqe_ptr filled in on success, -errno on failure.
1432
+ */
1433
+ IOURINGINLINE int io_uring_peek_cqe(struct io_uring *ring,
1434
+ struct io_uring_cqe **cqe_ptr)
1435
+ {
1436
+ if (!__io_uring_peek_cqe(ring, cqe_ptr, NULL) && *cqe_ptr)
1437
+ return 0;
1438
+
1439
+ return io_uring_wait_cqe_nr(ring, cqe_ptr, 0);
1440
+ }
1441
+
1442
+ /*
1443
+ * Return an IO completion, waiting for it if necessary. Returns 0 with
1444
+ * cqe_ptr filled in on success, -errno on failure.
1445
+ */
1446
+ IOURINGINLINE int io_uring_wait_cqe(struct io_uring *ring,
1447
+ struct io_uring_cqe **cqe_ptr)
1448
+ {
1449
+ if (!__io_uring_peek_cqe(ring, cqe_ptr, NULL) && *cqe_ptr)
1450
+ return 0;
1451
+
1452
+ return io_uring_wait_cqe_nr(ring, cqe_ptr, 1);
1453
+ }
1454
+
1455
+ /*
1456
+ * Return an sqe to fill. Application must later call io_uring_submit()
1457
+ * when it's ready to tell the kernel about it. The caller may call this
1458
+ * function multiple times before calling io_uring_submit().
1459
+ *
1460
+ * Returns a vacant sqe, or NULL if we're full.
1461
+ */
1462
+ IOURINGINLINE struct io_uring_sqe *_io_uring_get_sqe(struct io_uring *ring)
1463
+ {
1464
+ struct io_uring_sq *sq = &ring->sq;
1465
+ unsigned int head, next = sq->sqe_tail + 1;
1466
+ int shift = 0;
1467
+
1468
+ if (ring->flags & IORING_SETUP_SQE128)
1469
+ shift = 1;
1470
+ if (!(ring->flags & IORING_SETUP_SQPOLL))
1471
+ head = *sq->khead;
1472
+ else
1473
+ head = io_uring_smp_load_acquire(sq->khead);
1474
+
1475
+ if (next - head <= sq->ring_entries) {
1476
+ struct io_uring_sqe *sqe;
1477
+
1478
+ sqe = &sq->sqes[(sq->sqe_tail & sq->ring_mask) << shift];
1479
+ sq->sqe_tail = next;
1480
+ io_uring_initialize_sqe(sqe);
1481
+ return sqe;
1482
+ }
1483
+
1484
+ return NULL;
1485
+ }
1486
+
1487
+ /*
1488
+ * Return the appropriate mask for a buffer ring of size 'ring_entries'
1489
+ */
1490
+ IOURINGINLINE int io_uring_buf_ring_mask(__u32 ring_entries)
1491
+ {
1492
+ return ring_entries - 1;
1493
+ }
1494
+
1495
+ IOURINGINLINE void io_uring_buf_ring_init(struct io_uring_buf_ring *br)
1496
+ {
1497
+ br->tail = 0;
1498
+ }
1499
+
1500
+ /*
1501
+ * Assign 'buf' with the addr/len/buffer ID supplied
1502
+ */
1503
+ IOURINGINLINE void io_uring_buf_ring_add(struct io_uring_buf_ring *br,
1504
+ void *addr, unsigned int len,
1505
+ unsigned short bid, int mask,
1506
+ int buf_offset)
1507
+ {
1508
+ struct io_uring_buf *buf = &br->bufs[(br->tail + buf_offset) & mask];
1509
+
1510
+ buf->addr = (unsigned long) (uintptr_t) addr;
1511
+ buf->len = len;
1512
+ buf->bid = bid;
1513
+ }
1514
+
1515
+ /*
1516
+ * Make 'count' new buffers visible to the kernel. Called after
1517
+ * io_uring_buf_ring_add() has been called 'count' times to fill in new
1518
+ * buffers.
1519
+ */
1520
+ IOURINGINLINE void io_uring_buf_ring_advance(struct io_uring_buf_ring *br,
1521
+ int count)
1522
+ {
1523
+ unsigned short new_tail = br->tail + count;
1524
+
1525
+ io_uring_smp_store_release(&br->tail, new_tail);
1526
+ }
1527
+
1528
+ IOURINGINLINE void __io_uring_buf_ring_cq_advance(struct io_uring *ring,
1529
+ struct io_uring_buf_ring *br,
1530
+ int cq_count, int buf_count)
1531
+ {
1532
+ io_uring_buf_ring_advance(br, buf_count);
1533
+ io_uring_cq_advance(ring, cq_count);
1534
+ }
1535
+
1536
+ /*
1537
+ * Make 'count' new buffers visible to the kernel while at the same time
1538
+ * advancing the CQ ring seen entries. This can be used when the application
1539
+ * is using ring provided buffers and returns buffers while processing CQEs,
1540
+ * avoiding an extra atomic when needing to increment both the CQ ring and
1541
+ * the ring buffer index at the same time.
1542
+ */
1543
+ IOURINGINLINE void io_uring_buf_ring_cq_advance(struct io_uring *ring,
1544
+ struct io_uring_buf_ring *br,
1545
+ int count)
1546
+ {
1547
+ __io_uring_buf_ring_cq_advance(ring, br, count, count);
1548
+ }
1549
+
1550
+ IOURINGINLINE int io_uring_buf_ring_available(struct io_uring *ring,
1551
+ struct io_uring_buf_ring *br,
1552
+ unsigned short bgid)
1553
+ {
1554
+ uint16_t head;
1555
+ int ret;
1556
+
1557
+ ret = io_uring_buf_ring_head(ring, bgid, &head);
1558
+ if (ret)
1559
+ return ret;
1560
+
1561
+ return (uint16_t) (br->tail - head);
1562
+ }
1563
+
1564
+ #ifndef LIBURING_INTERNAL
1565
+ IOURINGINLINE struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring)
1566
+ {
1567
+ return _io_uring_get_sqe(ring);
1568
+ }
1569
+ #else
1570
+ struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring);
1571
+ #endif
1572
+
1573
+ ssize_t io_uring_mlock_size(unsigned entries, unsigned flags);
1574
+ ssize_t io_uring_mlock_size_params(unsigned entries, struct io_uring_params *p);
1575
+
1576
+ /*
1577
+ * Versioning information for liburing.
1578
+ *
1579
+ * Use IO_URING_CHECK_VERSION() for compile time checks including from
1580
+ * preprocessor directives.
1581
+ *
1582
+ * Use io_uring_check_version() for runtime checks of the version of
1583
+ * liburing that was loaded by the dynamic linker.
1584
+ */
1585
+ int io_uring_major_version(void);
1586
+ int io_uring_minor_version(void);
1587
+ bool io_uring_check_version(int major, int minor);
1588
+
1589
+ #define IO_URING_CHECK_VERSION(major,minor) \
1590
+ (major > IO_URING_VERSION_MAJOR || \
1591
+ (major == IO_URING_VERSION_MAJOR && \
1592
+ minor > IO_URING_VERSION_MINOR))
1593
+
1594
+ #ifdef __cplusplus
1595
+ }
1596
+ #endif
1597
+
1598
+ #ifdef IOURINGINLINE
1599
+ #undef IOURINGINLINE
1600
+ #endif
1601
+
1602
+ #endif