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
@@ -114,9 +114,12 @@ run_test()
114
114
  elif [ "$status" -eq 77 ]; then
115
115
  echo "Skipped"
116
116
  SKIPPED+=("<$test_string>")
117
- elif [ "$status" -ne 0 ]; then
117
+ elif [[ $test_string != xfail* ]] && [ "$status" -ne 0 ]; then
118
118
  echo "Test $test_name failed with ret $status"
119
119
  FAILED+=("<$test_string>")
120
+ elif [[ $test_string == xfail* ]] && [ "$status" -ne 1 ]; then
121
+ echo "Test $test_name expected fail status 1 but returned $status"
122
+ FAILED+=("<$test_string>")
120
123
  elif ! _check_dmesg "$dmesg_marker" "$test_name"; then
121
124
  echo "Test $test_name failed dmesg check"
122
125
  FAILED+=("<$test_string>")
@@ -153,10 +156,22 @@ for tst in "${TESTS[@]}"; do
153
156
  fi
154
157
  done
155
158
 
159
+ if [ "$DO_KMSG" -eq "1" ]; then
160
+ for dmesg_file in *.dmesg; do
161
+ if [ -f "$dmesg_file" ]; then
162
+ echo "Found dmesg file $dmesg_file, outputting:"
163
+ cat "$dmesg_file"
164
+ fi
165
+ done
166
+ fi
167
+
156
168
  if [ "${#TIMED_OUT[*]}" -ne 0 ]; then
157
169
  echo "Tests timed out (${#TIMED_OUT[*]}): ${TIMED_OUT[*]}"
158
170
  fi
159
171
 
172
+ KVER=$(uname -rv)
173
+ echo "Test run complete, kernel: $KVER"
174
+
160
175
  if [ "${#FAILED[*]}" -ne 0 ]; then
161
176
  echo "Tests failed (${#FAILED[*]}): ${FAILED[*]}"
162
177
  exit 1
@@ -739,6 +739,59 @@ static int test_async_addr(struct io_uring *ring)
739
739
  return 0;
740
740
  }
741
741
 
742
+ static int test_sendzc_report(struct io_uring *ring)
743
+ {
744
+ struct io_uring_sqe *sqe;
745
+ struct io_uring_cqe *cqe;
746
+ struct sockaddr_storage addr;
747
+ int sock_tx, sock_rx;
748
+ int ret;
749
+
750
+ ret = create_socketpair_ip(&addr, &sock_tx, &sock_rx, true, true, false, true);
751
+ if (ret) {
752
+ fprintf(stderr, "sock prep failed %d\n", ret);
753
+ return 1;
754
+ }
755
+
756
+ sqe = io_uring_get_sqe(ring);
757
+ io_uring_prep_send_zc(sqe, sock_tx, tx_buffer, 1, 0,
758
+ IORING_SEND_ZC_REPORT_USAGE);
759
+ ret = io_uring_submit(ring);
760
+ if (ret != 1) {
761
+ fprintf(stderr, "io_uring_submit failed %i\n", ret);
762
+ return 1;
763
+ }
764
+ ret = io_uring_wait_cqe(ring, &cqe);
765
+ if (ret) {
766
+ fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret);
767
+ return 1;
768
+ }
769
+ if (cqe->res != 1 && cqe->res != -EINVAL) {
770
+ fprintf(stderr, "sendzc report failed %u\n", cqe->res);
771
+ return 1;
772
+ }
773
+ if (!(cqe->flags & IORING_CQE_F_MORE)) {
774
+ fprintf(stderr, "expected notification %i\n", cqe->res);
775
+ return 1;
776
+ }
777
+ io_uring_cqe_seen(ring, cqe);
778
+
779
+ ret = io_uring_wait_cqe(ring, &cqe);
780
+ if (ret) {
781
+ fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret);
782
+ return 1;
783
+ }
784
+ if (cqe->flags & IORING_CQE_F_MORE) {
785
+ fprintf(stderr, "F_MORE after notification\n");
786
+ return 1;
787
+ }
788
+ io_uring_cqe_seen(ring, cqe);
789
+
790
+ close(sock_tx);
791
+ close(sock_rx);
792
+ return 0;
793
+ }
794
+
742
795
  /* see also send_recv.c:test_invalid */
