uringmachine 0.19.1 → 0.21.0
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/.github/workflows/test.yml +3 -4
- data/CHANGELOG.md +32 -1
- data/TODO.md +0 -39
- data/examples/bm_fileno.rb +33 -0
- data/examples/bm_mutex.rb +85 -0
- data/examples/bm_mutex_single.rb +33 -0
- data/examples/bm_queue.rb +29 -29
- data/examples/bm_send.rb +2 -5
- data/examples/bm_snooze.rb +20 -42
- data/examples/bm_write.rb +4 -1
- data/examples/fiber_scheduler_demo.rb +15 -51
- data/examples/fiber_scheduler_fork.rb +24 -0
- data/examples/nc_ssl.rb +71 -0
- data/ext/um/extconf.rb +5 -15
- data/ext/um/um.c +310 -74
- data/ext/um/um.h +66 -29
- data/ext/um/um_async_op.c +1 -1
- data/ext/um/um_async_op_class.c +2 -2
- data/ext/um/um_buffer.c +1 -1
- data/ext/um/um_class.c +178 -31
- data/ext/um/um_const.c +51 -3
- data/ext/um/um_mutex_class.c +1 -1
- data/ext/um/um_op.c +37 -0
- data/ext/um/um_queue_class.c +1 -1
- data/ext/um/um_stream.c +5 -5
- data/ext/um/um_stream_class.c +3 -0
- data/ext/um/um_sync.c +28 -39
- data/ext/um/um_utils.c +59 -19
- data/grant-2025/journal.md +353 -0
- data/grant-2025/tasks.md +135 -0
- data/lib/uringmachine/fiber_scheduler.rb +316 -57
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +6 -0
- data/test/test_fiber_scheduler.rb +640 -0
- data/test/test_stream.rb +2 -2
- data/test/test_um.rb +722 -54
- data/uringmachine.gemspec +5 -5
- data/vendor/liburing/.github/workflows/ci.yml +94 -1
- data/vendor/liburing/.github/workflows/test_build.c +9 -0
- data/vendor/liburing/configure +27 -0
- data/vendor/liburing/examples/Makefile +6 -0
- data/vendor/liburing/examples/helpers.c +8 -0
- data/vendor/liburing/examples/helpers.h +5 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/Makefile +9 -3
- data/vendor/liburing/src/include/liburing/barrier.h +11 -5
- data/vendor/liburing/src/include/liburing/io_uring/query.h +41 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +51 -0
- data/vendor/liburing/src/include/liburing/sanitize.h +16 -4
- data/vendor/liburing/src/include/liburing.h +458 -121
- data/vendor/liburing/src/liburing-ffi.map +16 -0
- data/vendor/liburing/src/liburing.map +8 -0
- data/vendor/liburing/src/sanitize.c +4 -1
- data/vendor/liburing/src/setup.c +7 -4
- data/vendor/liburing/test/232c93d07b74.c +4 -16
- data/vendor/liburing/test/Makefile +15 -1
- data/vendor/liburing/test/accept.c +2 -13
- data/vendor/liburing/test/bind-listen.c +175 -13
- data/vendor/liburing/test/conn-unreach.c +132 -0
- data/vendor/liburing/test/fd-pass.c +32 -7
- data/vendor/liburing/test/fdinfo.c +39 -12
- data/vendor/liburing/test/fifo-futex-poll.c +114 -0
- data/vendor/liburing/test/fifo-nonblock-read.c +1 -12
- data/vendor/liburing/test/futex.c +1 -1
- data/vendor/liburing/test/helpers.c +99 -2
- data/vendor/liburing/test/helpers.h +9 -0
- data/vendor/liburing/test/io_uring_passthrough.c +6 -12
- data/vendor/liburing/test/mock_file.c +379 -0
- data/vendor/liburing/test/mock_file.h +47 -0
- data/vendor/liburing/test/nop.c +2 -2
- data/vendor/liburing/test/nop32-overflow.c +150 -0
- data/vendor/liburing/test/nop32.c +126 -0
- data/vendor/liburing/test/pipe.c +166 -0
- data/vendor/liburing/test/poll-race-mshot.c +13 -1
- data/vendor/liburing/test/read-write.c +4 -4
- data/vendor/liburing/test/recv-mshot-fair.c +81 -34
- data/vendor/liburing/test/recvsend_bundle.c +1 -1
- data/vendor/liburing/test/resize-rings.c +2 -0
- data/vendor/liburing/test/ring-query.c +322 -0
- data/vendor/liburing/test/ringbuf-loop.c +87 -0
- data/vendor/liburing/test/ringbuf-read.c +4 -4
- data/vendor/liburing/test/runtests.sh +2 -2
- data/vendor/liburing/test/send-zerocopy.c +43 -5
- data/vendor/liburing/test/send_recv.c +103 -32
- data/vendor/liburing/test/shutdown.c +2 -12
- data/vendor/liburing/test/socket-nb.c +3 -14
- data/vendor/liburing/test/socket-rw-eagain.c +2 -12
- data/vendor/liburing/test/socket-rw-offset.c +2 -12
- data/vendor/liburing/test/socket-rw.c +2 -12
- data/vendor/liburing/test/sqe-mixed-bad-wrap.c +87 -0
- data/vendor/liburing/test/sqe-mixed-nop.c +82 -0
- data/vendor/liburing/test/sqe-mixed-uring_cmd.c +153 -0
- data/vendor/liburing/test/timestamp.c +56 -19
- data/vendor/liburing/test/vec-regbuf.c +2 -4
- data/vendor/liburing/test/wq-aff.c +7 -0
- metadata +37 -15
|
@@ -57,7 +57,7 @@ static void fdinfo_read(struct io_uring *ring)
|
|
|
57
57
|
|
|
58
58
|
static int __test_io(const char *file, struct io_uring *ring, int write,
|
|
59
59
|
int buffered, int sqthread, int fixed, int nonvec,
|
|
60
|
-
int buf_select, int seq, int exp_len)
|
|
60
|
+
int buf_select, int seq, int exp_len, int mixed)
|
|
61
61
|
{
|
|
62
62
|
struct io_uring_sqe *sqe;
|
|
63
63
|
struct io_uring_cqe *cqe;
|
|
@@ -66,9 +66,9 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
|
|
|
66
66
|
off_t offset;
|
|
67
67
|
|
|
68
68
|
#ifdef VERBOSE
|
|
69
|
-
fprintf(stdout, "%s: start %d/%d/%d/%d/%d: ", __FUNCTION__, write,
|
|
69
|
+
fprintf(stdout, "%s: start %d/%d/%d/%d/%d/%d: ", __FUNCTION__, write,
|
|
70
70
|
buffered, sqthread,
|
|
71
|
-
fixed, nonvec);
|
|
71
|
+
fixed, nonvec, mixed);
|
|
72
72
|
#endif
|
|
73
73
|
if (write)
|
|
74
74
|
open_flags = O_WRONLY;
|
|
@@ -107,6 +107,17 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
|
|
|
107
107
|
|
|
108
108
|
offset = 0;
|
|
109
109
|
for (i = 0; i < BUFFERS; i++) {
|
|
110
|
+
if (mixed && i & 1) {
|
|
111
|
+
sqe = io_uring_get_sqe128(ring);
|
|
112
|
+
if (!sqe) {
|
|
113
|
+
fprintf(stderr, "sqe get failed\n");
|
|
114
|
+
goto err;
|
|
115
|
+
}
|
|
116
|
+
io_uring_prep_nop128(sqe);
|
|
117
|
+
sqe->user_data = i;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
110
121
|
sqe = io_uring_get_sqe(ring);
|
|
111
122
|
if (!sqe) {
|
|
112
123
|
fprintf(stderr, "sqe get failed\n");
|
|
@@ -167,12 +178,17 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
|
|
|
167
178
|
offset += BS;
|
|
168
179
|
}
|
|
169
180
|
|
|
181
|
+
__io_uring_flush_sq(ring);
|
|
170
182
|
fdinfo_read(ring);
|
|
171
183
|
|
|
172
184
|
ret = io_uring_submit(ring);
|
|
173
|
-
if (ret != BUFFERS) {
|
|
185
|
+
if (!mixed && ret != BUFFERS) {
|
|
174
186
|
fprintf(stderr, "submit got %d, wanted %d\n", ret, BUFFERS);
|
|
175
187
|
goto err;
|
|
188
|
+
} else if (mixed && ret != BUFFERS + (BUFFERS >> 1)) {
|
|
189
|
+
fprintf(stderr, "submit got %d, wanted %d\n", ret,
|
|
190
|
+
BUFFERS + (BUFFERS >> 1));
|
|
191
|
+
goto err;
|
|
176
192
|
}
|
|
177
193
|
|
|
178
194
|
for (i = 0; i < 10; i++) {
|
|
@@ -186,7 +202,13 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
|
|
|
186
202
|
fprintf(stderr, "wait_cqe=%d\n", ret);
|
|
187
203
|
goto err;
|
|
188
204
|
}
|
|
189
|
-
if (cqe->
|
|
205
|
+
if (mixed && cqe->user_data & 1) {
|
|
206
|
+
if (cqe->user_data > 32) {
|
|
207
|
+
fprintf(stderr, "cqe user data %lld, max expected %d\n",
|
|
208
|
+
cqe->user_data, BUFFERS - 1);
|
|
209
|
+
goto err;
|
|
210
|
+
}
|
|
211
|
+
} else if (cqe->res == -EINVAL && nonvec) {
|
|
190
212
|
if (!warned) {
|
|
191
213
|
fprintf(stdout, "Non-vectored IO not "
|
|
192
214
|
"supported, skipping\n");
|
|
@@ -252,15 +274,19 @@ err:
|
|
|
252
274
|
return 1;
|
|
253
275
|
}
|
|
254
276
|
static int test_io(const char *file, int write, int buffered, int sqthread,
|
|
255
|
-
int fixed, int nonvec, int exp_len)
|
|
277
|
+
int fixed, int nonvec, int exp_len, int mixed)
|
|
256
278
|
{
|
|
257
279
|
struct io_uring ring;
|
|
258
|
-
int ret, ring_flags = 0;
|
|
280
|
+
int ret, ring_flags = 0, entries = 64;
|
|
259
281
|
|
|
260
282
|
if (sqthread)
|
|
261
283
|
ring_flags = IORING_SETUP_SQPOLL;
|
|
284
|
+
if (mixed) {
|
|
285
|
+
ring_flags |= IORING_SETUP_SQE_MIXED;
|
|
286
|
+
entries = 128;
|
|
287
|
+
}
|
|
262
288
|
|
|
263
|
-
ret = t_create_ring(
|
|
289
|
+
ret = t_create_ring(entries, &ring, ring_flags);
|
|
264
290
|
if (ret == T_SETUP_SKIP)
|
|
265
291
|
return 0;
|
|
266
292
|
if (ret != T_SETUP_OK) {
|
|
@@ -269,7 +295,7 @@ static int test_io(const char *file, int write, int buffered, int sqthread,
|
|
|
269
295
|
}
|
|
270
296
|
|
|
271
297
|
ret = __test_io(file, &ring, write, buffered, sqthread, fixed, nonvec,
|
|
272
|
-
0, 0, exp_len);
|
|
298
|
+
0, 0, exp_len, mixed);
|
|
273
299
|
io_uring_queue_exit(&ring);
|
|
274
300
|
return ret;
|
|
275
301
|
}
|
|
@@ -379,17 +405,18 @@ int main(int argc, char *argv[])
|
|
|
379
405
|
vecs = t_create_buffers(BUFFERS, BS);
|
|
380
406
|
|
|
381
407
|
/* if we don't have nonvec read, skip testing that */
|
|
382
|
-
nr = has_nonvec_read() ?
|
|
408
|
+
nr = has_nonvec_read() ? 64 : 32;
|
|
383
409
|
|
|
384
410
|
for (i = 0; i < nr; i++) {
|
|
385
411
|
int write = (i & 1) != 0;
|
|
386
412
|
int buffered = (i & 2) != 0;
|
|
387
413
|
int sqthread = (i & 4) != 0;
|
|
388
414
|
int fixed = (i & 8) != 0;
|
|
389
|
-
int
|
|
415
|
+
int mixed = (i & 16) != 0;
|
|
416
|
+
int nonvec = (i & 32) != 0;
|
|
390
417
|
|
|
391
418
|
ret = test_io(fname, write, buffered, sqthread, fixed, nonvec,
|
|
392
|
-
BS);
|
|
419
|
+
BS, mixed);
|
|
393
420
|
if (ret == T_EXIT_SKIP)
|
|
394
421
|
continue;
|
|
395
422
|
if (ret) {
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/* SPDX-License-Identifier: MIT */
|
|
2
|
+
/*
|
|
3
|
+
* Description: Run a failing futex wait command followed up a POLL_ADD
|
|
4
|
+
* on a fifo.
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
#include <stdio.h>
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#include <linux/futex.h>
|
|
10
|
+
#include <linux/poll.h>
|
|
11
|
+
#include <unistd.h>
|
|
12
|
+
|
|
13
|
+
#include "liburing.h"
|
|
14
|
+
#include "helpers.h"
|
|
15
|
+
|
|
16
|
+
#ifndef FUTEX2_SIZE_U32
|
|
17
|
+
#define FUTEX2_SIZE_U32 0x02
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
int main(int argc, char *argv[])
|
|
21
|
+
{
|
|
22
|
+
struct io_uring_sqe *sqe;
|
|
23
|
+
struct io_uring_cqe *cqe;
|
|
24
|
+
struct io_uring ring;
|
|
25
|
+
int ret, pipe;
|
|
26
|
+
|
|
27
|
+
if (argc > 1)
|
|
28
|
+
return T_EXIT_SKIP;
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* Setup a FIFO for polling. FIFOs are interesting because they end
|
|
32
|
+
* up using two wait queue entries for poll, hitting double poll
|
|
33
|
+
* in io_uring.
|
|
34
|
+
*/
|
|
35
|
+
ret = mkfifo("fifo", 0644);
|
|
36
|
+
if (ret < 0) {
|
|
37
|
+
perror("mkfifo");
|
|
38
|
+
return 1;
|
|
39
|
+
}
|
|
40
|
+
pipe = open("fifo", O_RDWR);
|
|
41
|
+
if (pipe < 0) {
|
|
42
|
+
perror("open fifo");
|
|
43
|
+
ret = T_EXIT_FAIL;
|
|
44
|
+
goto err;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
ret = io_uring_queue_init(64, &ring, 0);
|
|
48
|
+
if (ret) {
|
|
49
|
+
ret = T_EXIT_FAIL;
|
|
50
|
+
goto err;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* Submit invalid futex wait, will error inline.
|
|
55
|
+
*/
|
|
56
|
+
sqe = io_uring_get_sqe(&ring);
|
|
57
|
+
io_uring_prep_futex_wait(sqe, NULL, 0, FUTEX_BITSET_MATCH_ANY, FUTEX2_SIZE_U32, 0);
|
|
58
|
+
sqe->user_data = 1;
|
|
59
|
+
io_uring_submit(&ring);
|
|
60
|
+
|
|
61
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
62
|
+
if (ret) {
|
|
63
|
+
fprintf(stderr, "wait %d \n", ret);
|
|
64
|
+
ret = T_EXIT_FAIL;
|
|
65
|
+
goto err_ring;
|
|
66
|
+
}
|
|
67
|
+
if (cqe->res != -EFAULT) {
|
|
68
|
+
if (cqe->res == -EINVAL) {
|
|
69
|
+
ret = T_EXIT_SKIP;
|
|
70
|
+
goto err_ring;
|
|
71
|
+
}
|
|
72
|
+
fprintf(stderr, "Unexpected futex return: %d\n", cqe->res);
|
|
73
|
+
ret = T_EXIT_FAIL;
|
|
74
|
+
goto err_ring;
|
|
75
|
+
}
|
|
76
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
77
|
+
|
|
78
|
+
ret = io_uring_register_files(&ring, &pipe, 1);
|
|
79
|
+
if (ret < 0) {
|
|
80
|
+
fprintf(stderr, "io_uring register files failed \n");
|
|
81
|
+
ret = T_EXIT_FAIL;
|
|
82
|
+
goto err_ring;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/*
|
|
86
|
+
* Submit poll request for POLLIN on the fifo
|
|
87
|
+
*/
|
|
88
|
+
sqe = io_uring_get_sqe(&ring);
|
|
89
|
+
io_uring_prep_poll_add(sqe, 0, POLLIN);
|
|
90
|
+
sqe->flags |= IOSQE_FIXED_FILE;
|
|
91
|
+
sqe->user_data = 2;
|
|
92
|
+
io_uring_submit(&ring);
|
|
93
|
+
|
|
94
|
+
/*
|
|
95
|
+
* Trigger the poll request
|
|
96
|
+
*/
|
|
97
|
+
ret = write(pipe, "FIFO test\n", 10);
|
|
98
|
+
if (ret < 0)
|
|
99
|
+
perror("fifo write");
|
|
100
|
+
|
|
101
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
102
|
+
if (ret) {
|
|
103
|
+
fprintf(stderr, "wait %d \n", ret);
|
|
104
|
+
ret = T_EXIT_FAIL;
|
|
105
|
+
}
|
|
106
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
107
|
+
err_ring:
|
|
108
|
+
io_uring_queue_exit(&ring);
|
|
109
|
+
err:
|
|
110
|
+
if (pipe != -1)
|
|
111
|
+
close(pipe);
|
|
112
|
+
unlink("fifo");
|
|
113
|
+
return ret;
|
|
114
|
+
}
|
|
@@ -18,7 +18,6 @@ int main(int argc, char *argv[])
|
|
|
18
18
|
struct io_uring ring;
|
|
19
19
|
char buf[32];
|
|
20
20
|
int fds[2];
|
|
21
|
-
int flags;
|
|
22
21
|
int ret;
|
|
23
22
|
|
|
24
23
|
io_uring_queue_init(1, &ring, 0);
|
|
@@ -28,17 +27,7 @@ int main(int argc, char *argv[])
|
|
|
28
27
|
return T_EXIT_FAIL;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
if (flags < 0) {
|
|
33
|
-
perror("fcntl get");
|
|
34
|
-
return T_EXIT_FAIL;
|
|
35
|
-
}
|
|
36
|
-
flags |= O_NONBLOCK;
|
|
37
|
-
ret = fcntl(fds[0], F_SETFL, flags);
|
|
38
|
-
if (ret < 0) {
|
|
39
|
-
perror("fcntl set");
|
|
40
|
-
return T_EXIT_FAIL;
|
|
41
|
-
}
|
|
30
|
+
t_set_nonblock(fds[0]);
|
|
42
31
|
|
|
43
32
|
sqe = io_uring_get_sqe(&ring);
|
|
44
33
|
io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0);
|
|
@@ -149,7 +149,7 @@ static int test(int flags, int vectored)
|
|
|
149
149
|
return ret;
|
|
150
150
|
|
|
151
151
|
for (i = 0; i < LOOPS; i++) {
|
|
152
|
-
int async_cancel = (
|
|
152
|
+
int async_cancel = !(i % 2);
|
|
153
153
|
int async_wait = !(i % 3);
|
|
154
154
|
ret = __test(&ring, vectored, async_wait, async_cancel);
|
|
155
155
|
if (ret) {
|
|
@@ -136,9 +136,10 @@ enum t_setup_ret t_create_ring_params(int depth, struct io_uring *ring,
|
|
|
136
136
|
fprintf(stdout, "SQPOLL skipped for regular user\n");
|
|
137
137
|
return T_SETUP_SKIP;
|
|
138
138
|
}
|
|
139
|
+
if (ret == -EINVAL)
|
|
140
|
+
return T_SETUP_SKIP;
|
|
139
141
|
|
|
140
|
-
|
|
141
|
-
fprintf(stderr, "queue_init: %s\n", strerror(-ret));
|
|
142
|
+
fprintf(stderr, "queue_init: %s\n", strerror(-ret));
|
|
142
143
|
return ret;
|
|
143
144
|
}
|
|
144
145
|
|
|
@@ -484,3 +485,99 @@ int t_create_socketpair_ip(struct sockaddr_storage *addr,
|
|
|
484
485
|
}
|
|
485
486
|
return 0;
|
|
486
487
|
}
|
|
488
|
+
|
|
489
|
+
static void __t_toggle_nonblock(int fd, int set)
|
|
490
|
+
{
|
|
491
|
+
int flags;
|
|
492
|
+
|
|
493
|
+
flags = fcntl(fd, F_GETFL, 0);
|
|
494
|
+
if (flags < 0)
|
|
495
|
+
t_error(1, errno, "fcntl F_GETFL");
|
|
496
|
+
if (set)
|
|
497
|
+
flags |= O_NONBLOCK;
|
|
498
|
+
else
|
|
499
|
+
flags &= ~O_NONBLOCK;
|
|
500
|
+
if (fcntl(fd, F_SETFL, flags) < 0)
|
|
501
|
+
t_error(1, errno, "fcntl F_SETFL");
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
void t_set_nonblock(int fd)
|
|
505
|
+
{
|
|
506
|
+
__t_toggle_nonblock(fd, 1);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
void t_clear_nonblock(int fd)
|
|
510
|
+
{
|
|
511
|
+
__t_toggle_nonblock(fd, 0);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
int t_submit_and_wait_single(struct io_uring *ring, struct io_uring_cqe **cqe)
|
|
515
|
+
{
|
|
516
|
+
int ret;
|
|
517
|
+
|
|
518
|
+
ret = io_uring_submit(ring);
|
|
519
|
+
if (ret <= 0) {
|
|
520
|
+
fprintf(stderr, "sqe submit failed: %d\n", ret);
|
|
521
|
+
return -1;
|
|
522
|
+
}
|
|
523
|
+
ret = io_uring_wait_cqe(ring, cqe);
|
|
524
|
+
if (ret < 0) {
|
|
525
|
+
fprintf(stderr, "wait completion %d\n", ret);
|
|
526
|
+
return ret;
|
|
527
|
+
}
|
|
528
|
+
return 0;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
size_t t_iovec_data_length(struct iovec *iov, unsigned iov_len)
|
|
532
|
+
{
|
|
533
|
+
size_t sz = 0;
|
|
534
|
+
int i;
|
|
535
|
+
|
|
536
|
+
for (i = 0; i < iov_len; i++)
|
|
537
|
+
sz += iov[i].iov_len;
|
|
538
|
+
return sz;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
#define t_min(a, b) ((a) < (b) ? (a) : (b))
|
|
542
|
+
|
|
543
|
+
unsigned long t_compare_data_iovec(struct iovec *iov_src, unsigned nr_src,
|
|
544
|
+
struct iovec *iov_dst, unsigned nr_dst)
|
|
545
|
+
{
|
|
546
|
+
size_t src_len = t_iovec_data_length(iov_src, nr_src);
|
|
547
|
+
size_t dst_len = t_iovec_data_length(iov_dst, nr_dst);
|
|
548
|
+
size_t len_left = t_min(src_len, dst_len);
|
|
549
|
+
unsigned long src_off = 0, dst_off = 0;
|
|
550
|
+
unsigned long offset = 0;
|
|
551
|
+
|
|
552
|
+
while (offset != len_left) {
|
|
553
|
+
size_t len = len_left - offset;
|
|
554
|
+
unsigned long i;
|
|
555
|
+
|
|
556
|
+
len = t_min(len, iov_src->iov_len - src_off);
|
|
557
|
+
len = t_min(len, iov_dst->iov_len - dst_off);
|
|
558
|
+
|
|
559
|
+
for (i = 0; i < len; i++) {
|
|
560
|
+
char csrc = ((char *)iov_src->iov_base)[src_off + i];
|
|
561
|
+
char cdst = ((char *)iov_dst->iov_base)[dst_off + i];
|
|
562
|
+
|
|
563
|
+
if (csrc != cdst) {
|
|
564
|
+
fprintf(stderr, "data mismatch, %i vs %i\n",
|
|
565
|
+
csrc, cdst);
|
|
566
|
+
return -EINVAL;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
src_off += len;
|
|
571
|
+
dst_off += len;
|
|
572
|
+
if (src_off == iov_src->iov_len) {
|
|
573
|
+
src_off = 0;
|
|
574
|
+
iov_src++;
|
|
575
|
+
}
|
|
576
|
+
if (dst_off == iov_dst->iov_len) {
|
|
577
|
+
dst_off = 0;
|
|
578
|
+
iov_dst++;
|
|
579
|
+
}
|
|
580
|
+
offset += len;
|
|
581
|
+
}
|
|
582
|
+
return 0;
|
|
583
|
+
}
|
|
@@ -99,6 +99,8 @@ enum t_setup_ret t_register_buffers(struct io_uring *ring,
|
|
|
99
99
|
unsigned nr_iovecs);
|
|
100
100
|
|
|
101
101
|
bool t_probe_defer_taskrun(void);
|
|
102
|
+
void t_set_nonblock(int fd);
|
|
103
|
+
void t_clear_nonblock(int fd);
|
|
102
104
|
|
|
103
105
|
unsigned __io_uring_flush_sq(struct io_uring *ring);
|
|
104
106
|
|
|
@@ -120,6 +122,13 @@ unsigned long long mtime_since_now(struct timeval *tv);
|
|
|
120
122
|
unsigned long long utime_since(const struct timeval *s, const struct timeval *e);
|
|
121
123
|
unsigned long long utime_since_now(struct timeval *tv);
|
|
122
124
|
|
|
125
|
+
int t_submit_and_wait_single(struct io_uring *ring, struct io_uring_cqe **cqe);
|
|
126
|
+
|
|
127
|
+
size_t t_iovec_data_length(struct iovec *iov, unsigned iov_len);
|
|
128
|
+
|
|
129
|
+
unsigned long t_compare_data_iovec(struct iovec *iov_src, unsigned nr_src,
|
|
130
|
+
struct iovec *iov_dst, unsigned nr_dst);
|
|
131
|
+
|
|
123
132
|
#ifdef __cplusplus
|
|
124
133
|
}
|
|
125
134
|
#endif
|
|
@@ -141,18 +141,16 @@ static int __test_io(const char *file, struct io_uring *ring, int tc, int read,
|
|
|
141
141
|
|
|
142
142
|
if (sqthread)
|
|
143
143
|
use_fd = 0;
|
|
144
|
+
if (nonvec)
|
|
145
|
+
io_uring_prep_uring_cmd(sqe, NVME_URING_CMD_IO, use_fd);
|
|
146
|
+
else
|
|
147
|
+
io_uring_prep_uring_cmd(sqe, NVME_URING_CMD_IO_VEC, use_fd);
|
|
144
148
|
if (fixed && (i & 1))
|
|
145
149
|
do_fixed = 0;
|
|
146
150
|
if (do_fixed)
|
|
147
151
|
sqe->buf_index = 0;
|
|
148
152
|
if (async)
|
|
149
153
|
sqe->flags |= IOSQE_ASYNC;
|
|
150
|
-
if (nonvec)
|
|
151
|
-
sqe->cmd_op = NVME_URING_CMD_IO;
|
|
152
|
-
else
|
|
153
|
-
sqe->cmd_op = NVME_URING_CMD_IO_VEC;
|
|
154
|
-
sqe->fd = use_fd;
|
|
155
|
-
sqe->opcode = IORING_OP_URING_CMD;
|
|
156
154
|
if (do_fixed)
|
|
157
155
|
sqe->uring_cmd_flags |= IORING_URING_CMD_FIXED;
|
|
158
156
|
sqe->user_data = ((uint64_t)offset << 32) | i;
|
|
@@ -328,9 +326,7 @@ static int test_invalid_passthru_submit(const char *file)
|
|
|
328
326
|
}
|
|
329
327
|
|
|
330
328
|
sqe = io_uring_get_sqe(&ring);
|
|
331
|
-
|
|
332
|
-
sqe->cmd_op = NVME_URING_CMD_IO;
|
|
333
|
-
sqe->opcode = IORING_OP_URING_CMD;
|
|
329
|
+
io_uring_prep_uring_cmd(sqe, NVME_URING_CMD_IO, fd);
|
|
334
330
|
sqe->user_data = 1;
|
|
335
331
|
cmd = (struct nvme_uring_cmd *)sqe->cmd;
|
|
336
332
|
memset(cmd, 0, sizeof(struct nvme_uring_cmd));
|
|
@@ -401,10 +397,8 @@ static int test_io_uring_submit_enters(const char *file)
|
|
|
401
397
|
__u32 nlb;
|
|
402
398
|
|
|
403
399
|
sqe = io_uring_get_sqe(&ring);
|
|
404
|
-
|
|
400
|
+
io_uring_prep_uring_cmd(sqe, NVME_URING_CMD_IO, fd);
|
|
405
401
|
sqe->user_data = i;
|
|
406
|
-
sqe->opcode = IORING_OP_URING_CMD;
|
|
407
|
-
sqe->cmd_op = NVME_URING_CMD_IO;
|
|
408
402
|
cmd = (struct nvme_uring_cmd *)sqe->cmd;
|
|
409
403
|
memset(cmd, 0, sizeof(struct nvme_uring_cmd));
|
|
410
404
|
|