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
@@ -102,31 +102,6 @@ static int wait_nr(int nr)
102
102
  return 0;
103
103
  }
104
104
 
105
- static unsigned long long mtime_since(const struct timeval *s,
106
- const struct timeval *e)
107
- {
108
- long long sec, usec;
109
-
110
- sec = e->tv_sec - s->tv_sec;
111
- usec = (e->tv_usec - s->tv_usec);
112
- if (sec > 0 && usec < 0) {
113
- sec--;
114
- usec += 1000000;
115
- }
116
-
117
- sec *= 1000;
118
- usec /= 1000;
119
- return sec + usec;
120
- }
121
-
122
- static unsigned long long mtime_since_now(struct timeval *tv)
123
- {
124
- struct timeval end;
125
-
126
- gettimeofday(&end, NULL);
127
- return mtime_since(tv, &end);
128
- }
129
-
130
105
  static int test_reuse(int argc, char *argv[], int split, int async)
131
106
  {
132
107
  struct thread_data data;
@@ -162,6 +137,8 @@ static int test_reuse(int argc, char *argv[], int split, int async)
162
137
  if (do_unlink)
163
138
  unlink(fname1);
164
139
  if (fd1 < 0) {
140
+ if (errno == EPERM || errno == EACCES)
141
+ return T_EXIT_SKIP;
165
142
  perror("open fname1");
166
143
  goto err;
167
144
  }
@@ -211,7 +188,6 @@ static int test_reuse(int argc, char *argv[], int split, int async)
211
188
  err:
212
189
  io_uring_queue_exit(&ring);
213
190
  return 1;
214
-
215
191
  }
216
192
 
217
193
  int main(int argc, char *argv[])
@@ -225,6 +201,8 @@ int main(int argc, char *argv[])
225
201
  async = (i & 2) != 0;
226
202
 
227
203
  ret = test_reuse(argc, argv, split, async);
