polyphony 1.4 → 1.6
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +22 -0
- data/TODO.md +5 -14
- data/examples/pipes/http_server.rb +42 -12
- data/examples/pipes/http_server2.rb +45 -0
- data/ext/polyphony/backend_common.h +5 -0
- data/ext/polyphony/backend_io_uring.c +174 -121
- data/ext/polyphony/backend_io_uring_context.c +24 -18
- data/ext/polyphony/backend_io_uring_context.h +4 -2
- data/ext/polyphony/backend_libev.c +46 -22
- data/ext/polyphony/event.c +21 -0
- data/ext/polyphony/extconf.rb +25 -19
- data/ext/polyphony/fiber.c +0 -2
- data/ext/polyphony/pipe.c +1 -1
- data/ext/polyphony/polyphony.c +2 -20
- data/ext/polyphony/polyphony.h +5 -5
- data/ext/polyphony/ring_buffer.c +1 -0
- data/ext/polyphony/runqueue_ring_buffer.c +1 -0
- data/ext/polyphony/thread.c +63 -0
- data/ext/polyphony/win_uio.h +18 -0
- data/lib/polyphony/adapters/open3.rb +190 -0
- data/lib/polyphony/core/sync.rb +83 -13
- data/lib/polyphony/core/timer.rb +7 -25
- data/lib/polyphony/extensions/exception.rb +15 -0
- data/lib/polyphony/extensions/fiber.rb +14 -13
- data/lib/polyphony/extensions/io.rb +56 -14
- data/lib/polyphony/extensions/kernel.rb +1 -1
- data/lib/polyphony/extensions/object.rb +1 -13
- data/lib/polyphony/extensions/process.rb +76 -1
- data/lib/polyphony/extensions/socket.rb +0 -14
- data/lib/polyphony/extensions/thread.rb +19 -27
- data/lib/polyphony/extensions/timeout.rb +5 -1
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +11 -5
- data/test/helper.rb +46 -4
- data/test/open3/envutil.rb +380 -0
- data/test/open3/find_executable.rb +24 -0
- data/test/stress.rb +11 -7
- data/test/test_backend.rb +11 -4
- data/test/test_event.rb +10 -3
- data/test/test_ext.rb +16 -1
- data/test/test_fiber.rb +16 -4
- data/test/test_global_api.rb +17 -16
- data/test/test_io.rb +39 -0
- data/test/test_kernel.rb +2 -2
- data/test/test_monitor.rb +356 -0
- data/test/test_open3.rb +338 -0
- data/test/test_signal.rb +5 -1
- data/test/test_socket.rb +6 -98
- data/test/test_sync.rb +46 -0
- data/test/test_thread.rb +10 -1
- data/test/test_thread_pool.rb +5 -0
- data/test/test_throttler.rb +1 -1
- data/test/test_timer.rb +8 -2
- data/test/test_trace.rb +2 -0
- data/vendor/liburing/.github/workflows/build.yml +8 -0
- data/vendor/liburing/.gitignore +1 -0
- data/vendor/liburing/CHANGELOG +8 -0
- data/vendor/liburing/configure +17 -25
- data/vendor/liburing/debian/liburing-dev.manpages +2 -0
- data/vendor/liburing/debian/rules +2 -1
- data/vendor/liburing/examples/Makefile +2 -1
- data/vendor/liburing/examples/io_uring-udp.c +11 -3
- data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/make-debs.sh +4 -2
- data/vendor/liburing/src/Makefile +5 -5
- data/vendor/liburing/src/arch/aarch64/lib.h +1 -1
- data/vendor/liburing/src/include/liburing/io_uring.h +41 -16
- data/vendor/liburing/src/include/liburing.h +86 -11
- data/vendor/liburing/src/int_flags.h +1 -0
- data/vendor/liburing/src/liburing-ffi.map +12 -0
- data/vendor/liburing/src/liburing.map +8 -0
- data/vendor/liburing/src/register.c +7 -2
- data/vendor/liburing/src/setup.c +373 -81
- data/vendor/liburing/test/232c93d07b74.c +3 -3
- data/vendor/liburing/test/Makefile +10 -3
- data/vendor/liburing/test/accept.c +2 -1
- data/vendor/liburing/test/buf-ring.c +35 -75
- data/vendor/liburing/test/connect-rep.c +204 -0
- data/vendor/liburing/test/coredump.c +59 -0
- data/vendor/liburing/test/fallocate.c +9 -0
- data/vendor/liburing/test/fd-pass.c +34 -3
- data/vendor/liburing/test/file-verify.c +27 -6
- data/vendor/liburing/test/helpers.c +3 -1
- data/vendor/liburing/test/io_uring_register.c +25 -28
- data/vendor/liburing/test/io_uring_setup.c +1 -1
- data/vendor/liburing/test/poll-cancel-all.c +29 -5
- data/vendor/liburing/test/poll-race-mshot.c +6 -22
- data/vendor/liburing/test/read-write.c +53 -0
- data/vendor/liburing/test/recv-msgall.c +21 -23
- data/vendor/liburing/test/reg-fd-only.c +55 -0
- data/vendor/liburing/test/reg-hint.c +56 -0
- data/vendor/liburing/test/regbuf-merge.c +91 -0
- data/vendor/liburing/test/ringbuf-read.c +2 -10
- data/vendor/liburing/test/send_recvmsg.c +5 -16
- data/vendor/liburing/test/shutdown.c +2 -1
- data/vendor/liburing/test/socket-io-cmd.c +215 -0
- data/vendor/liburing/test/socket-rw-eagain.c +2 -1
- data/vendor/liburing/test/socket-rw-offset.c +2 -1
- data/vendor/liburing/test/socket-rw.c +2 -1
- data/vendor/liburing/test/timeout.c +276 -0
- data/vendor/liburing/test/xattr.c +38 -25
- metadata +20 -7
- 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
|
-
|
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
|
-
|
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
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
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",
|
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
|
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",
|
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
|
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. */
|
@@ -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,
|
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
|
-
|
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
|
-
|
79
|
-
if (
|
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
|
-
|
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
|
-
|
181
|
-
if (
|
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
|
-
|
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
|
55
|
-
|
56
|
-
msg
|
57
|
-
|
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
|
-
|
125
|
+
pthread_barrier_wait(&rd->barrier);
|
124
126
|
ret = 0;
|
125
127
|
goto err;
|
126
128
|
} else if (ret < 0) {
|
127
|
-
|
129
|
+
pthread_barrier_wait(&rd->barrier);
|
128
130
|
goto err;
|
129
131
|
}
|
130
132
|
|
131
|
-
ret = recv_prep(&ring, &iov, &sock, rd
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
+
}
|