uringmachine 0.4 → 0.5.1
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 +2 -1
- data/CHANGELOG.md +16 -0
- data/README.md +44 -1
- data/TODO.md +12 -3
- data/examples/bm_snooze.rb +89 -0
- data/examples/bm_sqlite.rb +89 -0
- data/examples/bm_write.rb +56 -0
- data/examples/dns_client.rb +12 -0
- data/examples/http_server.rb +42 -43
- data/examples/pg.rb +85 -0
- data/examples/server_client.rb +64 -0
- data/examples/snooze.rb +44 -0
- data/examples/stream.rb +85 -0
- data/examples/write_dev_null.rb +16 -0
- data/ext/um/extconf.rb +81 -14
- data/ext/um/um.c +468 -414
- data/ext/um/um.h +149 -40
- data/ext/um/um_async_op.c +40 -0
- data/ext/um/um_async_op_class.c +136 -0
- data/ext/um/um_buffer.c +49 -0
- data/ext/um/um_class.c +176 -44
- data/ext/um/um_const.c +174 -9
- data/ext/um/um_ext.c +8 -0
- data/ext/um/um_mutex_class.c +47 -0
- data/ext/um/um_op.c +89 -111
- data/ext/um/um_queue_class.c +58 -0
- data/ext/um/um_ssl.c +850 -0
- data/ext/um/um_ssl.h +22 -0
- data/ext/um/um_ssl_class.c +138 -0
- data/ext/um/um_sync.c +273 -0
- data/ext/um/um_utils.c +1 -1
- data/lib/uringmachine/dns_resolver.rb +84 -0
- data/lib/uringmachine/ssl/context_builder.rb +96 -0
- data/lib/uringmachine/ssl.rb +394 -0
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +27 -3
- data/supressions/ruby.supp +71 -0
- data/test/helper.rb +6 -0
- data/test/test_async_op.rb +119 -0
- data/test/test_ssl.rb +155 -0
- data/test/test_um.rb +464 -47
- data/uringmachine.gemspec +3 -2
- data/vendor/liburing/.gitignore +5 -0
- data/vendor/liburing/CHANGELOG +1 -0
- data/vendor/liburing/configure +32 -0
- data/vendor/liburing/examples/Makefile +1 -0
- data/vendor/liburing/examples/reg-wait.c +159 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/include/liburing/io_uring.h +48 -2
- data/vendor/liburing/src/include/liburing.h +28 -2
- data/vendor/liburing/src/int_flags.h +10 -3
- data/vendor/liburing/src/liburing-ffi.map +13 -2
- data/vendor/liburing/src/liburing.map +9 -0
- data/vendor/liburing/src/queue.c +25 -16
- data/vendor/liburing/src/register.c +73 -4
- data/vendor/liburing/src/setup.c +46 -18
- data/vendor/liburing/src/setup.h +6 -0
- data/vendor/liburing/test/Makefile +7 -0
- data/vendor/liburing/test/cmd-discard.c +427 -0
- data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
- data/vendor/liburing/test/file-exit-unreg.c +48 -0
- data/vendor/liburing/test/io_uring_passthrough.c +2 -0
- data/vendor/liburing/test/io_uring_register.c +13 -2
- data/vendor/liburing/test/napi-test.c +1 -1
- data/vendor/liburing/test/no-mmap-inval.c +1 -1
- data/vendor/liburing/test/read-mshot-empty.c +2 -0
- data/vendor/liburing/test/read-mshot-stdin.c +121 -0
- data/vendor/liburing/test/read-mshot.c +6 -0
- data/vendor/liburing/test/recvsend_bundle.c +2 -2
- data/vendor/liburing/test/reg-fd-only.c +1 -1
- data/vendor/liburing/test/reg-wait.c +251 -0
- data/vendor/liburing/test/regbuf-clone.c +458 -0
- data/vendor/liburing/test/resize-rings.c +643 -0
- data/vendor/liburing/test/rsrc_tags.c +1 -1
- data/vendor/liburing/test/sqpoll-sleep.c +39 -8
- data/vendor/liburing/test/sqwait.c +136 -0
- data/vendor/liburing/test/sync-cancel.c +8 -1
- data/vendor/liburing/test/timeout.c +13 -8
- metadata +52 -8
- data/examples/http_server_multishot.rb +0 -57
- data/examples/http_server_simpler.rb +0 -34
data/vendor/liburing/CHANGELOG
CHANGED
data/vendor/liburing/configure
CHANGED
@@ -417,6 +417,21 @@ if compile_prog "" "" "futexv"; then
|
|
417
417
|
fi
|
418
418
|
print_config "futex waitv support" "$futexv"
|
419
419
|
|
420
|
+
##########################################
|
421
|
+
# Check block discard cmd support
|
422
|
+
discard_cmd="no"
|
423
|
+
cat > $TMPC << EOF
|
424
|
+
#include <linux/blkdev.h>
|
425
|
+
int main(void)
|
426
|
+
{
|
427
|
+
return BLOCK_URING_CMD_DISCARD;
|
428
|
+
}
|
429
|
+
EOF
|
430
|
+
if compile_prog "" "" "discard command"; then
|
431
|
+
discard_cmd="yes"
|
432
|
+
fi
|
433
|
+
print_config "io_uring discard command support" "$discard_cmd"
|
434
|
+
|
420
435
|
##########################################
|
421
436
|
# Check idtype_t support
|
422
437
|
has_idtype_t="no"
|
@@ -651,6 +666,23 @@ typedef enum
|
|
651
666
|
} idtype_t;
|
652
667
|
EOF
|
653
668
|
fi
|
669
|
+
|
670
|
+
if test "$discard_cmd" != "yes"; then
|
671
|
+
cat >> $compat_h << EOF
|
672
|
+
|
673
|
+
#include <linux/ioctl.h>
|
674
|
+
|
675
|
+
#ifndef BLOCK_URING_CMD_DISCARD
|
676
|
+
#define BLOCK_URING_CMD_DISCARD _IO(0x12, 0)
|
677
|
+
#endif
|
678
|
+
|
679
|
+
EOF
|
680
|
+
else cat >> $compat_h << EOF
|
681
|
+
#include <linux/blkdev.h>
|
682
|
+
|
683
|
+
EOF
|
684
|
+
fi
|
685
|
+
|
654
686
|
cat >> $compat_h << EOF
|
655
687
|
#endif
|
656
688
|
EOF
|
@@ -0,0 +1,159 @@
|
|
1
|
+
/* SPDX-License-Identifier: MIT */
|
2
|
+
/*
|
3
|
+
* Sample program that shows how to use registered waits.
|
4
|
+
*
|
5
|
+
* (C) 2024 Jens Axboe <axboe@kernel.dk>
|
6
|
+
*/
|
7
|
+
#include <stdint.h>
|
8
|
+
#include <stdio.h>
|
9
|
+
#include <stdlib.h>
|
10
|
+
#include <string.h>
|
11
|
+
#include <unistd.h>
|
12
|
+
#include <assert.h>
|
13
|
+
#include <sys/time.h>
|
14
|
+
#include <liburing.h>
|
15
|
+
|
16
|
+
static unsigned long long mtime_since(const struct timeval *s,
|
17
|
+
const struct timeval *e)
|
18
|
+
{
|
19
|
+
long long sec, usec;
|
20
|
+
|
21
|
+
sec = e->tv_sec - s->tv_sec;
|
22
|
+
usec = (e->tv_usec - s->tv_usec);
|
23
|
+
if (sec > 0 && usec < 0) {
|
24
|
+
sec--;
|
25
|
+
usec += 1000000;
|
26
|
+
}
|
27
|
+
|
28
|
+
sec *= 1000;
|
29
|
+
usec /= 1000;
|
30
|
+
return sec + usec;
|
31
|
+
}
|
32
|
+
|
33
|
+
static unsigned long long mtime_since_now(struct timeval *tv)
|
34
|
+
{
|
35
|
+
struct timeval end;
|
36
|
+
|
37
|
+
gettimeofday(&end, NULL);
|
38
|
+
return mtime_since(tv, &end);
|
39
|
+
}
|
40
|
+
|
41
|
+
int main(int argc, char *argv[])
|
42
|
+
{
|
43
|
+
struct io_uring_reg_wait *reg;
|
44
|
+
struct io_uring_sqe *sqe;
|
45
|
+
struct io_uring_cqe *cqe[2];
|
46
|
+
struct io_uring ring;
|
47
|
+
char b1[8], b2[8];
|
48
|
+
unsigned long msec;
|
49
|
+
struct timeval tv;
|
50
|
+
int ret, fds[2];
|
51
|
+
|
52
|
+
if (argc > 1) {
|
53
|
+
fprintf(stdout, "%s: takes no arguments\n", argv[0]);
|
54
|
+
return 0;
|
55
|
+
}
|
56
|
+
|
57
|
+
if (pipe(fds) < 0) {
|
58
|
+
perror("pipe");
|
59
|
+
return 1;
|
60
|
+
}
|
61
|
+
|
62
|
+
ret = io_uring_queue_init(8, &ring, 0);
|
63
|
+
if (ret) {
|
64
|
+
fprintf(stderr, "Queue init: %d\n", ret);
|
65
|
+
return 1;
|
66
|
+
}
|
67
|
+
|
68
|
+
/*
|
69
|
+
* Setup wait region. We'll use 32 here, but 64 is probably a more
|
70
|
+
* logical value, as it'll pin a page regardless of size. 64 is the
|
71
|
+
* max value on a 4k page size architecture.
|
72
|
+
*/
|
73
|
+
reg = io_uring_setup_reg_wait(&ring, 32, &ret);
|
74
|
+
if (!reg) {
|
75
|
+
if (ret == -EINVAL) {
|
76
|
+
fprintf(stderr, "Kernel doesn't support registered waits\n");
|
77
|
+
return 1;
|
78
|
+
}
|
79
|
+
fprintf(stderr, "Registered wait: %d\n", ret);
|
80
|
+
return 1;
|
81
|
+
}
|
82
|
+
|
83
|
+
/*
|
84
|
+
* Setup two distinct wait regions. Index 0 will be a 1 second wait,
|
85
|
+
* and region 2 is a short wait using min_wait_usec as well. Neither
|
86
|
+
* of these use a signal mask, but sigmask/sigmask_sz can be set as
|
87
|
+
* well for that.
|
88
|
+
*/
|
89
|
+
reg[0].ts.tv_sec = 1;
|
90
|
+
reg[0].ts.tv_nsec = 0;
|
91
|
+
reg[0].flags = IORING_REG_WAIT_TS;
|
92
|
+
|
93
|
+
reg[1].ts.tv_sec = 0;
|
94
|
+
reg[1].ts.tv_nsec = 100000000LL;
|
95
|
+
reg[1].min_wait_usec = 10000;
|
96
|
+
reg[1].flags = IORING_REG_WAIT_TS;
|
97
|
+
|
98
|
+
/*
|
99
|
+
* No pending completions. Wait with region 0, which should time
|
100
|
+
* out after 1 second.
|
101
|
+
*/
|
102
|
+
gettimeofday(&tv, NULL);
|
103
|
+
ret = io_uring_submit_and_wait_reg(&ring, cqe, 1, 0);
|
104
|
+
if (ret == -EINVAL) {
|
105
|
+
fprintf(stderr, "Kernel doesn't support registered waits\n");
|
106
|
+
return 1;
|
107
|
+
} else if (ret != -ETIME) {
|
108
|
+
fprintf(stderr, "Wait should've timed out... %d\n", ret);
|
109
|
+
return 1;
|
110
|
+
}
|
111
|
+
msec = mtime_since_now(&tv);
|
112
|
+
if (msec < 900 || msec > 1100) {
|
113
|
+
fprintf(stderr, "Wait took an unexpected amount of time: %lu\n",
|
114
|
+
msec);
|
115
|
+
return 1;
|
116
|
+
}
|
117
|
+
|
118
|
+
/*
|
119
|
+
* Now prepare two pipe reads. We'll trigger one completion quickly,
|
120
|
+
* but the other one will never happen. Use min_wait_usec timeout
|
121
|
+
* to abort after 10 msec of time, where the overall timeout is
|
122
|
+
* otherwise 100 msec. Since we're waiting on two events, the min
|
123
|
+
* timeout ends up aborting us.
|
124
|
+
*/
|
125
|
+
sqe = io_uring_get_sqe(&ring);
|
126
|
+
io_uring_prep_read(sqe, fds[0], b1, sizeof(b1), 0);
|
127
|
+
sqe = io_uring_get_sqe(&ring);
|
128
|
+
io_uring_prep_read(sqe, fds[0], b2, sizeof(b2), 0);
|
129
|
+
|
130
|
+
/* trigger one read */
|
131
|
+
ret = write(fds[1], "Hello", 5);
|
132
|
+
if (ret < 0) {
|
133
|
+
perror("write");
|
134
|
+
return 1;
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* This should will wait for 2 entries, where 1 is already available.
|
139
|
+
* Since we're using min_wait_usec == 10 msec here with an overall
|
140
|
+
* wait of 100 msec, we expect the wait to abort after 10 msec since
|
141
|
+
* one or more events are available.
|
142
|
+
*/
|
143
|
+
gettimeofday(&tv, NULL);
|
144
|
+
ret = io_uring_submit_and_wait_reg(&ring, cqe, 2, 1);
|
145
|
+
msec = mtime_since_now(&tv);
|
146
|
+
if (ret != 2) {
|
147
|
+
fprintf(stderr, "Should have submitted 2: %d\n", ret);
|
148
|
+
return 1;
|
149
|
+
}
|
150
|
+
if (msec < 8 || msec > 12)
|
151
|
+
fprintf(stderr, "min_wait_usec should take ~10 msec: %lu\n", msec);
|
152
|
+
|
153
|
+
/*
|
154
|
+
* Cleanup after ourselves
|
155
|
+
*/
|
156
|
+
io_uring_queue_exit(&ring);
|
157
|
+
io_uring_free_reg_wait(reg, 32);
|
158
|
+
return 0;
|
159
|
+
}
|
@@ -518,6 +518,7 @@ struct io_cqring_offsets {
|
|
518
518
|
#define IORING_ENTER_EXT_ARG (1U << 3)
|
519
519
|
#define IORING_ENTER_REGISTERED_RING (1U << 4)
|
520
520
|
#define IORING_ENTER_ABS_TIMER (1U << 5)
|
521
|
+
#define IORING_ENTER_EXT_ARG_REG (1U << 6)
|
521
522
|
|
522
523
|
/*
|
523
524
|
* Passed in for io_uring_setup(2). Copied back with updated info on success
|
@@ -612,6 +613,10 @@ enum io_uring_register_op {
|
|
612
613
|
/* clone registered buffers from source ring to current ring */
|
613
614
|
IORING_REGISTER_CLONE_BUFFERS = 30,
|
614
615
|
|
616
|
+
IORING_REGISTER_RESIZE_RINGS = 33,
|
617
|
+
|
618
|
+
IORING_REGISTER_CQWAIT_REG = 34,
|
619
|
+
|
615
620
|
/* this goes last */
|
616
621
|
IORING_REGISTER_LAST,
|
617
622
|
|
@@ -698,13 +703,17 @@ struct io_uring_clock_register {
|
|
698
703
|
};
|
699
704
|
|
700
705
|
enum {
|
701
|
-
IORING_REGISTER_SRC_REGISTERED
|
706
|
+
IORING_REGISTER_SRC_REGISTERED = (1U << 0),
|
707
|
+
IORING_REGISTER_DST_REPLACE = (1U << 1),
|
702
708
|
};
|
703
709
|
|
704
710
|
struct io_uring_clone_buffers {
|
705
711
|
__u32 src_fd;
|
706
712
|
__u32 flags;
|
707
|
-
__u32
|
713
|
+
__u32 src_off;
|
714
|
+
__u32 dst_off;
|
715
|
+
__u32 nr;
|
716
|
+
__u32 pad[3];
|
708
717
|
};
|
709
718
|
|
710
719
|
struct io_uring_buf {
|
@@ -795,6 +804,43 @@ enum io_uring_register_restriction_op {
|
|
795
804
|
IORING_RESTRICTION_LAST
|
796
805
|
};
|
797
806
|
|
807
|
+
enum {
|
808
|
+
IORING_REG_WAIT_TS = (1U << 0),
|
809
|
+
};
|
810
|
+
|
811
|
+
/*
|
812
|
+
* Argument for IORING_REGISTER_CQWAIT_REG, registering a region of
|
813
|
+
* struct io_uring_reg_wait that can be indexed when io_uring_enter(2) is
|
814
|
+
* called rather than pass in a wait argument structure separately.
|
815
|
+
*/
|
816
|
+
struct io_uring_cqwait_reg_arg {
|
817
|
+
__u32 flags;
|
818
|
+
__u32 struct_size;
|
819
|
+
__u32 nr_entries;
|
820
|
+
__u32 pad;
|
821
|
+
__u64 user_addr;
|
822
|
+
__u64 pad2[3];
|
823
|
+
};
|
824
|
+
|
825
|
+
/*
|
826
|
+
* Argument for io_uring_enter(2) with
|
827
|
+
* IORING_GETEVENTS | IORING_ENTER_EXT_ARG_REG set, where the actual argument
|
828
|
+
* is an index into a previously registered fixed wait region described by
|
829
|
+
* the below structure.
|
830
|
+
*/
|
831
|
+
struct io_uring_reg_wait {
|
832
|
+
struct __kernel_timespec ts;
|
833
|
+
__u32 min_wait_usec;
|
834
|
+
__u32 flags;
|
835
|
+
__u64 sigmask;
|
836
|
+
__u32 sigmask_sz;
|
837
|
+
__u32 pad[3];
|
838
|
+
__u64 pad2[2];
|
839
|
+
};
|
840
|
+
|
841
|
+
/*
|
842
|
+
* Argument for io_uring_enter(2) with IORING_GETEVENTS | IORING_ENTER_EXT_ARG
|
843
|
+
*/
|
798
844
|
struct io_uring_getevents_arg {
|
799
845
|
__u64 sigmask;
|
800
846
|
__u32 sigmask_sz;
|
@@ -196,7 +196,16 @@ int io_uring_submit_and_wait_min_timeout(struct io_uring *ring,
|
|
196
196
|
struct __kernel_timespec *ts,
|
197
197
|
unsigned min_wait,
|
198
198
|
sigset_t *sigmask);
|
199
|
-
|
199
|
+
int io_uring_submit_and_wait_reg(struct io_uring *ring,
|
200
|
+
struct io_uring_cqe **cqe_ptr, unsigned wait_nr,
|
201
|
+
int reg_index);
|
202
|
+
|
203
|
+
int io_uring_register_wait_reg(struct io_uring *ring,
|
204
|
+
struct io_uring_reg_wait *reg, int nr);
|
205
|
+
int io_uring_resize_rings(struct io_uring *ring, struct io_uring_params *p);
|
206
|
+
int io_uring_clone_buffers_offset(struct io_uring *dst, struct io_uring *src,
|
207
|
+
unsigned int dst_off, unsigned int src_off,
|
208
|
+
unsigned int nr, unsigned int flags);
|
200
209
|
int io_uring_clone_buffers(struct io_uring *dst, struct io_uring *src);
|
201
210
|
int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs,
|
202
211
|
unsigned nr_iovecs);
|
@@ -275,13 +284,20 @@ int io_uring_setup(unsigned int entries, struct io_uring_params *p);
|
|
275
284
|
int io_uring_register(unsigned int fd, unsigned int opcode, const void *arg,
|
276
285
|
unsigned int nr_args);
|
277
286
|
|
287
|
+
/*
|
288
|
+
* Mapped/registered wait regions
|
289
|
+
*/
|
290
|
+
struct io_uring_reg_wait *io_uring_setup_reg_wait(struct io_uring *ring,
|
291
|
+
unsigned nentries, int *err);
|
292
|
+
void io_uring_free_reg_wait(struct io_uring_reg_wait *reg, unsigned nentries);
|
293
|
+
|
278
294
|
/*
|
279
295
|
* Mapped buffer ring alloc/register + unregister/free helpers
|
280
296
|
*/
|
281
297
|
struct io_uring_buf_ring *io_uring_setup_buf_ring(struct io_uring *ring,
|
282
298
|
unsigned int nentries,
|
283
299
|
int bgid, unsigned int flags,
|
284
|
-
int *
|
300
|
+
int *err);
|
285
301
|
int io_uring_free_buf_ring(struct io_uring *ring, struct io_uring_buf_ring *br,
|
286
302
|
unsigned int nentries, int bgid);
|
287
303
|
|
@@ -1292,6 +1308,16 @@ IOURINGINLINE void io_uring_prep_ftruncate(struct io_uring_sqe *sqe,
|
|
1292
1308
|
}
|
1293
1309
|
#endif
|
1294
1310
|
|
1311
|
+
IOURINGINLINE void io_uring_prep_cmd_discard(struct io_uring_sqe *sqe,
|
1312
|
+
int fd,
|
1313
|
+
uint64_t offset, uint64_t nbytes)
|
1314
|
+
{
|
1315
|
+
io_uring_prep_rw(IORING_OP_URING_CMD, sqe, fd, 0, 0, 0);
|
1316
|
+
sqe->cmd_op = BLOCK_URING_CMD_DISCARD;
|
1317
|
+
sqe->addr = offset;
|
1318
|
+
sqe->addr3 = nbytes;
|
1319
|
+
}
|
1320
|
+
|
1295
1321
|
/*
|
1296
1322
|
* Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
|
1297
1323
|
* the SQ ring
|
@@ -2,10 +2,17 @@
|
|
2
2
|
#ifndef LIBURING_INT_FLAGS
|
3
3
|
#define LIBURING_INT_FLAGS
|
4
4
|
|
5
|
+
#define INT_FLAGS_MASK (IORING_ENTER_REGISTERED_RING)
|
6
|
+
|
5
7
|
enum {
|
6
|
-
INT_FLAG_REG_RING =
|
7
|
-
INT_FLAG_REG_REG_RING =
|
8
|
-
INT_FLAG_APP_MEM =
|
8
|
+
INT_FLAG_REG_RING = IORING_ENTER_REGISTERED_RING,
|
9
|
+
INT_FLAG_REG_REG_RING = 1,
|
10
|
+
INT_FLAG_APP_MEM = 2,
|
9
11
|
};
|
10
12
|
|
13
|
+
static inline int ring_enter_flags(struct io_uring *ring)
|
14
|
+
{
|
15
|
+
return ring->int_flags & INT_FLAGS_MASK;
|
16
|
+
}
|
17
|
+
|
11
18
|
#endif
|
@@ -211,6 +211,17 @@ LIBURING_2.8 {
|
|
211
211
|
io_uring_submit_and_wait_min_timeout;
|
212
212
|
io_uring_wait_cqes_min_timeout;
|
213
213
|
io_uring_clone_buffers;
|
214
|
-
|
215
|
-
|
214
|
+
io_uring_prep_cmd_discard;
|
215
|
+
io_uring_prep_open;
|
216
|
+
io_uring_prep_open_direct;
|
216
217
|
} LIBURING_2.7;
|
218
|
+
|
219
|
+
LIBURING_2.9 {
|
220
|
+
global:
|
221
|
+
io_uring_resize_rings;
|
222
|
+
io_uring_register_wait_reg;
|
223
|
+
io_uring_submit_and_wait_reg;
|
224
|
+
io_uring_free_reg_wait;
|
225
|
+
io_uring_setup_reg_wait;
|
226
|
+
io_uring_clone_buffers_offset;
|
227
|
+
} LIBURING_2.8;
|
@@ -103,3 +103,12 @@ LIBURING_2.8 {
|
|
103
103
|
io_uring_wait_cqes_min_timeout;
|
104
104
|
io_uring_clone_buffers;
|
105
105
|
} LIBURING_2.7;
|
106
|
+
|
107
|
+
LIBURING_2.9 {
|
108
|
+
io_uring_resize_rings;
|
109
|
+
io_uring_register_wait_reg;
|
110
|
+
io_uring_submit_and_wait_reg;
|
111
|
+
io_uring_free_reg_wait;
|
112
|
+
io_uring_setup_reg_wait;
|
113
|
+
io_uring_clone_buffers_offset;
|
114
|
+
} LIBURING_2.8;
|
data/vendor/liburing/src/queue.c
CHANGED
@@ -6,7 +6,6 @@
|
|
6
6
|
#include "liburing.h"
|
7
7
|
#include "int_flags.h"
|
8
8
|
#include "liburing/sanitize.h"
|
9
|
-
#include "liburing/compat.h"
|
10
9
|
#include "liburing/io_uring.h"
|
11
10
|
|
12
11
|
/*
|
@@ -70,7 +69,7 @@ static int _io_uring_get_cqe(struct io_uring *ring,
|
|
70
69
|
|
71
70
|
do {
|
72
71
|
bool need_enter = false;
|
73
|
-
unsigned flags =
|
72
|
+
unsigned flags = ring_enter_flags(ring);
|
74
73
|
unsigned nr_available;
|
75
74
|
int ret;
|
76
75
|
|
@@ -94,7 +93,7 @@ static int _io_uring_get_cqe(struct io_uring *ring,
|
|
94
93
|
need_enter = true;
|
95
94
|
}
|
96
95
|
if (data->wait_nr > nr_available || need_enter) {
|
97
|
-
flags
|
96
|
+
flags |= IORING_ENTER_GETEVENTS | data->get_flags;
|
98
97
|
need_enter = true;
|
99
98
|
}
|
100
99
|
if (sq_ring_needs_enter(ring, data->submit, &flags))
|
@@ -109,8 +108,6 @@ static int _io_uring_get_cqe(struct io_uring *ring,
|
|
109
108
|
break;
|
110
109
|
}
|
111
110
|
|
112
|
-
if (ring->int_flags & INT_FLAG_REG_RING)
|
113
|
-
flags |= IORING_ENTER_REGISTERED_RING;
|
114
111
|
ret = __sys_io_uring_enter2(ring->enter_ring_fd, data->submit,
|
115
112
|
data->wait_nr, flags, data->arg,
|
116
113
|
data->sz);
|
@@ -149,10 +146,8 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr,
|
|
149
146
|
|
150
147
|
int io_uring_get_events(struct io_uring *ring)
|
151
148
|
{
|
152
|
-
int flags = IORING_ENTER_GETEVENTS;
|
149
|
+
int flags = IORING_ENTER_GETEVENTS | ring_enter_flags(ring);
|
153
150
|
|
154
|
-
if (ring->int_flags & INT_FLAG_REG_RING)
|
155
|
-
flags |= IORING_ENTER_REGISTERED_RING;
|
156
151
|
return __sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL);
|
157
152
|
}
|
158
153
|
|
@@ -325,6 +320,26 @@ int io_uring_wait_cqes_min_timeout(struct io_uring *ring,
|
|
325
320
|
sigmask);
|
326
321
|
}
|
327
322
|
|
323
|
+
int io_uring_submit_and_wait_reg(struct io_uring *ring,
|
324
|
+
struct io_uring_cqe **cqe_ptr,
|
325
|
+
unsigned wait_nr, int reg_index)
|
326
|
+
{
|
327
|
+
struct get_data data = {
|
328
|
+
.submit = __io_uring_flush_sq(ring),
|
329
|
+
.wait_nr = wait_nr,
|
330
|
+
.get_flags = IORING_ENTER_EXT_ARG |
|
331
|
+
IORING_ENTER_EXT_ARG_REG,
|
332
|
+
.sz = sizeof(struct io_uring_reg_wait),
|
333
|
+
.has_ts = true,
|
334
|
+
.arg = (void *) (uintptr_t) reg_index,
|
335
|
+
};
|
336
|
+
|
337
|
+
if (!(ring->features & IORING_FEAT_EXT_ARG))
|
338
|
+
return -EINVAL;
|
339
|
+
|
340
|
+
return _io_uring_get_cqe(ring, cqe_ptr, &data);
|
341
|
+
}
|
342
|
+
|
328
343
|
static int __io_uring_submit_and_wait_timeout(struct io_uring *ring,
|
329
344
|
struct io_uring_cqe **cqe_ptr, unsigned wait_nr,
|
330
345
|
struct __kernel_timespec *ts,
|
@@ -403,17 +418,14 @@ static int __io_uring_submit(struct io_uring *ring, unsigned submitted,
|
|
403
418
|
unsigned wait_nr, bool getevents)
|
404
419
|
{
|
405
420
|
bool cq_needs_enter = getevents || wait_nr || cq_ring_needs_enter(ring);
|
406
|
-
unsigned flags;
|
421
|
+
unsigned flags = ring_enter_flags(ring);
|
407
422
|
int ret;
|
408
423
|
|
409
424
|
liburing_sanitize_ring(ring);
|
410
425
|
|
411
|
-
flags = 0;
|
412
426
|
if (sq_ring_needs_enter(ring, submitted, &flags) || cq_needs_enter) {
|
413
427
|
if (cq_needs_enter)
|
414
428
|
flags |= IORING_ENTER_GETEVENTS;
|
415
|
-
if (ring->int_flags & INT_FLAG_REG_RING)
|
416
|
-
flags |= IORING_ENTER_REGISTERED_RING;
|
417
429
|
|
418
430
|
ret = __sys_io_uring_enter(ring->enter_ring_fd, submitted,
|
419
431
|
wait_nr, flags, NULL);
|
@@ -462,10 +474,7 @@ struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring)
|
|
462
474
|
|
463
475
|
int __io_uring_sqring_wait(struct io_uring *ring)
|
464
476
|
{
|
465
|
-
int flags = IORING_ENTER_SQ_WAIT;
|
466
|
-
|
467
|
-
if (ring->int_flags & INT_FLAG_REG_RING)
|
468
|
-
flags |= IORING_ENTER_REGISTERED_RING;
|
477
|
+
int flags = IORING_ENTER_SQ_WAIT | ring_enter_flags(ring);
|
469
478
|
|
470
479
|
return __sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL);
|
471
480
|
}
|
@@ -4,8 +4,8 @@
|
|
4
4
|
#include "lib.h"
|
5
5
|
#include "syscall.h"
|
6
6
|
#include "liburing.h"
|
7
|
+
#include "setup.h"
|
7
8
|
#include "int_flags.h"
|
8
|
-
#include "liburing/compat.h"
|
9
9
|
#include "liburing/io_uring.h"
|
10
10
|
#include "liburing/sanitize.h"
|
11
11
|
|
@@ -395,16 +395,85 @@ int io_uring_register_clock(struct io_uring *ring,
|
|
395
395
|
return do_register(ring, IORING_REGISTER_CLOCK, arg, 0);
|
396
396
|
}
|
397
397
|
|
398
|
-
int
|
398
|
+
int io_uring_clone_buffers_offset(struct io_uring *dst, struct io_uring *src,
|
399
|
+
unsigned int dst_off, unsigned int src_off,
|
400
|
+
unsigned int nr, unsigned int flags)
|
399
401
|
{
|
400
|
-
struct io_uring_clone_buffers buf = {
|
402
|
+
struct io_uring_clone_buffers buf = {
|
403
|
+
.src_fd = src->ring_fd,
|
404
|
+
.flags = flags,
|
405
|
+
.src_off = src_off,
|
406
|
+
.dst_off = dst_off,
|
407
|
+
.nr = nr,
|
408
|
+
};
|
401
409
|
|
402
410
|
if (src->int_flags & INT_FLAG_REG_REG_RING) {
|
403
411
|
buf.src_fd = src->enter_ring_fd;
|
404
|
-
buf.flags
|
412
|
+
buf.flags |= IORING_REGISTER_SRC_REGISTERED;
|
405
413
|
} else {
|
406
414
|
buf.src_fd = src->ring_fd;
|
407
415
|
}
|
408
416
|
|
409
417
|
return do_register(dst, IORING_REGISTER_CLONE_BUFFERS, &buf, 1);
|
410
418
|
}
|
419
|
+
|
420
|
+
int io_uring_clone_buffers(struct io_uring *dst, struct io_uring *src)
|
421
|
+
{
|
422
|
+
return io_uring_clone_buffers_offset(dst, src, 0, 0, 0, 0);
|
423
|
+
}
|
424
|
+
|
425
|
+
int io_uring_resize_rings(struct io_uring *ring, struct io_uring_params *p)
|
426
|
+
{
|
427
|
+
unsigned sq_head, sq_tail;
|
428
|
+
int ret;
|
429
|
+
|
430
|
+
if (ring->flags & IORING_SETUP_NO_MMAP)
|
431
|
+
return -EINVAL;
|
432
|
+
|
433
|
+
memset(&p->sq_off, 0, sizeof(p->sq_off));
|
434
|
+
memset(&p->cq_off, 0, sizeof(p->cq_off));
|
435
|
+
|
436
|
+
ret = do_register(ring, IORING_REGISTER_RESIZE_RINGS, p, 1);
|
437
|
+
if (ret < 0)
|
438
|
+
goto out;
|
439
|
+
|
440
|
+
sq_head = ring->sq.sqe_head;
|
441
|
+
sq_tail = ring->sq.sqe_tail;
|
442
|
+
io_uring_unmap_rings(&ring->sq, &ring->cq);
|
443
|
+
memset(&ring->sq, 0, sizeof(ring->sq));
|
444
|
+
memset(&ring->cq, 0, sizeof(ring->cq));
|
445
|
+
ret = io_uring_mmap(ring->ring_fd, p, &ring->sq, &ring->cq);
|
446
|
+
if (ret)
|
447
|
+
goto out;
|
448
|
+
|
449
|
+
ring->sq.sqe_head = sq_head;
|
450
|
+
ring->sq.sqe_tail = sq_tail;
|
451
|
+
|
452
|
+
/*
|
453
|
+
* Directly map SQ slots to SQEs
|
454
|
+
*/
|
455
|
+
if (!(p->flags & IORING_SETUP_NO_SQARRAY)) {
|
456
|
+
unsigned index;
|
457
|
+
|
458
|
+
for (index = 0; index < p->sq_entries; index++)
|
459
|
+
ring->sq.array[index] = index;
|
460
|
+
}
|
461
|
+
|
462
|
+
/* clear for next use */
|
463
|
+
out:
|
464
|
+
p->flags = 0;
|
465
|
+
return ret;
|
466
|
+
}
|
467
|
+
|
468
|
+
int io_uring_register_wait_reg(struct io_uring *ring,
|
469
|
+
struct io_uring_reg_wait *reg, int nr)
|
470
|
+
{
|
471
|
+
struct io_uring_cqwait_reg_arg arg = {
|
472
|
+
.flags = 0,
|
473
|
+
.struct_size = sizeof(*reg),
|
474
|
+
.nr_entries = nr,
|
475
|
+
.user_addr = (unsigned long) (uintptr_t) reg,
|
476
|
+
};
|
477
|
+
|
478
|
+
return do_register(ring, IORING_REGISTER_CQWAIT_REG, &arg, 1);
|
479
|
+
}
|