polyphony 1.5 → 1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +14 -0
  4. data/TODO.md +0 -4
  5. data/ext/polyphony/backend_io_uring.c +34 -1
  6. data/ext/polyphony/backend_io_uring_context.c +24 -18
  7. data/ext/polyphony/backend_io_uring_context.h +4 -2
  8. data/ext/polyphony/backend_libev.c +4 -7
  9. data/ext/polyphony/event.c +21 -0
  10. data/ext/polyphony/extconf.rb +20 -18
  11. data/ext/polyphony/fiber.c +0 -2
  12. data/ext/polyphony/polyphony.c +2 -0
  13. data/ext/polyphony/polyphony.h +5 -0
  14. data/ext/polyphony/ring_buffer.c +1 -0
  15. data/ext/polyphony/runqueue_ring_buffer.c +1 -0
  16. data/ext/polyphony/thread.c +63 -0
  17. data/lib/polyphony/adapters/open3.rb +190 -0
  18. data/lib/polyphony/core/sync.rb +83 -13
  19. data/lib/polyphony/core/timer.rb +7 -25
  20. data/lib/polyphony/extensions/exception.rb +15 -0
  21. data/lib/polyphony/extensions/fiber.rb +14 -13
  22. data/lib/polyphony/extensions/io.rb +56 -14
  23. data/lib/polyphony/extensions/kernel.rb +1 -1
  24. data/lib/polyphony/extensions/object.rb +1 -13
  25. data/lib/polyphony/extensions/process.rb +76 -1
  26. data/lib/polyphony/extensions/thread.rb +19 -27
  27. data/lib/polyphony/version.rb +1 -1
  28. data/lib/polyphony.rb +11 -5
  29. data/test/helper.rb +46 -4
  30. data/test/open3/envutil.rb +380 -0
  31. data/test/open3/find_executable.rb +24 -0
  32. data/test/stress.rb +11 -7
  33. data/test/test_backend.rb +7 -2
  34. data/test/test_event.rb +10 -3
  35. data/test/test_ext.rb +2 -1
  36. data/test/test_fiber.rb +16 -4
  37. data/test/test_global_api.rb +13 -12
  38. data/test/test_io.rb +39 -0
  39. data/test/test_kernel.rb +2 -2
  40. data/test/test_monitor.rb +356 -0
  41. data/test/test_open3.rb +338 -0
  42. data/test/test_signal.rb +5 -1
  43. data/test/test_socket.rb +6 -3
  44. data/test/test_sync.rb +46 -0
  45. data/test/test_thread.rb +10 -1
  46. data/test/test_thread_pool.rb +5 -0
  47. data/test/test_throttler.rb +1 -1
  48. data/test/test_timer.rb +8 -2
  49. data/test/test_trace.rb +2 -0
  50. data/vendor/liburing/.github/workflows/build.yml +8 -0
  51. data/vendor/liburing/.gitignore +1 -0
  52. data/vendor/liburing/CHANGELOG +8 -0
  53. data/vendor/liburing/configure +17 -25
  54. data/vendor/liburing/debian/liburing-dev.manpages +2 -0
  55. data/vendor/liburing/debian/rules +2 -1
  56. data/vendor/liburing/examples/Makefile +2 -1
  57. data/vendor/liburing/examples/io_uring-udp.c +11 -3
  58. data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
  59. data/vendor/liburing/liburing.spec +1 -1
  60. data/vendor/liburing/make-debs.sh +4 -2
  61. data/vendor/liburing/src/Makefile +5 -5
  62. data/vendor/liburing/src/arch/aarch64/lib.h +1 -1
  63. data/vendor/liburing/src/include/liburing/io_uring.h +41 -16
  64. data/vendor/liburing/src/include/liburing.h +86 -11
  65. data/vendor/liburing/src/int_flags.h +1 -0
  66. data/vendor/liburing/src/liburing-ffi.map +12 -0
  67. data/vendor/liburing/src/liburing.map +8 -0
  68. data/vendor/liburing/src/register.c +7 -2
  69. data/vendor/liburing/src/setup.c +373 -81
  70. data/vendor/liburing/test/232c93d07b74.c +3 -3
  71. data/vendor/liburing/test/Makefile +10 -3
  72. data/vendor/liburing/test/accept.c +2 -1
  73. data/vendor/liburing/test/buf-ring.c +35 -75
  74. data/vendor/liburing/test/connect-rep.c +204 -0
  75. data/vendor/liburing/test/coredump.c +59 -0
  76. data/vendor/liburing/test/fallocate.c +9 -0
  77. data/vendor/liburing/test/fd-pass.c +34 -3
  78. data/vendor/liburing/test/file-verify.c +27 -6
  79. data/vendor/liburing/test/helpers.c +3 -1
  80. data/vendor/liburing/test/io_uring_register.c +25 -28
  81. data/vendor/liburing/test/io_uring_setup.c +1 -1
  82. data/vendor/liburing/test/poll-cancel-all.c +29 -5
  83. data/vendor/liburing/test/poll-race-mshot.c +6 -22
  84. data/vendor/liburing/test/read-write.c +53 -0
  85. data/vendor/liburing/test/recv-msgall.c +21 -23
  86. data/vendor/liburing/test/reg-fd-only.c +55 -0
  87. data/vendor/liburing/test/reg-hint.c +56 -0
  88. data/vendor/liburing/test/regbuf-merge.c +91 -0
  89. data/vendor/liburing/test/ringbuf-read.c +2 -10
  90. data/vendor/liburing/test/send_recvmsg.c +5 -16
  91. data/vendor/liburing/test/shutdown.c +2 -1
  92. data/vendor/liburing/test/socket-io-cmd.c +215 -0
  93. data/vendor/liburing/test/socket-rw-eagain.c +2 -1
  94. data/vendor/liburing/test/socket-rw-offset.c +2 -1
  95. data/vendor/liburing/test/socket-rw.c +2 -1
  96. data/vendor/liburing/test/timeout.c +276 -0
  97. data/vendor/liburing/test/xattr.c +38 -25
  98. metadata +14 -3
  99. data/vendor/liburing/test/timeout-overflow.c +0 -204
