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
@@ -80,7 +80,7 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
80
80
  if (fixed) {
81
81
  ret = t_register_buffers(ring, vecs, BUFFERS);
82
82
  if (ret == T_SETUP_SKIP)
83
- return 0;
83
+ return T_EXIT_SKIP;
84
84
  if (ret != T_SETUP_OK) {
85
85
  fprintf(stderr, "buffer reg failed: %d\n", ret);
86
86
  goto err;
@@ -91,6 +91,8 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
91
91
  if (fd < 0) {
92
92
  if (errno == EINVAL)
93
93
  return 0;
94
+ if (errno == EPERM || errno == EACCES)
95
+ return T_EXIT_SKIP;
94
96
  perror("file open");
95
97
  goto err;
96
98
  }
@@ -290,6 +292,7 @@ static int has_nonvec_read(void)
290
292
  if (ret == -EINVAL) {
291
293
  out:
292
294
  io_uring_queue_exit(&ring);
295
+ free(p);
293
296
  return 0;
294
297
  } else if (ret) {
295
298
  fprintf(stderr, "register_probe: %d\n", ret);
@@ -301,6 +304,7 @@ out:
301
304
  if (!(p->ops[IORING_OP_READ].flags & IO_URING_OP_SUPPORTED))
302
305
  goto out;
303
306
  io_uring_queue_exit(&ring);
307
+ free(p);
304
308
  return 1;
305
309
  }
306
310
 
@@ -318,6 +322,8 @@ static int test_eventfd_read(int flags)
318
322
  if (ret == T_SETUP_SKIP)
319
323
  return 0;
320
324
  if (ret != T_SETUP_OK) {
325
+ if (ret == -EINVAL)
326
+ return 0;
321
327
  fprintf(stderr, "ring create failed: %d\n", ret);
322
328
  return 1;
323
329
  }
@@ -384,6 +390,8 @@ int main(int argc, char *argv[])
384
390
 
385
391
  ret = test_io(fname, write, buffered, sqthread, fixed, nonvec,
386
392
  BS);
393
+ if (ret == T_EXIT_SKIP)
394
+ continue;
387
395
  if (ret) {
388
396
  fprintf(stderr, "test_io failed %d/%d/%d/%d/%d\n",
389
397
  write, buffered, sqthread, fixed, nonvec);
@@ -0,0 +1,69 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: Test O_NONBLOCK reading from fifo, should result in proper
4
+ * retry and a positive read results. Buggy result would be
5
+ * -EAGAIN being returned to the user.
6
+ */
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+ #include <unistd.h>
10
+
11
+ #include "liburing.h"
12
+ #include "helpers.h"
13
+
14
+ int main(int argc, char *argv[])
15
+ {
16
+ struct io_uring_sqe *sqe;
17
+ struct io_uring_cqe *cqe;
18
+ struct io_uring ring;
19
+ char buf[32];
20
+ int fds[2];
21
+ int flags;
22
+ int ret;
23
+
24
+ io_uring_queue_init(1, &ring, 0);
25
+
26
+ if (pipe(fds) < 0) {
27
+ perror("pipe");
28
+ return T_EXIT_FAIL;
29
+ }
30
+
31
+ flags = fcntl(fds[0], F_GETFL, 0);
32
+ if (flags < 0) {
33
+ perror("fcntl get");
34
+ return T_EXIT_FAIL;
35
+ }
36
+ flags |= O_NONBLOCK;
37
+ ret = fcntl(fds[0], F_SETFL, flags);
38
+ if (ret < 0) {
39
+ perror("fcntl set");
40
+ return T_EXIT_FAIL;
41
+ }
42
+
43
+ sqe = io_uring_get_sqe(&ring);
44
+ io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0);
45
+ io_uring_submit(&ring);
46
+
47
+ usleep(10000);
48
+
49
+ ret = write(fds[1], "Hello\n", 6);
50
+ if (ret < 0) {
51
+ perror("pipe write");
52
+ return T_EXIT_FAIL;
53
+ }
54
+
55
+ ret = io_uring_wait_cqe(&ring, &cqe);
56
+ if (ret < 0) {
57
+ fprintf(stderr, "wait=%d\n", ret);
58
+ return T_EXIT_FAIL;
59
+ }
60
+
61
+ if (cqe->res < 0) {
62
+ fprintf(stderr, "cqe res %d\n", cqe->res);
63
+ return T_EXIT_FAIL;
64
+ }
65
+
66
+ io_uring_cqe_seen(&ring, cqe);
67
+ io_uring_queue_exit(&ring);
68
+ return T_EXIT_PASS;
69
+ }
@@ -0,0 +1,48 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test that a defer task_work file with tags unregistration
4
+ * doesn't trigger a lockdep violation
5
+ *
6
+ */
7
+ #include <stdio.h>
8
+ #include <inttypes.h>
9
+ #include <stdlib.h>
10
+ #include <unistd.h>
11
+
12
+ #include "liburing.h"
13
+ #include "helpers.h"
14
+
15
+ int main(int argc, char *argv[])
16
+ {
17
+ __u64 tags[2] = { 1, 2 };
18
+ struct io_uring ring;
19
+ int fds[2], ret;
20
+
21
+ if (argc > 1)
22
+ return T_EXIT_SKIP;
23
+
24
+ if (pipe(fds) < 0) {
25
+ perror("pipe");
26
+ return 1;
27
+ }
28
+
29
+ ret = io_uring_queue_init(4, &ring, IORING_SETUP_SINGLE_ISSUER|IORING_SETUP_DEFER_TASKRUN);
30
+ if (ret == -EINVAL) {
31
+ return T_EXIT_SKIP;
32
+ } else if (ret < 0) {
33
+ fprintf(stderr, "queue_init: %d\n", ret);
34
+ return T_EXIT_FAIL;
35
+ }
36
+
37
+ ret = io_uring_register_files_tags(&ring, fds, tags, 2);
38
+ if (ret == -EINVAL) {
39
+ return T_EXIT_SKIP;
40
+ } else if (ret < 0) {
41
+ fprintf(stderr, "file_register_init: %d\n", ret);
42
+ return T_EXIT_FAIL;
43
+ }
44
+
45
+ io_uring_queue_exit(&ring);
46
+ sleep(1);
47
+ return 0;
48
+ }
@@ -120,16 +120,21 @@ static int test_grow(struct io_uring *ring)
120
120
  fds = open_files(1, 0, off);
121
121
  ret = io_uring_register_files_update(ring, off, fds, 1);
122
122
  if (ret != 1) {
123
- if (off == 300 && ret == -EINVAL)
123
+ if (off == 300 && ret == -EINVAL) {
124
+ free(fds);
124
125
  break;
126
+ }
125
127
  fprintf(stderr, "%s: update ret=%d\n", __FUNCTION__, ret);
128
+ free(fds);
126
129
  break;
127
130
  }
128
131
  if (off >= 300) {
129
132
  fprintf(stderr, "%s: Succeeded beyond end-of-list?\n", __FUNCTION__);
133
+ free(fds);
130
134
  goto err;
131
135
  }
132
136
  off++;
137
+ free(fds);
133
138
  } while (1);
134
139
 
135
140
  ret = io_uring_unregister_files(ring);
@@ -363,8 +368,10 @@ static int test_basic(struct io_uring *ring, int fail)
363
368
  ret = io_uring_register_files(ring, files, 100);
364
369
  if (ret) {
365
370
  if (fail) {
366
- if (ret == -EBADF || ret == -EFAULT)
371
+ if (ret == -EBADF || ret == -EFAULT) {
372
+ close_files(files, nr_files, 0);
367
373
  return 0;
374
+ }
368
375
  }
369
376
  fprintf(stderr, "%s: register %d\n", __FUNCTION__, ret);
370
377
  goto err;
@@ -631,6 +638,7 @@ static int test_sparse_updates(void)
631
638
  ret = io_uring_register_files(&ring, fds, 256);
632
639
  if (ret) {
633
640
  fprintf(stderr, "file_register: %d\n", ret);
641
+ free(fds);
634
642
  return ret;
635
643
  }
636
644
 
@@ -639,6 +647,7 @@ static int test_sparse_updates(void)
639
647
  ret = io_uring_register_files_update(&ring, i, &newfd, 1);
640
648
  if (ret != 1) {
641
649
  fprintf(stderr, "file_update: %d\n", ret);
650
+ free(fds);
642
651
  return ret;
643
652
  }
644
653
  }
@@ -650,6 +659,7 @@ static int test_sparse_updates(void)
650
659
  ret = io_uring_register_files(&ring, fds, 256);
651
660
  if (ret) {
652
661
  fprintf(stderr, "file_register: %d\n", ret);
662
+ free(fds);
653
663
  return ret;
654
664
  }
655
665
 
@@ -658,12 +668,14 @@ static int test_sparse_updates(void)
658
668
  ret = io_uring_register_files_update(&ring, i, &newfd, 1);
659
669
  if (ret != 1) {
660
670
  fprintf(stderr, "file_update: %d\n", ret);
671
+ free(fds);
661
672
  return ret;
662
673
  }
663
674
  }
