polyphony 0.98 → 0.99.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 (267) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -1
  3. data/.rubocop.yml +3 -3
  4. data/.yardopts +30 -0
  5. data/CHANGELOG.md +11 -0
  6. data/LICENSE +1 -1
  7. data/README.md +63 -29
  8. data/Rakefile +1 -5
  9. data/TODO.md +0 -4
  10. data/docs/{main-concepts/concurrency.md → concurrency.md} +2 -9
  11. data/docs/{main-concepts/design-principles.md → design-principles.md} +3 -9
  12. data/docs/{main-concepts/exception-handling.md → exception-handling.md} +2 -9
  13. data/docs/{main-concepts/extending.md → extending.md} +2 -9
  14. data/docs/faq.md +3 -16
  15. data/docs/{main-concepts/fiber-scheduling.md → fiber-scheduling.md} +1 -9
  16. data/docs/link_rewriter.rb +16 -0
  17. data/docs/{getting-started/overview.md → overview.md} +1 -30
  18. data/docs/{getting-started/tutorial.md → tutorial.md} +3 -28
  19. data/docs/{_posts/2020-07-26-polyphony-0.44.md → whats-new.md} +3 -1
  20. data/examples/adapters/redis_client.rb +3 -2
  21. data/examples/io/echo_server.rb +1 -1
  22. data/examples/io/echo_server_plain_ruby.rb +26 -0
  23. data/examples/io/https_server_sni_2.rb +14 -8
  24. data/ext/polyphony/backend_io_uring.c +154 -9
  25. data/ext/polyphony/backend_io_uring_context.c +21 -12
  26. data/ext/polyphony/backend_io_uring_context.h +12 -7
  27. data/ext/polyphony/backend_libev.c +1 -1
  28. data/ext/polyphony/extconf.rb +25 -8
  29. data/ext/polyphony/fiber.c +79 -2
  30. data/ext/polyphony/io_extensions.c +53 -0
  31. data/ext/polyphony/libev.h +0 -2
  32. data/ext/polyphony/pipe.c +42 -2
  33. data/ext/polyphony/polyphony.c +345 -31
  34. data/ext/polyphony/polyphony.h +9 -2
  35. data/ext/polyphony/queue.c +181 -0
  36. data/ext/polyphony/ring_buffer.c +0 -1
  37. data/ext/polyphony/runqueue.c +8 -1
  38. data/ext/polyphony/runqueue_ring_buffer.c +13 -0
  39. data/ext/polyphony/runqueue_ring_buffer.h +2 -1
  40. data/ext/polyphony/socket_extensions.c +6 -0
  41. data/ext/polyphony/thread.c +34 -2
  42. data/lib/polyphony/adapters/process.rb +11 -1
  43. data/lib/polyphony/adapters/sequel.rb +1 -1
  44. data/lib/polyphony/core/channel.rb +2 -0
  45. data/lib/polyphony/core/debug.rb +1 -1
  46. data/lib/polyphony/core/global_api.rb +25 -24
  47. data/lib/polyphony/core/resource_pool.rb +7 -6
  48. data/lib/polyphony/core/sync.rb +55 -2
  49. data/lib/polyphony/core/thread_pool.rb +3 -3
  50. data/lib/polyphony/core/timer.rb +8 -8
  51. data/lib/polyphony/extensions/exception.rb +2 -0
  52. data/lib/polyphony/extensions/fiber.rb +15 -13
  53. data/lib/polyphony/extensions/io.rb +161 -16
  54. data/lib/polyphony/extensions/kernel.rb +20 -2
  55. data/lib/polyphony/extensions/openssl.rb +101 -12
  56. data/lib/polyphony/extensions/pipe.rb +103 -7
  57. data/lib/polyphony/extensions/process.rb +13 -1
  58. data/lib/polyphony/extensions/socket.rb +93 -27
  59. data/lib/polyphony/extensions/thread.rb +9 -1
  60. data/lib/polyphony/extensions/timeout.rb +1 -1
  61. data/lib/polyphony/version.rb +2 -1
  62. data/lib/polyphony.rb +27 -7
  63. data/polyphony.gemspec +1 -8
  64. data/test/stress.rb +1 -1
  65. data/test/test_global_api.rb +45 -7
  66. data/test/test_io.rb +6 -7
  67. data/test/test_socket.rb +157 -0
  68. data/test/test_sync.rb +42 -1
  69. data/test/test_timer.rb +5 -5
  70. data/vendor/liburing/.github/workflows/build.yml +7 -16
  71. data/vendor/liburing/.gitignore +5 -0
  72. data/vendor/liburing/CHANGELOG +23 -1
  73. data/vendor/liburing/Makefile +4 -3
  74. data/vendor/liburing/Makefile.common +1 -0
  75. data/vendor/liburing/README +48 -0
  76. data/vendor/liburing/configure +76 -6
  77. data/vendor/liburing/debian/changelog +11 -0
  78. data/vendor/liburing/debian/control +7 -16
  79. data/vendor/liburing/debian/liburing-dev.manpages +3 -6
  80. data/vendor/liburing/debian/liburing2.install +1 -0
  81. data/vendor/liburing/debian/liburing2.symbols +56 -0
  82. data/vendor/liburing/debian/rules +15 -68
  83. data/vendor/liburing/examples/Makefile +4 -0
  84. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  85. data/vendor/liburing/examples/io_uring-udp.c +1 -1
  86. data/vendor/liburing/examples/send-zerocopy.c +315 -56
  87. data/vendor/liburing/examples/ucontext-cp.c +2 -17
  88. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  89. data/vendor/liburing/liburing.pc.in +1 -1
  90. data/vendor/liburing/liburing.spec +1 -1
  91. data/vendor/liburing/make-debs.sh +3 -3
  92. data/vendor/liburing/man/IO_URING_CHECK_VERSION.3 +1 -0
  93. data/vendor/liburing/man/IO_URING_VERSION_MAJOR.3 +1 -0
  94. data/vendor/liburing/man/IO_URING_VERSION_MINOR.3 +1 -0
  95. data/vendor/liburing/man/io_uring_buf_ring_add.3 +6 -6
  96. data/vendor/liburing/man/io_uring_check_version.3 +72 -0
  97. data/vendor/liburing/man/io_uring_close_ring_fd.3 +43 -0
  98. data/vendor/liburing/man/io_uring_major_version.3 +1 -0
  99. data/vendor/liburing/man/io_uring_minor_version.3 +1 -0
  100. data/vendor/liburing/man/io_uring_prep_accept.3 +1 -1
  101. data/vendor/liburing/man/io_uring_prep_fgetxattr.3 +1 -0
  102. data/vendor/liburing/man/io_uring_prep_fsetxattr.3 +1 -0
  103. data/vendor/liburing/man/io_uring_prep_getxattr.3 +61 -0
  104. data/vendor/liburing/man/io_uring_prep_link_timeout.3 +94 -0
  105. data/vendor/liburing/man/io_uring_prep_msg_ring.3 +22 -2
  106. data/vendor/liburing/man/io_uring_prep_msg_ring_cqe_flags.3 +1 -0
  107. data/vendor/liburing/man/io_uring_prep_poll_add.3 +1 -1
  108. data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +18 -9
  109. data/vendor/liburing/man/io_uring_prep_readv.3 +3 -3
  110. data/vendor/liburing/man/io_uring_prep_readv2.3 +3 -3
  111. data/vendor/liburing/man/io_uring_prep_recv.3 +5 -5
  112. data/vendor/liburing/man/io_uring_prep_recvmsg.3 +4 -4
  113. data/vendor/liburing/man/io_uring_prep_send.3 +9 -0
  114. data/vendor/liburing/man/io_uring_prep_send_set_addr.3 +38 -0
  115. data/vendor/liburing/man/io_uring_prep_send_zc.3 +39 -7
  116. data/vendor/liburing/man/io_uring_prep_send_zc_fixed.3 +1 -0
  117. data/vendor/liburing/man/io_uring_prep_sendmsg.3 +20 -0
  118. data/vendor/liburing/man/io_uring_prep_sendmsg_zc.3 +1 -0
  119. data/vendor/liburing/man/io_uring_prep_setxattr.3 +64 -0
  120. data/vendor/liburing/man/io_uring_prep_splice.3 +40 -0
  121. data/vendor/liburing/man/io_uring_prep_writev.3 +2 -2
  122. data/vendor/liburing/man/io_uring_prep_writev2.3 +2 -2
  123. data/vendor/liburing/man/io_uring_recvmsg_out.3 +13 -9
  124. data/vendor/liburing/man/io_uring_register.2 +15 -9
  125. data/vendor/liburing/man/io_uring_register_buf_ring.3 +4 -4
  126. data/vendor/liburing/man/io_uring_register_buffers.3 +49 -6
  127. data/vendor/liburing/man/io_uring_register_buffers_sparse.3 +1 -0
  128. data/vendor/liburing/man/io_uring_register_buffers_tags.3 +1 -0
  129. data/vendor/liburing/man/io_uring_register_buffers_update_tag.3 +1 -0
  130. data/vendor/liburing/man/io_uring_register_files.3 +60 -5
  131. data/vendor/liburing/man/io_uring_register_files_tags.3 +1 -0
  132. data/vendor/liburing/man/io_uring_register_files_update.3 +1 -0
  133. data/vendor/liburing/man/io_uring_register_files_update_tag.3 +1 -0
  134. data/vendor/liburing/man/io_uring_setup.2 +31 -2
  135. data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +1 -1
  136. data/vendor/liburing/src/Makefile +25 -3
  137. data/vendor/liburing/src/ffi.c +15 -0
  138. data/vendor/liburing/src/include/liburing/io_uring.h +30 -7
  139. data/vendor/liburing/src/include/liburing.h +190 -148
  140. data/vendor/liburing/src/int_flags.h +1 -0
  141. data/vendor/liburing/src/lib.h +5 -16
  142. data/vendor/liburing/src/liburing-ffi.map +172 -0
  143. data/vendor/liburing/src/liburing.map +11 -0
  144. data/vendor/liburing/src/nolibc.c +9 -2
  145. data/vendor/liburing/src/queue.c +2 -2
  146. data/vendor/liburing/src/register.c +66 -96
  147. data/vendor/liburing/src/setup.c +5 -4
  148. data/vendor/liburing/src/version.c +21 -0
  149. data/vendor/liburing/test/232c93d07b74.c +3 -3
  150. data/vendor/liburing/test/35fa71a030ca.c +3 -3
  151. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  152. data/vendor/liburing/test/917257daa0fe.c +1 -1
  153. data/vendor/liburing/test/Makefile +27 -7
  154. data/vendor/liburing/test/a0908ae19763.c +2 -2
  155. data/vendor/liburing/test/a4c0b3decb33.c +2 -2
  156. data/vendor/liburing/test/accept-link.c +4 -4
  157. data/vendor/liburing/test/accept-reuse.c +5 -7
  158. data/vendor/liburing/test/accept.c +34 -31
  159. data/vendor/liburing/test/b19062a56726.c +1 -1
  160. data/vendor/liburing/test/buf-ring.c +58 -4
  161. data/vendor/liburing/test/ce593a6c480a.c +2 -2
  162. data/vendor/liburing/test/close-opath.c +2 -1
  163. data/vendor/liburing/test/connect.c +8 -0
  164. data/vendor/liburing/test/cq-overflow.c +14 -8
  165. data/vendor/liburing/test/d4ae271dfaae.c +1 -1
  166. data/vendor/liburing/test/defer-taskrun.c +64 -9
  167. data/vendor/liburing/test/defer.c +1 -1
  168. data/vendor/liburing/test/double-poll-crash.c +3 -3
  169. data/vendor/liburing/test/eeed8b54e0df.c +8 -3
  170. data/vendor/liburing/test/eploop.c +74 -0
  171. data/vendor/liburing/test/eventfd-ring.c +1 -1
  172. data/vendor/liburing/test/eventfd.c +1 -1
  173. data/vendor/liburing/test/evloop.c +73 -0
  174. data/vendor/liburing/test/exit-no-cleanup.c +1 -1
  175. data/vendor/liburing/test/fadvise.c +1 -1
  176. data/vendor/liburing/test/fc2a85cb02ef.c +3 -3
  177. data/vendor/liburing/test/fd-pass.c +35 -16
  178. data/vendor/liburing/test/file-register.c +61 -0
  179. data/vendor/liburing/test/file-verify.c +2 -2
  180. data/vendor/liburing/test/files-exit-hang-timeout.c +2 -2
  181. data/vendor/liburing/test/fixed-link.c +1 -1
  182. data/vendor/liburing/test/fsnotify.c +118 -0
  183. data/vendor/liburing/test/hardlink.c +1 -1
  184. data/vendor/liburing/test/helpers.c +54 -2
  185. data/vendor/liburing/test/helpers.h +4 -0
  186. data/vendor/liburing/test/io-cancel.c +3 -1
  187. data/vendor/liburing/test/io_uring_passthrough.c +39 -8
  188. data/vendor/liburing/test/io_uring_setup.c +3 -80
  189. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  190. data/vendor/liburing/test/iopoll.c +90 -4
  191. data/vendor/liburing/test/lfs-openat-write.c +7 -9
  192. data/vendor/liburing/test/lfs-openat.c +6 -8
  193. data/vendor/liburing/test/link_drain.c +31 -5
  194. data/vendor/liburing/test/madvise.c +1 -1
  195. data/vendor/liburing/test/msg-ring-flags.c +192 -0
  196. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  197. data/vendor/liburing/test/msg-ring.c +173 -13
  198. data/vendor/liburing/test/multicqes_drain.c +22 -19
  199. data/vendor/liburing/test/nvme.h +4 -3
  200. data/vendor/liburing/test/pipe-bug.c +95 -0
  201. data/vendor/liburing/test/poll-link.c +3 -3
  202. data/vendor/liburing/test/poll-many.c +41 -19
  203. data/vendor/liburing/test/poll-mshot-overflow.c +105 -2
  204. data/vendor/liburing/test/poll-race-mshot.c +292 -0
  205. data/vendor/liburing/test/poll-race.c +105 -0
  206. data/vendor/liburing/test/poll.c +244 -26
  207. data/vendor/liburing/test/pollfree.c +5 -5
  208. data/vendor/liburing/test/read-before-exit.c +20 -3
  209. data/vendor/liburing/test/read-write.c +2 -0
  210. data/vendor/liburing/test/recv-multishot.c +96 -3
  211. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  212. data/vendor/liburing/test/rename.c +1 -1
  213. data/vendor/liburing/test/ring-leak.c +0 -1
  214. data/vendor/liburing/test/ring-leak2.c +1 -1
  215. data/vendor/liburing/test/ringbuf-read.c +10 -6
  216. data/vendor/liburing/test/send-zerocopy.c +273 -103
  217. data/vendor/liburing/test/send_recv.c +7 -4
  218. data/vendor/liburing/test/sendmsg_fs_cve.c +2 -2
  219. data/vendor/liburing/test/single-issuer.c +7 -9
  220. data/vendor/liburing/test/skip-cqe.c +3 -4
  221. data/vendor/liburing/test/socket.c +0 -1
  222. data/vendor/liburing/test/sq-poll-dup.c +10 -3
  223. data/vendor/liburing/test/sq-poll-kthread.c +1 -1
  224. data/vendor/liburing/test/sq-poll-share.c +3 -2
  225. data/vendor/liburing/test/sqpoll-cancel-hang.c +17 -6
  226. data/vendor/liburing/test/sqpoll-disable-exit.c +4 -4
  227. data/vendor/liburing/test/symlink.c +2 -1
  228. data/vendor/liburing/test/test.h +2 -1
  229. data/vendor/liburing/test/timeout-new.c +11 -7
  230. data/vendor/liburing/test/timeout.c +1 -2
  231. data/vendor/liburing/test/unlink.c +1 -1
  232. data/vendor/liburing/test/version.c +25 -0
  233. data/vendor/liburing/test/wakeup-hang.c +1 -1
  234. data/vendor/liburing/test/xattr.c +8 -4
  235. metadata +57 -44
  236. data/docs/_config.yml +0 -64
  237. data/docs/_includes/head.html +0 -40
  238. data/docs/_includes/title.html +0 -1
  239. data/docs/_sass/custom/custom.scss +0 -10
  240. data/docs/_sass/overrides.scss +0 -0
  241. data/docs/api-reference/exception.md +0 -31
  242. data/docs/api-reference/fiber.md +0 -425
  243. data/docs/api-reference/index.md +0 -9
  244. data/docs/api-reference/io.md +0 -36
  245. data/docs/api-reference/object.md +0 -99
  246. data/docs/api-reference/polyphony-baseexception.md +0 -33
  247. data/docs/api-reference/polyphony-cancel.md +0 -26
  248. data/docs/api-reference/polyphony-moveon.md +0 -24
  249. data/docs/api-reference/polyphony-net.md +0 -20
  250. data/docs/api-reference/polyphony-process.md +0 -28
  251. data/docs/api-reference/polyphony-resourcepool.md +0 -59
  252. data/docs/api-reference/polyphony-restart.md +0 -18
  253. data/docs/api-reference/polyphony-terminate.md +0 -18
  254. data/docs/api-reference/polyphony-threadpool.md +0 -67
  255. data/docs/api-reference/polyphony-throttler.md +0 -77
  256. data/docs/api-reference/polyphony.md +0 -36
  257. data/docs/api-reference/thread.md +0 -88
  258. data/docs/favicon.ico +0 -0
  259. data/docs/getting-started/index.md +0 -10
  260. data/docs/getting-started/installing.md +0 -34
  261. data/vendor/liburing/debian/compat +0 -1
  262. data/vendor/liburing/debian/liburing1-udeb.install +0 -1
  263. data/vendor/liburing/debian/liburing1.install +0 -1
  264. data/vendor/liburing/debian/liburing1.symbols +0 -32
  265. /data/{docs/assets/img → assets}/echo-fibers.svg +0 -0
  266. /data/{docs → assets}/polyphony-logo.png +0 -0
  267. /data/{docs/assets/img → assets}/sleeping-fiber.svg +0 -0