743
796
  static int test_invalid_zc(int fds[2])
744
797
  {
@@ -833,6 +886,12 @@ static int run_basic_tests(void)
833
886
  return T_EXIT_FAIL;
834
887
  }
835
888
 
889
+ ret = test_sendzc_report(&ring);
890
+ if (ret) {
891
+ fprintf(stderr, "test_sendzc_report() failed\n");
892
+ return T_EXIT_FAIL;
893
+ }
894
+
836
895
  io_uring_queue_exit(&ring);
837
896
  }
838
897
 
@@ -71,5 +71,6 @@ int main(int argc, char *argv[])
71
71
  }
72
72
 
73
73
  io_uring_cqe_seen(&ring, cqe);
74
+ free(vec.iov_base);
74
75
  return 0;
75
76
  }
@@ -365,6 +365,43 @@ static int test(int use_sqthread, int regfiles, int socket_direct, int alloc)
365
365
  return (intptr_t)retval;
366
366
  }
367
367
 
368
+ static int test_bad_socket(void)
369
+ {
370
+ struct io_uring ring;
371
+ struct io_uring_cqe *cqe;
372
+ struct io_uring_sqe *sqe;
373
+ int ret;
374
+
375
+ ret = io_uring_queue_init(1, &ring, 0);
376
+ if (ret) {
377
+ fprintf(stderr, "queue init failed: %d\n", ret);
378
+ return 1;
379
+ }
380
+
381
+ sqe = io_uring_get_sqe(&ring);
382
+ io_uring_prep_socket(sqe, -1, SOCK_DGRAM, 0, 0);
383
+ ret = io_uring_submit(&ring);
384
+ if (ret != 1) {
385
+ fprintf(stderr, "socket submit: %d\n", ret);
386
+ goto err;
387
+ }
388
+ ret = io_uring_wait_cqe(&ring, &cqe);
389
+ if (ret) {
390
+ fprintf(stderr, "wait_cqe: %d\n", ret);
391
+ goto err;
392
+ }
393
+ if (cqe->res != -EAFNOSUPPORT) {
394
+ fprintf(stderr, "socket res: %d\n", cqe->res);
395
+ goto err;
396
+ }
397
+ io_uring_cqe_seen(&ring, cqe);
398
+ io_uring_queue_exit(&ring);
399
+ return 0;
400
+ err:
401
+ io_uring_queue_exit(&ring);
402
+ return 1;
403
+ }
404
+
368
405
  int main(int argc, char *argv[])
369
406
  {
370
407
  int ret;
@@ -404,5 +441,11 @@ int main(int argc, char *argv[])
404
441
  return ret;
405
442
  }
406
443
 
444
+ ret = test_bad_socket();
445
+ if (ret) {
446
+ fprintf(stderr, "test bad socket failed\n");
447
+ return 1;
448
+ }
449
+
407
450
  return 0;
408
451
  }
@@ -191,7 +191,7 @@ static int do_splice(struct io_uring *ring,
191
191
  IORING_OP_SPLICE);
192
192
  }
193
193
 