664
675
  io_uring_unregister_files(&ring);
665
676
 
666
677
  io_uring_queue_exit(&ring);
678
+ free(fds);
667
679
  return 0;
668
680
  }
669
681
 
@@ -174,7 +174,7 @@ static int test_update_no_table(void)
174
174
  ret = cqe->res;
175
175
  io_uring_cqe_seen(&ring, cqe);
176
176
  if (ret != -EMFILE && ret != -EINVAL && ret != -EOVERFLOW &&
177
- ret != -ENXIO) {
177
+ ret != -ENXIO && ret != -EBADF) {
178
178
  fprintf(stderr, "Bad cqe res: %d\n", ret);
179
179
  goto fail;
180
180
  }
@@ -90,6 +90,8 @@ static int test_truncate(struct io_uring *ring, const char *fname, int buffered,
90
90
  else
91
91
  fd = open(fname, O_DIRECT | O_RDWR);
92
92
  if (fd < 0) {
93
+ if (!buffered && errno == EINVAL)
94
+ return T_EXIT_SKIP;
93
95
  perror("open");
94
96
  return 1;
95
97
  }
@@ -346,6 +348,8 @@ static int test(struct io_uring *ring, const char *fname, int buffered,
346
348
  flags |= O_DIRECT;
347
349
  fd = open(fname, flags);
348
350
  if (fd < 0) {
351
+ if (errno == EINVAL || errno == EPERM || errno == EACCES)
352
+ return T_EXIT_SKIP;
349
353
  perror("open");
350
354
  return 1;
351
355
  }
@@ -505,6 +509,8 @@ static int fill_pattern(const char *fname)
505
509
 
506
510
  fd = open(fname, O_WRONLY);
507
511
  if (fd < 0) {
512
+ if (errno == EPERM || errno == EACCES)
513
+ return T_EXIT_SKIP;
508
514
  perror("open");
509
515
  return 1;
510
516
  }
@@ -557,89 +563,94 @@ int main(int argc, char *argv[])
557
563
  goto err;
558
564
  }
559
565
 
560
- if (fill_pattern(fname))
566
+ ret = fill_pattern(fname);
567
+ if (ret == T_EXIT_SKIP)
568
+ return T_EXIT_SKIP;
569
+ else if (ret)
561
570
  goto err;
562
571
 
563
572
  ret = test(&ring, fname, 1, 0, 0, 0, 0);
573
+ if (ret == T_EXIT_SKIP)
574
+ return T_EXIT_SKIP;
564
575
  if (ret) {
565
576
  fprintf(stderr, "Buffered novec test failed\n");
566
577
  goto err;
567
578
  }
568
579
  ret = test(&ring, fname, 1, 0, 0, 1, 0);
569
- if (ret) {
580
+ if (ret == T_EXIT_FAIL) {
570
581
  fprintf(stderr, "Buffered novec reg test failed\n");
571
582
  goto err;
572
583
  }
573
584
  ret = test(&ring, fname, 1, 0, 0, 0, 1);
574
- if (ret) {
585
+ if (ret == T_EXIT_FAIL) {
575
586
  fprintf(stderr, "Buffered novec provide test failed\n");
576
587
  goto err;
577
588
  }
578
589
  ret = test(&ring, fname, 1, 1, 0, 0, 0);
579
- if (ret) {
590
+ if (ret == T_EXIT_FAIL) {
580
591
  fprintf(stderr, "Buffered vec test failed\n");
581
592
  goto err;
582
593
  }
583
594
  ret = test(&ring, fname, 1, 1, 1, 0, 0);
584
- if (ret) {
595
+ if (ret == T_EXIT_FAIL) {
585
596
  fprintf(stderr, "Buffered small vec test failed\n");
586
597
  goto err;
587
598
  }
588
599
 
589
600
  ret = test(&ring, fname, 0, 0, 0, 0, 0);
590
- if (ret) {
601
+ if (ret == T_EXIT_FAIL) {
591
602
  fprintf(stderr, "O_DIRECT novec test failed\n");
592
603
  goto err;
593
604
  }
594
605
  ret = test(&ring, fname, 0, 0, 0, 1, 0);
595
- if (ret) {
606
+ if (ret == T_EXIT_FAIL) {
596
607
  fprintf(stderr, "O_DIRECT novec reg test failed\n");
597
608
  goto err;
598
609
  }
599
610
  ret = test(&ring, fname, 0, 0, 0, 0, 1);
600
- if (ret) {
611
+ if (ret == T_EXIT_FAIL) {
601
612
  fprintf(stderr, "O_DIRECT novec provide test failed\n");
602
613
  goto err;
603
614
  }
604
615
  ret = test(&ring, fname, 0, 1, 0, 0, 0);
605
- if (ret) {
616
+ if (ret == T_EXIT_FAIL) {
606
617
  fprintf(stderr, "O_DIRECT vec test failed\n");
607
618
  goto err;
608
619
  }
609
620
  ret = test(&ring, fname, 0, 1, 1, 0, 0);
610
- if (ret) {
621
+ if (ret == T_EXIT_FAIL) {
611
622
  fprintf(stderr, "O_DIRECT small vec test failed\n");
612
623
  goto err;
613
624
  }
614
625
 
615
626
  ret = test_truncate(&ring, fname, 1, 0, 0);
616
- if (ret) {
627
+ if (ret == T_EXIT_FAIL) {
617
628
  fprintf(stderr, "Buffered end truncate read failed\n");
618
629
  goto err;
619
630
  }
620
631
  ret = test_truncate(&ring, fname, 1, 1, 0);
621
- if (ret) {
632
+ if (ret == T_EXIT_FAIL) {
622
633
  fprintf(stderr, "Buffered end truncate vec read failed\n");
623
634
  goto err;
624
635
  }
625
636
  ret = test_truncate(&ring, fname, 1, 0, 1);
626
- if (ret) {
637
+ if (ret == T_EXIT_FAIL) {
627
638
  fprintf(stderr, "Buffered end truncate pbuf read failed\n");
628
639
  goto err;
629
640
  }
630
641
 
631
642
  ret = test_truncate(&ring, fname, 0, 0, 0);
632
- if (ret) {
643
+ if (ret == T_EXIT_FAIL) {
633
644
  fprintf(stderr, "O_DIRECT end truncate read failed\n");
634
645
  goto err;
635
646
  }
636
647
  ret = test_truncate(&ring, fname, 0, 1, 0);
637
- if (ret) {
648
+ if (ret == T_EXIT_FAIL) {
638
649
  fprintf(stderr, "O_DIRECT end truncate vec read failed\n");
639
650
  goto err;
640
651
  }
641
652
  ret = test_truncate(&ring, fname, 0, 0, 1);
642
- if (ret) {
653
+ if (ret == T_EXIT_FAIL) {
643
654
  fprintf(stderr, "O_DIRECT end truncate pbuf read failed\n");
644
655
  goto err;
645
656
  }
@@ -43,13 +43,12 @@ static void add_accept(struct io_uring *ring, int fd)
43
43
 
44
44
  sqe = io_uring_get_sqe(ring);
45
45
  io_uring_prep_accept(sqe, fd, 0, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
46
- sqe->flags |= IOSQE_IO_LINK;
47
46
  }
48
47
 
49
48
  static int setup_io_uring(void)
50
49
  {
51
50
  int ret;
52
-
51
+
53
52
  ret = io_uring_queue_init(16, &ring, 0);
54
53
  if (ret) {
55
54
  fprintf(stderr, "Unable to setup io_uring: %s\n", strerror(-ret));
@@ -63,7 +63,7 @@ static int test(struct io_uring *ring)
63
63
  return 1;
64
64
  }
65
65
 
66
- if (cqe->res < 0) {
66
+ if (cqe->res < 0) {
67
67
  fprintf(stderr, "Error in async operation: %s\n", strerror(-cqe->res));
68
68
  return 1;
69
69
  }
@@ -87,6 +87,8 @@ static int test(struct io_uring *ring)
87
87
  return 1;
88
88
  }
89
89
  io_uring_cqe_seen(ring, cqe);
90
+ for (i = 0; i < BUFFERS; i++)
91
+ free(iov[i].iov_base);
90
92
  return 0;
91
93
  }
92
94
 
@@ -246,7 +246,8 @@ static int register_submit(struct io_uring *ring, struct iovec *iov,
246
246
 
247
247
  ret = io_uring_register_buffers(ring, iov, nr_bufs);
248
248
  if (ret) {
249
- fprintf(stderr, "Error registering buffers: %s\n", strerror(-ret));
249
+ if (ret != -ENOMEM)
250
+ fprintf(stderr, "Error registering buffers: %s\n", strerror(-ret));
250
251
  return ret;
251
252
  }
252
253
 
@@ -282,6 +283,8 @@ static int test_one_hugepage(struct io_uring *ring, int fd_in, int fd_out)
282
283
 
283
284
  ret = register_submit(ring, iov, NR_BUFS, fd_in, fd_out);
284
285
  unmap(iov, NR_BUFS, 0);
286
+ if (ret == -ENOMEM)
287
+ return T_EXIT_SKIP;
285
288
  return ret ? T_EXIT_FAIL : T_EXIT_PASS;
286
289
  }
287
290
 
@@ -296,6 +299,8 @@ static int test_multi_hugepages(struct io_uring *ring, int fd_in, int fd_out)
296
299
 
297
300
  ret = register_submit(ring, iov, NR_BUFS, fd_in, fd_out);
298
301
  unmap(iov, NR_BUFS, 0);
302
+ if (ret == -ENOMEM)
303
+ return T_EXIT_SKIP;
299
304
  return ret ? T_EXIT_FAIL : T_EXIT_PASS;
300
305
  }
301
306
 
@@ -311,6 +316,8 @@ static int test_unaligned_hugepage(struct io_uring *ring, int fd_in, int fd_out)
311
316
 
312
317
  ret = register_submit(ring, iov, NR_BUFS, fd_in, fd_out);
313
318
  unmap(iov, NR_BUFS, offset);
319
+ if (ret == -ENOMEM)
320
+ return T_EXIT_SKIP;
314
321
  return ret ? T_EXIT_FAIL : T_EXIT_PASS;
315
322
  }
316
323
 
@@ -326,6 +333,8 @@ static int test_multi_unaligned_mthps(struct io_uring *ring, int fd_in, int fd_o
326
333
 
327
334
  ret = register_submit(ring, iov, NR_BUFS, fd_in, fd_out);
328
335
  free_bufs(iov, NR_BUFS, offset);
336
+ if (ret == -ENOMEM)
337
+ return T_EXIT_SKIP;
329
338
  return ret ? T_EXIT_FAIL : T_EXIT_PASS;
330
339
  }
331
340
 
@@ -341,6 +350,8 @@ static int test_page_mixture(struct io_uring *ring, int fd_in, int fd_out, int h
341
350
 
342
351
  ret = register_submit(ring, iov, NR_BUFS, fd_in, fd_out);
343
352
  unmap(iov, NR_BUFS, 0);
353
+ if (ret == -ENOMEM)
354
+ return T_EXIT_SKIP;
344
355
  return ret ? T_EXIT_FAIL : T_EXIT_PASS;
345
356
  }
346
357
 
@@ -90,6 +90,7 @@ int main(int argc, char *argv[])
90
90
  wait(&wstat);
91
91
  if (!WEXITSTATUS(wstat))
92
92
  err = T_EXIT_PASS;
93
+ free(buf);
93
94
  } else {
94
95
  struct fanotify_event_metadata m;
95
96
  int fret;
@@ -120,6 +120,7 @@ static int __test(struct io_uring *ring, int vectored, int async,
120
120
 
121
121
  if (cqe->res == -EINVAL || cqe->res == -EOPNOTSUPP) {
122
122
  no_futex = 1;
123
+ free(futex);
123
124
  return 0;
124
125
  }
125
126
  io_uring_cqe_seen(ring, cqe);
@@ -134,6 +135,7 @@ static int __test(struct io_uring *ring, int vectored, int async,
134
135
  for (i = 0; i < nfutex; i++)
135
136
  pthread_join(threads[i], &tret);
136
137
 
138
+ free(futex);
137
139
  return 0;
138
140
  }
139
141
 
@@ -145,7 +147,7 @@ static int test(int flags, int vectored)
145
147
  ret = io_uring_queue_init(8, &ring, flags);
146
148
  if (ret)
147
149
  return ret;
148
-
150
+
149
151
  for (i = 0; i < LOOPS; i++) {
150
152
  int async_cancel = (!i % 2);
151
153
  int async_wait = !(i % 3);
@@ -166,7 +168,8 @@ static int test_order(int vectored, int async)
166
168
  {
167
169
  struct io_uring_sqe *sqe;
168
170
  struct io_uring_cqe *cqe;
169
- struct futex_waitv fw;
171
+ struct futex_waitv fw = { };
172
+ struct io_uring_sync_cancel_reg reg = { };
170
173
  struct io_uring ring;
171
174
  unsigned int *futex;
172
175
  int ret, i;
@@ -178,10 +181,8 @@ static int test_order(int vectored, int async)
178
181
  futex = malloc(sizeof(*futex));
179
182
  *futex = 0;
180
183
 
181
- fw.val = 0;
182
184
  fw.uaddr = (unsigned long) futex;
183
185
  fw.flags = FUTEX2_SIZE_U32;
184
- fw.__reserved = 0;
185
186
 
186
187
  /*
187
188
  * Submit two futex waits
@@ -241,7 +242,15 @@ static int test_order(int vectored, int async)
241
242
  return 1;
242
243
  }
243
244
 
245
+ reg.addr = 2;
246
+ ret = io_uring_register_sync_cancel(&ring, &reg);
247
+ if (ret != 1) {
248
+ fprintf(stderr, "Failed to cancel pending futex wait: %d\n", ret);
249
+ return 1;
250
+ }
251
+
244
252
  io_uring_queue_exit(&ring);
253
+ free(futex);
245
254
  return 0;
246
255
  }
247
256
 
@@ -322,6 +331,7 @@ static int test_multi_wake(int vectored)
322
331
  }
323
332
 
324
333
  io_uring_queue_exit(&ring);
334
+ free(futex);
325
335
  return 0;
326
336
  }
327
337
 
@@ -378,6 +388,7 @@ static int test_wake_zero(void)
378
388
  }
379
389
 
380
390
  io_uring_queue_exit(&ring);
391
+ free(futex);
381
392
  return 0;
382
393
  }
383
394
 
@@ -459,6 +470,7 @@ static int test_invalid(void)
459
470
  io_uring_cqe_seen(&ring, cqe);
460
471
 
461
472
  io_uring_queue_exit(&ring);
473
+ free(futex);
462
474
  return 0;
463
475
  }
464
476
 
@@ -316,3 +316,50 @@ void t_error(int status, int errnum, const char *format, ...)
316
316
  va_end(args);
317
317
  exit(status);
318
318
  }
319
+
320
+ unsigned long long mtime_since(const struct timeval *s, const struct timeval *e)
321
+ {
322
+ long long sec, usec;
323
+
324
+ sec = e->tv_sec - s->tv_sec;
325
+ usec = (e->tv_usec - s->tv_usec);
326
+ if (sec > 0 && usec < 0) {
327
+ sec--;
328
+ usec += 1000000;
329
+ }
330
+
331
+ sec *= 1000;
332
+ usec /= 1000;
333
+ return sec + usec;
334
+ }
335
+
336
+ unsigned long long mtime_since_now(struct timeval *tv)
337
+ {
338
+ struct timeval end;
339
+
340
+ gettimeofday(&end, NULL);
341
+ return mtime_since(tv, &end);
342
+ }
343
+
344
+ unsigned long long utime_since(const struct timeval *s, const struct timeval *e)
345
+ {
346
+ long long sec, usec;
347
+
348
+ sec = e->tv_sec - s->tv_sec;
349
+ usec = (e->tv_usec - s->tv_usec);
350
+ if (sec > 0 && usec < 0) {
351
+ sec--;
352
+ usec += 1000000;
353
+ }
354
+
355
+ sec *= 1000000;
356
+ return sec + usec;
357
+ }
358
+
359
+ unsigned long long utime_since_now(struct timeval *tv)
360
+ {
361
+ struct timeval end;
362
+
363
+ gettimeofday(&end, NULL);
364
+ return utime_since(tv, &end);
365
+ }
@@ -12,6 +12,7 @@ extern "C" {
12
12
  #include "liburing.h"
13
13
  #include "../src/setup.h"
14
14
  #include <arpa/inet.h>
15
+ #include <sys/time.h>
15
16
 
16
17
  enum t_setup_ret {
17
18
  T_SETUP_OK = 0,
@@ -101,6 +102,11 @@ static inline int t_io_uring_init_sqarray(unsigned entries, struct io_uring *rin
101
102
 
102
103
  void t_error(int status, int errnum, const char *format, ...);
103
104
 
105
+ unsigned long long mtime_since(const struct timeval *s, const struct timeval *e);
106
+ unsigned long long mtime_since_now(struct timeval *tv);
107
+ unsigned long long utime_since(const struct timeval *s, const struct timeval *e);
108
+ unsigned long long utime_since_now(struct timeval *tv);
109
+
104
110
  #ifdef __cplusplus
105
111
  }
106
112
  #endif
@@ -13,7 +13,6 @@
13
13
  #include <netinet/udp.h>
14
14
  #include <arpa/inet.h>
15
15
  #include <net/if.h>
16
- #include <error.h>
17
16
 
18
17
  #include "liburing.h"
19
18
  #include "helpers.h"
@@ -68,6 +67,7 @@ static int setup_ctx(struct ctx *ctx, struct q_entries *q)
68
67
  static void clean_ctx(struct ctx *ctx)
69
68
  {
70
69
  io_uring_queue_exit(&ctx->ring);
70
+ free(ctx->mem);
71
71
  }
72
72
 
73
73
  static int check_red(struct ctx *ctx, unsigned long i)
@@ -94,10 +94,12 @@ static int test(struct q_entries *q)
94
94
  int j, ret, batch;
95
95
 
96
96
  ret = setup_ctx(&ctx, q);
97
- if (ret == T_EXIT_SKIP)
97
+ if (ret == T_EXIT_SKIP) {
98
+ clean_ctx(&ctx);
98
99
  return T_EXIT_SKIP;
99
- else if (ret != T_EXIT_PASS)
100
+ } else if (ret != T_EXIT_PASS) {
100
101
  return ret;
102
+ }
101
103
 
102
104
  batch = 64;
103
105
  if (batch > q->sqes)
@@ -22,30 +22,6 @@
22
22
 
23
23
  static struct iovec *vecs;
24
24
 
25
- static unsigned long long utime_since(const struct timeval *s,
26
- const struct timeval *e)
27
- {
28
- long long sec, usec;
29
-
30
- sec = e->tv_sec - s->tv_sec;
31
- usec = (e->tv_usec - s->tv_usec);
32
- if (sec > 0 && usec < 0) {
33
- sec--;
34
- usec += 1000000;
35
- }
36
-
37
- sec *= 1000000;
38
- return sec + usec;
39
- }
40
-
41
- static unsigned long long utime_since_now(struct timeval *tv)
42
- {
43
- struct timeval end;
44
-
45
- gettimeofday(&end, NULL);
46
- return utime_since(tv, &end);
47
- }
48
-
49
25
  static int start_io(struct io_uring *ring, int fd, int do_write)
50
26
  {
51
27
  struct io_uring_sqe *sqe;