204
+ if (ret == T_EXIT_SKIP)
205
+ continue;
228
206
  if (ret) {
229
207
  fprintf(stderr, "test_reuse %d %d failed\n", split, async);
230
208
  return ret;
@@ -11,7 +11,6 @@
11
11
 
12
12
  #include "liburing.h"
13
13
 
14
-
15
14
  static int do_symlinkat(struct io_uring *ring, const char *oldname, const char *newname)
16
15
  {
17
16
  int ret;
@@ -105,6 +104,18 @@ int main(int argc, char *argv[])
105
104
  goto err1;
106
105
  }
107
106
 
107
+ ret = do_symlinkat(&ring, target, (const char *) (uintptr_t) 0x1234);
108
+ if (ret != -EFAULT) {
109
+ fprintf(stderr, "test_symlinkat bad target failed: %d\n", ret);
110
+ goto err1;
111
+ }
112
+
113
+ ret = do_symlinkat(&ring, (const char *) (uintptr_t) 0x1234, target);
114
+ if (ret != -EFAULT) {
115
+ fprintf(stderr, "test_symlinkat bad source failed: %d\n", ret);
116
+ goto err1;
117
+ }
118
+
108
119
  out:
109
120
  unlinkat(AT_FDCWD, linkname, 0);
110
121
  io_uring_queue_exit(&ring);
@@ -13,9 +13,9 @@
13
13
  #include "liburing.h"
14
14
  #include "helpers.h"
15
15
 
16
- static int no_sync_cancel;
16
+ static int no_sync_cancel, no_sync_cancel_op;
17
17
 
18
- static int test_sync_cancel_timeout(struct io_uring *ring, int async)
18
+ static int test_sync_cancel_timeout(struct io_uring *ring, int async, int by_op)
19
19
  {
20
20
  struct io_uring_sync_cancel_reg reg = { };
21
21
  struct io_uring_sqe *sqe;
@@ -43,9 +43,15 @@ static int test_sync_cancel_timeout(struct io_uring *ring, int async)
43
43
 
44
44
  usleep(10000);
45
45
 
46
- reg.addr = 0x89;
46
+ reg.flags = IORING_ASYNC_CANCEL_OP;
47
+ reg.opcode = IORING_OP_READ;
47
48
  reg.timeout.tv_nsec = 1;
48
49
  ret = io_uring_register_sync_cancel(ring, &reg);
50
+ /* earlier kernels had sync cancel, but not per-op */
51
+ if (ret == -EINVAL) {
52
+ no_sync_cancel_op = 1;
53
+ return 0;
54
+ }
49
55
  if (async) {
50
56
  /* we expect -ETIME here, but can race and get 0 */
51
57
  if (ret != -ETIME && ret != 0) {
@@ -80,7 +86,7 @@ static int test_sync_cancel_timeout(struct io_uring *ring, int async)
80
86
  }
81
87
 
82
88
  static int test_sync_cancel(struct io_uring *ring, int async, int nr_all,
83
- int use_fd)
89
+ int use_fd, int by_op)
84
90
  {
85
91
  struct io_uring_sync_cancel_reg reg = { };
86
92
  struct io_uring_sqe *sqe;
@@ -168,7 +174,7 @@ int main(int argc, char *argv[])
168
174
  else if (ret != T_SETUP_OK)
169
175
  return ret;
170
176
 
171
- ret = test_sync_cancel(&ring, 0, 0, 0);
177
+ ret = test_sync_cancel(&ring, 0, 0, 0, 0);
172
178
  if (ret) {
173
179
  fprintf(stderr, "test_sync_cancel 0 0 0 failed\n");
174
180
  return T_EXIT_FAIL;
@@ -176,56 +182,84 @@ int main(int argc, char *argv[])
176
182
  if (no_sync_cancel)
177
183
  return T_EXIT_SKIP;
178
184
 
179
- ret = test_sync_cancel(&ring, 1, 0, 0);
185
+ ret = test_sync_cancel(&ring, 0, 0, 0, 1);
180
186
  if (ret) {
181
- fprintf(stderr, "test_sync_cancel 1 0 0 failed\n");
187
+ fprintf(stderr, "test_sync_cancel 0 0 1 failed\n");
182
188
  return T_EXIT_FAIL;
183
189
  }
184
190
 
185
- ret = test_sync_cancel(&ring, 0, 1, 0);
191
+ ret = test_sync_cancel(&ring, 1, 0, 0, 0);
186
192
  if (ret) {
187
- fprintf(stderr, "test_sync_cancel 0 1 0 failed\n");
193
+ fprintf(stderr, "test_sync_cancel 1 0 0 0 failed\n");
188
194
  return T_EXIT_FAIL;
189
195
  }
190
196
 
191
- ret = test_sync_cancel(&ring, 1, 1, 0);
197
+ ret = test_sync_cancel(&ring, 1, 0, 0, 1);
192
198
  if (ret) {
193
- fprintf(stderr, "test_sync_cancel 1 1 0 failed\n");
199
+ fprintf(stderr, "test_sync_cancel 1 0 0 1 failed\n");
194
200
  return T_EXIT_FAIL;
195
201
  }
196
202
 
197
- ret = test_sync_cancel(&ring, 0, 0, 1);
203
+
204
+ ret = test_sync_cancel(&ring, 0, 1, 0, 0);
198
205
  if (ret) {
199
- fprintf(stderr, "test_sync_cancel 0 0 1 failed\n");
206
+ fprintf(stderr, "test_sync_cancel 0 1 0 0 failed\n");
207
+ return T_EXIT_FAIL;
208
+ }
209
+
210
+ ret = test_sync_cancel(&ring, 0, 1, 0, 1);
211
+ if (ret) {
212
+ fprintf(stderr, "test_sync_cancel 0 1 0 1 failed\n");
213
+ return T_EXIT_FAIL;
214
+ }
215
+
216
+
217
+ ret = test_sync_cancel(&ring, 1, 1, 0, 0);
218
+ if (ret) {
219
+ fprintf(stderr, "test_sync_cancel 1 1 0 0 failed\n");
220
+ return T_EXIT_FAIL;
221
+ }
222
+
223
+ ret = test_sync_cancel(&ring, 0, 0, 1, 0);
224
+ if (ret) {
225
+ fprintf(stderr, "test_sync_cancel 0 0 1 0 failed\n");
226
+ return T_EXIT_FAIL;
227
+ }
228
+
229
+ ret = test_sync_cancel(&ring, 1, 0, 1, 0);
230
+ if (ret) {
231
+ fprintf(stderr, "test_sync_cancel 1 0 1 0 failed\n");
200
232
  return T_EXIT_FAIL;
201
233
  }
202
234
 
203
- ret = test_sync_cancel(&ring, 1, 0, 1);
235
+ ret = test_sync_cancel(&ring, 0, 1, 1, 0);
204
236
  if (ret) {
205
- fprintf(stderr, "test_sync_cancel 1 0 1 failed\n");
237
+ fprintf(stderr, "test_sync_cancel 0 1 1 0 failed\n");
206
238
  return T_EXIT_FAIL;
207
239
  }
208
240
 
209
- ret = test_sync_cancel(&ring, 0, 1, 1);
241
+ ret = test_sync_cancel(&ring, 1, 1, 1, 0);
210
242
  if (ret) {
211
- fprintf(stderr, "test_sync_cancel 0 1 1 failed\n");
243
+ fprintf(stderr, "test_sync_cancel 1 1 1 0 failed\n");
212
244
  return T_EXIT_FAIL;
213
245
  }
214
246
 
215
- ret = test_sync_cancel(&ring, 1, 1, 1);
247
+ ret = test_sync_cancel_timeout(&ring, 0, 0);
216
248
  if (ret) {
217
- fprintf(stderr, "test_sync_cancel 1 1 1 failed\n");
249
+ fprintf(stderr, "test_sync_cancel_timeout 0 0\n");
218
250
  return T_EXIT_FAIL;
219
251
  }
252
+ if (no_sync_cancel_op)
253
+ return T_EXIT_PASS;
220
254
 
221
- ret = test_sync_cancel_timeout(&ring, 0);
255
+ ret = test_sync_cancel_timeout(&ring, 0, 1);
222
256
  if (ret) {
223
- fprintf(stderr, "test_sync_cancel_timeout 0\n");
257
+ fprintf(stderr, "test_sync_cancel_timeout 0 1\n");
224
258
  return T_EXIT_FAIL;
225
259
  }
226
260
 
227
261
  /* must be last, leaves request */
228
- ret = test_sync_cancel_timeout(&ring, 1);
262
+ ret = test_sync_cancel_timeout(&ring, 1, 0);
229
263
  if (ret) {
230
264
  fprintf(stderr, "test_sync_cancel_timeout 1\n");
231
265
  return T_EXIT_FAIL;
@@ -102,6 +102,8 @@ int main(int argc, char *argv[])
102
102
  if (do_unlink)
103
103
  unlink(fname);
104
104
  if (fd < 0) {
105
+ if (errno == EPERM || errno == EACCES)
106
+ goto skip;
105
107
  perror("open");
106
108
  return 1;
107
109
  }
@@ -140,4 +142,7 @@ int main(int argc, char *argv[])
140
142
  err:
141
143
  free_g_buf();
142
144
  return 1;
145
+ skip:
146
+ free_g_buf();
147
+ return T_EXIT_SKIP;
143
148
  }
@@ -8,6 +8,7 @@
8
8
  #include <unistd.h>
9
9
  #include <pthread.h>
10
10
  #include "liburing.h"
11
+ #include "helpers.h"
11
12
 
12
13
  #define TIMEOUT_MSEC 200
13
14
  #define TIMEOUT_SEC 10
@@ -22,32 +23,6 @@ static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec)
22
23
  ts->tv_nsec = (msec % 1000) * 1000000;
23
24
  }
24
25
 
25
- static unsigned long long mtime_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 *= 1000;
38
- usec /= 1000;
39
- return sec + usec;
40
- }
41
-
42
- static unsigned long long mtime_since_now(struct timeval *tv)
43
- {
44
- struct timeval end;
45
-
46
- gettimeofday(&end, NULL);
47
- return mtime_since(tv, &end);
48
- }
49
-
50
-
51
26
  static int test_return_before_timeout(struct io_uring *ring)
52
27
  {
53
28
  struct io_uring_cqe *cqe;
@@ -29,31 +29,6 @@ static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec)
29
29
  ts->tv_nsec = (msec % 1000) * 1000000;
30
30
  }
