uringmachine 0.3 → 0.5

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.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -1
  3. data/CHANGELOG.md +23 -0
  4. data/README.md +128 -0
  5. data/TODO.md +14 -0
  6. data/examples/bm_snooze.rb +89 -0
  7. data/examples/bm_write.rb +56 -0
  8. data/examples/dns_client.rb +12 -0
  9. data/examples/echo_server.rb +18 -40
  10. data/examples/http_server.rb +42 -43
  11. data/examples/inout.rb +19 -0
  12. data/examples/nc.rb +36 -0
  13. data/examples/server_client.rb +64 -0
  14. data/examples/snooze.rb +44 -0
  15. data/examples/write_dev_null.rb +16 -0
  16. data/ext/um/extconf.rb +24 -23
  17. data/ext/um/um.c +524 -278
  18. data/ext/um/um.h +146 -44
  19. data/ext/um/um_buffer.c +49 -0
  20. data/ext/um/um_class.c +217 -106
  21. data/ext/um/um_const.c +213 -0
  22. data/ext/um/um_ext.c +4 -0
  23. data/ext/um/um_mutex_class.c +47 -0
  24. data/ext/um/um_op.c +86 -114
  25. data/ext/um/um_queue_class.c +58 -0
  26. data/ext/um/um_sync.c +273 -0
  27. data/ext/um/um_utils.c +49 -4
  28. data/lib/uringmachine/dns_resolver.rb +84 -0
  29. data/lib/uringmachine/version.rb +1 -1
  30. data/lib/uringmachine.rb +28 -0
  31. data/supressions/ruby.supp +71 -0
  32. data/test/helper.rb +8 -0
  33. data/test/test_um.rb +685 -46
  34. data/vendor/liburing/.github/workflows/build.yml +29 -1
  35. data/vendor/liburing/.gitignore +6 -0
  36. data/vendor/liburing/CHANGELOG +16 -0
  37. data/vendor/liburing/CONTRIBUTING.md +165 -0
  38. data/vendor/liburing/configure +64 -0
  39. data/vendor/liburing/examples/Makefile +9 -1
  40. data/vendor/liburing/examples/kdigest.c +405 -0
  41. data/vendor/liburing/examples/proxy.c +75 -8
  42. data/vendor/liburing/examples/reg-wait.c +159 -0
  43. data/vendor/liburing/liburing.pc.in +1 -1
  44. data/vendor/liburing/liburing.spec +1 -1
  45. data/vendor/liburing/src/Makefile +16 -2
  46. data/vendor/liburing/src/include/liburing/io_uring.h +77 -0
  47. data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
  48. data/vendor/liburing/src/include/liburing.h +59 -6
  49. data/vendor/liburing/src/int_flags.h +10 -3
  50. data/vendor/liburing/src/liburing-ffi.map +16 -0
  51. data/vendor/liburing/src/liburing.map +10 -0
  52. data/vendor/liburing/src/queue.c +28 -16
  53. data/vendor/liburing/src/register.c +106 -1
  54. data/vendor/liburing/src/sanitize.c +176 -0
  55. data/vendor/liburing/src/setup.c +47 -19
  56. data/vendor/liburing/src/setup.h +6 -0
  57. data/vendor/liburing/test/35fa71a030ca.c +7 -0
  58. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  59. data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
  60. data/vendor/liburing/test/917257daa0fe.c +7 -0
  61. data/vendor/liburing/test/Makefile +38 -4
  62. data/vendor/liburing/test/a0908ae19763.c +7 -0
  63. data/vendor/liburing/test/a4c0b3decb33.c +7 -0
  64. data/vendor/liburing/test/accept.c +14 -4
  65. data/vendor/liburing/test/b19062a56726.c +7 -0
  66. data/vendor/liburing/test/bind-listen.c +2 -2
  67. data/vendor/liburing/test/buf-ring-nommap.c +10 -3
  68. data/vendor/liburing/test/buf-ring.c +2 -0
  69. data/vendor/liburing/test/cmd-discard.c +427 -0
  70. data/vendor/liburing/test/coredump.c +7 -0
  71. data/vendor/liburing/test/cq-overflow.c +13 -1
  72. data/vendor/liburing/test/d4ae271dfaae.c +11 -3
  73. data/vendor/liburing/test/defer-taskrun.c +2 -2
  74. data/vendor/liburing/test/defer-tw-timeout.c +4 -1
  75. data/vendor/liburing/test/defer.c +2 -2
  76. data/vendor/liburing/test/double-poll-crash.c +1 -1
  77. data/vendor/liburing/test/eeed8b54e0df.c +2 -0
  78. data/vendor/liburing/test/eventfd.c +0 -1
  79. data/vendor/liburing/test/exit-no-cleanup.c +11 -0
  80. data/vendor/liburing/test/fadvise.c +9 -26
  81. data/vendor/liburing/test/fdinfo.c +9 -1
  82. data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
  83. data/vendor/liburing/test/file-exit-unreg.c +48 -0
  84. data/vendor/liburing/test/file-register.c +14 -2
  85. data/vendor/liburing/test/file-update.c +1 -1
  86. data/vendor/liburing/test/file-verify.c +27 -16
  87. data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
  88. data/vendor/liburing/test/fixed-buf-iter.c +3 -1
  89. data/vendor/liburing/test/fixed-hugepage.c +12 -1
  90. data/vendor/liburing/test/fsnotify.c +1 -0
  91. data/vendor/liburing/test/futex.c +16 -4
  92. data/vendor/liburing/test/helpers.c +47 -0
  93. data/vendor/liburing/test/helpers.h +6 -0
  94. data/vendor/liburing/test/init-mem.c +5 -3
  95. data/vendor/liburing/test/io-cancel.c +0 -24
  96. data/vendor/liburing/test/io_uring_passthrough.c +4 -0
  97. data/vendor/liburing/test/io_uring_register.c +38 -8
  98. data/vendor/liburing/test/iopoll-leak.c +4 -0
  99. data/vendor/liburing/test/iopoll-overflow.c +1 -1
  100. data/vendor/liburing/test/iopoll.c +3 -3
  101. data/vendor/liburing/test/kallsyms.c +203 -0
  102. data/vendor/liburing/test/link-timeout.c +159 -0
  103. data/vendor/liburing/test/linked-defer-close.c +224 -0
  104. data/vendor/liburing/test/madvise.c +12 -25
  105. data/vendor/liburing/test/min-timeout-wait.c +0 -25
  106. data/vendor/liburing/test/min-timeout.c +0 -25
  107. data/vendor/liburing/test/mkdir.c +6 -0
  108. data/vendor/liburing/test/msg-ring.c +8 -2
  109. data/vendor/liburing/test/napi-test.c +16 -3
  110. data/vendor/liburing/test/no-mmap-inval.c +3 -1
  111. data/vendor/liburing/test/nop.c +44 -0
  112. data/vendor/liburing/test/ooo-file-unreg.c +1 -1
  113. data/vendor/liburing/test/open-close.c +40 -0
  114. data/vendor/liburing/test/openat2.c +37 -14
  115. data/vendor/liburing/test/poll-many.c +13 -7
  116. data/vendor/liburing/test/poll-mshot-update.c +17 -10
  117. data/vendor/liburing/test/poll-v-poll.c +6 -3
  118. data/vendor/liburing/test/pollfree.c +148 -0
  119. data/vendor/liburing/test/read-mshot-empty.c +158 -153
  120. data/vendor/liburing/test/read-mshot-stdin.c +121 -0
  121. data/vendor/liburing/test/read-mshot.c +282 -27
  122. data/vendor/liburing/test/read-write.c +78 -13
  123. data/vendor/liburing/test/recv-msgall-stream.c +3 -0
  124. data/vendor/liburing/test/recv-msgall.c +5 -0
  125. data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
  126. data/vendor/liburing/test/recvsend_bundle.c +94 -31
  127. data/vendor/liburing/test/reg-fd-only.c +15 -5
  128. data/vendor/liburing/test/reg-wait.c +251 -0
  129. data/vendor/liburing/test/regbuf-clone.c +645 -0
  130. data/vendor/liburing/test/regbuf-merge.c +7 -0
  131. data/vendor/liburing/test/register-restrictions.c +86 -85
  132. data/vendor/liburing/test/rename.c +59 -1
  133. data/vendor/liburing/test/resize-rings.c +643 -0
  134. data/vendor/liburing/test/ringbuf-read.c +5 -0
  135. data/vendor/liburing/test/ringbuf-status.c +5 -1
  136. data/vendor/liburing/test/rsrc_tags.c +1 -1
  137. data/vendor/liburing/test/runtests.sh +16 -1
  138. data/vendor/liburing/test/send-zerocopy.c +59 -0
  139. data/vendor/liburing/test/short-read.c +1 -0
  140. data/vendor/liburing/test/socket.c +43 -0
  141. data/vendor/liburing/test/splice.c +3 -1
  142. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  143. data/vendor/liburing/test/sq-poll-share.c +2 -0
  144. data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
  145. data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
  146. data/vendor/liburing/test/sqpoll-sleep.c +40 -33
  147. data/vendor/liburing/test/sqwait.c +136 -0
  148. data/vendor/liburing/test/statx.c +89 -0
  149. data/vendor/liburing/test/stdout.c +2 -0
  150. data/vendor/liburing/test/submit-and-wait.c +1 -25
  151. data/vendor/liburing/test/submit-reuse.c +4 -26
  152. data/vendor/liburing/test/symlink.c +12 -1
  153. data/vendor/liburing/test/sync-cancel.c +56 -22
  154. data/vendor/liburing/test/thread-exit.c +5 -0
  155. data/vendor/liburing/test/timeout-new.c +1 -26
  156. data/vendor/liburing/test/timeout.c +25 -34
  157. data/vendor/liburing/test/unlink.c +94 -1
  158. data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
  159. data/vendor/liburing/test/waitid.c +62 -8
  160. data/vendor/liburing/test/wq-aff.c +35 -0
  161. data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
  162. data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
  163. metadata +37 -6
  164. data/examples/event_loop.rb +0 -69
  165. data/examples/fibers.rb +0 -105
  166. data/examples/http_server_multishot.rb +0 -57
  167. data/examples/http_server_simpler.rb +0 -34
