polyphony 1.4 → 1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +22 -0
  4. data/TODO.md +5 -14
  5. data/examples/pipes/http_server.rb +42 -12
  6. data/examples/pipes/http_server2.rb +45 -0
  7. data/ext/polyphony/backend_common.h +5 -0
  8. data/ext/polyphony/backend_io_uring.c +174 -121
  9. data/ext/polyphony/backend_io_uring_context.c +24 -18
  10. data/ext/polyphony/backend_io_uring_context.h +4 -2
  11. data/ext/polyphony/backend_libev.c +46 -22
  12. data/ext/polyphony/event.c +21 -0
  13. data/ext/polyphony/extconf.rb +25 -19
  14. data/ext/polyphony/fiber.c +0 -2
  15. data/ext/polyphony/pipe.c +1 -1
  16. data/ext/polyphony/polyphony.c +2 -20
  17. data/ext/polyphony/polyphony.h +5 -5
  18. data/ext/polyphony/ring_buffer.c +1 -0
  19. data/ext/polyphony/runqueue_ring_buffer.c +1 -0
  20. data/ext/polyphony/thread.c +63 -0
  21. data/ext/polyphony/win_uio.h +18 -0
  22. data/lib/polyphony/adapters/open3.rb +190 -0
  23. data/lib/polyphony/core/sync.rb +83 -13
  24. data/lib/polyphony/core/timer.rb +7 -25
  25. data/lib/polyphony/extensions/exception.rb +15 -0
  26. data/lib/polyphony/extensions/fiber.rb +14 -13
  27. data/lib/polyphony/extensions/io.rb +56 -14
  28. data/lib/polyphony/extensions/kernel.rb +1 -1
  29. data/lib/polyphony/extensions/object.rb +1 -13
  30. data/lib/polyphony/extensions/process.rb +76 -1
  31. data/lib/polyphony/extensions/socket.rb +0 -14
  32. data/lib/polyphony/extensions/thread.rb +19 -27
  33. data/lib/polyphony/extensions/timeout.rb +5 -1
  34. data/lib/polyphony/version.rb +1 -1
  35. data/lib/polyphony.rb +11 -5
  36. data/test/helper.rb +46 -4
  37. data/test/open3/envutil.rb +380 -0
  38. data/test/open3/find_executable.rb +24 -0
  39. data/test/stress.rb +11 -7
  40. data/test/test_backend.rb +11 -4
  41. data/test/test_event.rb +10 -3
  42. data/test/test_ext.rb +16 -1
  43. data/test/test_fiber.rb +16 -4
  44. data/test/test_global_api.rb +17 -16
  45. data/test/test_io.rb +39 -0
  46. data/test/test_kernel.rb +2 -2
  47. data/test/test_monitor.rb +356 -0
  48. data/test/test_open3.rb +338 -0
  49. data/test/test_signal.rb +5 -1
  50. data/test/test_socket.rb +6 -98
  51. data/test/test_sync.rb +46 -0
  52. data/test/test_thread.rb +10 -1
  53. data/test/test_thread_pool.rb +5 -0
  54. data/test/test_throttler.rb +1 -1
  55. data/test/test_timer.rb +8 -2
  56. data/test/test_trace.rb +2 -0
  57. data/vendor/liburing/.github/workflows/build.yml +8 -0
  58. data/vendor/liburing/.gitignore +1 -0
  59. data/vendor/liburing/CHANGELOG +8 -0
  60. data/vendor/liburing/configure +17 -25
  61. data/vendor/liburing/debian/liburing-dev.manpages +2 -0
  62. data/vendor/liburing/debian/rules +2 -1
  63. data/vendor/liburing/examples/Makefile +2 -1
  64. data/vendor/liburing/examples/io_uring-udp.c +11 -3
  65. data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
  66. data/vendor/liburing/liburing.spec +1 -1
  67. data/vendor/liburing/make-debs.sh +4 -2
  68. data/vendor/liburing/src/Makefile +5 -5
  69. data/vendor/liburing/src/arch/aarch64/lib.h +1 -1
  70. data/vendor/liburing/src/include/liburing/io_uring.h +41 -16
  71. data/vendor/liburing/src/include/liburing.h +86 -11
  72. data/vendor/liburing/src/int_flags.h +1 -0
  73. data/vendor/liburing/src/liburing-ffi.map +12 -0
  74. data/vendor/liburing/src/liburing.map +8 -0
  75. data/vendor/liburing/src/register.c +7 -2
  76. data/vendor/liburing/src/setup.c +373 -81
  77. data/vendor/liburing/test/232c93d07b74.c +3 -3
  78. data/vendor/liburing/test/Makefile +10 -3
  79. data/vendor/liburing/test/accept.c +2 -1
  80. data/vendor/liburing/test/buf-ring.c +35 -75
  81. data/vendor/liburing/test/connect-rep.c +204 -0
  82. data/vendor/liburing/test/coredump.c +59 -0
  83. data/vendor/liburing/test/fallocate.c +9 -0
  84. data/vendor/liburing/test/fd-pass.c +34 -3
  85. data/vendor/liburing/test/file-verify.c +27 -6
  86. data/vendor/liburing/test/helpers.c +3 -1
  87. data/vendor/liburing/test/io_uring_register.c +25 -28
  88. data/vendor/liburing/test/io_uring_setup.c +1 -1
  89. data/vendor/liburing/test/poll-cancel-all.c +29 -5
  90. data/vendor/liburing/test/poll-race-mshot.c +6 -22
  91. data/vendor/liburing/test/read-write.c +53 -0
  92. data/vendor/liburing/test/recv-msgall.c +21 -23
  93. data/vendor/liburing/test/reg-fd-only.c +55 -0
  94. data/vendor/liburing/test/reg-hint.c +56 -0
  95. data/vendor/liburing/test/regbuf-merge.c +91 -0
  96. data/vendor/liburing/test/ringbuf-read.c +2 -10
  97. data/vendor/liburing/test/send_recvmsg.c +5 -16
  98. data/vendor/liburing/test/shutdown.c +2 -1
  99. data/vendor/liburing/test/socket-io-cmd.c +215 -0
  100. data/vendor/liburing/test/socket-rw-eagain.c +2 -1
  101. data/vendor/liburing/test/socket-rw-offset.c +2 -1
  102. data/vendor/liburing/test/socket-rw.c +2 -1
  103. data/vendor/liburing/test/timeout.c +276 -0
  104. data/vendor/liburing/test/xattr.c +38 -25
  105. metadata +20 -7
  106. data/vendor/liburing/test/timeout-overflow.c +0 -204
