uringmachine 0.3 → 0.5

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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -1
  3. data/CHANGELOG.md +23 -0
  4. data/README.md +128 -0
  5. data/TODO.md +14 -0
  6. data/examples/bm_snooze.rb +89 -0
  7. data/examples/bm_write.rb +56 -0
  8. data/examples/dns_client.rb +12 -0
  9. data/examples/echo_server.rb +18 -40
  10. data/examples/http_server.rb +42 -43
  11. data/examples/inout.rb +19 -0
  12. data/examples/nc.rb +36 -0
  13. data/examples/server_client.rb +64 -0
  14. data/examples/snooze.rb +44 -0
  15. data/examples/write_dev_null.rb +16 -0
  16. data/ext/um/extconf.rb +24 -23
  17. data/ext/um/um.c +524 -278
  18. data/ext/um/um.h +146 -44
  19. data/ext/um/um_buffer.c +49 -0
  20. data/ext/um/um_class.c +217 -106
  21. data/ext/um/um_const.c +213 -0
  22. data/ext/um/um_ext.c +4 -0
  23. data/ext/um/um_mutex_class.c +47 -0
  24. data/ext/um/um_op.c +86 -114
  25. data/ext/um/um_queue_class.c +58 -0
  26. data/ext/um/um_sync.c +273 -0
  27. data/ext/um/um_utils.c +49 -4
  28. data/lib/uringmachine/dns_resolver.rb +84 -0
  29. data/lib/uringmachine/version.rb +1 -1
  30. data/lib/uringmachine.rb +28 -0
  31. data/supressions/ruby.supp +71 -0
  32. data/test/helper.rb +8 -0
  33. data/test/test_um.rb +685 -46
  34. data/vendor/liburing/.github/workflows/build.yml +29 -1
  35. data/vendor/liburing/.gitignore +6 -0
  36. data/vendor/liburing/CHANGELOG +16 -0
  37. data/vendor/liburing/CONTRIBUTING.md +165 -0
  38. data/vendor/liburing/configure +64 -0
  39. data/vendor/liburing/examples/Makefile +9 -1
  40. data/vendor/liburing/examples/kdigest.c +405 -0
  41. data/vendor/liburing/examples/proxy.c +75 -8
  42. data/vendor/liburing/examples/reg-wait.c +159 -0
  43. data/vendor/liburing/liburing.pc.in +1 -1
  44. data/vendor/liburing/liburing.spec +1 -1
  45. data/vendor/liburing/src/Makefile +16 -2
  46. data/vendor/liburing/src/include/liburing/io_uring.h +77 -0
  47. data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
  48. data/vendor/liburing/src/include/liburing.h +59 -6
  49. data/vendor/liburing/src/int_flags.h +10 -3
  50. data/vendor/liburing/src/liburing-ffi.map +16 -0
  51. data/vendor/liburing/src/liburing.map +10 -0
  52. data/vendor/liburing/src/queue.c +28 -16
  53. data/vendor/liburing/src/register.c +106 -1
  54. data/vendor/liburing/src/sanitize.c +176 -0
  55. data/vendor/liburing/src/setup.c +47 -19
  56. data/vendor/liburing/src/setup.h +6 -0
  57. data/vendor/liburing/test/35fa71a030ca.c +7 -0
  58. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  59. data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
  60. data/vendor/liburing/test/917257daa0fe.c +7 -0
  61. data/vendor/liburing/test/Makefile +38 -4
  62. data/vendor/liburing/test/a0908ae19763.c +7 -0
  63. data/vendor/liburing/test/a4c0b3decb33.c +7 -0
  64. data/vendor/liburing/test/accept.c +14 -4
  65. data/vendor/liburing/test/b19062a56726.c +7 -0
  66. data/vendor/liburing/test/bind-listen.c +2 -2
  67. data/vendor/liburing/test/buf-ring-nommap.c +10 -3
  68. data/vendor/liburing/test/buf-ring.c +2 -0
  69. data/vendor/liburing/test/cmd-discard.c +427 -0
  70. data/vendor/liburing/test/coredump.c +7 -0
  71. data/vendor/liburing/test/cq-overflow.c +13 -1
  72. data/vendor/liburing/test/d4ae271dfaae.c +11 -3
  73. data/vendor/liburing/test/defer-taskrun.c +2 -2
  74. data/vendor/liburing/test/defer-tw-timeout.c +4 -1
  75. data/vendor/liburing/test/defer.c +2 -2
  76. data/vendor/liburing/test/double-poll-crash.c +1 -1
  77. data/vendor/liburing/test/eeed8b54e0df.c +2 -0
  78. data/vendor/liburing/test/eventfd.c +0 -1
  79. data/vendor/liburing/test/exit-no-cleanup.c +11 -0
  80. data/vendor/liburing/test/fadvise.c +9 -26
  81. data/vendor/liburing/test/fdinfo.c +9 -1
  82. data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
  83. data/vendor/liburing/test/file-exit-unreg.c +48 -0
  84. data/vendor/liburing/test/file-register.c +14 -2
  85. data/vendor/liburing/test/file-update.c +1 -1
  86. data/vendor/liburing/test/file-verify.c +27 -16
  87. data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
  88. data/vendor/liburing/test/fixed-buf-iter.c +3 -1
  89. data/vendor/liburing/test/fixed-hugepage.c +12 -1
  90. data/vendor/liburing/test/fsnotify.c +1 -0
  91. data/vendor/liburing/test/futex.c +16 -4
  92. data/vendor/liburing/test/helpers.c +47 -0
  93. data/vendor/liburing/test/helpers.h +6 -0
  94. data/vendor/liburing/test/init-mem.c +5 -3
  95. data/vendor/liburing/test/io-cancel.c +0 -24
  96. data/vendor/liburing/test/io_uring_passthrough.c +4 -0
  97. data/vendor/liburing/test/io_uring_register.c +38 -8
  98. data/vendor/liburing/test/iopoll-leak.c +4 -0
  99. data/vendor/liburing/test/iopoll-overflow.c +1 -1
  100. data/vendor/liburing/test/iopoll.c +3 -3
  101. data/vendor/liburing/test/kallsyms.c +203 -0
  102. data/vendor/liburing/test/link-timeout.c +159 -0
  103. data/vendor/liburing/test/linked-defer-close.c +224 -0
  104. data/vendor/liburing/test/madvise.c +12 -25
  105. data/vendor/liburing/test/min-timeout-wait.c +0 -25
  106. data/vendor/liburing/test/min-timeout.c +0 -25
  107. data/vendor/liburing/test/mkdir.c +6 -0
  108. data/vendor/liburing/test/msg-ring.c +8 -2
  109. data/vendor/liburing/test/napi-test.c +16 -3
  110. data/vendor/liburing/test/no-mmap-inval.c +3 -1
  111. data/vendor/liburing/test/nop.c +44 -0
  112. data/vendor/liburing/test/ooo-file-unreg.c +1 -1
  113. data/vendor/liburing/test/open-close.c +40 -0
  114. data/vendor/liburing/test/openat2.c +37 -14
  115. data/vendor/liburing/test/poll-many.c +13 -7
  116. data/vendor/liburing/test/poll-mshot-update.c +17 -10
  117. data/vendor/liburing/test/poll-v-poll.c +6 -3
  118. data/vendor/liburing/test/pollfree.c +148 -0
  119. data/vendor/liburing/test/read-mshot-empty.c +158 -153
  120. data/vendor/liburing/test/read-mshot-stdin.c +121 -0
  121. data/vendor/liburing/test/read-mshot.c +282 -27
  122. data/vendor/liburing/test/read-write.c +78 -13
  123. data/vendor/liburing/test/recv-msgall-stream.c +3 -0
  124. data/vendor/liburing/test/recv-msgall.c +5 -0
  125. data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
  126. data/vendor/liburing/test/recvsend_bundle.c +94 -31
  127. data/vendor/liburing/test/reg-fd-only.c +15 -5
  128. data/vendor/liburing/test/reg-wait.c +251 -0
  129. data/vendor/liburing/test/regbuf-clone.c +645 -0
  130. data/vendor/liburing/test/regbuf-merge.c +7 -0
  131. data/vendor/liburing/test/register-restrictions.c +86 -85
  132. data/vendor/liburing/test/rename.c +59 -1
  133. data/vendor/liburing/test/resize-rings.c +643 -0
  134. data/vendor/liburing/test/ringbuf-read.c +5 -0
  135. data/vendor/liburing/test/ringbuf-status.c +5 -1
  136. data/vendor/liburing/test/rsrc_tags.c +1 -1
  137. data/vendor/liburing/test/runtests.sh +16 -1
  138. data/vendor/liburing/test/send-zerocopy.c +59 -0
  139. data/vendor/liburing/test/short-read.c +1 -0
  140. data/vendor/liburing/test/socket.c +43 -0
  141. data/vendor/liburing/test/splice.c +3 -1
  142. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  143. data/vendor/liburing/test/sq-poll-share.c +2 -0
  144. data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
  145. data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
  146. data/vendor/liburing/test/sqpoll-sleep.c +40 -33
  147. data/vendor/liburing/test/sqwait.c +136 -0
  148. data/vendor/liburing/test/statx.c +89 -0
  149. data/vendor/liburing/test/stdout.c +2 -0
  150. data/vendor/liburing/test/submit-and-wait.c +1 -25
  151. data/vendor/liburing/test/submit-reuse.c +4 -26
  152. data/vendor/liburing/test/symlink.c +12 -1
  153. data/vendor/liburing/test/sync-cancel.c +56 -22
  154. data/vendor/liburing/test/thread-exit.c +5 -0
  155. data/vendor/liburing/test/timeout-new.c +1 -26
  156. data/vendor/liburing/test/timeout.c +25 -34
  157. data/vendor/liburing/test/unlink.c +94 -1
  158. data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
  159. data/vendor/liburing/test/waitid.c +62 -8
  160. data/vendor/liburing/test/wq-aff.c +35 -0
  161. data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
  162. data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
  163. metadata +37 -6
  164. data/examples/event_loop.rb +0 -69
  165. data/examples/fibers.rb +0 -105
  166. data/examples/http_server_multishot.rb +0 -57
  167. data/examples/http_server_simpler.rb +0 -34