@@ -9,4 +9,4 @@ Description: io_uring library
9
9
  URL: https://git.kernel.dk/cgit/liburing/
10
10
 
11
11
  Libs: -L${libdir} -luring
12
- Cflags: -I${includedir} -D_GNU_SOURCE
12
+ Cflags: -I${includedir}
@@ -1,5 +1,5 @@
1
1
  Name: liburing
2
- Version: 2.8
2
+ Version: 2.9
3
3
  Release: 1%{?dist}
4
4
  Summary: Linux-native io_uring I/O access library
5
5
  License: (GPLv2 with exceptions and LGPLv2+) or MIT
@@ -16,8 +16,6 @@ override CFLAGS += -Wno-unused-parameter \
16
16
  $(LIBURING_CFLAGS)
17
17
  SO_CFLAGS=-fPIC $(CFLAGS)
18
18
  L_CFLAGS=$(CFLAGS)
19
- LINK_FLAGS=-Wl,-z,defs
20
- LINK_FLAGS+=$(LDFLAGS)
21
19
  ENABLE_SHARED ?= 1
22
20
 
23
21
  soname=liburing.so.$(VERSION_MAJOR)
@@ -39,6 +37,13 @@ ifneq ($(MAKECMDGOALS),clean)
39
37
  include ../config-host.mak