31
31
 
32
- static unsigned long long mtime_since(const struct timeval *s,
33
- const struct timeval *e)
34
- {
35
- long long sec, usec;
36
-
37
- sec = e->tv_sec - s->tv_sec;
38
- usec = (e->tv_usec - s->tv_usec);
39
- if (sec > 0 && usec < 0) {
40
- sec--;
41
- usec += 1000000;
42
- }
43
-
44
- sec *= 1000;
45
- usec /= 1000;
46
- return sec + usec;
47
- }
48
-
49
- static unsigned long long mtime_since_now(struct timeval *tv)
50
- {
51
- struct timeval end;
52
-
53
- gettimeofday(&end, NULL);
54
- return mtime_since(tv, &end);
55
- }
56
-
57
32
  /*
58
33
  * Test that we return to userspace if a timeout triggers, even if we
59
34
  * don't satisfy the number of events asked for.
@@ -980,6 +955,7 @@ static int test_update_timeout(struct io_uring *ring, unsigned long ms,
980
955
  struct io_uring_cqe *cqe;
981
956
  struct __kernel_timespec ts, ts_upd;
982
957
  unsigned long long exp_ms, base_ms = 10000;
958
+ bool update_ealready = false;
983
959
  struct timeval tv;
984
960
  int ret, i, nr = 2;
985
961
  __u32 mode = abs ? IORING_TIMEOUT_ABS : 0;
@@ -1042,6 +1018,16 @@ static int test_update_timeout(struct io_uring *ring, unsigned long ms,
1042
1018
  }
1043
1019
  break;
1044
1020
  case 2:
1021
+ /*
1022
+ * We should not be hitting this case, but for
1023
+ * a kernel with PREEMPT_RT, even an instant attempt
1024
+ * to remove a timer will return that the timer is
1025
+ * already running... Deal with it.
1026
+ */
1027
+ if (cqe->res == -EALREADY) {
1028
+ update_ealready = true;
1029
+ break;
1030
+ }
1045
1031
  if (cqe->res != 0) {
1046
1032
  fprintf(stderr, "%s: got %d, wanted %d\n",
1047
1033
  __FUNCTION__, cqe->res,
@@ -1062,7 +1048,7 @@ static int test_update_timeout(struct io_uring *ring, unsigned long ms,
1062
1048
  }
1063
1049
 
1064
1050
  exp_ms = mtime_since_now(&tv);
1065
- if (exp_ms >= base_ms / 2) {
1051
+ if (!update_ealready && exp_ms >= base_ms / 2) {
1066
1052
  fprintf(stderr, "too long, timeout wasn't updated\n");
1067
1053
  goto err;
1068
1054
  }
@@ -1242,14 +1228,19 @@ static int test_timeout_link_cancel(void)
1242
1228
  exit(0);
1243
1229
  }
1244
1230
 
1245
- if (waitpid(p, &wstatus, 0) == (pid_t)-1) {
1246
- perror("waitpid()");
1247
- return 1;
1248
- }
1249
- if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) {
1250
- fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus));
1251
- return 1;
1252
- }
1231
+ do {
1232
+ if (waitpid(p, &wstatus, 0) == (pid_t)-1) {
1233
+ perror("waitpid()");
1234
+ return 1;
1235
+ }
1236
+ if (!WIFEXITED(wstatus))
1237
+ continue;
1238
+ if (WEXITSTATUS(wstatus)) {
1239
+ fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus));
1240
+ return 1;
1241
+ }
1242
+ break;
1243
+ } while (1);
1253
1244
 