@@ -95,6 +95,8 @@ static int __test_io(const char *file, struct io_uring *ring, int tc, int read,
95
95
 
96
96
  fd = open(file, open_flags);
97
97
  if (fd < 0) {
98
+ if (errno == EACCES || errno == EPERM)
99
+ return T_EXIT_SKIP;
98
100
  perror("file open");
99
101
  goto err;
100
102
  }
@@ -165,6 +167,8 @@ static int __test_io(const char *file, struct io_uring *ring, int tc, int read,
165
167
  }
166
168
  }
167
169
  sqe->opcode = IORING_OP_URING_CMD;
170
+ if (do_fixed)
171
+ sqe->uring_cmd_flags |= IORING_URING_CMD_FIXED;
168
172
  sqe->user_data = ((uint64_t)offset << 32) | i;
169
173
  if (sqthread)
170
174
  sqe->flags |= IOSQE_FIXED_FILE;
@@ -21,6 +21,7 @@
21
21
  #include <linux/mman.h>
22
22
  #include <sys/time.h>
23
23
  #include <sys/resource.h>
24
+ #include <sys/vfs.h>
24
25
  #include <limits.h>
25
26
 
26
27
  #include "helpers.h"
@@ -76,8 +77,13 @@ static int new_io_uring(int entries, struct io_uring_params *p)
76
77
 