@@ -21,9 +21,9 @@
21
21
 
22
22
  #define PORT 9100
23
23
 
24
- struct io_uring ring;
24
+ static struct io_uring ring;
25
25
 
26
- struct __kernel_timespec ts = {
26
+ static struct __kernel_timespec ts = {
27
27
  .tv_sec = 300,
28
28
  .tv_nsec = 0,
29
29
  };
@@ -36,7 +36,7 @@ int main(int argc, char *argv[])
36
36
  for (i = 0; i < IOVECS_LEN; ++i) {
37
37
  iovecs[i].iov_base = t_malloc(64);
38
38
  iovecs[i].iov_len = 64;
39
- };
39
+ }
40
40
 
41
41
  ret = io_uring_register_buffers(&ring, iovecs, IOVECS_LEN);
42
42
  if (ret) {
@@ -0,0 +1,118 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test fsnotify access off O_DIRECT read
4
+ */
5
+
6
+ #include "helpers.h"
7
+
8
+ #ifdef CONFIG_HAVE_FANOTIFY
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+ #include <unistd.h>
12
+ #include <fcntl.h>
13
+ #include <sys/fanotify.h>
14
+ #include <sys/stat.h>
15
+ #include <sys/wait.h>
16
+
17
+ #include "liburing.h"
18
+
19
+ int main(int argc, char *argv[])
20
+ {
21
+ struct io_uring_sqe *sqe;
22
+ struct io_uring_cqe *cqe;
23
+ struct io_uring ring;
24
+ int fan, ret, fd, err;
25
+ char fname[64], *f;
26
+ struct stat sb;
27
+ void *buf;
28
+
29
+ fan = fanotify_init(FAN_CLASS_NOTIF|FAN_CLASS_CONTENT, 0);
30
+ if (fan < 0) {
31
+ if (errno == ENOSYS)
32
+ return T_EXIT_SKIP;
33
+ if (geteuid())
34
+ return T_EXIT_SKIP;
35
+ perror("fanotify_init");
36
+ return T_EXIT_FAIL;
37
+ }
38
+
39
+ err = T_EXIT_FAIL;
40
+ if (argc > 1) {
41
+ f = argv[1];
42
+ fd = open(argv[1], O_RDONLY | O_DIRECT);
43
+ if (fd < 0 && errno == EINVAL)
44
+ return T_EXIT_SKIP;
45
+ } else {
46
+ sprintf(fname, ".fsnotify.%d", getpid());
47
+ f = fname;
48
+ t_create_file(fname, 8192);
49
+ fd = open(fname, O_RDONLY | O_DIRECT);
50
+ if (fd < 0 && errno == EINVAL) {
51
+ unlink(fname);
52
+ return T_EXIT_SKIP;
53
+ }
54
+ }
55
+ if (fd < 0) {
56
+ perror("open");
57
+ goto out;
58
+ }
59
+
60
+ if (fstat(fd, &sb) < 0) {
61
+ perror("fstat");
62
+ goto out;
63
+ }
64
+ if ((sb.st_mode & S_IFMT) != S_IFREG) {
65
+ err = T_EXIT_SKIP;
66
+ close(fd);
67
+ goto out;
68
+ }
69
+
70
+ ret = fanotify_mark(fan, FAN_MARK_ADD, FAN_ACCESS|FAN_MODIFY, fd, NULL);
71
+ if (ret < 0) {
72
+ perror("fanotify_mark");
73
+ goto out;
74
+ }
75
+
76
+ if (fork()) {
77
+ int wstat;
78
+
79
+ io_uring_queue_init(1, &ring, 0);
80
+ if (posix_memalign(&buf, 4096, 4096))
81
+ goto out;
82
+ sqe = io_uring_get_sqe(&ring);
83
+ io_uring_prep_read(sqe, fd, buf, 4096, 0);
84
+ io_uring_submit(&ring);
85
+ ret = io_uring_wait_cqe(&ring, &cqe);
86
+ if (ret) {
87
+ fprintf(stderr, "wait_ret=%d\n", ret);
88
+ goto out;
89
+ }
90
+ wait(&wstat);
91
+ if (!WEXITSTATUS(wstat))
92
+ err = T_EXIT_PASS;
93
+ } else {
94
+ struct fanotify_event_metadata m;
95
+ int fret;
96
+
97
+ fret = read(fan, &m, sizeof(m));
98
+ if (fret < 0)
99
+ perror("fanotify read");
100
+ /* fail if mask isn't right or pid indicates non-task context */
101
+ else if (!(m.mask & 1) || !m.pid)
102
+ exit(1);
103
+ exit(0);
104
+ }
105
+
106
+ out:
107
+ if (f == fname)
108
+ unlink(fname);
109
+ return err;
110
+ }
111
+
112
+ #else /* #ifdef CONFIG_HAVE_FANOTIFY */
113
+
114
+ int main(void)
115
+ {
116
+ return T_EXIT_SKIP;
117
+ }
118
+ #endif /* #ifdef CONFIG_HAVE_FANOTIFY */
@@ -44,7 +44,7 @@ err:
44
44
  return 1;
45
45
  }