@@ -32,7 +32,7 @@ static rlim_t mlock_limit;
32
32
  static int devnull;
33
33
 
34
34
  static int expect_fail(int fd, unsigned int opcode, void *arg,
35
- unsigned int nr_args, int error)
35
+ unsigned int nr_args, int error, int error2)
36
36
  {
37
37
  int ret;
38
38
 
@@ -55,8 +55,8 @@ static int expect_fail(int fd, unsigned int opcode, void *arg,
55
55
  return 1;
56
56
  }
57
57
 
58
- if (ret != error) {
59
- fprintf(stderr, "expected %d, got %d\n", error, ret);
58
+ if (ret != error && (error2 && ret != error2)) {
59
+ fprintf(stderr, "expected %d/%d, got %d\n", error, error2, ret);
60
60
  return 1;
61
61
  }
62
62
  return 0;
@@ -195,8 +195,7 @@ static int test_max_fds(int uring_fd)
195
195
  status = 0;
196
196
  ret = io_uring_register(uring_fd, IORING_UNREGISTER_FILES, 0, 0);
197
197
  if (ret < 0) {
198
- ret = errno;
199
- errno = ret;
198
+ errno = -ret;
200
199
  perror("io_uring_register UNREGISTER_FILES");
201
200
  exit(1);
202
201
  }
@@ -230,22 +229,20 @@ static int test_memlock_exceeded(int fd)
230
229
 
231
230
  while (iov.iov_len) {
232
231
  ret = io_uring_register(fd, IORING_REGISTER_BUFFERS, &iov, 1);
233
- if (ret < 0) {
234
- if (errno == ENOMEM) {
235
- iov.iov_len /= 2;
236
- continue;
237
- }
238
- if (errno == EFAULT) {
239
- free(buf);
240
- return 0;
241
- }
242
- fprintf(stderr, "expected success or EFAULT, got %d\n", errno);
232
+ if (ret == -ENOMEM) {
233
+ iov.iov_len /= 2;
234
+ continue;
235
+ } else if (ret == -EFAULT) {
236
+ free(buf);
237
+ return 0;
238
+ } else if (ret) {
239
+ fprintf(stderr, "expected success or EFAULT, got %d\n", ret);
243
240
  free(buf);
244
241
  return 1;
245
242
  }
246
243
  ret = io_uring_register(fd, IORING_UNREGISTER_BUFFERS, NULL, 0);
247
244
  if (ret != 0) {
248
- fprintf(stderr, "error: unregister failed with %d\n", errno);
245
+ fprintf(stderr, "error: unregister failed with %d\n", ret);
249
246
  free(buf);
250
247
  return 1;
251
248
  }
@@ -277,15 +274,15 @@ static int test_iovec_nr(int fd)
277
274
  iovs[i].iov_len = pagesize;
278
275
  }
279
276
 
280
- status |= expect_fail(fd, IORING_REGISTER_BUFFERS, iovs, nr, -EINVAL);
277
+ status |= expect_fail(fd, IORING_REGISTER_BUFFERS, iovs, nr, -EINVAL, 0);
281
278
 
282
279
  /* reduce to UIO_MAXIOV */
283
280
  nr = UIO_MAXIOV;
284
281
  ret = io_uring_register(fd, IORING_REGISTER_BUFFERS, iovs, nr);
285
- if (ret && (errno == ENOMEM || errno == EPERM) && geteuid()) {
282
+ if ((ret == -ENOMEM || ret == -EPERM) && geteuid()) {
286
283
  fprintf(stderr, "can't register large iovec for regular users, skip\n");
287
284
  } else if (ret != 0) {
288
- fprintf(stderr, "expected success, got %d\n", errno);
285
+ fprintf(stderr, "expected success, got %d\n", ret);
289
286
  status = 1;
290
287
  } else {
291
288
  io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 0, 0);
@@ -308,12 +305,12 @@ static int test_iovec_size(int fd)
308
305
  /* NULL pointer for base */
309
306
  iov.iov_base = 0;
310
307
  iov.iov_len = 4096;
311
- status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT);
308
+ status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT, 0);
312
309
 
313
310
  /* valid base, 0 length */
314
311
  iov.iov_base = &buf;
315
312
  iov.iov_len = 0;
316
- status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT);
313
+ status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT, 0);
317
314
 
