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,654 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: run various reads tests, verifying data
4
+ *
5
+ */
6
+ #include <errno.h>
7
+ #include <stdio.h>
8
+ #include <unistd.h>
9
+ #include <stdlib.h>
10
+ #include <string.h>
11
+ #include <fcntl.h>
12
+ #include <assert.h>
13
+ #include <sys/ioctl.h>
14
+ #include <sys/stat.h>
15
+ #include <linux/fs.h>
16
+
17
+ #include "helpers.h"
18
+ #include "liburing.h"
19
+
20
+ #define FSIZE 128*1024*1024
21
+ #define CHUNK_SIZE 131072
22
+ #define PUNCH_SIZE 32768
23
+
24
+ /*
25
+ * 8 because it fits within the on-stack iov, 16 because it's larger than 8
26
+ */
27
+ #define MIN_VECS 8
28
+ #define MAX_VECS 16
29
+
30
+ /*
31
+ * Can be anything, let's just do something for a bit of parallelism
32
+ */
33
+ #define READ_BATCH 16
34
+
35
+ static void verify_buf_sync(void *buf, size_t size, bool registered)
36
+ {
37
+ #if defined(__hppa__)
38
+ if (registered) {
39
+ unsigned long off = (unsigned long) buf & 4095;
40
+ unsigned long p = (unsigned long) buf & ~4095;
41
+ int i;
42
+
43
+ size += off;
44
+ for (i = 0; i < size; i += 32)
45
+ asm volatile("fdc 0(%0)" : : "r" (p + i));
46
+ }
47
+ #endif
48
+ }
49
+
50
+ /*
51
+ * Each offset in the file has the offset / sizeof(int) stored for every
52
+ * sizeof(int) address.
53
+ */
54
+ static int verify_buf(void *buf, size_t size, off_t off, bool registered)
55
+ {
56
+ int i, u_in_buf = size / sizeof(unsigned int);
57
+ unsigned int *ptr;
58
+
59
+ verify_buf_sync(buf, size, registered);
60
+
61
+ off /= sizeof(unsigned int);
62
+ ptr = buf;
63
+ for (i = 0; i < u_in_buf; i++) {
64
+ if (off != *ptr) {
65
+ fprintf(stderr, "Found %u, wanted %llu\n", *ptr,
66
+ (unsigned long long) off);
67
+ return 1;
68
+ }
69
+ ptr++;
70
+ off++;
71
+ }
72
+
73
+ return 0;
74
+ }
75
+
76
+ static int test_truncate(struct io_uring *ring, const char *fname, int buffered,
77
+ int vectored, int provide_buf)
78
+ {
79
+ struct io_uring_cqe *cqe;
80
+ struct io_uring_sqe *sqe;
81
+ struct iovec vec;
82
+ struct stat sb;
83
+ off_t punch_off, off, file_size;
84
+ void *buf = NULL;
85
+ int u_in_buf, i, ret, fd, first_pass = 1;
86
+ unsigned int *ptr;
87
+
88
+ if (buffered)
89
+ fd = open(fname, O_RDWR);
90
+ else
91
+ fd = open(fname, O_DIRECT | O_RDWR);
92
+ if (fd < 0) {
93
+ perror("open");
94
+ return 1;
95
+ }
96
+
97
+ if (fstat(fd, &sb) < 0) {
98
+ perror("stat");
99
+ close(fd);
100
+ return 1;
101
+ }
102
+
103
+ if (S_ISREG(sb.st_mode)) {
104
+ file_size = sb.st_size;
105
+ } else if (S_ISBLK(sb.st_mode)) {
106
+ unsigned long long bytes;
107
+
108
+ if (ioctl(fd, BLKGETSIZE64, &bytes) < 0) {
109
+ perror("ioctl");
110
+ close(fd);
111
+ return 1;
112
+ }
113
+ file_size = bytes;
114
+ } else {
115
+ goto out;
116
+ }
117
+
118
+ if (file_size < CHUNK_SIZE)
119
+ goto out;
120
+
121
+ t_posix_memalign(&buf, 4096, CHUNK_SIZE);
122
+
123
+ off = file_size - (CHUNK_SIZE / 2);
124
+ punch_off = off + CHUNK_SIZE / 4;
125
+
126
+ u_in_buf = CHUNK_SIZE / sizeof(unsigned int);
127
+ ptr = buf;
128
+ for (i = 0; i < u_in_buf; i++) {
129
+ *ptr = i;
130
+ ptr++;
131
+ }
132
+ ret = pwrite(fd, buf, CHUNK_SIZE / 2, off);
133
+ if (ret < 0) {
134
+ perror("pwrite");
135
+ goto err;
136
+ } else if (ret != CHUNK_SIZE / 2)
137
+ goto out;
138
+
139
+ again:
140
+ /*
141
+ * Read in last bit of file so it's known cached, then remove half of that
142
+ * last bit so we get a short read that needs retry
143
+ */
144
+ ret = pread(fd, buf, CHUNK_SIZE / 2, off);
145
+ if (ret < 0) {
146
+ perror("pread");
147
+ goto err;
148
+ } else if (ret != CHUNK_SIZE / 2)
149
+ goto out;
150
+
151
+ if (posix_fadvise(fd, punch_off, CHUNK_SIZE / 4, POSIX_FADV_DONTNEED) < 0) {
152
+ perror("posix_fadivse");
153
+ goto err;
154
+ }
155
+
156
+ if (provide_buf) {
157
+ sqe = io_uring_get_sqe(ring);
158
+ io_uring_prep_provide_buffers(sqe, buf, CHUNK_SIZE, 1, 0, 0);
159
+ ret = io_uring_submit(ring);
160
+ if (ret != 1) {
161
+ fprintf(stderr, "submit failed %d\n", ret);
162
+ goto err;
163
+ }
164
+ ret = io_uring_wait_cqe(ring, &cqe);
165
+ if (ret < 0) {
166
+ fprintf(stderr, "wait completion %d\n", ret);
167
+ goto err;
168
+ }
169
+ ret = cqe->res;
170
+ io_uring_cqe_seen(ring, cqe);
171
+ if (ret) {
172
+ fprintf(stderr, "Provide buffer failed %d\n", ret);
173
+ goto err;
174
+ }
175
+ }
176
+
177
+ sqe = io_uring_get_sqe(ring);
178
+ if (!sqe) {
179
+ fprintf(stderr, "get sqe failed\n");
180
+ goto err;
181
+ }
182
+
183
+ if (vectored) {
184
+ assert(!provide_buf);
185
+ vec.iov_base = buf;
186
+ vec.iov_len = CHUNK_SIZE;
187
+ io_uring_prep_readv(sqe, fd, &vec, 1, off);
188
+ } else {
189
+ if (provide_buf) {
190
+ io_uring_prep_read(sqe, fd, NULL, CHUNK_SIZE, off);
191
+ sqe->flags |= IOSQE_BUFFER_SELECT;
192
+ } else {
193
+ io_uring_prep_read(sqe, fd, buf, CHUNK_SIZE, off);
194
+ }
195
+ }
196
+ memset(buf, 0, CHUNK_SIZE);
197
+
198
+ ret = io_uring_submit(ring);
199
+ if (ret != 1) {
200
+ fprintf(stderr, "Submit failed %d\n", ret);
201
+ goto err;
202
+ }
203
+
204
+ ret = io_uring_wait_cqe(ring, &cqe);
205
+ if (ret < 0) {
206
+ fprintf(stderr, "wait completion %d\n", ret);
207
+ goto err;
208
+ }
209
+
210
+ ret = cqe->res;
211
+ io_uring_cqe_seen(ring, cqe);
212
+ if (ret != CHUNK_SIZE / 2) {
213
+ fprintf(stderr, "Unexpected truncated read %d\n", ret);
214
+ goto err;
215
+ }
216
+
217
+ if (verify_buf(buf, CHUNK_SIZE / 2, 0, false))
218
+ goto err;
219
+
220
+ /*
221
+ * Repeat, but punch first part instead of last
222
+ */
223
+ if (first_pass) {
224
+ punch_off = file_size - CHUNK_SIZE / 4;
225
+ first_pass = 0;
226
+ goto again;
227
+ }
228
+
229
+ out:
230
+ free(buf);
231
+ close(fd);
232
+ return 0;
233
+ err:
234
+ free(buf);
235
+ close(fd);
236
+ return 1;
237
+ }
238
+
239
+ enum {
240
+ PUNCH_NONE,
241
+ PUNCH_FRONT,
242
+ PUNCH_MIDDLE,
243
+ PUNCH_END,
244
+ };
245
+
246
+ /*
247
+ * For each chunk in file, DONTNEED a start, end, or middle segment of it.
248
+ * We enter here with the file fully cached every time, either freshly
249
+ * written or after other reads. This forces (at least) the buffered reads
250
+ * to be handled incrementally, exercising that path.
251
+ */
252
+ static int do_punch(int fd)
253
+ {
254
+ off_t offset = 0;
255
+ int punch_type;
256
+
257
+ while (offset + CHUNK_SIZE <= FSIZE) {
258
+ off_t punch_off;
259
+
260
+ punch_type = rand() % (PUNCH_END + 1);
261
+ switch (punch_type) {
262
+ default:
263
+ case PUNCH_NONE:
264
+ punch_off = -1; /* gcc... */
265
+ break;
266
+ case PUNCH_FRONT:
267
+ punch_off = offset;
268
+ break;
269
+ case PUNCH_MIDDLE:
270
+ punch_off = offset + PUNCH_SIZE;
271
+ break;
272
+ case PUNCH_END:
273
+ punch_off = offset + CHUNK_SIZE - PUNCH_SIZE;
274
+ break;
275
+ }
276
+
277
+ offset += CHUNK_SIZE;
278
+ if (punch_type == PUNCH_NONE)
279
+ continue;
280
+ if (posix_fadvise(fd, punch_off, PUNCH_SIZE, POSIX_FADV_DONTNEED) < 0) {
281
+ perror("posix_fadivse");
282
+ return 1;
283
+ }
284
+ }
285
+
286
+ return 0;
287
+ }
288
+
289
+ static int provide_buffers(struct io_uring *ring, void **buf)
290
+ {
291
+ struct io_uring_cqe *cqe;
292
+ struct io_uring_sqe *sqe;
293
+ int i, ret;
294
+
295
+ /* real use case would have one buffer chopped up, but... */
296
+ for (i = 0; i < READ_BATCH; i++) {
297
+ sqe = io_uring_get_sqe(ring);
298
+ io_uring_prep_provide_buffers(sqe, buf[i], CHUNK_SIZE, 1, 0, i);
299
+ }
300
+
301
+ ret = io_uring_submit(ring);
302
+ if (ret != READ_BATCH) {
303
+ fprintf(stderr, "Submit failed %d\n", ret);
304
+ return 1;
305
+ }
306
+
307
+ for (i = 0; i < READ_BATCH; i++) {
308
+ ret = io_uring_wait_cqe(ring, &cqe);
309
+ if (ret) {
310
+ fprintf(stderr, "wait cqe %d\n", ret);
311
+ return 1;
312
+ }
313
+ if (cqe->res < 0) {
314
+ fprintf(stderr, "cqe res provide %d\n", cqe->res);
315
+ return 1;
316
+ }
317
+ io_uring_cqe_seen(ring, cqe);
318
+ }
319
+
320
+ return 0;
321
+ }
322
+
323
+ static int test(struct io_uring *ring, const char *fname, int buffered,
324
+ int vectored, int small_vecs, int registered, int provide)
325
+ {
326
+ struct iovec vecs[READ_BATCH][MAX_VECS];
327
+ struct io_uring_cqe *cqe;
328
+ struct io_uring_sqe *sqe;
329
+ void *buf[READ_BATCH];
330
+ int ret, fd, flags;
331
+ int i, j, nr_vecs;
332
+ off_t off, voff;
333
+ size_t left;
334
+
335
+ if (registered) {
336
+ assert(!provide);
337
+ assert(!vectored && !small_vecs);
338
+ }
339
+ if (provide) {
340
+ assert(!registered);
341
+ assert(!vectored && !small_vecs);
342
+ }
343
+
344
+ flags = O_RDONLY;
345
+ if (!buffered)
346
+ flags |= O_DIRECT;
347
+ fd = open(fname, flags);
348
+ if (fd < 0) {
349
+ perror("open");
350
+ return 1;
351
+ }
352
+
353
+ if (do_punch(fd))
354
+ return 1;
355
+
356
+ if (vectored) {
357
+ if (small_vecs)
358
+ nr_vecs = MIN_VECS;
359
+ else
360
+ nr_vecs = MAX_VECS;
361
+
362
+ for (j = 0; j < READ_BATCH; j++) {
363
+ for (i = 0; i < nr_vecs; i++) {
364
+ void *ptr;
365
+
366
+ t_posix_memalign(&ptr, 4096, CHUNK_SIZE / nr_vecs);
367
+ vecs[j][i].iov_base = ptr;
368
+ vecs[j][i].iov_len = CHUNK_SIZE / nr_vecs;
369
+ }
370
+ }
371
+ } else {
372
+ for (j = 0; j < READ_BATCH; j++)
373
+ t_posix_memalign(&buf[j], 4096, CHUNK_SIZE);
374
+ nr_vecs = 0;
375
+ }
376
+
377
+ if (registered) {
378
+ struct iovec v[READ_BATCH];
379
+
380
+ for (i = 0; i < READ_BATCH; i++) {
381
+ v[i].iov_base = buf[i];
382
+ v[i].iov_len = CHUNK_SIZE;
383
+ }
384
+ ret = t_register_buffers(ring, v, READ_BATCH);
385
+ if (ret) {
386
+ if (ret == T_SETUP_SKIP) {
387
+ ret = 0;
388
+ goto free_bufs;
389
+ }
390
+ goto err;
391
+ }
392
+ }
393
+
394
+ i = 0;
395
+ left = FSIZE;
396
+ off = 0;
397
+ while (left) {
398
+ int pending = 0;
399
+
400
+ if (provide && provide_buffers(ring, buf))
401
+ goto err;
402
+
403
+ for (i = 0; i < READ_BATCH; i++) {
404
+ size_t this = left;
405
+
406
+ if (this > CHUNK_SIZE)
407
+ this = CHUNK_SIZE;
408
+
409
+ sqe = io_uring_get_sqe(ring);
410
+ if (!sqe) {
411
+ fprintf(stderr, "get sqe failed\n");
412
+ goto err;
413
+ }
414
+
415
+ if (vectored) {
416
+ io_uring_prep_readv(sqe, fd, vecs[i], nr_vecs, off);
417
+ } else {
418
+ if (registered) {
419
+ io_uring_prep_read_fixed(sqe, fd, buf[i], this, off, i);
420
+ } else if (provide) {
421
+ io_uring_prep_read(sqe, fd, NULL, this, off);
422
+ sqe->flags |= IOSQE_BUFFER_SELECT;
423
+ } else {
424
+ io_uring_prep_read(sqe, fd, buf[i], this, off);
425
+ }
426
+ }
427
+ sqe->user_data = ((uint64_t)off << 32) | i;
428
+ off += this;
429
+ left -= this;
430
+ pending++;
431
+ if (!left)
432
+ break;
433
+ }
434
+
435
+ ret = io_uring_submit(ring);
436
+ if (ret != pending) {
437
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
438
+ goto err;
439
+ }
440
+
441
+ for (i = 0; i < pending; i++) {
442
+ int index;
443
+
444
+ ret = io_uring_wait_cqe(ring, &cqe);
445
+ if (ret < 0) {
446
+ fprintf(stderr, "wait completion %d\n", ret);
447
+ goto err;
448
+ }
449
+ if (cqe->res < 0) {
450
+ fprintf(stderr, "bad read %d, read %d\n", cqe->res, i);
451
+ goto err;
452
+ }
453
+ if (cqe->res < CHUNK_SIZE) {
454
+ fprintf(stderr, "short read %d, read %d\n", cqe->res, i);
455
+ goto err;
456
+ }
457
+ if (cqe->flags & IORING_CQE_F_BUFFER)
458
+ index = cqe->flags >> 16;
459
+ else
460
+ index = cqe->user_data & 0xffffffff;
461
+ voff = cqe->user_data >> 32;
462
+ io_uring_cqe_seen(ring, cqe);
463
+ if (vectored) {
464
+ for (j = 0; j < nr_vecs; j++) {
465
+ void *buf = vecs[index][j].iov_base;
466
+ size_t len = vecs[index][j].iov_len;
467
+
468
+ if (verify_buf(buf, len, voff, registered))
469
+ goto err;
470
+ voff += len;
471
+ }
472
+ } else {
473
+ if (verify_buf(buf[index], CHUNK_SIZE, voff, registered))
474
+ goto err;
475
+ }
476
+ }
477
+ }
478
+
479
+ ret = 0;
480
+ done:
481
+ if (registered)
482
+ io_uring_unregister_buffers(ring);
483
+ free_bufs:
484
+ if (vectored) {
485
+ for (j = 0; j < READ_BATCH; j++)
486
+ for (i = 0; i < nr_vecs; i++)
487
+ free(vecs[j][i].iov_base);
488
+ } else {
489
+ for (j = 0; j < READ_BATCH; j++)
490
+ free(buf[j]);
491
+ }
492
+ close(fd);
493
+ return ret;
494
+ err:
495
+ ret = 1;
496
+ goto done;
497
+ }
498
+
499
+ static int fill_pattern(const char *fname)
500
+ {
501
+ size_t left = FSIZE;
502
+ unsigned int val, *ptr;
503
+ void *buf;
504
+ int fd, i;
505
+
506
+ fd = open(fname, O_WRONLY);
507
+ if (fd < 0) {
508
+ perror("open");
509
+ return 1;
510
+ }
511
+
512
+ val = 0;
513
+ buf = t_malloc(4096);
514
+ while (left) {
515
+ int u_in_buf = 4096 / sizeof(val);
516
+ size_t this = left;
517
+
518
+ if (this > 4096)
519
+ this = 4096;
520
+ ptr = buf;
521
+ for (i = 0; i < u_in_buf; i++) {
522
+ *ptr = val;
523
+ val++;
524
+ ptr++;
525
+ }
526
+ if (write(fd, buf, 4096) != 4096)
527
+ return 1;
528
+ left -= 4096;
529
+ }
530
+
531
+ fsync(fd);
532
+ close(fd);
533
+ free(buf);
534
+ return 0;
535
+ }
536
+
537
+ int main(int argc, char *argv[])
538
+ {
539
+ struct io_uring ring;
540
+ const char *fname;
541
+ char buf[32];
542
+ int ret;
543
+
544
+ srand(getpid());
545
+
546
+ if (argc > 1) {
547
+ fname = argv[1];
548
+ } else {
549
+ sprintf(buf, ".file-verify.%d", getpid());
550
+ fname = buf;
551
+ t_create_file(fname, FSIZE);
552
+ }
553
+
554
+ ret = io_uring_queue_init(READ_BATCH, &ring, 0);
555
+ if (ret) {
556
+ fprintf(stderr, "ring setup failed: %d\n", ret);
557
+ goto err;
558
+ }
559
+
560
+ if (fill_pattern(fname))
561
+ goto err;
562
+
563
+ ret = test(&ring, fname, 1, 0, 0, 0, 0);
564
+ if (ret) {
565
+ fprintf(stderr, "Buffered novec test failed\n");
566
+ goto err;
567
+ }
568
+ ret = test(&ring, fname, 1, 0, 0, 1, 0);
569
+ if (ret) {
570
+ fprintf(stderr, "Buffered novec reg test failed\n");
571
+ goto err;
572
+ }
573
+ ret = test(&ring, fname, 1, 0, 0, 0, 1);
574
+ if (ret) {
575
+ fprintf(stderr, "Buffered novec provide test failed\n");
576
+ goto err;
577
+ }
578
+ ret = test(&ring, fname, 1, 1, 0, 0, 0);
579
+ if (ret) {
580
+ fprintf(stderr, "Buffered vec test failed\n");
581
+ goto err;
582
+ }
583
+ ret = test(&ring, fname, 1, 1, 1, 0, 0);
584
+ if (ret) {
585
+ fprintf(stderr, "Buffered small vec test failed\n");
586
+ goto err;
587
+ }
588
+
589
+ ret = test(&ring, fname, 0, 0, 0, 0, 0);
590
+ if (ret) {
591
+ fprintf(stderr, "O_DIRECT novec test failed\n");
592
+ goto err;
593
+ }
594
+ ret = test(&ring, fname, 0, 0, 0, 1, 0);
595
+ if (ret) {
596
+ fprintf(stderr, "O_DIRECT novec reg test failed\n");
597
+ goto err;
598
+ }
599
+ ret = test(&ring, fname, 0, 0, 0, 0, 1);
600
+ if (ret) {
601
+ fprintf(stderr, "O_DIRECT novec provide test failed\n");
602
+ goto err;
603
+ }
604
+ ret = test(&ring, fname, 0, 1, 0, 0, 0);
605
+ if (ret) {
606
+ fprintf(stderr, "O_DIRECT vec test failed\n");
607
+ goto err;
608
+ }
609
+ ret = test(&ring, fname, 0, 1, 1, 0, 0);
610
+ if (ret) {
611
+ fprintf(stderr, "O_DIRECT small vec test failed\n");
612
+ goto err;
613
+ }
614
+
615
+ ret = test_truncate(&ring, fname, 1, 0, 0);
616
+ if (ret) {
617
+ fprintf(stderr, "Buffered end truncate read failed\n");
618
+ goto err;
619
+ }
620
+ ret = test_truncate(&ring, fname, 1, 1, 0);
621
+ if (ret) {
622
+ fprintf(stderr, "Buffered end truncate vec read failed\n");
623
+ goto err;
624
+ }
625
+ ret = test_truncate(&ring, fname, 1, 0, 1);
626
+ if (ret) {
627
+ fprintf(stderr, "Buffered end truncate pbuf read failed\n");
628
+ goto err;
629
+ }
630
+
631
+ ret = test_truncate(&ring, fname, 0, 0, 0);
632
+ if (ret) {
633
+ fprintf(stderr, "O_DIRECT end truncate read failed\n");
634
+ goto err;
635
+ }
636
+ ret = test_truncate(&ring, fname, 0, 1, 0);
637
+ if (ret) {
638
+ fprintf(stderr, "O_DIRECT end truncate vec read failed\n");
639
+ goto err;
640
+ }
641
+ ret = test_truncate(&ring, fname, 0, 0, 1);
642
+ if (ret) {
643
+ fprintf(stderr, "O_DIRECT end truncate pbuf read failed\n");
644
+ goto err;
645
+ }
646
+
647
+ if (buf == fname)
648
+ unlink(fname);
649
+ return T_EXIT_PASS;
650
+ err:
651
+ if (buf == fname)
652
+ unlink(fname);
653
+ return T_EXIT_FAIL;
654
+ }