77
78
  #define MAXFDS (UINT_MAX * sizeof(int))
78
79
 
80
+ #define OFS_MAGIC 0x794c7630
81
+ #define TMPFS_MAGIC 0x01021994
82
+ #define RAMFS_MAGIC 0x858458f6
83
+
79
84
  static void *map_filebacked(size_t size)
80
85
  {
86
+ struct statfs buf;
81
87
  int fd, ret;
82
88
  void *addr;
83
89
  char template[32] = "io_uring_register-test-XXXXXXXX";
@@ -87,8 +93,21 @@ static void *map_filebacked(size_t size)
87
93
  perror("mkstemp");
88
94
  return NULL;
89
95
  }
96
+ if (statfs(template, &buf) < 0) {
97
+ perror("statfs");
98
+ unlink(template);
99
+ close(fd);
100
+ return NULL;
101
+ }
90
102
  unlink(template);
91
103
 
104
+ /* virtual file systems may not present as file mapped */
105
+ if (buf.f_type == OFS_MAGIC || buf.f_type == RAMFS_MAGIC ||
106
+ buf.f_type == TMPFS_MAGIC) {
107
+ close(fd);
108
+ return NULL;
109
+ }
110
+
92
111
  ret = ftruncate(fd, size);
93
112
  if (ret < 0) {
94
113
  perror("ftruncate");
@@ -365,12 +384,12 @@ static int test_iovec_size(int fd)
365
384
 
366
385
  /* file-backed buffers -- not supported */
367
386
  buf = map_filebacked(2*1024*1024);
368
- if (!buf)
369
- status = 1;
370
- iov.iov_base = buf;
371
- iov.iov_len = 2*1024*1024;
372
- status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT, -EOPNOTSUPP);
373
- munmap(buf, 2*1024*1024);
387
+ if (buf) {
388
+ iov.iov_base = buf;
389
+ iov.iov_len = 2*1024*1024;
390
+ status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT, -EOPNOTSUPP);
391
+ munmap(buf, 2*1024*1024);
392
+ }
374
393
 