318
315
  /* valid base, length exceeds size */
319
316
  /* this requires an unampped page directly after buf */
@@ -324,7 +321,7 @@ static int test_iovec_size(int fd)
324
321
  assert(ret == 0);
325
322
  iov.iov_base = buf;
326
323
  iov.iov_len = 2 * pagesize;
327
- status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT);
324
+ status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT, 0);
328
325
  munmap(buf, pagesize);
329
326
 
330
327
  /* huge page */
@@ -372,7 +369,7 @@ static int test_iovec_size(int fd)
372
369
  status = 1;
373
370
  iov.iov_base = buf;
374
371
  iov.iov_len = 2*1024*1024;
375
- status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EOPNOTSUPP);
372
+ status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT, -EOPNOTSUPP);
376
373
  munmap(buf, 2*1024*1024);
377
374
 
378
375
  /* bump up against the soft limit and make sure we get EFAULT
@@ -410,7 +407,7 @@ static int ioring_poll(struct io_uring *ring, int fd, int fixed)
410
407
  return 1;
411
408
  }
412
409
  ret = 0;
413
- if (cqe->res != POLLOUT) {
410
+ if (!(cqe->res & POLLOUT)) {
414
411
  fprintf(stderr, "io_uring_wait_cqe: expected 0x%.8x, got 0x%.8x\n",
415
412
  POLLOUT, cqe->res);
416
413
  ret = 1;
@@ -442,7 +439,7 @@ static int test_poll_ringfd(void)
442
439
  * fail, because the kernel does not allow registering of the
443
440
  * ring_fd.
444
441
  */
445
- status |= expect_fail(fd, IORING_REGISTER_FILES, &fd, 1, -EBADF);
442
+ status |= expect_fail(fd, IORING_REGISTER_FILES, &fd, 1, -EBADF, 0);
446
443
 
447
444
  /* tear down queue */
448
445
  io_uring_queue_exit(&ring);
@@ -475,14 +472,14 @@ int main(int argc, char **argv)
475
472
  }
476
473
 
477
474
  /* invalid fd */
478
- status |= expect_fail(-1, 0, NULL, 0, -EBADF);
475
+ status |= expect_fail(-1, 0, NULL, 0, -EBADF, 0);
479
476
  /* valid fd that is not an io_uring fd */
480
- status |= expect_fail(devnull, 0, NULL, 0, -EOPNOTSUPP);
477
+ status |= expect_fail(devnull, 0, NULL, 0, -EOPNOTSUPP, 0);
481
478
 
482
479
  /* invalid opcode */
483
480
  memset(&p, 0, sizeof(p));
484
481
  fd = new_io_uring(1, &p);