46
46
 
47
- int files_linked_ok(const char* fn1, const char *fn2)
47
+ static int files_linked_ok(const char* fn1, const char *fn2)
48
48
  {
49
49
  struct stat s1, s2;
50
50
 
@@ -8,6 +8,7 @@
8
8
  #include <stdio.h>
9
9
  #include <fcntl.h>
10
10
  #include <unistd.h>
11
+ #include <stdarg.h>
11
12
  #include <sys/types.h>
12
13
 
13
14
  #include <arpa/inet.h>
@@ -134,7 +135,8 @@ enum t_setup_ret t_create_ring_params(int depth, struct io_uring *ring,
134
135
  return T_SETUP_SKIP;
135
136
  }
136
137
 
137
- fprintf(stderr, "queue_init: %s\n", strerror(-ret));
138
+ if (ret != -EINVAL)
139
+ fprintf(stderr, "queue_init: %s\n", strerror(-ret));
138
140
  return ret;
139
141
  }
140
142
 
@@ -173,7 +175,7 @@ int t_create_socket_pair(int fd[2], bool stream)
173
175
  int val;
174
176
  struct sockaddr_in serv_addr;
175
177
  struct sockaddr *paddr;
176
- size_t paddrlen;
178
+ socklen_t paddrlen;
177
179
 