1254
1245
  for (i = 0; i < 2; ++i) {
1255
1246
  ret = io_uring_wait_cqe(&ring, &cqe);
@@ -13,6 +13,87 @@
13
13
 
14
14
  #include "liburing.h"
15
15
 
16
+ static int test_rmdir(struct io_uring *ring)
17
+ {
18
+ struct io_uring_cqe *cqe;
19
+ struct io_uring_sqe *sqe;
20
+ char buf[32];
21
+ int ret;
22
+
23
+ sprintf(buf, ".tmp.dir.%d", getpid());
24
+ if (mkdir(buf, 0755) < 0) {
25
+ perror("mkdir");
26
+ return 1;
27
+ }
28
+
29
+ sqe = io_uring_get_sqe(ring);
30
+ if (!sqe) {
31
+ fprintf(stderr, "get sqe failed\n");
32
+ goto err;
33
+ }
34
+ io_uring_prep_unlink(sqe, buf, AT_REMOVEDIR);
35
+
36
+ ret = io_uring_submit(ring);
37
+ if (ret <= 0) {
38
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
39
+ goto err;
40
+ }
41
+
42
+ ret = io_uring_wait_cqe(ring, &cqe);
43
+ if (ret < 0) {
44
+ fprintf(stderr, "wait completion %d\n", ret);
45
+ goto err;
46
+ }
47
+ ret = cqe->res;
48
+ io_uring_cqe_seen(ring, cqe);
49
+
50
+ if (!ret) {
51
+ struct stat sb;
52
+
53
+ if (!stat(buf, &sb)) {
54
+ fprintf(stderr, "dir unlinked but still there\n");
55
+ goto err;
56
+ }
57
+ }
58
+ unlink(buf);
59
+ return ret;
60
+ err:
61
+ unlink(buf);
62
+ return 1;
63
+ }
64
+
65
+ static int test_unlink_badaddr(struct io_uring *ring)
66
+ {
67
+ const char *old = (const char *) (uintptr_t) 0x1234;
68
+ struct io_uring_cqe *cqe;
69
+ struct io_uring_sqe *sqe;
70
+ int ret;
71
+
72
+ sqe = io_uring_get_sqe(ring);
73
+ if (!sqe) {
74
+ fprintf(stderr, "get sqe failed\n");
75
+ goto err;
76
+ }
77
+ io_uring_prep_unlink(sqe, old, 0);
78
+
79
+ ret = io_uring_submit(ring);
80
+ if (ret <= 0) {
81
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
82
+ goto err;
83
+ }
84
+
85
+ ret = io_uring_wait_cqe(ring, &cqe);
86
+ if (ret < 0) {
87
+ fprintf(stderr, "wait completion %d\n", ret);
88
+ goto err;
89
+ }
90
+ ret = cqe->res;
91
+ io_uring_cqe_seen(ring, cqe);
92
+ return ret;
93
+ err:
94
+ return 1;
95
+ }
96
+
16
97
  static int test_unlink(struct io_uring *ring, const char *old)
17
98
  {
18
99
  struct io_uring_cqe *cqe;
@@ -25,7 +106,7 @@ static int test_unlink(struct io_uring *ring, const char *old)
25
106
  goto err;
26
107
  }
27
108
  io_uring_prep_unlink(sqe, old, 0);
28
-
109
+
29
110
  ret = io_uring_submit(ring);
30
111
  if (ret <= 0) {
31
112
  fprintf(stderr, "sqe submit failed: %d\n", ret);
@@ -105,6 +186,18 @@ int main(int argc, char *argv[])
105
186
  return 1;
106
187
  }
107
188
 
189
+ ret = test_unlink_badaddr(&ring);
190
+ if (ret != -EFAULT) {
191
+ fprintf(stderr, "badaddr unlink got %s\n", strerror(-ret));
192
+ return 1;
193
+ }
194
+
195
+ ret = test_rmdir(&ring);
196
+ if (ret) {
197
+ fprintf(stderr, "rmdir failed: %s\n", strerror(-ret));
198
+ return 1;
199
+ }
200
+
108
201
  return 0;
109
202
  err:
110
203
  unlink(buf);