polyphony 1.5 → 1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +14 -0
- data/TODO.md +0 -4
- data/ext/polyphony/backend_io_uring.c +34 -1
- 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 +4 -7
- data/ext/polyphony/event.c +21 -0
- data/ext/polyphony/extconf.rb +20 -18
- data/ext/polyphony/fiber.c +0 -2
- data/ext/polyphony/polyphony.c +2 -0
- data/ext/polyphony/polyphony.h +5 -0
- 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/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/thread.rb +19 -27
- 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 +7 -2
- data/test/test_event.rb +10 -3
- data/test/test_ext.rb +2 -1
- data/test/test_fiber.rb +16 -4
- data/test/test_global_api.rb +13 -12
- 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 -3
- 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 +14 -3
- 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
|
+
}
|