178
180
  type |= SOCK_CLOEXEC;
179
181
  fd[0] = socket(AF_INET, type, 0);
@@ -266,3 +268,53 @@ bool t_probe_defer_taskrun(void)
266
268
  io_uring_queue_exit(&ring);
267
269
  return true;
268
270
  }
271
+
272
+ /*
273
+ * Sync internal state with kernel ring state on the SQ side. Returns the
274
+ * number of pending items in the SQ ring, for the shared ring.
275
+ */
276
+ unsigned __io_uring_flush_sq(struct io_uring *ring)
277
+ {
278
+ struct io_uring_sq *sq = &ring->sq;
279
+ unsigned tail = sq->sqe_tail;
280
+
281
+ if (sq->sqe_head != tail) {
282
+ sq->sqe_head = tail;
283
+ /*
284
+ * Ensure kernel sees the SQE updates before the tail update.
285
+ */
286
+ if (!(ring->flags & IORING_SETUP_SQPOLL))
287
+ IO_URING_WRITE_ONCE(*sq->ktail, tail);
288
+ else
289
+ io_uring_smp_store_release(sq->ktail, tail);
290
+ }
291
+ /*
292
+ * This _may_ look problematic, as we're not supposed to be reading
293
+ * SQ->head without acquire semantics. When we're in SQPOLL mode, the
294
+ * kernel submitter could be updating this right now. For non-SQPOLL,
295
+ * task itself does it, and there's no potential race. But even for
296
+ * SQPOLL, the load is going to be potentially out-of-date the very
297
+ * instant it's done, regardless or whether or not it's done
298
+ * atomically. Worst case, we're going to be over-estimating what
299
+ * we can submit. The point is, we need to be able to deal with this
300
+ * situation regardless of any perceived atomicity.
301
+ */
302
+ return tail - *sq->khead;
303
+ }
304
+
305
+ /*
306
+ * Implementation of error(3), prints an error message and exits.
307
+ */
308
+ void t_error(int status, int errnum, const char *format, ...)
309
+ {
310
+ va_list args;
311
+ va_start(args, format);
312
+
313
+ vfprintf(stderr, format, args);
314
+ if (errnum)
315
+ fprintf(stderr, ": %s", strerror(errnum));
316
+
317
+ fprintf(stderr, "\n");
318
+ va_end(args);
319
+ exit(status);
320
+ }
@@ -85,8 +85,12 @@ enum t_setup_ret t_register_buffers(struct io_uring *ring,
85
85
 
86
86
  bool t_probe_defer_taskrun(void);
87
87
 
88
+ unsigned __io_uring_flush_sq(struct io_uring *ring);
89
+
88
90
  #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
89
91
 
92
+ void t_error(int status, int errnum, const char *format, ...);
93
+
90
94
  #ifdef __cplusplus
91
95
  }