194
- static int do_tee(struct io_uring *ring, int fd_in, int fd_out,
194
+ static int do_tee(struct io_uring *ring, int fd_in, int fd_out,
195
195
  unsigned int len)
196
196
  {
197
197
  return do_splice_op(ring, fd_in, 0, fd_out, 0, len, IORING_OP_TEE);
@@ -504,6 +504,8 @@ int main(int argc, char *argv[])
504
504
  splice_flags = SPLICE_F_FD_IN_FIXED;
505
505
  sqe_flags = IOSQE_FIXED_FILE;
506
506
  ret = test_splice(&ring, &ctx);
507
+ free(ctx.buf_in);
508
+ free(ctx.buf_out);
507
509
  if (ret) {
508
510
  fprintf(stderr, "registered fds splice tests failed\n");
509
511
  return ret;
@@ -177,7 +177,7 @@ int main(int argc, char *argv[])
177
177
  if (fname != argv[1])
178
178
  unlink(fname);
179
179
 
180
- if (__e == EINVAL)
180
+ if (__e == EINVAL || __e == EPERM || __e == EACCES)
181
181
  return T_EXIT_SKIP;
182
182
  perror("open");
183
183
  return -1;
@@ -90,6 +90,8 @@ int main(int argc, char *argv[])
90
90
 
91
91
  fd = open(fname, O_RDONLY | O_DIRECT);
92
92
  if (fd < 0) {
93
+ if (errno == EPERM || errno == EACCES || errno == EINVAL)
94
+ return T_EXIT_SKIP;
93
95
  perror("open");
94
96
  return -1;
95
97
  }
@@ -22,8 +22,10 @@
22
22
  #include <unistd.h>
23
23
 
24
24
  #include "liburing.h"
25
+ #include "helpers.h"
25
26
  #include "../src/syscall.h"
26
27
 
28
+ #ifndef CONFIG_USE_SANITIZER
27
29
  static void sleep_ms(uint64_t ms)
28
30
  {
29
31
  usleep(ms * 1000);
@@ -194,3 +196,9 @@ int main(void)
194
196
  loop();
195
197
  return 0;
196
198
  }
199
+ #else
200
+ int main(int argc, char *argv[])
201
+ {
202
+ return T_EXIT_SKIP;
203
+ }
204
+ #endif
@@ -10,31 +10,7 @@
10
10
  #include <sys/time.h>
11
11
  #include <poll.h>
12
12
  #include "liburing.h"
13
-
14
- static unsigned long long mtime_since(const struct timeval *s,
15
- const struct timeval *e)
16
- {
17
- long long sec, usec;
18
-
19
- sec = e->tv_sec - s->tv_sec;
20
- usec = (e->tv_usec - s->tv_usec);
21
- if (sec > 0 && usec < 0) {
22
- sec--;
23
- usec += 1000000;
24
- }
25
-
26
- sec *= 1000;
27
- usec /= 1000;
28
- return sec + usec;
29
- }
30
-
31
- static unsigned long long mtime_since_now(struct timeval *tv)
32
- {
33
- struct timeval end;
34
-
35
- gettimeofday(&end, NULL);
36
- return mtime_since(tv, &end);
37
- }
13
+ #include "helpers.h"
38
14
 
39
15
  int main(int argc, char *argv[])
40
16
  {
@@ -9,41 +9,21 @@
9
9
  #include <unistd.h>
10
10
  #include <sys/time.h>
11
11
  #include "liburing.h"
12
-
13
- static unsigned long long mtime_since(const struct timeval *s,
14
- const struct timeval *e)
15
- {
16
- long long sec, usec;
17
-
18
- sec = e->tv_sec - s->tv_sec;
19
- usec = (e->tv_usec - s->tv_usec);
20
- if (sec > 0 && usec < 0) {
21
- sec--;
22
- usec += 1000000;
23
- }
24
-
25
- sec *= 1000;
26
- usec /= 1000;
27
- return sec + usec;
28
- }
29
-
30
- static unsigned long long mtime_since_now(struct timeval *tv)
31
- {
32
- struct timeval end;
33
-
34
- gettimeofday(&end, NULL);
35
- return mtime_since(tv, &end);
36
- }
12
+ #include "helpers.h"
37
13
 
38
14
  int main(int argc, char *argv[])
39
15
  {
40
16
  struct io_uring_params p = {};
17
+ struct io_uring_sqe *sqe;
18
+ struct io_uring_cqe *cqe;
41
19
  struct timeval tv;
42
20
  struct io_uring ring;
21
+ unsigned long elapsed;
22
+ bool seen_wakeup;
43
23
  int ret;
44
24
 
45
25
  if (argc > 1)
46
- return 0;
26
+ return T_EXIT_SKIP;
47
27
 
48
28
  p.flags = IORING_SETUP_SQPOLL;
49
29
  p.sq_thread_idle = 100;
@@ -52,18 +32,45 @@ int main(int argc, char *argv[])
52
32
  if (ret) {
53
33
  if (geteuid()) {
54
34
  printf("%s: skipped, not root\n", argv[0]);
55
- return 0;
35
+ return T_EXIT_SKIP;
56
36
  }
57
37
  fprintf(stderr, "queue_init=%d\n", ret);
58
- return 1;
38
+ return T_EXIT_FAIL;
59
39
  }
60
40
 
41
+ sqe = io_uring_get_sqe(&ring);
42
+ io_uring_prep_nop(sqe);
43
+ io_uring_submit(&ring);
44
+
45
+ ret = io_uring_wait_cqe(&ring, &cqe);
46
+ if (ret) {
47
+ fprintf(stderr, "wait_cqe: %d\n", ret);
48
+ return T_EXIT_FAIL;
49
+ }
50
+ io_uring_cqe_seen(&ring, cqe);
51
+
52
+ elapsed = 0;
53
+ seen_wakeup = false;
61
54
  gettimeofday(&tv, NULL);
62
55
  do {
63
- usleep(1000);
64
- if ((*ring.sq.kflags) & IORING_SQ_NEED_WAKEUP)
65
- return 0;
66
- } while (mtime_since_now(&tv) < 1000);
56
+ usleep(100);
57
+ if (IO_URING_READ_ONCE(*ring.sq.kflags) & IORING_SQ_NEED_WAKEUP) {
58
+ seen_wakeup = true;
59
+ break;
60
+ }
61
+ elapsed = mtime_since_now(&tv);
62
+ } while (elapsed < 1000);
63
+
64
+ if (!seen_wakeup) {
65
+ fprintf(stderr, "SQPOLL didn't flag wakeup\n");
66
+ return T_EXIT_FAIL;
67
+ }
68
+
69
+ /* should be around 100 msec */
70
+ if (elapsed < 90 || elapsed > 110) {
71
+ fprintf(stderr, "SQPOLL wakeup timing off %lu\n", elapsed);
72
+ return T_EXIT_FAIL;
73
+ }
67
74
 
68
- return 1;
75
+ return T_EXIT_PASS;
69
76
  }
@@ -0,0 +1,136 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test that the app can always get a new sqe after having
4
+ * called io_uring_sqring_wait().
5
+ *
6
+ */
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+ #include <unistd.h>
10
+
11
+ #include "liburing.h"
12
+ #include "helpers.h"
13
+
14
+ #define NR_IOS 10000
15
+ #define INFLIGHT 256
16
+ #define FILE_SIZE (256 * 1024 * 1024)
17
+
18
+ static int inflight;
19
+
20
+ static int reap(struct io_uring *ring)
21
+ {
22
+ struct io_uring_cqe *cqe;
23
+ int ret;
24
+
25
+ while (inflight >= INFLIGHT / 2) {
26
+ ret = io_uring_wait_cqe(ring, &cqe);
27
+ if (ret < 0) {
28
+ fprintf(stderr, "wait=%d\n", ret);
29
+ return 1;
30
+ }
31
+ if (cqe->res < 0) {
32
+ printf("cqe res %d\n", cqe->res);
33
+ return 1;
34
+ }
35
+ io_uring_cqe_seen(ring, cqe);
36
+ inflight--;
37
+ }
38
+
39
+ return 0;
40
+ }
41
+
42
+ int main(int argc, char *argv[])
43
+ {
44
+ struct io_uring_sqe *sqe;
45
+ struct io_uring ring;
46
+ int fd = -1, i, iov_off, ret, fret;
47
+ struct iovec iovs[INFLIGHT];
48
+ const char *fname;
49
+ char buf[256];
50
+ loff_t off;
51
+
52
+ if (argc > 1) {
53
+ fname = argv[1];
54
+ } else {
55
+ srand((unsigned)time(NULL));
56
+ snprintf(buf, sizeof(buf), ".sqwait-%u-%u", (unsigned)rand(),
57
+ (unsigned)getpid());
58
+ fname = buf;
59
+ t_create_file(fname, FILE_SIZE);
60
+ }
61
+
62
+ fret = T_EXIT_SKIP;
63
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_SQPOLL);
64
+ if (ret < 0) {
65
+ if (errno == EINVAL || errno == EPERM)
66
+ goto err;
67
+ fprintf(stderr, "queue init %d\n", ret);
68
+ fret = T_EXIT_FAIL;
69
+ goto err;
70
+ }
71
+
72
+ fd = open(fname, O_RDONLY | O_DIRECT);
73
+ if (fd < 0) {
74
+ if (errno == EACCES || errno == EPERM || errno == EINVAL)
75
+ return T_EXIT_SKIP;
76
+ perror("open");
77
+ fret = T_EXIT_FAIL;
78
+ goto err;
79
+ }
80
+
81
+ for (i = 0; i < INFLIGHT; i++) {
82
+ if (posix_memalign(&iovs[i].iov_base, 4096, 4096))
83
+ goto err;
84
+ iovs[i].iov_len = 4096;
85
+ }
86
+
87
+ iov_off = off = 0;
88
+ for (i = 0; i < NR_IOS; i++) {
89
+ struct iovec *iov = &iovs[iov_off];
90
+
91
+ sqe = io_uring_get_sqe(&ring);
92
+ if (!sqe) {
93
+ ret = io_uring_sqring_wait(&ring);
94
+ if (ret < 0) {
95
+ if (ret == -EINVAL)
96
+ return T_EXIT_SKIP;
97
+ fprintf(stderr, "sqwait=%d\n", ret);
98
+ fret = T_EXIT_FAIL;
99
+ goto err;
100
+ }
101
+ sqe = io_uring_get_sqe(&ring);
102
+ if (!sqe) {
103
+ fprintf(stderr, "No sqe post wait\n");
104
+ fret = T_EXIT_FAIL;
105
+ goto err;
106
+ }
107
+ }
108
+ io_uring_prep_read(sqe, fd, iov->iov_base, iov->iov_len, 0);
109
+ io_uring_submit(&ring);
110
+ inflight++;
111
+
112
+ iov_off++;
113
+ if (iov_off == INFLIGHT)
114
+ iov_off = 0;
115
+ off += 8192;
116
+ if (off > FILE_SIZE - 8192)
117
+ off = 0;
118
+ if (reap(&ring)) {
119
+ fret = T_EXIT_FAIL;
120
+ goto err;
121
+ }
122
+ }
123
+
124
+ if (fd != -1)
125
+ close(fd);
126
+ if (fname != argv[1])
127
+ unlink(fname);
128
+ io_uring_queue_exit(&ring);
129
+ return T_EXIT_PASS;
130
+ err:
131
+ if (fd != -1)
132
+ close(fd);
133
+ if (fname != argv[1])
134
+ unlink(fname);
135
+ return fret;
136
+ }
@@ -36,6 +36,81 @@ static int statx_syscall_supported(void)
36
36
  return errno == ENOSYS ? 0 : -1;
37
37
  }
38
38
 
39
+ static int test_statx_invalid_buf(struct io_uring *ring, const char *path)
40
+ {
41
+ struct io_uring_cqe *cqe;
42
+ struct io_uring_sqe *sqe;
43
+ struct statx *x = (struct statx *) (uintptr_t) 0x1234;
44
+ int ret;
45
+
46
+ sqe = io_uring_get_sqe(ring);
47
+ if (!sqe) {
48
+ fprintf(stderr, "get sqe failed\n");
49
+ goto err;
50
+ }
51
+ io_uring_prep_statx(sqe, -1, path, 0, STATX_ALL, x);
52
+
53
+ ret = io_uring_submit(ring);
54
+ if (ret <= 0) {
55
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
56
+ goto err;
57
+ }
58
+
59
+ ret = io_uring_wait_cqe(ring, &cqe);
60
+ if (ret < 0) {
61
+ fprintf(stderr, "wait completion %d\n", ret);
62
+ goto err;
63
+ }
64
+ ret = cqe->res;
65
+ io_uring_cqe_seen(ring, cqe);
66
+ if (ret != -EFAULT) {
67
+ fprintf(stderr, "Invalid address didn't fail\n");
68
+ goto err;
69
+ }
70
+
71
+ return 0;
72
+ err:
73
+ return -1;
74
+ }
75
+
76
+ static int test_statx_invalid_path(struct io_uring *ring)
77
+ {
78
+ const char *path = (const char *) (uintptr_t) 0x1234;
79
+ struct io_uring_cqe *cqe;
80
+ struct io_uring_sqe *sqe;
81
+ struct statx x1 = { };
82
+ int ret;
83
+
84
+ sqe = io_uring_get_sqe(ring);
85
+ if (!sqe) {
86
+ fprintf(stderr, "get sqe failed\n");
87
+ goto err;
88
+ }
89
+ io_uring_prep_statx(sqe, -1, path, 0, STATX_ALL, &x1);
90
+
91
+ ret = io_uring_submit(ring);
92
+ if (ret <= 0) {
93
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
94
+ goto err;
95
+ }
96
+
97
+ ret = io_uring_wait_cqe(ring, &cqe);
98
+ if (ret < 0) {
99
+ fprintf(stderr, "wait completion %d\n", ret);
100
+ goto err;
101
+ }
102
+ ret = cqe->res;
103
+ io_uring_cqe_seen(ring, cqe);
104
+ if (ret != -EFAULT) {
105
+ fprintf(stderr, "Invalid address didn't fail\n");
106
+ goto err;
107
+ }
108
+
109
+ return 0;
110
+ err:
111
+ return -1;
112
+ }
113
+
39
114
  static int test_statx(struct io_uring *ring, const char *path)
40
115
  {
41
116
  struct io_uring_cqe *cqe;
@@ -86,6 +161,8 @@ static int test_statx_fd(struct io_uring *ring, const char *path)
86
161
 
87
162
  fd = open(path, O_RDONLY);
88
163
  if (fd < 0) {
164
+ if (errno == EPERM || errno == EACCES)
165
+ return 0;
89
166
  perror("open");
90
167
  return 1;
91
168
  }
@@ -156,6 +233,18 @@ int main(int argc, char *argv[])
156
233
  goto err;
157
234
  }
158
235
 
236
+ ret = test_statx_invalid_path(&ring);
237
+ if (ret) {
238
+ fprintf(stderr, "test_statx_invalid_path failed: %d\n", ret);
239
+ goto err;
240
+ }
241
+
242
+ ret = test_statx_invalid_buf(&ring, fname);
243
+ if (ret) {
244
+ fprintf(stderr, "test_statx_invalid_buf failed: %d\n", ret);
245
+ goto err;
246
+ }
247
+
159
248
  ret = test_statx_fd(&ring, fname);
160
249
  if (ret) {
161
250
  fprintf(stderr, "test_statx_fd failed: %d\n", ret);
@@ -89,6 +89,7 @@ static int test_pipe_io_fixed(struct io_uring *ring)
89
89
  io_uring_cqe_seen(ring, cqe);
90
90
  }
91
91
  io_uring_unregister_buffers(ring);
92
+ free(vecs[0].iov_base);
92
93
  return 0;
93
94
  err:
94
95
  return 1;
@@ -143,6 +144,7 @@ static int test_stdout_io_fixed(struct io_uring *ring)
143
144
  }