485
- ret = expect_fail(fd, ~0U, NULL, 0, -EINVAL);
482
+ ret = expect_fail(fd, ~0U, NULL, 0, -EINVAL, 0);
486
483
  if (ret) {
487
484
  /* if this succeeds, tear down the io_uring instance
488
485
  * and start clean for the next test. */
@@ -17,7 +17,7 @@
17
17
  #include "liburing.h"
18
18
  #include "helpers.h"
19
19
 
20
- #include "../syscall.h"
20
+ #include "../src/syscall.h"
21
21
 
22
22
  /* bogus: setup returns a valid fd on success... expect can't predict the
23
23
  fd we'll get, so this really only takes 1 parameter: error */
@@ -14,11 +14,22 @@
14
14
 
15
15
  static int no_cancel_flags;
16
16
 
17
- static int test1(struct io_uring *ring, int *fd)
17
+ static int test1(struct io_uring *ring, int *fd, int fixed)
18
18
  {
19
19
  struct io_uring_sqe *sqe;
20
20
  struct io_uring_cqe *cqe;
21
- int ret, i;
21
+ int ret, i, __fd = fd[0];
22
+
23
+ if (fixed)
24
+ __fd = 0;
25
+
26
+ if (fixed) {
27
+ ret = io_uring_register_files(ring, fd, 1);
28
+ if (ret) {
29
+ fprintf(stderr, "failed file register %d\n", ret);
30
+ return 1;
31
+ }
32
+ }
22
33
 
23
34
  for (i = 0; i < 8; i++) {
24
35
  sqe = io_uring_get_sqe(ring);
@@ -27,8 +38,10 @@ static int test1(struct io_uring *ring, int *fd)
27
38
  return 1;
28
39
  }
29
40
 
30
- io_uring_prep_poll_add(sqe, fd[0], POLLIN);
41
+ io_uring_prep_poll_add(sqe, __fd, POLLIN);
31
42
  sqe->user_data = i + 1;
43
+ if (fixed)
44
+ sqe->flags |= IOSQE_FIXED_FILE;
32
45
  }
33
46
 
34
47
  ret = io_uring_submit(ring);
@@ -51,7 +64,9 @@ static int test1(struct io_uring *ring, int *fd)
51
64
  */
52
65
  io_uring_prep_cancel(sqe, 0, IORING_ASYNC_CANCEL_ALL);
53
66
  sqe->cancel_flags |= IORING_ASYNC_CANCEL_FD;
54
- sqe->fd = fd[0];
67
+ if (fixed)
68
+ sqe->cancel_flags |= IORING_ASYNC_CANCEL_FD_FIXED;
69
+ sqe->fd = __fd;
55
70
  sqe->user_data = 100;
56
71
 
57
72
  ret = io_uring_submit(ring);
@@ -93,6 +108,9 @@ static int test1(struct io_uring *ring, int *fd)
93
108
  io_uring_cqe_seen(ring, cqe);
94
109
  }
95
110
 
111
+ if (fixed)
112
+ io_uring_unregister_files(ring);
113
+
96
114
  return 0;
97
115
  }
98
116
 
@@ -442,7 +460,7 @@ int main(int argc, char *argv[])
442
460
  return 1;
443
461
  }
444
462
 