375
394
  /* bump up against the soft limit and make sure we get EFAULT
376
395
  * or whatever we're supposed to get. NOTE: this requires
@@ -417,14 +436,14 @@ static int ioring_poll(struct io_uring *ring, int fd, int fixed)
417
436
  return ret;
418
437
  }
419
438
 
420
- static int test_poll_ringfd(void)
439
+ static int __test_poll_ringfd(int ring_flags)
421
440
  {
422
441
  int status = 0;
423
442
  int ret;
424
443
  int fd;
425
444
  struct io_uring ring;
426
445
 
427
- ret = io_uring_queue_init(1, &ring, 0);
446
+ ret = io_uring_queue_init(2, &ring, ring_flags);
428
447
  if (ret) {
429
448
  perror("io_uring_queue_init");
430
449
  return 1;
@@ -447,6 +466,17 @@ static int test_poll_ringfd(void)
447
466
  return status;
448
467
  }
449
468
 
469
+ static int test_poll_ringfd(void)
470
+ {
471
+ int ret;
472
+
473
+ ret = __test_poll_ringfd(0);
474
+ if (ret)
475
+ return ret;
476
+
477
+ return __test_poll_ringfd(IORING_SETUP_SQPOLL);
478
+ }
479
+
450
480
  int main(int argc, char **argv)
451
481
  {
452
482
  int fd, ret;
@@ -26,6 +26,8 @@ static int do_iopoll(const char *fname)
26
26
 
27
27
  fd = open(fname, O_RDONLY | O_DIRECT);
28
28
  if (fd < 0) {
29
+ if (errno == EINVAL || errno == EPERM || errno == EACCES)
30
+ return T_EXIT_SKIP;
29
31
  perror("open");
30
32
  return T_EXIT_SKIP;
31
33
  }
@@ -39,6 +41,8 @@ static int do_iopoll(const char *fname)
39
41
  io_uring_submit(&ring);
40
42
 
41
43
  close(fd);
44
+ free(iov->iov_base);
45
+ free(iov);
42
46
  return T_EXIT_PASS;
43
47
  }
44
48
 
@@ -95,7 +95,7 @@ int main(int argc, char *argv[])
95
95
 
96
96
  fd = open(fname, O_RDONLY | O_DIRECT);
97
97
  if (fd < 0) {
98
- if (errno == EINVAL) {
98
+ if (errno == EINVAL || errno == EACCES || errno == EPERM) {
99
99
  if (fname != argv[1])
100
100
  unlink(fname);
101
101
  return T_EXIT_SKIP;
@@ -87,7 +87,7 @@ static int __test_io(const char *file, struct io_uring *ring, int write, int sqt
87
87
  }
88
88
  fd = open(file, open_flags);
89
89
  if (fd < 0) {
90
- if (errno == EINVAL)
90
+ if (errno == EINVAL || errno == EPERM || errno == EACCES)
91
91
  return 0;
92
92
  perror("file open");
93
93
  goto err;
@@ -230,7 +230,7 @@ static int test_io_uring_cqe_peek(const char *file)
230
230
 
231
231
  fd = open(file, O_RDONLY | O_DIRECT);
232
232
  if (fd < 0) {
233
- if (errno == EINVAL) {
233
+ if (errno == EINVAL || errno == EPERM || errno == EACCES) {
234
234
  io_uring_queue_exit(&ring);
235
235
  return T_EXIT_SKIP;
236
236
  }
@@ -302,7 +302,7 @@ static int test_io_uring_submit_enters(const char *file)
302
302
  open_flags = O_WRONLY | O_DIRECT;
303
303
  fd = open(file, open_flags);
304
304
  if (fd < 0) {
305
- if (errno == EINVAL)
305
+ if (errno == EINVAL || errno == EPERM || errno == EACCES)
306
306
  return T_EXIT_SKIP;
307
307
  perror("file open");
308
308
  goto err;
@@ -0,0 +1,203 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: read /proc/kallsyms. Mostly just here so that fops->read() can
4
+ * get exercised, with and without registered buffers
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 <sys/types.h>
13
+ #include <poll.h>
14
+ #include <sys/eventfd.h>
15
+ #include <sys/resource.h>
16
+
17
+ #include "helpers.h"
18
+ #include "liburing.h"
19
+
20
+ #define FILE_SIZE (8 * 1024)
21
+ #define BS 8192
22
+ #define BUFFERS (FILE_SIZE / BS)
23
+
24
+ static struct iovec *vecs;
25
+ static int warned;
26
+
27
+ static int __test_io(const char *file, struct io_uring *ring, int fixed, int nonvec)
28
+ {
29
+ struct io_uring_sqe *sqe;
30
+ struct io_uring_cqe *cqe;
31
+ int open_flags;
32
+ int i, fd = -1, ret;
33
+ off_t offset;
34
+
35
+ open_flags = O_RDONLY;
36
+ if (fixed) {
37
+ ret = t_register_buffers(ring, vecs, BUFFERS);
38
+ if (ret == T_SETUP_SKIP)
39
+ return 0;
40
+ if (ret != T_SETUP_OK) {
41
+ fprintf(stderr, "buffer reg failed: %d\n", ret);
42
+ goto err;
43
+ }
44
+ }
45
+
46
+ fd = open(file, open_flags);
47
+ if (fd < 0) {
48
+ if (errno == EINVAL || errno == EPERM || errno == ENOENT)
49
+ return 0;
50
+ perror("file open");
51
+ goto err;
52
+ }
53
+
54
+ offset = 0;
55
+ for (i = 0; i < BUFFERS; i++) {
56
+ int do_fixed = fixed;
57
+
58
+ sqe = io_uring_get_sqe(ring);
59
+ if (!sqe) {
60
+ fprintf(stderr, "sqe get failed\n");
61
+ goto err;
62
+ }
63
+ if (fixed && (i & 1))
64
+ do_fixed = 0;
65
+ if (do_fixed) {
66
+ io_uring_prep_read_fixed(sqe, fd, vecs[i].iov_base,
67
+ vecs[i].iov_len, offset, i);
68
+ } else if (nonvec) {
69
+ io_uring_prep_read(sqe, fd, vecs[i].iov_base,
70
+ vecs[i].iov_len, offset);
71
+ } else {
72
+ io_uring_prep_readv(sqe, fd, &vecs[i], 1, offset);
73
+ }
74
+ sqe->user_data = i;
75
+ offset += BS;
76
+ }
77
+
78
+ ret = io_uring_submit(ring);
79
+ if (ret != BUFFERS) {
80
+ fprintf(stderr, "submit got %d, wanted %d\n", ret, BUFFERS);
81
+ goto err;
82
+ }
83
+
84
+ for (i = 0; i < BUFFERS; i++) {
85
+ ret = io_uring_wait_cqe(ring, &cqe);
86
+ if (ret) {
87
+ fprintf(stderr, "wait_cqe=%d\n", ret);
88
+ goto err;
89
+ }
90
+ if (cqe->res == -EINVAL && nonvec) {
91
+ if (!warned) {
92
+ fprintf(stdout, "Non-vectored IO not "
93
+ "supported, skipping\n");
94
+ warned = 1;
95
+ }
96
+ }
97
+ io_uring_cqe_seen(ring, cqe);
98
+ }
99
+
100
+ if (fixed) {
101
+ ret = io_uring_unregister_buffers(ring);
102
+ if (ret) {
103
+ fprintf(stderr, "buffer unreg failed: %d\n", ret);
104
+ goto err;
105
+ }
106
+ }
107
+
108
+ close(fd);
109
+ return 0;
110
+ err:
111
+ if (fd != -1)
112
+ close(fd);
113
+ return 1;
114
+ }
115
+ static int test_io(const char *file, int fixed, int nonvec)
116
+ {
117
+ struct io_uring ring;
118
+ int ret, ring_flags = 0;
119
+
120
+ ret = t_create_ring(64, &ring, ring_flags);
121
+ if (ret == T_SETUP_SKIP)
122
+ return 0;
123
+ if (ret != T_SETUP_OK) {
124
+ fprintf(stderr, "ring create failed: %d\n", ret);
125
+ return 1;
126
+ }
127
+
128
+ ret = __test_io(file, &ring, fixed, nonvec);
129
+ io_uring_queue_exit(&ring);
130
+ return ret;
131
+ }
132
+
133
+ static int has_nonvec_read(void)
134
+ {
135
+ struct io_uring_probe *p;
136
+ struct io_uring ring;
137
+ int ret;
138
+
139
+ ret = io_uring_queue_init(1, &ring, 0);
140
+ if (ret) {
141
+ fprintf(stderr, "queue init failed: %d\n", ret);
142
+ exit(ret);
143
+ }
144
+
145
+ p = t_calloc(1, sizeof(*p) + 256 * sizeof(struct io_uring_probe_op));
146
+ ret = io_uring_register_probe(&ring, p, 256);
147
+ /* if we don't have PROBE_REGISTER, we don't have OP_READ/WRITE */
148
+ if (ret == -EINVAL) {
149
+ out:
150
+ io_uring_queue_exit(&ring);
151
+ free(p);
152
+ return 0;
153
+ } else if (ret) {
154
+ fprintf(stderr, "register_probe: %d\n", ret);
155
+ goto out;
156
+ }
157
+
158
+ if (p->ops_len <= IORING_OP_READ)
159
+ goto out;
160
+ if (!(p->ops[IORING_OP_READ].flags & IO_URING_OP_SUPPORTED))
161
+ goto out;
162
+ io_uring_queue_exit(&ring);
163
+ free(p);
164
+ return 1;
165
+ }
166
+
167
+ int main(int argc, char *argv[])
168
+ {
169
+ int ret, nonvec;
170
+
171
+ if (argc > 1)
172
+ return T_EXIT_SKIP;
173
+
174
+ vecs = t_create_buffers(BUFFERS, BS);
175
+
176
+ /* if we don't have nonvec read, skip testing that */
177
+ nonvec = has_nonvec_read();
178
+
179
+ if (nonvec) {
180
+ ret = test_io("/proc/kallsyms", 0, 0);
181
+ if (ret)
182
+ goto err;
183
+ }
184
+
185
+ ret = test_io("/proc/kallsyms", 0, 1);
186
+ if (ret)
187
+ goto err;
188
+
189
+ if (nonvec) {
190
+ ret = test_io("/proc/kallsyms", 1, 0);
191
+ if (ret)
192
+ goto err;
193
+ }
194
+
195
+ ret = test_io("/proc/kallsyms", 1, 1);
196
+ if (ret)
197
+ goto err;
198
+
199
+ return 0;
200
+ err:
201
+ fprintf(stderr, "Reading kallsyms failed\n");
202
+ return 1;
203
+ }
@@ -10,6 +10,7 @@
10
10
  #include <string.h>