92
96
  #endif
@@ -161,6 +161,8 @@ static int test_io_cancel(const char *file, int do_write, int do_partial,
161
161
 
162
162
  fd = open(file, O_RDWR | O_DIRECT);
163
163
  if (fd < 0) {
164
+ if (errno == EINVAL)
165
+ return T_EXIT_SKIP;
164
166
  perror("file open");
165
167
  goto err;
166
168
  }
@@ -540,7 +542,7 @@ int main(int argc, char *argv[])
540
542
  int async = (i & 4) != 0;
541
543
 
542
544
  ret = test_io_cancel(fname, write, partial, async);
543
- if (ret) {
545
+ if (ret == T_EXIT_FAIL) {
544
546
  fprintf(stderr, "test_io_cancel %d %d %d failed\n",
545
547
  write, partial, async);
546
548
  goto err;
@@ -18,6 +18,7 @@
18
18
  #define BUFFERS (FILE_SIZE / BS)
19
19
 
20
20
  static struct iovec *vecs;
21
+ static int no_pt;
21
22
 
22
23
  /*
23
24
  * Each offset in the file has the ((test_case / 2) * FILE_SIZE)
@@ -34,7 +35,8 @@ static int verify_buf(int tc, void *buf, off_t off)
34
35
  ptr = buf;
35
36
  for (i = 0; i < u_in_buf; i++) {
36
37
  if (off != *ptr) {
37
- fprintf(stderr, "Found %u, wanted %lu\n", *ptr, off);
38
+ fprintf(stderr, "Found %u, wanted %llu\n", *ptr,
39
+ (unsigned long long) off);
38
40
  return 1;
39
41
  }
40
42
  ptr++;
@@ -205,6 +207,10 @@ static int __test_io(const char *file, struct io_uring *ring, int tc, int read,
205
207
  goto err;
206
208
  }
207
209
  if (cqe->res != 0) {
210
+ if (!no_pt) {
211
+ no_pt = 1;
212
+ goto skip;
213
+ }
208
214
  fprintf(stderr, "cqe res %d, wanted 0\n", cqe->res);
209
215
  goto err;
210
216
  }
@@ -234,6 +240,7 @@ static int __test_io(const char *file, struct io_uring *ring, int tc, int read,
234
240
  }
235
241
  }
236
242
 
243
+ skip:
237
244
  close(fd);
238
245
  return 0;
239
246
  err:
@@ -258,6 +265,10 @@ static int test_io(const char *file, int tc, int read, int sqthread,
258
265
  if (ret == T_SETUP_SKIP)
259
266
  return 0;
260
267
  if (ret != T_SETUP_OK) {
268
+ if (ret == -EINVAL) {
269
+ no_pt = 1;
270
+ return T_SETUP_SKIP;
271
+ }
261
272
  fprintf(stderr, "ring create failed: %d\n", ret);
262
273
  return 1;
263
274
  }
@@ -268,8 +279,6 @@ static int test_io(const char *file, int tc, int read, int sqthread,
268
279
  return ret;
269
280
  }
270
281
 
271
- extern unsigned __io_uring_flush_sq(struct io_uring *ring);
272
-
273
282
  /*
274
283
  * Send a passthrough command that nvme will fail during submission.
275
284
  * This comes handy for testing error handling.
@@ -282,8 +291,7 @@ static int test_invalid_passthru_submit(const char *file)
282
291
  struct io_uring_sqe *sqe;
283
292
  struct nvme_uring_cmd *cmd;
284
293
 
285
- ring_flags = IORING_SETUP_IOPOLL | IORING_SETUP_SQE128;
286
- ring_flags |= IORING_SETUP_CQE32;
294
+ ring_flags = IORING_SETUP_CQE32 | IORING_SETUP_SQE128;
287
295
 
288
296
  ret = t_create_ring(1, &ring, ring_flags);
289
297
  if (ret != T_SETUP_OK) {
@@ -346,6 +354,8 @@ static int test_io_uring_submit_enters(const char *file)
346
354
  int fd, i, ret, ring_flags, open_flags;
347
355
  unsigned head;
348
356
  struct io_uring_cqe *cqe;
357
+ struct nvme_uring_cmd *cmd;
358
+ struct io_uring_sqe *sqe;
349
359
 
350
360
  ring_flags = IORING_SETUP_IOPOLL;
351
361
  ring_flags |= IORING_SETUP_SQE128;
@@ -365,12 +375,28 @@ static int test_io_uring_submit_enters(const char *file)
365
375
  }
366
376
 
367
377
  for (i = 0; i < BUFFERS; i++) {
368
- struct io_uring_sqe *sqe;
369
378
  off_t offset = BS * (rand() % BUFFERS);
379
+ __u64 slba;
380
+ __u32 nlb;
370
381
 
371
382
  sqe = io_uring_get_sqe(&ring);
372
- io_uring_prep_writev(sqe, fd, &vecs[i], 1, offset);
373
- sqe->user_data = 1;
383
+ io_uring_prep_readv(sqe, fd, &vecs[i], 1, offset);
384
+ sqe->user_data = i;
385
+ sqe->opcode = IORING_OP_URING_CMD;
386
+ sqe->cmd_op = NVME_URING_CMD_IO;
387
+ cmd = (struct nvme_uring_cmd *)sqe->cmd;
388
+ memset(cmd, 0, sizeof(struct nvme_uring_cmd));
389
+
390
+ slba = offset >> lba_shift;
391
+ nlb = (BS >> lba_shift) - 1;
392
+
393
+ cmd->opcode = nvme_cmd_read;
394
+ cmd->cdw10 = slba & 0xffffffff;
395
+ cmd->cdw11 = slba >> 32;
396
+ cmd->cdw12 = nlb;
397
+ cmd->addr = (__u64)(uintptr_t)&vecs[i];
398
+ cmd->data_len = 1;
399
+ cmd->nsid = nsid;
374
400
  }
375
401
 
376
402
  /* submit manually to avoid adding IORING_ENTER_GETEVENTS */
@@ -426,6 +452,8 @@ int main(int argc, char *argv[])
426
452
  int nonvec = (i & 8) != 0;
427
453
 
428
454
  ret = test_io(fname, i, read, sqthread, fixed, nonvec);
455
+ if (no_pt)
456
+ break;
429
457
  if (ret) {
430
458
  fprintf(stderr, "test_io failed %d/%d/%d/%d\n",
431
459
  read, sqthread, fixed, nonvec);
@@ -433,6 +461,9 @@ int main(int argc, char *argv[])
433
461
  }
434
462
  }
435
463
 
464
+ if (no_pt)
465
+ return T_EXIT_SKIP;
466
+
436
467
  ret = test_io_uring_submit_enters(fname);
437
468
  if (ret) {
438
469
  fprintf(stderr, "test_io_uring_submit_enters failed\n");
@@ -19,86 +19,10 @@
19
19
 
20
20
  #include "../syscall.h"
21
21
 
22
- char *features_string(struct io_uring_params *p)
23
- {
24
- static char flagstr[64];
25
-
26
- if (!p || !p->features)
27
- return "none";
28
-
29
- if (p->features & ~IORING_FEAT_SINGLE_MMAP) {
30
- snprintf(flagstr, 64, "0x%.8x", p->features);
31
- return flagstr;
32
- }
33
-
34
- if (p->features & IORING_FEAT_SINGLE_MMAP)
35
- strncat(flagstr, "IORING_FEAT_SINGLE_MMAP", 64 - strlen(flagstr));
36
-
37
- return flagstr;
38
- }
39
-
40
- /*
41
- * Attempt the call with the given args. Return 0 when expect matches
42
- * the return value of the system call, 1 otherwise.
43
- */
44
- char *
45
- flags_string(struct io_uring_params *p)
46
- {
47
- static char flagstr[64];
48
- int add_pipe = 0;
49
-
50
- memset(flagstr, 0, sizeof(flagstr));
51
-
52
- if (!p || p->flags == 0)
53
- return "none";
54
-
55
- /*
56
- * If unsupported flags are present, just print the bitmask.
57
- */
58
- if (p->flags & ~(IORING_SETUP_IOPOLL | IORING_SETUP_SQPOLL |
59
- IORING_SETUP_SQ_AFF)) {
60
- snprintf(flagstr, 64, "0x%.8x", p->flags);
61
- return flagstr;
62
- }
63
-
64
- if (p->flags & IORING_SETUP_IOPOLL) {
65
- strncat(flagstr, "IORING_SETUP_IOPOLL", 64 - strlen(flagstr));
66
- add_pipe = 1;
67
- }
68
- if (p->flags & IORING_SETUP_SQPOLL) {
69
- if (add_pipe)
70
- strncat(flagstr, "|", 64 - strlen(flagstr));
71
- else
72
- add_pipe = 1;
73
- strncat(flagstr, "IORING_SETUP_SQPOLL", 64 - strlen(flagstr));
74
- }
75
- if (p->flags & IORING_SETUP_SQ_AFF) {
76
- if (add_pipe)
77
- strncat(flagstr, "|", 64 - strlen(flagstr));
78
- strncat(flagstr, "IORING_SETUP_SQ_AFF", 64 - strlen(flagstr));
79
- }
80
-
81
- return flagstr;
82
- }
83
-
84
- char *
85
- dump_resv(struct io_uring_params *p)
86
- {
87
- static char resvstr[4096];
88
-
89
- if (!p)
90
- return "";
91
-
92
- sprintf(resvstr, "0x%.8x 0x%.8x 0x%.8x", p->resv[0],
93
- p->resv[1], p->resv[2]);
94
-
95
- return resvstr;
96
- }
97
-
98
22
  /* bogus: setup returns a valid fd on success... expect can't predict the
99
23
  fd we'll get, so this really only takes 1 parameter: error */
100
- int
101
- try_io_uring_setup(unsigned entries, struct io_uring_params *p, int expect)
24
+ static int try_io_uring_setup(unsigned entries, struct io_uring_params *p,
25
+ int expect)
102
26
  {
103
27
  int ret;
104
28
 
@@ -123,8 +47,7 @@ try_io_uring_setup(unsigned entries, struct io_uring_params *p, int expect)
123
47
  return 0;
124
48
  }
125
49
 
126
- int
127
- main(int argc, char **argv)
50
+ int main(int argc, char **argv)
128
51
  {
129
52
  int fd;
130
53
  unsigned int status = 0;
@@ -0,0 +1,118 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: IOPOLL with overflow test case
4
+ */
5
+ #include <errno.h>
6
+ #include <stdio.h>
7
+ #include <unistd.h>
8
+ #include <stdlib.h>
9
+ #include <string.h>
10
+ #include <fcntl.h>
11
+ #include <sys/types.h>
12
+ #include <poll.h>
13
+ #include <sys/eventfd.h>
14
+ #include <sys/resource.h>
15
+ #include "helpers.h"
16
+ #include "liburing.h"
17
+ #include "../src/syscall.h"
18
+
19
+ #define FILE_SIZE (128 * 1024)
20
+ #define BS 4096
21
+ #define BUFFERS (FILE_SIZE / BS)
22
+
23
+ static struct iovec *vecs;
24
+
25
+ static int test(struct io_uring *ring, int fd)
26
+ {
27
+ struct io_uring_sqe *sqe;
28
+ int i, j, ret;
29
+ loff_t off;
30
+
31
+ off = FILE_SIZE - BS;
32
+ for (j = 0; j < 8; j++) {
33
+ for (i = 0; i < BUFFERS; i++) {
34
+ sqe = io_uring_get_sqe(ring);
35
+ io_uring_prep_read(sqe, fd, vecs[i].iov_base,
36
+ vecs[i].iov_len, off);
37
+ if (!off)
38
+ off = FILE_SIZE - BS;
39
+ else
40
+ off -= BS;
41
+ }
42
+ ret = io_uring_submit(ring);
43
+ if (ret != BUFFERS) {
44
+ fprintf(stderr, "submitted %d\n", ret);
45
+ return T_EXIT_FAIL;
46
+ }
47
+ }
48
+
49
+ sleep(1);
50
+
51
+ ret = __sys_io_uring_enter(ring->ring_fd, 0, BUFFERS * 8,
52
+ IORING_ENTER_GETEVENTS, NULL);
53
+
54
+ for (i = 0; i < BUFFERS * 8; i++) {
55
+ struct io_uring_cqe *cqe;
56
+
57
+ ret = io_uring_wait_cqe(ring, &cqe);
58
+ if (ret) {
59
+ fprintf(stderr, "wait=%d\n", ret);
60
+ return T_EXIT_FAIL;
61
+ }
62
+ io_uring_cqe_seen(ring, cqe);
63
+ }
64
+
65
+ return T_EXIT_PASS;
66
+ }
67
+
68
+ int main(int argc, char *argv[])
69
+ {
70
+ struct io_uring_params p = { };
71
+ struct io_uring ring;
72
+ char buf[256];
73
+ char *fname;
74
+ int ret, fd;
75
+
76
+ p.flags = IORING_SETUP_IOPOLL | IORING_SETUP_CQSIZE;
77
+ p.cq_entries = 64;
78
+ ret = t_create_ring_params(64, &ring, &p);
79
+ if (ret == T_SETUP_SKIP)
80
+ return 0;
81
+ if (ret != T_SETUP_OK) {
82
+ fprintf(stderr, "ring create failed: %d\n", ret);
83
+ return 1;
84
+ }
85
+
86
+ if (argc > 1) {
87
+ fname = argv[1];
88
+ } else {
89
+ srand((unsigned)time(NULL));
90
+ snprintf(buf, sizeof(buf), ".basic-rw-%u-%u",
91
+ (unsigned)rand(), (unsigned)getpid());
92
+ fname = buf;
93
+ t_create_file(fname, FILE_SIZE);
94
+ }
95
+
96
+ fd = open(fname, O_RDONLY | O_DIRECT);
97
+ if (fd < 0) {
98
+ if (errno == EINVAL) {
99
+ if (fname != argv[1])
100
+ unlink(fname);
101
+ return T_EXIT_SKIP;
102
+ }
103
+ perror("open");
104
+ goto err;
105
+ }
106
+
107
+ vecs = t_create_buffers(BUFFERS, BS);
108
+
109
+ ret = test(&ring, fd);
110
+
111
+ if (fname != argv[1])
112
+ unlink(fname);
113
+ return ret;
114
+ err:
115
+ if (fname != argv[1])
116
+ unlink(fname);
117
+ return T_EXIT_FAIL;
118
+ }