@@ -5,22 +5,6 @@ set -e
5
5
  cc=${CC:-gcc}
6
6
  cxx=${CXX:-g++}
7
7
 
8
- #
9
- # TODO(ammarfaizi2): Remove this notice and `--nolibc` option.
10
- #
11
- nolibc_deprecated() {
12
- echo "";
13
- echo "=================================================================";
14
- echo "";
15
- echo " --nolibc option is deprecated and has no effect.";
16
- echo " It will be removed in a future liburing release.";
17
- echo "";
18
- echo " liburing on x86-64, x86 (32-bit) and aarch64 always use CONFIG_NOLIBC.";
19
- echo "";
20
- echo "=================================================================";
21
- echo "";
22
- }
23
-
24
8
  for opt do
25
9
  optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)' || true)
26
10
  case "$opt" in
@@ -42,7 +26,7 @@ for opt do
42
26
  ;;
43
27
  --cxx=*) cxx="$optarg"
44
28
  ;;
45
- --nolibc) nolibc_deprecated
29
+ --use-libc) use_libc=yes
46
30
  ;;
47
31
  *)
48
32
  echo "ERROR: unknown option $opt"
@@ -91,7 +75,7 @@ Options: [defaults in brackets after descriptions]
91
75
  --datadir=PATH install shared data in PATH [$datadir]
92
76
  --cc=CMD use CMD as the C compiler
93
77
  --cxx=CMD use CMD as the C++ compiler
94
- --nolibc build liburing without libc
78
+ --use-libc use libc for liburing (useful for hardening)
95
79
  EOF
96
80
  exit 0
97
81
  fi
@@ -401,10 +385,13 @@ fi
401
385
  print_config "NVMe uring command support" "$nvme_uring_cmd"
402
386
 
403
387
  #############################################################################