445
- ret = test1(&ring, fd);
463
+ ret = test1(&ring, fd, 0);
446
464
  if (ret) {
447
465
  fprintf(stderr, "test1 failed\n");
448
466
  return ret;
@@ -450,6 +468,12 @@ int main(int argc, char *argv[])
450
468
  if (no_cancel_flags)
451
469
  return 0;
452
470
 
471
+ ret = test1(&ring, fd, 1);
472
+ if (ret) {
473
+ fprintf(stderr, "test1 fixed failed\n");
474
+ return ret;
475
+ }
476
+
453
477
  ret = test2(&ring, fd);
454
478
  if (ret) {
455
479
  fprintf(stderr, "test2 failed\n");
@@ -49,7 +49,6 @@ static void *thread(void *data)
49
49
 
50
50
  static int test(struct io_uring *ring, struct data *d)
51
51
  {
52
- struct io_uring_buf_reg reg = { };
53
52
  struct io_uring_buf_ring *br;
54
53
  struct io_uring_sqe *sqe;
55
54
  struct io_uring_cqe *cqe;
@@ -67,16 +66,9 @@ static int test(struct io_uring *ring, struct data *d)
67
66
 
68
67
  if (posix_memalign((void **) &buf, 16384, BUF_SIZE * NREQS))
69
68
  return T_EXIT_FAIL;
70
- if (posix_memalign((void **) &br, 16384, sizeof(struct io_uring_buf) * NREQS))
71
- return T_EXIT_FAIL;
72
-
73
- io_uring_buf_ring_init(br);
74
- reg.ring_addr = (unsigned long) br;
75
- reg.ring_entries = NREQS;
76
- reg.bgid = 1;
77
69
 
78
- ret = io_uring_register_buf_ring(ring, &reg, 0);
79
- if (ret) {
70
+ br = io_uring_setup_buf_ring(ring, NREQS, 1, 0, &ret);
71
+ if (!br) {
80
72
  if (ret == -EINVAL) {
81
73
  no_buf_ring = 1;
82
74
  return T_EXIT_SKIP;
@@ -143,7 +135,7 @@ static int test(struct io_uring *ring, struct data *d)
143
135
 
144
136
  pthread_join(t, &ret2);
145
137
  free(buf);
146
- free(br);
138
+ io_uring_free_buf_ring(ring, br, NREQS, 1);
147
139
  close(fd[0]);
148
140
  close(fd[1]);
149
141
  return T_EXIT_PASS;
@@ -151,7 +143,6 @@ static int test(struct io_uring *ring, struct data *d)
151
143
 
152
144
  static int test_mshot(struct io_uring *ring, struct data *d)
153
145
  {
154
- struct io_uring_buf_reg reg = { };
155
146
  struct io_uring_buf_ring *br;
156
147
  struct io_uring_sqe *sqe;
157
148
  struct io_uring_cqe *cqe;
@@ -169,16 +160,9 @@ static int test_mshot(struct io_uring *ring, struct data *d)
169
160
 
170
161
  if (posix_memalign((void *) &buf, 16384, BUF_SIZE * NREQS))
171
162
  return T_EXIT_FAIL;
172
- if (posix_memalign((void *) &br, 16384, sizeof(struct io_uring_buf) * NREQS))
173
- return T_EXIT_FAIL;
174
-
175
- io_uring_buf_ring_init(br);
176
- reg.ring_addr = (unsigned long) br;
177
- reg.ring_entries = NREQS;
178
- reg.bgid = 1;
179
163
 
180
- ret = io_uring_register_buf_ring(ring, &reg, 0);
181
- if (ret) {
164
+ br = io_uring_setup_buf_ring(ring, NREQS, 1, 0, &ret);
165
+ if (!br) {
182
166
  fprintf(stderr, "buf ring reg %d\n", ret);
183
167
  return T_EXIT_FAIL;
184
168
  }
@@ -245,8 +229,8 @@ static int test_mshot(struct io_uring *ring, struct data *d)
245
229
  }
246
230
 
247
231
  pthread_join(t, &ret2);
232
+ io_uring_free_buf_ring(ring, br, NREQS, 1);
248
233
  free(buf);
249
- free(br);
250
234
  close(fd[0]);
251
235
  close(fd[1]);
252
236
  return T_EXIT_PASS;
@@ -637,6 +637,53 @@ static int test_rem_buf(int batch, int sqe_flags)
637
637
  return ret;
638
638
  }
639
639
 
640
+ static int test_rem_buf_single(int to_rem)
641
+ {
642
+ struct io_uring_sqe *sqe;
643
+ struct io_uring_cqe *cqe;
644
+ struct io_uring ring;
645
+ int ret, expected;
646
+ int bgid = 1;
647
+
648
+ if (no_buf_select)
649
+ return 0;
650
+
651
+ ret = io_uring_queue_init(64, &ring, 0);
652
+ if (ret) {
653
+ fprintf(stderr, "ring create failed: %d\n", ret);
654
+ return 1;
655
+ }
656
+
657
+ ret = provide_buffers_iovec(&ring, bgid);
658
+ if (ret)
659
+ return ret;
660
+
661
+ expected = (to_rem > BUFFERS) ? BUFFERS : to_rem;
662
+
663
+ sqe = io_uring_get_sqe(&ring);
664
+ io_uring_prep_remove_buffers(sqe, to_rem, bgid);
665
+
666
+ ret = io_uring_submit(&ring);
667
+ if (ret != 1) {
668
+ fprintf(stderr, "submit: %d\n", ret);
669
+ return -1;
670
+ }
671
+
672
+ ret = io_uring_wait_cqe(&ring, &cqe);
673
+ if (ret) {
674
+ fprintf(stderr, "wait_cqe=%d\n", ret);
675
+ return 1;
676
+ }
677
+ if (cqe->res != expected) {
678
+ fprintf(stderr, "cqe->res=%d, expected=%d\n", cqe->res, expected);
679
+ return 1;
680
+ }
681
+ io_uring_cqe_seen(&ring, cqe);
682
+
683
+ io_uring_queue_exit(&ring);
684
+ return ret;
685
+ }
686
+
640
687
  static int test_io_link(const char *file)
641
688
  {
642
689
  const int nr_links = 100;
@@ -950,6 +997,12 @@ int main(int argc, char *argv[])
950
997
  }
951
998
  }
952
999
 
1000
+ ret = test_rem_buf_single(BUFFERS + 1);
1001
+ if (ret) {
1002
+ fprintf(stderr, "test_rem_buf_single(BUFFERS + 1) failed\n");
1003
+ goto err;
1004
+ }
1005
+
953
1006
  if (fname != argv[1])
954
1007
  unlink(fname);
955
1008
  return 0;
@@ -18,14 +18,18 @@
18
18
  #define MAX_MSG 128
19
19
  #define HOST "127.0.0.1"
20
20
  static __be16 bind_port;
21
+ struct recv_data {
22
+ pthread_barrier_t barrier;
23
+ int use_recvmsg;
24
+ struct msghdr msg;
25
+ };
21
26
 
22
27
  static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock,
23
- int use_recvmsg)
28
+ struct recv_data *rd)
24
29
  {
25
30
  struct sockaddr_in saddr;
26
31
  struct io_uring_sqe *sqe;
27
32
  int sockfd, ret, val;
28
- struct msghdr msg = { };
29
33
 
30
34
  memset(&saddr, 0, sizeof(saddr));
31
35
  saddr.sin_family = AF_INET;
@@ -47,14 +51,17 @@ static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock,
47
51
  bind_port = saddr.sin_port;
48
52
 
49
53
  sqe = io_uring_get_sqe(ring);
50
- if (!use_recvmsg) {
54
+ if (!rd->use_recvmsg) {
51
55
  io_uring_prep_recv(sqe, sockfd, iov->iov_base, iov->iov_len,
52
56
  MSG_WAITALL);
53
57
  } else {
54
- msg.msg_namelen = sizeof(struct sockaddr_in);
55
- msg.msg_iov = iov;
56
- msg.msg_iovlen = 1;
57
- io_uring_prep_recvmsg(sqe, sockfd, &msg, MSG_WAITALL);
58
+ struct msghdr *msg = &rd->msg;
59
+
60
+ memset(msg, 0, sizeof(*msg));
61
+ msg->msg_namelen = sizeof(struct sockaddr_in);
62
+ msg->msg_iov = iov;
63
+ msg->msg_iovlen = 1;
64
+ io_uring_prep_recvmsg(sqe, sockfd, msg, MSG_WAITALL);
58
65
  }
59
66
 
60
67
  sqe->user_data = 2;
@@ -101,11 +108,6 @@ err:
101
108
  return 1;
102
109
  }
103
110
 
104
- struct recv_data {
105
- pthread_mutex_t mutex;
106
- int use_recvmsg;
107
- };
108
-
109
111
  static void *recv_fn(void *data)
110
112
  {
111
113
  struct recv_data *rd = data;
@@ -120,20 +122,20 @@ static void *recv_fn(void *data)
120
122
 
121
123
  ret = t_create_ring_params(1, &ring, &p);
122
124
  if (ret == T_SETUP_SKIP) {
123
- pthread_mutex_unlock(&rd->mutex);
125
+ pthread_barrier_wait(&rd->barrier);
124
126
  ret = 0;
125
127
  goto err;
126
128
  } else if (ret < 0) {
127
- pthread_mutex_unlock(&rd->mutex);
129
+ pthread_barrier_wait(&rd->barrier);
128
130
  goto err;
129
131
  }
130
132
 
131
- ret = recv_prep(&ring, &iov, &sock, rd->use_recvmsg);
133
+ ret = recv_prep(&ring, &iov, &sock, rd);
132
134
  if (ret) {
133
135
  fprintf(stderr, "recv_prep failed: %d\n", ret);
134
136
  goto err;
135
137
  }
136
- pthread_mutex_unlock(&rd->mutex);
138
+ pthread_barrier_wait(&rd->barrier);
137
139
  ret = do_recv(&ring);
138
140
  close(sock);
139
141
  io_uring_queue_exit(&ring);
@@ -217,28 +219,24 @@ err:
217
219
 
218
220
  static int test(int use_recvmsg)
219
221
  {
220
- pthread_mutexattr_t attr;
221
222
  pthread_t recv_thread;
222
223
  struct recv_data rd;
223
224
  int ret;
224
225
  void *retval;
225
226
 
226
- pthread_mutexattr_init(&attr);
227
- pthread_mutexattr_setpshared(&attr, 1);
228
- pthread_mutex_init(&rd.mutex, &attr);
229
- pthread_mutex_lock(&rd.mutex);
227
+ pthread_barrier_init(&rd.barrier, NULL, 2);
230
228
  rd.use_recvmsg = use_recvmsg;
231
229
 
232
230
  ret = pthread_create(&recv_thread, NULL, recv_fn, &rd);
233
231
  if (ret) {
234
232
  fprintf(stderr, "Thread create failed: %d\n", ret);
235
- pthread_mutex_unlock(&rd.mutex);
236
233
  return 1;
237
234
  }
238
235
 
239
- pthread_mutex_lock(&rd.mutex);
236
+ pthread_barrier_wait(&rd.barrier);
240
237
  do_send();
241
238
  pthread_join(recv_thread, &retval);
239
+ pthread_barrier_destroy(&rd.barrier);
242
240
  return (intptr_t)retval;
243
241
  }
244
242
 
@@ -0,0 +1,55 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Test io_uring_setup with IORING_SETUP_REGISTERED_FD_ONLY
4
+ *
5
+ */
6
+ #include <stdio.h>
7
+
8
+ #include "helpers.h"
9
+
10
+ int main(int argc, char *argv[])
11
+ {
12
+ struct io_uring ring;
13
+ unsigned values[2];
14
+ int ret;
15
+
16
+ if (argc > 1)
17
+ return T_EXIT_SKIP;
18
+
19
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_REGISTERED_FD_ONLY | IORING_SETUP_NO_MMAP);
20
+ if (ret == -EINVAL)
21
+ return T_EXIT_SKIP;
22
+ else if (ret) {
23
+ fprintf(stderr, "ring setup failed\n");
24
+ return T_EXIT_FAIL;
25
+ }
26
+
27
+ ret = io_uring_register_ring_fd(&ring);
28
+ if (ret != -EEXIST) {
29
+ fprintf(stderr, "registering already-registered ring fd should fail\n");
30
+ goto err;
31
+ }
32
+
33
+ ret = io_uring_close_ring_fd(&ring);
34
+ if (ret != -EBADF) {
35
+ fprintf(stderr, "closing already-closed ring fd should fail\n");
36
+ goto err;
37
+ }
38
+
39
+ /* Test a simple io_uring_register operation expected to work.
40
+ * io_uring_register_iowq_max_workers is arbitrary.
41
+ */
42
+ values[0] = values[1] = 0;
43
+ ret = io_uring_register_iowq_max_workers(&ring, values);
44
+ if (ret || (values[0] == 0 && values[1] == 0)) {
45
+ fprintf(stderr, "io_uring_register operation failed after closing ring fd\n");
46
+ goto err;
47
+ }
48
+
49
+ io_uring_queue_exit(&ring);
50
+ return T_EXIT_PASS;
51
+
52
+ err:
53
+ io_uring_queue_exit(&ring);
54
+ return T_EXIT_FAIL;
55
+ }
@@ -0,0 +1,56 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Test alloc hint sanity after unregistering the file table
4
+ */
5
+ #include <stdio.h>
6
+ #include <unistd.h>
7
+ #include <sys/socket.h>
8
+
9
+ #include "liburing.h"
10
+ #include "helpers.h"
11
+
12
+ int main(int argc, char *argv[])
13
+ {
14
+ struct io_uring_sqe *sqe;
15
+ struct io_uring_cqe *cqe;
16
+ struct io_uring ring;
17
+ int ret;
18
+
19
+ if (argc > 1)
20
+ return T_EXIT_SKIP;
21
+
22
+ io_uring_queue_init(1, &ring, 0);
23
+
24
+ ret = io_uring_register_files_sparse(&ring, 16);
25
+ if (ret) {
26
+ if (ret == -EINVAL)
27
+ return T_EXIT_SKIP;
28
+
29
+ fprintf(stderr, "Failed to register file table: %d\n", ret);
30
+ return T_EXIT_FAIL;
31
+ }
32
+ io_uring_unregister_files(&ring);
33
+
34
+ sqe = io_uring_get_sqe(&ring);
35
+ io_uring_prep_socket_direct_alloc(sqe, AF_UNIX, SOCK_DGRAM, 0, 0);
36
+
37
+ ret = io_uring_submit(&ring);
38
+ if (ret != 1) {
39
+ fprintf(stderr, "submit %d\n", ret);
40
+ return T_EXIT_FAIL;
41
+ }
42
+
43
+ ret = io_uring_wait_cqe(&ring, &cqe);
44
+ if (ret) {
45
+ fprintf(stderr, "wait cqe: %d\n", ret);
46
+ return T_EXIT_FAIL;
47
+ }
48
+
49
+ if (cqe->res != -ENFILE) {
50
+ fprintf(stderr, "Bad CQE res: %d\n", cqe->res);
51
+ return T_EXIT_FAIL;
52
+ }
53
+
54
+ io_uring_cqe_seen(&ring, cqe);
55
+ return T_EXIT_PASS;
56
+ }
@@ -0,0 +1,91 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ // autogenerated by syzkaller (https://github.com/google/syzkaller)
3
+
4
+ #include <endian.h>
5
+ #include <stdint.h>
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+ #include <sys/mman.h>
10
+ #include <sys/syscall.h>
11
+ #include <sys/types.h>
12
+ #include <unistd.h>
13
+
14
+ #include "helpers.h"
15
+
16
+ #ifndef __NR_io_uring_register
17
+ #define __NR_io_uring_register 427
18
+ #endif
19
+ #ifndef __NR_io_uring_setup
20
+ #define __NR_io_uring_setup 425
21
+ #endif
22
+
23
+ #define SIZEOF_IO_URING_SQE 64
24
+ #define SIZEOF_IO_URING_CQE 16
25
+ #define SQ_HEAD_OFFSET 0
26
+ #define SQ_TAIL_OFFSET 64
27
+ #define SQ_RING_MASK_OFFSET 256
28
+ #define SQ_RING_ENTRIES_OFFSET 264
29
+ #define SQ_FLAGS_OFFSET 276
30
+ #define SQ_DROPPED_OFFSET 272
31
+ #define CQ_HEAD_OFFSET 128
32
+ #define CQ_TAIL_OFFSET 192
33
+ #define CQ_RING_MASK_OFFSET 260
34
+ #define CQ_RING_ENTRIES_OFFSET 268
35
+ #define CQ_RING_OVERFLOW_OFFSET 284
36
+ #define CQ_FLAGS_OFFSET 280
37
+ #define CQ_CQES_OFFSET 320
38
+
39
+ static long syz_io_uring_setup(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5)
40
+ {
41
+ uint32_t entries = (uint32_t)a0;
42
+ struct io_uring_params* setup_params = (struct io_uring_params*)a1;
43
+ void* vma1 = (void*)a2;
44
+ void* vma2 = (void*)a3;
45
+ void** ring_ptr_out = (void**)a4;
46
+ void** sqes_ptr_out = (void**)a5;
47
+ uint32_t fd_io_uring = syscall(__NR_io_uring_setup, entries, setup_params);
48
+ uint32_t sq_ring_sz = setup_params->sq_off.array + setup_params->sq_entries * sizeof(uint32_t);
49
+ uint32_t cq_ring_sz = setup_params->cq_off.cqes + setup_params->cq_entries * SIZEOF_IO_URING_CQE;
50
+ uint32_t ring_sz = sq_ring_sz > cq_ring_sz ? sq_ring_sz : cq_ring_sz;
51
+ *ring_ptr_out = mmap(vma1, ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, IORING_OFF_SQ_RING);
52
+ uint32_t sqes_sz = setup_params->sq_entries * SIZEOF_IO_URING_SQE;
53
+ *sqes_ptr_out = mmap(vma2, sqes_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, IORING_OFF_SQES);
54
+ return fd_io_uring;
55
+ }
56
+
57
+ static uint64_t r[1] = {0xffffffffffffffff};
58
+
59
+ int main(int argc, char *argv[])
60
+ {
61
+ intptr_t res = 0;
62
+
63
+ if (argc > 1)
64
+ return T_EXIT_SKIP;
65
+
66
+ mmap((void *) 0x1ffff000ul, 0x1000ul, PROT_NONE,
67
+ MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0ul);
68
+ mmap((void *) 0x20000000ul, 0x1000000ul, PROT_READ|PROT_WRITE|PROT_EXEC,
69
+ MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0ul);
70
+ mmap((void *) 0x21000000ul, 0x1000ul, PROT_NONE,
71
+ MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0ul);
72
+
73
+ *(uint32_t*)0x20000684 = 0;
74
+ *(uint32_t*)0x20000688 = 0;
75
+ *(uint32_t*)0x2000068c = 0;
76
+ *(uint32_t*)0x20000690 = 0;
77
+ *(uint32_t*)0x20000698 = -1;
78
+ memset((void*)0x2000069c, 0, 12);
79
+
80
+ res = syz_io_uring_setup(0x2fd6, 0x20000680, 0x20ffd000, 0x20ffc000,
81
+ 0x20000700, 0x20000740);
82
+ if (res != -1)
83
+ r[0] = res;
84
+
85
+ *(uint64_t*)0x20002840 = 0;
86
+ *(uint64_t*)0x20002848 = 0;
87
+ *(uint64_t*)0x20002850 = 0x20000840;
88
+ *(uint64_t*)0x20002858 = 0x1000;
89
+ syscall(__NR_io_uring_register, r[0], 0ul, 0x20002840ul, 2ul);
90
+ return T_EXIT_PASS;
91
+ }