40
38
  endif
41
39
 
40
+ ifeq ($(CONFIG_USE_SANITIZER),y)
41
+ LINK_FLAGS=
42
+ else
43
+ LINK_FLAGS=-Wl,-z,defs
44
+ endif
45
+ LINK_FLAGS+=$(LDFLAGS)
46
+
42
47
  all: $(all_targets)
43
48
 
44
49
  liburing_srcs := setup.c queue.c register.c syscall.c version.c
@@ -50,6 +55,13 @@ ifeq ($(CONFIG_NOLIBC),y)
50
55
  override LINK_FLAGS += -nostdlib -nodefaultlibs $(libgcc_link_flag)
51
56
  endif
52
57
 
58
+ ifeq ($(CONFIG_USE_SANITIZER),y)
59
+ override CFLAGS += -fsanitize=address,undefined -g -fno-omit-frame-pointer -fno-optimize-sibling-calls
60
+ override CPPFLAGS += -fsanitize=address,undefined -g -fno-omit-frame-pointer -fno-optimize-sibling-calls
61
+ override LINK_FLAGS += -fsanitize=address,undefined
62
+ liburing_srcs += sanitize.c
63
+ endif
64
+
53
65
  override CPPFLAGS += -MT "$@" -MMD -MP -MF "$@.d"