11
11
  #include <fcntl.h>
12
12
  #include <poll.h>
13
+ #include <sys/time.h>
13
14
 
14
15
  #include "liburing.h"
15
16
  #include "helpers.h"
@@ -537,6 +538,139 @@ err:
537
538
  return 1;
538
539
  }
539
540
 
541
+ static int test_link_timeout_update(struct io_uring *ring, int async)
542
+ {
543
+ struct __kernel_timespec ts;
544
+ struct io_uring_cqe *cqe;
545
+ struct io_uring_sqe *sqe;
546
+ struct timeval start;
547
+ unsigned long msec;
548
+ int fds[2], ret, i;
549
+ struct iovec iov;
550
+ char buffer[128];
551
+
552
+ if (pipe(fds)) {
553
+ perror("pipe");
554
+ return 1;
555
+ }
556
+
557
+ sqe = io_uring_get_sqe(ring);
558
+ if (!sqe) {
559
+ printf("get sqe failed\n");
560
+ goto err;
561
+ }
562
+ iov.iov_base = buffer;
563
+ iov.iov_len = sizeof(buffer);
564
+ io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
565
+ sqe->flags |= IOSQE_IO_LINK;
566
+ sqe->user_data = 1;
567
+
568
+ sqe = io_uring_get_sqe(ring);
569
+ if (!sqe) {
570
+ printf("get sqe failed\n");
571
+ goto err;
572
+ }
573
+ ts.tv_sec = 5;
574
+ ts.tv_nsec = 0;
575
+ io_uring_prep_link_timeout(sqe, &ts, 0);
576
+ sqe->user_data = 2;
577
+
578
+ ret = io_uring_submit(ring);
579
+ if (ret != 2) {
580
+ printf("sqe submit failed: %d\n", ret);
581
+ goto err;
582
+ }
583
+
584
+ ts.tv_sec = 0;
585
+ ts.tv_nsec = 100000000LL;
586
+ sqe = io_uring_get_sqe(ring);
587
+ io_uring_prep_timeout_update(sqe, &ts, 2, IORING_LINK_TIMEOUT_UPDATE);
588
+ if (async)
589
+ sqe->flags |= IOSQE_ASYNC;
590
+ sqe->user_data = 3;
591
+
592
+ io_uring_submit(ring);
593
+
594
+ gettimeofday(&start, NULL);
595
+ for (i = 0; i < 3; i++) {
596
+ ret = io_uring_wait_cqe(ring, &cqe);
597
+ if (ret < 0) {
598
+ printf("wait completion %d\n", ret);
599
+ goto err;
600
+ }
601
+ switch (cqe->user_data) {
602
+ case 1:
603
+ if (cqe->res != -EINTR && cqe->res != -ECANCELED) {
604
+ fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
605
+ cqe->res);
606
+ goto err;
607
+ }
608
+ break;
609
+ case 2:
610
+ /* FASTPOLL kernels can cancel successfully */
611
+ if (cqe->res != -EALREADY && cqe->res != -ETIME) {
612
+ fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
613
+ cqe->res);
614
+ goto err;
615
+ }
616
+ break;
617
+ case 3:
618
+ if (cqe->res) {
619
+ fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
620
+ cqe->res);
621
+ goto err;
622
+ }
623
+ break;
624
+ }
625
+
626
+ io_uring_cqe_seen(ring, cqe);
627
+ }
628
+
629
+ msec = mtime_since_now(&start);
630
+ if (msec < 10 || msec > 200) {
631
+ fprintf(stderr, "Timeout appears incorrect: %lu\n", msec);
632
+ goto err;
633
+ }
634
+
635
+ close(fds[0]);
636
+ close(fds[1]);
637
+ return 0;
638
+ err:
639
+ return 1;
640
+ }
641
+
642
+ static int test_link_timeout_update_invalid(struct io_uring *ring, int async)
643
+ {
644
+ struct __kernel_timespec ts;
645
+ struct io_uring_cqe *cqe;
646
+ struct io_uring_sqe *sqe;
647
+ int ret;
648
+
649
+ ts.tv_sec = 0;
650
+ ts.tv_nsec = 100000000LL;
651
+ sqe = io_uring_get_sqe(ring);
652
+ io_uring_prep_timeout_update(sqe, &ts, 2, IORING_LINK_TIMEOUT_UPDATE);
653
+ sqe->user_data = 0xcafe0000;
654
+ if (async)
655
+ sqe->flags |= IOSQE_ASYNC;
656
+
657
+ io_uring_submit(ring);
658
+
659
+ ret = io_uring_wait_cqe(ring, &cqe);
660
+ if (ret < 0) {
661
+ printf("wait completion %d\n", ret);
662
+ goto err;
663
+ }
664
+ if (cqe->res != -ENOENT) {
665
+ fprintf(stderr, "bad timeout update: %d\n", cqe->res);
666
+ goto err;
667
+ }
668
+ io_uring_cqe_seen(ring, cqe);
669
+ return 0;
670
+ err:
671
+ return 1;
672
+ }
673
+
540
674
  static int test_timeout_link_chain1(struct io_uring *ring)
541
675
  {
542
676
  struct __kernel_timespec ts;
@@ -1104,5 +1238,30 @@ int main(int argc, char *argv[])
1104
1238
  return ret;
1105
1239
  }
1106
1240
 
1241
+ ret = test_link_timeout_update(&ring, 0);
1242
+ if (ret) {
1243
+ printf("test_link_timeout_update 0 failed\n");
1244
+ return ret;
1245
+ }
1246
+
1247
+ ret = test_link_timeout_update(&ring, 1);
1248
+ if (ret) {
1249
+ printf("test_link_timeout_update 1 failed\n");
1250
+ return ret;
1251
+ }
1252
+
1253
+ ret = test_link_timeout_update_invalid(&ring, 0);
1254
+ if (ret) {
1255
+ printf("test_link_timeout_update_invalid 0 failed\n");
1256
+ return ret;
1257
+ }
1258
+
1259
+ ret = test_link_timeout_update_invalid(&ring, 1);
1260
+ if (ret) {
1261
+ printf("test_link_timeout_update_invalid 1 failed\n");
1262
+ return ret;
1263
+ }
1264
+
1265
+
1107
1266
  return T_EXIT_PASS;
1108
1267
  }