144
145
  io_uring_cqe_seen(ring, cqe);
145
146
  io_uring_unregister_buffers(ring);
147
+ free(vecs.iov_base);
146
148
  return 0;
147
149
  err:
148
150
  return 1;
@@ -13,33 +13,9 @@
13
13
  #include <sys/time.h>
14
14
 
15
15
  #include "liburing.h"
16
+ #include "helpers.h"
16
17
  #include "test.h"
17
18
 
18
- static unsigned long long mtime_since(const struct timeval *s,
19
- const struct timeval *e)
20
- {
21
- long long sec, usec;
22
-
23
- sec = e->tv_sec - s->tv_sec;
24
- usec = (e->tv_usec - s->tv_usec);
25
- if (sec > 0 && usec < 0) {
26
- sec--;
27
- usec += 1000000;
28
- }
29
-
30
- sec *= 1000;
31
- usec /= 1000;
32
- return sec + usec;
33
- }
34
-
35
- static unsigned long long mtime_since_now(struct timeval *tv)
36
- {
37
- struct timeval end;
38
-
39
- gettimeofday(&end, NULL);
40
- return mtime_since(tv, &end);
41
- }
42
-
43
19
  static int test(struct io_uring *ring)
44
20
  {
45
21
  struct io_uring_cqe *cqe;