54
66
  liburing_objs := $(patsubst %.c,%.ol,$(liburing_srcs))
55
67
  liburing_sobjs := $(patsubst %.c,%.os,$(liburing_srcs))
@@ -89,6 +101,7 @@ install: $(all_targets)
89
101
  install -D -m 644 include/liburing.h $(includedir)/liburing.h
90
102
  install -D -m 644 include/liburing/compat.h $(includedir)/liburing/compat.h
91
103
  install -D -m 644 include/liburing/barrier.h $(includedir)/liburing/barrier.h
104
+ install -D -m 644 include/liburing/sanitize.h $(includedir)/liburing/sanitize.h
92
105
  install -D -m 644 include/liburing/io_uring_version.h $(includedir)/liburing/io_uring_version.h
93
106
  install -D -m 644 liburing.a $(libdevdir)/liburing.a
94
107
  install -D -m 644 liburing-ffi.a $(libdevdir)/liburing-ffi.a
@@ -106,6 +119,7 @@ uninstall:
106
119
  @rm -f $(includedir)/liburing.h
107
120
  @rm -f $(includedir)/liburing/compat.h
108
121
  @rm -f $(includedir)/liburing/barrier.h
122
+ @rm -f $(includedir)/liburing/sanitize.h
109
123
  @rm -f $(includedir)/liburing/io_uring_version.h
110
124
  @rm -f $(libdevdir)/liburing.a
111
125
  @rm -f $(libdevdir)/liburing-ffi.a