404
- #
405
- # Currently, CONFIG_NOLIBC is only enabled on x86-64, x86 (32-bit) and aarch64.
406
- #
407
- cat > $TMPC << EOF
388
+ liburing_nolibc="no"
389
+ if test "$use_libc" != "yes"; then
390
+
391
+ #
392
+ # Currently, CONFIG_NOLIBC only supports x86-64, x86 (32-bit) and aarch64.
393
+ #
394
+ cat > $TMPC << EOF
408
395
  int main(void){
409
396
  #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__)
410
397
  return 0;
@@ -413,10 +400,13 @@ int main(void){
413
400
  #endif
414
401
  }
415
402
  EOF
416
- if compile_prog "" "" "nolibc support"; then
417
- liburing_nolibc="yes"
403
+
404
+ if compile_prog "" "" "nolibc"; then
405
+ liburing_nolibc="yes"
406
+ fi
418
407
  fi
419
- print_config "nolibc support" "$liburing_nolibc";
408
+
409
+ print_config "nolibc" "$liburing_nolibc";
420
410
  #############################################################################
421
411
 
422
412
  ####################################################
@@ -478,6 +468,8 @@ echo "CXX=$cxx" >> $config_host_mak
478
468
  print_config "CXX" "$cxx"
479
469
 
480
470
  # generate io_uring_version.h
471
+ # Reset MAKEFLAGS
472
+ MAKEFLAGS=
481
473
  MAKE_PRINT_VARS="include Makefile.common\nprint-%: ; @echo \$(\$*)\n"
482
474
  VERSION_MAJOR=$(env echo -e "$MAKE_PRINT_VARS" | make -s --no-print-directory -f - print-VERSION_MAJOR)
483
475
  VERSION_MINOR=$(env echo -e "$MAKE_PRINT_VARS" | make -s --no-print-directory -f - print-VERSION_MINOR)
@@ -1,3 +1,5 @@
1
1
  usr/share/man/man2/io_uring_*.2
2
2
  usr/share/man/man3/io_uring_*.3
3
3
  usr/share/man/man7/io_uring.7
4
+ usr/share/man/man3/IO_URING_*.3
5
+ usr/share/man/man3/__io_uring_*.3
@@ -5,12 +5,13 @@
5
5
 
6
6
  DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow
7
7
  DEB_CFLAGS_MAINT_PREPEND = -Wall
8
+ DEB_BUILD_OPTIONS += nocheck
8
9
 
9
10
  include /usr/share/dpkg/default.mk
10
11
  include /usr/share/dpkg/buildtools.mk
11
12
 
12
13
  %:
13
- dh $@
14
+ dh $@ --parallel
14
15
 
15
16
  override_dh_auto_configure:
16
17
  ./configure \
@@ -20,7 +20,8 @@ example_srcs := \
20
20
  io_uring-udp.c \
21
21
  link-cp.c \
22
22
  poll-bench.c \
23
- send-zerocopy.c
23
+ send-zerocopy.c \
24
+ rsrc-update-bench.c
24
25
 
25
26
  all_targets :=
26
27
 
@@ -271,14 +271,22 @@ static int process_cqe_recv(struct ctx *ctx, struct io_uring_cqe *cqe,
271
271
  }
272
272
 
273
273
  if (ctx->verbose) {
274
+ struct sockaddr_in *addr = io_uring_recvmsg_name(o);
275
+ struct sockaddr_in6 *addr6 = (void *)addr;
274
276
  char buff[INET6_ADDRSTRLEN + 1];
275
277
  const char *name;
276
- struct sockaddr_in *addr = io_uring_recvmsg_name(o);
278
+ void *paddr;
277
279
 
278
- name = inet_ntop(ctx->af, &addr->sin_addr, buff, sizeof(buff));
280
+ if (ctx->af == AF_INET6)
281
+ paddr = &addr6->sin6_addr;
282
+ else
283
+ paddr = &addr->sin_addr;
284
+
285
+ name = inet_ntop(ctx->af, paddr, buff, sizeof(buff));
279
286
  if (!name)
280
287
  name = "<INVALID>";
281
- fprintf(stderr, "received %u bytes %d from %s:%d\n",
288
+
289
+ fprintf(stderr, "received %u bytes %d from [%s]:%d\n",
282
290
  io_uring_recvmsg_payload_length(o, cqe->res, &ctx->msg),
283
291
  o->namelen, name, (int)ntohs(addr->sin_port));
284
292
  }
@@ -0,0 +1,100 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ #include <errno.h>
3
+ #include <stdio.h>
4
+ #include <unistd.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <signal.h>
8
+ #include <poll.h>
9
+ #include <sys/time.h>
10
+ #include <sys/wait.h>
11
+
12
+ #include "liburing.h"
13
+
14
+ static unsigned long runtime_ms = 10000;
15
+
16
+ static unsigned long gettimeofday_ms(void)
17
+ {
18
+ struct timeval tv;
19
+
20
+ gettimeofday(&tv, NULL);
21
+ return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
22
+ }
23
+
24
+ int main(void)
25
+ {
26
+ unsigned long tstop;
27
+ unsigned long nr_reqs = 0;
28
+ struct io_uring_cqe *cqe;
29
+ struct io_uring_sqe *sqe;
30
+ struct io_uring ring;
31
+ int pipe1[2];
32
+ int ret, i, qd = 32;
33
+ int table_size = 128;
34
+
35
+ if (pipe(pipe1) != 0) {
36
+ perror("pipe");
37
+ return 1;
38
+ }
39
+
40
+ ret = io_uring_queue_init(1024, &ring, IORING_SETUP_SINGLE_ISSUER |
41
+ IORING_SETUP_DEFER_TASKRUN);
42
+ if (ret) {
43
+ fprintf(stderr, "io_uring_queue_init failed: %d\n", ret);
44
+ return 1;
45
+ }
46
+ ret = io_uring_register_ring_fd(&ring);
47
+ if (ret < 0) {
48
+ fprintf(stderr, "io_uring_register_ring_fd failed\n");
49
+ return 1;
50
+ }
51
+ ret = io_uring_register_files_sparse(&ring, table_size);
52
+ if (ret < 0) {
53
+ fprintf(stderr, "io_uring_register_files_sparse failed\n");
54
+ return 1;
55
+ }
56
+
57
+ for (i = 0; i < table_size; i++) {
58
+ ret = io_uring_register_files_update(&ring, i, pipe1, 1);
59
+ if (ret < 0) {
60
+ fprintf(stderr, "io_uring_register_files_update failed\n");
61
+ return 1;
62
+ }
63
+ }
64
+
65
+ srand(time(NULL));
66
+
67
+ tstop = gettimeofday_ms() + runtime_ms;
68
+ do {
69
+ int off = rand();
70
+
71
+ for (i = 0; i < qd; i++) {
72
+ sqe = io_uring_get_sqe(&ring);
73
+ int roff = (off + i) % table_size;
74
+ io_uring_prep_files_update(sqe, pipe1, 1, roff);
75
+ }
76
+
77
+ ret = io_uring_submit(&ring);
78
+ if (ret != qd) {
79
+ fprintf(stderr, "child: sqe submit failed: %d\n", ret);
80
+ return 1;
81
+ }
82
+
83
+ for (i = 0; i < qd; i++) {
84
+ ret = io_uring_wait_cqe(&ring, &cqe);
85
+ if (ret < 0) {
86
+ fprintf(stderr, "child: wait completion %d\n", ret);
87
+ break;
88
+ }
89
+ io_uring_cqe_seen(&ring, cqe);
90
+ nr_reqs++;
91
+ }
92
+ } while (gettimeofday_ms() < tstop);
93
+
94
+ fprintf(stderr, "max updates/s: %lu\n", nr_reqs * 1000UL / runtime_ms);
95
+
96
+ io_uring_queue_exit(&ring);
97
+ close(pipe1[0]);
98
+ close(pipe1[1]);
99
+ return 0;
100
+ }
@@ -1,5 +1,5 @@
1
1
  Name: liburing
2
- Version: 2.4
2
+ Version: 2.5
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
@@ -23,6 +23,8 @@ distro=unstable
23
23
  releasedir=$base/$(lsb_release -si)/liburing
24
24
  rm -rf $releasedir
25
25
  mkdir -p $releasedir
26
+ HEAD=$(which head)
27
+ DCH=$(which dch)
26
28
 
27
29
  src_dir=$(readlink -e `basename $0`)
28
30
  liburing_dir=$(dirname $src_dir)
@@ -38,9 +40,9 @@ cd ${releasedir}/${outfile}
38
40
  git clean -dxf
39
41
 
40
42
  # Change changelog if it's needed
41
- cur_ver=`head -l debian/changelog | sed -n -e 's/.* (\(.*\)) .*/\1/p'`
43
+ cur_ver=`$HEAD < debian/changelog | sed -n -e 's/.* (\(.*\)) .*/\1/p'`
42
44
  if [ "$cur_ver" != "$version-1" ]; then
43
- dch -D $distro --force-distribution -b -v "$version-1" "new version"
45
+ $DCH -D $distro --force-distribution -b -v "$version-1" "new version"
44
46
  fi
45
47
 
46
48
  # Create tar archieve
@@ -11,12 +11,12 @@ override CPPFLAGS += -D_GNU_SOURCE \
11
11
  -Iinclude/ -include ../config-host.h \
12
12
  -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
13
13
  CFLAGS ?= -g -O3 -Wall -Wextra -fno-stack-protector
14
- override CFLAGS += -Wno-unused-parameter -Wno-sign-compare \
14
+ override CFLAGS += -Wno-unused-parameter \
15
15
  -DLIBURING_INTERNAL \
16
16
  $(LIBURING_CFLAGS)
17
17
  SO_CFLAGS=-fPIC $(CFLAGS)
18
18
  L_CFLAGS=$(CFLAGS)
19
- LINK_FLAGS=
19
+ LINK_FLAGS=-Wl,-z,defs
20
20
  LINK_FLAGS+=$(LDFLAGS)
21
21
  ENABLE_SHARED ?= 1
22
22
 
@@ -45,8 +45,8 @@ liburing_srcs := setup.c queue.c register.c syscall.c version.c
45
45
 
46
46
  ifeq ($(CONFIG_NOLIBC),y)
47
47
  liburing_srcs += nolibc.c
48
- override CFLAGS += -nostdlib -nodefaultlibs -ffreestanding
49
- override CPPFLAGS += -nostdlib -nodefaultlibs -ffreestanding
48
+ override CFLAGS += -nostdlib -nodefaultlibs -ffreestanding -fno-builtin -fno-stack-protector
49
+ override CPPFLAGS += -nostdlib -nodefaultlibs -ffreestanding -fno-builtin -fno-stack-protector
50
50
  override LINK_FLAGS += -nostdlib -nodefaultlibs
51
51
  endif
52
52
 
@@ -81,7 +81,7 @@ liburing-ffi.a: $(liburing_objs) $(liburing_ffi_objs)
81
81
  $(libname): $(liburing_sobjs) liburing.map
82
82
  $(QUIET_CC)$(CC) $(SO_CFLAGS) -shared -Wl,--version-script=liburing.map -Wl,-soname=$(soname) -o $@ $(liburing_sobjs) $(LINK_FLAGS)
83
83
 
84
- $(ffi_libname): $(liburing_ffi_objs) $(liburing_ffi_sobjs) liburing-ffi.map
84
+ $(ffi_libname): $(liburing_ffi_objs) $(liburing_ffi_sobjs) $(liburing_sobjs) liburing-ffi.map
85
85
  $(QUIET_CC)$(CC) $(SO_CFLAGS) -shared -Wl,--version-script=liburing-ffi.map -Wl,-soname=$(ffi_soname) -o $@ $(liburing_sobjs) $(liburing_ffi_sobjs) $(LINK_FLAGS)
86
86
 
87
87
  install: $(all_targets)
@@ -21,7 +21,7 @@ static inline long __get_page_size(void)
21
21
  ssize_t x;
22
22
 
23
23
  x = __sys_read(fd, buf, sizeof(buf));
24
- if (x < sizeof(buf))
24
+ if (x < (long) sizeof(buf))
25
25
  break;
26
26
 
27
27
  if (buf[0] == AT_PAGESZ) {
@@ -173,6 +173,18 @@ enum {
173
173
  */
174
174
  #define IORING_SETUP_DEFER_TASKRUN (1U << 13)
175
175
 
176
+ /*
177
+ * Application provides ring memory
178
+ */
179
+ #define IORING_SETUP_NO_MMAP (1U << 14)
180
+
181
+ /*
182
+ * Register the ring fd in itself for use with
183
+ * IORING_REGISTER_USE_REGISTERED_RING; return a registered fd index rather
184
+ * than an fd.
185
+ */
186
+ #define IORING_SETUP_REGISTERED_FD_ONLY (1U << 15)
187
+
176
188
  enum io_uring_op {
177
189
  IORING_OP_NOP,
178
190
  IORING_OP_READV,
@@ -250,6 +262,7 @@ enum io_uring_op {
250
262
  #define IORING_TIMEOUT_REALTIME (1U << 3)
251
263
  #define IORING_LINK_TIMEOUT_UPDATE (1U << 4)
252
264
  #define IORING_TIMEOUT_ETIME_SUCCESS (1U << 5)
265
+ #define IORING_TIMEOUT_MULTISHOT (1U << 6)
253
266
  #define IORING_TIMEOUT_CLOCK_MASK (IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME)
254
267
  #define IORING_TIMEOUT_UPDATE_MASK (IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE)
255
268
  /*
@@ -389,6 +402,9 @@ enum {
389
402
  #define IORING_OFF_SQ_RING 0ULL
390
403
  #define IORING_OFF_CQ_RING 0x8000000ULL
391
404
  #define IORING_OFF_SQES 0x10000000ULL
405
+ #define IORING_OFF_PBUF_RING 0x80000000ULL
406
+ #define IORING_OFF_PBUF_SHIFT 16
407
+ #define IORING_OFF_MMAP_MASK 0xf8000000ULL
392
408
 
393
409
  /*
394
410
  * Filled with the offset for mmap(2)
@@ -402,7 +418,7 @@ struct io_sqring_offsets {
402
418
  __u32 dropped;
403
419
  __u32 array;
404
420
  __u32 resv1;
405
- __u64 resv2;
421
+ __u64 user_addr;
406
422
  };
407
423
 
408
424
  /*
@@ -421,7 +437,7 @@ struct io_cqring_offsets {
421
437
  __u32 cqes;
422
438
  __u32 flags;
423
439
  __u32 resv1;
424
- __u64 resv2;
440
+ __u64 user_addr;
425
441
  };
426
442
 
427
443
  /*
@@ -568,19 +584,6 @@ struct io_uring_rsrc_update2 {
568
584
  __u32 resv2;
569
585
  };
570
586
 
571
- struct io_uring_notification_slot {
572
- __u64 tag;
573
- __u64 resv[3];
574
- };
575
-
576
- struct io_uring_notification_register {
577
- __u32 nr_slots;
578
- __u32 resv;
579
- __u64 resv2;
580
- __u64 data;
581
- __u64 resv3;
582
- };
583
-
584
587
  /* Skip updating fd indexes set to this value in the fd table */
585
588
  #define IORING_REGISTER_FILES_SKIP (-2)
586
589
 
@@ -635,12 +638,26 @@ struct io_uring_buf_ring {
635
638
  };
636
639
  };
637
640
 
641
+ /*
642
+ * Flags for IORING_REGISTER_PBUF_RING.
643
+ *
644
+ * IOU_PBUF_RING_MMAP: If set, kernel will allocate the memory for the ring.
645
+ * The application must not set a ring_addr in struct
646
+ * io_uring_buf_reg, instead it must subsequently call
647
+ * mmap(2) with the offset set as:
648
+ * IORING_OFF_PBUF_RING | (bgid << IORING_OFF_PBUF_SHIFT)
649
+ * to get a virtual mapping for the ring.
650
+ */
651
+ enum {
652
+ IOU_PBUF_RING_MMAP = 1,
653
+ };
654
+
638
655
  /* argument for IORING_(UN)REGISTER_PBUF_RING */
639
656
  struct io_uring_buf_reg {
640
657
  __u64 ring_addr;
641
658
  __u32 ring_entries;
642
659
  __u16 bgid;
643
- __u16 pad;
660
+ __u16 flags;
644
661
  __u64 resv[3];
645
662
  };
646
663
 
@@ -698,6 +715,14 @@ struct io_uring_recvmsg_out {
698
715
  __u32 flags;
699
716
  };
700
717
 
718
+ /*
719
+ * Argument for IORING_OP_URING_CMD when file is a socket
720
+ */
721
+ enum {
722
+ SOCKET_URING_OP_SIOCINQ = 0,
723
+ SOCKET_URING_OP_SIOCOUTQ,
724
+ };
725
+
701
726
  #ifdef __cplusplus
702
727
  }
703
728
  #endif
@@ -164,6 +164,9 @@ IOURINGINLINE int io_uring_opcode_supported(const struct io_uring_probe *p,
164
164
  return (p->ops[op].flags & IO_URING_OP_SUPPORTED) != 0;
165
165
  }
166
166
 
167
+ int io_uring_queue_init_mem(unsigned entries, struct io_uring *ring,
168
+ struct io_uring_params *p,
169
+ void *buf, size_t buf_size);
167
170
  int io_uring_queue_init_params(unsigned entries, struct io_uring *ring,
168
171
  struct io_uring_params *p);
169
172
  int io_uring_queue_init(unsigned entries, struct io_uring *ring,
@@ -256,6 +259,16 @@ int io_uring_setup(unsigned int entries, struct io_uring_params *p);
256
259
  int io_uring_register(unsigned int fd, unsigned int opcode, const void *arg,
257
260
  unsigned int nr_args);
258
261
 
262
+ /*
263
+ * Mapped buffer ring alloc/register + unregister/free helpers
264
+ */
265
+ struct io_uring_buf_ring *io_uring_setup_buf_ring(struct io_uring *ring,
266
+ unsigned int nentries,
267
+ int bgid, unsigned int flags,
268
+ int *ret);
269
+ int io_uring_free_buf_ring(struct io_uring *ring, struct io_uring_buf_ring *br,
270
+ unsigned int nentries, int bgid);
271
+
259
272
  /*
260
273
  * Helper for the peek/wait single cqe functions. Exported because of that,
261
274
  * but probably shouldn't be used directly in an application.
@@ -594,6 +607,9 @@ IOURINGINLINE void io_uring_prep_accept_direct(struct io_uring_sqe *sqe, int fd,
594
607
  unsigned int file_index)
595
608
  {
596
609
  io_uring_prep_accept(sqe, fd, addr, addrlen, flags);
610
+ /* offset by 1 for allocation */
611
+ if (file_index == IORING_FILE_INDEX_ALLOC)
612
+ file_index--;
597
613
  __io_uring_set_target_fixed_file(sqe, file_index);
598
614
  }
599
615
 
@@ -661,7 +677,7 @@ IOURINGINLINE void io_uring_prep_files_update(struct io_uring_sqe *sqe,
661
677
  }
662
678
 
663
679
  IOURINGINLINE void io_uring_prep_fallocate(struct io_uring_sqe *sqe, int fd,
664
- int mode, off_t offset, off_t len)
680
+ int mode, __u64 offset, __u64 len)
665
681
  {
666
682
  io_uring_prep_rw(IORING_OP_FALLOCATE, sqe, fd,
667
683
  0, (unsigned int) mode, (__u64) offset);
@@ -683,6 +699,9 @@ IOURINGINLINE void io_uring_prep_openat_direct(struct io_uring_sqe *sqe,
683
699
  unsigned file_index)
684
700
  {
685
701
  io_uring_prep_openat(sqe, dfd, path, flags, mode);
702
+ /* offset by 1 for allocation */
703
+ if (file_index == IORING_FILE_INDEX_ALLOC)
704
+ file_index--;
686
705
  __io_uring_set_target_fixed_file(sqe, file_index);
687
706
  }
688
707
 
@@ -742,6 +761,23 @@ IOURINGINLINE void io_uring_prep_send(struct io_uring_sqe *sqe, int sockfd,
742
761
  sqe->msg_flags = (__u32) flags;
743
762
  }
744
763
 
764
+ IOURINGINLINE void io_uring_prep_send_set_addr(struct io_uring_sqe *sqe,
765
+ const struct sockaddr *dest_addr,
766
+ __u16 addr_len)
767
+ {
768
+ sqe->addr2 = (unsigned long)(const void *)dest_addr;
769
+ sqe->addr_len = addr_len;
770
+ }
771
+
772
+ IOURINGINLINE void io_uring_prep_sendto(struct io_uring_sqe *sqe, int sockfd,
773
+ const void *buf, size_t len, int flags,
774
+ const struct sockaddr *addr,
775
+ socklen_t addrlen)
776
+ {
777
+ io_uring_prep_send(sqe, sockfd, buf, len, flags);
778
+ io_uring_prep_send_set_addr(sqe, addr, addrlen);
779
+ }
780
+
745
781
  IOURINGINLINE void io_uring_prep_send_zc(struct io_uring_sqe *sqe, int sockfd,
746
782
  const void *buf, size_t len, int flags,
747
783
  unsigned zc_flags)
@@ -770,14 +806,6 @@ IOURINGINLINE void io_uring_prep_sendmsg_zc(struct io_uring_sqe *sqe, int fd,
770
806
  sqe->opcode = IORING_OP_SENDMSG_ZC;
771
807
  }
772
808
 
773
- IOURINGINLINE void io_uring_prep_send_set_addr(struct io_uring_sqe *sqe,
774
- const struct sockaddr *dest_addr,
775
- __u16 addr_len)
776
- {
777
- sqe->addr2 = (unsigned long)(const void *)dest_addr;
778
- sqe->addr_len = addr_len;
779
- }
780
-
781
809
  IOURINGINLINE void io_uring_prep_recv(struct io_uring_sqe *sqe, int sockfd,
782
810
  void *buf, size_t len, int flags)
783
811
  {
@@ -872,6 +900,9 @@ IOURINGINLINE void io_uring_prep_openat2_direct(struct io_uring_sqe *sqe,
872
900
  unsigned file_index)
873
901
  {
874
902
  io_uring_prep_openat2(sqe, dfd, path, how);
903
+ /* offset by 1 for allocation */
904
+ if (file_index == IORING_FILE_INDEX_ALLOC)
905
+ file_index--;
875
906
  __io_uring_set_target_fixed_file(sqe, file_index);
876
907
  }
877
908
 
@@ -1011,10 +1042,21 @@ IOURINGINLINE void io_uring_prep_msg_ring_fd(struct io_uring_sqe *sqe, int fd,
1011
1042
  io_uring_prep_rw(IORING_OP_MSG_RING, sqe, fd,
1012
1043
  (void *) (uintptr_t) IORING_MSG_SEND_FD, 0, data);
1013
1044
  sqe->addr3 = source_fd;
1045
+ /* offset by 1 for allocation */
1046
+ if ((unsigned int) target_fd == IORING_FILE_INDEX_ALLOC)
1047
+ target_fd--;
1014
1048
  __io_uring_set_target_fixed_file(sqe, target_fd);
1015
1049
  sqe->msg_ring_flags = flags;
1016
1050
  }
1017
1051
 
1052
+ IOURINGINLINE void io_uring_prep_msg_ring_fd_alloc(struct io_uring_sqe *sqe,
1053
+ int fd, int source_fd,
1054
+ __u64 data, unsigned int flags)
1055
+ {
1056
+ io_uring_prep_msg_ring_fd(sqe, fd, source_fd, IORING_FILE_INDEX_ALLOC,
1057
+ data, flags);
1058
+ }
1059
+
1018
1060
  IOURINGINLINE void io_uring_prep_getxattr(struct io_uring_sqe *sqe,
1019
1061
  const char *name, char *value,
1020
1062
  const char *path, unsigned int len)
@@ -1070,6 +1112,9 @@ IOURINGINLINE void io_uring_prep_socket_direct(struct io_uring_sqe *sqe,
1070
1112
  {
1071
1113
  io_uring_prep_rw(IORING_OP_SOCKET, sqe, domain, NULL, protocol, type);
1072
1114
  sqe->rw_flags = flags;
1115
+ /* offset by 1 for allocation */
1116
+ if (file_index == IORING_FILE_INDEX_ALLOC)
1117
+ file_index--;
1073
1118
  __io_uring_set_target_fixed_file(sqe, file_index);
1074
1119
  }
1075
1120
 
@@ -1083,6 +1128,29 @@ IOURINGINLINE void io_uring_prep_socket_direct_alloc(struct io_uring_sqe *sqe,
1083
1128
  __io_uring_set_target_fixed_file(sqe, IORING_FILE_INDEX_ALLOC - 1);
1084
1129
  }
1085
1130
 
1131
+
1132
+ #define UNUSED(x) (void)(x)
1133
+
1134
+ /*
1135
+ * Prepare commands for sockets
1136
+ */
1137
+ IOURINGINLINE void io_uring_prep_cmd_sock(struct io_uring_sqe *sqe,
1138
+ int cmd_op,
1139
+ int fd,
1140
+ int level,
1141
+ int optname,
1142
+ void *optval,
1143
+ int optlen)
1144
+ {
1145
+ /* This will be removed once the get/setsockopt() patches land */
1146
+ UNUSED(optlen);
1147
+ UNUSED(optval);
1148
+ UNUSED(level);
1149
+ UNUSED(optname);
1150
+ io_uring_prep_rw(IORING_OP_URING_CMD, sqe, fd, NULL, 0, 0);
1151
+ sqe->cmd_op = cmd_op;
1152
+ }
1153
+
1086
1154
  /*
1087
1155
  * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
1088
1156
  * the SQ ring
@@ -1340,6 +1408,14 @@ IOURINGINLINE void io_uring_buf_ring_advance(struct io_uring_buf_ring *br,
1340
1408
  io_uring_smp_store_release(&br->tail, new_tail);
1341
1409
  }
1342
1410
 
1411
+ IOURINGINLINE void __io_uring_buf_ring_cq_advance(struct io_uring *ring,
1412
+ struct io_uring_buf_ring *br,
1413
+ int cq_count, int buf_count)
1414
+ {
1415
+ br->tail += buf_count;
1416
+ io_uring_cq_advance(ring, cq_count);
1417
+ }
1418
+
1343
1419
  /*
1344
1420
  * Make 'count' new buffers visible to the kernel while at the same time
1345
1421
  * advancing the CQ ring seen entries. This can be used when the application
@@ -1351,8 +1427,7 @@ IOURINGINLINE void io_uring_buf_ring_cq_advance(struct io_uring *ring,
1351
1427
  struct io_uring_buf_ring *br,
1352
1428
  int count)
1353
1429
  {
1354
- br->tail += count;
1355
- io_uring_cq_advance(ring, count);
1430
+ __io_uring_buf_ring_cq_advance(ring, br, count, count);
1356
1431
  }
1357
1432
 
1358
1433
  #ifndef LIBURING_INTERNAL
@@ -5,6 +5,7 @@
5
5
  enum {
6
6
  INT_FLAG_REG_RING = 1,
7
7
  INT_FLAG_REG_REG_RING = 2,
8
+ INT_FLAG_APP_MEM = 4,
8
9
  };
9
10
 
10
11
  #endif
@@ -47,6 +47,8 @@ LIBURING_2.4 {
47
47
  io_uring_register_buf_ring;
48
48
  io_uring_unregister_buf_ring;
49
49
  io_uring_close_ring_fd;
50
+ io_uring_setup_buf_ring;
51
+ io_uring_free_buf_ring;
50
52
 
51
53
  io_uring_register_sync_cancel;
52
54
  io_uring_register_file_alloc_range;
@@ -118,6 +120,7 @@ LIBURING_2.4 {
118
120
  io_uring_recvmsg_cmsg_firsthdr;
119
121
  io_uring_prep_socket_direct;
120
122
  io_uring_buf_ring_cq_advance;
123
+ __io_uring_buf_ring_cq_advance;
121
124
  io_uring_prep_mkdir;
122
125
  io_uring_wait_cqe_nr;
123
126
  io_uring_prep_unlink;
@@ -167,6 +170,15 @@ LIBURING_2.4 {
167
170
  io_uring_prep_recv;
168
171
  io_uring_prep_msg_ring_cqe_flags;
169
172
  io_uring_prep_msg_ring_fd;
173
+ io_uring_prep_msg_ring_fd_alloc;
174
+ io_uring_prep_sendto;
175
+ io_uring_queue_init_mem;
176
+ io_uring_prep_sock_cmd;
170
177
  local:
171
178
  *;
172
179
  };
180
+
181
+ LIBURING_2.5 {
182
+ global:
183
+ io_uring_queue_init_mem;
184
+ } LIBURING_2.4;
@@ -77,4 +77,12 @@ LIBURING_2.4 {
77
77
  io_uring_close_ring_fd;
78
78
  io_uring_enable_rings;
79
79
  io_uring_register_restrictions;
80
+ io_uring_setup_buf_ring;
81
+ io_uring_free_buf_ring;
82
+ io_uring_queue_init_mem;
80
83
  } LIBURING_2.3;
84
+
85
+ LIBURING_2.5 {
86
+ global:
87
+ io_uring_queue_init_mem;
88
+ } LIBURING_2.4;
@@ -11,11 +11,16 @@
11
11
  static inline int do_register(struct io_uring *ring, unsigned int opcode,
12
12
  const void *arg, unsigned int nr_args)
13
13
  {
14
+ int fd;
15
+
14
16
  if (ring->int_flags & INT_FLAG_REG_REG_RING) {
15
17
  opcode |= IORING_REGISTER_USE_REGISTERED_RING;
16
- return __sys_io_uring_register(ring->enter_ring_fd, opcode, arg, nr_args);
18
+ fd = ring->enter_ring_fd;
19
+ } else {
20
+ fd = ring->ring_fd;
17
21
  }
18
- return __sys_io_uring_register(ring->ring_fd, opcode, arg, nr_args);
22
+
23
+ return __sys_io_uring_register(fd, opcode, arg, nr_args);
19
24
  }
20
25
 
21
26
  int io_uring_register_buffers_update_tag(struct io_uring *ring, unsigned off,