@@ -440,11 +440,21 @@ struct io_uring_cqe {
440
440
  * IORING_CQE_F_SOCK_NONEMPTY If set, more data to read after socket recv
441
441
  * IORING_CQE_F_NOTIF Set for notification CQEs. Can be used to distinct
442
442
  * them from sends.
443
+ * IORING_CQE_F_BUF_MORE If set, the buffer ID set in the completion will get
444
+ * more completions. In other words, the buffer is being
445
+ * partially consumed, and will be used by the kernel for
446
+ * more completions. This is only set for buffers used via
447
+ * the incremental buffer consumption, as provided by
448
+ * a ring buffer setup with IOU_PBUF_RING_INC. For any
449
+ * other provided buffer type, all completions with a
450
+ * buffer passed back is automatically returned to the
451
+ * application.
443
452
  */
444
453
  #define IORING_CQE_F_BUFFER (1U << 0)
445
454
  #define IORING_CQE_F_MORE (1U << 1)
446
455
  #define IORING_CQE_F_SOCK_NONEMPTY (1U << 2)
447
456
  #define IORING_CQE_F_NOTIF (1U << 3)
457
+ #define IORING_CQE_F_BUF_MORE (1U << 4)
448
458
 
449
459
  #define IORING_CQE_BUFFER_SHIFT 16
450
460
 
@@ -508,6 +518,7 @@ struct io_cqring_offsets {
508
518
  #define IORING_ENTER_EXT_ARG (1U << 3)
509
519
  #define IORING_ENTER_REGISTERED_RING (1U << 4)
510
520
  #define IORING_ENTER_ABS_TIMER (1U << 5)
521
+ #define IORING_ENTER_EXT_ARG_REG (1U << 6)
511
522
 
512
523
  /*
513
524
  * Passed in for io_uring_setup(2). Copied back with updated info on success
@@ -599,6 +610,13 @@ enum io_uring_register_op {
599
610
 
600
611
  IORING_REGISTER_CLOCK = 29,
601
612
 
613
+ /* clone registered buffers from source ring to current ring */
614
+ IORING_REGISTER_CLONE_BUFFERS = 30,
615
+
616
+ IORING_REGISTER_RESIZE_RINGS = 33,
617
+
618
+ IORING_REGISTER_CQWAIT_REG = 34,
619
+
602
620
  /* this goes last */
603
621
  IORING_REGISTER_LAST,
604
622
 
@@ -684,6 +702,20 @@ struct io_uring_clock_register {
684
702
  __u32 __resv[3];
685
703
  };
686
704
 
705
+ enum {
706
+ IORING_REGISTER_SRC_REGISTERED = (1U << 0),
707
+ IORING_REGISTER_DST_REPLACE = (1U << 1),
708
+ };
709
+
710
+ struct io_uring_clone_buffers {
711
+ __u32 src_fd;
712
+ __u32 flags;
713
+ __u32 src_off;
714
+ __u32 dst_off;
715
+ __u32 nr;
716
+ __u32 pad[3];
717
+ };
718
+
687
719
  struct io_uring_buf {
688
720
  __u64 addr;
689
721
  __u32 len;
@@ -716,9 +748,17 @@ struct io_uring_buf_ring {
716
748
  * mmap(2) with the offset set as:
717
749
  * IORING_OFF_PBUF_RING | (bgid << IORING_OFF_PBUF_SHIFT)
718
750
  * to get a virtual mapping for the ring.
751
+ * IOU_PBUF_RING_INC: If set, buffers consumed from this buffer ring can be
752
+ * consumed incrementally. Normally one (or more) buffers
753
+ * are fully consumed. With incremental consumptions, it's
754
+ * feasible to register big ranges of buffers, and each
755
+ * use of it will consume only as much as it needs. This
756
+ * requires that both the kernel and application keep
757
+ * track of where the current read/recv index is at.
719
758
  */
720
759
  enum io_uring_register_pbuf_ring_flags {
721
760
  IOU_PBUF_RING_MMAP = 1,
761
+ IOU_PBUF_RING_INC = 2,
722
762
  };
723
763
 
724
764
  /* argument for IORING_(UN)REGISTER_PBUF_RING */
@@ -764,6 +804,43 @@ enum io_uring_register_restriction_op {
764
804
  IORING_RESTRICTION_LAST
765
805
  };
766
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
+ */
767
844
  struct io_uring_getevents_arg {
768
845
  __u64 sigmask;
769
846
  __u32 sigmask_sz;
@@ -0,0 +1,39 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ #ifndef LIBURING_SANITIZE_H
3
+ #define LIBURING_SANITIZE_H
4
+
5
+ #ifdef __cplusplus
6
+ extern "C" {
7
+ #endif
8
+
9
+ struct io_uring;
10
+ struct iovec;
11
+
12
+ #if defined(CONFIG_USE_SANITIZER)
13
+ void liburing_sanitize_ring(struct io_uring *ring);
14
+ void liburing_sanitize_address(const void *addr);
15
+ void liburing_sanitize_region(const void *addr, unsigned int len);
16
+ void liburing_sanitize_iovecs(const struct iovec *iovecs, unsigned nr);
17
+ #else
18
+ #define __maybe_unused __attribute__((__unused__))
19
+ static inline void liburing_sanitize_ring(struct io_uring __maybe_unused *ring)
20
+ {
21
+ }
22
+ static inline void liburing_sanitize_address(const void __maybe_unused *addr)
23
+ {
24
+ }
25
+ static inline void liburing_sanitize_region(const void __maybe_unused *addr,
26
+ unsigned int __maybe_unused len)
27
+ {
28
+ }
29
+ static inline void liburing_sanitize_iovecs(const struct iovec __maybe_unused *iovecs,
30
+ unsigned __maybe_unused nr)
31
+ {
32
+ }
33
+ #endif
34
+
35
+ #ifdef __cplusplus
36
+ }
37
+ #endif
38
+
39
+ #endif
@@ -19,6 +19,7 @@
19
19
  #include "liburing/io_uring_version.h"
20
20
  #include "liburing/barrier.h"
21
21
 
22
+
22
23
  #ifndef uring_unlikely
23
24
  #define uring_unlikely(cond) __builtin_expect(!!(cond), 0)
24
25
  #endif
@@ -195,7 +196,17 @@ int io_uring_submit_and_wait_min_timeout(struct io_uring *ring,
195
196
  struct __kernel_timespec *ts,
196
197
  unsigned min_wait,
197
198
  sigset_t *sigmask);
198
-
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);
209
+ int io_uring_clone_buffers(struct io_uring *dst, struct io_uring *src);
199
210
  int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs,
200
211
  unsigned nr_iovecs);
201
212
  int io_uring_register_buffers_tags(struct io_uring *ring,
@@ -232,8 +243,10 @@ int io_uring_register_restrictions(struct io_uring *ring,
232
243
  unsigned int nr_res);
233
244
  int io_uring_enable_rings(struct io_uring *ring);
234
245
  int __io_uring_sqring_wait(struct io_uring *ring);
246
+ #ifdef _GNU_SOURCE
235
247
  int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz,
236
248
  const cpu_set_t *mask);
249
+ #endif
237
250
  int io_uring_unregister_iowq_aff(struct io_uring *ring);
238
251
  int io_uring_register_iowq_max_workers(struct io_uring *ring,
239
252
  unsigned int *values);
@@ -271,13 +284,20 @@ int io_uring_setup(unsigned int entries, struct io_uring_params *p);
271
284
  int io_uring_register(unsigned int fd, unsigned int opcode, const void *arg,
272
285
  unsigned int nr_args);
273
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
+
274
294
  /*
275
295
  * Mapped buffer ring alloc/register + unregister/free helpers
276
296
  */
277
297
  struct io_uring_buf_ring *io_uring_setup_buf_ring(struct io_uring *ring,
278
298
  unsigned int nentries,
279
299
  int bgid, unsigned int flags,
280
- int *ret);
300
+ int *err);
281
301
  int io_uring_free_buf_ring(struct io_uring *ring, struct io_uring_buf_ring *br,
282
302
  unsigned int nentries, int bgid);
283
303
 
@@ -301,15 +321,22 @@ int __io_uring_get_cqe(struct io_uring *ring,
301
321
  #define io_uring_cqe_index(ring,ptr,mask) \
302
322
  (((ptr) & (mask)) << io_uring_cqe_shift(ring))
303
323
 
324
+ /*
325
+ * NOTE: we should just get rid of the 'head' being passed in here, it doesn't
326
+ * serve a purpose anymore. The below is a bit of a work-around to ensure that
327
+ * the compiler doesn't complain about 'head' being unused (or only written,
328
+ * never read), as we use a local iterator for both the head and tail tracking.
329
+ */
304
330
  #define io_uring_for_each_cqe(ring, head, cqe) \
305
331
  /* \
306
332
  * io_uring_smp_load_acquire() enforces the order of tail \
307
333
  * and CQE reads. \
308
334
  */ \
309
- for (head = *(ring)->cq.khead; \
310
- (cqe = (head != io_uring_smp_load_acquire((ring)->cq.ktail) ? \
311
- &(ring)->cq.cqes[io_uring_cqe_index(ring, head, (ring)->cq.ring_mask)] : NULL)); \
312
- head++) \
335
+ for (__u32 __HEAD__ = (head) = *(ring)->cq.khead, \
336
+ __TAIL__ = io_uring_smp_load_acquire((ring)->cq.ktail); \
337
+ (cqe = ((head) != __TAIL__ ? \
338
+ &(ring)->cq.cqes[io_uring_cqe_index(ring, __HEAD__, (ring)->cq.ring_mask)] : NULL)); \
339
+ (head) = ++__HEAD__)
313
340
 
314
341
  /*
315
342
  * Must be called after io_uring_for_each_cqe()
@@ -734,6 +761,20 @@ IOURINGINLINE void io_uring_prep_openat_direct(struct io_uring_sqe *sqe,
734
761
  __io_uring_set_target_fixed_file(sqe, file_index);
735
762
  }
736
763
 
764
+ IOURINGINLINE void io_uring_prep_open(struct io_uring_sqe *sqe,
765
+ const char *path, int flags, mode_t mode)
766
+ {
767
+ io_uring_prep_openat(sqe, AT_FDCWD, path, flags, mode);
768
+ }
769
+
770
+ /* open directly into the fixed file table */
771
+ IOURINGINLINE void io_uring_prep_open_direct(struct io_uring_sqe *sqe,
772
+ const char *path, int flags, mode_t mode,
773
+ unsigned file_index)
774
+ {
775
+ io_uring_prep_openat_direct(sqe, AT_FDCWD, path, flags, mode, file_index);
776
+ }
777
+
737
778
  IOURINGINLINE void io_uring_prep_close(struct io_uring_sqe *sqe, int fd)
738
779
  {
739
780
  io_uring_prep_rw(IORING_OP_CLOSE, sqe, fd, NULL, 0, 0);
@@ -1259,11 +1300,23 @@ IOURINGINLINE void io_uring_prep_fixed_fd_install(struct io_uring_sqe *sqe,
1259
1300
  sqe->install_fd_flags = flags;
1260
1301
  }
1261
1302
 
1303
+ #ifdef _GNU_SOURCE
1262
1304
  IOURINGINLINE void io_uring_prep_ftruncate(struct io_uring_sqe *sqe,
1263
1305
  int fd, loff_t len)
1264
1306
  {
1265
1307
  io_uring_prep_rw(IORING_OP_FTRUNCATE, sqe, fd, 0, 0, len);
1266
1308
  }
1309
+ #endif
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
+ }
1267
1320
 
1268
1321
  /*
1269
1322
  * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
@@ -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 = 1,
7
- INT_FLAG_REG_REG_RING = 2,
8
- INT_FLAG_APP_MEM = 4,
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
@@ -208,4 +208,20 @@ LIBURING_2.7 {
208
208
  LIBURING_2.8 {
209
209
  global:
210
210
  io_uring_register_clock;
211
+ io_uring_submit_and_wait_min_timeout;
212
+ io_uring_wait_cqes_min_timeout;
213
+ io_uring_clone_buffers;
214
+ io_uring_prep_cmd_discard;
215
+ io_uring_prep_open;
216
+ io_uring_prep_open_direct;
211
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;
@@ -101,4 +101,14 @@ LIBURING_2.8 {
101
101
  io_uring_register_clock;
102
102
  io_uring_submit_and_wait_min_timeout;
103
103
  io_uring_wait_cqes_min_timeout;
104
+ io_uring_clone_buffers;
104
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;
@@ -5,7 +5,7 @@
5
5
  #include "syscall.h"
6
6
  #include "liburing.h"
7
7
  #include "int_flags.h"
8
- #include "liburing/compat.h"
8
+ #include "liburing/sanitize.h"
9
9
  #include "liburing/io_uring.h"
10
10
 
11
11
  /*
@@ -69,7 +69,7 @@ static int _io_uring_get_cqe(struct io_uring *ring,
69
69
 
70
70
  do {
71
71
  bool need_enter = false;
72
- unsigned flags = 0;
72
+ unsigned flags = ring_enter_flags(ring);
73
73
  unsigned nr_available;
74
74
  int ret;
75
75
 
@@ -93,7 +93,7 @@ static int _io_uring_get_cqe(struct io_uring *ring,
93
93
  need_enter = true;
94
94
  }
95
95
  if (data->wait_nr > nr_available || need_enter) {
96
- flags = IORING_ENTER_GETEVENTS | data->get_flags;
96
+ flags |= IORING_ENTER_GETEVENTS | data->get_flags;
97
97
  need_enter = true;
98
98
  }
99
99
  if (sq_ring_needs_enter(ring, data->submit, &flags))
@@ -108,8 +108,6 @@ static int _io_uring_get_cqe(struct io_uring *ring,
108
108
  break;
109
109
  }
110
110
 
111
- if (ring->int_flags & INT_FLAG_REG_RING)
112
- flags |= IORING_ENTER_REGISTERED_RING;
113
111
  ret = __sys_io_uring_enter2(ring->enter_ring_fd, data->submit,
114
112
  data->wait_nr, flags, data->arg,
115
113
  data->sz);
@@ -148,10 +146,8 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr,
148
146
 
149
147
  int io_uring_get_events(struct io_uring *ring)
150
148
  {
151
- int flags = IORING_ENTER_GETEVENTS;
149
+ int flags = IORING_ENTER_GETEVENTS | ring_enter_flags(ring);
152
150
 
153
- if (ring->int_flags & INT_FLAG_REG_RING)
154
- flags |= IORING_ENTER_REGISTERED_RING;
155
151
  return __sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL);
156
152
  }
157
153
 
@@ -324,6 +320,26 @@ int io_uring_wait_cqes_min_timeout(struct io_uring *ring,
324
320
  sigmask);
325
321
  }
326
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
+
327
343
  static int __io_uring_submit_and_wait_timeout(struct io_uring *ring,
328
344
  struct io_uring_cqe **cqe_ptr, unsigned wait_nr,
329
345
  struct __kernel_timespec *ts,
@@ -402,15 +418,14 @@ static int __io_uring_submit(struct io_uring *ring, unsigned submitted,
402
418
  unsigned wait_nr, bool getevents)
403
419
  {
404
420
  bool cq_needs_enter = getevents || wait_nr || cq_ring_needs_enter(ring);
405
- unsigned flags;
421
+ unsigned flags = ring_enter_flags(ring);
406
422
  int ret;
407
423
 
408
- flags = 0;
424
+ liburing_sanitize_ring(ring);
425
+
409
426
  if (sq_ring_needs_enter(ring, submitted, &flags) || cq_needs_enter) {
410
427
  if (cq_needs_enter)
411
428
  flags |= IORING_ENTER_GETEVENTS;
412
- if (ring->int_flags & INT_FLAG_REG_RING)
413
- flags |= IORING_ENTER_REGISTERED_RING;
414
429
 
415
430
  ret = __sys_io_uring_enter(ring->enter_ring_fd, submitted,
416
431
  wait_nr, flags, NULL);
@@ -459,10 +474,7 @@ struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring)
459
474
 
460
475
  int __io_uring_sqring_wait(struct io_uring *ring)
461
476
  {
462
- int flags = IORING_ENTER_SQ_WAIT;
463
-
464
- if (ring->int_flags & INT_FLAG_REG_RING)
465
- flags |= IORING_ENTER_REGISTERED_RING;
477
+ int flags = IORING_ENTER_SQ_WAIT | ring_enter_flags(ring);
466
478
 
467
479
  return __sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL);
468
480
  }