From af31ce2cbfcaecc2a6f342532ede5e293a34f7f7 Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Tue, 4 May 2021 10:32:08 -0700 Subject: examples/ucontext-cp.c: Do not use SIGSTKSZ glibc 2.34 has removed SIGSTKSZ therefore we replace it Signed-off-by: Khem Raj --- examples/ucontext-cp.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/ucontext-cp.c b/examples/ucontext-cp.c index ea0c934..b1369e2 100644 --- a/examples/ucontext-cp.c +++ b/examples/ucontext-cp.c @@ -3,6 +3,7 @@ * gcc -Wall -O2 -D_GNU_SOURCE -o ucontext-cp ucontext-cp.c -luring */ #define _POSIX_C_SOURCE 199309L +#include #include #include #include @@ -22,9 +23,7 @@ #define QD 64 #define BS 1024 -#ifndef SIGSTKSZ -#define SIGSTKSZ 8192 -#endif +size_t sigstksz = (8 * 1024 + sizeof (max_align_t) - 1) / sizeof (max_align_t); typedef struct { struct io_uring *ring; @@ -115,13 +114,13 @@ static int setup_context(async_context *pctx, struct io_uring *ring) perror("getcontext"); return -1; } - pctx->stack_buf = malloc(SIGSTKSZ); + pctx->stack_buf = malloc(sigstksz); if (!pctx->stack_buf) { perror("malloc"); return -1; } pctx->ctx_fnew.uc_stack.ss_sp = pctx->stack_buf; - pctx->ctx_fnew.uc_stack.ss_size = SIGSTKSZ; + pctx->ctx_fnew.uc_stack.ss_size = sigstksz; pctx->ctx_fnew.uc_link = &pctx->ctx_main; return 0; -- cgit v1.2.3 From acb906fc859c548b334192226215667c29dc2f45 Mon Sep 17 00:00:00 2001 From: Palash Oswal Date: Tue, 25 May 2021 15:51:56 +0530 Subject: add test for sqpoll cancel hang Added test and updated Makefile to include the test Lore link on discussion : https://lore.kernel.org/io-uring/CAGyP=7cr1S462e+ZNQY_s3ygmHbYpRo6OLrx7RCLKX8h6F=OnQ@mail.gmail.com/ Signed-off-by: Palash Oswal --- test/Makefile | 2 + test/sqpoll-cancel-hang.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 test/sqpoll-cancel-hang.c diff --git a/test/Makefile b/test/Makefile index a312409..dc67522 100644 --- a/test/Makefile +++ b/test/Makefile @@ -103,6 +103,7 @@ test_targets += \ sq-poll-share \ sqpoll-disable-exit \ sqpoll-exit-hang \ + sqpoll-cancel-hang \ sqpoll-sleep \ sq-space_left \ stdout \ @@ -241,6 +242,7 @@ test_srcs := \ sq-poll-share.c \ sqpoll-disable-exit.c \ sqpoll-exit-hang.c \ + sqpoll-cancel-hang.c \ sqpoll-sleep.c \ sq-space_left.c \ statx.c \ diff --git a/test/sqpoll-cancel-hang.c b/test/sqpoll-cancel-hang.c new file mode 100644 index 0000000..0b90426 --- /dev/null +++ b/test/sqpoll-cancel-hang.c @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "liburing.h" +#include "../src/syscall.h" + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +#define SIZEOF_IO_URING_SQE 64 +#define SIZEOF_IO_URING_CQE 16 +#define SQ_TAIL_OFFSET 64 +#define SQ_RING_MASK_OFFSET 256 +#define SQ_RING_ENTRIES_OFFSET 264 +#define CQ_RING_ENTRIES_OFFSET 268 +#define CQ_CQES_OFFSET 320 + +#define IORING_OFF_SQES 0x10000000ULL + +#define sys_io_uring_setup 425 + +static void kill_and_wait(int pid, int* status) +{ + kill(-pid, SIGKILL); + kill(pid, SIGKILL); + while (waitpid(-1, status, __WALL) != pid) { + } +} + +#define WAIT_FLAGS __WALL + +uint64_t r[3] = {0xffffffffffffffff, 0x0, 0x0}; + +static long syz_io_uring_setup(volatile long a0, volatile long a1, +volatile long a2, volatile long a3, volatile long a4, volatile long +a5) +{ + uint32_t entries = (uint32_t)a0; + struct io_uring_params* setup_params = (struct io_uring_params*)a1; + void* vma1 = (void*)a2; + void* vma2 = (void*)a3; + void** ring_ptr_out = (void**)a4; + void** sqes_ptr_out = (void**)a5; + uint32_t fd_io_uring = syscall(sys_io_uring_setup, entries, setup_params); + uint32_t sq_ring_sz = setup_params->sq_off.array + +setup_params->sq_entries * sizeof(uint32_t); + uint32_t cq_ring_sz = setup_params->cq_off.cqes + +setup_params->cq_entries * SIZEOF_IO_URING_CQE; + uint32_t ring_sz = sq_ring_sz > cq_ring_sz ? sq_ring_sz : cq_ring_sz; + *ring_ptr_out = mmap(vma1, ring_sz, PROT_READ | PROT_WRITE, +MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, +IORING_OFF_SQ_RING); + uint32_t sqes_sz = setup_params->sq_entries * SIZEOF_IO_URING_SQE; + *sqes_ptr_out = mmap(vma2, sqes_sz, PROT_READ | PROT_WRITE, +MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, IORING_OFF_SQES); + return fd_io_uring; +} + +static long syz_io_uring_submit(volatile long a0, volatile long a1, +volatile long a2, volatile long a3) +{ + char* ring_ptr = (char*)a0; + char* sqes_ptr = (char*)a1; + char* sqe = (char*)a2; + uint32_t sqes_index = (uint32_t)a3; + uint32_t sq_ring_entries = *(uint32_t*)(ring_ptr + SQ_RING_ENTRIES_OFFSET); + uint32_t cq_ring_entries = *(uint32_t*)(ring_ptr + CQ_RING_ENTRIES_OFFSET); + uint32_t sq_array_off = (CQ_CQES_OFFSET + cq_ring_entries * +SIZEOF_IO_URING_CQE + 63) & ~63; + if (sq_ring_entries) + sqes_index %= sq_ring_entries; + char* sqe_dest = sqes_ptr + sqes_index * SIZEOF_IO_URING_SQE; + memcpy(sqe_dest, sqe, SIZEOF_IO_URING_SQE); + uint32_t sq_ring_mask = *(uint32_t*)(ring_ptr + SQ_RING_MASK_OFFSET); + uint32_t* sq_tail_ptr = (uint32_t*)(ring_ptr + SQ_TAIL_OFFSET); + uint32_t sq_tail = *sq_tail_ptr & sq_ring_mask; + uint32_t sq_tail_next = *sq_tail_ptr + 1; + uint32_t* sq_array = (uint32_t*)(ring_ptr + sq_array_off); + *(sq_array + sq_tail) = sqes_index; + __atomic_store_n(sq_tail_ptr, sq_tail_next, __ATOMIC_RELEASE); + return 0; +} + + +void trigger_bug(void) +{ + intptr_t res = 0; + *(uint32_t*)0x20000204 = 0; + *(uint32_t*)0x20000208 = 2; + *(uint32_t*)0x2000020c = 0; + *(uint32_t*)0x20000210 = 0; + *(uint32_t*)0x20000218 = -1; + memset((void*)0x2000021c, 0, 12); + res = -1; + res = syz_io_uring_setup(0x7987, 0x20000200, 0x20400000, 0x20ffd000, 0x200000c0, 0x200001c0); + if (res != -1) { + r[0] = res; + r[1] = *(uint64_t*)0x200000c0; + r[2] = *(uint64_t*)0x200001c0; + } + *(uint8_t*)0x20000180 = 0xb; + *(uint8_t*)0x20000181 = 1; + *(uint16_t*)0x20000182 = 0; + *(uint32_t*)0x20000184 = 0; + *(uint64_t*)0x20000188 = 4; + *(uint64_t*)0x20000190 = 0x20000140; + *(uint64_t*)0x20000140 = 0x77359400; + *(uint64_t*)0x20000148 = 0; + *(uint32_t*)0x20000198 = 1; + *(uint32_t*)0x2000019c = 0; + *(uint64_t*)0x200001a0 = 0; + *(uint16_t*)0x200001a8 = 0; + *(uint16_t*)0x200001aa = 0; + memset((void*)0x200001ac, 0, 20); + syz_io_uring_submit(r[1], r[2], 0x20000180, 1); + *(uint32_t*)0x20000544 = 0; + *(uint32_t*)0x20000548 = 0x36; + *(uint32_t*)0x2000054c = 0; + *(uint32_t*)0x20000550 = 0; + *(uint32_t*)0x20000558 = r[0]; + memset((void*)0x2000055c, 0, 12); + syz_io_uring_setup(0x4bf1, 0x20000540, 0x20ffd000, 0x20ffc000, 0, 0); + +} +int main(void) +{ + syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + trigger_bug(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (current_time_ms() - start < 1000) { + continue; + } + kill_and_wait(pid, &status); + break; + } + return 0; +} + + + -- cgit v1.2.3 From 9c43f134f1e6e86bf3f9c674d0b44d76760944c4 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 12 Jun 2021 10:19:00 +0700 Subject: test/file-register: fix heap overflow read on test_basic When `test_basic` is called with `fail == 1`, the allocated array for it is just 10, but the close_files is always called with 100. Signed-off-by: Ammar Faizi --- test/file-register.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/file-register.c b/test/file-register.c index c5c5507..e7aa870 100644 --- a/test/file-register.c +++ b/test/file-register.c @@ -351,8 +351,9 @@ static int test_basic(struct io_uring *ring, int fail) { int *files; int ret; + int nr_files = fail ? 10 : 100; - files = open_files(fail ? 10 : 100, 0, 0); + files = open_files(nr_files, 0, 0); ret = io_uring_register_files(ring, files, 100); if (ret) { if (fail) { @@ -371,10 +372,10 @@ static int test_basic(struct io_uring *ring, int fail) fprintf(stderr, "%s: unregister %d\n", __FUNCTION__, ret); goto err; } - close_files(files, 100, 0); + close_files(files, nr_files, 0); return 0; err: - close_files(files, 100, 0); + close_files(files, nr_files, 0); return 1; } -- cgit v1.2.3 From ec6f75a63bb3a18a68d0a3d1580db6c1b0a1e9c4 Mon Sep 17 00:00:00 2001 From: anson-lo <83398016+anson-lo@users.noreply.github.com> Date: Thu, 22 Jul 2021 12:50:43 +0800 Subject: Fix a bug due to the unreleased lock before function returns Fix a bug due to the unreleased lock before the function returns by inserting unlock statement before breaking. Signed-off-by: Anson Lo ycaibb@gmail.com --- test/ring-leak2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/ring-leak2.c b/test/ring-leak2.c index d9bfe0f..77e7d82 100644 --- a/test/ring-leak2.c +++ b/test/ring-leak2.c @@ -197,6 +197,7 @@ static void *client_thread(void *arg) // connection closed or error shutdown(conn_i.fd, SHUT_RDWR); } else { + pthread_mutex_unlock(&lock); break; } add_socket_pollin(&ring, conn_i.fd); -- cgit v1.2.3 From 054a908d752f85af30522409569d5fd881930a85 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sat, 24 Jul 2021 13:41:12 +0200 Subject: Refer to the accept_flags in io_uring_enter manual In the section describing the IORING_OP_ACCEPT flag. Signed-off-by: Thomas de Zeeuw --- man/io_uring_enter.2 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 909cc9b..ec55828 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -389,7 +389,10 @@ must be set to the socket file descriptor, .I addr must contain the pointer to the sockaddr structure, and .I addr2 -must contain a pointer to the socklen_t addrlen field. See also +must contain a pointer to the socklen_t addrlen field. Flags can be passed using +the +.I accept_flags +field. See also .BR accept4(2) for the general description of the related system call. Available since 5.5. -- cgit v1.2.3 From f19bb01a66e89c0e16046d89072816dae7b1fa3c Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Mon, 26 Jul 2021 16:50:55 +0100 Subject: tests: fix poll update compatibility check Compatibility checks in poll-mshot-update doesn't always work well, and so the test can fail even if poll updates are not supported. Do the check separately and at the beginning. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/2a5f83d0cda642d97ea633b55ba0d53e82cbb064.1627314599.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/poll-mshot-update.c | 63 ++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/test/poll-mshot-update.c b/test/poll-mshot-update.c index 1a9ea0a..a3e4951 100644 --- a/test/poll-mshot-update.c +++ b/test/poll-mshot-update.c @@ -28,7 +28,37 @@ struct p { }; static struct p p[NFILES]; -static int no_update; + +static int has_poll_update(void) +{ + struct io_uring ring; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + bool has_update = false; + int ret; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) + return -1; + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_poll_update(sqe, NULL, NULL, POLLIN, IORING_TIMEOUT_UPDATE); + + ret = io_uring_submit(&ring); + if (ret != 1) + return -1; + + ret = io_uring_wait_cqe(&ring, &cqe); + if (!ret) { + if (cqe->res == -ENOENT) + has_update = true; + else if (cqe->res != -EINVAL) + return -1; + io_uring_cqe_seen(&ring, cqe); + } + io_uring_queue_exit(&ring); + return has_update; +} static int arm_poll(struct io_uring *ring, int off) { @@ -128,19 +158,6 @@ static void *trigger_polls_fn(void *data) return NULL; } -static int check_no_update(struct io_uring *ring) -{ - struct io_uring_cqe *cqe; - int ret; - - ret = io_uring_wait_cqe(ring, &cqe); - if (ret) - return 0; - ret = cqe->res; - io_uring_cqe_seen(ring, cqe); - return ret == -EINVAL; -} - static int arm_polls(struct io_uring *ring) { int ret, to_arm = NFILES, i, off; @@ -163,10 +180,6 @@ static int arm_polls(struct io_uring *ring) ret = io_uring_submit(ring); if (ret != this_arm) { - if (ret > 0 && check_no_update(ring)) { - no_update = 1; - return 0; - } fprintf(stderr, "submitted %d, %d\n", ret, this_arm); return 1; } @@ -187,6 +200,15 @@ int main(int argc, char *argv[]) if (argc > 1) return 0; + ret = has_poll_update(); + if (ret < 0) { + fprintf(stderr, "poll update check failed %i\n", ret); + return -1; + } else if (!ret) { + fprintf(stderr, "no poll update, skip\n"); + return 0; + } + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { perror("getrlimit"); goto err_noring; @@ -227,10 +249,6 @@ int main(int argc, char *argv[]) if (arm_polls(&ring)) goto err; - if (no_update) { - printf("No poll update support, skipping\n"); - goto done; - } for (i = 0; i < NLOOPS; i++) { pthread_create(&thread, NULL, trigger_polls_fn, NULL); @@ -240,7 +258,6 @@ int main(int argc, char *argv[]) pthread_join(thread, NULL); } -done: io_uring_queue_exit(&ring); return 0; err: -- cgit v1.2.3 From 67fcc9c9762652df1d84d7eb4ca6b21c7d5b3fa6 Mon Sep 17 00:00:00 2001 From: Shin Seunghun Date: Tue, 27 Jul 2021 08:18:19 +0900 Subject: test/io_uring_enter.c: set to_submit to 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `to_submit` argument probably should be 0 Signed-off-by: 신승훈 --- test/io_uring_enter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/io_uring_enter.c b/test/io_uring_enter.c index a6bb8f5..12f4ac9 100644 --- a/test/io_uring_enter.c +++ b/test/io_uring_enter.c @@ -234,7 +234,7 @@ main(int argc, char **argv) status |= try_io_uring_enter(0, 0, 0, 0, NULL, -1, EOPNOTSUPP); /* to_submit: 0, flags: 0; should get back 0. */ - status |= try_io_uring_enter(ring.ring_fd, 1, 0, 0, NULL, 0, 0); + status |= try_io_uring_enter(ring.ring_fd, 0, 0, 0, NULL, 0, 0); /* fill the sq ring */ sq_entries = *ring.sq.kring_entries; -- cgit v1.2.3 From a6afed8d67b55d6006e5f95ddf5decdf407185b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Kosobucki?= Date: Tue, 27 Jul 2021 21:30:16 +0200 Subject: Clarify information about error results One could (and did) interpret that cqe->res mathes the return *value* of preadv2 and pwritev2. Clarify that it matches the errno values used by these two. --- man/io_uring_enter.2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index ec55828..70c2970 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -944,7 +944,7 @@ They are described in section .B CQE ERRORS. .PP For read and write opcodes, the -return values match those documented in the +return values match errno values documented in the .BR preadv2 (2) and .BR pwritev2 (2) -- cgit v1.2.3 From 4c23254cc770505816a307ed8c4f17f9a4aaefb9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 27 Jul 2021 14:38:24 -0600 Subject: man/io_uring_enter.2: further clarify what cqe->res holds Hopefully no one gets confused by this anymore - or, deity forbid, throw tantrums over it. Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 70c2970..00f0778 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -944,13 +944,22 @@ They are described in section .B CQE ERRORS. .PP For read and write opcodes, the -return values match errno values documented in the +return values match +.I errno +values documented in the .BR preadv2 (2) and .BR pwritev2 (2) -man pages. -Return codes for the io_uring-specific opcodes are documented in the -description of the opcodes above. +man pages, with +.I +res +holding the equivalent of +.I -errno +for error cases, or the transferred number of bytes in case the operation +is succesful. Hence both error and success return can be found in that +field in the CQE. For other request types, the return values are documented +in the matching man page for that type, or in the opcodes section above for +io_uring-specific opcodes. .PP .SH RETURN VALUE .BR io_uring_enter () -- cgit v1.2.3 From c1176b78ed612a9c82243cf1c37cf66f8d6e6b3a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 28 Jul 2021 17:30:03 -0600 Subject: test/Makefile: silence string/array overflow for tests These are false positives, and they are annoying when trying to see if new warnings have been added. Silence them. Signed-off-by: Jens Axboe --- configure | 37 +++++++++++++++++++++++++++++++++++++ test/Makefile | 16 ++++++++++++---- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 3b96cde..68537d5 100755 --- a/configure +++ b/configure @@ -191,6 +191,37 @@ print_and_output_mak "relativelibdir" "$relativelibdir" print_and_output_mak "mandir" "$mandir" print_and_output_mak "datadir" "$datadir" +########################################## +# check for compiler -Wstringop-overflow +stringop_overflow="no" +cat > $TMPC << EOF +#include +int main(int argc, char **argv) +{ + return 0; +} +EOF +if compile_prog "-Werror -Wstringop-overflow=0" "" "stringop_overflow"; then + stringop_overflow="yes" +fi +print_config "stringop_overflow" "$stringop_overflow" + +########################################## +# check for compiler -Warryr-bounds +array_bounds="no" +cat > $TMPC << EOF +#include +int main(int argc, char **argv) +{ + return 0; +} +EOF +if compile_prog "-Werror -Warray-bounds=0" "" "array_bounds"; then + array_bounds="yes" +fi +print_config "array_bounds" "$array_bounds" + + ########################################## # check for __kernel_rwf_t __kernel_rwf_t="no" @@ -325,6 +356,12 @@ fi if test "$has_ucontext" = "yes"; then output_sym "CONFIG_HAVE_UCONTEXT" fi +if test "$stringop_overflow" = "yes"; then + output_sym "CONFIG_HAVE_STRINGOP_OVERFLOW" +fi +if test "$array_bounds" = "yes"; then + output_sym "CONFIG_HAVE_ARRAY_BOUNDS" +fi echo "CC=$cc" >> $config_host_mak print_config "CC" "$cc" diff --git a/test/Makefile b/test/Makefile index 7a9b50d..93be736 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,6 +3,10 @@ datadir ?= $(prefix)/share INSTALL=install +ifneq ($(MAKECMDGOALS),clean) +include ../config-host.mak +endif + CPPFLAGS ?= override CPPFLAGS += -D_GNU_SOURCE -D__SANE_USERSPACE_TYPES__ \ -I../src/include/ -include ../config-host.h @@ -10,6 +14,14 @@ CFLAGS ?= -g -O2 XCFLAGS = override CFLAGS += -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare \ -L../src/ + +ifdef CONFIG_HAVE_STRINGOP_OVERFLOW + XCFLAGS += -Wstringop-overflow=0 +endif +ifdef CONFIG_HAVE_ARRAY_BOUNDS + XCFLAGS += -Warray-bounds=0 +endif + CXXFLAGS ?= override CXXFLAGS += $(CFLAGS) -std=c++11 @@ -126,10 +138,6 @@ all_targets += $(test_targets) include ../Makefile.quiet -ifneq ($(MAKECMDGOALS),clean) -include ../config-host.mak -endif - ifdef CONFIG_HAVE_STATX test_targets += statx endif -- cgit v1.2.3 From 72a943982615b655d0cfc08f882ab91079f3287e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 5 Aug 2021 09:42:40 -0600 Subject: test/sqpoll-cancel-hang.c: fix test crash For some reason, after the test, the syz reproducer does a setup with NULL pointers for the ring and sqes pointers. This obviously causes a crash. Remove it. Signed-off-by: Jens Axboe --- test/sqpoll-cancel-hang.c | 1 - 1 file changed, 1 deletion(-) diff --git a/test/sqpoll-cancel-hang.c b/test/sqpoll-cancel-hang.c index 0b90426..c9032c8 100644 --- a/test/sqpoll-cancel-hang.c +++ b/test/sqpoll-cancel-hang.c @@ -131,7 +131,6 @@ void trigger_bug(void) *(uint32_t*)0x20000550 = 0; *(uint32_t*)0x20000558 = r[0]; memset((void*)0x2000055c, 0, 12); - syz_io_uring_setup(0x4bf1, 0x20000540, 0x20ffd000, 0x20ffc000, 0, 0); } int main(void) -- cgit v1.2.3 From d6eec536638520257b42b71dbfb51cd3c8903d1f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 8 Aug 2021 21:44:31 -0600 Subject: test/timeout: newer kernel require separate submit Signed-off-by: Jens Axboe --- test/timeout.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/timeout.c b/test/timeout.c index a28d599..d2e4930 100644 --- a/test/timeout.c +++ b/test/timeout.c @@ -180,7 +180,8 @@ err: return 1; } -static int test_single_timeout_wait(struct io_uring *ring) +static int test_single_timeout_wait(struct io_uring *ring, + struct io_uring_params *p) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -195,6 +196,15 @@ static int test_single_timeout_wait(struct io_uring *ring) io_uring_prep_nop(sqe); io_uring_sqe_set_data(sqe, (void *) 1); + /* no implied submit for newer kernels */ + if (p->features & IORING_FEAT_EXT_ARG) { + ret = io_uring_submit(ring); + if (ret != 2) { + fprintf(stderr, "%s: submit %d\n", __FUNCTION__, ret); + return 1; + } + } + msec_to_ts(&ts, 1000); i = 0; @@ -1165,12 +1175,13 @@ int main(int argc, char *argv[]) { struct io_uring ring, sqpoll_ring; bool has_timeout_update, sqpoll; + struct io_uring_params p = { }; int ret; if (argc > 1) return 0; - ret = io_uring_queue_init(8, &ring, 0); + ret = io_uring_queue_init_params(8, &ring, &p); if (ret) { fprintf(stderr, "ring setup failed\n"); return 1; @@ -1252,7 +1263,7 @@ int main(int argc, char *argv[]) return ret; } - ret = test_single_timeout_wait(&ring); + ret = test_single_timeout_wait(&ring, &p); if (ret) { fprintf(stderr, "test_single_timeout_wait failed\n"); return ret; -- cgit v1.2.3 From 0ea4ccd1c0e4bb05cb4471d64e55d2e7d4e8a24c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 8 Aug 2021 21:32:29 -0600 Subject: src/queue: don't flush SQ ring for new wait interface If we have IORING_FEAT_EXT_ARG, then timeouts are done through the syscall instead of by posting an internal timeout. This was done to be both more efficient, but also to enable multi-threaded use the wait side. If we touch the SQ state by flushing it, that isn't safe without synchronization. Fixes: https://github.com/axboe/liburing/issues/402 Signed-off-by: Jens Axboe --- src/queue.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/queue.c b/src/queue.c index 2f0f19b..5d2c2a5 100644 --- a/src/queue.c +++ b/src/queue.c @@ -248,7 +248,6 @@ static int io_uring_wait_cqes_new(struct io_uring *ring, .ts = (unsigned long) ts }; struct get_data data = { - .submit = __io_uring_flush_sq(ring), .wait_nr = wait_nr, .get_flags = IORING_ENTER_EXT_ARG, .sz = sizeof(arg), -- cgit v1.2.3 From 5864c926a7a0988bb70c626195ed891bbb5e63cd Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 9 Aug 2021 17:22:44 +0700 Subject: .gitignore: add several untracked test files After running the tests, we have these untracked files that shouldn't be commited: test/multicqes_drain test/poll-mshot-update test/rsrc_tags test/rw_merge_test test/sqpoll-cancel-hang test/testfile This commit adds them to .gitignore. Signed-off-by: Ammar Faizi --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 7a6f75c..89a66ca 100644 --- a/.gitignore +++ b/.gitignore @@ -121,6 +121,12 @@ /test/timeout-overflow /test/unlink /test/wakeup-hang +/test/multicqes_drain +/test/poll-mshot-update +/test/rsrc_tags +/test/rw_merge_test +/test/sqpoll-cancel-hang +/test/testfile /test/*.dmesg config-host.h -- cgit v1.2.3 From 1a3cb95f08656578202a1d4fade17b5f31ffdd69 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 9 Aug 2021 18:07:53 +0700 Subject: test/fsync: clean up t_malloc() before return Trivial memory leak fix. This commit also adds a new macro helper `ARRAY_SIZE`. Defined as: #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) Signed-off-by: Ammar Faizi --- test/fsync.c | 13 +++++++++---- test/helpers.h | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/test/fsync.c b/test/fsync.c index 7e93ecc..8454398 100644 --- a/test/fsync.c +++ b/test/fsync.c @@ -69,7 +69,7 @@ static int test_barrier_fsync(struct io_uring *ring) return 1; } - for (i = 0; i < 4; i++) { + for (i = 0; i < ARRAY_SIZE(iovecs); i++) { iovecs[i].iov_base = t_malloc(4096); iovecs[i].iov_len = 4096; } @@ -129,11 +129,16 @@ static int test_barrier_fsync(struct io_uring *ring) io_uring_cqe_seen(ring, cqe); } - unlink("testfile"); - return 0; + + ret = 0; + goto out; err: + ret = 1; +out: unlink("testfile"); - return 1; + for (i = 0; i < ARRAY_SIZE(iovecs); i++) + free(iovecs[i].iov_base); + return ret; } #define FILE_SIZE 1024 diff --git a/test/helpers.h b/test/helpers.h index 74fe162..18de463 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -54,6 +54,8 @@ enum t_setup_ret t_create_ring_params(int depth, struct io_uring *ring, enum t_setup_ret t_create_ring(int depth, struct io_uring *ring, unsigned int flags); +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + #ifdef __cplusplus } #endif -- cgit v1.2.3 From f0230dc3fcbd54d9a371553f84f97db8092556ce Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 9 Aug 2021 18:51:36 +0700 Subject: test/file-update: clean up t_malloc() before return Trivial memory leak fix. Signed-off-by: Ammar Faizi --- test/file-update.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/file-update.c b/test/file-update.c index 38059d4..578017e 100644 --- a/test/file-update.c +++ b/test/file-update.c @@ -128,6 +128,7 @@ static int test_sqe_update(struct io_uring *ring) ret = cqe->res; io_uring_cqe_seen(ring, cqe); + free(fds); if (ret == -EINVAL) { fprintf(stdout, "IORING_OP_FILES_UPDATE not supported, skipping\n"); return 0; -- cgit v1.2.3 From 83645b2d2d87a39fa8103b6ee89e0c037a7210f4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 9 Aug 2021 14:44:40 -0600 Subject: liburing.h: make all file/IO offset __u64 off_t may depend on various settings, it's safer to not truncate this (temporarily) to an off_t as we use 64-bit types otherwise. Fixes: https://github.com/axboe/liburing/issues/403 Signed-off-by: Jens Axboe --- src/include/liburing.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 51dc602..b378741 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -271,14 +271,14 @@ static inline void io_uring_prep_tee(struct io_uring_sqe *sqe, static inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd, const struct iovec *iovecs, - unsigned nr_vecs, off_t offset) + unsigned nr_vecs, __u64 offset) { io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset); } static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd, void *buf, unsigned nbytes, - off_t offset, int buf_index) + __u64 offset, int buf_index) { io_uring_prep_rw(IORING_OP_READ_FIXED, sqe, fd, buf, nbytes, offset); sqe->buf_index = buf_index; @@ -286,14 +286,14 @@ static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd, static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd, const struct iovec *iovecs, - unsigned nr_vecs, off_t offset) + unsigned nr_vecs, __u64 offset) { io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset); } static inline void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd, const void *buf, unsigned nbytes, - off_t offset, int buf_index) + __u64 offset, int buf_index) { io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset); sqe->buf_index = buf_index; @@ -439,13 +439,13 @@ static inline void io_uring_prep_close(struct io_uring_sqe *sqe, int fd) } static inline void io_uring_prep_read(struct io_uring_sqe *sqe, int fd, - void *buf, unsigned nbytes, off_t offset) + void *buf, unsigned nbytes, __u64 offset) { io_uring_prep_rw(IORING_OP_READ, sqe, fd, buf, nbytes, offset); } static inline void io_uring_prep_write(struct io_uring_sqe *sqe, int fd, - const void *buf, unsigned nbytes, off_t offset) + const void *buf, unsigned nbytes, __u64 offset) { io_uring_prep_rw(IORING_OP_WRITE, sqe, fd, buf, nbytes, offset); } @@ -461,7 +461,7 @@ static inline void io_uring_prep_statx(struct io_uring_sqe *sqe, int dfd, } static inline void io_uring_prep_fadvise(struct io_uring_sqe *sqe, int fd, - off_t offset, off_t len, int advice) + __u64 offset, off_t len, int advice) { io_uring_prep_rw(IORING_OP_FADVISE, sqe, fd, NULL, len, offset); sqe->fadvise_advice = advice; @@ -542,7 +542,7 @@ static inline void io_uring_prep_renameat(struct io_uring_sqe *sqe, int olddfd, static inline void io_uring_prep_sync_file_range(struct io_uring_sqe *sqe, int fd, unsigned len, - off_t offset, int flags) + __u64 offset, int flags) { io_uring_prep_rw(IORING_OP_SYNC_FILE_RANGE, sqe, fd, NULL, len, offset); sqe->sync_range_flags = flags; -- cgit v1.2.3 From e98b974502d10e4decdd6fa2d304a655cefe0d59 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 9 Aug 2021 14:46:55 -0600 Subject: Fix 32-bit compile warnings Just a few cases of casting a pointer to an u64, which the compiler warns about. Cast it to uintptr_t first to silence them. Signed-off-by: Jens Axboe --- src/include/liburing.h | 2 +- test/rsrc_tags.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index b378741..f073e25 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -335,7 +335,7 @@ static inline void io_uring_prep_poll_update(struct io_uring_sqe *sqe, unsigned poll_mask, unsigned flags) { io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, old_user_data, flags, - (__u64)new_user_data); + (__u64)(uintptr_t)new_user_data); #if __BYTE_ORDER == __BIG_ENDIAN poll_mask = __swahw32(poll_mask); #endif diff --git a/test/rsrc_tags.c b/test/rsrc_tags.c index 2b4890b..337fbb8 100644 --- a/test/rsrc_tags.c +++ b/test/rsrc_tags.c @@ -40,8 +40,8 @@ static int register_rsrc(struct io_uring *ring, int type, int nr, memset(®, 0, sizeof(reg)); reg.nr = nr; - reg.data = (__u64)arg; - reg.tags = (__u64)tags; + reg.data = (__u64)(uintptr_t)arg; + reg.tags = (__u64)(uintptr_t)tags; reg_type = IORING_REGISTER_FILES2; if (type != TEST_IORING_RSRC_FILE) @@ -60,8 +60,8 @@ static int update_rsrc(struct io_uring *ring, int type, int nr, int off, memset(&up, 0, sizeof(up)); up.offset = off; - up.data = (__u64)arg; - up.tags = (__u64)tags; + up.data = (__u64)(uintptr_t)arg; + up.tags = (__u64)(uintptr_t)tags; up.nr = nr; up_type = IORING_REGISTER_FILES_UPDATE2; -- cgit v1.2.3 From c75b1c04fcb2f9bdd381592e079126e9c2ecb7e0 Mon Sep 17 00:00:00 2001 From: wangyangbo Date: Fri, 13 Aug 2021 10:37:07 +0800 Subject: correct syscall NR in mips Signed-off-by: wangyangbo --- src/syscall.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/syscall.c b/src/syscall.c index 2fd3dd4..69027e5 100644 --- a/src/syscall.c +++ b/src/syscall.c @@ -13,8 +13,8 @@ #ifdef __alpha__ /* - * alpha is the only exception, all other architectures - * have common numbers for new system calls. + * alpha and mips are exception, other architectures have + * common numbers for new system calls. */ # ifndef __NR_io_uring_setup # define __NR_io_uring_setup 535 @@ -25,7 +25,17 @@ # ifndef __NR_io_uring_register # define __NR_io_uring_register 537 # endif -#else /* !__alpha__ */ +#elif defined __mips__ +# ifndef __NR_io_uring_setup +# define __NR_io_uring_setup (__NR_Linux + 425) +# endif +# ifndef __NR_io_uring_enter +# define __NR_io_uring_enter (__NR_Linux + 426) +# endif +# ifndef __NR_io_uring_register +# define __NR_io_uring_register (__NR_Linux + 427) +# endif +#else /* !__alpha__ and !__mips__ */ # ifndef __NR_io_uring_setup # define __NR_io_uring_setup 425 # endif -- cgit v1.2.3 From a182c26d2a5f537e95db7c6a34c88c4b797b5789 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 13 Aug 2021 12:36:28 -0600 Subject: man/io_uring_setup.2: make sure FEAT flags are kernel versioned Also document IORING_FEAT_EXT_ARG, which hadn't been added yet. Signed-off-by: Jens Axboe --- man/io_uring_setup.2 | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index cb8eba9..977109b 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -202,7 +202,7 @@ If this flag is set, the two SQ and CQ rings can be mapped with a single .I mmap(2) call. The SQEs must still be allocated separately. This brings the necessary .I mmap(2) -calls down from three to two. +calls down from three to two. Available since kernel 5.4. .TP .B IORING_FEAT_NODROP If this flag is set, io_uring supports never dropping completion events. @@ -213,11 +213,12 @@ IO with fail with the .B -EBUSY error value, if it can't flush the overflown events to the CQ ring. If this happens, the application must reap events from the CQ ring and attempt the -submit again. +submit again. Available since kernel 5.5. .TP .B IORING_FEAT_SUBMIT_STABLE If this flag is set, applications can be certain that any data for -async offload has been consumed when the kernel has consumed the SQE. +async offload has been consumed when the kernel has consumed the SQE. Available +since kernel 5.5. .TP .B IORING_FEAT_RW_CUR_POS If this flag is set, applications can specify @@ -237,7 +238,8 @@ with == -1. It'll use (and update) the current file position. This obviously comes with the caveat that if the application has multiple reads or writes in flight, then the end result will not be as expected. This is similar to threads sharing -a file descriptor and doing IO using the current file position. +a file descriptor and doing IO using the current file position. Available since +kernel 5.6. .TP .B IORING_FEAT_CUR_PERSONALITY If this flag is set, then io_uring guarantees that both sync and async @@ -253,7 +255,7 @@ still register different personalities through io_uring_register(2) with .B IORING_REGISTER_PERSONALITY -and specify the personality to use in the sqe. +and specify the personality to use in the sqe. Available since kernel 5.6. .TP .B IORING_FEAT_FAST_POLL If this flag is set, then io_uring supports using an internal poll mechanism @@ -262,20 +264,49 @@ write data to a file no longer need to be punted to an async thread for handling, instead they will begin operation when the file is ready. This is similar to doing poll + read/write in userspace, but eliminates the need to do so. If this flag is set, requests waiting on space/data consume a lot less -resources doing so as they are not blocking a thread. +resources doing so as they are not blocking a thread. Available since kernel +5.7. .TP .B IORING_FEAT_POLL_32BITS If this flag is set, the .B IORING_OP_POLL_ADD command accepts the full 32-bit range of epoll based flags. Most notably .B EPOLLEXCLUSIVE -which allows exclusive (waking single waiters) behavior. +which allows exclusive (waking single waiters) behavior. Available since kernel +5.9. .TP .B IORING_FEAT_SQPOLL_NONFIXED If this flag is set, the .B IORING_SETUP_SQPOLL feature no longer requires the use of fixed files. Any normal file descriptor -can be used for IO commands without needing registration. +can be used for IO commands without needing registration. Available since +kernel 5.11. +.TP +.B IORING_FEAT_ENTER_EXT_ARG +If this flag is set, then the +.BR io_uring_enter (2) +system call supports passing in an extended argument instead of just the +.IR "sigset_t" +of earlier kernels. This. +extended argument is of type +.IR "struct io_uring_getevents_arg" +and allows the caller to pass in both a +.IR "sigset_t" +and a timeout argument for waiting on events. The struct layout is as follows: +.TP +.in +8n +.EX +struct io_uring_getevents_arg { + __u64 sigmask; + __u32 sigmask_sz; + __u32 pad; + __u64 ts; +}; +.EE + +and a pointer to this struct must be passed in if +.B IORING_ENTER_EXT_ARG +is set in the flags for the enter system call. Available since kernel 5.11. .PP The rest of the fields in the -- cgit v1.2.3 From a13a84260a982692b28c7416292f5c98151e4c92 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 13 Aug 2021 12:37:37 -0600 Subject: test/runtests.sh: report what tests timed out Not necessarily a failure, but can be. Signed-off-by: Jens Axboe --- test/runtests.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/runtests.sh b/test/runtests.sh index e8f4ae5..26371ec 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -8,6 +8,7 @@ TEST_DIR=$(dirname $0) FAILED="" SKIPPED="" MAYBE_FAILED="" +TIMED_OUT="" TEST_FILES="" declare -A TEST_MAP @@ -97,6 +98,7 @@ run_test() # Check test status if [ "$status" -eq 124 ]; then echo "Test $test_name timed out (may not be a failure)" + TIMED_OUT="$TIMED_OUT <$test_string>" elif [ "$status" -ne 0 ]; then echo "Test $test_name failed with ret $status" FAILED="$FAILED <$test_string>" @@ -144,6 +146,9 @@ else if [ ! -z "$MAYBE_FAILED" ]; then echo "Tests _maybe_ failed: $MAYBE_FAILED" fi + if [ ! -z "$TIMED_OUT" ]; then + echo "Tests timed out: $TIMED_OUT" + fi echo "All tests passed" exit 0 fi -- cgit v1.2.3 From 11db8b30ebd5b1f2840f0e6e93324bbed5811ede Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 13 Aug 2021 12:41:20 -0600 Subject: man/io_uring_setup.2: document the two most recent FEAT flags Signed-off-by: Jens Axboe --- man/io_uring_setup.2 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index 977109b..495d6af 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -307,6 +307,19 @@ struct io_uring_getevents_arg { and a pointer to this struct must be passed in if .B IORING_ENTER_EXT_ARG is set in the flags for the enter system call. Available since kernel 5.11. +.TP +.B IORING_FEAT_NATIVE_WORKERS +If this flag is set, io_uring is using native workers for its async helpers. +Previous kernels used kernel threads that assumed the identity of the +original io_uring owning task, but later kernels will actively create what +looks more like regular process threads instead. Available since kernel +5.12. +.TP +.B IORING_FEAT_RSRC_TAGS +If this flag is set, then io_uring supports a variety of features related +to fixed files and buffers. In particular, it indicates that registered +buffers can be updated in-place, whereas before the full set would have to +be unregistered first. Available since kernel 5.13. .PP The rest of the fields in the -- cgit v1.2.3 From 82bbab585ed8fdef5c65ec826e5fcbfa9f370a25 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 Aug 2021 09:00:33 -0600 Subject: Add test case for empty submit/wait SQPOLL EOWNERDEAD failure case Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 2 ++ test/empty-eownerdead.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 test/empty-eownerdead.c diff --git a/.gitignore b/.gitignore index 89a66ca..3d67ef9 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ /test/defer /test/double-poll-crash /test/eeed8b54e0df-test +/test/empty-eownerdead /test/eventfd /test/eventfd-disable /test/eventfd-ring diff --git a/test/Makefile b/test/Makefile index 93be736..46af135 100644 --- a/test/Makefile +++ b/test/Makefile @@ -54,6 +54,7 @@ test_targets += \ defer \ double-poll-crash \ eeed8b54e0df-test \ + empty-eownerdead \ eventfd \ eventfd-disable \ eventfd-ring \ @@ -191,6 +192,7 @@ test_srcs := \ defer.c \ double-poll-crash.c \ eeed8b54e0df-test.c \ + empty-eownerdead.c \ eventfd-disable.c \ eventfd-ring.c \ eventfd.c \ diff --git a/test/empty-eownerdead.c b/test/empty-eownerdead.c new file mode 100644 index 0000000..59d00ba --- /dev/null +++ b/test/empty-eownerdead.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Test if entering with nothing to submit/wait for SQPOLL returns an error. + */ +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" +#include "../src/syscall.h" + +int main(int argc, char *argv[]) +{ + struct io_uring_params p = {}; + struct io_uring ring; + int ret; + + if (argc > 1) + return 0; + + p.flags = IORING_SETUP_SQPOLL; + p.sq_thread_idle = 100; + + ret = t_create_ring_params(1, &ring, &p); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret < 0) + goto err; + + ret = __sys_io_uring_enter(ring.ring_fd, 0, 0, 0, NULL); + if (ret < 0) { + int __e = errno; + + fprintf(stderr, "child: sqe submit failed: %s\n", strerror(__e)); + goto err; + } + + return 0; +err: + return 1; +} -- cgit v1.2.3 From c776ee947f471e68149342e63e8d0fdb04d7acad Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 Aug 2021 13:05:19 -0600 Subject: test/mkdir: ignore run if argument given Signed-off-by: Jens Axboe --- test/mkdir.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/mkdir.c b/test/mkdir.c index c044652..363fe1e 100644 --- a/test/mkdir.c +++ b/test/mkdir.c @@ -58,6 +58,9 @@ int main(int argc, char *argv[]) int ret; struct io_uring ring; + if (argc > 1) + return 0; + ret = io_uring_queue_init(8, &ring, 0); if (ret) { fprintf(stderr, "queue init failed: %d\n", ret); -- cgit v1.2.3 From c9644872c263d62ab103d1a28bdc3c9855e4a6b7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 Aug 2021 13:05:56 -0600 Subject: test/symlink: ignore run if agument given Signed-off-by: Jens Axboe --- test/symlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/symlink.c b/test/symlink.c index 8b5e04a..cf4aa96 100644 --- a/test/symlink.c +++ b/test/symlink.c @@ -67,6 +67,9 @@ int main(int argc, char *argv[]) int ret; struct io_uring ring; + if (argc > 1) + return 0; + ret = io_uring_queue_init(8, &ring, 0); if (ret) { fprintf(stderr, "queue init failed: %d\n", ret); -- cgit v1.2.3 From b936762bb0aea0c259ee46a8cd350b5229c635ca Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 Aug 2021 13:07:48 -0600 Subject: test/hardlink: ignore run if argument given Signed-off-by: Jens Axboe --- test/hardlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/hardlink.c b/test/hardlink.c index 1c73424..634b8ed 100644 --- a/test/hardlink.c +++ b/test/hardlink.c @@ -73,6 +73,9 @@ int main(int argc, char *argv[]) int ret; struct io_uring ring; + if (argc > 1) + return 0; + ret = io_uring_queue_init(8, &ring, 0); if (ret) { fprintf(stderr, "queue init failed: %d\n", ret); -- cgit v1.2.3 From 5693e2128de5b67f2349afb187069a70477d525e Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 15 Aug 2021 10:43:51 +0100 Subject: tests: close pipes in link-timeout Don't forget to close pipe fds after link-timeout tests Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/02771d9c5820fa0fa2fc87f697f0f232b9b23a0d.1629020550.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/link-timeout.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/link-timeout.c b/test/link-timeout.c index 5d8417f..8c3e203 100644 --- a/test/link-timeout.c +++ b/test/link-timeout.c @@ -619,6 +619,8 @@ static int test_timeout_link_chain1(struct io_uring *ring) io_uring_cqe_seen(ring, cqe); } + close(fds[0]); + close(fds[1]); return 0; err: return 1; @@ -713,6 +715,8 @@ static int test_timeout_link_chain2(struct io_uring *ring) io_uring_cqe_seen(ring, cqe); } + close(fds[0]); + close(fds[1]); return 0; err: return 1; @@ -833,6 +837,8 @@ static int test_timeout_link_chain3(struct io_uring *ring) io_uring_cqe_seen(ring, cqe); } + close(fds[0]); + close(fds[1]); return 0; err: return 1; @@ -917,6 +923,8 @@ static int test_timeout_link_chain4(struct io_uring *ring) io_uring_cqe_seen(ring, cqe); } + close(fds[0]); + close(fds[1]); return 0; err: return 1; -- cgit v1.2.3 From fa15080b491d659a211384f783f066fa565ebea9 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 15 Aug 2021 10:43:52 +0100 Subject: tests: fail early invalid linked setups We're going to fail links with invalid timeout combinations early. E.g. op1 -> link timeout -> link timeout Update tests to handle it. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/d2576c13100bacc00467c9ccfaedca1e71117e97.1629020550.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/link-timeout.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/test/link-timeout.c b/test/link-timeout.c index 8c3e203..c8c289c 100644 --- a/test/link-timeout.c +++ b/test/link-timeout.c @@ -63,7 +63,7 @@ static int test_fail_two_link_timeouts(struct io_uring *ring) struct __kernel_timespec ts; struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; - int ret, i; + int ret, i, nr_wait; ts.tv_sec = 1; ts.tv_nsec = 0; @@ -114,12 +114,13 @@ static int test_fail_two_link_timeouts(struct io_uring *ring) sqe->user_data = 4; ret = io_uring_submit(ring); - if (ret != 4) { + if (ret < 3) { printf("sqe submit failed: %d\n", ret); goto err; } + nr_wait = ret; - for (i = 0; i < 4; i++) { + for (i = 0; i < nr_wait; i++) { ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { printf("wait completion %d\n", ret); @@ -981,14 +982,16 @@ static int test_timeout_link_chain5(struct io_uring *ring) } switch (cqe->user_data) { case 1: - if (cqe->res) { - fprintf(stderr, "Timeout got %d, wanted -EINVAL\n", + case 2: + if (cqe->res && cqe->res != -ECANCELED) { + fprintf(stderr, "Request got %d, wanted -EINVAL " + "or -ECANCELED\n", cqe->res); goto err; } break; - case 2: - if (cqe->res != -ECANCELED) { + case 3: + if (cqe->res != -ECANCELED && cqe->res != -EINVAL) { fprintf(stderr, "Link timeout got %d, wanted -ECANCELED\n", cqe->res); goto err; } -- cgit v1.2.3 From 59e7bf135de4d858ea1b0245548f756bdbf7f132 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 19 Aug 2021 14:42:21 +0100 Subject: tests: create new files for rw testing Currently rw/iopoll tests use a fixed name file, so several instances of the same test can't run in parallel. Use unique names instead. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/470033f83e6ee15af154fd1a464ba3118f2bf2eb.1629380408.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/iopoll.c | 6 +++++- test/read-write.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/test/iopoll.c b/test/iopoll.c index 3d94dfe..1adee7f 100644 --- a/test/iopoll.c +++ b/test/iopoll.c @@ -325,6 +325,7 @@ static int probe_buf_select(void) int main(int argc, char *argv[]) { int i, ret, nr; + char buf[256]; char *fname; if (probe_buf_select()) @@ -333,7 +334,10 @@ int main(int argc, char *argv[]) if (argc > 1) { fname = argv[1]; } else { - fname = ".iopoll-rw"; + srand((unsigned)time(NULL)); + snprintf(buf, sizeof(buf), ".basic-rw-%u-%u", + (unsigned)rand(), (unsigned)getpid()); + fname = buf; t_create_file(fname, FILE_SIZE); } diff --git a/test/read-write.c b/test/read-write.c index d0a77fa..b0a2bde 100644 --- a/test/read-write.c +++ b/test/read-write.c @@ -746,12 +746,16 @@ err: int main(int argc, char *argv[]) { int i, ret, nr; + char buf[256]; char *fname; if (argc > 1) { fname = argv[1]; } else { - fname = ".basic-rw"; + srand((unsigned)time(NULL)); + snprintf(buf, sizeof(buf), ".basic-rw-%u-%u", + (unsigned)rand(), (unsigned)getpid()); + fname = buf; t_create_file(fname, FILE_SIZE); } -- cgit v1.2.3 From ed5d3b23a5c8646f84fcc21cb70b0dfda8003f86 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 19 Aug 2021 14:42:22 +0100 Subject: tests: rename iopoll test variables Rename v1-v4 variables into something more descriptive, makes debugging easier. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/66e749793b37a702c1ac37556c1e354e9dff3298.1629380408.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/iopoll.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/iopoll.c b/test/iopoll.c index 1adee7f..b450618 100644 --- a/test/iopoll.c +++ b/test/iopoll.c @@ -347,15 +347,15 @@ int main(int argc, char *argv[]) if (no_buf_select) nr = 8; for (i = 0; i < nr; i++) { - int v1, v2, v3, v4; + int write = (i & 1) != 0; + int sqthread = (i & 2) != 0; + int fixed = (i & 4) != 0; + int buf_select = (i & 8) != 0; - v1 = (i & 1) != 0; - v2 = (i & 2) != 0; - v3 = (i & 4) != 0; - v4 = (i & 8) != 0; - ret = test_io(fname, v1, v2, v3, v4); + ret = test_io(fname, write, sqthread, fixed, buf_select); if (ret) { - fprintf(stderr, "test_io failed %d/%d/%d/%d\n", v1, v2, v3, v4); + fprintf(stderr, "test_io failed %d/%d/%d/%d\n", + write, sqthread, fixed, buf_select); goto err; } if (no_iopoll) -- cgit v1.2.3 From 62a5004f2cad8d9a6440bb8ac87d3b4d3895430a Mon Sep 17 00:00:00 2001 From: Mark Papadakis Date: Fri, 20 Aug 2021 13:39:20 +0300 Subject: Update io_uring_setup.2 --- man/io_uring_setup.2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index 495d6af..88ce1f9 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -209,7 +209,7 @@ If this flag is set, io_uring supports never dropping completion events. If a completion event occurs and the CQ ring is full, the kernel stores the event internally until such a time that the CQ ring has room for more entries. If this overflow condition is entered, attempting to submit more -IO with fail with the +IO will fail with the .B -EBUSY error value, if it can't flush the overflown events to the CQ ring. If this happens, the application must reap events from the CQ ring and attempt the -- cgit v1.2.3 From b5f2347b53d4336da355aeafbb81ee748f8bc600 Mon Sep 17 00:00:00 2001 From: pechenkin Date: Thu, 19 Aug 2021 14:05:31 +0300 Subject: examples: disable ucontext-cp for elbrus (e2k) architecture Elbrus 2000 (aka e2k) is a 64-bit little-endian architecture. For several reasons it use makecontext_e2k(ctx, ...) with different semantic instead of makecontext(ctx, ...). Signed-off-by: Nikita Pechenkin --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 68537d5..5a0ae89 100755 --- a/configure +++ b/configure @@ -327,6 +327,7 @@ int main(int argc, char **argv) { ucontext_t ctx; getcontext(&ctx); + makecontext(&ctx, 0, 0); return 0; } EOF -- cgit v1.2.3 From 135f32ab4ea6cae754b3f7522fc3da603fd3fe1b Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sat, 21 Aug 2021 15:22:04 +0100 Subject: tests: fix test_cancel_req_across_fork Rarely, the request we're trying to cancel may not yet got picked by a worker, and so the cancel request returns 0 instead of -EALREADY, and it's a valid output we should consider. Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- test/io-cancel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/io-cancel.c b/test/io-cancel.c index 9a36dd9..a4cc361 100644 --- a/test/io-cancel.c +++ b/test/io-cancel.c @@ -339,7 +339,7 @@ static int test_cancel_req_across_fork(void) return 1; } if ((cqe->user_data == 1 && cqe->res != -EINTR) || - (cqe->user_data == 2 && cqe->res != -EALREADY)) { + (cqe->user_data == 2 && cqe->res != -EALREADY && cqe->res)) { fprintf(stderr, "%i %i\n", (int)cqe->user_data, cqe->res); exit(1); } -- cgit v1.2.3 From e430dd21d91ff016228e84ea62fd42dab29d8a8e Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 22 Aug 2021 13:07:58 +0100 Subject: tests: migrate rw tests to t_create_ring() Use t_create_ring() in read-write.c and iopoll.c, the function will do all the privilege checks. Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- test/iopoll.c | 23 ++++++----------------- test/read-write.c | 21 +++++++-------------- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/test/iopoll.c b/test/iopoll.c index b450618..5273279 100644 --- a/test/iopoll.c +++ b/test/iopoll.c @@ -271,31 +271,20 @@ static int test_io(const char *file, int write, int sqthread, int fixed, int buf_select) { struct io_uring ring; - int ret, ring_flags; + int ret, ring_flags = IORING_SETUP_IOPOLL; if (no_iopoll) return 0; - ring_flags = IORING_SETUP_IOPOLL; - if (sqthread) { - static int warned; - - if (geteuid()) { - if (!warned) - fprintf(stdout, "SQPOLL requires root, skipping\n"); - warned = 1; - return 0; - } - } - - ret = io_uring_queue_init(64, &ring, ring_flags); - if (ret) { + ret = t_create_ring(64, &ring, ring_flags); + if (ret == T_SETUP_SKIP) + goto done; + if (ret != T_SETUP_OK) { fprintf(stderr, "ring create failed: %d\n", ret); return 1; } - ret = __test_io(file, &ring, write, sqthread, fixed, buf_select); - +done: io_uring_queue_exit(&ring); return ret; } diff --git a/test/read-write.c b/test/read-write.c index b0a2bde..93f6803 100644 --- a/test/read-write.c +++ b/test/read-write.c @@ -235,23 +235,15 @@ static int test_io(const char *file, int write, int buffered, int sqthread, int fixed, int nonvec, int exp_len) { struct io_uring ring; - int ret, ring_flags; + int ret, ring_flags = 0; - if (sqthread) { - if (geteuid()) { - if (!warned) { - fprintf(stderr, "SQPOLL requires root, skipping\n"); - warned = 1; - } - return 0; - } + if (sqthread) ring_flags = IORING_SETUP_SQPOLL; - } else { - ring_flags = 0; - } - ret = io_uring_queue_init(64, &ring, ring_flags); - if (ret) { + ret = t_create_ring(64, &ring, ring_flags); + if (ret == T_SETUP_SKIP) + goto done; + if (ret != T_SETUP_OK) { fprintf(stderr, "ring create failed: %d\n", ret); return 1; } @@ -259,6 +251,7 @@ static int test_io(const char *file, int write, int buffered, int sqthread, ret = __test_io(file, &ring, write, buffered, sqthread, fixed, nonvec, 0, 0, exp_len); +done: io_uring_queue_exit(&ring); return ret; } -- cgit v1.2.3 From a395fbb34e4e0f083ca43b2a5db319dd53573ea1 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 22 Aug 2021 13:49:32 +0100 Subject: tests; skip non-root sendmsg_fs_cve Skip sendmsg_fd_cve if we don't have enough privileges to chroot(). Cc: Ammar Faizi Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- test/sendmsg_fs_cve.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/sendmsg_fs_cve.c b/test/sendmsg_fs_cve.c index 8de220a..3866e5d 100644 --- a/test/sendmsg_fs_cve.c +++ b/test/sendmsg_fs_cve.c @@ -154,7 +154,13 @@ int main(int argc, char *argv[]) if (!c) { close(rcv_sock); - if (chroot(tmpdir)) { + r = chroot(tmpdir); + if (r) { + if (errno == EPERM) { + fprintf(stderr, "chroot not allowed, skip\n"); + return 0; + } + perror("chroot()"); return 1; } -- cgit v1.2.3 From f632c1079d3559bbf4deb2d899f9aed40e51c165 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Mon, 23 Aug 2021 12:16:56 +0100 Subject: tests: add IOSQE_ASYNC cancel testing We miss tests for IORING_OP_ASYNC_CANCEL requests issued with IOSQE_ASYNC, so add it. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/b5dada6cba71207dd8b282a805714a4fe8db2258.1629717388.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/io-cancel.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/test/io-cancel.c b/test/io-cancel.c index a4cc361..63d2f7d 100644 --- a/test/io-cancel.c +++ b/test/io-cancel.c @@ -115,7 +115,7 @@ static int do_io(struct io_uring *ring, int fd, int do_write) return 0; } -static int start_cancel(struct io_uring *ring, int do_partial) +static int start_cancel(struct io_uring *ring, int do_partial, int async_cancel) { struct io_uring_sqe *sqe; int i, ret, submitted = 0; @@ -129,6 +129,8 @@ static int start_cancel(struct io_uring *ring, int do_partial) goto err; } io_uring_prep_cancel(sqe, (void *) (unsigned long) i + 1, 0); + if (async_cancel) + sqe->flags |= IOSQE_ASYNC; sqe->user_data = 0; submitted++; } @@ -148,7 +150,8 @@ err: * the submitted IO. This is done to verify that cancelling one piece of IO doesn't * impact others. */ -static int test_io_cancel(const char *file, int do_write, int do_partial) +static int test_io_cancel(const char *file, int do_write, int do_partial, + int async_cancel) { struct io_uring ring; struct timeval start_tv; @@ -179,7 +182,7 @@ static int test_io_cancel(const char *file, int do_write, int do_partial) goto err; /* sleep for 1/3 of the total time, to allow some to start/complete */ usleep(usecs / 3); - if (start_cancel(&ring, do_partial)) + if (start_cancel(&ring, do_partial, async_cancel)) goto err; to_wait = BUFFERS; if (do_partial) @@ -512,13 +515,15 @@ int main(int argc, char *argv[]) vecs = t_create_buffers(BUFFERS, BS); - for (i = 0; i < 4; i++) { - int v1 = (i & 1) != 0; - int v2 = (i & 2) != 0; + for (i = 0; i < 8; i++) { + int write = (i & 1) != 0; + int partial = (i & 2) != 0; + int async = (i & 4) != 0; - ret = test_io_cancel(".basic-rw", v1, v2); + ret = test_io_cancel(".basic-rw", write, partial, async); if (ret) { - fprintf(stderr, "test_io_cancel %d %d failed\n", v1, v2); + fprintf(stderr, "test_io_cancel %d %d %d failed\n", + write, partial, async); goto err; } } -- cgit v1.2.3 From 526f270bb6e7155c37276feced1616e101e0e1dd Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 24 Aug 2021 14:57:51 +0100 Subject: tests: rw: don't exit ring when init failed Don't do io_uring_queue_exit() after t_create_ring() got skipped. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/28376af76af7bfb9059b6b9ad3a01eb0b07e7244.1629813328.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/iopoll.c | 3 +-- test/read-write.c | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test/iopoll.c b/test/iopoll.c index 5273279..7037c31 100644 --- a/test/iopoll.c +++ b/test/iopoll.c @@ -278,13 +278,12 @@ static int test_io(const char *file, int write, int sqthread, int fixed, ret = t_create_ring(64, &ring, ring_flags); if (ret == T_SETUP_SKIP) - goto done; + return 0; if (ret != T_SETUP_OK) { fprintf(stderr, "ring create failed: %d\n", ret); return 1; } ret = __test_io(file, &ring, write, sqthread, fixed, buf_select); -done: io_uring_queue_exit(&ring); return ret; } diff --git a/test/read-write.c b/test/read-write.c index 93f6803..1cfa2d5 100644 --- a/test/read-write.c +++ b/test/read-write.c @@ -242,7 +242,7 @@ static int test_io(const char *file, int write, int buffered, int sqthread, ret = t_create_ring(64, &ring, ring_flags); if (ret == T_SETUP_SKIP) - goto done; + return 0; if (ret != T_SETUP_OK) { fprintf(stderr, "ring create failed: %d\n", ret); return 1; @@ -250,8 +250,6 @@ static int test_io(const char *file, int write, int buffered, int sqthread, ret = __test_io(file, &ring, write, buffered, sqthread, fixed, nonvec, 0, 0, exp_len); - -done: io_uring_queue_exit(&ring); return ret; } -- cgit v1.2.3 From 608598ff3e61ece9804ab9da76b61ed3d2a34750 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 24 Aug 2021 14:57:52 +0100 Subject: tests: non-root io_uring_register Non-previliged users can't register too many buffers, just skip the test in this case. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/2d40f84f0fa5e5dc53ef8b55bdcc00a11e0dc5a7.1629813328.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/io_uring_register.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/io_uring_register.c b/test/io_uring_register.c index 53e3987..9475739 100644 --- a/test/io_uring_register.c +++ b/test/io_uring_register.c @@ -303,12 +303,14 @@ test_iovec_nr(int fd) printf("io_uring_register(%d, %u, %p, %u)\n", fd, IORING_REGISTER_BUFFERS, iovs, nr); ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, iovs, nr); - if (ret != 0) { + if (ret && (errno == ENOMEM || errno == EPERM) && geteuid()) { + printf("can't register large iovec for regular users, skip\n"); + } else if (ret != 0) { printf("expected success, got %d\n", errno); status = 1; - } else + } else { __sys_io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 0, 0); - + } free(buf); free(iovs); return status; -- cgit v1.2.3 From ed1632ede2d360ade4aaa795b572c10e86e4959f Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 24 Aug 2021 12:39:27 +0100 Subject: tests: non-privileged defer test Reduce ring sizes because non-privileged users can't create them, clean up dead code, and SQPOLL testing to the end, so it doesn't stop all other tests if not supported. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/726e3cd30a1e5689e6b87c252ddd2770aa431b41.1629805109.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/defer.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/test/defer.c b/test/defer.c index 885cf5c..825b69f 100644 --- a/test/defer.c +++ b/test/defer.c @@ -11,6 +11,8 @@ #include "helpers.h" #include "liburing.h" +#define RING_SIZE 128 + struct test_context { struct io_uring *ring; struct io_uring_sqe **sqes; @@ -243,30 +245,24 @@ int main(int argc, char *argv[]) { struct io_uring ring, poll_ring, sqthread_ring; struct io_uring_params p; - int ret, no_sqthread = 0; + int ret; if (argc > 1) return 0; memset(&p, 0, sizeof(p)); - ret = io_uring_queue_init_params(1000, &ring, &p); + ret = io_uring_queue_init_params(RING_SIZE, &ring, &p); if (ret) { - printf("ring setup failed\n"); + printf("ring setup failed %i\n", ret); return 1; } - ret = io_uring_queue_init(1000, &poll_ring, IORING_SETUP_IOPOLL); + ret = io_uring_queue_init(RING_SIZE, &poll_ring, IORING_SETUP_IOPOLL); if (ret) { printf("poll_ring setup failed\n"); return 1; } - ret = t_create_ring(1000, &sqthread_ring, - IORING_SETUP_SQPOLL | IORING_SETUP_IOPOLL); - if (ret == T_SETUP_SKIP) - return 0; - else if (ret < 0) - return 1; ret = test_cancelled_userdata(&poll_ring); if (ret) { @@ -274,16 +270,6 @@ int main(int argc, char *argv[]) return ret; } - if (no_sqthread) { - printf("test_thread_link_cancel: skipped, not root\n"); - } else { - ret = test_thread_link_cancel(&sqthread_ring); - if (ret) { - printf("test_thread_link_cancel failed\n"); - return ret; - } - } - if (!(p.features & IORING_FEAT_NODROP)) { ret = test_overflow_hung(&ring); if (ret) { @@ -304,5 +290,18 @@ int main(int argc, char *argv[]) return ret; } + ret = t_create_ring(RING_SIZE, &sqthread_ring, + IORING_SETUP_SQPOLL | IORING_SETUP_IOPOLL); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret < 0) + return 1; + + ret = test_thread_link_cancel(&sqthread_ring); + if (ret) { + printf("test_thread_link_cancel failed\n"); + return ret; + } + return 0; } -- cgit v1.2.3 From 30f49fb03b2d61c824da766a6f3397915ed18eee Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 24 Aug 2021 12:39:28 +0100 Subject: tests: non-privileged io_uring_enter Decrease the ring size in io_uring_enter if can't allocate a large ring. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/34c67bd613fe241a5942a1c5befecaa81cb73dc9.1629805109.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/io_uring_enter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/io_uring_enter.c b/test/io_uring_enter.c index 12f4ac9..4ea990c 100644 --- a/test/io_uring_enter.c +++ b/test/io_uring_enter.c @@ -30,6 +30,7 @@ #include "../src/syscall.h" #define IORING_MAX_ENTRIES 4096 +#define IORING_MAX_ENTRIES_FALLBACK 128 int expect_failed_submit(struct io_uring *ring, int error) @@ -218,6 +219,8 @@ main(int argc, char **argv) return 0; ret = io_uring_queue_init(IORING_MAX_ENTRIES, &ring, 0); + if (ret == -ENOMEM) + ret = io_uring_queue_init(IORING_MAX_ENTRIES_FALLBACK, &ring, 0); if (ret < 0) { perror("io_uring_queue_init"); exit(1); -- cgit v1.2.3 From d9fe6161e40a3a9746fbc7f7fe7e42a55eab97cf Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 24 Aug 2021 18:38:47 +0100 Subject: tests: fix poll-mshot-update poll-mshot-update constantly hangs. Apparently, the reason is reap_polls() clearing ->triggered flags racing with trigger_polls() setting them. So, reinit the flags only after joining the thread. Also, replace magic constants with proper identificators, e.g. 1 -> IORING_POLL_ADD_MULTI. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/7e588f712ec61e0ddc619ce016d1c3b9445716e1.1629826707.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/poll-mshot-update.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/poll-mshot-update.c b/test/poll-mshot-update.c index a3e4951..6bf4679 100644 --- a/test/poll-mshot-update.c +++ b/test/poll-mshot-update.c @@ -71,7 +71,7 @@ static int arm_poll(struct io_uring *ring, int off) } io_uring_prep_poll_add(sqe, p[off].fd[0], POLLIN); - sqe->len = 1; + sqe->len = IORING_POLL_ADD_MULTI; sqe->user_data = off; return 0; } @@ -88,7 +88,7 @@ static int reap_polls(struct io_uring *ring) sqe = io_uring_get_sqe(ring); /* update event */ io_uring_prep_poll_update(sqe, (void *)(unsigned long)i, NULL, - POLLIN, 2); + POLLIN, IORING_POLL_UPDATE_EVENTS); sqe->user_data = 0x12345678; } @@ -107,7 +107,6 @@ static int reap_polls(struct io_uring *ring) off = cqe->user_data; if (off == 0x12345678) goto seen; - p[off].triggered = 0; ret = read(p[off].fd[0], &c, 1); if (ret != 1) { if (ret == -1 && errno == EAGAIN) @@ -195,7 +194,7 @@ int main(int argc, char *argv[]) struct io_uring_params params = { }; struct rlimit rlim; pthread_t thread; - int i, ret; + int i, j, ret; if (argc > 1) return 0; @@ -256,6 +255,9 @@ int main(int argc, char *argv[]) if (ret) goto err; pthread_join(thread, NULL); + + for (j = 0; j < NFILES; j++) + p[j].triggered = 0; } io_uring_queue_exit(&ring); -- cgit v1.2.3 From 48792358a9fc73e112788e2a8c507ad20bcf65ab Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 25 Aug 2021 08:59:03 -0600 Subject: Update io_uring.h Sync with kernel 5.15-pending, and update io_uring_prep_rw() to ensure we properly clear everything. Signed-off-by: Jens Axboe --- src/include/liburing.h | 5 ++++- src/include/liburing/io_uring.h | 29 ++++++++++++++++------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index f073e25..63cc4e6 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -224,7 +224,10 @@ static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd, sqe->len = len; sqe->rw_flags = 0; sqe->user_data = 0; - sqe->__pad2[0] = sqe->__pad2[1] = sqe->__pad2[2] = 0; + sqe->buf_index = 0; + sqe->personality = 0; + sqe->file_index = 0; + sqe->__pad2[0] = sqe->__pad2[1] = 0; } /** diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index e4a4fc4..efd6e65 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -51,21 +51,20 @@ struct io_uring_sqe { __u32 hardlink_flags; }; __u64 user_data; /* data to be passed back at completion time */ + /* pack this to avoid bogus arm OABI complaints */ union { - struct { - /* pack this to avoid bogus arm OABI complaints */ - union { - /* index into fixed buffers, if used */ - __u16 buf_index; - /* for grouped buffer selection */ - __u16 buf_group; - } __attribute__((packed)); - /* personality to use, if used */ - __u16 personality; - __s32 splice_fd_in; - }; - __u64 __pad2[3]; + /* index into fixed buffers, if used */ + __u16 buf_index; + /* for grouped buffer selection */ + __u16 buf_group; + } __attribute__((packed)); + /* personality to use, if used */ + __u16 personality; + union { + __s32 splice_fd_in; + __u32 file_index; }; + __u64 __pad2[2]; }; enum { @@ -314,6 +313,10 @@ enum { IORING_REGISTER_BUFFERS2 = 15, IORING_REGISTER_BUFFERS_UPDATE = 16, + /* set/clear io-wq thread affinities */ + IORING_REGISTER_IOWQ_AFF = 17, + IORING_UNREGISTER_IOWQ_AFF = 18, + /* this goes last */ IORING_REGISTER_LAST }; -- cgit v1.2.3 From c1c8b893b389eee01ec21551be9155239fb055bc Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Wed, 25 Aug 2021 13:23:01 +0100 Subject: liburing.h: add a multipoll helper Add a helper for preparing a multipoll request and use it in a test. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/b795d577590abd84f435381f02363551e7fd13b4.1629893954.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 7 +++++++ test/poll-mshot-update.c | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 63cc4e6..883dff1 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -326,6 +326,13 @@ static inline void io_uring_prep_poll_add(struct io_uring_sqe *sqe, int fd, sqe->poll32_events = poll_mask; } +static inline void io_uring_prep_poll_multishot(struct io_uring_sqe *sqe, + int fd, unsigned poll_mask) +{ + io_uring_prep_poll_add(sqe, fd, poll_mask); + sqe->len = IORING_POLL_ADD_MULTI; +} + static inline void io_uring_prep_poll_remove(struct io_uring_sqe *sqe, void *user_data) { diff --git a/test/poll-mshot-update.c b/test/poll-mshot-update.c index 6bf4679..75ee52f 100644 --- a/test/poll-mshot-update.c +++ b/test/poll-mshot-update.c @@ -70,8 +70,7 @@ static int arm_poll(struct io_uring *ring, int off) return 1; } - io_uring_prep_poll_add(sqe, p[off].fd[0], POLLIN); - sqe->len = IORING_POLL_ADD_MULTI; + io_uring_prep_poll_multishot(sqe, p[off].fd[0], POLLIN); sqe->user_data = off; return 0; } -- cgit v1.2.3 From 0837dadfcda7ed4c32340850e66a538376a82853 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Wed, 25 Aug 2021 13:23:02 +0100 Subject: liburing.h: dedup poll mask conversion Poll mask LE/BE translation is ugly enough to want to hide it in a helper and not hand code many times. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/9035fff2bde1c54bcac87ca48dfcfc54e6a815ab.1629893954.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 883dff1..4c7bedb 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -316,14 +316,19 @@ static inline void io_uring_prep_sendmsg(struct io_uring_sqe *sqe, int fd, sqe->msg_flags = flags; } -static inline void io_uring_prep_poll_add(struct io_uring_sqe *sqe, int fd, - unsigned poll_mask) +static inline unsigned __io_uring_prep_poll_mask(unsigned poll_mask) { - io_uring_prep_rw(IORING_OP_POLL_ADD, sqe, fd, NULL, 0, 0); #if __BYTE_ORDER == __BIG_ENDIAN poll_mask = __swahw32(poll_mask); #endif - sqe->poll32_events = poll_mask; + return poll_mask; +} + +static inline void io_uring_prep_poll_add(struct io_uring_sqe *sqe, int fd, + unsigned poll_mask) +{ + io_uring_prep_rw(IORING_OP_POLL_ADD, sqe, fd, NULL, 0, 0); + sqe->poll32_events = __io_uring_prep_poll_mask(poll_mask); } static inline void io_uring_prep_poll_multishot(struct io_uring_sqe *sqe, @@ -346,10 +351,7 @@ static inline void io_uring_prep_poll_update(struct io_uring_sqe *sqe, { io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, old_user_data, flags, (__u64)(uintptr_t)new_user_data); -#if __BYTE_ORDER == __BIG_ENDIAN - poll_mask = __swahw32(poll_mask); -#endif - sqe->poll32_events = poll_mask; + sqe->poll32_events = __io_uring_prep_poll_mask(poll_mask); } static inline void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd, -- cgit v1.2.3 From 5b45e4b4d50a391a4991edc1fe4c7e684b4cc73a Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Wed, 25 Aug 2021 18:53:35 +0100 Subject: tests: don't skip sqpoll needlessly Newer kernels support non-privileged SQPOLL, don't skip sqpoll testing in sq-poll-kthread and others when it would work just fine. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/9ace2f7ac85ac105e46bb8d09afee96c5dc842b1.1629913874.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/d4ae271dfaae-test.c | 5 ----- test/sq-poll-kthread.c | 14 ++++++-------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/test/d4ae271dfaae-test.c b/test/d4ae271dfaae-test.c index 80d3f71..10c7e98 100644 --- a/test/d4ae271dfaae-test.c +++ b/test/d4ae271dfaae-test.c @@ -27,11 +27,6 @@ int main(int argc, char *argv[]) char *fname; void *buf; - if (geteuid()) { - fprintf(stdout, "Test requires root, skipping\n"); - return 0; - } - memset(&p, 0, sizeof(p)); p.flags = IORING_SETUP_SQPOLL; ret = t_create_ring_params(4, &ring, &p); diff --git a/test/sq-poll-kthread.c b/test/sq-poll-kthread.c index ed7d0bf..0a0a75a 100644 --- a/test/sq-poll-kthread.c +++ b/test/sq-poll-kthread.c @@ -17,6 +17,7 @@ #include #include "liburing.h" +#include "helpers.h" #define SQ_THREAD_IDLE 2000 #define BUF_SIZE 128 @@ -38,23 +39,20 @@ static int do_test_sq_poll_kthread_stopped(bool do_exit) uint8_t buf[BUF_SIZE]; struct iovec iov; - if (geteuid()) { - fprintf(stderr, "sqpoll requires root!\n"); - return TEST_SKIPPED; - } - if (pipe(pipe1) != 0) { perror("pipe"); return TEST_FAILED; } memset(¶m, 0, sizeof(param)); - param.flags |= IORING_SETUP_SQPOLL; param.sq_thread_idle = SQ_THREAD_IDLE; - ret = io_uring_queue_init_params(16, &ring, ¶m); - if (ret) { + ret = t_create_ring_params(16, &ring, ¶m); + if (ret == T_SETUP_SKIP) { + ret = TEST_FAILED; + goto err_pipe; + } else if (ret != T_SETUP_OK) { fprintf(stderr, "ring setup failed\n"); ret = TEST_FAILED; goto err_pipe; -- cgit v1.2.3 From b3dc872f2fde55349d6e678e61df84deffed67b1 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Wed, 25 Aug 2021 18:53:36 +0100 Subject: tests: skip when large buf register fails Registering lots of memory will fail for non-privileged users, so skip tests if that happens. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/682c09c1d153cd4dfe505ded6069b294e98078e3.1629913874.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/helpers.c | 19 +++++++++++++++++++ test/helpers.h | 4 ++++ test/iopoll.c | 24 ++++++++++++------------ test/read-write.c | 26 +++++++++++--------------- 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/test/helpers.c b/test/helpers.c index 930d82a..975e7cb 100644 --- a/test/helpers.c +++ b/test/helpers.c @@ -114,3 +114,22 @@ enum t_setup_ret t_create_ring(int depth, struct io_uring *ring, p.flags = flags; return t_create_ring_params(depth, ring, &p); } + +enum t_setup_ret t_register_buffers(struct io_uring *ring, + const struct iovec *iovecs, + unsigned nr_iovecs) +{ + int ret; + + ret = io_uring_register_buffers(ring, iovecs, nr_iovecs); + if (!ret) + return T_SETUP_OK; + + if ((ret == -EPERM || ret == -ENOMEM) && geteuid()) { + fprintf(stdout, "too large non-root buffer registration, skip\n"); + return T_SETUP_SKIP; + } + + fprintf(stderr, "buffer register failed: %s\n", strerror(-ret)); + return ret; +} diff --git a/test/helpers.h b/test/helpers.h index 18de463..7526d46 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -54,6 +54,10 @@ enum t_setup_ret t_create_ring_params(int depth, struct io_uring *ring, enum t_setup_ret t_create_ring(int depth, struct io_uring *ring, unsigned int flags); +enum t_setup_ret t_register_buffers(struct io_uring *ring, + const struct iovec *iovecs, + unsigned nr_iovecs); + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #ifdef __cplusplus diff --git a/test/iopoll.c b/test/iopoll.c index 7037c31..de36473 100644 --- a/test/iopoll.c +++ b/test/iopoll.c @@ -60,14 +60,13 @@ static int __test_io(const char *file, struct io_uring *ring, int write, int sqt struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; int open_flags; - int i, fd, ret; + int i, fd = -1, ret; off_t offset; - if (buf_select && write) + if (buf_select) { write = 0; - if (buf_select && fixed) fixed = 0; - + } if (buf_select && provide_buffers(ring)) return 1; @@ -77,19 +76,20 @@ static int __test_io(const char *file, struct io_uring *ring, int write, int sqt open_flags = O_RDONLY; open_flags |= O_DIRECT; - fd = open(file, open_flags); - if (fd < 0) { - perror("file open"); - goto err; - } - if (fixed) { - ret = io_uring_register_buffers(ring, vecs, BUFFERS); - if (ret) { + ret = t_register_buffers(ring, vecs, BUFFERS); + if (ret == T_SETUP_SKIP) + return 0; + if (ret != T_SETUP_OK) { fprintf(stderr, "buffer reg failed: %d\n", ret); goto err; } } + fd = open(file, open_flags); + if (fd < 0) { + perror("file open"); + goto err; + } if (sqthread) { ret = io_uring_register_files(ring, &fd, 1); if (ret) { diff --git a/test/read-write.c b/test/read-write.c index 1cfa2d5..0c55159 100644 --- a/test/read-write.c +++ b/test/read-write.c @@ -49,7 +49,7 @@ static int __test_io(const char *file, struct io_uring *ring, int write, struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; int open_flags; - int i, fd, ret; + int i, fd = -1, ret; off_t offset; #ifdef VERBOSE @@ -57,13 +57,6 @@ static int __test_io(const char *file, struct io_uring *ring, int write, buffered, sqthread, fixed, nonvec); #endif - if (sqthread && geteuid()) { -#ifdef VERBOSE - fprintf(stdout, "SKIPPED (not root)\n"); -#endif - return 0; - } - if (write) open_flags = O_WRONLY; else @@ -71,19 +64,22 @@ static int __test_io(const char *file, struct io_uring *ring, int write, if (!buffered) open_flags |= O_DIRECT; + if (fixed) { + ret = t_register_buffers(ring, vecs, BUFFERS); + if (ret == T_SETUP_SKIP) + return 0; + if (ret != T_SETUP_OK) { + fprintf(stderr, "buffer reg failed: %d\n", ret); + goto err; + } + } + fd = open(file, open_flags); if (fd < 0) { perror("file open"); goto err; } - if (fixed) { - ret = io_uring_register_buffers(ring, vecs, BUFFERS); - if (ret) { - fprintf(stderr, "buffer reg failed: %d\n", ret); - goto err; - } - } if (sqthread) { ret = io_uring_register_files(ring, &fd, 1); if (ret) { -- cgit v1.2.3 From d74b028b735eb77e67db707df28b02e7dcacab2a Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sat, 21 Aug 2021 16:53:53 +0100 Subject: tests: test open/accept directly into fixed table Test a new feature allowing to open/accept directly into io_uring's fixed table bypassing normal fdtable. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/e4326cd1629f9f3c5db3aee7cd976d99df18aff9.1629560358.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/accept.c | 74 +++++++++++++++++++++------- test/openat2.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 199 insertions(+), 27 deletions(-) diff --git a/test/accept.c b/test/accept.c index f096f8a..41caa48 100644 --- a/test/accept.c +++ b/test/accept.c @@ -39,9 +39,10 @@ static void queue_send(struct io_uring *ring, int fd) sqe = io_uring_get_sqe(ring); io_uring_prep_writev(sqe, fd, &d->iov, 1, 0); + sqe->user_data = 1; } -static void queue_recv(struct io_uring *ring, int fd) +static void queue_recv(struct io_uring *ring, int fd, bool fixed) { struct io_uring_sqe *sqe; struct data *d; @@ -52,16 +53,21 @@ static void queue_recv(struct io_uring *ring, int fd) sqe = io_uring_get_sqe(ring); io_uring_prep_readv(sqe, fd, &d->iov, 1, 0); + sqe->user_data = 2; + if (fixed) + sqe->flags |= IOSQE_FIXED_FILE; } -static int accept_conn(struct io_uring *ring, int fd) +static int accept_conn(struct io_uring *ring, int fd, bool fixed) { struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; - int ret; + int ret, fixed_idx = 0; sqe = io_uring_get_sqe(ring); io_uring_prep_accept(sqe, fd, NULL, NULL, 0); + if (fixed) + sqe->splice_fd_in = fixed_idx + 1; ret = io_uring_submit(ring); assert(ret != -1); @@ -70,6 +76,15 @@ static int accept_conn(struct io_uring *ring, int fd) assert(!ret); ret = cqe->res; io_uring_cqe_seen(ring, cqe); + + if (fixed) { + if (ret > 0) { + close(ret); + return -EINVAL; + } else if (!ret) { + ret = fixed_idx; + } + } return ret; } @@ -102,15 +117,12 @@ static int start_accept_listen(struct sockaddr_in *addr, int port_off) return fd; } -static int test(struct io_uring *ring, int accept_should_error) +static int test(struct io_uring *ring, int accept_should_error, bool fixed) { struct io_uring_cqe *cqe; struct sockaddr_in addr; - uint32_t head; - uint32_t count = 0; - int done = 0; - int p_fd[2]; - int ret; + uint32_t head, count = 0; + int ret, p_fd[2], done = 0; int32_t val, recv_s0 = start_accept_listen(&addr, 0); @@ -137,11 +149,14 @@ static int test(struct io_uring *ring, int accept_should_error) ret = fcntl(p_fd[1], F_SETFL, flags); assert(ret != -1); - p_fd[0] = accept_conn(ring, recv_s0); + p_fd[0] = accept_conn(ring, recv_s0, fixed); if (p_fd[0] == -EINVAL) { if (accept_should_error) goto out; - fprintf(stdout, "Accept not supported, skipping\n"); + if (fixed) + fprintf(stdout, "Fixed accept not supported, skipping\n"); + else + fprintf(stdout, "Accept not supported, skipping\n"); no_accept = 1; goto out; } else if (p_fd[0] < 0) { @@ -153,7 +168,7 @@ static int test(struct io_uring *ring, int accept_should_error) } queue_send(ring, p_fd[1]); - queue_recv(ring, p_fd[0]); + queue_recv(ring, p_fd[0], fixed); ret = io_uring_submit_and_wait(ring, 2); assert(ret != -1); @@ -161,7 +176,8 @@ static int test(struct io_uring *ring, int accept_should_error) while (count < 2) { io_uring_for_each_cqe(ring, head, cqe) { if (cqe->res < 0) { - fprintf(stderr, "Got cqe res %d\n", cqe->res); + fprintf(stderr, "Got cqe res %d, user_data %i\n", + cqe->res, (int)cqe->user_data); done = 1; break; } @@ -176,12 +192,14 @@ static int test(struct io_uring *ring, int accept_should_error) } out: - close(p_fd[0]); + if (!fixed) + close(p_fd[0]); close(p_fd[1]); close(recv_s0); return 0; err: - close(p_fd[0]); + if (!fixed) + close(p_fd[0]); close(p_fd[1]); close(recv_s0); return 1; @@ -302,7 +320,7 @@ static int test_accept_cancel(unsigned usecs) sqe = io_uring_get_sqe(&m_io_uring); io_uring_prep_accept(sqe, fd, NULL, NULL, 0); sqe->user_data = 1; - ret = io_uring_submit(&m_io_uring); + ret = io_uring_submit(&m_io_uring); assert(ret == 1); if (usecs) @@ -355,7 +373,21 @@ static int test_accept(void) ret = io_uring_queue_init(32, &m_io_uring, 0); assert(ret >= 0); - ret = test(&m_io_uring, 0); + ret = test(&m_io_uring, 0, false); + io_uring_queue_exit(&m_io_uring); + return ret; +} + +static int test_accept_fixed(void) +{ + struct io_uring m_io_uring; + int ret, fd = -1; + + ret = io_uring_queue_init(32, &m_io_uring, 0); + assert(ret >= 0); + ret = io_uring_register_files(&m_io_uring, &fd, 1); + assert(ret == 0); + ret = test(&m_io_uring, 0, true); io_uring_queue_exit(&m_io_uring); return ret; } @@ -377,7 +409,7 @@ static int test_accept_sqpoll(void) if (p.features & IORING_FEAT_SQPOLL_NONFIXED) should_fail = 0; - ret = test(&m_io_uring, should_fail); + ret = test(&m_io_uring, should_fail, false); io_uring_queue_exit(&m_io_uring); return ret; } @@ -397,6 +429,12 @@ int main(int argc, char *argv[]) if (no_accept) return 0; + ret = test_accept_fixed(); + if (ret) { + fprintf(stderr, "test_accept_fixed failed\n"); + return ret; + } + ret = test_accept_sqpoll(); if (ret) { fprintf(stderr, "test_accept_sqpoll failed\n"); diff --git a/test/openat2.c b/test/openat2.c index 65f81b1..8964208 100644 --- a/test/openat2.c +++ b/test/openat2.c @@ -13,7 +13,8 @@ #include "helpers.h" #include "liburing.h" -static int test_openat2(struct io_uring *ring, const char *path, int dfd) +static int test_openat2(struct io_uring *ring, const char *path, int dfd, + int fixed_slot) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -23,30 +24,151 @@ static int test_openat2(struct io_uring *ring, const char *path, int dfd) sqe = io_uring_get_sqe(ring); if (!sqe) { fprintf(stderr, "get sqe failed\n"); - goto err; + return -1; } memset(&how, 0, sizeof(how)); - how.flags = O_RDONLY; + how.flags = O_RDWR; io_uring_prep_openat2(sqe, dfd, path, &how); + sqe->splice_fd_in = fixed_slot; ret = io_uring_submit(ring); if (ret <= 0) { fprintf(stderr, "sqe submit failed: %d\n", ret); - goto err; + return -1; } ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { fprintf(stderr, "wait completion %d\n", ret); - goto err; + return -1; } ret = cqe->res; io_uring_cqe_seen(ring, cqe); + + if (fixed_slot && ret > 0) { + close(ret); + return -EINVAL; + } return ret; -err: - return -1; } +static int test_open_fixed(const char *path, int dfd) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + struct io_uring ring; + const char pattern = 0xac; + char buffer[] = { 0, 0 }; + int i, ret, fd = -1; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed\n"); + return -1; + } + ret = io_uring_register_files(&ring, &fd, 1); + if (ret) { + fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret); + return -1; + } + + ret = test_openat2(&ring, path, dfd, 1); + if (ret == -EINVAL) { + printf("fixed open isn't supported\n"); + return 1; + } else if (ret) { + fprintf(stderr, "direct open failed %d\n", ret); + return -1; + } + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_write(sqe, 0, &pattern, 1, 0); + sqe->user_data = 1; + sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK; + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_read(sqe, 0, buffer, 1, 0); + sqe->user_data = 2; + sqe->flags |= IOSQE_FIXED_FILE; + + ret = io_uring_submit(&ring); + if (ret != 2) { + fprintf(stderr, "%s: got %d, wanted 2\n", __FUNCTION__, ret); + return -1; + } + + for (i = 0; i < 2; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + return -1; + } + if (cqe->res != 1) { + fprintf(stderr, "unexpectetd ret %d\n", cqe->res); + return -1; + } + io_uring_cqe_seen(&ring, cqe); + } + if (memcmp(&pattern, buffer, 1) != 0) { + fprintf(stderr, "buf validation failed\n"); + return -1; + } + + ret = test_openat2(&ring, path, dfd, 1); + if (ret != -EBADF) { + fprintf(stderr, "bogus double register %d\n", ret); + return -1; + } + io_uring_queue_exit(&ring); + return 0; +} + +static int test_open_fixed_fail(const char *path, int dfd) +{ + struct io_uring ring; + int ret, fd = -1; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed\n"); + return -1; + } + + ret = test_openat2(&ring, path, dfd, 1); + if (ret != -ENXIO) { + fprintf(stderr, "install into not existing table, %i\n", ret); + return 1; + } + + ret = io_uring_register_files(&ring, &fd, 1); + if (ret) { + fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret); + return -1; + } + + ret = test_openat2(&ring, path, dfd, 2); + if (ret != -EINVAL) { + fprintf(stderr, "install out of bounds, %i\n", ret); + return 1; + } + + ret = test_openat2(&ring, path, dfd, (1u << 16)); + if (ret != -EINVAL) { + fprintf(stderr, "install out of bounds or u16 overflow, %i\n", ret); + return 1; + } + + ret = test_openat2(&ring, path, dfd, (1u << 16) + 1); + if (ret != -EINVAL) { + fprintf(stderr, "install out of bounds or u16 overflow, %i\n", ret); + return 1; + } + + io_uring_queue_exit(&ring); + return 0; +} + + int main(int argc, char *argv[]) { struct io_uring ring; @@ -74,7 +196,7 @@ int main(int argc, char *argv[]) if (do_unlink) t_create_file(path_rel, 4096); - ret = test_openat2(&ring, path, -1); + ret = test_openat2(&ring, path, -1, 0); if (ret < 0) { if (ret == -EINVAL) { fprintf(stdout, "openat2 not supported, skipping\n"); @@ -84,12 +206,24 @@ int main(int argc, char *argv[]) goto err; } - ret = test_openat2(&ring, path_rel, AT_FDCWD); + ret = test_openat2(&ring, path_rel, AT_FDCWD, 0); if (ret < 0) { fprintf(stderr, "test_openat2 relative failed: %d\n", ret); goto err; } + ret = test_open_fixed(path, -1); + if (ret > 0) + goto done; + if (ret) { + fprintf(stderr, "test_open_fixed failed\n"); + goto err; + } + ret = test_open_fixed_fail(path, -1); + if (ret) { + fprintf(stderr, "test_open_fixed_fail failed\n"); + goto err; + } done: unlink(path); if (do_unlink) -- cgit v1.2.3 From 2e8854eb5d912ac68c186e7aab8c2805cef2a5bd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 25 Aug 2021 11:58:31 -0600 Subject: test/{accept,openat2}: use sqe->file_index Signed-off-by: Jens Axboe --- test/accept.c | 2 +- test/openat2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/accept.c b/test/accept.c index 41caa48..21db14f 100644 --- a/test/accept.c +++ b/test/accept.c @@ -67,7 +67,7 @@ static int accept_conn(struct io_uring *ring, int fd, bool fixed) sqe = io_uring_get_sqe(ring); io_uring_prep_accept(sqe, fd, NULL, NULL, 0); if (fixed) - sqe->splice_fd_in = fixed_idx + 1; + sqe->file_index = fixed_idx + 1; ret = io_uring_submit(ring); assert(ret != -1); diff --git a/test/openat2.c b/test/openat2.c index 8964208..afc30a0 100644 --- a/test/openat2.c +++ b/test/openat2.c @@ -29,7 +29,7 @@ static int test_openat2(struct io_uring *ring, const char *path, int dfd, memset(&how, 0, sizeof(how)); how.flags = O_RDWR; io_uring_prep_openat2(sqe, dfd, path, &how); - sqe->splice_fd_in = fixed_slot; + sqe->file_index = fixed_slot; ret = io_uring_submit(ring); if (ret <= 0) { -- cgit v1.2.3 From ea3ca3be8d84f130d9e39078e1d54b09176c8f8a Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 26 Aug 2021 12:13:16 +0100 Subject: io_uring: update buffer update feature testing IORING_FEAT_RSRC_TAGS came late, and it's the best way to check if a ring supports resource (i.e. buffer or file) tagging and dynamic buffer updates. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/de5fd2626bd4eabd0eec3eb8310888b4eb1a2539.1629976377.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/rsrc_tags.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/rsrc_tags.c b/test/rsrc_tags.c index 337fbb8..a82ba21 100644 --- a/test/rsrc_tags.c +++ b/test/rsrc_tags.c @@ -75,17 +75,17 @@ static int update_rsrc(struct io_uring *ring, int type, int nr, int off, static bool has_rsrc_update(void) { struct io_uring ring; - char buf[1024]; - struct iovec vec = {.iov_base = buf, .iov_len = sizeof(buf), }; int ret; ret = io_uring_queue_init(1, &ring, 0); - if (ret) - return false; + if (ret) { + fprintf(stderr, "io_uring_queue_init() failed, %d\n", ret); + exit(1); + } - ret = register_rsrc(&ring, TEST_IORING_RSRC_BUFFER, 1, &vec, NULL); + ret = ring.features & IORING_FEAT_RSRC_TAGS; io_uring_queue_exit(&ring); - return ret != -EINVAL; + return ret; } static int test_tags_generic(int nr, int type, void *rsrc, int ring_flags) -- cgit v1.2.3 From 191731414a5bc76ce085cbe9132979a56ad976d8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 Aug 2021 08:27:24 -0600 Subject: configure: document --cc and --cxx options Signed-off-by: Jens Axboe --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 5a0ae89..afccef1 100755 --- a/configure +++ b/configure @@ -69,6 +69,8 @@ Options: [defaults in brackets after descriptions] --libdevdir=PATH install development libraries in PATH [$libdevdir] --mandir=PATH install man pages in PATH [$mandir] --datadir=PATH install shared data in PATH [$datadir] + --cc=CMD use CMD as the C compiler + --cxx=CMD use CMD as the C++ compiler EOF exit 0 fi -- cgit v1.2.3 From 1584f9a6b5027369ecf0afb6a6f1ab76599f37b5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 Aug 2021 08:40:41 -0600 Subject: liburing.h: make header clean for implicit sign and size conversions Link: https://github.com/axboe/liburing/issues/366 Signed-off-by: Jens Axboe --- src/include/liburing.h | 67 +++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 4c7bedb..71e5241 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -208,14 +208,14 @@ static inline void *io_uring_cqe_get_data(const struct io_uring_cqe *cqe) static inline void io_uring_sqe_set_flags(struct io_uring_sqe *sqe, unsigned flags) { - sqe->flags = flags; + sqe->flags = (__u8) flags; } static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd, const void *addr, unsigned len, __u64 offset) { - sqe->opcode = op; + sqe->opcode = (__u8) op; sqe->flags = 0; sqe->ioprio = 0; sqe->fd = fd; @@ -255,8 +255,9 @@ static inline void io_uring_prep_splice(struct io_uring_sqe *sqe, unsigned int nbytes, unsigned int splice_flags) { - io_uring_prep_rw(IORING_OP_SPLICE, sqe, fd_out, NULL, nbytes, off_out); - sqe->splice_off_in = off_in; + io_uring_prep_rw(IORING_OP_SPLICE, sqe, fd_out, NULL, nbytes, + (__u64) off_out); + sqe->splice_off_in = (__u64) off_in; sqe->splice_fd_in = fd_in; sqe->splice_flags = splice_flags; } @@ -284,7 +285,7 @@ static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd, __u64 offset, int buf_index) { io_uring_prep_rw(IORING_OP_READ_FIXED, sqe, fd, buf, nbytes, offset); - sqe->buf_index = buf_index; + sqe->buf_index = (__u16) buf_index; } static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd, @@ -299,7 +300,7 @@ static inline void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd, __u64 offset, int buf_index) { io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset); - sqe->buf_index = buf_index; + sqe->buf_index = (__u16) buf_index; } static inline void io_uring_prep_recvmsg(struct io_uring_sqe *sqe, int fd, @@ -398,14 +399,14 @@ static inline void io_uring_prep_accept(struct io_uring_sqe *sqe, int fd, { io_uring_prep_rw(IORING_OP_ACCEPT, sqe, fd, addr, 0, (__u64) (unsigned long) addrlen); - sqe->accept_flags = flags; + sqe->accept_flags = (__u32) flags; } static inline void io_uring_prep_cancel(struct io_uring_sqe *sqe, void *user_data, int flags) { io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, -1, user_data, 0, 0); - sqe->cancel_flags = flags; + sqe->cancel_flags = (__u32) flags; } static inline void io_uring_prep_link_timeout(struct io_uring_sqe *sqe, @@ -427,7 +428,8 @@ static inline void io_uring_prep_files_update(struct io_uring_sqe *sqe, int *fds, unsigned nr_fds, int offset) { - io_uring_prep_rw(IORING_OP_FILES_UPDATE, sqe, -1, fds, nr_fds, offset); + io_uring_prep_rw(IORING_OP_FILES_UPDATE, sqe, -1, fds, nr_fds, + (__u64) offset); } static inline void io_uring_prep_fallocate(struct io_uring_sqe *sqe, int fd, @@ -435,14 +437,15 @@ static inline void io_uring_prep_fallocate(struct io_uring_sqe *sqe, int fd, { io_uring_prep_rw(IORING_OP_FALLOCATE, sqe, fd, - (const uintptr_t *) (unsigned long) len, mode, offset); + (const uintptr_t *) (unsigned long) len, + (unsigned int) mode, (__u64) offset); } static inline void io_uring_prep_openat(struct io_uring_sqe *sqe, int dfd, const char *path, int flags, mode_t mode) { io_uring_prep_rw(IORING_OP_OPENAT, sqe, dfd, path, mode, 0); - sqe->open_flags = flags; + sqe->open_flags = (__u32) flags; } static inline void io_uring_prep_close(struct io_uring_sqe *sqe, int fd) @@ -469,35 +472,35 @@ static inline void io_uring_prep_statx(struct io_uring_sqe *sqe, int dfd, { io_uring_prep_rw(IORING_OP_STATX, sqe, dfd, path, mask, (__u64) (unsigned long) statxbuf); - sqe->statx_flags = flags; + sqe->statx_flags = (__u32) flags; } static inline void io_uring_prep_fadvise(struct io_uring_sqe *sqe, int fd, __u64 offset, off_t len, int advice) { - io_uring_prep_rw(IORING_OP_FADVISE, sqe, fd, NULL, len, offset); - sqe->fadvise_advice = advice; + io_uring_prep_rw(IORING_OP_FADVISE, sqe, fd, NULL, (__u32) len, offset); + sqe->fadvise_advice = (__u32) advice; } static inline void io_uring_prep_madvise(struct io_uring_sqe *sqe, void *addr, off_t length, int advice) { - io_uring_prep_rw(IORING_OP_MADVISE, sqe, -1, addr, length, 0); - sqe->fadvise_advice = advice; + io_uring_prep_rw(IORING_OP_MADVISE, sqe, -1, addr, (__u32) length, 0); + sqe->fadvise_advice = (__u32) advice; } static inline void io_uring_prep_send(struct io_uring_sqe *sqe, int sockfd, const void *buf, size_t len, int flags) { - io_uring_prep_rw(IORING_OP_SEND, sqe, sockfd, buf, len, 0); - sqe->msg_flags = flags; + io_uring_prep_rw(IORING_OP_SEND, sqe, sockfd, buf, (__u32) len, 0); + sqe->msg_flags = (__u32) flags; } static inline void io_uring_prep_recv(struct io_uring_sqe *sqe, int sockfd, void *buf, size_t len, int flags) { - io_uring_prep_rw(IORING_OP_RECV, sqe, sockfd, buf, len, 0); - sqe->msg_flags = flags; + io_uring_prep_rw(IORING_OP_RECV, sqe, sockfd, buf, (__u32) len, 0); + sqe->msg_flags = (__u32) flags; } static inline void io_uring_prep_openat2(struct io_uring_sqe *sqe, int dfd, @@ -512,44 +515,46 @@ static inline void io_uring_prep_epoll_ctl(struct io_uring_sqe *sqe, int epfd, int fd, int op, struct epoll_event *ev) { - io_uring_prep_rw(IORING_OP_EPOLL_CTL, sqe, epfd, ev, op, fd); + io_uring_prep_rw(IORING_OP_EPOLL_CTL, sqe, epfd, ev, + (__u32) op, (__u32) fd); } static inline void io_uring_prep_provide_buffers(struct io_uring_sqe *sqe, void *addr, int len, int nr, int bgid, int bid) { - io_uring_prep_rw(IORING_OP_PROVIDE_BUFFERS, sqe, nr, addr, len, bid); - sqe->buf_group = bgid; + io_uring_prep_rw(IORING_OP_PROVIDE_BUFFERS, sqe, nr, addr, (__u32) len, + (__u64) bid); + sqe->buf_group = (__u16) bgid; } static inline void io_uring_prep_remove_buffers(struct io_uring_sqe *sqe, int nr, int bgid) { io_uring_prep_rw(IORING_OP_REMOVE_BUFFERS, sqe, nr, NULL, 0, 0); - sqe->buf_group = bgid; + sqe->buf_group = (__u16) bgid; } static inline void io_uring_prep_shutdown(struct io_uring_sqe *sqe, int fd, int how) { - io_uring_prep_rw(IORING_OP_SHUTDOWN, sqe, fd, NULL, how, 0); + io_uring_prep_rw(IORING_OP_SHUTDOWN, sqe, fd, NULL, (__u32) how, 0); } static inline void io_uring_prep_unlinkat(struct io_uring_sqe *sqe, int dfd, const char *path, int flags) { io_uring_prep_rw(IORING_OP_UNLINKAT, sqe, dfd, path, 0, 0); - sqe->unlink_flags = flags; + sqe->unlink_flags = (__u32) flags; } static inline void io_uring_prep_renameat(struct io_uring_sqe *sqe, int olddfd, const char *oldpath, int newdfd, const char *newpath, int flags) { - io_uring_prep_rw(IORING_OP_RENAMEAT, sqe, olddfd, oldpath, newdfd, + io_uring_prep_rw(IORING_OP_RENAMEAT, sqe, olddfd, oldpath, (__u32) newdfd, (uint64_t) (uintptr_t) newpath); - sqe->rename_flags = flags; + sqe->rename_flags = (__u32) flags; } static inline void io_uring_prep_sync_file_range(struct io_uring_sqe *sqe, @@ -557,7 +562,7 @@ static inline void io_uring_prep_sync_file_range(struct io_uring_sqe *sqe, __u64 offset, int flags) { io_uring_prep_rw(IORING_OP_SYNC_FILE_RANGE, sqe, fd, NULL, len, offset); - sqe->sync_range_flags = flags; + sqe->sync_range_flags = (__u32) flags; } static inline void io_uring_prep_mkdirat(struct io_uring_sqe *sqe, int dfd, @@ -577,9 +582,9 @@ static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd, const char *oldpath, int newdfd, const char *newpath, int flags) { - io_uring_prep_rw(IORING_OP_LINKAT, sqe, olddfd, oldpath, newdfd, + io_uring_prep_rw(IORING_OP_LINKAT, sqe, olddfd, oldpath, (__u32) newdfd, (uint64_t) (uintptr_t) newpath); - sqe->hardlink_flags = flags; + sqe->hardlink_flags = (__u32) flags; } /* -- cgit v1.2.3 From 0fe4657b3c5fb2f6d22eb6ab9903074826deb367 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 Aug 2021 08:54:19 -0600 Subject: test/35fa71a030ca-test.c: limit runtime to 5 seconds This test always keeps running and depends on our normal timeout to terminate it. That is somewhat annoying, we really should not have tests that time out. That should be an exception condition, something that should be investigated. Signed-off-by: Jens Axboe --- test/35fa71a030ca-test.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/35fa71a030ca-test.c b/test/35fa71a030ca-test.c index f5fcc4d..f83cc9d 100644 --- a/test/35fa71a030ca-test.c +++ b/test/35fa71a030ca-test.c @@ -321,6 +321,9 @@ int main(int argc, char *argv[]) return 0; signal(SIGINT, sig_int); mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); + signal(SIGALRM, sig_int); + alarm(5); + loop(); return 0; } -- cgit v1.2.3 From 42c7cea5d6ad9a3c8a607111967bef316d3ed1d3 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 27 Aug 2021 22:49:32 +0700 Subject: test/connect: fix random EACCES for non-root test We found random failures on `test/connect`, the bug reproduction is very easy, just run the test in a loop as non-root user and we will see couple of failures with `EACCES` on bind(). ammarfaizi2@integral:~/project/now/liburing$ for i in {1..1000}; do test/connect; done; bind(): Permission denied test_connect(): failed bind(): Permission denied test_connect(): failed bind(): Permission denied test_connect(): failed bind(): Permission denied test_connect(): failed bind(): Permission denied test_connect(): failed bind(): Permission denied test_connect(): failed bind(): Permission denied test_connect(): failed ^C ammarfaizi2@integral:~/project/now/liburing$ It turned out that we didn't take care of endianess. Fix this by applying `htons()` after generating port. We also changed the s_addr assignment with inet_addr("127.0.0.1") instead of 0x0100007fU to make it cleaner. Fixes: c8291a94ddf695447f94728a2b819550138e36e8 ("Add a simple connect test") Reported-by: Louvian Lyndal Signed-off-by: Ammar Faizi --- test/connect.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/connect.c b/test/connect.c index 0ba3ee6..3ae10de 100644 --- a/test/connect.c +++ b/test/connect.c @@ -19,7 +19,8 @@ #include "liburing.h" static int no_connect; -static int use_port; +static unsigned short use_port; +static unsigned int use_addr; static int create_socket(void) { @@ -90,7 +91,7 @@ static int listen_on_socket(int fd) memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = use_port; - addr.sin_addr.s_addr = 0x0100007fU; + addr.sin_addr.s_addr = use_addr; ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); if (ret == -1) { @@ -369,6 +370,8 @@ int main(int argc, char *argv[]) srand(getpid()); use_port = (rand() % 61440) + 4096; + use_port = htons(use_port); + use_addr = inet_addr("127.0.0.1"); ret = test_connect_with_no_peer(&ring); if (ret == -1) { -- cgit v1.2.3 From 6f86e447ce5f89c6ba278ad24962c221cea4b8f3 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 27 Aug 2021 17:38:23 +0100 Subject: tests: file create/unlink cleanup Unlink earlier if possible right after getting an fd, so tests don't leave files when exited abnormally. Also, improve test file naming in a couple of cases. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/abbcfa9fa56fde7e740a2c887afef74a779bf36f.1630082134.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/cq-overflow.c | 13 +++++++------ test/d4ae271dfaae-test.c | 4 ++-- test/eeed8b54e0df-test.c | 11 +++-------- test/fallocate.c | 9 +++------ test/fsync.c | 4 ++-- test/io-cancel.c | 9 +++++---- test/link_drain.c | 3 +-- test/read-write.c | 2 +- test/sq-poll-dup.c | 7 +++---- test/sq-poll-share.c | 6 ++---- test/submit-reuse.c | 25 +++++++++++-------------- test/thread-exit.c | 10 +++------- 12 files changed, 43 insertions(+), 60 deletions(-) diff --git a/test/cq-overflow.c b/test/cq-overflow.c index 945dc93..057570e 100644 --- a/test/cq-overflow.c +++ b/test/cq-overflow.c @@ -243,6 +243,7 @@ err: int main(int argc, char *argv[]) { + const char *fname = ".cq-overflow"; unsigned iters, drops; unsigned long usecs; int ret; @@ -256,7 +257,7 @@ int main(int argc, char *argv[]) return ret; } - t_create_file(".basic-rw", FILE_SIZE); + t_create_file(fname, FILE_SIZE); vecs = t_create_buffers(BUFFERS, BS); @@ -265,7 +266,7 @@ int main(int argc, char *argv[]) do { drops = 0; - if (test_io(".basic-rw", usecs, &drops, 0)) { + if (test_io(fname, usecs, &drops, 0)) { fprintf(stderr, "test_io nofault failed\n"); goto err; } @@ -275,19 +276,19 @@ int main(int argc, char *argv[]) iters++; } while (iters < 40); - if (test_io(".basic-rw", usecs, &drops, 0)) { + if (test_io(fname, usecs, &drops, 0)) { fprintf(stderr, "test_io nofault failed\n"); goto err; } - if (test_io(".basic-rw", usecs, &drops, 1)) { + if (test_io(fname, usecs, &drops, 1)) { fprintf(stderr, "test_io fault failed\n"); goto err; } - unlink(".basic-rw"); + unlink(fname); return 0; err: - unlink(".basic-rw"); + unlink(fname); return 1; } diff --git a/test/d4ae271dfaae-test.c b/test/d4ae271dfaae-test.c index 10c7e98..397b94b 100644 --- a/test/d4ae271dfaae-test.c +++ b/test/d4ae271dfaae-test.c @@ -43,6 +43,8 @@ int main(int argc, char *argv[]) } fd = open(fname, O_RDONLY | O_DIRECT); + if (fname != argv[1]) + unlink(fname); if (fd < 0) { perror("open"); goto out; @@ -89,8 +91,6 @@ int main(int argc, char *argv[]) close(fd); out: - if (fname != argv[1]) - unlink(fname); io_uring_queue_exit(&ring); return ret; } diff --git a/test/eeed8b54e0df-test.c b/test/eeed8b54e0df-test.c index b6e27cc..62f6f45 100644 --- a/test/eeed8b54e0df-test.c +++ b/test/eeed8b54e0df-test.c @@ -26,6 +26,7 @@ static int get_file_fd(void) int fd; fd = open("testfile", O_RDWR | O_CREAT, 0644); + unlink("testfile"); if (fd < 0) { perror("open file"); return -1; @@ -54,12 +55,6 @@ err: return fd; } -static void put_file_fd(int fd) -{ - close(fd); - unlink("testfile"); -} - int main(int argc, char *argv[]) { struct io_uring ring; @@ -111,9 +106,9 @@ int main(int argc, char *argv[]) goto err; } - put_file_fd(fd); + close(fd); return 0; err: - put_file_fd(fd); + close(fd); return 1; } diff --git a/test/fallocate.c b/test/fallocate.c index da90be8..ddb53a6 100644 --- a/test/fallocate.c +++ b/test/fallocate.c @@ -42,6 +42,7 @@ static int test_fallocate_rlimit(struct io_uring *ring) perror("open"); return 1; } + unlink(buf); sqe = io_uring_get_sqe(ring); if (!sqe) { @@ -72,10 +73,8 @@ static int test_fallocate_rlimit(struct io_uring *ring) } io_uring_cqe_seen(ring, cqe); out: - unlink(buf); return 0; err: - unlink(buf); return 1; } @@ -93,6 +92,7 @@ static int test_fallocate(struct io_uring *ring) perror("open"); return 1; } + unlink(buf); sqe = io_uring_get_sqe(ring); if (!sqe) { @@ -136,10 +136,8 @@ static int test_fallocate(struct io_uring *ring) } out: - unlink(buf); return 0; err: - unlink(buf); return 1; } @@ -160,6 +158,7 @@ static int test_fallocate_fsync(struct io_uring *ring) perror("open"); return 1; } + unlink(buf); sqe = io_uring_get_sqe(ring); if (!sqe) { @@ -209,10 +208,8 @@ static int test_fallocate_fsync(struct io_uring *ring) goto err; } - unlink(buf); return 0; err: - unlink(buf); return 1; } diff --git a/test/fsync.c b/test/fsync.c index 8454398..5ae8441 100644 --- a/test/fsync.c +++ b/test/fsync.c @@ -63,11 +63,12 @@ static int test_barrier_fsync(struct io_uring *ring) int i, fd, ret; off_t off; - fd = open("testfile", O_WRONLY | O_CREAT, 0644); + fd = open("fsync-testfile", O_WRONLY | O_CREAT, 0644); if (fd < 0) { perror("open"); return 1; } + unlink("fsync-testfile"); for (i = 0; i < ARRAY_SIZE(iovecs); i++) { iovecs[i].iov_base = t_malloc(4096); @@ -135,7 +136,6 @@ static int test_barrier_fsync(struct io_uring *ring) err: ret = 1; out: - unlink("testfile"); for (i = 0; i < ARRAY_SIZE(iovecs); i++) free(iovecs[i].iov_base); return ret; diff --git a/test/io-cancel.c b/test/io-cancel.c index 63d2f7d..b5b443d 100644 --- a/test/io-cancel.c +++ b/test/io-cancel.c @@ -486,6 +486,7 @@ static int test_sqpoll_cancel_iowq_requests(void) int main(int argc, char *argv[]) { + const char *fname = ".io-cancel-test"; int i, ret; if (argc > 1) @@ -511,7 +512,7 @@ int main(int argc, char *argv[]) return 1; } - t_create_file(".basic-rw", FILE_SIZE); + t_create_file(fname, FILE_SIZE); vecs = t_create_buffers(BUFFERS, BS); @@ -520,7 +521,7 @@ int main(int argc, char *argv[]) int partial = (i & 2) != 0; int async = (i & 4) != 0; - ret = test_io_cancel(".basic-rw", write, partial, async); + ret = test_io_cancel(fname, write, partial, async); if (ret) { fprintf(stderr, "test_io_cancel %d %d %d failed\n", write, partial, async); @@ -528,9 +529,9 @@ int main(int argc, char *argv[]) } } - unlink(".basic-rw"); + unlink(fname); return 0; err: - unlink(".basic-rw"); + unlink(fname); return 1; } diff --git a/test/link_drain.c b/test/link_drain.c index a50fe88..b95168d 100644 --- a/test/link_drain.c +++ b/test/link_drain.c @@ -111,6 +111,7 @@ int test_link_drain_multi(struct io_uring *ring) perror("open"); return 1; } + unlink("testfile"); iovecs.iov_base = t_malloc(4096); iovecs.iov_len = 4096; @@ -189,12 +190,10 @@ int test_link_drain_multi(struct io_uring *ring) free(iovecs.iov_base); close(fd); - unlink("testfile"); return 0; err: free(iovecs.iov_base); close(fd); - unlink("testfile"); return 1; } diff --git a/test/read-write.c b/test/read-write.c index 0c55159..885905b 100644 --- a/test/read-write.c +++ b/test/read-write.c @@ -670,6 +670,7 @@ static int test_write_efbig(void) perror("file open"); goto err; } + unlink(".efbig"); ret = io_uring_queue_init(32, &ring, 0); if (ret) { @@ -726,7 +727,6 @@ static int test_write_efbig(void) err: if (fd != -1) close(fd); - unlink(".efbig"); return 1; } diff --git a/test/sq-poll-dup.c b/test/sq-poll-dup.c index eeb619c..e688c9f 100644 --- a/test/sq-poll-dup.c +++ b/test/sq-poll-dup.c @@ -167,6 +167,9 @@ int main(int argc, char *argv[]) vecs = t_create_buffers(BUFFERS, BS); fd = open(fname, O_RDONLY | O_DIRECT); + if (fname != argv[1]) + unlink(fname); + if (fd < 0) { perror("open"); return -1; @@ -191,11 +194,7 @@ int main(int argc, char *argv[]) goto err; } - if (fname != argv[1]) - unlink(fname); return 0; err: - if (fname != argv[1]) - unlink(fname); return 1; } diff --git a/test/sq-poll-share.c b/test/sq-poll-share.c index a46b94f..99227d5 100644 --- a/test/sq-poll-share.c +++ b/test/sq-poll-share.c @@ -89,6 +89,8 @@ int main(int argc, char *argv[]) vecs = t_create_buffers(BUFFERS, BS); fd = open(fname, O_RDONLY | O_DIRECT); + if (fname != argv[1]) + unlink(fname); if (fd < 0) { perror("open"); return -1; @@ -129,11 +131,7 @@ int main(int argc, char *argv[]) ios += BUFFERS; } - if (fname != argv[1]) - unlink(fname); return 0; err: - if (fname != argv[1]) - unlink(fname); return 1; } diff --git a/test/submit-reuse.c b/test/submit-reuse.c index 74ba769..ca30e98 100644 --- a/test/submit-reuse.c +++ b/test/submit-reuse.c @@ -140,11 +140,6 @@ static int test_reuse(int argc, char *argv[], int split, int async) int do_unlink = 1; void *tret; - if (argc > 1) { - fname1 = argv[1]; - do_unlink = 0; - } - ret = io_uring_queue_init_params(32, &ring, &p); if (ret) { fprintf(stderr, "io_uring_queue_init: %d\n", ret); @@ -153,21 +148,29 @@ static int test_reuse(int argc, char *argv[], int split, int async) if (!(p.features & IORING_FEAT_SUBMIT_STABLE)) { fprintf(stdout, "FEAT_SUBMIT_STABLE not there, skipping\n"); + io_uring_queue_exit(&ring); no_stable = 1; return 0; } - if (do_unlink) + if (argc > 1) { + fname1 = argv[1]; + do_unlink = 0; + } else { t_create_file(fname1, FILE_SIZE); - - t_create_file(".reuse.2", FILE_SIZE); + } fd1 = open(fname1, O_RDONLY); + if (do_unlink) + unlink(fname1); if (fd1 < 0) { perror("open fname1"); goto err; } + + t_create_file(".reuse.2", FILE_SIZE); fd2 = open(".reuse.2", O_RDONLY); + unlink(".reuse.2"); if (fd2 < 0) { perror("open .reuse.2"); goto err; @@ -206,15 +209,9 @@ static int test_reuse(int argc, char *argv[], int split, int async) close(fd2); close(fd1); io_uring_queue_exit(&ring); - if (do_unlink) - unlink(fname1); - unlink(".reuse.2"); return 0; err: io_uring_queue_exit(&ring); - if (do_unlink) - unlink(fname1); - unlink(".reuse.2"); return 1; } diff --git a/test/thread-exit.c b/test/thread-exit.c index c2f2148..7f66028 100644 --- a/test/thread-exit.c +++ b/test/thread-exit.c @@ -86,12 +86,12 @@ int main(int argc, char *argv[]) } else { fname = ".thread.exit"; do_unlink = 1; - } - - if (do_unlink) t_create_file(fname, 4096); + } fd = open(fname, O_WRONLY); + if (do_unlink) + unlink(fname); if (fd < 0) { perror("open"); return 1; @@ -125,11 +125,7 @@ int main(int argc, char *argv[]) io_uring_cqe_seen(&ring, cqe); } - if (do_unlink) - unlink(fname); return d.err; err: - if (do_unlink) - unlink(fname); return 1; } -- cgit v1.2.3 From e65cbc32f76566bde66c6db2d3d867b461138b26 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 27 Aug 2021 20:32:14 +0100 Subject: register: add tagging and buf update helpers Add heplers for rsrc (buffers, files) updates and registration with tags. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/314323bcd6d053f063181d5b900f6d8f6fb3ce6a.1630092701.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 20 ++++++++++++++ src/liburing.map | 4 +++ src/register.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/rsrc_tags.c | 8 ++++++ 4 files changed, 103 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 71e5241..fbd1cc5 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -125,9 +125,29 @@ extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); extern int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, unsigned nr_iovecs); +extern int io_uring_register_buffers_tags(struct io_uring *ring, + const struct iovec *iovecs, + const __u64 *tags, + unsigned nr); +extern int io_uring_register_buffers_update_tag(struct io_uring *ring, + unsigned off, + const struct iovec *iovecs, + const __u64 *tags, + unsigned nr); extern int io_uring_unregister_buffers(struct io_uring *ring); + extern int io_uring_register_files(struct io_uring *ring, const int *files, unsigned nr_files); +extern int io_uring_register_files_tags(struct io_uring *ring, + const int *files, + const __u64 *tags, + unsigned nr); +extern int io_uring_register_files_update_tag(struct io_uring *ring, + unsigned off, + const int *files, + const __u64 *tags, + unsigned nr_files); + extern int io_uring_unregister_files(struct io_uring *ring); extern int io_uring_register_files_update(struct io_uring *ring, unsigned off, int *files, unsigned nr_files); diff --git a/src/liburing.map b/src/liburing.map index 012ac4e..b29aa5f 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -36,4 +36,8 @@ LIBURING_2.1 { global: io_uring_mlock_size_params; io_uring_mlock_size; + io_uring_register_buffers_tags; + io_uring_register_buffers_update_tag; + io_uring_register_files_tags; + io_uring_register_files_update_tag; } LIBURING_2.0; diff --git a/src/register.c b/src/register.c index 994aaff..a947aec 100644 --- a/src/register.c +++ b/src/register.c @@ -14,6 +14,42 @@ #include "syscall.h" +int io_uring_register_buffers_update_tag(struct io_uring *ring, unsigned off, + const struct iovec *iovecs, + const __u64 *tags, + unsigned nr) +{ + struct io_uring_rsrc_update2 up = { + .offset = off, + .data = (unsigned long)iovecs, + .tags = (unsigned long)tags, + .nr = nr, + }; + int ret; + + ret = __sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_BUFFERS_UPDATE, + &up, sizeof(up)); + return ret < 0 ? -errno : ret; +} + +int io_uring_register_buffers_tags(struct io_uring *ring, + const struct iovec *iovecs, + const __u64 *tags, + unsigned nr) +{ + struct io_uring_rsrc_register reg = { + .nr = nr, + .data = (unsigned long)iovecs, + .tags = (unsigned long)tags, + }; + int ret; + + ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_BUFFERS2, + ®, sizeof(reg)); + return ret < 0 ? -errno : ret; +} + int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, unsigned nr_iovecs) { @@ -39,6 +75,24 @@ int io_uring_unregister_buffers(struct io_uring *ring) return 0; } +int io_uring_register_files_update_tag(struct io_uring *ring, unsigned off, + const int *files, const __u64 *tags, + unsigned nr_files) +{ + struct io_uring_rsrc_update2 up = { + .offset = off, + .data = (unsigned long)files, + .tags = (unsigned long)tags, + .nr = nr_files, + }; + int ret; + + ret = __sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_FILES_UPDATE2, + &up, sizeof(up)); + return ret < 0 ? -errno : ret; +} + /* * Register an update for an existing file set. The updates will start at * 'off' in the original array, and 'nr_files' is the number of files we'll @@ -64,6 +118,23 @@ int io_uring_register_files_update(struct io_uring *ring, unsigned off, return ret; } + +int io_uring_register_files_tags(struct io_uring *ring, + const int *files, const __u64 *tags, + unsigned nr) +{ + struct io_uring_rsrc_register reg = { + .nr = nr, + .data = (unsigned long)files, + .tags = (unsigned long)tags, + }; + int ret; + + ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_FILES2, + ®, sizeof(reg)); + return ret < 0 ? -errno : ret; +} + int io_uring_register_files(struct io_uring *ring, const int *files, unsigned nr_files) { diff --git a/test/rsrc_tags.c b/test/rsrc_tags.c index a82ba21..a3fec0c 100644 --- a/test/rsrc_tags.c +++ b/test/rsrc_tags.c @@ -32,6 +32,10 @@ static bool check_cq_empty(struct io_uring *ring) return ret == -EAGAIN; } +/* + * There are io_uring_register_buffers_tags() and other wrappers, + * but they may change, so hand-code to specifically test this ABI. + */ static int register_rsrc(struct io_uring *ring, int type, int nr, const void *arg, const __u64 *tags) { @@ -52,6 +56,10 @@ static int register_rsrc(struct io_uring *ring, int type, int nr, return ret ? -errno : 0; } +/* + * There are io_uring_register_buffers_update_tag() and other wrappers, + * but they may change, so hand-code to specifically test this ABI. + */ static int update_rsrc(struct io_uring *ring, int type, int nr, int off, const void *arg, const __u64 *tags) { -- cgit v1.2.3 From 311f02b30c5d6818ede4cd809b57758dcd99ea79 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sat, 28 Aug 2021 19:30:43 +0100 Subject: man: fix io_uring_sqe alignment Tabs make man to go crazy, replace them with spaces where it haven't been done yet. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/82fb889efbf3a7138a564eb10ce7c14d04227701.1630175370.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 00f0778..fc81099 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -162,18 +162,18 @@ struct io_uring_sqe { }; __u64 user_data; /* data to be passed back at completion time */ union { - struct { - /* index into fixed buffers, if used */ + struct { + /* index into fixed buffers, if used */ union { /* index into fixed buffers, if used */ __u16 buf_index; /* for grouped buffer selection */ __u16 buf_group; } - /* personality to use, if used */ - __u16 personality; + /* personality to use, if used */ + __u16 personality; __s32 splice_fd_in; - }; + }; __u64 __pad2[3]; }; }; -- cgit v1.2.3 From 40477e3b9a14a26024209473a0fac88833e5b20d Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sat, 28 Aug 2021 19:30:44 +0100 Subject: man: update notes on register quiesce We don't quiesce rsrc registrations since 5.13, reflect it in the man. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/9976eea690c26a86c5f02f7a9b99bd8b58548d3e.1630175370.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- man/io_uring_register.2 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index 5326a87..a8479fd 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -88,9 +88,9 @@ then issuing a new call to .BR io_uring_register () with the new buffers. -Note that registering buffers will wait for the ring to idle. If the application -currently has requests in-flight, the registration will wait for those to -finish before proceeding. +Note that before 5.13 registering buffers would wait for the ring to idle. +If the application currently has requests in-flight, the registration will +wait for those to finish before proceeding. An application need not unregister buffers explicitly before shutting down the io_uring instance. Available since 5.1. @@ -128,9 +128,9 @@ See .B IORING_REGISTER_FILES_UPDATE for how to update files in place. -Note that registering files will wait for the ring to idle. If the application -currently has requests in-flight, the registration will wait for those to -finish before proceeding. See +Note that before 5.13 registering files would wait for the ring to idle. +If the application currently has requests in-flight, the registration will +wait for those to finish before proceeding. See .B IORING_REGISTER_FILES_UPDATE for how to update an existing set without that limitation. -- cgit v1.2.3 From 09f9c79d1bb8cd24b1b83c9b880863db8bbf5cfd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 13:46:49 -0600 Subject: man/io_uring_register.2: add IORING_(UN)REGISTER_IOWQ Signed-off-by: Jens Axboe --- man/io_uring_register.2 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index a8479fd..e1c0ed4 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -292,6 +292,28 @@ must be specified in the call to Available since 5.10. +.TP +.B IORING_REGISTER_IOWQ_AFF +By default, async workers created by io_uring will inherit the CPU mask of its +parent. This is usually all the CPUs in the system, unless the parent is being +run with a limited set. If this isn't the desired outcome, the application +may explicitly tell io_uring what CPUs the async workers may run on. +.I arg +must point to a +.B cpu_set_t +mask, and +.I nr_args +the byte size of that mask. + +Available since 5.14. + +.TP +.B IORING_UNREGISTER_IOWQ_AFF +Undoes a CPU mask previously set with +.B IORING_REGISTER_IOWQ_AFF + +Available since 5.14. + .SH RETURN VALUE On success, -- cgit v1.2.3 From 529821a8924007d2e84e4916b960ff9fb0bf13f4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:01:15 -0600 Subject: man/io_uring_enter.2: add poll update and multishot mode Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 55 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index fc81099..4808bfe 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -228,11 +228,55 @@ specified in the .I poll_events field. Unlike poll or epoll without .BR EPOLLONESHOT , -this interface always works in one shot mode. That is, once the poll -operation is completed, it will have to be resubmitted. This command works like +by default this interface always works in one shot mode. That is, once the poll +operation is completed, it will have to be resubmitted. + +If +.B IORING_POLL_ADD_MULTI +is set in the SQE +.I len +field, then the poll will work in multi shot mode instead. That means it'll +repatedly trigger when the requested event becomes true, and hence multiple +CQEs can be generated from this single SQE. The CQE +.I flags +field will have +.B IORING_CQE_F_MORE +set on completion if the application should expect further CQE entries from +the original request. If this flag isn't set on completion, then the poll +request has been terminated and no further events will be generated. This mode +is available since 5.13. + +If +.B IORING_POLL_UPDATE_EVENTS +is set in the SQE +.I len +field, then the request will update an existing poll request with the mask of +events passed in with this request. The lookup is based on the +.I user_data +field of the original SQE submitted, and this values is passed in the +.I addr +field of the SQE. This mode is available since 5.13. + +If +.B IORING_POLL_UPDATE_USER_DATA +is set in the SQE +.I len +field, then the request will update the +.I user_data +of an existing poll request based on the value passed in the +.I off +field. This mode is available since 5.13. + +This command works like an async .BR poll(2) -and the completion event result is the returned mask of events. +and the completion event result is the returned mask of events. For the +variants that update +.I user_data +or +.I events +, the completion result will be similar to +.B IORING_OP_POLL_REMOVE. .TP .B IORING_OP_POLL_REMOVE @@ -243,7 +287,10 @@ field of the will contain 0. If not found, .I res will contain -.B -ENOENT. +.B -ENOENT, +or +.B -EALREADY +if the poll request was in the process of completing already. .TP .B IORING_OP_EPOLL_CTL -- cgit v1.2.3 From b96ad722afee987ce6e0c75cde459af600179427 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:04:35 -0600 Subject: man/io_uring_enter.2: note that cqe->flags is indeed used Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 4808bfe..7bc64d7 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -983,7 +983,11 @@ is copied from the field of the same name in the submission queue entry. The primary use case is to store data that the application will need to access upon completion of this particular I/O. The .I flags -is reserved for future use. +is used for certain commands, like +.B IORING_OP_POLL_ADD +or in conjunction with +.B IOSQE_BUFFER_SELECT +, see those entries. .I res is the operation-specific result, but io_uring-specific errors (e.g. flags or opcode invalid) are returned through this field. -- cgit v1.2.3 From 4e335a52e55174f0f134c73938b111471d56d7b9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:12:47 -0600 Subject: man/io_uring_enter.2: add new 5.15 opcodes This documents: IORING_OP_MKDIRAT, IORING_OP_SYMLINKAT, and IORING_OP_LINKAT. Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 7bc64d7..fc56e66 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -824,6 +824,69 @@ being passed in to .BR unlinkat(2). Available since 5.11. +.TP +.B IORING_OP_MKDIRAT +Issue the equivalent of a +.BR mkdirat2(2) +system call. +.I fd +should be set to the +.I dirfd, +.I addr +should be set to the +.I pathname, +and +.I len +should be set to the +.I mode +being passed in to +.BR mkdirat(2). +Available since 5.15. + +.TP +.B IORING_OP_SYMLINKAT +Issue the equivalent of a +.BR symlinkat2(2) +system call. +.I fd +should be set to the +.I newdirfd, +.I addr +should be set to the +.I target +and +.I addr2 +should be set to the +.I linkpath +being passed in to +.BR symlinkat(2). +Available since 5.15. + +.TP +.B IORING_OP_LINKAT +Issue the equivalent of a +.BR linkat2(2) +system call. +.I fd +should be set to the +.I olddirfd, +.I addr +should be set to the +.I oldpath, +.I len +should be set to the +.I newdirfd, +.I addr2 +should be set to the +.I newpath, +and +.I hardlink_flags +should be set to the +.I flags +being passed in to +.BR linkat(2). +Available since 5.15. + .PP The .I flags -- cgit v1.2.3 From eecd4462b37b2e86a450d47e362a66deae17b976 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:14:30 -0600 Subject: man/io_uring_enter.2: note that not all requests support fixed files Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index fc56e66..6dd889a 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -899,7 +899,10 @@ is an index into the files array registered with the io_uring instance (see the .B IORING_REGISTER_FILES section of the .BR io_uring_register (2) -man page). Available since 5.1. +man page). Note that this isn't always available for all commands. If used on +a command that doesn't support fixed files, the SQE will error with +.B -EBADF. +Available since 5.1. .TP .B IOSQE_IO_DRAIN When this flag is specified, the SQE will not be started before previously -- cgit v1.2.3 From c5debc35b3ab6f17345275e0e8f33ade5a6c6dc4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:17:28 -0600 Subject: man/io_uring_enter.2: update SQE Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 6dd889a..682aaec 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -159,6 +159,9 @@ struct io_uring_sqe { __u32 statx_flags; __u32 fadvise_advice; __u32 splice_flags; + __u32 rename_flags; + __u32 unlink_flags; + __u32 hardlink_flags; }; __u64 user_data; /* data to be passed back at completion time */ union { @@ -172,9 +175,12 @@ struct io_uring_sqe { } /* personality to use, if used */ __u16 personality; + union { __s32 splice_fd_in; + __u32 file_index; + }; }; - __u64 __pad2[3]; + __u64 __pad2[3]; }; }; .EE -- cgit v1.2.3 From aa70ec6cdaafa489f1eca049d02ad0fa634f7e55 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:19:49 -0600 Subject: man/io_uring_enter.2: improve timeout entry Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 682aaec..68f5eb3 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -423,13 +423,14 @@ If .I timeout_flags contain .I IORING_TIMEOUT_UPDATE, -instead of removing an existing operation it updates it. +instead of removing an existing operation, it updates it. .I addr and return values are same as before. .I addr2 field must contain a pointer to a struct timespec64 structure. .I timeout_flags -may also contain IORING_TIMEOUT_ABS. +may also contain IORING_TIMEOUT_ABS, in which case the value given is an +absolute one, not a relative one. Available since 5.11. .TP -- cgit v1.2.3 From ed972e95c99b34893c35acb0de7899a875f06e95 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:26:40 -0600 Subject: man/io_uring_enter.2: add IORING_OP_TIMEOUT clock sources Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 68f5eb3..482e866 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -399,6 +399,28 @@ the timeout was cancelled before it expired, the request will complete with .I -ECANCELED. Available since 5.4. +Since 5.15, this command also supports the following modifiers in +.I timeout_flags: + +.PP +.in +12 +.B IORING_TIMEOUT_BOOTTIME +If set, then the clocksource used is +.I CLOCK_BOOTTIME +instead of +.I CLOCK_MONOTONIC. +This clocksource differs in that it includes time elapsed if the system was +suspend while having a timeout request in-flight. + +.B IORING_TIMEOUT_REALTIME +If set, then the clocksource used is +.I CLOCK_BOOTTIME +instead of +.I CLOCK_MONOTONIC. +.EE +.in +.PP + .TP .B IORING_OP_TIMEOUT_REMOVE If -- cgit v1.2.3 From 26c77d8997616432186512b212b572763f6f5da5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:33:57 -0600 Subject: man/io_uring_register.2: document IORING_REGISTER_IOWQ_MAX_UNBOUND Signed-off-by: Jens Axboe --- man/io_uring_register.2 | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index e1c0ed4..24bba5e 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -311,9 +311,33 @@ Available since 5.14. .B IORING_UNREGISTER_IOWQ_AFF Undoes a CPU mask previously set with .B IORING_REGISTER_IOWQ_AFF +Must not have +.I arg +or +.I nr_args +set. Available since 5.14. +.TP +.B IORING_REGISTER_IOWQ_MAX_UNBOUND +By default, io_uring limits the unbounded workers created to the maximum +processor count set by +.I RLIMIT_NPROC. +Sometimes this can be excessive, and this command provides a way to limit +the count per ring (per NUMA node) instead. +.I arg +must be set to an +.I unsigned int +pointer, with the value in the variable being set to the maximum count of +unbounded workers per NUMA node. If the count being passed in is 0, then +this command returns the current maximum values. If any other values is set, +this command returns either the old value, or -1 and +.I errno +set appropriately. +.I nr_args +must be set to 1, as the command only takes one argument. + .SH RETURN VALUE On success, -- cgit v1.2.3 From 02e9104c1111a48137460d831ee7f96bc4a854ec Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:34:36 -0600 Subject: man/io_uring_register.2: add missing punctuation Signed-off-by: Jens Axboe --- man/io_uring_register.2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index 24bba5e..d38d668 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -310,7 +310,7 @@ Available since 5.14. .TP .B IORING_UNREGISTER_IOWQ_AFF Undoes a CPU mask previously set with -.B IORING_REGISTER_IOWQ_AFF +.B IORING_REGISTER_IOWQ_AFF. Must not have .I arg or -- cgit v1.2.3 From 340e5b9b34ed793ba45899edb9e3f0b24488a4fd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:35:15 -0600 Subject: man/io_uring_register.2: note when MAX_UNBOUND became available Signed-off-by: Jens Axboe --- man/io_uring_register.2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index d38d668..e9a5ca4 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -338,6 +338,8 @@ set appropriately. .I nr_args must be set to 1, as the command only takes one argument. +Available since 5.15. + .SH RETURN VALUE On success, -- cgit v1.2.3 From d0e727fd768a302b6bbe04fc2674a2abb4ca9b9f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:42:08 -0600 Subject: Add (UN)REGISTER_IOWQ_AFF helpers Signed-off-by: Jens Axboe --- src/include/liburing.h | 4 ++++ src/liburing.map | 2 ++ src/register.c | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index fbd1cc5..78156d4 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "liburing/compat.h" #include "liburing/io_uring.h" @@ -163,6 +164,9 @@ extern int io_uring_register_restrictions(struct io_uring *ring, unsigned int nr_res); extern int io_uring_enable_rings(struct io_uring *ring); extern int __io_uring_sqring_wait(struct io_uring *ring); +int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, + const cpu_set_t *mask); +int io_uring_unregister_iowq_aff(struct io_uring *ring); /* * Helper for the peek/wait single cqe functions. Exported because of that, diff --git a/src/liburing.map b/src/liburing.map index b29aa5f..e493b72 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -40,4 +40,6 @@ LIBURING_2.1 { io_uring_register_buffers_update_tag; io_uring_register_files_tags; io_uring_register_files_update_tag; + io_uring_register_iowq_aff; + io_uring_unregister_iowq_aff; } LIBURING_2.0; diff --git a/src/register.c b/src/register.c index a947aec..bc8bd44 100644 --- a/src/register.c +++ b/src/register.c @@ -258,3 +258,28 @@ int io_uring_enable_rings(struct io_uring *ring) return ret; } + +int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, + const cpu_set_t *mask) +{ + int ret; + + ret = __sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_IOWQ_AFF, mask, cpusz); + if (ret < 0) + return -errno; + + return ret; +} + +int io_uring_unregister_iowq_aff(struct io_uring *ring) +{ + int ret; + + ret = __sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_IOWQ_AFF, NULL, 0); + if (ret < 0) + return -errno; + + return ret; +} -- cgit v1.2.3 From a7dd951d2b9bb93e36c344f1f3d37501cca41aad Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:46:17 -0600 Subject: Get rid of useless 'extern' on function declarations in liburing.h Signed-off-by: Jens Axboe --- src/include/liburing.h | 122 +++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 64 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 78156d4..00aea86 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -87,15 +87,15 @@ struct io_uring { * return an allocated io_uring_probe structure, or NULL if probe fails (for * example, if it is not available). The caller is responsible for freeing it */ -extern struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring); +struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring); /* same as io_uring_get_probe_ring, but takes care of ring init and teardown */ -extern struct io_uring_probe *io_uring_get_probe(void); +struct io_uring_probe *io_uring_get_probe(void); /* * frees a probe allocated through io_uring_get_probe() or * io_uring_get_probe_ring() */ -extern void io_uring_free_probe(struct io_uring_probe *probe); +void io_uring_free_probe(struct io_uring_probe *probe); static inline int io_uring_opcode_supported(const struct io_uring_probe *p, int op) { @@ -104,66 +104,60 @@ static inline int io_uring_opcode_supported(const struct io_uring_probe *p, int return (p->ops[op].flags & IO_URING_OP_SUPPORTED) != 0; } -extern int io_uring_queue_init_params(unsigned entries, struct io_uring *ring, - struct io_uring_params *p); -extern int io_uring_queue_init(unsigned entries, struct io_uring *ring, - unsigned flags); -extern int io_uring_queue_mmap(int fd, struct io_uring_params *p, - struct io_uring *ring); -extern int io_uring_ring_dontfork(struct io_uring *ring); -extern void io_uring_queue_exit(struct io_uring *ring); +int io_uring_queue_init_params(unsigned entries, struct io_uring *ring, + struct io_uring_params *p); +int io_uring_queue_init(unsigned entries, struct io_uring *ring, + unsigned flags); +int io_uring_queue_mmap(int fd, struct io_uring_params *p, + struct io_uring *ring); +int io_uring_ring_dontfork(struct io_uring *ring); +void io_uring_queue_exit(struct io_uring *ring); unsigned io_uring_peek_batch_cqe(struct io_uring *ring, struct io_uring_cqe **cqes, unsigned count); -extern int io_uring_wait_cqes(struct io_uring *ring, - struct io_uring_cqe **cqe_ptr, unsigned wait_nr, - struct __kernel_timespec *ts, sigset_t *sigmask); -extern int io_uring_wait_cqe_timeout(struct io_uring *ring, - struct io_uring_cqe **cqe_ptr, struct __kernel_timespec *ts); -extern int io_uring_submit(struct io_uring *ring); -extern int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr); -extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); - -extern int io_uring_register_buffers(struct io_uring *ring, - const struct iovec *iovecs, - unsigned nr_iovecs); -extern int io_uring_register_buffers_tags(struct io_uring *ring, - const struct iovec *iovecs, - const __u64 *tags, - unsigned nr); -extern int io_uring_register_buffers_update_tag(struct io_uring *ring, - unsigned off, - const struct iovec *iovecs, - const __u64 *tags, - unsigned nr); -extern int io_uring_unregister_buffers(struct io_uring *ring); - -extern int io_uring_register_files(struct io_uring *ring, const int *files, - unsigned nr_files); -extern int io_uring_register_files_tags(struct io_uring *ring, - const int *files, - const __u64 *tags, - unsigned nr); -extern int io_uring_register_files_update_tag(struct io_uring *ring, - unsigned off, - const int *files, - const __u64 *tags, - unsigned nr_files); - -extern int io_uring_unregister_files(struct io_uring *ring); -extern int io_uring_register_files_update(struct io_uring *ring, unsigned off, - int *files, unsigned nr_files); -extern int io_uring_register_eventfd(struct io_uring *ring, int fd); -extern int io_uring_register_eventfd_async(struct io_uring *ring, int fd); -extern int io_uring_unregister_eventfd(struct io_uring *ring); -extern int io_uring_register_probe(struct io_uring *ring, - struct io_uring_probe *p, unsigned nr); -extern int io_uring_register_personality(struct io_uring *ring); -extern int io_uring_unregister_personality(struct io_uring *ring, int id); -extern int io_uring_register_restrictions(struct io_uring *ring, - struct io_uring_restriction *res, - unsigned int nr_res); -extern int io_uring_enable_rings(struct io_uring *ring); -extern int __io_uring_sqring_wait(struct io_uring *ring); +int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, + unsigned wait_nr, struct __kernel_timespec *ts, + sigset_t *sigmask); +int io_uring_wait_cqe_timeout(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, + struct __kernel_timespec *ts); +int io_uring_submit(struct io_uring *ring); +int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr); +struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); + +int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, + unsigned nr_iovecs); +int io_uring_register_buffers_tags(struct io_uring *ring, + const struct iovec *iovecs, + const __u64 *tags, unsigned nr); +int io_uring_register_buffers_update_tag(struct io_uring *ring, + unsigned off, + const struct iovec *iovecs, + const __u64 *tags, unsigned nr); +int io_uring_unregister_buffers(struct io_uring *ring); + +int io_uring_register_files(struct io_uring *ring, const int *files, + unsigned nr_files); +int io_uring_register_files_tags(struct io_uring *ring, const int *files, + const __u64 *tags, unsigned nr); +int io_uring_register_files_update_tag(struct io_uring *ring, unsigned off, + const int *files, const __u64 *tags, + unsigned nr_files); + +int io_uring_unregister_files(struct io_uring *ring); +int io_uring_register_files_update(struct io_uring *ring, unsigned off, + int *files, unsigned nr_files); +int io_uring_register_eventfd(struct io_uring *ring, int fd); +int io_uring_register_eventfd_async(struct io_uring *ring, int fd); +int io_uring_unregister_eventfd(struct io_uring *ring); +int io_uring_register_probe(struct io_uring *ring, struct io_uring_probe *p, + unsigned nr); +int io_uring_register_personality(struct io_uring *ring); +int io_uring_unregister_personality(struct io_uring *ring, int id); +int io_uring_register_restrictions(struct io_uring *ring, + struct io_uring_restriction *res, + unsigned int nr_res); +int io_uring_enable_rings(struct io_uring *ring); +int __io_uring_sqring_wait(struct io_uring *ring); int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, const cpu_set_t *mask); int io_uring_unregister_iowq_aff(struct io_uring *ring); @@ -172,9 +166,9 @@ int io_uring_unregister_iowq_aff(struct io_uring *ring); * Helper for the peek/wait single cqe functions. Exported because of that, * but probably shouldn't be used directly in an application. */ -extern int __io_uring_get_cqe(struct io_uring *ring, - struct io_uring_cqe **cqe_ptr, unsigned submit, - unsigned wait_nr, sigset_t *sigmask); +int __io_uring_get_cqe(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, unsigned submit, + unsigned wait_nr, sigset_t *sigmask); #define LIBURING_UDATA_TIMEOUT ((__u64) -1) -- cgit v1.2.3 From 099d06e68acacdf380e14b6442ffd106ec913610 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 14:49:02 -0600 Subject: Add io_uring_register_iowq_max_unbound() helper Signed-off-by: Jens Axboe --- src/include/liburing.h | 2 ++ src/include/liburing/io_uring.h | 3 +++ src/liburing.map | 1 + src/register.c | 14 ++++++++++++++ 4 files changed, 20 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 00aea86..c8a7803 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -161,6 +161,8 @@ int __io_uring_sqring_wait(struct io_uring *ring); int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, const cpu_set_t *mask); int io_uring_unregister_iowq_aff(struct io_uring *ring); +int io_uring_unregister_iowq_max_unbound(struct io_uring *ring, + unsigned int value); /* * Helper for the peek/wait single cqe functions. Exported because of that, diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index efd6e65..ac0e42b 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -317,6 +317,9 @@ enum { IORING_REGISTER_IOWQ_AFF = 17, IORING_UNREGISTER_IOWQ_AFF = 18, + /* set/get max number of unbounded workers */ + IORING_REGISTER_IOWQ_MAX_UNBOUND = 19, + /* this goes last */ IORING_REGISTER_LAST }; diff --git a/src/liburing.map b/src/liburing.map index e493b72..2a01261 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -42,4 +42,5 @@ LIBURING_2.1 { io_uring_register_files_update_tag; io_uring_register_iowq_aff; io_uring_unregister_iowq_aff; + io_uring_register_iowq_max_unbound; } LIBURING_2.0; diff --git a/src/register.c b/src/register.c index bc8bd44..e78ffe6 100644 --- a/src/register.c +++ b/src/register.c @@ -283,3 +283,17 @@ int io_uring_unregister_iowq_aff(struct io_uring *ring) return ret; } + +int io_uring_register_iowq_max_unbound(struct io_uring *ring, unsigned int val) +{ + int ret; + + ret = __sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_IOWQ_MAX_UNBOUND, + &val, 1); + if (ret < 0) + return -errno; + + return ret; + +} -- cgit v1.2.3 From 1dbc9974486cbc5f60eeeca092fd434c40d3a484 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 15:04:21 -0600 Subject: man/io_uring_enter.2: document IORING_ENTER_EXT_ARG Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 482e866..9ccedef 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -55,6 +55,45 @@ application can no longer get a free SQE entry to submit, without knowing when it one becomes available as the SQ kernel thread consumes them. If the system call is used with this flag set, then it will wait until at least one entry is free in the SQ ring. +.TP +.B IORING_ENTER_EXT_ARG +Since kernel 5.11, the system calls arguments have been modified to look like +the following: + +.nf +.BI "int io_uring_enter(unsigned int " fd ", unsigned int " to_submit , +.BI " unsigned int " min_complete ", unsigned int " flags , +.BI " const void *" arg ", size_t " argsz ); +.fi + +which is behaves just like the original definition by default. However, if +.B IORING_ENTER_EXT_ARG +is set, then instead of a +.I sigset_t +being passed in, a pointer to a +.I struct io_uring_getevents_arg +is used instead and +.I argsz +must be set to the size of this structure. The definition is as follows: + +.nf +.BI "struct io_uring_getevents_args { +.BI " __u64 sigmask; +.BI " __u32 sigmask_sz; +.BI " __u32 pad; +.BI " __u64 ts; +.BI "}; +.fi + +which allows passing in both a signal mask as well as pointer to a +.I struct __kernel_timespec +timeout value. If +.I ts +is set to a valid pointer, then this time value indicates the timeout for +waiting on events. If an application is waiting on events and wishes to +stop waiting after a specified amount of time, then this can be accomplished +directly in version 5.11 and newer by using this feature. + .PP .PP If the io_uring instance was configured for polling, by specifying -- cgit v1.2.3 From fb1a8c1bb15ef73dee3b69b9e2ccfadb67a02e96 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 28 Aug 2021 15:06:52 -0600 Subject: src/syscall.h: get rid of useless externs Signed-off-by: Jens Axboe --- src/syscall.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/syscall.h b/src/syscall.h index 3b94efc..2368f83 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -9,12 +9,12 @@ struct io_uring_params; /* * System calls */ -extern int __sys_io_uring_setup(unsigned entries, struct io_uring_params *p); -extern int __sys_io_uring_enter(int fd, unsigned to_submit, - unsigned min_complete, unsigned flags, sigset_t *sig); -extern int __sys_io_uring_enter2(int fd, unsigned to_submit, - unsigned min_complete, unsigned flags, sigset_t *sig, int sz); -extern int __sys_io_uring_register(int fd, unsigned int opcode, const void *arg, - unsigned int nr_args); +int __sys_io_uring_setup(unsigned entries, struct io_uring_params *p); +int __sys_io_uring_enter(int fd, unsigned to_submit, unsigned min_complete, + unsigned flags, sigset_t *sig); +int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, + unsigned flags, sigset_t *sig, int sz); +int __sys_io_uring_register(int fd, unsigned int opcode, const void *arg, + unsigned int nr_args); #endif -- cgit v1.2.3 From 21916ba392108e791fdabd600fe6f1673e957244 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 29 Aug 2021 08:04:00 -0600 Subject: Change IORING_REGISTER_IOWQ_MAX_UNBOUND_WORKERS This syncs with the kernel, it's now IORING_REGISTER_IOWQ_MAX_WORKERS and can get/set the values for both bounded and unbounded workers. Signed-off-by: Jens Axboe --- man/io_uring_register.2 | 25 ++++++++++++++----------- src/include/liburing.h | 4 ++-- src/liburing.map | 2 +- src/register.c | 4 ++-- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index e9a5ca4..a17e411 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -320,23 +320,26 @@ set. Available since 5.14. .TP -.B IORING_REGISTER_IOWQ_MAX_UNBOUND +.B IORING_REGISTER_IOWQ_MAX_WORKERS By default, io_uring limits the unbounded workers created to the maximum processor count set by -.I RLIMIT_NPROC. -Sometimes this can be excessive, and this command provides a way to limit -the count per ring (per NUMA node) instead. +.I RLIMIT_NPROC +and the bounded workers is a function of the SQ ring size and the number +of CPUs in the system. Sometimes this can be excessive (or too little, for +bounded), and this command provides a way to change the count per ring (per NUMA +node) instead. + .I arg must be set to an .I unsigned int -pointer, with the value in the variable being set to the maximum count of -unbounded workers per NUMA node. If the count being passed in is 0, then -this command returns the current maximum values. If any other values is set, -this command returns either the old value, or -1 and -.I errno -set appropriately. +pointer to an array of two values, with the values in the array being set to +the maximum count of workers per NUMA node. Index 0 holds the bounded worker +count, and index 1 holds the unbounded worker count. On successful return, the +passed in array will contain the previous maximum valyes for each type. If the +count being passed in is 0, then this command returns the current maximum values +and doesn't modify the current setting. .I nr_args -must be set to 1, as the command only takes one argument. +must be set to 2, as the command takes two values. Available since 5.15. diff --git a/src/include/liburing.h b/src/include/liburing.h index c8a7803..16a7ac0 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -161,8 +161,8 @@ int __io_uring_sqring_wait(struct io_uring *ring); int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, const cpu_set_t *mask); int io_uring_unregister_iowq_aff(struct io_uring *ring); -int io_uring_unregister_iowq_max_unbound(struct io_uring *ring, - unsigned int value); +int io_uring_unregister_iowq_max_workers(struct io_uring *ring, + unsigned int *values); /* * Helper for the peek/wait single cqe functions. Exported because of that, diff --git a/src/liburing.map b/src/liburing.map index 2a01261..6692a3b 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -42,5 +42,5 @@ LIBURING_2.1 { io_uring_register_files_update_tag; io_uring_register_iowq_aff; io_uring_unregister_iowq_aff; - io_uring_register_iowq_max_unbound; + io_uring_register_iowq_max_workers; } LIBURING_2.0; diff --git a/src/register.c b/src/register.c index e78ffe6..09e0bba 100644 --- a/src/register.c +++ b/src/register.c @@ -284,13 +284,13 @@ int io_uring_unregister_iowq_aff(struct io_uring *ring) return ret; } -int io_uring_register_iowq_max_unbound(struct io_uring *ring, unsigned int val) +int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *val) { int ret; ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_IOWQ_MAX_UNBOUND, - &val, 1); + val, 2); if (ret < 0) return -errno; -- cgit v1.2.3 From 1f4d3a15d7d92c7d28bdc92c7b7da0c5ecd4c964 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 30 Aug 2021 14:34:59 -0600 Subject: liburing.h: correct max_worker name Fixes: 21916ba39210 ("Change IORING_REGISTER_IOWQ_MAX_UNBOUND_WORKERS") Signed-off-by: Jens Axboe --- src/include/liburing.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 16a7ac0..9ff7179 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -161,8 +161,8 @@ int __io_uring_sqring_wait(struct io_uring *ring); int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, const cpu_set_t *mask); int io_uring_unregister_iowq_aff(struct io_uring *ring); -int io_uring_unregister_iowq_max_workers(struct io_uring *ring, - unsigned int *values); +int io_uring_register_iowq_max_workers(struct io_uring *ring, + unsigned int *values); /* * Helper for the peek/wait single cqe functions. Exported because of that, -- cgit v1.2.3 From 3e81df1d27ab01e1dc911a9160b2be3befd4e7d1 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 31 Aug 2021 17:30:12 +0100 Subject: liburing: add helpers for direct open/accept We allow openat/openat2/accept to place new files right into the internal fixed table, add helpers. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/1508fe7ab545d52d1849daceb07e8a349ebfa08d.1630427247.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 9ff7179..38dbbfe 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -231,6 +231,13 @@ static inline void io_uring_sqe_set_flags(struct io_uring_sqe *sqe, sqe->flags = (__u8) flags; } +static inline void __io_uring_set_target_fixed_file(struct io_uring_sqe *sqe, + unsigned int file_index) +{ + /* 0 means no fixed files, indexes should be encoded as "index + 1" */ + sqe->file_index = file_index + 1; +} + static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd, const void *addr, unsigned len, __u64 offset) @@ -422,6 +429,16 @@ static inline void io_uring_prep_accept(struct io_uring_sqe *sqe, int fd, sqe->accept_flags = (__u32) flags; } +/* accept directly into the fixed file table */ +static inline void io_uring_prep_accept_direct(struct io_uring_sqe *sqe, int fd, + struct sockaddr *addr, + socklen_t *addrlen, int flags, + unsigned int file_index) +{ + io_uring_prep_accept(sqe, fd, addr, addrlen, flags); + __io_uring_set_target_fixed_file(sqe, file_index); +} + static inline void io_uring_prep_cancel(struct io_uring_sqe *sqe, void *user_data, int flags) { @@ -468,6 +485,17 @@ static inline void io_uring_prep_openat(struct io_uring_sqe *sqe, int dfd, sqe->open_flags = (__u32) flags; } +/* open directly into the fixed file table */ +static inline void io_uring_prep_openat_direct(struct io_uring_sqe *sqe, + int dfd, const char *path, + int flags, mode_t mode, + unsigned file_index) +{ + io_uring_prep_openat(sqe, dfd, path, flags, mode); + __io_uring_set_target_fixed_file(sqe, file_index); +} + + static inline void io_uring_prep_close(struct io_uring_sqe *sqe, int fd) { io_uring_prep_rw(IORING_OP_CLOSE, sqe, fd, NULL, 0, 0); @@ -530,6 +558,16 @@ static inline void io_uring_prep_openat2(struct io_uring_sqe *sqe, int dfd, (uint64_t) (uintptr_t) how); } +/* open directly into the fixed file table */ +static inline void io_uring_prep_openat2_direct(struct io_uring_sqe *sqe, + int dfd, const char *path, + struct open_how *how, + unsigned file_index) +{ + io_uring_prep_openat2(sqe, dfd, path, how); + __io_uring_set_target_fixed_file(sqe, file_index); +} + struct epoll_event; static inline void io_uring_prep_epoll_ctl(struct io_uring_sqe *sqe, int epfd, int fd, int op, -- cgit v1.2.3 From c63e4f2fc7b393b0f3e52ce975eef0b229223383 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 31 Aug 2021 17:30:13 +0100 Subject: tests: use helpers for direct open/accept For the test to be less confusing, use helpers in tests that place new files right into the fixed file table. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/d720255e0861688541efb812318f9423ee01e2a3.1630427247.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/accept.c | 7 ++++--- test/openat2.c | 27 +++++++++++++++------------ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/test/accept.c b/test/accept.c index 21db14f..0c69b98 100644 --- a/test/accept.c +++ b/test/accept.c @@ -65,9 +65,10 @@ static int accept_conn(struct io_uring *ring, int fd, bool fixed) int ret, fixed_idx = 0; sqe = io_uring_get_sqe(ring); - io_uring_prep_accept(sqe, fd, NULL, NULL, 0); - if (fixed) - sqe->file_index = fixed_idx + 1; + if (!fixed) + io_uring_prep_accept(sqe, fd, NULL, NULL, 0); + else + io_uring_prep_accept_direct(sqe, fd, NULL, NULL, 0, fixed_idx); ret = io_uring_submit(ring); assert(ret != -1); diff --git a/test/openat2.c b/test/openat2.c index afc30a0..7838c05 100644 --- a/test/openat2.c +++ b/test/openat2.c @@ -14,7 +14,7 @@ #include "liburing.h" static int test_openat2(struct io_uring *ring, const char *path, int dfd, - int fixed_slot) + bool direct, int fixed_index) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -28,8 +28,11 @@ static int test_openat2(struct io_uring *ring, const char *path, int dfd, } memset(&how, 0, sizeof(how)); how.flags = O_RDWR; - io_uring_prep_openat2(sqe, dfd, path, &how); - sqe->file_index = fixed_slot; + + if (!direct) + io_uring_prep_openat2(sqe, dfd, path, &how); + else + io_uring_prep_openat2_direct(sqe, dfd, path, &how, fixed_index); ret = io_uring_submit(ring); if (ret <= 0) { @@ -45,7 +48,7 @@ static int test_openat2(struct io_uring *ring, const char *path, int dfd, ret = cqe->res; io_uring_cqe_seen(ring, cqe); - if (fixed_slot && ret > 0) { + if (direct && ret > 0) { close(ret); return -EINVAL; } @@ -72,7 +75,7 @@ static int test_open_fixed(const char *path, int dfd) return -1; } - ret = test_openat2(&ring, path, dfd, 1); + ret = test_openat2(&ring, path, dfd, true, 0); if (ret == -EINVAL) { printf("fixed open isn't supported\n"); return 1; @@ -114,7 +117,7 @@ static int test_open_fixed(const char *path, int dfd) return -1; } - ret = test_openat2(&ring, path, dfd, 1); + ret = test_openat2(&ring, path, dfd, true, 0); if (ret != -EBADF) { fprintf(stderr, "bogus double register %d\n", ret); return -1; @@ -134,7 +137,7 @@ static int test_open_fixed_fail(const char *path, int dfd) return -1; } - ret = test_openat2(&ring, path, dfd, 1); + ret = test_openat2(&ring, path, dfd, true, 0); if (ret != -ENXIO) { fprintf(stderr, "install into not existing table, %i\n", ret); return 1; @@ -146,19 +149,19 @@ static int test_open_fixed_fail(const char *path, int dfd) return -1; } - ret = test_openat2(&ring, path, dfd, 2); + ret = test_openat2(&ring, path, dfd, true, 1); if (ret != -EINVAL) { fprintf(stderr, "install out of bounds, %i\n", ret); return 1; } - ret = test_openat2(&ring, path, dfd, (1u << 16)); + ret = test_openat2(&ring, path, dfd, true, (1u << 16)); if (ret != -EINVAL) { fprintf(stderr, "install out of bounds or u16 overflow, %i\n", ret); return 1; } - ret = test_openat2(&ring, path, dfd, (1u << 16) + 1); + ret = test_openat2(&ring, path, dfd, true, (1u << 16) + 1); if (ret != -EINVAL) { fprintf(stderr, "install out of bounds or u16 overflow, %i\n", ret); return 1; @@ -196,7 +199,7 @@ int main(int argc, char *argv[]) if (do_unlink) t_create_file(path_rel, 4096); - ret = test_openat2(&ring, path, -1, 0); + ret = test_openat2(&ring, path, -1, false, 0); if (ret < 0) { if (ret == -EINVAL) { fprintf(stdout, "openat2 not supported, skipping\n"); @@ -206,7 +209,7 @@ int main(int argc, char *argv[]) goto err; } - ret = test_openat2(&ring, path_rel, AT_FDCWD, 0); + ret = test_openat2(&ring, path_rel, AT_FDCWD, false, 0); if (ret < 0) { fprintf(stderr, "test_openat2 relative failed: %d\n", ret); goto err; -- cgit v1.2.3 From f8bcd0341591d61439e53d8d24e7e6012fe9f280 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 31 Aug 2021 16:49:46 +0100 Subject: tests: test early-submit link fails Add a whole bunch of tests for when linked requests fail early during submission. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/3e02f382b64e7d09c8226ee02be130e4b75d890e.1630424932.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 2 + test/submit-link-fail.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 test/submit-link-fail.c diff --git a/.gitignore b/.gitignore index 3d67ef9..df0f740 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,7 @@ /test/rw_merge_test /test/sqpoll-cancel-hang /test/testfile +/test/submit-link-fail /test/*.dmesg config-host.h diff --git a/test/Makefile b/test/Makefile index 46af135..1e27a54 100644 --- a/test/Makefile +++ b/test/Makefile @@ -123,6 +123,7 @@ test_targets += \ sq-space_left \ stdout \ submit-reuse \ + submit-link-fail \ symlink \ teardowns \ thread-exit \ @@ -263,6 +264,7 @@ test_srcs := \ statx.c \ stdout.c \ submit-reuse.c \ + submit-link-fail.c \ symlink.c \ teardowns.c \ thread-exit.c \ diff --git a/test/submit-link-fail.c b/test/submit-link-fail.c new file mode 100644 index 0000000..b79aa7c --- /dev/null +++ b/test/submit-link-fail.c @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: tests linked requests failing during submission + */ +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" + +#define DRAIN_USER_DATA 42 + +static int test_underprep_fail(bool hardlink, bool drain, bool link_last, + int link_size, int fail_idx) +{ + const int invalid_fd = 42; + int link_flags = IOSQE_IO_LINK; + int total_submit = link_size; + struct io_uring ring; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + char buffer[1]; + int i, ret, fds[2]; + + if (drain) + link_flags |= IOSQE_IO_DRAIN; + if (hardlink) + link_flags |= IOSQE_IO_HARDLINK; + + assert(fail_idx < link_size); + assert(link_size < 40); + + /* create a new ring as it leaves it dirty */ + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + printf("ring setup failed\n"); + return -1; + } + if (pipe(fds)) { + perror("pipe"); + return -1; + } + + if (drain) { + /* clog drain, so following reqs sent to draining */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_read(sqe, fds[0], buffer, sizeof(buffer), 0); + sqe->user_data = DRAIN_USER_DATA; + sqe->flags |= IOSQE_IO_DRAIN; + total_submit++; + } + + for (i = 0; i < link_size; i++) { + sqe = io_uring_get_sqe(&ring); + if (i == fail_idx) + io_uring_prep_read(sqe, invalid_fd, buffer, 1, 0); + else + io_uring_prep_nop(sqe); + + if (i != link_size - 1 || !link_last) + sqe->flags |= link_flags; + sqe->user_data = i; + } + + ret = io_uring_submit(&ring); + if (ret != total_submit) { + /* Old behaviour, failed early and under-submitted */ + if (ret == fail_idx + 1 + drain) + goto out; + fprintf(stderr, "submit failed: %d\n", ret); + return -1; + } + + if (drain) { + /* unclog drain */ + write(fds[1], buffer, sizeof(buffer)); + } + + for (i = 0; i < total_submit; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe=%d\n", ret); + return 1; + } + + ret = cqe->res; + if (cqe->user_data == DRAIN_USER_DATA) { + if (ret != 1) { + fprintf(stderr, "drain failed %d\n", ret); + return 1; + } + } else if (cqe->user_data == fail_idx) { + if (ret == 0 || ret == -ECANCELED) { + fprintf(stderr, "half-prep req unexpected return %d\n", ret); + return 1; + } + } else { + if (ret != -ECANCELED) { + fprintf(stderr, "cancel failed %d, ud %d\n", ret, (int)cqe->user_data); + return 1; + } + } + io_uring_cqe_seen(&ring, cqe); + } +out: + close(fds[0]); + close(fds[1]); + io_uring_queue_exit(&ring); + return 0; +} + +int main(int argc, char *argv[]) +{ + int ret, link_size, fail_idx, i; + + if (argc > 1) + return 0; + + /* + * hardlink, size=3, fail_idx=1, drain=false -- kernel fault + * link, size=3, fail_idx=0, drain=true -- kernel fault + * link, size=3, fail_idx=1, drain=true -- invalid cqe->res + */ + for (link_size = 0; link_size < 3; link_size++) { + for (fail_idx = 0; fail_idx < link_size; fail_idx++) { + for (i = 0; i < 8; i++) { + bool hardlink = (i & 1) != 0; + bool drain = (i & 2) != 0; + bool link_last = (i & 4) != 0; + + ret = test_underprep_fail(hardlink, drain, link_last, + link_size, fail_idx); + if (!ret) + continue; + + fprintf(stderr, "failed %d, hard %d, drain %d," + "link_last %d, size %d, idx %d\n", + ret, hardlink, drain, link_last, + link_size, fail_idx); + return 1; + } + } + } + + return 0; +} -- cgit v1.2.3 From 1dba431f22523e7337c7e3b6d9b4a20518d74cf0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 31 Aug 2021 11:02:27 -0600 Subject: test/submit-link-fail: fix unchecked write(2) return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit submit-link-fail.c: In function ‘test_underprep_fail’: submit-link-fail.c:80:17: warning: ignoring return value of ‘write’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 80 | write(fds[1], buffer, sizeof(buffer)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Jens Axboe --- test/submit-link-fail.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/submit-link-fail.c b/test/submit-link-fail.c index b79aa7c..a12bdae 100644 --- a/test/submit-link-fail.c +++ b/test/submit-link-fail.c @@ -77,7 +77,11 @@ static int test_underprep_fail(bool hardlink, bool drain, bool link_last, if (drain) { /* unclog drain */ - write(fds[1], buffer, sizeof(buffer)); + ret = write(fds[1], buffer, sizeof(buffer)); + if (ret < 0) { + perror("write"); + return 1; + } } for (i = 0; i < total_submit; i++) { -- cgit v1.2.3 From a467e0940f6dd1476247a5673d6f47b4a75bac92 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 31 Aug 2021 20:05:19 +0100 Subject: man: document new register/update API Document - IORING_REGISTER_FILES2 - IORING_REGISTER_FILES_UPDATE2, - IORING_REGISTER_BUFFERS2 - IORING_REGISTER_BUFFERS_UPDATE, And add a couple of words on registered resources (buffers, files) tagging. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/f456c80bb8795eb7b8c3db8279206d94ce148587.1630436406.git.asml.silence@gmail.com [axboe: minor edits] Signed-off-by: Jens Axboe --- man/io_uring_register.2 | 151 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 1 deletion(-) diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index a17e411..9618f15 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -95,6 +95,99 @@ wait for those to finish before proceeding. An application need not unregister buffers explicitly before shutting down the io_uring instance. Available since 5.1. +.TP +.B IORING_REGISTER_BUFFERS2 +Register buffers for I/O. Similar to +.B IORING_REGISTER_BUFFERS +but aims to have a more extensible ABI. + +.I arg +points to a +.I struct io_uring_rsrc_register, +and +.I nr_args +should be set to the number of bytes in the structure. + +.PP +.in +8n +.EX +struct io_uring_rsrc_register { + __u32 nr; + __u32 resv; + __u64 resv2; + __aligned_u64 data; + __aligned_u64 tags; +}; + +.EE +.in +.PP + +.in +8n + +The +.I data +field contains a pointer to a +.I struct iovec +array of +.I nr +entries. +The +.I tags +field should either be 0, then tagging is disabled, or point to an array +of +.I nr +"tags" (unsigned 64 bit integers). If a tag is zero, then tagging for this +particular resource (a buffer in this case) is disabled. Otherwise, after the +resource had been unregistered and it's not used anymore, a CQE will be +posted with +.I user_data +set to the specified tag and all other fields zeroed. + +Note that resource updates, e.g. +.B IORING_REGISTER_BUFFERS_UPDATE, +don't necessarily deallocate resources by the time it returns, but they might +be held alive until all requests using it complete. + +Available since 5.13. + +.TP +.B IORING_REGISTER_BUFFERS_UPDATE +Updates registered buffers with new ones, either turning a sparse entry into +a real one, or replacing an existing entry. + +.I arg +must contain a pointer to a struct io_uring_rsrc_update2, which contains +an offset on which to start the update, and an array of +.I struct iovec. +.I tags +points to an array of tags. +.I nr +must contain the number of descriptors in the passed in arrays. +See +.B IORING_REGISTER_BUFFERS2 +for the resource tagging description. + +.PP +.in +8n +.EX + +struct io_uring_rsrc_update2 { + __u32 offset; + __u32 resv; + __aligned_u64 data; + __aligned_u64 tags; + __u32 nr; + __u32 resv2; +}; +.EE +.in +.PP + +.in +8n + +Available since 5.13. + .TP .B IORING_UNREGISTER_BUFFERS This operation takes no argument, and @@ -138,6 +231,37 @@ Files are automatically unregistered when the io_uring instance is torn down. An application need only unregister if it wishes to register a new set of fds. Available since 5.1. +.TP +.B IORING_REGISTER_FILES2 +Register files for I/O. Similar to +.B IORING_REGISTER_FILES. + +.I arg +points to a +.I struct io_uring_rsrc_register, +and +.I nr_args +should be set to the number of bytes in the structure. + +The +.I data +field contains a pointer to an array of +.I nr +file descriptors (signed 32 bit integers). +.I tags +field should either be 0 or or point to an array of +.I nr +"tags" (unsigned 64 bit integers). See +.B IORING_REGISTER_BUFFERS2 +for more info on resource tagging. + +Note that resource updates, e.g. +.B IORING_REGISTER_FILES_UPDATE, +don't necessarily deallocate resources, they might be held until all requests +using that resource complete. + +Available since 5.13. + .TP .B IORING_REGISTER_FILES_UPDATE This operation replaces existing files in the registered file set with new @@ -146,7 +270,9 @@ real one, removing an existing entry (new one is set to -1), or replacing an existing entry with a new existing entry. .I arg -must contain a pointer to a struct io_uring_files_update, which contains +must contain a pointer to a +.I struct io_uring_files_update, +which contains an offset on which to start the update, and an array of file descriptors to use for the update. .I nr_args @@ -158,6 +284,29 @@ File descriptors can be skipped if they are set to Skipping an fd will not touch the file associated with the previous fd at that index. Available since 5.12. +.TP +.B IORING_REGISTER_FILES_UPDATE2 +Similar to IORING_REGISTER_FILES_UPDATE, replaces existing files in the +registered file set with new ones, either turning a sparse entry (one where +fd is equal to -1) into a real one, removing an existing entry (new one is +set to -1), or replacing an existing entry with a new existing entry. + +.I arg +must contain a pointer to a +.I struct io_uring_rsrc_update2, +which contains +an offset on which to start the update, and an array of file descriptors to +use for the update stored in +.I data. +.I tags +points to an array of tags. +.I nr +must contain the number of descriptors in the passed in arrays. +See +.B IORING_REGISTER_BUFFERS2 +for the resource tagging description. + +Available since 5.13. .TP .B IORING_UNREGISTER_FILES -- cgit v1.2.3 From 168d5a4e6654f68ad0f2c867a771749701341be9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 31 Aug 2021 14:13:15 -0600 Subject: Fix IORING_REGISTER_IOWQ_MAX_WORKERS name A previous commit did sync with the kernel in terms of the API, but we neglected to change the actual enum as well. Fixes: 21916ba39210 ("Change IORING_REGISTER_IOWQ_MAX_UNBOUND_WORKERS") Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 4 ++-- src/register.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index ac0e42b..dfbbf02 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -317,8 +317,8 @@ enum { IORING_REGISTER_IOWQ_AFF = 17, IORING_UNREGISTER_IOWQ_AFF = 18, - /* set/get max number of unbounded workers */ - IORING_REGISTER_IOWQ_MAX_UNBOUND = 19, + /* set/get max number of async workers */ + IORING_REGISTER_IOWQ_MAX_WORKERS = 19, /* this goes last */ IORING_REGISTER_LAST diff --git a/src/register.c b/src/register.c index 09e0bba..a4e8c37 100644 --- a/src/register.c +++ b/src/register.c @@ -289,7 +289,7 @@ int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *val) int ret; ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_IOWQ_MAX_UNBOUND, + IORING_REGISTER_IOWQ_MAX_WORKERS, val, 2); if (ret < 0) return -errno; -- cgit v1.2.3 From 5497c50a392f22ac6c323415cb2c8ff7874cc7b8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 31 Aug 2021 14:16:11 -0600 Subject: io_uring.h: sync with 5.15 kernel Just the timeout flags are missing at this point. Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index dfbbf02..69f23a9 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -157,9 +157,13 @@ enum { /* * sqe->timeout_flags */ -#define IORING_TIMEOUT_ABS (1U << 0) -#define IORING_TIMEOUT_UPDATE (1U << 1) - +#define IORING_TIMEOUT_ABS (1U << 0) +#define IORING_TIMEOUT_UPDATE (1U << 1) +#define IORING_TIMEOUT_BOOTTIME (1U << 2) +#define IORING_TIMEOUT_REALTIME (1U << 3) +#define IORING_LINK_TIMEOUT_UPDATE (1U << 4) +#define IORING_TIMEOUT_CLOCK_MASK (IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME) +#define IORING_TIMEOUT_UPDATE_MASK (IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE) /* * sqe->splice_flags * extends splice(2) flags -- cgit v1.2.3 From bb75e12e9bb628b62c13149478035b37acd518b5 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 31 Aug 2021 21:54:25 +0100 Subject: man/io_uring_enter.2: add notes about direct open/accept Add a few lines describing openat/openat2/accept bypassing normal file tables and installing files right into the fixed file table. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/cf33283b0f2e795ac7f9b6e2eabc70a4f71863c0.1630443189.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 9ccedef..e1ae707 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -511,6 +511,22 @@ field. See also .BR accept4(2) for the general description of the related system call. Available since 5.5. +If the +.I file_index +field is set to a positive number, the file won't be installed into the +normal file table as usual but will be placed into the fixed file table at index +.I file_index - 1. +In this case, instead of returning a file descriptor, the result will contain +either 0 on success or an error. If there is already a file registered at this +index, the request will fail with +.B -EBADF. +Only io_uring has access to such files and no other syscall can use them. See +.B IOSQE_FIXED_FILE +and +.B IORING_REGISTER_FILES. + +Available since 5.15. + .TP .B IORING_OP_ASYNC_CANCEL Attempt to cancel an already issued request. @@ -634,6 +650,22 @@ is access mode of the file. See also .BR openat(2) for the general description of the related system call. Available since 5.6. +If the +.I file_index +field is set to a positive number, the file won't be installed into the +normal file table as usual but will be placed into the fixed file table at index +.I file_index - 1. +In this case, instead of returning a file descriptor, the result will contain +either 0 on success or an error. If there is already a file registered at this +index, the request will fail with +.B -EBADF. +Only io_uring has access to such files and no other syscall can use them. See +.B IOSQE_FIXED_FILE +and +.B IORING_REGISTER_FILES. + +Available since 5.15. + .TP .B IORING_OP_OPENAT2 Issue the equivalent of a @@ -654,6 +686,22 @@ should be set to the address of the open_how structure. See also .BR openat2(2) for the general description of the related system call. Available since 5.6. +If the +.I file_index +field is set to a positive number, the file won't be installed into the +normal file table as usual but will be placed into the fixed file table at index +.I file_index - 1. +In this case, instead of returning a file descriptor, the result will contain +either 0 on success or an error. If there is already a file registered at this +index, the request will fail with +.B -EBADF. +Only io_uring has access to such files and no other syscall can use them. See +.B IOSQE_FIXED_FILE +and +.B IORING_REGISTER_FILES. + +Available since 5.15. + .TP .B IORING_OP_CLOSE Issue the equivalent of a -- cgit v1.2.3 From 4c5987928e8df326e682c85e7deff557c0d0eebd Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Wed, 1 Sep 2021 09:16:12 +0700 Subject: man: clean up spelling Signed-off-by: Ammar Faizi --- man/io_uring.7 | 4 ++-- man/io_uring_enter.2 | 4 ++-- man/io_uring_register.2 | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/man/io_uring.7 b/man/io_uring.7 index a63b3e9..972683b 100644 --- a/man/io_uring.7 +++ b/man/io_uring.7 @@ -425,7 +425,7 @@ successful read and update of the head. Because of the shared ring buffers between kernel and user space, .B io_uring can be a zero-copy system. -Copying buffers to and fro becomes necessary when system calls that +Copying buffers to and from becomes necessary when system calls that transfer data between kernel and user space are involved. But since the bulk of the communication in .B io_uring @@ -435,7 +435,7 @@ this huge performance overhead is completely avoided. While system calls may not seem like a significant overhead, in high performance applications, making a lot of them will begin to matter. -While workarounds the operating system has in place to deal with Specter +While workarounds the operating system has in place to deal with Spectre and Meltdown are ideally best done away with, unfortunately, some of these workarounds are around the system call interface, diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index e1ae707..ad86961 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -1061,7 +1061,7 @@ Used in conjunction with the command, which registers a pool of buffers to be used by commands that read or receive data. When buffers are registered for this use case, and this flag is set in the command, io_uring will grab a buffer from this pool when -the request is ready to receive or read data. If succesful, the resulting CQE +the request is ready to receive or read data. If successful, the resulting CQE will have .B IORING_CQE_F_BUFFER set in the flags part of the struct, and the upper @@ -1189,7 +1189,7 @@ res holding the equivalent of .I -errno for error cases, or the transferred number of bytes in case the operation -is succesful. Hence both error and success return can be found in that +is successful. Hence both error and success return can be found in that field in the CQE. For other request types, the return values are documented in the matching man page for that type, or in the opcodes section above for io_uring-specific opcodes. diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index 9618f15..887567f 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -228,7 +228,7 @@ wait for those to finish before proceeding. See for how to update an existing set without that limitation. Files are automatically unregistered when the io_uring instance is -torn down. An application need only unregister if it wishes to +torn down. An application needs only unregister if it wishes to register a new set of fds. Available since 5.1. .TP -- cgit v1.2.3 From 43b7ec8d17888df0debccda27dd58f4d1b90245e Mon Sep 17 00:00:00 2001 From: Uman Shahzad Date: Thu, 2 Sep 2021 01:56:09 +0500 Subject: build: add -D_GNU_SOURCE to all CPPFLAGS/CFLAGS. Needed for e.g. musl libc which only includes entities like cpu_set_t if this is defined. Signed-off-by: Uman Shahzad --- examples/Makefile | 2 +- src/Makefile | 6 ++++-- test/Makefile | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 60c1b71..a5d0b93 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -2,7 +2,7 @@ CPPFLAGS ?= override CPPFLAGS += -D_GNU_SOURCE -I../src/include/ CFLAGS ?= -g -O2 XCFLAGS = -override CFLAGS += -Wall -L../src/ +override CFLAGS += -D_GNU_SOURCE -Wall -L../src/ include ../Makefile.quiet diff --git a/src/Makefile b/src/Makefile index dfca826..68efbdc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,9 +4,11 @@ libdir ?= $(prefix)/lib libdevdir ?= $(prefix)/lib CPPFLAGS ?= -override CPPFLAGS += -Iinclude/ -include ../config-host.h +override CPPFLAGS += -D_GNU_SOURCE \ + -Iinclude/ -include ../config-host.h CFLAGS ?= -g -fomit-frame-pointer -O2 -override CFLAGS += -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare +override CFLAGS += -D_GNU_SOURCE \ + -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare SO_CFLAGS=-fPIC $(CFLAGS) L_CFLAGS=$(CFLAGS) LINK_FLAGS= diff --git a/test/Makefile b/test/Makefile index 1e27a54..c631d64 100644 --- a/test/Makefile +++ b/test/Makefile @@ -12,7 +12,8 @@ override CPPFLAGS += -D_GNU_SOURCE -D__SANE_USERSPACE_TYPES__ \ -I../src/include/ -include ../config-host.h CFLAGS ?= -g -O2 XCFLAGS = -override CFLAGS += -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare \ +override CFLAGS += -D_GNU_SOURCE \ + -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare \ -L../src/ ifdef CONFIG_HAVE_STRINGOP_OVERFLOW -- cgit v1.2.3 From 187a39d3e6182b467299637ad20e15a7e6b5548c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 2 Sep 2021 09:44:19 -0600 Subject: test/runtests.sh: remove old manager/worker checks They can't happen with later kernels anyway, and it's been 2 releases since they went away. Signed-off-by: Jens Axboe --- test/runtests.sh | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/test/runtests.sh b/test/runtests.sh index 26371ec..8d4ce11 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -7,7 +7,6 @@ DMESG_FILTER="cat" TEST_DIR=$(dirname $0) FAILED="" SKIPPED="" -MAYBE_FAILED="" TIMED_OUT="" TEST_FILES="" declare -A TEST_MAP @@ -107,12 +106,6 @@ run_test() echo "Test $test_name failed dmesg check" FAILED="$FAILED <$test_string>" RET=1 - elif [ -n "$dev" ]; then - sleep .1 - ps aux | grep "\[io_wq_manager\]" > /dev/null - if [ $? -eq 0 ]; then - MAYBE_FAILED="$MAYBE_FAILED $test_string" - fi fi } @@ -138,14 +131,6 @@ if [ "${RET}" -ne 0 ]; then echo "Tests failed: $FAILED" exit $RET else - sleep 1 - ps aux | grep "\[io_wq_manager\]" > /dev/null - if [ $? -ne 0 ]; then - MAYBE_FAILED="" - fi - if [ ! -z "$MAYBE_FAILED" ]; then - echo "Tests _maybe_ failed: $MAYBE_FAILED" - fi if [ ! -z "$TIMED_OUT" ]; then echo "Tests timed out: $TIMED_OUT" fi -- cgit v1.2.3 From 1b11c071c576e823646c030edfbf1b66e1b5c604 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 3 Sep 2021 09:15:31 -0600 Subject: test: add basic time measurement Will show the runtime of the test, as well as the previous runtime if available: Running test iopoll /dev/nvme0n1p2: 13 sec [14] Running test iopoll /dev/nvme1n1p1: 14 sec [13] Not perfect yet, and alignment isn't that pretty either. But it's very useful to see if there are differences between two runs, if you run with a new kernel that has changes. We can always pretty it up later. Signed-off-by: Jens Axboe --- test/Makefile | 3 ++- test/runtests.sh | 26 ++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/test/Makefile b/test/Makefile index c631d64..2313fcc 100644 --- a/test/Makefile +++ b/test/Makefile @@ -303,7 +303,8 @@ install: $(test_targets) runtests.sh runtests-loop.sh $(INSTALL) -D -m 755 runtests.sh $(datadir)/liburing-test/ $(INSTALL) -D -m 755 runtests-loop.sh $(datadir)/liburing-test/ clean: - @rm -f $(all_targets) $(test_objs) helpers.o + @rm -f $(all_targets) $(test_objs) helpers.o output/* + @rm -rf output/ runtests: all @./runtests.sh $(test_targets) diff --git a/test/runtests.sh b/test/runtests.sh index 8d4ce11..a8a77ae 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -67,19 +67,23 @@ run_test() local test_name="$1" local dev="$2" local test_string=$test_name + local out_name=$test_name # Specify test string to print if [ -n "$dev" ]; then test_string="$test_name $dev" + local suffix=$(basename $dev) + out_name="$out_name.$suffix" fi # Log start of the test if [ "$DO_KMSG" -eq 1 ]; then local dmesg_marker="Running test $test_string:" - echo $dmesg_marker | tee /dev/kmsg + echo $dmesg_marker > /dev/kmsg + echo -n $dmesg_marker else local dmesg_marker="" - echo Running test $test_name $dev + echo -n Running test $test_name $dev fi # Do we have to exclude the test ? @@ -91,7 +95,9 @@ run_test() fi # Run the test + T_START=$(date +%s) timeout -s INT -k $TIMEOUT $TIMEOUT ./$test_name $dev + T_END=$(date +%s) local status=$? # Check test status @@ -106,11 +112,27 @@ run_test() echo "Test $test_name failed dmesg check" FAILED="$FAILED <$test_string>" RET=1 + else + if [ -f "output/$out_name" ]; then + T_PREV=$(cat output/$out_name) + else + T_PREV="" + fi + T_DIFF=$(($T_END-$T_START)) + if [ ! -z $T_PREV ]; then + echo -e "\t\t\t $T_DIFF sec [$T_PREV]" + else + echo -e "\t\t\t $T_DIFF sec" + fi + echo $T_DIFF > "output/$out_name" fi } # Run all specified tests for tst in $TESTS; do + if [ ! -d output ]; then + mkdir output + fi if [ ! -n "${TEST_MAP[$tst]}" ]; then run_test $tst if [ ! -z "$TEST_FILES" ]; then -- cgit v1.2.3 From 47096ad620925a5cefe2a92c1615ca9c2383cbcc Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Sun, 29 Aug 2021 00:08:33 +0200 Subject: test: Fix build failure with gcc -O0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function needs to be «static inline», otherwise an extern definition is expected to be present too. This shows when building with no optimization, which is rather helpful when debugging core dumps. Signed-off-by: Guillem Jover --- test/multicqes_drain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/multicqes_drain.c b/test/multicqes_drain.c index 609d583..d04cf37 100644 --- a/test/multicqes_drain.c +++ b/test/multicqes_drain.c @@ -157,7 +157,7 @@ int generate_opcode(int i, int pre_flags) return sqe_op; } -inline void add_multishot_sqe(int index) +static inline void add_multishot_sqe(int index) { multi_sqes[cnt++] = index; } -- cgit v1.2.3 From 32534655131b2d51cace2c84c6b35736ba9c4bb4 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Sun, 29 Aug 2021 00:09:39 +0200 Subject: test: Namespace core files with the test name When multiple tests core dump, this makes it possible to check each of them instead of having to run them individually. Signed-off-by: Guillem Jover --- test/runtests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/runtests.sh b/test/runtests.sh index a8a77ae..6742a56 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -100,6 +100,10 @@ run_test() T_END=$(date +%s) local status=$? + if [ -e ./core ]; then + mv core core-$test_name + fi + # Check test status if [ "$status" -eq 124 ]; then echo "Test $test_name timed out (may not be a failure)" -- cgit v1.2.3 From 6c529eab130e58b11f256eb1963bf00ce83d49e8 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 00:31:14 +0200 Subject: test: Fix runner output to avoid concatenated strings If the test prints messages, those would get concatenated to the test runner progress message. Instead format the text columnized in preparation for the next output whether it is coming from the test itself or the subsequent test runner result prints. Signed-off-by: Guillem Jover --- test/runtests.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/runtests.sh b/test/runtests.sh index 6742a56..40083f0 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -80,11 +80,10 @@ run_test() if [ "$DO_KMSG" -eq 1 ]; then local dmesg_marker="Running test $test_string:" echo $dmesg_marker > /dev/kmsg - echo -n $dmesg_marker else local dmesg_marker="" - echo -n Running test $test_name $dev fi + printf "Running test %-25s" "$test_string" # Do we have to exclude the test ? echo $TEST_EXCLUDE | grep -w "$test_name" > /dev/null 2>&1 @@ -124,9 +123,9 @@ run_test() fi T_DIFF=$(($T_END-$T_START)) if [ ! -z $T_PREV ]; then - echo -e "\t\t\t $T_DIFF sec [$T_PREV]" + echo "$T_DIFF sec [$T_PREV]" else - echo -e "\t\t\t $T_DIFF sec" + echo "$T_DIFF sec" fi echo $T_DIFF > "output/$out_name" fi -- cgit v1.2.3 From 7200a9665771ed0ec36c16f8fb257cd69ed96f2e Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 00:33:39 +0200 Subject: test: Print timed out tests also on failure These tests are considered successful, but they might also occur as part of a failed run. Print their summary in that case too. Signed-off-by: Guillem Jover --- test/runtests.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/runtests.sh b/test/runtests.sh index 40083f0..5f40392 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -152,13 +152,14 @@ if [ -n "$SKIPPED" ]; then echo "Tests skipped: $SKIPPED" fi +if [ ! -z "$TIMED_OUT" ]; then + echo "Tests timed out: $TIMED_OUT" +fi + if [ "${RET}" -ne 0 ]; then echo "Tests failed: $FAILED" exit $RET else - if [ ! -z "$TIMED_OUT" ]; then - echo "Tests timed out: $TIMED_OUT" - fi echo "All tests passed" exit 0 fi -- cgit v1.2.3 From 6f5eaddbb9d3e801acb940e7a3749183fff28687 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Sun, 29 Aug 2021 00:10:58 +0200 Subject: test/timeout-new: Explicitly note that we are skipping the test Signed-off-by: Guillem Jover --- test/timeout-new.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/timeout-new.c b/test/timeout-new.c index b0bb5ee..19c5ac3 100644 --- a/test/timeout-new.c +++ b/test/timeout-new.c @@ -202,7 +202,7 @@ int main(int argc, char *argv[]) return 1; } if (!(ring_normal.features & IORING_FEAT_EXT_ARG)) { - fprintf(stderr, "feature IORING_FEAT_EXT_ARG not supported.\n"); + fprintf(stderr, "feature IORING_FEAT_EXT_ARG not supported, skipping.\n"); return 0; } -- cgit v1.2.3 From f7cb889530f6aa6181f5c3b1baa3de73b62ef51e Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Sun, 29 Aug 2021 01:05:14 +0200 Subject: test/io_uring_register: Expect ENOMEM or EFAULT from __sys_io_uring_register The code was only handling ENOMEM, but the function was getting an EFAULT, which a later print mentions as being an expected value anyway. Signed-off-by: Guillem Jover --- test/io_uring_register.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/io_uring_register.c b/test/io_uring_register.c index 9475739..da7bc0d 100644 --- a/test/io_uring_register.c +++ b/test/io_uring_register.c @@ -254,6 +254,10 @@ test_memlock_exceeded(int fd) iov.iov_len /= 2; continue; } + if (errno == EFAULT) { + free(buf); + return 0; + } printf("expected success or EFAULT, got %d\n", errno); free(buf); return 1; -- cgit v1.2.3 From 6e72065e39e6bb7e744c6ba24d1a62a8d84d3e27 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Sun, 29 Aug 2021 01:06:36 +0200 Subject: test/empty-eownerdead: Only expect EOWNERDEAD as test success The code was exiting with success on unexpected success from the function, and returning failure when the expected EOWNERDEAD was getting returned. Remove spurious "child" from error message. Signed-off-by: Guillem Jover --- test/empty-eownerdead.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/empty-eownerdead.c b/test/empty-eownerdead.c index 59d00ba..2783a74 100644 --- a/test/empty-eownerdead.c +++ b/test/empty-eownerdead.c @@ -32,11 +32,14 @@ int main(int argc, char *argv[]) if (ret < 0) { int __e = errno; - fprintf(stderr, "child: sqe submit failed: %s\n", strerror(__e)); - goto err; + if (errno == EOWNERDEAD) + return 0; + + fprintf(stderr, "sqe submit failed: %s\n", strerror(__e)); + } else { + fprintf(stderr, "sqe submit unexpected success, expecting EOWNERDEAD\n"); } - return 0; err: return 1; } -- cgit v1.2.3 From 18aed2911e8a6fecbaccf2ac09938fec12d06074 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 04:10:13 +0200 Subject: test: Use -n instead of ! -z Signed-off-by: Guillem Jover --- test/runtests.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/runtests.sh b/test/runtests.sh index 5f40392..5743547 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -122,7 +122,7 @@ run_test() T_PREV="" fi T_DIFF=$(($T_END-$T_START)) - if [ ! -z $T_PREV ]; then + if [ -n $T_PREV ]; then echo "$T_DIFF sec [$T_PREV]" else echo "$T_DIFF sec" @@ -138,7 +138,7 @@ for tst in $TESTS; do fi if [ ! -n "${TEST_MAP[$tst]}" ]; then run_test $tst - if [ ! -z "$TEST_FILES" ]; then + if [ -n "$TEST_FILES" ]; then for dev in $TEST_FILES; do run_test $tst $dev done @@ -152,7 +152,7 @@ if [ -n "$SKIPPED" ]; then echo "Tests skipped: $SKIPPED" fi -if [ ! -z "$TIMED_OUT" ]; then +if [ -n "$TIMED_OUT" ]; then echo "Tests timed out: $TIMED_OUT" fi -- cgit v1.2.3 From 974cd681956530fb2b3e5286d196a47b47532f1b Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 04:18:35 +0200 Subject: test: Use -z instead of ! -n Warned-by: shellcheck Signed-off-by: Guillem Jover --- test/runtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.sh b/test/runtests.sh index 5743547..e2ead92 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -136,7 +136,7 @@ for tst in $TESTS; do if [ ! -d output ]; then mkdir output fi - if [ ! -n "${TEST_MAP[$tst]}" ]; then + if [ -z "${TEST_MAP[$tst]}" ]; then run_test $tst if [ -n "$TEST_FILES" ]; then for dev in $TEST_FILES; do -- cgit v1.2.3 From 0d14fcb2a9badfab07d235c95396adc136741f18 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 04:11:34 +0200 Subject: test: Use an array instead of interpolating into a string via $@ Use a better type, instead of relying on word-expansion later on when using the variable with no quotes. Warned-by: shellcheck Signed-off-by: Guillem Jover --- test/runtests-loop.sh | 4 ++-- test/runtests.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/runtests-loop.sh b/test/runtests-loop.sh index 4019eba..f56d26d 100755 --- a/test/runtests-loop.sh +++ b/test/runtests-loop.sh @@ -1,10 +1,10 @@ #!/bin/bash -TESTS="$@" +TESTS=("$@") ITER=0 while true; do - ./runtests.sh "$TESTS" + ./runtests.sh "${TESTS[@]}" RET="$?" if [ "${RET}" -ne 0 ]; then echo "Tests failed at loop $ITER" diff --git a/test/runtests.sh b/test/runtests.sh index e2ead92..21b1f08 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -1,6 +1,6 @@ #!/bin/bash -TESTS="$@" +TESTS=("$@") RET=0 TIMEOUT=60 DMESG_FILTER="cat" @@ -132,7 +132,7 @@ run_test() } # Run all specified tests -for tst in $TESTS; do +for tst in "${TESTS[@]}"; do if [ ! -d output ]; then mkdir output fi -- cgit v1.2.3 From 148642c31ca2809fe6650c40ce7b7b994c3aee14 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 04:50:49 +0200 Subject: test: Pass an array to run_tests instead of an undefined variable The tests explicitly check the number of arguments and will skip them in case they are passed one if they are not supposed to be handling it. Do not pass an undefined variable, as that means we cannot quote it, which is not future-proof. Instead use an array and append the dev variable to it, if it is not defined. Warned-by: shellcheck Signed-off-by: Guillem Jover --- test/runtests.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/runtests.sh b/test/runtests.sh index 21b1f08..291481d 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -66,11 +66,13 @@ run_test() { local test_name="$1" local dev="$2" + local test_exec=("./$test_name") local test_string=$test_name local out_name=$test_name # Specify test string to print if [ -n "$dev" ]; then + test_exec+=("$dev") test_string="$test_name $dev" local suffix=$(basename $dev) out_name="$out_name.$suffix" @@ -95,7 +97,7 @@ run_test() # Run the test T_START=$(date +%s) - timeout -s INT -k $TIMEOUT $TIMEOUT ./$test_name $dev + timeout -s INT -k $TIMEOUT $TIMEOUT "${test_exec[@]}" T_END=$(date +%s) local status=$? -- cgit v1.2.3 From 35b79402797519a6387b7cada848eb5e804e7028 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 04:19:21 +0200 Subject: test: Add missing quotes around variables Warned-by: shellcheck Signed-off-by: Guillem Jover --- test/runtests.sh | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/runtests.sh b/test/runtests.sh index 291481d..98d14ac 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -4,7 +4,7 @@ TESTS=("$@") RET=0 TIMEOUT=60 DMESG_FILTER="cat" -TEST_DIR=$(dirname $0) +TEST_DIR=$(dirname "$0") FAILED="" SKIPPED="" TIMED_OUT="" @@ -17,14 +17,14 @@ DO_KMSG="1" # Include config.local if exists and check TEST_FILES for valid devices if [ -f "$TEST_DIR/config.local" ]; then - . $TEST_DIR/config.local + . "$TEST_DIR/config.local" for dev in $TEST_FILES; do if [ ! -e "$dev" ]; then echo "Test file $dev not valid" exit 1 fi done - for dev in ${TEST_MAP[@]}; do + for dev in "${TEST_MAP[@]}"; do if [ ! -e "$dev" ]; then echo "Test file in map $dev not valid" exit 1 @@ -37,7 +37,7 @@ _check_dmesg() local dmesg_marker="$1" local seqres="$2.seqres" - if [ $DO_KMSG -eq 0 ]; then + if [ "$DO_KMSG" -eq 0 ]; then return 0 fi @@ -67,28 +67,28 @@ run_test() local test_name="$1" local dev="$2" local test_exec=("./$test_name") - local test_string=$test_name - local out_name=$test_name + local test_string="$test_name" + local out_name="$test_name" # Specify test string to print if [ -n "$dev" ]; then test_exec+=("$dev") test_string="$test_name $dev" - local suffix=$(basename $dev) + local suffix=$(basename "$dev") out_name="$out_name.$suffix" fi # Log start of the test if [ "$DO_KMSG" -eq 1 ]; then local dmesg_marker="Running test $test_string:" - echo $dmesg_marker > /dev/kmsg + echo "$dmesg_marker" > /dev/kmsg else local dmesg_marker="" fi printf "Running test %-25s" "$test_string" # Do we have to exclude the test ? - echo $TEST_EXCLUDE | grep -w "$test_name" > /dev/null 2>&1 + echo "$TEST_EXCLUDE" | grep -w "$test_name" > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "Test skipped" SKIPPED="$SKIPPED <$test_string>" @@ -102,7 +102,7 @@ run_test() local status=$? if [ -e ./core ]; then - mv core core-$test_name + mv core "core-$test_name" fi # Check test status @@ -119,12 +119,12 @@ run_test() RET=1 else if [ -f "output/$out_name" ]; then - T_PREV=$(cat output/$out_name) + T_PREV=$(cat "output/$out_name") else T_PREV="" fi T_DIFF=$(($T_END-$T_START)) - if [ -n $T_PREV ]; then + if [ -n "$T_PREV" ]; then echo "$T_DIFF sec [$T_PREV]" else echo "$T_DIFF sec" @@ -139,14 +139,14 @@ for tst in "${TESTS[@]}"; do mkdir output fi if [ -z "${TEST_MAP[$tst]}" ]; then - run_test $tst + run_test "$tst" if [ -n "$TEST_FILES" ]; then for dev in $TEST_FILES; do - run_test $tst $dev + run_test "$tst" "$dev" done fi else - run_test $tst ${TEST_MAP[$tst]} + run_test "$tst" "${TEST_MAP[$tst]}" fi done -- cgit v1.2.3 From cc5aea4a1f7580577e48a34f254c1d8cb7238a79 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 04:21:12 +0200 Subject: test: Do not use $ in variables within $(()) Warned-by: shellcheck Signed-off-by: Guillem Jover --- test/runtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.sh b/test/runtests.sh index 98d14ac..c37f670 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -123,7 +123,7 @@ run_test() else T_PREV="" fi - T_DIFF=$(($T_END-$T_START)) + T_DIFF=$((T_END-T_START)) if [ -n "$T_PREV" ]; then echo "$T_DIFF sec [$T_PREV]" else -- cgit v1.2.3 From 27b9e5610f9de1cc12b6b4789ecc5c9987e49cfb Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 04:23:24 +0200 Subject: test: Declare and assign shell variable separately to not mask return value Warned-by: shellcheck Signed-off-by: Guillem Jover --- test/runtests.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/runtests.sh b/test/runtests.sh index c37f670..a9b27e3 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -74,7 +74,8 @@ run_test() if [ -n "$dev" ]; then test_exec+=("$dev") test_string="$test_name $dev" - local suffix=$(basename "$dev") + local suffix + suffix=$(basename "$dev") out_name="$out_name.$suffix" fi -- cgit v1.2.3 From 6955c95ce7a2bb9440e8c5edcb3409b1e4bf53bd Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Tue, 7 Sep 2021 04:55:16 +0200 Subject: test: Disable shellcheck checks The first depends on an optional file which we cannot guarantee to be present. The second matches an existing check currently disabled. Warned-by: shellcheck Signed-off-by: Guillem Jover --- test/runtests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/runtests.sh b/test/runtests.sh index a9b27e3..79184c0 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -17,6 +17,7 @@ DO_KMSG="1" # Include config.local if exists and check TEST_FILES for valid devices if [ -f "$TEST_DIR/config.local" ]; then + # shellcheck disable=SC1091 . "$TEST_DIR/config.local" for dev in $TEST_FILES; do if [ ! -e "$dev" ]; then @@ -90,6 +91,7 @@ run_test() # Do we have to exclude the test ? echo "$TEST_EXCLUDE" | grep -w "$test_name" > /dev/null 2>&1 + # shellcheck disable=SC2181 if [ $? -eq 0 ]; then echo "Test skipped" SKIPPED="$SKIPPED <$test_string>" -- cgit v1.2.3 From eaf51d51098995305a31b5d18fec7bbf9d0b12ce Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 7 Sep 2021 12:44:24 -0600 Subject: test/runtests.sh: align at 55 wide If you use a parameter for the tests, we run out pretty quickly. Move the alignment to 55, that still leaves plenty of room for the duration (and prev duration). Signed-off-by: Jens Axboe --- test/runtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.sh b/test/runtests.sh index 79184c0..a5c33a4 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -87,7 +87,7 @@ run_test() else local dmesg_marker="" fi - printf "Running test %-25s" "$test_string" + printf "Running test %-55s" "$test_string" # Do we have to exclude the test ? echo "$TEST_EXCLUDE" | grep -w "$test_name" > /dev/null 2>&1 -- cgit v1.2.3 From aefd23d05d68265feb2ff5cdb6bea1f8d9ac00e9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 7 Sep 2021 12:49:36 -0600 Subject: Revert "test/empty-eownerdead: Only expect EOWNERDEAD as test success" This reverts commit 6e72065e39e6bb7e744c6ba24d1a62a8d84d3e27. Signed-off-by: Jens Axboe --- test/empty-eownerdead.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/empty-eownerdead.c b/test/empty-eownerdead.c index 2783a74..59d00ba 100644 --- a/test/empty-eownerdead.c +++ b/test/empty-eownerdead.c @@ -32,14 +32,11 @@ int main(int argc, char *argv[]) if (ret < 0) { int __e = errno; - if (errno == EOWNERDEAD) - return 0; - - fprintf(stderr, "sqe submit failed: %s\n", strerror(__e)); - } else { - fprintf(stderr, "sqe submit unexpected success, expecting EOWNERDEAD\n"); + fprintf(stderr, "child: sqe submit failed: %s\n", strerror(__e)); + goto err; } + return 0; err: return 1; } -- cgit v1.2.3 From a357750b1547a7c5f4caac49bb0c556e4d4bb8c6 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 7 Sep 2021 12:51:29 -0600 Subject: Ignore spurious fadvise/madvise failures It's just too hard to reliably test, don't warn about it. Signed-off-by: Jens Axboe --- test/fadvise.c | 4 +++- test/madvise.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/fadvise.c b/test/fadvise.c index b6d4462..278a045 100644 --- a/test/fadvise.c +++ b/test/fadvise.c @@ -184,7 +184,9 @@ int main(int argc, char *argv[]) if (i >= MIN_LOOPS && !bad) break; } - if (bad > good) { + + /* too hard to reliably test, just ignore */ + if (0 && bad > good) { fprintf(stderr, "Suspicious timings\n"); goto err; } diff --git a/test/madvise.c b/test/madvise.c index 89057af..b85aba8 100644 --- a/test/madvise.c +++ b/test/madvise.c @@ -181,7 +181,8 @@ int main(int argc, char *argv[]) break; } - if (bad > good) + /* too hard to reliably test, just ignore */ + if (0 && bad > good) fprintf(stderr, "Suspicious timings (%u > %u)\n", bad, good); if (fname != argv[1]) unlink(fname); -- cgit v1.2.3 From 41a61c97c2e3df4475c93fdf5026d575ce3f1377 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 9 Sep 2021 09:28:22 -0600 Subject: liburing 2.1 Signed-off-by: Jens Axboe --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 68efbdc..57abbbe 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,7 +16,7 @@ LINK_FLAGS+=$(LDFLAGS) ENABLE_SHARED ?= 1 soname=liburing.so.2 -minor=0 +minor=1 micro=0 libname=$(soname).$(minor).$(micro) all_targets += liburing.a -- cgit v1.2.3 From e80b7ae99326d64e37302874cff5682515ec6485 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 9 Sep 2021 09:46:53 -0600 Subject: liburing.spec: bump to version 2.1 Signed-off-by: Jens Axboe --- liburing.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liburing.spec b/liburing.spec index 0268d23..7eb5731 100644 --- a/liburing.spec +++ b/liburing.spec @@ -1,5 +1,5 @@ Name: liburing -Version: 2.0 +Version: 2.1 Release: 1%{?dist} Summary: Linux-native io_uring I/O access library License: (GPLv2 with exceptions and LGPLv2+) or MIT -- cgit v1.2.3 From f618cbcea3aabbfee600df1fe5a30eb3cdb9c7bc Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 9 Sep 2021 12:31:19 -0600 Subject: test/file-register: newer kernels limit based on RLIMIT_NOFILE Adjust this when testing huge file sets, as that exceeds the standard default of 1024 open files. Signed-off-by: Jens Axboe --- test/file-register.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/file-register.c b/test/file-register.c index e7aa870..bd15408 100644 --- a/test/file-register.c +++ b/test/file-register.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "helpers.h" #include "liburing.h" @@ -494,6 +495,18 @@ static int test_fixed_read_write(struct io_uring *ring, int index) return 0; } +static void adjust_nfiles(int want_files) +{ + struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) + return; + if (rlim.rlim_cur >= want_files) + return; + rlim.rlim_cur = want_files; + setrlimit(RLIMIT_NOFILE, &rlim); +} + /* * Register 8K of sparse files, update one at a random spot, then do some * file IO to verify it works. @@ -503,6 +516,8 @@ static int test_huge(struct io_uring *ring) int *files; int ret; + adjust_nfiles(16384); + files = open_files(0, 8192, 0); ret = io_uring_register_files(ring, files, 8192); if (ret) { -- cgit v1.2.3 From 8b087c441ed5f57e344b2ec1b26fcac42b42896a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 10 Sep 2021 10:17:31 -0600 Subject: test/runtests.sh: fix retrieving status After adding the timing parts, we get the exit status after running date. That's obviously not very useful... Signed-off-by: Jens Axboe --- test/runtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.sh b/test/runtests.sh index a5c33a4..bc9978f 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -101,8 +101,8 @@ run_test() # Run the test T_START=$(date +%s) timeout -s INT -k $TIMEOUT $TIMEOUT "${test_exec[@]}" - T_END=$(date +%s) local status=$? + T_END=$(date +%s) if [ -e ./core ]; then mv core "core-$test_name" -- cgit v1.2.3 From 7154d88fb6f1eac943afb809d1612acf1ecb8fe2 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 11 Sep 2021 08:47:18 +0700 Subject: .github/workflows: add build_with_gcc.yml Add GitHub Actions build with GCC. Link: https://github.com/axboe/liburing/pull/425#issuecomment-914540396 Cc: Guillem Jover Signed-off-by: Ammar Faizi --- .github/workflows/build_with_gcc.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/build_with_gcc.yml diff --git a/.github/workflows/build_with_gcc.yml b/.github/workflows/build_with_gcc.yml new file mode 100644 index 0000000..63a99ce --- /dev/null +++ b/.github/workflows/build_with_gcc.yml @@ -0,0 +1,32 @@ +name: Build with GCC + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + main: + name: Build with GCC + strategy: + fail-fast: false + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Install Toolchains + run: | + sudo apt install -y man git gcc g++ make && \ + git --version && \ + gcc --version && \ + g++ --version && \ + make --version; + + - name: Build + run: | + make -j$(nproc) V=1 CFLAGS="-Werror" CPPFLAGS="-Werror" CXXFLAGS="-Werror" CC=gcc CXX=g++; + + - name: Test install command + run: sudo make install; -- cgit v1.2.3 From c4fc701966ea564d86d998cdc645f8fba7522fb6 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 11 Sep 2021 09:30:45 +0700 Subject: .github/workflows: add build_with_clang.yml Add GitHub Actions build with Clang. Link: https://github.com/axboe/liburing/pull/425#issuecomment-914540396 Cc: Guillem Jover Signed-off-by: Ammar Faizi --- .github/workflows/build_with_clang.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/build_with_clang.yml diff --git a/.github/workflows/build_with_clang.yml b/.github/workflows/build_with_clang.yml new file mode 100644 index 0000000..9a1987b --- /dev/null +++ b/.github/workflows/build_with_clang.yml @@ -0,0 +1,32 @@ +name: Build with Clang + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + main: + name: Build with Clang + strategy: + fail-fast: false + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Install Toolchains + run: | + sudo apt install -y man git clang make && \ + git --version && \ + clang --version && \ + clang++ --version && \ + make --version; + + - name: Build + run: | + make -j$(nproc) V=1 CFLAGS="-Werror" CPPFLAGS="-Werror" CXXFLAGS="-Werror" CC=clang CXX=clang++; + + - name: Test install command + run: sudo make install; -- cgit v1.2.3 From 008ccce8858aa620315aba71e6d2b332dff5a39c Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 11 Sep 2021 09:34:04 +0700 Subject: build_with_clang.yml: fix clang build error -Wunused-command-line-argument Buildling with Clang -Werror error: make[1]: Entering directory '/home/runner/work/liburing/liburing/test' clang -Werror -D_GNU_SOURCE -D__SANE_USERSPACE_TYPES__ -I../src/include/ -include ../config-host.h -Werror -D_GNU_SOURCE -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare -L../src/ -o helpers.o -c helpers.c -luring clang: error: -luring: 'linker' input unused [-Werror,-Wunused-command-line-argument] make[1]: *** [Makefile:159: helpers.o] Error 1 make[1]: Leaving directory '/home/runner/work/liburing/liburing/test' make: *** [Makefile:13: all] Error 2 ##[error]Process completed with exit code 2. Fix this by adding `-Wno-unused-command-line-argument` for Clang build. Signed-off-by: Ammar Faizi --- .github/workflows/build_with_clang.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_with_clang.yml b/.github/workflows/build_with_clang.yml index 9a1987b..28b0e08 100644 --- a/.github/workflows/build_with_clang.yml +++ b/.github/workflows/build_with_clang.yml @@ -26,7 +26,12 @@ jobs: - name: Build run: | - make -j$(nproc) V=1 CFLAGS="-Werror" CPPFLAGS="-Werror" CXXFLAGS="-Werror" CC=clang CXX=clang++; + make -j$(nproc) V=1 \ + CFLAGS="-Werror -Wno-unused-command-line-argument" \ + CPPFLAGS="-Werror -Wno-unused-command-line-argument" \ + CXXFLAGS="-Werror -Wno-unused-command-line-argument" \ + CC=clang \ + CXX=clang++; - name: Test install command run: sudo make install; -- cgit v1.2.3 From 17d25f4c73b89dfc722a367914776577e266638c Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 11 Sep 2021 13:10:04 +0700 Subject: test/io_uring_register: fix -Wimplicit-function-declaration of memfd_create On some systems, there is no `memfd_create` function. This commit fixes this: ``` CC io_uring_register io_uring_register.c: In function 'test_shmem': io_uring_register.c:514:10: warning: implicit declaration of function 'memfd_create' [-Wimplicit-function-declaration] memfd = memfd_create("uring-shmem-test", 0); ^ ``` Fix for this is based on an answer on Stack Overflow [1]. On Jun 16 '19 at 5:12, mosvy wrote: > On older systems, you'll have to include linux/memfd.h for the MFD_ > defines, and call memfd_create() via the the syscall(2) wrapper > (and include unistd.h and sys/syscall.h for it work). > Link: https://stackoverflow.com/a/56616264/7275114 [1] Reported-by: Louvian Lyndal Tested-by: Louvian Lyndal Signed-off-by: Ammar Faizi --- configure | 20 ++++++++++++++++++++ test/io_uring_register.c | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/configure b/configure index afccef1..a7caa07 100755 --- a/configure +++ b/configure @@ -338,6 +338,23 @@ if compile_prog "" "" "has_ucontext"; then fi print_config "has_ucontext" "$has_ucontext" +########################################## +# check for memfd_create(2) +has_memfd_create="no" +cat > $TMPC << EOF +#define _GNU_SOURCE +#include +int main(int argc, char **argv) +{ + int memfd = memfd_create("test", 0); + return 0; +} +EOF +if compile_prog "-Werror=implicit-function-declaration" "" "has_memfd_create"; then + has_memfd_create="yes" +fi +print_config "has_memfd_create" "$has_memfd_create" + ############################################################################# @@ -365,6 +382,9 @@ fi if test "$array_bounds" = "yes"; then output_sym "CONFIG_HAVE_ARRAY_BOUNDS" fi +if test "$has_memfd_create" = "yes"; then + output_sym "CONFIG_HAVE_MEMFD_CREATE" +fi echo "CC=$cc" >> $config_host_mak print_config "CC" "$cc" diff --git a/test/io_uring_register.c b/test/io_uring_register.c index da7bc0d..b8a4ea5 100644 --- a/test/io_uring_register.c +++ b/test/io_uring_register.c @@ -31,6 +31,17 @@ static int pagesize; static rlim_t mlock_limit; static int devnull; +#if !defined(CONFIG_HAVE_MEMFD_CREATE) +#include +#include + +static int memfd_create(const char *name, unsigned int flags) +{ + return (int)syscall(SYS_memfd_create, name, flags); +} +#endif + + int expect_fail(int fd, unsigned int opcode, void *arg, unsigned int nr_args, int error) -- cgit v1.2.3 From cb57034d2ff203cc5dbfd91ac9f0f6b0c8a511bf Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 11 Sep 2021 14:00:12 +0700 Subject: .github/workflows: fix apt warning Using `apt` gives the following warning: ``` WARNING: apt does not have a stable CLI interface. Use with caution in scripts. ``` Fix this by using `apt-get` instead of `apt`. On Dec 30 '17 at 15:15, dessert wrote: > apt is for the terminal and gives beautiful output while apt-get and > apt-cache are for scripts and give stable, parsable output. > Link: https://askubuntu.com/a/990838/1038828 Signed-off-by: Ammar Faizi --- .github/workflows/build_with_clang.yml | 4 ++-- .github/workflows/build_with_gcc.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_with_clang.yml b/.github/workflows/build_with_clang.yml index 28b0e08..3aca007 100644 --- a/.github/workflows/build_with_clang.yml +++ b/.github/workflows/build_with_clang.yml @@ -5,7 +5,7 @@ on: branches: [ master ] pull_request: branches: [ master ] - + jobs: main: name: Build with Clang @@ -18,7 +18,7 @@ jobs: - name: Install Toolchains run: | - sudo apt install -y man git clang make && \ + sudo apt-get install -y man git clang make && \ git --version && \ clang --version && \ clang++ --version && \ diff --git a/.github/workflows/build_with_gcc.yml b/.github/workflows/build_with_gcc.yml index 63a99ce..7c2e103 100644 --- a/.github/workflows/build_with_gcc.yml +++ b/.github/workflows/build_with_gcc.yml @@ -5,7 +5,7 @@ on: branches: [ master ] pull_request: branches: [ master ] - + jobs: main: name: Build with GCC @@ -18,7 +18,7 @@ jobs: - name: Install Toolchains run: | - sudo apt install -y man git gcc g++ make && \ + sudo apt-get install -y man git gcc g++ make && \ git --version && \ gcc --version && \ g++ --version && \ -- cgit v1.2.3 From d81e65241d3f4ad0445453fe7aa8adc0f84bf3fb Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sat, 11 Sep 2021 12:11:55 +0100 Subject: tests: add no-op executable for exec There are differences between close and exec from io_uring perspective, so we want to test exec as well. For that we need a program doing nothing to exec into. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/ed97597635e67d750bff377bdf68d03e1eb022e5.1631358658.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 2 ++ test/exec-target.c | 4 ++++ 3 files changed, 7 insertions(+) create mode 100644 test/exec-target.c diff --git a/.gitignore b/.gitignore index df0f740..0213bfa 100644 --- a/.gitignore +++ b/.gitignore @@ -129,6 +129,7 @@ /test/sqpoll-cancel-hang /test/testfile /test/submit-link-fail +/test/exec-target /test/*.dmesg config-host.h diff --git a/test/Makefile b/test/Makefile index 2313fcc..54ee730 100644 --- a/test/Makefile +++ b/test/Makefile @@ -135,6 +135,7 @@ test_targets += \ wakeup-hang \ sendmsg_fs_cve \ rsrc_tags \ + exec-target \ # EOL all_targets += $(test_targets) @@ -276,6 +277,7 @@ test_srcs := \ wakeup-hang.c \ sendmsg_fs_cve.c \ rsrc_tags.c \ + exec-target.c \ # EOL test_objs := $(patsubst %.c,%.ol,$(patsubst %.cc,%.ol,$(test_srcs))) diff --git a/test/exec-target.c b/test/exec-target.c new file mode 100644 index 0000000..50bc2c9 --- /dev/null +++ b/test/exec-target.c @@ -0,0 +1,4 @@ +int main(int argc, char *argv[]) +{ + return 0; +} -- cgit v1.2.3 From a802b850543f32247f7bcc2819226d075b0a50b7 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sat, 11 Sep 2021 12:11:56 +0100 Subject: tests: test timeout cancellation fails links Test that we appropriately fail linked requests when we cancel a normal timeout. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/e9acec809a3d86cab22601fe87c963c4ffac61e6.1631358658.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/timeout.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test/timeout.c b/test/timeout.c index d2e4930..cef6846 100644 --- a/test/timeout.c +++ b/test/timeout.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include "liburing.h" #include "../src/syscall.h" @@ -1171,6 +1173,82 @@ err: return 1; } +static int test_timeout_link_cancel(void) +{ + struct io_uring ring; + struct io_uring_cqe *cqe; + pid_t p; + int ret, i, wstatus; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring create failed: %d\n", ret); + return 1; + } + + p = fork(); + if (p == -1) { + fprintf(stderr, "fork() failed\n"); + return 1; + } + + if (p == 0) { + struct io_uring_sqe *sqe; + struct __kernel_timespec ts; + const char *prog_path = "./exec-target"; + + msec_to_ts(&ts, 10000); + sqe = io_uring_get_sqe(&ring); + io_uring_prep_timeout(sqe, &ts, 0, 0); + sqe->flags |= IOSQE_IO_LINK; + sqe->user_data = 0; + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_nop(sqe); + sqe->user_data = 1; + + ret = io_uring_submit(&ring); + if (ret != 2) { + fprintf(stderr, "%s: got %d, wanted 1\n", __FUNCTION__, ret); + exit(1); + } + + /* trigger full cancellation */ + ret = execl(prog_path, prog_path, NULL); + if (ret) { + fprintf(stderr, "exec failed %i\n", errno); + exit(1); + } + exit(0); + } + + if (waitpid(p, &wstatus, 0) == (pid_t)-1) { + perror("waitpid()"); + return 1; + } + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) { + fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus)); + return 1; + } + + for (i = 0; i < 2; ++i) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe=%d\n", ret); + return 1; + } + if (cqe->res != -ECANCELED) { + fprintf(stderr, "invalid result, user_data: %i res: %i\n", + (int)cqe->user_data, cqe->res); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + } + + io_uring_queue_exit(&ring); + return 0; +} + int main(int argc, char *argv[]) { struct io_uring ring, sqpoll_ring; @@ -1348,6 +1426,12 @@ int main(int argc, char *argv[]) return ret; } + ret = test_timeout_link_cancel(); + if (ret) { + fprintf(stderr, "test_timeout_link_cancel failed\n"); + return ret; + } + if (sqpoll) io_uring_queue_exit(&sqpoll_ring); return 0; -- cgit v1.2.3 From b7c779a90a987f7e65405c7985c52212fcf3cb53 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 24 May 2021 00:27:22 +0200 Subject: build: Fix build flags support The usual convention is that the various *FLAGS are user controllable, and can be overridden, so anything that is essential for the build should be passed respecting that. The other usual convention is that CPPFLAGS only contain pre-processor options, CFLAGS and CXXFLAGS only contain compilation options and LDFLAGS only contain linker flags, where all of these are honored in all build rules. Switch to set optional flags conditionally into the *FLAGS variables if they are not set, and then unconditionally append any required flags. And pass the various *FLAGS to the rules as expected. Signed-off-by: Guillem Jover --- .github/workflows/build_with_clang.yml | 6 ++-- examples/Makefile | 8 +++--- src/Makefile | 5 ++-- test/Makefile | 52 +++++++++++++++++----------------- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/.github/workflows/build_with_clang.yml b/.github/workflows/build_with_clang.yml index 3aca007..ce6707e 100644 --- a/.github/workflows/build_with_clang.yml +++ b/.github/workflows/build_with_clang.yml @@ -27,9 +27,9 @@ jobs: - name: Build run: | make -j$(nproc) V=1 \ - CFLAGS="-Werror -Wno-unused-command-line-argument" \ - CPPFLAGS="-Werror -Wno-unused-command-line-argument" \ - CXXFLAGS="-Werror -Wno-unused-command-line-argument" \ + CFLAGS="-Werror" \ + CPPFLAGS="-Werror" \ + CXXFLAGS="-Werror" \ CC=clang \ CXX=clang++; diff --git a/examples/Makefile b/examples/Makefile index a5d0b93..d3c5000 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,8 +1,8 @@ CPPFLAGS ?= override CPPFLAGS += -D_GNU_SOURCE -I../src/include/ -CFLAGS ?= -g -O2 -XCFLAGS = -override CFLAGS += -D_GNU_SOURCE -Wall -L../src/ +CFLAGS ?= -g -O2 -Wall +LDFLAGS ?= +override LDFLAGS += -L../src/ -luring include ../Makefile.quiet @@ -23,7 +23,7 @@ test_srcs := io_uring-test.c io_uring-cp.c link-cp.c test_objs := $(patsubst %.c,%.ol,$(test_srcs)) %: %.c - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -luring $(XCFLAGS) + $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(LDFLAGS) clean: @rm -f $(all_targets) $(test_objs) diff --git a/src/Makefile b/src/Makefile index 57abbbe..5e46a9d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,9 +6,8 @@ libdevdir ?= $(prefix)/lib CPPFLAGS ?= override CPPFLAGS += -D_GNU_SOURCE \ -Iinclude/ -include ../config-host.h -CFLAGS ?= -g -fomit-frame-pointer -O2 -override CFLAGS += -D_GNU_SOURCE \ - -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare +CFLAGS ?= -g -fomit-frame-pointer -O2 -Wall -Wextra +override CFLAGS += -Wno-unused-parameter -Wno-sign-compare SO_CFLAGS=-fPIC $(CFLAGS) L_CFLAGS=$(CFLAGS) LINK_FLAGS= diff --git a/test/Makefile b/test/Makefile index 54ee730..c626f8f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -10,12 +10,9 @@ endif CPPFLAGS ?= override CPPFLAGS += -D_GNU_SOURCE -D__SANE_USERSPACE_TYPES__ \ -I../src/include/ -include ../config-host.h -CFLAGS ?= -g -O2 -XCFLAGS = -override CFLAGS += -D_GNU_SOURCE \ - -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare \ - -L../src/ +CFLAGS ?= -g -O2 -Wall -Wextra +XCFLAGS = -Wno-unused-parameter -Wno-sign-compare ifdef CONFIG_HAVE_STRINGOP_OVERFLOW XCFLAGS += -Wstringop-overflow=0 endif @@ -23,8 +20,11 @@ ifdef CONFIG_HAVE_ARRAY_BOUNDS XCFLAGS += -Warray-bounds=0 endif -CXXFLAGS ?= -override CXXFLAGS += $(CFLAGS) -std=c++11 +CXXFLAGS ?= $(CFLAGS) +override CFLAGS += $(XCFLAGS) +override CXXFLAGS += $(XCFLAGS) -std=c++11 +LDFLAGS ?= +override LDFLAGS += -L../src/ -luring test_targets += \ 232c93d07b74-test \ @@ -157,13 +157,13 @@ helpers = helpers.o all: ${helpers} $(test_targets) helpers.o: helpers.c helpers.c - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< -luring + $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< %: %.c ${helpers} helpers.h - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< ${helpers} -luring $(XCFLAGS) + $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< ${helpers} $(LDFLAGS) %: %.cc ${helpers} helpers.h - $(QUIET_CXX)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< ${helpers} -luring $(XCFLAGS) + $(QUIET_CXX)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< ${helpers} $(LDFLAGS) test_srcs := \ helpers.c \ @@ -282,22 +282,22 @@ test_srcs := \ test_objs := $(patsubst %.c,%.ol,$(patsubst %.cc,%.ol,$(test_srcs))) -35fa71a030ca-test: XCFLAGS = -lpthread -232c93d07b74-test: XCFLAGS = -lpthread -send_recv: XCFLAGS = -lpthread -send_recvmsg: XCFLAGS = -lpthread -poll-link: XCFLAGS = -lpthread -accept-link: XCFLAGS = -lpthread -submit-reuse: XCFLAGS = -lpthread -poll-v-poll: XCFLAGS = -lpthread -across-fork: XCFLAGS = -lpthread -ce593a6c480a-test: XCFLAGS = -lpthread -wakeup-hang: XCFLAGS = -lpthread -pipe-eof: XCFLAGS = -lpthread -timeout-new: XCFLAGS = -lpthread -thread-exit: XCFLAGS = -lpthread -ring-leak2: XCFLAGS = -lpthread -poll-mshot-update: XCFLAGS = -lpthread +35fa71a030ca-test: override LDFLAGS += -lpthread +232c93d07b74-test: override LDFLAGS += -lpthread +send_recv: override LDFLAGS += -lpthread +send_recvmsg: override LDFLAGS += -lpthread +poll-link: override LDFLAGS += -lpthread +accept-link: override LDFLAGS += -lpthread +submit-reuse: override LDFLAGS += -lpthread +poll-v-poll: override LDFLAGS += -lpthread +across-fork: override LDFLAGS += -lpthread +ce593a6c480a-test: override LDFLAGS += -lpthread +wakeup-hang: override LDFLAGS += -lpthread +pipe-eof: override LDFLAGS += -lpthread +timeout-new: override LDFLAGS += -lpthread +thread-exit: override LDFLAGS += -lpthread +ring-leak2: override LDFLAGS += -lpthread +poll-mshot-update: override LDFLAGS += -lpthread install: $(test_targets) runtests.sh runtests-loop.sh $(INSTALL) -D -d -m 755 $(datadir)/liburing-test/ -- cgit v1.2.3 From 62ba337d48825dc6bb68980a28a50b7a7683c2ff Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 13 Sep 2021 13:04:43 +0200 Subject: test/poll-cancel-ton: Remove unused variable Warned-by: clang-14 Signed-off-by: Guillem Jover --- test/poll-cancel-ton.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/poll-cancel-ton.c b/test/poll-cancel-ton.c index e9d612e..f0875cd 100644 --- a/test/poll-cancel-ton.c +++ b/test/poll-cancel-ton.c @@ -71,10 +71,10 @@ static int del_polls(struct io_uring *ring, int fd, int nr) static int add_polls(struct io_uring *ring, int fd, int nr) { - int pending, batch, i, count, ret; + int batch, i, count, ret; struct io_uring_sqe *sqe; - pending = count = 0; + count = 0; while (nr) { batch = 1024; if (batch > nr) @@ -93,7 +93,6 @@ static int add_polls(struct io_uring *ring, int fd, int nr) return 1; } nr -= batch; - pending += batch; reap_events(ring, batch, 1); } return 0; -- cgit v1.2.3 From 84875f42cab07d4b39d64b043cf9dbbdfe618674 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 13 Sep 2021 12:40:46 +0200 Subject: test/empty-eownerdead: Clarify unexpected error message Old kernels incorrectly return EOWNERDEAD, catch that explicitly and print a more clear error message to avoid unsuspecting users think the test might be buggy, when it is the kernel. Reword fallback error message too to make it clear these are unexpected too. Signed-off-by: Guillem Jover --- test/empty-eownerdead.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/empty-eownerdead.c b/test/empty-eownerdead.c index 59d00ba..40f854f 100644 --- a/test/empty-eownerdead.c +++ b/test/empty-eownerdead.c @@ -32,7 +32,10 @@ int main(int argc, char *argv[]) if (ret < 0) { int __e = errno; - fprintf(stderr, "child: sqe submit failed: %s\n", strerror(__e)); + if (__e == EOWNERDEAD) + fprintf(stderr, "sqe submit unexpected failure due old kernel bug: %s\n", strerror(__e)); + else + fprintf(stderr, "sqe submit unexpected failure: %s\n", strerror(__e)); goto err; } -- cgit v1.2.3 From 422f5c109fbea6901f92021a8a0eb789791ce593 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Sat, 11 Sep 2021 23:30:12 +0200 Subject: test/runtests.sh: Fix shellcheck directive for old versions The sourced file cannot be guaranteed to be present, and old shellcheck versions do not take into account the annotated suppression. Instead unconditionally redirect it to /dev/null. Signed-off-by: Guillem Jover --- test/runtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.sh b/test/runtests.sh index bc9978f..c77df6a 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -17,7 +17,7 @@ DO_KMSG="1" # Include config.local if exists and check TEST_FILES for valid devices if [ -f "$TEST_DIR/config.local" ]; then - # shellcheck disable=SC1091 + # shellcheck source=/dev/null disable=SC1091 . "$TEST_DIR/config.local" for dev in $TEST_FILES; do if [ ! -e "$dev" ]; then -- cgit v1.2.3 From a8feca92ea9613e05acc7b7f4713071e36a4fe9a Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 13 Sep 2021 12:46:15 +0200 Subject: .github/workflows: Add new shellcheck CI test Signed-off-by: Guillem Jover --- .github/workflows/shellcheck.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/shellcheck.yml diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml new file mode 100644 index 0000000..8873f0b --- /dev/null +++ b/.github/workflows/shellcheck.yml @@ -0,0 +1,20 @@ +name: Shellcheck + +on: + # Trigger the workflow on push or pull requests. + push: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Display shellcheck version + run: shellcheck --version + + - name: Shellcheck execution + run: shellcheck test/runtest*.sh -- cgit v1.2.3 From eb6f8905db08130242dd02df0583107feccfe6fb Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Wed, 8 Sep 2021 02:10:15 +0200 Subject: .github/workflows: Simplify and unify build tests - Use a single definition for both gcc and clang tests, by using a matrix. - Remove redundant installation for packages present in the CI system. - Remove version printing for uninteresting programs. - Trigger for all branches, so that MRs can see results on non-master. Signed-off-by: Guillem Jover --- .github/workflows/build.yml | 40 ++++++++++++++++++++++++++++++++++ .github/workflows/build_with_clang.yml | 37 ------------------------------- .github/workflows/build_with_gcc.yml | 32 --------------------------- 3 files changed, 40 insertions(+), 69 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/build_with_clang.yml delete mode 100644 .github/workflows/build_with_gcc.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..432dbb6 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,40 @@ +name: Build test + +on: + # Trigger the workflow on push or pull requests. + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + include: + - cc: gcc + cxx: g++ + - cc: clang + cxx: clang++ + + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Display compiler versions + run: | + ${{matrix.cc}} --version + ${{matrix.cxx}} --version + + - name: Build + run: | + ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} + make V=1 -j$(nproc) \ + CPPFLAGS="-Werror" \ + CFLAGS="-Werror" \ + CXXFLAGS="-Werror" + + - name: Test install command + run: | + sudo make install diff --git a/.github/workflows/build_with_clang.yml b/.github/workflows/build_with_clang.yml deleted file mode 100644 index ce6707e..0000000 --- a/.github/workflows/build_with_clang.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Build with Clang - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - main: - name: Build with Clang - strategy: - fail-fast: false - - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Install Toolchains - run: | - sudo apt-get install -y man git clang make && \ - git --version && \ - clang --version && \ - clang++ --version && \ - make --version; - - - name: Build - run: | - make -j$(nproc) V=1 \ - CFLAGS="-Werror" \ - CPPFLAGS="-Werror" \ - CXXFLAGS="-Werror" \ - CC=clang \ - CXX=clang++; - - - name: Test install command - run: sudo make install; diff --git a/.github/workflows/build_with_gcc.yml b/.github/workflows/build_with_gcc.yml deleted file mode 100644 index 7c2e103..0000000 --- a/.github/workflows/build_with_gcc.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Build with GCC - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - main: - name: Build with GCC - strategy: - fail-fast: false - - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Install Toolchains - run: | - sudo apt-get install -y man git gcc g++ make && \ - git --version && \ - gcc --version && \ - g++ --version && \ - make --version; - - - name: Build - run: | - make -j$(nproc) V=1 CFLAGS="-Werror" CPPFLAGS="-Werror" CXXFLAGS="-Werror" CC=gcc CXX=g++; - - - name: Test install command - run: sudo make install; -- cgit v1.2.3 From 1c9ff85e5d03aeb021a5da6b480359259668b712 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 13 Sep 2021 13:25:42 +0200 Subject: .travis.yml: Remove unused Travis CI support We have switched now to use GitHub actions, and Travis has changed their policy and quotas to the point of making their usage very cumbersome. Signed-off-by: Guillem Jover --- .travis.yml | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e02fdd0..0000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: cpp -os: - - linux -compiler: - - clang - - gcc -env: - matrix: - - BUILD_ARCH="x86" - - BUILD_ARCH="x86_64" - global: - - MAKEFLAGS="-j 2" -matrix: - exclude: - - os: linux - compiler: clang - env: BUILD_ARCH="x86" # Only do the gcc x86 build to reduce clutter -before_install: - - EXTRA_CFLAGS="-Werror" -script: - - ./configure && make - - sudo make runtests || true -- cgit v1.2.3 From cb350a8989adbd65db574325d9a86d5437d800da Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 13 Sep 2021 23:56:08 +0200 Subject: test: Use syscall wrappers instead of using syscall(2) directly Some of these syscalls have different entry points depending on the architecture. Use the wrappers to avoid having to reimplement them portably. Fixes build failures on Debian armel and armhf builds. Signed-off-by: Guillem Jover --- test/sqpoll-cancel-hang.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/sqpoll-cancel-hang.c b/test/sqpoll-cancel-hang.c index c9032c8..e561478 100644 --- a/test/sqpoll-cancel-hang.c +++ b/test/sqpoll-cancel-hang.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -29,8 +28,6 @@ static uint64_t current_time_ms(void) #define IORING_OFF_SQES 0x10000000ULL -#define sys_io_uring_setup 425 - static void kill_and_wait(int pid, int* status) { kill(-pid, SIGKILL); @@ -53,7 +50,7 @@ a5) void* vma2 = (void*)a3; void** ring_ptr_out = (void**)a4; void** sqes_ptr_out = (void**)a5; - uint32_t fd_io_uring = syscall(sys_io_uring_setup, entries, setup_params); + uint32_t fd_io_uring = __sys_io_uring_setup(entries, setup_params); uint32_t sq_ring_sz = setup_params->sq_off.array + setup_params->sq_entries * sizeof(uint32_t); uint32_t cq_ring_sz = setup_params->cq_off.cqes + @@ -135,7 +132,7 @@ void trigger_bug(void) } int main(void) { - syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); + mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); int pid = fork(); if (pid < 0) exit(1); -- cgit v1.2.3 From 49e703816b51fc375d1e34a72937a2daeaea17c8 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 13 Sep 2021 23:58:10 +0200 Subject: test: Remove unused syscall number definitions These are leftovers from when the tests used direct syscall(2) calls. Signed-off-by: Guillem Jover --- test/double-poll-crash.c | 4 ---- test/fc2a85cb02ef-test.c | 7 ------- 2 files changed, 11 deletions(-) diff --git a/test/double-poll-crash.c b/test/double-poll-crash.c index 2a012e5..d9277be 100644 --- a/test/double-poll-crash.c +++ b/test/double-poll-crash.c @@ -103,10 +103,6 @@ static long syz_open_dev(volatile long a0, volatile long a1, volatile long a2) } } -#ifndef __NR_io_uring_enter -#define __NR_io_uring_enter 426 -#endif - uint64_t r[4] = {0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff}; int main(int argc, char *argv[]) diff --git a/test/fc2a85cb02ef-test.c b/test/fc2a85cb02ef-test.c index 35addf5..bdc3c48 100644 --- a/test/fc2a85cb02ef-test.c +++ b/test/fc2a85cb02ef-test.c @@ -78,13 +78,6 @@ static int setup_fault() return 0; } -#ifndef __NR_io_uring_register -#define __NR_io_uring_register 427 -#endif -#ifndef __NR_io_uring_setup -#define __NR_io_uring_setup 425 -#endif - uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff}; int main(int argc, char *argv[]) -- cgit v1.2.3 From 7e37d3ec6852551f6c4690da4d8c4ef072c7719e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 14 Sep 2021 08:44:25 -0600 Subject: test/timeout: improve finding exec-target The test is currently broken because it assumes that it's in the same directory, that's never the case if the test is run from the make runtests target. Try both ./exec-target and test/exec-target, that should make it work more reliably. Fixes: a802b850543f ("tests: test timeout cancellation fails links") Signed-off-by: Jens Axboe --- test/timeout.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/timeout.c b/test/timeout.c index cef6846..775063f 100644 --- a/test/timeout.c +++ b/test/timeout.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "liburing.h" #include "../src/syscall.h" @@ -1173,13 +1174,31 @@ err: return 1; } +static int fill_exec_target(char *dst, char *path) +{ + struct stat sb; + + /* + * Should either be ./exec-target or test/exec-target + */ + sprintf(dst, "%s", path); + return stat(dst, &sb); +} + static int test_timeout_link_cancel(void) { struct io_uring ring; struct io_uring_cqe *cqe; + char prog_path[PATH_MAX]; pid_t p; int ret, i, wstatus; + if (fill_exec_target(prog_path, "./exec-target") && + fill_exec_target(prog_path, "test/exec-target")) { + fprintf(stdout, "Can't find exec-target, skipping\n"); + return 0; + } + ret = io_uring_queue_init(8, &ring, 0); if (ret) { fprintf(stderr, "ring create failed: %d\n", ret); @@ -1195,7 +1214,6 @@ static int test_timeout_link_cancel(void) if (p == 0) { struct io_uring_sqe *sqe; struct __kernel_timespec ts; - const char *prog_path = "./exec-target"; msec_to_ts(&ts, 10000); sqe = io_uring_get_sqe(&ring); -- cgit v1.2.3 From 026483605806f25f37d7e090bd163b4cb1b6c7b7 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 14 Sep 2021 16:20:31 +0100 Subject: tests: test open into taken fixed slot Add a test case verifying opening into an already teaken fixed file slot. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/d87d67a95dc816556e3e38440bf34163fba3861f.1631632805.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/openat2.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 8 deletions(-) diff --git a/test/openat2.c b/test/openat2.c index 7838c05..379c61e 100644 --- a/test/openat2.c +++ b/test/openat2.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "helpers.h" #include "liburing.h" @@ -117,11 +118,6 @@ static int test_open_fixed(const char *path, int dfd) return -1; } - ret = test_openat2(&ring, path, dfd, true, 0); - if (ret != -EBADF) { - fprintf(stderr, "bogus double register %d\n", ret); - return -1; - } io_uring_queue_exit(&ring); return 0; } @@ -152,25 +148,90 @@ static int test_open_fixed_fail(const char *path, int dfd) ret = test_openat2(&ring, path, dfd, true, 1); if (ret != -EINVAL) { fprintf(stderr, "install out of bounds, %i\n", ret); - return 1; + return -1; } ret = test_openat2(&ring, path, dfd, true, (1u << 16)); if (ret != -EINVAL) { fprintf(stderr, "install out of bounds or u16 overflow, %i\n", ret); - return 1; + return -1; } ret = test_openat2(&ring, path, dfd, true, (1u << 16) + 1); if (ret != -EINVAL) { fprintf(stderr, "install out of bounds or u16 overflow, %i\n", ret); - return 1; + return -1; } io_uring_queue_exit(&ring); return 0; } +static int test_direct_reinstall(const char *path, int dfd) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + char buf[1] = { 0xfa }; + struct io_uring ring; + int ret, pipe_fds[2]; + ssize_t ret2; + + if (pipe2(pipe_fds, O_NONBLOCK)) { + fprintf(stderr, "pipe() failed\n"); + return -1; + } + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed\n"); + return -1; + } + ret = io_uring_register_files(&ring, pipe_fds, 2); + if (ret) { + fprintf(stderr, "%s: register ret=%d\n", __FUNCTION__, ret); + return -1; + } + + /* reinstall into the second slot */ + ret = test_openat2(&ring, path, dfd, true, 1); + if (ret != 0) { + fprintf(stderr, "reinstall failed, %i\n", ret); + return -1; + } + + /* verify it's reinstalled, first write into the slot... */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_write(sqe, 1, buf, sizeof(buf), 0); + sqe->flags |= IOSQE_FIXED_FILE; + + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + return -1; + } + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + return ret; + } + ret = cqe->res; + io_uring_cqe_seen(&ring, cqe); + if (ret != 1) { + fprintf(stderr, "invalid write %i\n", ret); + return -1; + } + + /* ... and make sure nothing has been written to the pipe */ + ret2 = read(pipe_fds[0], buf, 1); + if (ret2 != 0 && !(ret2 < 0 && errno == EAGAIN)) { + fprintf(stderr, "invalid pipe read, %d %d\n", errno, (int)ret2); + return -1; + } + + close(pipe_fds[0]); + close(pipe_fds[1]); + io_uring_queue_exit(&ring); + return 0; +} int main(int argc, char *argv[]) { @@ -227,6 +288,13 @@ int main(int argc, char *argv[]) fprintf(stderr, "test_open_fixed_fail failed\n"); goto err; } + + ret = test_direct_reinstall(path, -1); + if (ret) { + fprintf(stderr, "test_direct_reinstall failed\n"); + goto err; + } + done: unlink(path); if (do_unlink) -- cgit v1.2.3 From 10a0f65c617ed084281cd16c8b6e41cd6e307235 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 14 Sep 2021 18:54:48 +0100 Subject: man/io_uring_enter.2: update notes about direct open/accept Reflect recent changes in the man, i.e. direct open/accept now would try to remove a file from the fixed file table if the slot they target is already taken. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/e5fe9b4c3130a5402e4328d87f214a98b39e33f7.1631642033.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index ad86961..6b31061 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -517,10 +517,12 @@ field is set to a positive number, the file won't be installed into the normal file table as usual but will be placed into the fixed file table at index .I file_index - 1. In this case, instead of returning a file descriptor, the result will contain -either 0 on success or an error. If there is already a file registered at this -index, the request will fail with -.B -EBADF. -Only io_uring has access to such files and no other syscall can use them. See +either 0 on success or an error. If the index points to a valid empty slot, the +installation is guaranteed to not fail. If there is already a file in the slot, +it will be replaced, similar to +.B IORING_OP_FILES_UPDATE. +Please note that only io_uring has access to such files and no other syscall +can use them. See .B IOSQE_FIXED_FILE and .B IORING_REGISTER_FILES. @@ -656,10 +658,12 @@ field is set to a positive number, the file won't be installed into the normal file table as usual but will be placed into the fixed file table at index .I file_index - 1. In this case, instead of returning a file descriptor, the result will contain -either 0 on success or an error. If there is already a file registered at this -index, the request will fail with -.B -EBADF. -Only io_uring has access to such files and no other syscall can use them. See +either 0 on success or an error. If the index points to a valid empty slot, the +installation is guaranteed to not fail. If there is already a file in the slot, +it will be replaced, similar to +.B IORING_OP_FILES_UPDATE. +Please note that only io_uring has access to such files and no other syscall +can use them. See .B IOSQE_FIXED_FILE and .B IORING_REGISTER_FILES. @@ -692,10 +696,12 @@ field is set to a positive number, the file won't be installed into the normal file table as usual but will be placed into the fixed file table at index .I file_index - 1. In this case, instead of returning a file descriptor, the result will contain -either 0 on success or an error. If there is already a file registered at this -index, the request will fail with -.B -EBADF. -Only io_uring has access to such files and no other syscall can use them. See +either 0 on success or an error. If the index points to a valid empty slot, the +installation is guaranteed to not fail. If there is already a file in the slot, +it will be replaced, similar to +.B IORING_OP_FILES_UPDATE. +Please note that only io_uring has access to such files and no other syscall +can use them. See .B IOSQE_FIXED_FILE and .B IORING_REGISTER_FILES. -- cgit v1.2.3 From 63e3be514c1059009940a23f268494a146a946be Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Wed, 15 Sep 2021 15:11:56 +0700 Subject: test/io_uring_setup: Don't use `__errno` as local variable name This commit fixes build for armv8l. On some systems, the macro `errno` is defined as `#define errno (*__errno())` It is clear that `__errno` is a global function on such systems. The problem is, `io_uring_setup.c` uses `int __errno` as a local variable, so it shadows the `__errno` function, result in the following error: ``` CC io_uring_setup io_uring_setup.c:116:12: error: called object type 'int' is not a function or function pointer __errno = errno; ^~~~~ /usr/include/errno.h:58:24: note: expanded from macro 'errno' #define errno (*__errno()) ~~~~~~~^ 1 error generated. make[1]: *** [Makefile:163: io_uring_setup] Error 1 make[1]: *** Waiting for unfinished jobs.... ``` Fix this by not using `__errno` as local variable name. Reported-by: Louvian Lyndal Tested-by: Louvian Lyndal Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/2d53ef3f50713749511865a7f89e27c5378e316d.1631692342.git.ammarfaizi2@gmail.com Signed-off-by: Jens Axboe --- test/io_uring_setup.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/io_uring_setup.c b/test/io_uring_setup.c index a0709a7..94b54fd 100644 --- a/test/io_uring_setup.c +++ b/test/io_uring_setup.c @@ -99,7 +99,7 @@ dump_resv(struct io_uring_params *p) int try_io_uring_setup(unsigned entries, struct io_uring_params *p, int expect, int error) { - int ret, __errno; + int ret, err; printf("io_uring_setup(%u, %p), flags: %s, feat: %s, resv: %s, sq_thread_cpu: %u\n", entries, p, flags_string(p), features_string(p), dump_resv(p), @@ -113,13 +113,13 @@ try_io_uring_setup(unsigned entries, struct io_uring_params *p, int expect, int close(ret); return 1; } - __errno = errno; - if (expect == -1 && error != __errno) { - if (__errno == EPERM && geteuid() != 0) { + err = errno; + if (expect == -1 && error != err) { + if (err == EPERM && geteuid() != 0) { printf("Needs root, not flagging as an error\n"); return 0; } - printf("expected errno %d, got %d\n", error, __errno); + printf("expected errno %d, got %d\n", error, err); return 1; } -- cgit v1.2.3 From 87e8a7aaf6a7a1089c6479f438b11299206c7a01 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Wed, 15 Sep 2021 15:11:57 +0700 Subject: test/send_recv: Use proper cast for (struct sockaddr *) argument This commit fixes build for armv8l. Sometimes the compiler accepts (struct sockaddr_in *) to be passed to (struct sockaddr *) without cast. But not all compilers agree with that. Louvian found the following warning on armv8l: ``` send_recv.c:203:24: warning: incompatible pointer types passing 'struct sockaddr_in *' to parameter of type 'const struct sockaddr *' [-Wincompatible-pointer-types] ret = connect(sockfd, &saddr, sizeof(saddr)); ^~~~~~ /usr/include/sys/socket.h:308:59: note: passing argument to parameter '__addr' here __socketcall int connect(int __fd, const struct sockaddr* __addr, socklen_t __addr_length); ^ 1 warning generated. ``` Fix this by casting the second argument to (struct sockaddr *). Reported-by: Louvian Lyndal Tested-by: Louvian Lyndal Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/91812264f5600e1a460203d5297eb43aa978f9bf.1631692342.git.ammarfaizi2@gmail.com Signed-off-by: Jens Axboe --- test/send_recv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/send_recv.c b/test/send_recv.c index 38ae27f..1ee0234 100644 --- a/test/send_recv.c +++ b/test/send_recv.c @@ -200,7 +200,7 @@ static int do_send(void) return 1; } - ret = connect(sockfd, &saddr, sizeof(saddr)); + ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { perror("connect"); return 1; -- cgit v1.2.3 From 1274abfc33450dde08a0166acc2beaba6ad0da2b Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Wed, 15 Sep 2021 15:11:58 +0700 Subject: .gitignore: add `/test/output/` Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/b9aacc68090774c08f871720d3f8b575e62f8807.1631692342.git.ammarfaizi2@gmail.com Signed-off-by: Jens Axboe --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0213bfa..45f3cde 100644 --- a/.gitignore +++ b/.gitignore @@ -131,6 +131,7 @@ /test/submit-link-fail /test/exec-target /test/*.dmesg +/test/output/ config-host.h config-host.mak -- cgit v1.2.3 From 055ed4352a159bf4c9ab14296a563f36a0a6b8f2 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Wed, 15 Sep 2021 14:50:58 +0200 Subject: examples: Fix warnings for comparison of integers with different signedness Warned-by: gcc -Wsign-compare Signed-off-by: Guillem Jover --- examples/io_uring-cp.c | 5 +++-- examples/link-cp.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/io_uring-cp.c b/examples/io_uring-cp.c index 2a44c30..9322575 100644 --- a/examples/io_uring-cp.c +++ b/examples/io_uring-cp.c @@ -127,7 +127,8 @@ static int copy_file(struct io_uring *ring, off_t insize) writes = reads = offset = 0; while (insize || write_left) { - int had_reads, got_comp; + unsigned long had_reads; + int got_comp; /* * Queue up as many reads as we can @@ -194,7 +195,7 @@ static int copy_file(struct io_uring *ring, off_t insize) fprintf(stderr, "cqe failed: %s\n", strerror(-cqe->res)); return 1; - } else if (cqe->res != data->iov.iov_len) { + } else if ((size_t)cqe->res != data->iov.iov_len) { /* Short read/write, adjust and requeue */ data->iov.iov_base += cqe->res; data->iov.iov_len -= cqe->res; diff --git a/examples/link-cp.c b/examples/link-cp.c index e15dfc3..244d21a 100644 --- a/examples/link-cp.c +++ b/examples/link-cp.c @@ -26,7 +26,7 @@ struct io_data { }; static int infd, outfd; -static unsigned inflight; +static int inflight; static int setup_context(unsigned entries, struct io_uring *ring) { @@ -115,7 +115,7 @@ static int handle_cqe(struct io_uring *ring, struct io_uring_cqe *cqe) static int copy_file(struct io_uring *ring, off_t insize) { struct io_uring_cqe *cqe; - size_t this_size; + off_t this_size; off_t offset; offset = 0; -- cgit v1.2.3 From 6b45ffafd101450dbd11ff0c40e8776974bee108 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Wed, 15 Sep 2021 14:15:24 +0200 Subject: .github/workflows/build.yml: Pass -g -O2 -Wall -Wextra explicitly As these flags are marked as optional now they get reset when we pass explicit flags. Signed-off-by: Guillem Jover --- .github/workflows/build.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 432dbb6..f82d0e6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,6 +18,9 @@ jobs: - cc: clang cxx: clang++ + env: + FLAGS: -g -O2 -Wall -Wextra -Werror + steps: - name: Checkout source uses: actions/checkout@v2 @@ -32,8 +35,8 @@ jobs: ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} make V=1 -j$(nproc) \ CPPFLAGS="-Werror" \ - CFLAGS="-Werror" \ - CXXFLAGS="-Werror" + CFLAGS="$FLAGS" \ + CXXFLAGS="$FLAGS" - name: Test install command run: | -- cgit v1.2.3 From 6ab387dab745aff2af760d9fed56a4154669edec Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 15 Sep 2021 18:05:13 -0600 Subject: test/file-verify: add read verification test This test attempts to exercise the various paths that a read can take. We try and trigger incremental reads and loops, by removing page cache parts of a cached file for reading. In essence, these are the two types of iterator conditions we want to hit: 1) We get -EAGAIN immediately. This is common for buffered IO when the range isn't in page cache. 2) We get a short read, again common for buffered read. Internally, we have three different mechanisms we want to exercise, as they can behave a bit differently: 1) Using non-vectored read 1) Using non-vectored registered buffer read 3) Using vectored read, segments that fit in UIO_FASTIOV 4) Using vectored read, segments larger than UIO_FASTIOV We try and accomplish this by doing reads that hit any of these three conditions, and then we remove page cache in chunks from a file from either the front, middle, or end of the file. We do go through all of these for both buffered and O_DIRECT reads. Signed-off-by: Jens Axboe --- test/Makefile | 2 + test/file-verify.c | 370 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 372 insertions(+) create mode 100644 test/file-verify.c diff --git a/test/Makefile b/test/Makefile index c626f8f..2936469 100644 --- a/test/Makefile +++ b/test/Makefile @@ -63,6 +63,7 @@ test_targets += \ fallocate \ fc2a85cb02ef-test \ file-register \ + file-verify \ file-update \ files-exit-hang-poll \ files-exit-hang-timeout \ @@ -203,6 +204,7 @@ test_srcs := \ fallocate.c \ fc2a85cb02ef-test.c \ file-register.c \ + file-verify.c \ file-update.c \ files-exit-hang-poll.c \ files-exit-hang-timeout.c \ diff --git a/test/file-verify.c b/test/file-verify.c new file mode 100644 index 0000000..ffedd87 --- /dev/null +++ b/test/file-verify.c @@ -0,0 +1,370 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: run various reads tests, verifying data + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "liburing.h" + +#define FSIZE 128*1024*1024 +#define CHUNK_SIZE 131072 +#define PUNCH_SIZE 32768 + +/* + * 8 because it fits within the on-stack iov, 16 because it's larger than 8 + */ +#define MIN_VECS 8 +#define MAX_VECS 16 + +/* + * Can be anything, let's just do something for a bit of parallellism + */ +#define READ_BATCH 16 + +/* + * Each offset in the file has the offset / sizeof(int) stored for every + * sizeof(int) address. + */ +static int verify_buf(void *buf, size_t size, off_t off) +{ + int i, u_in_buf = size / sizeof(unsigned int); + unsigned int *ptr; + + off /= sizeof(unsigned int); + ptr = buf; + for (i = 0; i < u_in_buf; i++) { + if (off != *ptr) { + fprintf(stderr, "Found %u, wanted %lu\n", *ptr, off); + return 1; + } + ptr++; + off++; + } + + return 0; +} + +enum { + PUNCH_NONE, + PUNCH_FRONT, + PUNCH_MIDDLE, + PUNCH_END, +}; + +/* + * For each chunk in file, DONTNEED a start, end, or middle segment of it. + * We enter here with the file fully cached every time, either freshly + * written or after other reads. This forces (at least) the buffered reads + * to be handled incrementally, exercising that path. + */ +static int do_punch(int fd) +{ + off_t offset = 0; + int punch_type; + + while (offset + CHUNK_SIZE <= FSIZE) { + off_t punch_off; + + punch_type = rand() % (PUNCH_END + 1); + switch (punch_type) { + default: + case PUNCH_NONE: + punch_off = -1; /* gcc... */ + break; + case PUNCH_FRONT: + punch_off = offset; + break; + case PUNCH_MIDDLE: + punch_off = offset + PUNCH_SIZE; + break; + case PUNCH_END: + punch_off = offset + CHUNK_SIZE - PUNCH_SIZE; + break; + } + + offset += CHUNK_SIZE; + if (punch_type == PUNCH_NONE) + continue; + if (posix_fadvise(fd, punch_off, PUNCH_SIZE, POSIX_FADV_DONTNEED) < 0) { + perror("posix_fadivse"); + return 1; + } + } + + return 0; +} + +static int test(struct io_uring *ring, const char *fname, int buffered, + int vectored, int small_vecs, int registered) +{ + struct iovec vecs[READ_BATCH][MAX_VECS]; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + void *buf[READ_BATCH]; + int ret, fd, flags; + int i, j, nr_vecs; + off_t off, voff; + size_t left; + + if (registered) + assert(!vectored && !small_vecs); + + flags = O_RDONLY; + if (!buffered) + flags |= O_DIRECT; + fd = open(fname, flags); + if (fd < 0) { + perror("open"); + return 1; + } + + if (do_punch(fd)) + return 1; + + if (vectored) { + if (small_vecs) + nr_vecs = MIN_VECS; + else + nr_vecs = MAX_VECS; + + for (j = 0; j < READ_BATCH; j++) { + for (i = 0; i < nr_vecs; i++) { + void *ptr; + + t_posix_memalign(&ptr, 4096, CHUNK_SIZE / nr_vecs); + vecs[j][i].iov_base = ptr; + vecs[j][i].iov_len = CHUNK_SIZE / nr_vecs; + } + } + } else { + for (j = 0; j < READ_BATCH; j++) + t_posix_memalign(&buf[j], 4096, CHUNK_SIZE); + nr_vecs = 0; + } + + if (registered) { + struct iovec v[READ_BATCH]; + + for (i = 0; i < READ_BATCH; i++) { + v[i].iov_base = buf[i]; + v[i].iov_len = CHUNK_SIZE; + } + ret = io_uring_register_buffers(ring, v, READ_BATCH); + if (ret) { + fprintf(stderr, "Error buffer reg %d\n", ret); + goto err; + } + } + + i = 0; + left = FSIZE; + off = 0; + while (left) { + int pending = 0; + + for (i = 0; i < READ_BATCH; i++) { + size_t this = left; + + if (this > CHUNK_SIZE) + this = CHUNK_SIZE; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + if (vectored) { + io_uring_prep_readv(sqe, fd, vecs[i], nr_vecs, off); + } else { + if (registered) + io_uring_prep_read_fixed(sqe, fd, buf[i], this, off, i); + else + io_uring_prep_read(sqe, fd, buf[i], this, off); + } + sqe->user_data = (off << 32) | i; + off += this; + left -= this; + pending++; + if (!left) + break; + } + + ret = io_uring_submit(ring); + if (ret != pending) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + for (i = 0; i < pending; i++) { + int index; + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + if (cqe->res < 0) { + fprintf(stderr, "bad read %d, read %d\n", cqe->res, i); + goto err; + } + index = cqe->user_data & 0xffffffff; + voff = cqe->user_data >> 32; + io_uring_cqe_seen(ring, cqe); + if (vectored) { + for (j = 0; j < nr_vecs; j++) { + void *buf = vecs[index][j].iov_base; + size_t len = vecs[index][j].iov_len; + + if (verify_buf(buf, len, voff)) + goto err; + voff += len; + } + } else { + if (verify_buf(buf[index], CHUNK_SIZE, voff)) + goto err; + } + } + } + + ret = 0; +done: + if (registered) + io_uring_unregister_buffers(ring); + if (vectored) { + for (j = 0; j < READ_BATCH; j++) + for (i = 0; i < nr_vecs; i++) + free(vecs[j][i].iov_base); + } else { + for (j = 0; j < READ_BATCH; j++) + free(buf[j]); + } + close(fd); + return ret; +err: + ret = 1; + goto done; +} + +static int fill_pattern(const char *fname) +{ + size_t left = FSIZE; + unsigned int val, *ptr; + void *buf; + int fd, i; + + fd = open(fname, O_WRONLY); + if (fd < 0) { + perror("open"); + return 1; + } + + val = 0; + buf = t_malloc(4096); + while (left) { + int u_in_buf = 4096 / sizeof(val); + size_t this = left; + + if (this > 4096) + this = 4096; + ptr = buf; + for (i = 0; i < u_in_buf; i++) { + *ptr = val; + val++; + ptr++; + } + if (write(fd, buf, 4096) != 4096) + return 1; + left -= 4096; + } + + fsync(fd); + close(fd); + free(buf); + return 0; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + const char *fname; + char buf[32]; + int ret; + + srand(getpid()); + + if (argc > 1) { + fname = argv[1]; + } else { + sprintf(buf, ".file-verify.%d", getpid()); + fname = buf; + t_create_file(fname, FSIZE); + } + + ret = io_uring_queue_init(READ_BATCH, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + goto err; + } + + if (fill_pattern(fname)) + goto err; + + ret = test(&ring, fname, 1, 0, 0, 0); + if (ret) { + fprintf(stderr, "Buffered novec test failed\n"); + goto err; + } + ret = test(&ring, fname, 1, 0, 0, 1); + if (ret) { + fprintf(stderr, "Buffered novec reg test failed\n"); + goto err; + } + ret = test(&ring, fname, 1, 1, 0, 0); + if (ret) { + fprintf(stderr, "Buffered vec test failed\n"); + goto err; + } + ret = test(&ring, fname, 1, 1, 1, 0); + if (ret) { + fprintf(stderr, "Buffered small vec test failed\n"); + goto err; + } + + ret = test(&ring, fname, 0, 0, 0, 0); + if (ret) { + fprintf(stderr, "O_DIRECT novec test failed\n"); + goto err; + } + ret = test(&ring, fname, 0, 0, 0, 1); + if (ret) { + fprintf(stderr, "O_DIRECT novec reg test failed\n"); + goto err; + } + ret = test(&ring, fname, 0, 1, 0, 0); + if (ret) { + fprintf(stderr, "O_DIRECT vec test failed\n"); + goto err; + } + ret = test(&ring, fname, 0, 1, 1, 0); + if (ret) { + fprintf(stderr, "O_DIRECT small vec test failed\n"); + goto err; + } + + if (buf == fname) + unlink(fname); + return 0; +err: + if (buf == fname) + unlink(fname); + return 1; +} -- cgit v1.2.3 From db0175faa852d7741df6fe9eaadd3d28af84e3e6 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 15 Sep 2021 19:26:14 -0600 Subject: test/socket-rw-eagain: ignore if FASTPOLL is available Signed-off-by: Jens Axboe --- test/socket-rw-eagain.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/socket-rw-eagain.c b/test/socket-rw-eagain.c index f15c0c1..cc87aca 100644 --- a/test/socket-rw-eagain.c +++ b/test/socket-rw-eagain.c @@ -92,10 +92,14 @@ int main(int argc, char *argv[]) } struct io_uring m_io_uring; + struct io_uring_params p = { }; - ret = io_uring_queue_init(32, &m_io_uring, 0); + ret = io_uring_queue_init_params(32, &m_io_uring, &p); assert(ret >= 0); + if (p.features & IORING_FEAT_FAST_POLL) + return 0; + char recv_buff[128]; char send_buff[128]; -- cgit v1.2.3 From 2ed672144e7b8bcaa3cf99698a3b9aa3a8d85b08 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 16 Sep 2021 09:04:39 -0600 Subject: test/file-verify: add verification for truncated end-of-file read Attempt to read beyond the end-of-file or device, which will cause the iterator to become truncated. Do this with both the first and second half of that last chunk invalidated, so we hit retry. We fill that last chunk with known data and validate it on read completion. Signed-off-by: Jens Axboe --- test/file-verify.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/test/file-verify.c b/test/file-verify.c index ffedd87..f5749a6 100644 --- a/test/file-verify.c +++ b/test/file-verify.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include "helpers.h" #include "liburing.h" @@ -52,6 +55,142 @@ static int verify_buf(void *buf, size_t size, off_t off) return 0; } +static int test_truncate(struct io_uring *ring, const char *fname, int buffered, + int vectored) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + struct iovec vec; + struct stat sb; + off_t punch_off, off, file_size; + void *buf = NULL; + int u_in_buf, i, ret, fd, first_pass = 1; + unsigned int *ptr; + + if (buffered) + fd = open(fname, O_RDWR); + else + fd = open(fname, O_DIRECT | O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + + if (fstat(fd, &sb) < 0) { + perror("stat"); + close(fd); + return 1; + } + + if (S_ISREG(sb.st_mode)) { + file_size = sb.st_size; + } else if (S_ISBLK(sb.st_mode)) { + unsigned long long bytes; + + if (ioctl(fd, BLKGETSIZE64, &bytes) < 0) { + perror("ioctl"); + close(fd); + return 1; + } + file_size = bytes; + } else { + goto out; + } + + if (file_size < CHUNK_SIZE) + goto out; + + t_posix_memalign(&buf, 4096, CHUNK_SIZE); + + off = file_size - (CHUNK_SIZE / 2); + punch_off = off + CHUNK_SIZE / 4; + + u_in_buf = CHUNK_SIZE / sizeof(unsigned int); + ptr = buf; + for (i = 0; i < u_in_buf; i++) { + *ptr = i; + ptr++; + } + ret = pwrite(fd, buf, CHUNK_SIZE / 2, off); + if (ret < 0) { + perror("pwrite"); + goto err; + } else if (ret != CHUNK_SIZE / 2) + goto out; + +again: + /* + * Read in last bit of file so it's known cached, then remove half of that + * last bit so we get a short read that needs retry + */ + ret = pread(fd, buf, CHUNK_SIZE / 2, off); + if (ret < 0) { + perror("pread"); + goto err; + } else if (ret != CHUNK_SIZE / 2) + goto out; + + if (posix_fadvise(fd, punch_off, CHUNK_SIZE / 4, POSIX_FADV_DONTNEED) < 0) { + perror("posix_fadivse"); + goto err; + } + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + if (vectored) { + vec.iov_base = buf; + vec.iov_len = CHUNK_SIZE; + io_uring_prep_readv(sqe, fd, &vec, 1, off); + } else { + io_uring_prep_read(sqe, fd, buf, CHUNK_SIZE, off); + } + memset(buf, 0, CHUNK_SIZE); + + ret = io_uring_submit(ring); + if (ret != 1) { + fprintf(stderr, "Submit failed %d\n", ret); + goto err; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + + ret = cqe->res; + io_uring_cqe_seen(ring, cqe); + if (ret != CHUNK_SIZE / 2) { + fprintf(stderr, "Unexpected truncated read %d\n", ret); + goto err; + } + + if (verify_buf(buf, CHUNK_SIZE / 2, 0)) + goto err; + + /* + * Repeat, but punch first part instead of last + */ + if (first_pass) { + punch_off = file_size - CHUNK_SIZE / 4; + first_pass = 0; + goto again; + } + +out: + free(buf); + close(fd); + return 0; +err: + free(buf); + close(fd); + return 1; +} + enum { PUNCH_NONE, PUNCH_FRONT, @@ -360,6 +499,28 @@ int main(int argc, char *argv[]) goto err; } + ret = test_truncate(&ring, fname, 1, 0); + if (ret) { + fprintf(stderr, "Buffered end truncate read failed\n"); + goto err; + } + ret = test_truncate(&ring, fname, 1, 1); + if (ret) { + fprintf(stderr, "Buffered end truncate vec read failed\n"); + goto err; + } + + ret = test_truncate(&ring, fname, 0, 0); + if (ret) { + fprintf(stderr, "O_DIRECT end truncate read failed\n"); + goto err; + } + ret = test_truncate(&ring, fname, 0, 1); + if (ret) { + fprintf(stderr, "O_DIRECT end truncate vec read failed\n"); + goto err; + } + if (buf == fname) unlink(fname); return 0; -- cgit v1.2.3 From 0e81b83dbac6da6715186210c7e65315456e2d6e Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 16 Sep 2021 11:31:42 +0700 Subject: .gitignore: add `test/file-verify` Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 45f3cde..fb3a859 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ /test/fc2a85cb02ef-test /test/file-register /test/file-update +/test/file-verify /test/files-exit-hang-poll /test/files-exit-hang-timeout /test/fixed-link -- cgit v1.2.3 From 64bcc40862b20d25efde357422e2dc76c9985c77 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 16 Sep 2021 11:27:31 +0700 Subject: test/file-verify: fix 32-bit build -Werror=shift-count-overflow `off_t` may not always be 64-bit in size. ``` file-verify.c: In function 'test': file-verify.c:193:26: error: left shift count >= width of type [-Werror=shift-count-overflow] sqe->user_data = (off << 32) | i; ^ cc1: all warnings being treated as errors Makefile:164: recipe for target 'file-verify' failed make[1]: *** [file-verify] Error 1 make[1]: Leaving directory '/root/liburing/test' Makefile:12: recipe for target 'all' failed make: *** [all] Error 2 ``` Fix this by using (uint64_t) cast. Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- test/file-verify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/file-verify.c b/test/file-verify.c index f5749a6..0a0b5e9 100644 --- a/test/file-verify.c +++ b/test/file-verify.c @@ -329,7 +329,7 @@ static int test(struct io_uring *ring, const char *fname, int buffered, else io_uring_prep_read(sqe, fd, buf[i], this, off); } - sqe->user_data = (off << 32) | i; + sqe->user_data = ((uint64_t)off << 32) | i; off += this; left -= this; pending++; -- cgit v1.2.3 From d68917b4207bd9a6d39a5b87109e9cfdde574878 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 16 Sep 2021 09:26:59 -0600 Subject: man/io_uring.7: clarify how success and error returns are propagated Also make it clear that IORING_OP_READ isn't a direct match for read(2), rather it's a mix of pread(2) and preadv2(2) in that it both takes an explicit file offset, and also supports using -1 for that offset to indicate that the current file position should be used. Fixes: https://github.com/axboe/liburing/issues/435 Signed-off-by: Jens Axboe --- man/io_uring.7 | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/man/io_uring.7 b/man/io_uring.7 index 972683b..dc76f42 100644 --- a/man/io_uring.7 +++ b/man/io_uring.7 @@ -84,17 +84,35 @@ a read operation under .BR io_uring , started with the .BR IORING_OP_READ -operation, -which issues the equivalent of the +operation, issues the equivalent of the .BR read (2) -system call, -would return as part of +system call. In practice, it mixes the semantics of +.BR pread (2) +and +.BR preadv2 (2) +in that it takes an explicit offset, and supports using -1 for the offset to +indicate that the current file position should be used instead of passing in +an explicit offset. See the opcode documentation for more details. Given that +io_uring is an async interface, +.I errno +is never used for passing back error information. Instead, .I res -what -.BR read (2) -would have returned if called directly, -without using -.BR io_uring . +will contain what the equivalent system call would have returned in case +of success, and in case of error +.I res +will contain +.I -errno . +For example, if the normal read system call would have returned -1 and set +.I errno +to +.B EINVAL , +then +.I res +would contain +.B -EINVAL . +If the normal system call would have returned a read size of 1024, then +.I res +would contain 1024. .IP \(bu Optionally, .BR io_uring_enter (2) -- cgit v1.2.3 From d06c81aa3c170b586b09a88ebcd2c04f3106bd44 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 16 Sep 2021 10:02:17 -0600 Subject: test/file-verify: add provide buffers test case This is another invariant where we provide buffers to the ring, and then have the read operation auto-select the buffer based on the buffer index specified. Signed-off-by: Jens Axboe --- test/file-verify.c | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/test/file-verify.c b/test/file-verify.c index 0a0b5e9..201306b 100644 --- a/test/file-verify.c +++ b/test/file-verify.c @@ -56,7 +56,7 @@ static int verify_buf(void *buf, size_t size, off_t off) } static int test_truncate(struct io_uring *ring, const char *fname, int buffered, - int vectored) + int vectored, int provide_buf) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -135,6 +135,27 @@ again: goto err; } + if (provide_buf) { + sqe = io_uring_get_sqe(ring); + io_uring_prep_provide_buffers(sqe, buf, CHUNK_SIZE, 1, 0, 0); + ret = io_uring_submit(ring); + if (ret != 1) { + fprintf(stderr, "submit failed %d\n", ret); + goto err; + } + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + ret = cqe->res; + io_uring_cqe_seen(ring, cqe); + if (ret) { + fprintf(stderr, "Provide buffer failed %d\n", ret); + goto err; + } + } + sqe = io_uring_get_sqe(ring); if (!sqe) { fprintf(stderr, "get sqe failed\n"); @@ -142,11 +163,17 @@ again: } if (vectored) { + assert(!provide_buf); vec.iov_base = buf; vec.iov_len = CHUNK_SIZE; io_uring_prep_readv(sqe, fd, &vec, 1, off); } else { - io_uring_prep_read(sqe, fd, buf, CHUNK_SIZE, off); + if (provide_buf) { + io_uring_prep_read(sqe, fd, NULL, CHUNK_SIZE, off); + sqe->flags |= IOSQE_BUFFER_SELECT; + } else { + io_uring_prep_read(sqe, fd, buf, CHUNK_SIZE, off); + } } memset(buf, 0, CHUNK_SIZE); @@ -499,27 +526,37 @@ int main(int argc, char *argv[]) goto err; } - ret = test_truncate(&ring, fname, 1, 0); + ret = test_truncate(&ring, fname, 1, 0, 0); if (ret) { fprintf(stderr, "Buffered end truncate read failed\n"); goto err; } - ret = test_truncate(&ring, fname, 1, 1); + ret = test_truncate(&ring, fname, 1, 1, 0); if (ret) { fprintf(stderr, "Buffered end truncate vec read failed\n"); goto err; } + ret = test_truncate(&ring, fname, 1, 0, 1); + if (ret) { + fprintf(stderr, "Buffered end truncate pbuf read failed\n"); + goto err; + } - ret = test_truncate(&ring, fname, 0, 0); + ret = test_truncate(&ring, fname, 0, 0, 0); if (ret) { fprintf(stderr, "O_DIRECT end truncate read failed\n"); goto err; } - ret = test_truncate(&ring, fname, 0, 1); + ret = test_truncate(&ring, fname, 0, 1, 0); if (ret) { fprintf(stderr, "O_DIRECT end truncate vec read failed\n"); goto err; } + ret = test_truncate(&ring, fname, 0, 0, 1); + if (ret) { + fprintf(stderr, "O_DIRECT end truncate pbuf read failed\n"); + goto err; + } if (buf == fname) unlink(fname); -- cgit v1.2.3 From d859ae0dd023dd37a12be30bfe0a7bca6dd4140a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 16 Sep 2021 12:04:29 -0600 Subject: test/file-verify: add provide buffers support for main test too Signed-off-by: Jens Axboe --- test/file-verify.c | 86 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 13 deletions(-) diff --git a/test/file-verify.c b/test/file-verify.c index 201306b..50cad45 100644 --- a/test/file-verify.c +++ b/test/file-verify.c @@ -268,8 +268,42 @@ static int do_punch(int fd) return 0; } +static int provide_buffers(struct io_uring *ring, void **buf) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int i, ret; + + /* real use case would have one buffer chopped up, but... */ + for (i = 0; i < READ_BATCH; i++) { + sqe = io_uring_get_sqe(ring); + io_uring_prep_provide_buffers(sqe, buf[i], CHUNK_SIZE, 1, 0, i); + } + + ret = io_uring_submit(ring); + if (ret != READ_BATCH) { + fprintf(stderr, "Submit failed %d\n", ret); + return 1; + } + + for (i = 0; i < READ_BATCH; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "wait cqe %d\n", ret); + return 1; + } + if (cqe->res < 0) { + fprintf(stderr, "cqe res provide %d\n", cqe->res); + return 1; + } + io_uring_cqe_seen(ring, cqe); + } + + return 0; +} + static int test(struct io_uring *ring, const char *fname, int buffered, - int vectored, int small_vecs, int registered) + int vectored, int small_vecs, int registered, int provide) { struct iovec vecs[READ_BATCH][MAX_VECS]; struct io_uring_cqe *cqe; @@ -280,8 +314,14 @@ static int test(struct io_uring *ring, const char *fname, int buffered, off_t off, voff; size_t left; - if (registered) + if (registered) { + assert(!provide); assert(!vectored && !small_vecs); + } + if (provide) { + assert(!registered); + assert(!vectored && !small_vecs); + } flags = O_RDONLY; if (!buffered) @@ -336,6 +376,9 @@ static int test(struct io_uring *ring, const char *fname, int buffered, while (left) { int pending = 0; + if (provide && provide_buffers(ring, buf)) + goto err; + for (i = 0; i < READ_BATCH; i++) { size_t this = left; @@ -351,10 +394,14 @@ static int test(struct io_uring *ring, const char *fname, int buffered, if (vectored) { io_uring_prep_readv(sqe, fd, vecs[i], nr_vecs, off); } else { - if (registered) + if (registered) { io_uring_prep_read_fixed(sqe, fd, buf[i], this, off, i); - else + } else if (provide) { + io_uring_prep_read(sqe, fd, NULL, this, off); + sqe->flags |= IOSQE_BUFFER_SELECT; + } else { io_uring_prep_read(sqe, fd, buf[i], this, off); + } } sqe->user_data = ((uint64_t)off << 32) | i; off += this; @@ -382,7 +429,10 @@ static int test(struct io_uring *ring, const char *fname, int buffered, fprintf(stderr, "bad read %d, read %d\n", cqe->res, i); goto err; } - index = cqe->user_data & 0xffffffff; + if (cqe->flags & IORING_CQE_F_BUFFER) + index = cqe->flags >> 16; + else + index = cqe->user_data & 0xffffffff; voff = cqe->user_data >> 32; io_uring_cqe_seen(ring, cqe); if (vectored) { @@ -484,43 +534,53 @@ int main(int argc, char *argv[]) if (fill_pattern(fname)) goto err; - ret = test(&ring, fname, 1, 0, 0, 0); + ret = test(&ring, fname, 1, 0, 0, 0, 0); if (ret) { fprintf(stderr, "Buffered novec test failed\n"); goto err; } - ret = test(&ring, fname, 1, 0, 0, 1); + ret = test(&ring, fname, 1, 0, 0, 1, 0); if (ret) { fprintf(stderr, "Buffered novec reg test failed\n"); goto err; } - ret = test(&ring, fname, 1, 1, 0, 0); + ret = test(&ring, fname, 1, 0, 0, 0, 1); + if (ret) { + fprintf(stderr, "Buffered novec provide test failed\n"); + goto err; + } + ret = test(&ring, fname, 1, 1, 0, 0, 0); if (ret) { fprintf(stderr, "Buffered vec test failed\n"); goto err; } - ret = test(&ring, fname, 1, 1, 1, 0); + ret = test(&ring, fname, 1, 1, 1, 0, 0); if (ret) { fprintf(stderr, "Buffered small vec test failed\n"); goto err; } - ret = test(&ring, fname, 0, 0, 0, 0); + ret = test(&ring, fname, 0, 0, 0, 0, 0); if (ret) { fprintf(stderr, "O_DIRECT novec test failed\n"); goto err; } - ret = test(&ring, fname, 0, 0, 0, 1); + ret = test(&ring, fname, 0, 0, 0, 1, 0); if (ret) { fprintf(stderr, "O_DIRECT novec reg test failed\n"); goto err; } - ret = test(&ring, fname, 0, 1, 0, 0); + ret = test(&ring, fname, 0, 0, 0, 0, 1); + if (ret) { + fprintf(stderr, "O_DIRECT novec provide test failed\n"); + goto err; + } + ret = test(&ring, fname, 0, 1, 0, 0, 0); if (ret) { fprintf(stderr, "O_DIRECT vec test failed\n"); goto err; } - ret = test(&ring, fname, 0, 1, 1, 0); + ret = test(&ring, fname, 0, 1, 1, 0, 0); if (ret) { fprintf(stderr, "O_DIRECT small vec test failed\n"); goto err; -- cgit v1.2.3 From dd5b44c509c9833da8bd283c3857b41bfe8bafe8 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 18 Sep 2021 05:14:47 +0700 Subject: .github/workflows/build.yml: add 32-bit build Signed-off-by: Ammar Faizi --- .github/workflows/build.yml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f82d0e6..a8c0503 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,17 +27,26 @@ jobs: - name: Display compiler versions run: | - ${{matrix.cc}} --version - ${{matrix.cxx}} --version + ${{matrix.cc}} --version; + ${{matrix.cxx}} --version; - name: Build run: | - ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} + ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}}; make V=1 -j$(nproc) \ CPPFLAGS="-Werror" \ CFLAGS="$FLAGS" \ - CXXFLAGS="$FLAGS" + CXXFLAGS="$FLAGS"; + + - name: Build (32 bit) + run: | + sudo apt-get install libc6-dev-i386 gcc-multilib g++-multilib -y; + make clean; + make V=1 -j$(nproc) \ + CPPFLAGS="-Werror" \ + CFLAGS="$FLAGS -m32" \ + CXXFLAGS="$FLAGS -m32"; - name: Test install command run: | - sudo make install + sudo make install; -- cgit v1.2.3 From a4a314a56d723385d3cbe8cdeac36da3fef40d42 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 18 Sep 2021 05:12:18 -0600 Subject: io_uring.h: include recent 5.15-git addition of exported worker type Applications can index the array they pass in to IORING_REGISTER_IOWQ_MAX_WORKERS instead of using non-specific 0 and 1 values for bound/unbound. Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 69f23a9..7aa43fc 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -321,13 +321,19 @@ enum { IORING_REGISTER_IOWQ_AFF = 17, IORING_UNREGISTER_IOWQ_AFF = 18, - /* set/get max number of async workers */ + /* set/get max number of io-wq workers */ IORING_REGISTER_IOWQ_MAX_WORKERS = 19, /* this goes last */ IORING_REGISTER_LAST }; +/* io-wq worker categories */ +enum { + IO_WQ_BOUND, + IO_WQ_UNBOUND, +}; + /* deprecated, see struct io_uring_rsrc_update */ struct io_uring_files_update { __u32 offset; -- cgit v1.2.3 From d9743fec01714a3ea5352db312564a5b3d6ff36d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 18 Sep 2021 16:18:37 -0600 Subject: src/register: automatically increase RLIMIT_NOFILE, if necessary A recent change, that also hit stable, means that any file table sizing will be under RLIMIT_NOFILE as well. We can just adjust this as needed if someone wants to register a fileset and the count is larger than RLIMIT_NOFILE rlim_cur. If it's beyond rlim_max, then we return -EMFILE as the kernel would have done. Reported-by: Victor Stewart Signed-off-by: Jens Axboe --- src/register.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/register.c b/src/register.c index a4e8c37..bab42d0 100644 --- a/src/register.c +++ b/src/register.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -118,6 +119,21 @@ int io_uring_register_files_update(struct io_uring *ring, unsigned off, return ret; } +static int bump_rlimit_nofile(unsigned nr) +{ + struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) + return -errno; + if (rlim.rlim_cur < nr) { + if (nr > rlim.rlim_max) + return -EMFILE; + rlim.rlim_cur = nr; + setrlimit(RLIMIT_NOFILE, &rlim); + } + + return 0; +} int io_uring_register_files_tags(struct io_uring *ring, const int *files, const __u64 *tags, @@ -130,6 +146,10 @@ int io_uring_register_files_tags(struct io_uring *ring, }; int ret; + ret = bump_rlimit_nofile(nr); + if (ret) + return ret; + ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_FILES2, ®, sizeof(reg)); return ret < 0 ? -errno : ret; @@ -140,6 +160,10 @@ int io_uring_register_files(struct io_uring *ring, const int *files, { int ret; + ret = bump_rlimit_nofile(nr_files); + if (ret) + return ret; + ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_FILES, files, nr_files); if (ret < 0) -- cgit v1.2.3 From 8de1e67876468f1ba123af7266ecf3d5ad57995b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 19 Sep 2021 08:07:32 -0600 Subject: man/io_uring_enter.2: correct IORING_OP_SHUTDOWN description We do take 2 arguments, both fd and how. Make sure the man page is correct. Fixes: https://github.com/axboe/liburing/issues/437 Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 6b31061..73c4959 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -896,8 +896,11 @@ Issue the equivalent of a .BR shutdown(2) system call. .I fd -is the file descriptor to the socket being shutdown, no other fields should -be set. Available since 5.11. +is the file descriptor to the socket being shutdown, and +.I len +must be set to the +.I how +argument. No no other fields should be set. Available since 5.11. .TP .B IORING_OP_RENAMEAT -- cgit v1.2.3 From 98db8e883c0fedcfbf74ba7922821ff3be0e7c98 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 19 Sep 2021 08:15:07 -0600 Subject: src/register: improve RLIMIT_NOFILE increase Only do it if we run into EMFILE, seems like the prudent thing to do, avoiding any getrlimit checking if the operation succeeds. And more importantly, add to the rlim_cur, don't just set it to what we need. Signed-off-by: Jens Axboe --- src/register.c | 55 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/register.c b/src/register.c index bab42d0..5ea4331 100644 --- a/src/register.c +++ b/src/register.c @@ -119,16 +119,14 @@ int io_uring_register_files_update(struct io_uring *ring, unsigned off, return ret; } -static int bump_rlimit_nofile(unsigned nr) +static int increase_rlimit_nofile(unsigned nr) { struct rlimit rlim; if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) return -errno; if (rlim.rlim_cur < nr) { - if (nr > rlim.rlim_max) - return -EMFILE; - rlim.rlim_cur = nr; + rlim.rlim_cur += nr; setrlimit(RLIMIT_NOFILE, &rlim); } @@ -144,32 +142,45 @@ int io_uring_register_files_tags(struct io_uring *ring, .data = (unsigned long)files, .tags = (unsigned long)tags, }; - int ret; - - ret = bump_rlimit_nofile(nr); - if (ret) - return ret; + int ret, did_increase = 0; + + do { + ret = __sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_FILES2, ®, + sizeof(reg)); + if (ret >= 0) + break; + if (errno == EMFILE && !did_increase) { + did_increase = 1; + increase_rlimit_nofile(nr); + continue; + } + break; + } while (1); - ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_FILES2, - ®, sizeof(reg)); return ret < 0 ? -errno : ret; } int io_uring_register_files(struct io_uring *ring, const int *files, unsigned nr_files) { - int ret; - - ret = bump_rlimit_nofile(nr_files); - if (ret) - return ret; + int ret, did_increase = 0; + + do { + ret = __sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_FILES, files, + nr_files); + if (ret >= 0) + break; + if (errno == EMFILE && !did_increase) { + did_increase = 1; + increase_rlimit_nofile(nr_files); + continue; + } + break; + } while (1); - ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_FILES, - files, nr_files); - if (ret < 0) - return -errno; - - return 0; + return ret < 0 ? -errno : ret; } int io_uring_unregister_files(struct io_uring *ring) -- cgit v1.2.3 From f8caf73d304461931feac70aa5cc48a36c0c78a2 Mon Sep 17 00:00:00 2001 From: godzie44 Date: Thu, 23 Sep 2021 13:30:51 +0300 Subject: test/nop-all-sizes.c: del some unnecessary checks Signed-off-by: Derevtsov Konstantin --- test/nop-all-sizes.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/nop-all-sizes.c b/test/nop-all-sizes.c index 49b8642..e8e4b9d 100644 --- a/test/nop-all-sizes.c +++ b/test/nop-all-sizes.c @@ -37,10 +37,6 @@ static int test_nops(struct io_uring *ring) int ret, nr, total = 0, i; nr = fill_nops(ring); - if (nr < 0) { - fprintf(stderr, "Fill: %d\n", nr); - goto err; - } ret = io_uring_submit(ring); if (ret != nr) { @@ -50,10 +46,6 @@ static int test_nops(struct io_uring *ring) total += ret; nr = fill_nops(ring); - if (nr < 0) { - fprintf(stderr, "Fill: %d\n", nr); - goto err; - } ret = io_uring_submit(ring); if (ret != nr) { -- cgit v1.2.3 From c3e3669838395cf17cd161890b0ee1c0d60ec373 Mon Sep 17 00:00:00 2001 From: godzie44 Date: Thu, 23 Sep 2021 13:33:11 +0300 Subject: test/probe.c: fix typo in assert output Signed-off-by: Derevtsov Konstantin --- test/probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/probe.c b/test/probe.c index c7fc053..29239ff 100644 --- a/test/probe.c +++ b/test/probe.c @@ -36,7 +36,7 @@ static int verify_probe(struct io_uring_probe *p, int full) return 1; } if (!(p->ops[IORING_OP_WRITE].flags & IO_URING_OP_SUPPORTED)) { - fprintf(stderr, "READV not supported!?\n"); + fprintf(stderr, "WRITE not supported!?\n"); return 1; } -- cgit v1.2.3 From ca9252f5f83d2497fa56aea559c774763b39ac4b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 23 Sep 2021 15:19:31 -0600 Subject: src/queue: only enter the kernel if both submit and need_enter are true We just take the submit count, and then unconditionally just call sq_ring_needs_enter() to ensure that flags are set appropriately. Only set need_enter for the submit side if sq_ring_needs_enter() is true, which may not be the case if SQPOLL is used. This can avoid a system call if we're not waiting on any CQEs, and the thread is already running. Reported-by: Olivier Langlois Link: https://github.com/axboe/liburing/issues/429#issuecomment-926069364 Signed-off-by: Jens Axboe --- src/queue.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/queue.c b/src/queue.c index 5d2c2a5..10ef31c 100644 --- a/src/queue.c +++ b/src/queue.c @@ -112,10 +112,8 @@ static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_pt flags = IORING_ENTER_GETEVENTS | data->get_flags; need_enter = true; } - if (data->submit) { - sq_ring_needs_enter(ring, &flags); + if (data->submit && sq_ring_needs_enter(ring, &flags)) need_enter = true; - } if (!need_enter) break; -- cgit v1.2.3 From e1a619775bbabd65821659d75e96b030ca830c08 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 24 Sep 2021 20:05:16 +0100 Subject: tests: improve multicqe_drain Small improvements for multicqe_drain test. - close pipes - use a helper for multishot poll - don't touch cqe after io_uring_cqe_seen() Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/3ab7e2b2e52dba8dff11253b2b7ea3f57074c24e.1632507515.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/multicqes_drain.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/multicqes_drain.c b/test/multicqes_drain.c index d04cf37..b107a48 100644 --- a/test/multicqes_drain.c +++ b/test/multicqes_drain.c @@ -288,9 +288,9 @@ static int test_simple_drain(struct io_uring *ring) } } - io_uring_prep_poll_add(sqe[0], pipe1[0], POLLIN); - sqe[0]->len |= IORING_POLL_ADD_MULTI; + io_uring_prep_poll_multishot(sqe[0], pipe1[0], POLLIN); sqe[0]->user_data = 0; + io_uring_prep_poll_add(sqe[1], pipe2[0], POLLIN); sqe[1]->user_data = 1; @@ -320,6 +320,7 @@ static int test_simple_drain(struct io_uring *ring) io_uring_prep_poll_remove(sqe[0], 0); sqe[0]->user_data = 2; + io_uring_prep_nop(sqe[1]); sqe[1]->flags |= IOSQE_IO_DRAIN; sqe[1]->user_data = 3; @@ -333,18 +334,21 @@ static int test_simple_drain(struct io_uring *ring) goto err; } - for (i = 0; i < 6; i++) { ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { printf("wait completion %d\n", ret); goto err; } - io_uring_cqe_seen(ring, cqe); if ((i == 5) && (cqe->user_data != 3)) goto err; + io_uring_cqe_seen(ring, cqe); } + close(pipe1[0]); + close(pipe1[1]); + close(pipe2[0]); + close(pipe2[1]); return 0; err: return 1; -- cgit v1.2.3 From 01396b738ef8fe58c14d93015afd1c9420a8b2a8 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 24 Sep 2021 20:05:17 +0100 Subject: tests: match kernel and pass fds in s32[] Follow the kernel ABI and pass fds in an array of s32 but not just ints. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/260526556a2a44c833e2265ba59e5d2705ce8870.1632507515.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/rsrc_tags.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rsrc_tags.c b/test/rsrc_tags.c index a3fec0c..f441b5c 100644 --- a/test/rsrc_tags.c +++ b/test/rsrc_tags.c @@ -322,7 +322,7 @@ static int test_files(int ring_flags) struct io_uring ring; const int nr = 50; int off = 5, i, ret, fd; - int files[nr]; + __s32 files[nr]; __u64 tags[nr], tag; for (i = 0; i < nr; ++i) { -- cgit v1.2.3 From 1a1ae01c147cb7da604c1d4eebdca41d7adc3959 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 24 Sep 2021 20:07:30 +0100 Subject: tests: test close with fixed file table Test IO_CLOSE closing files in the fixed file table. Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- test/open-close.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/test/open-close.c b/test/open-close.c index 648737c..d5c116b 100644 --- a/test/open-close.c +++ b/test/open-close.c @@ -9,10 +9,119 @@ #include #include #include +#include #include "helpers.h" #include "liburing.h" +static int submit_wait(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + int ret; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + return 1; + } + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + return 1; + } + + ret = cqe->res; + io_uring_cqe_seen(ring, cqe); + return ret; +} + +static inline int try_close(struct io_uring *ring, int fd, int slot) +{ + struct io_uring_sqe *sqe; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_close(sqe, fd); + __io_uring_set_target_fixed_file(sqe, slot); + return submit_wait(ring); +} + +static int test_close_fixed(void) +{ + struct io_uring ring; + struct io_uring_sqe *sqe; + int ret, fds[2]; + char buf[1]; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed\n"); + return -1; + } + if (pipe(fds)) { + perror("pipe"); + return -1; + } + + ret = try_close(&ring, 0, 0); + if (ret == -EINVAL) { + fprintf(stderr, "close for fixed files is not supported\n"); + return 0; + } else if (ret != -ENXIO) { + fprintf(stderr, "no table failed %i\n", ret); + return -1; + } + + ret = try_close(&ring, 1, 0); + if (ret != -EINVAL) { + fprintf(stderr, "set fd failed %i\n", ret); + return -1; + } + + ret = io_uring_register_files(&ring, fds, 2); + if (ret) { + fprintf(stderr, "file_register: %d\n", ret); + return ret; + } + + ret = try_close(&ring, 0, 2); + if (ret != -EINVAL) { + fprintf(stderr, "out of table failed %i\n", ret); + return -1; + } + + ret = try_close(&ring, 0, 0); + if (ret != 0) { + fprintf(stderr, "close failed %i\n", ret); + return -1; + } + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_read(sqe, 0, buf, sizeof(buf), 0); + sqe->flags |= IOSQE_FIXED_FILE; + ret = submit_wait(&ring); + if (ret != -EBADF) { + fprintf(stderr, "read failed %i\n", ret); + return -1; + } + + ret = try_close(&ring, 0, 1); + if (ret != 0) { + fprintf(stderr, "close 2 failed %i\n", ret); + return -1; + } + + ret = try_close(&ring, 0, 0); + if (ret != -EBADF) { + fprintf(stderr, "empty slot failed %i\n", ret); + return -1; + } + + close(fds[0]); + close(fds[1]); + io_uring_queue_exit(&ring); + return 0; +} + static int test_close(struct io_uring *ring, int fd, int is_ring_fd) { struct io_uring_cqe *cqe; @@ -133,6 +242,12 @@ int main(int argc, char *argv[]) goto err; } + ret = test_close_fixed(); + if (ret) { + fprintf(stderr, "test_close_fixed failed\n"); + goto err; + } + done: unlink(path); if (do_unlink) -- cgit v1.2.3 From 0f289c978846862ad4dec29de415e144c5cb05f9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 24 Sep 2021 14:32:25 -0600 Subject: man/io_uring_enter.2: add direct close description Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 73c4959..93b97e6 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -717,6 +717,18 @@ system call. is the file descriptor to be closed. See also .BR close(2) for the general description of the related system call. Available since 5.6. +If the +.I file_index +field is set to a positive number, this command can be used to close files +that were direct opened through +.B IORING_OP_OPENAT +, +.B IORING_OP_OPENAT2 +, or +.B IORING_OP_ACCEPT +using the io_uring specific direct descriptors. Note that only one of the +descriptor fields may be set. The direct close feature is available since +the 5.15 kernel, where direct descriptors were introduced. .TP .B IORING_OP_STATX -- cgit v1.2.3 From 117cb534abd9773d6f41b35e11311494e7e39be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 26 Sep 2021 07:42:56 +0000 Subject: liburing.h: add io_uring_prep_close_direct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 李通洲 --- src/include/liburing.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 38dbbfe..0c2c5c2 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -501,6 +501,13 @@ static inline void io_uring_prep_close(struct io_uring_sqe *sqe, int fd) io_uring_prep_rw(IORING_OP_CLOSE, sqe, fd, NULL, 0, 0); } +static inline void io_uring_prep_close_direct(struct io_uring_sqe *sqe, + unsigned file_index) +{ + io_uring_prep_close(sqe, 0); + __io_uring_set_target_fixed_file(sqe, file_index); +} + static inline void io_uring_prep_read(struct io_uring_sqe *sqe, int fd, void *buf, unsigned nbytes, __u64 offset) { -- cgit v1.2.3 From ce10538688b93dafd257ebfed7faf18844e0052d Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 27 Sep 2021 20:40:22 +0700 Subject: test: Fix endianess issue on `bind()` and `connect()` When we call `bind()` or `connect()`, the `addr` and `port` should be in big endian value representation. Portability notes: - Do not hard code the address with integer like this `0x0100007fU`. Instead, use `inet_addr("127.0.0.1")` to ensure portability for the machine with different endianess. It's also cleaner and more readable to use `inet_addr()` from `#include `. - Use `htons(port_number)` to make sure the port_number is properly choosen instead directly assign it with integer (still about endianess problem). This commit fixes endianess issue in these files: test/232c93d07b74-test.c test/accept-link.c test/accept.c test/poll-link.c test/shutdown.c test/socket-rw-eagain.c test/socket-rw.c Fixes: 08bd815170ab4352d71019f4d3e532cd3f6f0489 ("Un-DOSify test/232c93d07b74-test.c") Fixes: 4bce856d43ab1f9a64477aa5a8f9f02f53e64b74 ("Improve reliability of poll/accept-link tests") Fixes: 76e3b7921fee98a5627cd270628b6a5160d3857d ("Add nonblock empty socket read test") Fixes: 7de625356997dea66826007676224285d407a0fe ("test/accept: code reuse cleanup") Fixes: 8a3a8d744db428a326e2f54093665411734fa3a8 ("Add IORING_OP_SHUTDOWN test case") Fixes: e3adbfc235da96ac97a9cafac78292a22eb12036 ("Moves function calls out of assert().") Suggested-by: Louvian Lyndal Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- test/232c93d07b74-test.c | 9 +++++---- test/accept-link.c | 11 +++++++---- test/accept.c | 5 +++-- test/poll-link.c | 11 +++++++---- test/shutdown.c | 5 +++-- test/socket-rw-eagain.c | 5 +++-- test/socket-rw.c | 5 +++-- 7 files changed, 31 insertions(+), 20 deletions(-) diff --git a/test/232c93d07b74-test.c b/test/232c93d07b74-test.c index cd194cb..4153aef 100644 --- a/test/232c93d07b74-test.c +++ b/test/232c93d07b74-test.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "liburing.h" @@ -75,8 +76,8 @@ static void *rcv(void *arg) struct sockaddr_in addr; addr.sin_family = AF_INET; - addr.sin_port = PORT; - addr.sin_addr.s_addr = 0x0100007fU; + addr.sin_port = htons(PORT); + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); res = bind(s0, (struct sockaddr *) &addr, sizeof(addr)); assert(res != -1); } else { @@ -190,8 +191,8 @@ static void *snd(void *arg) struct sockaddr_in addr; addr.sin_family = AF_INET; - addr.sin_port = PORT; - addr.sin_addr.s_addr = 0x0100007fU; + addr.sin_port = htons(PORT); + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); ret = connect(s0, (struct sockaddr*) &addr, sizeof(addr)); assert(ret != -1); } else { diff --git a/test/accept-link.c b/test/accept-link.c index 605e0ec..f111275 100644 --- a/test/accept-link.c +++ b/test/accept-link.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "liburing.h" @@ -42,7 +43,8 @@ struct data { unsigned expected[2]; unsigned just_positive[2]; unsigned long timeout; - int port; + unsigned short port; + unsigned int addr; int stop; }; @@ -63,7 +65,7 @@ static void *send_thread(void *arg) addr.sin_family = AF_INET; addr.sin_port = data->port; - addr.sin_addr.s_addr = 0x0100007fU; + addr.sin_addr.s_addr = data->addr; ret = connect(s0, (struct sockaddr*)&addr, sizeof(addr)); assert(ret != -1); @@ -95,11 +97,12 @@ void *recv_thread(void *arg) struct sockaddr_in addr; addr.sin_family = AF_INET; - addr.sin_addr.s_addr = 0x0100007fU; + data->addr = inet_addr("127.0.0.1"); + addr.sin_addr.s_addr = data->addr; i = 0; do { - data->port = 1025 + (rand() % 64510); + data->port = htons(1025 + (rand() % 64510)); addr.sin_port = data->port; if (bind(s0, (struct sockaddr*)&addr, sizeof(addr)) != -1) diff --git a/test/accept.c b/test/accept.c index 0c69b98..a4fc677 100644 --- a/test/accept.c +++ b/test/accept.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "helpers.h" #include "liburing.h" @@ -107,8 +108,8 @@ static int start_accept_listen(struct sockaddr_in *addr, int port_off) addr = &laddr; addr->sin_family = AF_INET; - addr->sin_port = 0x1235 + port_off; - addr->sin_addr.s_addr = 0x0100007fU; + addr->sin_port = htons(0x1235 + port_off); + addr->sin_addr.s_addr = inet_addr("127.0.0.1"); ret = bind(fd, (struct sockaddr*)addr, sizeof(*addr)); assert(ret != -1); diff --git a/test/poll-link.c b/test/poll-link.c index 4b4f9aa..197ad77 100644 --- a/test/poll-link.c +++ b/test/poll-link.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "liburing.h" @@ -42,7 +43,8 @@ struct data { unsigned expected[2]; unsigned is_mask[2]; unsigned long timeout; - int port; + unsigned short port; + unsigned int addr; int stop; }; @@ -59,7 +61,7 @@ static void *send_thread(void *arg) addr.sin_family = AF_INET; addr.sin_port = data->port; - addr.sin_addr.s_addr = 0x0100007fU; + addr.sin_addr.s_addr = data->addr; if (connect(s0, (struct sockaddr*)&addr, sizeof(addr)) != -1) wait_for_var(&recv_thread_done); @@ -90,11 +92,12 @@ void *recv_thread(void *arg) struct sockaddr_in addr; addr.sin_family = AF_INET; - addr.sin_addr.s_addr = 0x0100007fU; + data->addr = inet_addr("127.0.0.1"); + addr.sin_addr.s_addr = data->addr; i = 0; do { - data->port = 1025 + (rand() % 64510); + data->port = htons(1025 + (rand() % 64510)); addr.sin_port = data->port; if (bind(s0, (struct sockaddr*)&addr, sizeof(addr)) != -1) diff --git a/test/shutdown.c b/test/shutdown.c index 5aa1371..20bcc77 100644 --- a/test/shutdown.c +++ b/test/shutdown.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "liburing.h" @@ -42,8 +43,8 @@ int main(int argc, char *argv[]) assert(ret != -1); addr.sin_family = AF_INET; - addr.sin_port = (rand() % 61440) + 4096; - addr.sin_addr.s_addr = 0x0100007fU; + addr.sin_port = htons((rand() % 61440) + 4096); + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)); assert(ret != -1); diff --git a/test/socket-rw-eagain.c b/test/socket-rw-eagain.c index cc87aca..9854e00 100644 --- a/test/socket-rw-eagain.c +++ b/test/socket-rw-eagain.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "liburing.h" @@ -38,10 +39,10 @@ int main(int argc, char *argv[]) assert(ret != -1); addr.sin_family = AF_INET; - addr.sin_addr.s_addr = 0x0100007fU; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); do { - addr.sin_port = (rand() % 61440) + 4096; + addr.sin_port = htons((rand() % 61440) + 4096); ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)); if (!ret) break; diff --git a/test/socket-rw.c b/test/socket-rw.c index 1b731b2..5afd14d 100644 --- a/test/socket-rw.c +++ b/test/socket-rw.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "liburing.h" @@ -40,10 +41,10 @@ int main(int argc, char *argv[]) assert(ret != -1); addr.sin_family = AF_INET; - addr.sin_addr.s_addr = 0x0100007fU; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); do { - addr.sin_port = (rand() % 61440) + 4096; + addr.sin_port = htons((rand() % 61440) + 4096); ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)); if (!ret) break; -- cgit v1.2.3 From 834496358870cb272f98cf22b3fe0307c83a526d Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 3 Oct 2021 08:06:08 +0700 Subject: test/probe: Use `io_uring_free_probe()` instead of `free()` `io_uring_free_probe()` should really be used to free the return value of `io_uring_get_probe_ring()`. As we may not always allocate it with `malloc()`. For example, to support no libc build [1]. Link: https://github.com/axboe/liburing/issues/443 [1] Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211003010608.58380-1-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- test/probe.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/probe.c b/test/probe.c index 29239ff..fd59612 100644 --- a/test/probe.c +++ b/test/probe.c @@ -45,6 +45,7 @@ static int verify_probe(struct io_uring_probe *p, int full) static int test_probe_helper(struct io_uring *ring) { + int ret; struct io_uring_probe *p; p = io_uring_get_probe_ring(ring); @@ -53,12 +54,9 @@ static int test_probe_helper(struct io_uring *ring) return 1; } - if (verify_probe(p, 1)) { - free(p); - return 1; - } - - return 0; + ret = verify_probe(p, 1); + io_uring_free_probe(p); + return ret; } static int test_probe(struct io_uring *ring) -- cgit v1.2.3 From a987d7031d95d88f0fdb0301cd5187c5bf3fb889 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 3 Oct 2021 12:10:59 +0100 Subject: io_uring: test IORING_TIMEOUT_ETIME_SUCCESS Make sure we don't fail links on ETIME when IORING_TIMEOUT_ETIME_SUCCESS is set. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/d1a5b6bdbcfa1ec6b5ca014248e12b3b1edb4e5d.1633259449.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 1 + test/timeout.c | 67 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 7aa43fc..61683bd 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -162,6 +162,7 @@ enum { #define IORING_TIMEOUT_BOOTTIME (1U << 2) #define IORING_TIMEOUT_REALTIME (1U << 3) #define IORING_LINK_TIMEOUT_UPDATE (1U << 4) +#define IORING_TIMEOUT_ETIME_SUCCESS (1U << 5) #define IORING_TIMEOUT_CLOCK_MASK (IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME) #define IORING_TIMEOUT_UPDATE_MASK (IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE) /* diff --git a/test/timeout.c b/test/timeout.c index 775063f..f8ba973 100644 --- a/test/timeout.c +++ b/test/timeout.c @@ -1267,6 +1267,67 @@ static int test_timeout_link_cancel(void) return 0; } + +static int test_not_failing_links(void) +{ + struct io_uring ring; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct __kernel_timespec ts; + int ret; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring create failed: %d\n", ret); + return 1; + } + + msec_to_ts(&ts, 1); + sqe = io_uring_get_sqe(&ring); + io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_ETIME_SUCCESS); + sqe->user_data = 1; + sqe->flags |= IOSQE_IO_LINK; + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_nop(sqe); + sqe->user_data = 2; + + ret = io_uring_submit(&ring); + if (ret != 2) { + fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret); + return 1; + } + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0) { + fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret); + return 1; + } else if (cqe->user_data == 1 && cqe->res == -EINVAL) { + fprintf(stderr, "ETIME_SUCCESS is not supported, skip\n"); + goto done; + } else if (cqe->res != -ETIME || cqe->user_data != 1) { + fprintf(stderr, "timeout failed %i %i\n", cqe->res, + (int)cqe->user_data); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0) { + fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret); + return 1; + } else if (cqe->res || cqe->user_data != 2) { + fprintf(stderr, "nop failed %i %i\n", cqe->res, + (int)cqe->user_data); + return 1; + } +done: + io_uring_cqe_seen(&ring, cqe); + io_uring_queue_exit(&ring); + return 0; +} + + int main(int argc, char *argv[]) { struct io_uring ring, sqpoll_ring; @@ -1450,6 +1511,12 @@ int main(int argc, char *argv[]) return ret; } + ret = test_not_failing_links(); + if (ret) { + fprintf(stderr, "test_not_failing_links failed\n"); + return ret; + } + if (sqpoll) io_uring_queue_exit(&sqpoll_ring); return 0; -- cgit v1.2.3 From f5b052a4f57d740258690cf77f99ea08225e12c4 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 3 Oct 2021 12:11:00 +0100 Subject: io_uring: fix SQPOLL timeout-new test Happens pretty rarely, but there were cases when CQE waitinig in test_return_before_timeout() time outs before the SQPOLL thread kicks in and executes submitted requests, give SQPOLL a little bit more time. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/5faf8ade7e161931d76a47b809650e68a1b361ba.1633259449.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/timeout-new.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/test/timeout-new.c b/test/timeout-new.c index 19c5ac3..6efcfb4 100644 --- a/test/timeout-new.c +++ b/test/timeout-new.c @@ -53,14 +53,12 @@ static int test_return_before_timeout(struct io_uring *ring) struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; int ret; + bool retried = false; struct __kernel_timespec ts; - sqe = io_uring_get_sqe(ring); - if (!sqe) { - fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__); - return 1; - } + msec_to_ts(&ts, TIMEOUT_MSEC); + sqe = io_uring_get_sqe(ring); io_uring_prep_nop(sqe); ret = io_uring_submit(ring); @@ -69,13 +67,21 @@ static int test_return_before_timeout(struct io_uring *ring) return 1; } - msec_to_ts(&ts, TIMEOUT_MSEC); +again: ret = io_uring_wait_cqe_timeout(ring, &cqe, &ts); - if (ret < 0) { + if (ret == -ETIME && (ring->flags & IORING_SETUP_SQPOLL) && !retried) { + /* + * there is a small chance SQPOLL hasn't been waked up yet, + * give it one more try. + */ + printf("warning: funky SQPOLL timing\n"); + sleep(1); + retried = true; + goto again; + } else if (ret < 0) { fprintf(stderr, "%s: timeout error: %d\n", __FUNCTION__, ret); return 1; } - io_uring_cqe_seen(ring, cqe); return 0; } -- cgit v1.2.3 From 1c591c368215a39fae2f9612cc456c7d1203ad0e Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 3 Oct 2021 22:34:26 +0700 Subject: src/syscall: Wrap `errno` for `__sys_io_uring_{register,setup,enter{2,}}` Make it possible to remove the dependency of `errno` variable (which comes from libc). Currently, we expose these functions to userland: 1) `__sys_io_uring_register` 2) `__sys_io_uring_setup` 3) `__sys_io_uring_enter2` 4) `__sys_io_uring_enter` The tests in `test/io_uring_{enter,register,setup}.c` are the examples of it. Since the userland needs to check the `errno` value to use them properly, this means those functions always depend on libc. So we cannot change their behavior. Don't touch them all, this ensures the changes only affect liburing internal and no visible functionality changes for the users. Then we introduce new functions with the same name (with extra underscore as prefix, 4 underscores): 1) `____sys_io_uring_register` 2) `____sys_io_uring_setup` 3) `____sys_io_uring_enter2` 4) `____sys_io_uring_enter` These functions do not use `errno` variable *on the caller*, they use the kernel style return value (return a negative value of error code when errors). These functions are defined as `static inline` in `src/syscall.h`. They are just a wrapper to make sure liburing internal sources do not touch `errno` variable from C files directly. We need to make C files not to touch the `errno` variable to support build without libc. Link: https://github.com/axboe/liburing/issues/443#issuecomment-927873932 Cc: Bedirhan KURT Suggested-by: Louvian Lyndal Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211003153428.369258-2-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- src/syscall.c | 43 +++---------------------------- src/syscall.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/syscall.c b/src/syscall.c index 69027e5..5923fbb 100644 --- a/src/syscall.c +++ b/src/syscall.c @@ -11,41 +11,6 @@ #include "liburing/io_uring.h" #include "syscall.h" -#ifdef __alpha__ -/* - * alpha and mips are exception, other architectures have - * common numbers for new system calls. - */ -# ifndef __NR_io_uring_setup -# define __NR_io_uring_setup 535 -# endif -# ifndef __NR_io_uring_enter -# define __NR_io_uring_enter 536 -# endif -# ifndef __NR_io_uring_register -# define __NR_io_uring_register 537 -# endif -#elif defined __mips__ -# ifndef __NR_io_uring_setup -# define __NR_io_uring_setup (__NR_Linux + 425) -# endif -# ifndef __NR_io_uring_enter -# define __NR_io_uring_enter (__NR_Linux + 426) -# endif -# ifndef __NR_io_uring_register -# define __NR_io_uring_register (__NR_Linux + 427) -# endif -#else /* !__alpha__ and !__mips__ */ -# ifndef __NR_io_uring_setup -# define __NR_io_uring_setup 425 -# endif -# ifndef __NR_io_uring_enter -# define __NR_io_uring_enter 426 -# endif -# ifndef __NR_io_uring_register -# define __NR_io_uring_register 427 -# endif -#endif int __sys_io_uring_register(int fd, unsigned opcode, const void *arg, unsigned nr_args) @@ -59,15 +24,15 @@ int __sys_io_uring_setup(unsigned entries, struct io_uring_params *p) } int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, - unsigned flags, sigset_t *sig, int sz) + unsigned flags, sigset_t *sig, int sz) { - return syscall(__NR_io_uring_enter, fd, to_submit, min_complete, - flags, sig, sz); + return syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, + sig, sz); } int __sys_io_uring_enter(int fd, unsigned to_submit, unsigned min_complete, unsigned flags, sigset_t *sig) { return __sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, - _NSIG / 8); + _NSIG / 8); } diff --git a/src/syscall.h b/src/syscall.h index 2368f83..f7f63aa 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -2,7 +2,49 @@ #ifndef LIBURING_SYSCALL_H #define LIBURING_SYSCALL_H +#include #include +#include +#include +#include +#include + +#ifdef __alpha__ +/* + * alpha and mips are exception, other architectures have + * common numbers for new system calls. + */ +# ifndef __NR_io_uring_setup +# define __NR_io_uring_setup 535 +# endif +# ifndef __NR_io_uring_enter +# define __NR_io_uring_enter 536 +# endif +# ifndef __NR_io_uring_register +# define __NR_io_uring_register 537 +# endif +#elif defined __mips__ +# ifndef __NR_io_uring_setup +# define __NR_io_uring_setup (__NR_Linux + 425) +# endif +# ifndef __NR_io_uring_enter +# define __NR_io_uring_enter (__NR_Linux + 426) +# endif +# ifndef __NR_io_uring_register +# define __NR_io_uring_register (__NR_Linux + 427) +# endif +#else /* !__alpha__ and !__mips__ */ +# ifndef __NR_io_uring_setup +# define __NR_io_uring_setup 425 +# endif +# ifndef __NR_io_uring_enter +# define __NR_io_uring_enter 426 +# endif +# ifndef __NR_io_uring_register +# define __NR_io_uring_register 427 +# endif +#endif + struct io_uring_params; @@ -17,4 +59,43 @@ int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, int __sys_io_uring_register(int fd, unsigned int opcode, const void *arg, unsigned int nr_args); + + +static inline int ____sys_io_uring_register(int fd, unsigned opcode, + const void *arg, unsigned nr_args) +{ + int ret; + + ret = syscall(__NR_io_uring_register, fd, opcode, arg, nr_args); + return (ret < 0) ? -errno : ret; +} + +static inline int ____sys_io_uring_setup(unsigned entries, + struct io_uring_params *p) +{ + int ret; + + ret = syscall(__NR_io_uring_setup, entries, p); + return (ret < 0) ? -errno : ret; +} + +static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig, int sz) +{ + int ret; + + ret = syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, + sig, sz); + return (ret < 0) ? -errno : ret; +} + +static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig) +{ + return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, + _NSIG / 8); +} + #endif -- cgit v1.2.3 From ad3dcbde721fedc497042f7a51277dd23f779f2d Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 3 Oct 2021 22:34:27 +0700 Subject: src/{queue,register,setup}: Don't use `__sys_io_uring*` Don't use `__sys_io_uring*` for liburing internal. These functions are now supposed for user backward compatibility. For now, we use `____sys_io_uring*` (4 underscores). These are `static inline` functions that wrap the `errno` variable in a kernel style return value (directly returns negative error code when errors). The main purpose of this change is to make it possible to remove the `errno` variable dependency from liburing C sources, so that later we will be able to build liburing without libc which doesn't use `errno` variable at all. Cc: Bedirhan KURT Cc: Louvian Lyndal Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211003153428.369258-3-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- src/queue.c | 27 +++------ src/register.c | 187 ++++++++++++++++++--------------------------------------- src/setup.c | 4 +- 3 files changed, 70 insertions(+), 148 deletions(-) diff --git a/src/queue.c b/src/queue.c index 10ef31c..c2881e9 100644 --- a/src/queue.c +++ b/src/queue.c @@ -117,11 +117,11 @@ static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_pt if (!need_enter) break; - ret = __sys_io_uring_enter2(ring->ring_fd, data->submit, - data->wait_nr, flags, data->arg, - data->sz); + ret = ____sys_io_uring_enter2(ring->ring_fd, data->submit, + data->wait_nr, flags, data->arg, + data->sz); if (ret < 0) { - err = -errno; + err = ret; break; } @@ -178,8 +178,8 @@ again: goto done; if (cq_ring_needs_flush(ring)) { - __sys_io_uring_enter(ring->ring_fd, 0, 0, - IORING_ENTER_GETEVENTS, NULL); + ____sys_io_uring_enter(ring->ring_fd, 0, 0, + IORING_ENTER_GETEVENTS, NULL); overflow_checked = true; goto again; } @@ -333,10 +333,8 @@ static int __io_uring_submit(struct io_uring *ring, unsigned submitted, if (wait_nr || (ring->flags & IORING_SETUP_IOPOLL)) flags |= IORING_ENTER_GETEVENTS; - ret = __sys_io_uring_enter(ring->ring_fd, submitted, wait_nr, - flags, NULL); - if (ret < 0) - return -errno; + ret = ____sys_io_uring_enter(ring->ring_fd, submitted, wait_nr, + flags, NULL); } else ret = submitted; @@ -391,11 +389,6 @@ struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) int __io_uring_sqring_wait(struct io_uring *ring) { - int ret; - - ret = __sys_io_uring_enter(ring->ring_fd, 0, 0, IORING_ENTER_SQ_WAIT, - NULL); - if (ret < 0) - ret = -errno; - return ret; + return ____sys_io_uring_enter(ring->ring_fd, 0, 0, + IORING_ENTER_SQ_WAIT, NULL); } diff --git a/src/register.c b/src/register.c index 5ea4331..cb09dea 100644 --- a/src/register.c +++ b/src/register.c @@ -26,12 +26,10 @@ int io_uring_register_buffers_update_tag(struct io_uring *ring, unsigned off, .tags = (unsigned long)tags, .nr = nr, }; - int ret; - ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_BUFFERS_UPDATE, - &up, sizeof(up)); - return ret < 0 ? -errno : ret; + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_BUFFERS_UPDATE, &up, + sizeof(up)); } int io_uring_register_buffers_tags(struct io_uring *ring, @@ -44,11 +42,9 @@ int io_uring_register_buffers_tags(struct io_uring *ring, .data = (unsigned long)iovecs, .tags = (unsigned long)tags, }; - int ret; - ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_BUFFERS2, - ®, sizeof(reg)); - return ret < 0 ? -errno : ret; + return ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_BUFFERS2, + ®, sizeof(reg)); } int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, @@ -56,24 +52,18 @@ int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, { int ret; - ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_BUFFERS, + ret = ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_BUFFERS, iovecs, nr_iovecs); - if (ret < 0) - return -errno; - - return 0; + return (ret < 0) ? ret : 0; } int io_uring_unregister_buffers(struct io_uring *ring) { int ret; - ret = __sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_BUFFERS, + ret = ____sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_BUFFERS, NULL, 0); - if (ret < 0) - return -errno; - - return 0; + return (ret < 0) ? ret : 0; } int io_uring_register_files_update_tag(struct io_uring *ring, unsigned off, @@ -86,12 +76,10 @@ int io_uring_register_files_update_tag(struct io_uring *ring, unsigned off, .tags = (unsigned long)tags, .nr = nr_files, }; - int ret; - ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_FILES_UPDATE2, - &up, sizeof(up)); - return ret < 0 ? -errno : ret; + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_FILES_UPDATE2, &up, + sizeof(up)); } /* @@ -108,15 +96,10 @@ int io_uring_register_files_update(struct io_uring *ring, unsigned off, .offset = off, .fds = (unsigned long) files, }; - int ret; - - ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_FILES_UPDATE, &up, - nr_files); - if (ret < 0) - return -errno; - return ret; + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_FILES_UPDATE, &up, + nr_files); } static int increase_rlimit_nofile(unsigned nr) @@ -133,9 +116,8 @@ static int increase_rlimit_nofile(unsigned nr) return 0; } -int io_uring_register_files_tags(struct io_uring *ring, - const int *files, const __u64 *tags, - unsigned nr) +int io_uring_register_files_tags(struct io_uring *ring, const int *files, + const __u64 *tags, unsigned nr) { struct io_uring_rsrc_register reg = { .nr = nr, @@ -145,12 +127,12 @@ int io_uring_register_files_tags(struct io_uring *ring, int ret, did_increase = 0; do { - ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_FILES2, ®, - sizeof(reg)); + ret = ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_FILES2, ®, + sizeof(reg)); if (ret >= 0) break; - if (errno == EMFILE && !did_increase) { + if (ret == -EMFILE && !did_increase) { did_increase = 1; increase_rlimit_nofile(nr); continue; @@ -158,21 +140,21 @@ int io_uring_register_files_tags(struct io_uring *ring, break; } while (1); - return ret < 0 ? -errno : ret; + return ret; } int io_uring_register_files(struct io_uring *ring, const int *files, - unsigned nr_files) + unsigned nr_files) { int ret, did_increase = 0; do { - ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_FILES, files, - nr_files); + ret = ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_FILES, files, + nr_files); if (ret >= 0) break; - if (errno == EMFILE && !did_increase) { + if (ret == -EMFILE && !did_increase) { did_increase = 1; increase_rlimit_nofile(nr_files); continue; @@ -180,55 +162,44 @@ int io_uring_register_files(struct io_uring *ring, const int *files, break; } while (1); - return ret < 0 ? -errno : ret; + return ret; } int io_uring_unregister_files(struct io_uring *ring) { int ret; - ret = __sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, + ret = ____sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, NULL, 0); - if (ret < 0) - return -errno; - - return 0; + return (ret < 0) ? ret : 0; } int io_uring_register_eventfd(struct io_uring *ring, int event_fd) { int ret; - ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_EVENTFD, + ret = ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_EVENTFD, &event_fd, 1); - if (ret < 0) - return -errno; - - return 0; + return (ret < 0) ? ret : 0; } int io_uring_unregister_eventfd(struct io_uring *ring) { int ret; - ret = __sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_EVENTFD, + ret = ____sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_EVENTFD, NULL, 0); - if (ret < 0) - return -errno; - - return 0; + return (ret < 0) ? ret : 0; } int io_uring_register_eventfd_async(struct io_uring *ring, int event_fd) { int ret; - ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_EVENTFD_ASYNC, - &event_fd, 1); - if (ret < 0) - return -errno; - - return 0; + ret = ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_EVENTFD_ASYNC, + &event_fd, 1); + return (ret < 0) ? ret : 0; } int io_uring_register_probe(struct io_uring *ring, struct io_uring_probe *p, @@ -236,36 +207,21 @@ int io_uring_register_probe(struct io_uring *ring, struct io_uring_probe *p, { int ret; - ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_PROBE, - p, nr_ops); - if (ret < 0) - return -errno; - - return 0; + ret = ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_PROBE, p, + nr_ops); + return (ret < 0) ? ret : 0; } int io_uring_register_personality(struct io_uring *ring) { - int ret; - - ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_PERSONALITY, - NULL, 0); - if (ret < 0) - return -errno; - - return ret; + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_PERSONALITY, NULL, 0); } int io_uring_unregister_personality(struct io_uring *ring, int id) { - int ret; - - ret = __sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_PERSONALITY, - NULL, id); - if (ret < 0) - return -errno; - - return ret; + return ____sys_io_uring_register(ring->ring_fd, + IORING_UNREGISTER_PERSONALITY, NULL, id); } int io_uring_register_restrictions(struct io_uring *ring, @@ -274,61 +230,34 @@ int io_uring_register_restrictions(struct io_uring *ring, { int ret; - ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_RESTRICTIONS, - res, nr_res); - if (ret < 0) - return -errno; - - return 0; + ret = ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_RESTRICTIONS, res, + nr_res); + return (ret < 0) ? ret : 0; } int io_uring_enable_rings(struct io_uring *ring) { - int ret; - - ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_ENABLE_RINGS, NULL, 0); - if (ret < 0) - return -errno; - - return ret; + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_ENABLE_RINGS, NULL, 0); } int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, const cpu_set_t *mask) { - int ret; - - ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_IOWQ_AFF, mask, cpusz); - if (ret < 0) - return -errno; - - return ret; + return ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_IOWQ_AFF, + mask, cpusz); } int io_uring_unregister_iowq_aff(struct io_uring *ring) { - int ret; - - ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_IOWQ_AFF, NULL, 0); - if (ret < 0) - return -errno; - - return ret; + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_IOWQ_AFF, NULL, 0); } int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *val) { - int ret; - - ret = __sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_IOWQ_MAX_WORKERS, - val, 2); - if (ret < 0) - return -errno; - - return ret; - + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_IOWQ_MAX_WORKERS, val, + 2); } diff --git a/src/setup.c b/src/setup.c index 54225e8..edfe94e 100644 --- a/src/setup.c +++ b/src/setup.c @@ -140,9 +140,9 @@ int io_uring_queue_init_params(unsigned entries, struct io_uring *ring, { int fd, ret; - fd = __sys_io_uring_setup(entries, p); + fd = ____sys_io_uring_setup(entries, p); if (fd < 0) - return -errno; + return fd; ret = io_uring_queue_mmap(fd, p, ring); if (ret) { -- cgit v1.2.3 From cccf0fa1762aac3f14323fbfc5cef2c99a03efe4 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 3 Oct 2021 22:34:28 +0700 Subject: Wrap all syscalls in a kernel style return value Add new syscall wrapper functions: 1) `uring_mmap` 2) `uring_munmap` 3) `uring_madvise` 4) `uring_getrlimit` 5) `uring_setrlimit` All of them are `static inline`. Use them to wrap the syscalls in a kernel style return value. The main purpose of this change is to make it possible to remove the dependency of `errno` variable in liburing C sources, so that later we can support build without libc. Extra new helpers: 1) `ERR_PTR()` 2) `PTR_ERR()` 3) `IS_ERR()` These helpers are used to deal with syscalls that return a pointer. Currently only `uring_mmap()` that depends on these. Link: https://github.com/axboe/liburing/issues/443#issuecomment-927873932 Cc: Bedirhan KURT Suggested-by: Louvian Lyndal Reviewed-by: Jens Axboe Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211003153428.369258-4-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- src/queue.c | 1 - src/register.c | 10 ++++++---- src/setup.c | 53 ++++++++++++++++++++++++++--------------------------- src/syscall.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 32 deletions(-) diff --git a/src/queue.c b/src/queue.c index c2881e9..31aa17c 100644 --- a/src/queue.c +++ b/src/queue.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include diff --git a/src/register.c b/src/register.c index cb09dea..074223f 100644 --- a/src/register.c +++ b/src/register.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "liburing/compat.h" @@ -104,13 +103,16 @@ int io_uring_register_files_update(struct io_uring *ring, unsigned off, static int increase_rlimit_nofile(unsigned nr) { + int ret; struct rlimit rlim; - if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) - return -errno; + ret = uring_getrlimit(RLIMIT_NOFILE, &rlim); + if (ret < 0) + return ret; + if (rlim.rlim_cur < nr) { rlim.rlim_cur += nr; - setrlimit(RLIMIT_NOFILE, &rlim); + uring_setrlimit(RLIMIT_NOFILE, &rlim); } return 0; diff --git a/src/setup.c b/src/setup.c index edfe94e..bdbf97c 100644 --- a/src/setup.c +++ b/src/setup.c @@ -3,9 +3,7 @@ #include #include -#include #include -#include #include #include #include @@ -18,9 +16,9 @@ static void io_uring_unmap_rings(struct io_uring_sq *sq, struct io_uring_cq *cq) { - munmap(sq->ring_ptr, sq->ring_sz); + uring_munmap(sq->ring_ptr, sq->ring_sz); if (cq->ring_ptr && cq->ring_ptr != sq->ring_ptr) - munmap(cq->ring_ptr, cq->ring_sz); + uring_munmap(cq->ring_ptr, cq->ring_sz); } static int io_uring_mmap(int fd, struct io_uring_params *p, @@ -37,19 +35,21 @@ static int io_uring_mmap(int fd, struct io_uring_params *p, sq->ring_sz = cq->ring_sz; cq->ring_sz = sq->ring_sz; } - sq->ring_ptr = mmap(0, sq->ring_sz, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQ_RING); - if (sq->ring_ptr == MAP_FAILED) - return -errno; + sq->ring_ptr = uring_mmap(0, sq->ring_sz, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, fd, + IORING_OFF_SQ_RING); + if (IS_ERR(sq->ring_ptr)) + return PTR_ERR(sq->ring_ptr); if (p->features & IORING_FEAT_SINGLE_MMAP) { cq->ring_ptr = sq->ring_ptr; } else { - cq->ring_ptr = mmap(0, cq->ring_sz, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_CQ_RING); - if (cq->ring_ptr == MAP_FAILED) { + cq->ring_ptr = uring_mmap(0, cq->ring_sz, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, fd, + IORING_OFF_CQ_RING); + if (IS_ERR(cq->ring_ptr)) { + ret = PTR_ERR(cq->ring_ptr); cq->ring_ptr = NULL; - ret = -errno; goto err; } } @@ -63,11 +63,10 @@ static int io_uring_mmap(int fd, struct io_uring_params *p, sq->array = sq->ring_ptr + p->sq_off.array; size = p->sq_entries * sizeof(struct io_uring_sqe); - sq->sqes = mmap(0, size, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_POPULATE, fd, - IORING_OFF_SQES); - if (sq->sqes == MAP_FAILED) { - ret = -errno; + sq->sqes = uring_mmap(0, size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQES); + if (IS_ERR(sq->sqes)) { + ret = PTR_ERR(sq->sqes); err: io_uring_unmap_rings(sq, cq); return ret; @@ -116,20 +115,20 @@ int io_uring_ring_dontfork(struct io_uring *ring) return -EINVAL; len = *ring->sq.kring_entries * sizeof(struct io_uring_sqe); - ret = madvise(ring->sq.sqes, len, MADV_DONTFORK); - if (ret == -1) - return -errno; + ret = uring_madvise(ring->sq.sqes, len, MADV_DONTFORK); + if (ret < 0) + return ret; len = ring->sq.ring_sz; - ret = madvise(ring->sq.ring_ptr, len, MADV_DONTFORK); - if (ret == -1) - return -errno; + ret = uring_madvise(ring->sq.ring_ptr, len, MADV_DONTFORK); + if (ret < 0) + return ret; if (ring->cq.ring_ptr != ring->sq.ring_ptr) { len = ring->cq.ring_sz; - ret = madvise(ring->cq.ring_ptr, len, MADV_DONTFORK); - if (ret == -1) - return -errno; + ret = uring_madvise(ring->cq.ring_ptr, len, MADV_DONTFORK); + if (ret < 0) + return ret; } return 0; @@ -173,7 +172,7 @@ void io_uring_queue_exit(struct io_uring *ring) struct io_uring_sq *sq = &ring->sq; struct io_uring_cq *cq = &ring->cq; - munmap(sq->sqes, *sq->kring_entries * sizeof(struct io_uring_sqe)); + uring_munmap(sq->sqes, *sq->kring_entries * sizeof(struct io_uring_sqe)); io_uring_unmap_rings(sq, cq); close(ring->ring_fd); } diff --git a/src/syscall.h b/src/syscall.h index f7f63aa..a9dd280 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -4,11 +4,15 @@ #include #include +#include #include +#include #include #include #include +#include + #ifdef __alpha__ /* * alpha and mips are exception, other architectures have @@ -59,7 +63,20 @@ int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, int __sys_io_uring_register(int fd, unsigned int opcode, const void *arg, unsigned int nr_args); +static inline void *ERR_PTR(intptr_t n) +{ + return (void *) n; +} +static inline intptr_t PTR_ERR(void *ptr) +{ + return (intptr_t) ptr; +} + +static inline bool IS_ERR(void *ptr) +{ + return uring_unlikely((uintptr_t) ptr >= (uintptr_t) -4095UL); +} static inline int ____sys_io_uring_register(int fd, unsigned opcode, const void *arg, unsigned nr_args) @@ -98,4 +115,45 @@ static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, _NSIG / 8); } +static inline void *uring_mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) +{ + void *ret; + + ret = mmap(addr, length, prot, flags, fd, offset); + return (ret == MAP_FAILED) ? ERR_PTR(-errno) : ret; +} + +static inline int uring_munmap(void *addr, size_t length) +{ + int ret; + + ret = munmap(addr, length); + return (ret < 0) ? -errno : ret; +} + +static inline int uring_madvise(void *addr, size_t length, int advice) +{ + int ret; + + ret = madvise(addr, length, advice); + return (ret < 0) ? -errno : ret; +} + +static inline int uring_getrlimit(int resource, struct rlimit *rlim) +{ + int ret; + + ret = getrlimit(resource, rlim); + return (ret < 0) ? -errno : ret; +} + +static inline int uring_setrlimit(int resource, const struct rlimit *rlim) +{ + int ret; + + ret = setrlimit(resource, rlim); + return (ret < 0) ? -errno : ret; +} + #endif -- cgit v1.2.3 From 601648ff09b138cadc312b02d497c204eba7fe48 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 4 Oct 2021 08:35:10 +0700 Subject: src/syscall: Add `close` syscall wrapper In commit 0c210dbae26a80ee82dbc7430828ab6fd7012548 ("Wrap all syscalls in a kernel style return value"), we forgot to add a syscall wrapper for `close()`. Add it. Fixes: cccf0fa1762aac3f14323fbfc5cef2c99a03efe4 ("Wrap all syscalls in a kernel style return value") Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211004013510.428077-1-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- src/setup.c | 4 ++-- src/syscall.h | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/setup.c b/src/setup.c index bdbf97c..4f006de 100644 --- a/src/setup.c +++ b/src/setup.c @@ -145,7 +145,7 @@ int io_uring_queue_init_params(unsigned entries, struct io_uring *ring, ret = io_uring_queue_mmap(fd, p, ring); if (ret) { - close(fd); + uring_close(fd); return ret; } @@ -174,7 +174,7 @@ void io_uring_queue_exit(struct io_uring *ring) uring_munmap(sq->sqes, *sq->kring_entries * sizeof(struct io_uring_sqe)); io_uring_unmap_rings(sq, cq); - close(ring->ring_fd); + uring_close(ring->ring_fd); } struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring) diff --git a/src/syscall.h b/src/syscall.h index a9dd280..9eff968 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -156,4 +156,12 @@ static inline int uring_setrlimit(int resource, const struct rlimit *rlim) return (ret < 0) ? -errno : ret; } +static inline int uring_close(int fd) +{ + int ret; + + ret = close(fd); + return (ret < 0) ? -errno : ret; +} + #endif -- cgit v1.2.3 From a060c8e55a6116342a16b5b6ac0c4afed17c1cd7 Mon Sep 17 00:00:00 2001 From: Olivier Langlois Date: Mon, 4 Oct 2021 12:56:49 -0400 Subject: liburing: Add io_uring_submit_and_wait_timeout function in API Before commit 0ea4ccd1c0e4 ("src/queue: don't flush SQ ring for new wait interface"), io_uring_wait_cqes() was serving the purpose of submit sqe and wait for cqe up to a certain timeout value. Since the commit, a new function is needed to fill this gap. Fixes: https://github.com/axboe/liburing/issues/440 Signed-off-by: Olivier Langlois Link: https://lore.kernel.org/r/1bbde6755535cb7b0bdfc0846254e7c06faf04e0.1633366467.git.olivier@trillion01.com [axboe: minor style and commit message fixup] Signed-off-by: Jens Axboe --- src/include/liburing.h | 5 ++++ src/liburing.map | 5 ++++ src/queue.c | 78 ++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 0c2c5c2..fe8bfbe 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -122,6 +122,11 @@ int io_uring_wait_cqe_timeout(struct io_uring *ring, struct __kernel_timespec *ts); int io_uring_submit(struct io_uring *ring); int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr); +int io_uring_submit_and_wait_timout(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, + unsigned wait_nr, + struct __kernel_timespec *ts, + sigset_t *sigmask); struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, diff --git a/src/liburing.map b/src/liburing.map index 6692a3b..09f4275 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -44,3 +44,8 @@ LIBURING_2.1 { io_uring_unregister_iowq_aff; io_uring_register_iowq_max_workers; } LIBURING_2.0; + +LIBURING_2.2 { + global: + io_uring_submit_and_wait_timout; +} LIBURING_2.1; diff --git a/src/queue.c b/src/queue.c index 31aa17c..b985056 100644 --- a/src/queue.c +++ b/src/queue.c @@ -271,36 +271,78 @@ static int io_uring_wait_cqes_new(struct io_uring *ring, * hence this function is safe to use for applications that split SQ and CQ * handling between two threads. */ + +static int __io_uring_submit_timeout(struct io_uring *ring, unsigned wait_nr, + struct __kernel_timespec *ts) +{ + struct io_uring_sqe *sqe; + int ret; + + /* + * If the SQ ring is full, we may need to submit IO first + */ + sqe = io_uring_get_sqe(ring); + if (!sqe) { + ret = io_uring_submit(ring); + if (ret < 0) + return ret; + sqe = io_uring_get_sqe(ring); + if (!sqe) + return -EAGAIN; + } + io_uring_prep_timeout(sqe, ts, wait_nr, 0); + sqe->user_data = LIBURING_UDATA_TIMEOUT; + return __io_uring_flush_sq(ring); +} + int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned wait_nr, struct __kernel_timespec *ts, sigset_t *sigmask) { - unsigned to_submit = 0; + int to_submit = 0; if (ts) { - struct io_uring_sqe *sqe; - int ret; - if (ring->features & IORING_FEAT_EXT_ARG) return io_uring_wait_cqes_new(ring, cqe_ptr, wait_nr, ts, sigmask); + to_submit = __io_uring_submit_timeout(ring, wait_nr, ts); + if (to_submit < 0) + return to_submit; + } - /* - * If the SQ ring is full, we may need to submit IO first - */ - sqe = io_uring_get_sqe(ring); - if (!sqe) { - ret = io_uring_submit(ring); - if (ret < 0) - return ret; - sqe = io_uring_get_sqe(ring); - if (!sqe) - return -EAGAIN; + return __io_uring_get_cqe(ring, cqe_ptr, to_submit, wait_nr, sigmask); +} + +int io_uring_submit_and_wait_timout(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, + unsigned wait_nr, + struct __kernel_timespec *ts, + sigset_t *sigmask) +{ + int to_submit; + + if (ts) { + if (ring->features & IORING_FEAT_EXT_ARG) { + struct io_uring_getevents_arg arg = { + .sigmask = (unsigned long) sigmask, + .sigmask_sz = _NSIG / 8, + .ts = (unsigned long) ts + }; + struct get_data data = { + .submit = __io_uring_flush_sq(ring), + .wait_nr = wait_nr, + .get_flags = IORING_ENTER_EXT_ARG, + .sz = sizeof(arg), + .arg = &arg + }; + + return _io_uring_get_cqe(ring, cqe_ptr, &data); } - io_uring_prep_timeout(sqe, ts, wait_nr, 0); - sqe->user_data = LIBURING_UDATA_TIMEOUT; + to_submit = __io_uring_submit_timeout(ring, wait_nr, ts); + if (to_submit < 0) + return to_submit; + } else to_submit = __io_uring_flush_sq(ring); - } return __io_uring_get_cqe(ring, cqe_ptr, to_submit, wait_nr, sigmask); } -- cgit v1.2.3 From a9895111798af2003f5298abb1d5bdaf11ca549e Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Wed, 6 Oct 2021 05:30:10 +0700 Subject: Fix typo "timout" -> "timeout" Cc: Jens Axboe Cc: Olivier Langlois Fixes: a060c8e55a6116342a16b5b6ac0c4afed17c1cd7 ("liburing: Add io_uring_submit_and_wait_timeout function in API") Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- src/include/liburing.h | 10 +++++----- src/liburing.map | 2 +- src/queue.c | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index fe8bfbe..99f4f37 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -122,11 +122,11 @@ int io_uring_wait_cqe_timeout(struct io_uring *ring, struct __kernel_timespec *ts); int io_uring_submit(struct io_uring *ring); int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr); -int io_uring_submit_and_wait_timout(struct io_uring *ring, - struct io_uring_cqe **cqe_ptr, - unsigned wait_nr, - struct __kernel_timespec *ts, - sigset_t *sigmask); +int io_uring_submit_and_wait_timeout(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, + unsigned wait_nr, + struct __kernel_timespec *ts, + sigset_t *sigmask); struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, diff --git a/src/liburing.map b/src/liburing.map index 09f4275..7f1eeb7 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -47,5 +47,5 @@ LIBURING_2.1 { LIBURING_2.2 { global: - io_uring_submit_and_wait_timout; + io_uring_submit_and_wait_timeout; } LIBURING_2.1; diff --git a/src/queue.c b/src/queue.c index b985056..9af29d5 100644 --- a/src/queue.c +++ b/src/queue.c @@ -313,11 +313,11 @@ int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, return __io_uring_get_cqe(ring, cqe_ptr, to_submit, wait_nr, sigmask); } -int io_uring_submit_and_wait_timout(struct io_uring *ring, - struct io_uring_cqe **cqe_ptr, - unsigned wait_nr, - struct __kernel_timespec *ts, - sigset_t *sigmask) +int io_uring_submit_and_wait_timeout(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, + unsigned wait_nr, + struct __kernel_timespec *ts, + sigset_t *sigmask) { int to_submit; -- cgit v1.2.3 From 326ed975d49e8c7bff071abe8e7ac5e0c0196622 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 6 Oct 2021 12:08:45 -0600 Subject: configure: add openat2.h for open_how and RESOLVE_* flags struct open_how and friends reside in the openat2.h header, so include that for the test case. Fixes: https://github.com/axboe/liburing/issues/360 Signed-off-by: Jens Axboe --- configure | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure b/configure index a7caa07..92f51bd 100755 --- a/configure +++ b/configure @@ -268,6 +268,7 @@ cat > $TMPC << EOF #include #include #include +#include int main(int argc, char **argv) { struct open_how how; @@ -432,6 +433,10 @@ struct open_how { uint64_t resolve; }; +EOF +else cat >> $compat_h << EOF +#include + EOF fi -- cgit v1.2.3 From c6f063cff1291c9972d0563dfc1ce3f1ebc8859c Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 7 Oct 2021 13:31:53 +0700 Subject: test/{iopoll,read-write}: Use `io_uring_free_probe()` instead of `free()` `io_uring_free_probe()` should really be used to free the return value of `io_uring_get_probe_ring()`. As we may not always allocate it with `malloc()`. For example, to support no libc build [1]. Link: https://github.com/axboe/liburing/issues/443 [1] Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- test/iopoll.c | 2 +- test/read-write.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/iopoll.c b/test/iopoll.c index de36473..4bfc26a 100644 --- a/test/iopoll.c +++ b/test/iopoll.c @@ -306,7 +306,7 @@ static int probe_buf_select(void) fprintf(stdout, "Buffer select not supported, skipping\n"); return 0; } - free(p); + io_uring_free_probe(p); return 0; } diff --git a/test/read-write.c b/test/read-write.c index 885905b..d54ad0e 100644 --- a/test/read-write.c +++ b/test/read-write.c @@ -480,7 +480,7 @@ static int test_buf_select(const char *filename, int nonvec) fprintf(stdout, "Buffer select not supported, skipping\n"); return 0; } - free(p); + io_uring_free_probe(p); /* * Write out data with known pattern -- cgit v1.2.3 From abd495348b5e0efee0a87b9206174a232932c21e Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 7 Oct 2021 13:31:54 +0700 Subject: test/cq-size: Don't use `errno` to check liburing's functions When we build liburing without libc, we can't check `errno` variable with respect to liburing's functions. Don't do that it in test. Note: The tests themselves can still use `errno` to check error from functions that come from the libc, but not liburing. Link: https://github.com/axboe/liburing/issues/443 Fixes: https://github.com/axboe/liburing/issues/449 Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- test/cq-size.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/cq-size.c b/test/cq-size.c index b7dd5b4..4e6e3d1 100644 --- a/test/cq-size.c +++ b/test/cq-size.c @@ -45,14 +45,20 @@ int main(int argc, char *argv[]) p.cq_entries = 0; ret = io_uring_queue_init_params(4, &ring, &p); - if (ret >= 0 || errno != EINVAL) { + if (ret >= 0) { printf("zero sized cq ring succeeded\n"); + io_uring_queue_exit(&ring); + goto err; + } + + if (ret != -EINVAL) { + printf("io_uring_queue_init_params failed, but not with -EINVAL" + ", returned error %d (%s)\n", ret, strerror(-ret)); goto err; } done: return 0; err: - io_uring_queue_exit(&ring); return 1; } -- cgit v1.2.3 From f6c1b4d7034f79b51cdacccfa2b5f33e9d0cf41c Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 10 Oct 2021 13:39:03 +0700 Subject: test/thread-exit: Fix use after free bug When I add support for nolibc x86-64, I find this test failed. Long story short, we provide our own `free()` that always unmaps the VM with `munmap()`. It makes the CQE return -EFAULT because the kernel reads unmapped user memory from the pending `write()` SQE. I believe this test can run properly with libc build because `free()` from libc doesn't always unmap the memory, instead it uses free list on the userspace and the freed heap may still be userspace addressable. Fix this by deferring the free. Cc: Jens Axboe Fixes: 2edfa3f84bcc44612b7a04caf1f048f5406fcc7a ("Add test case for thread exiting with pending IO") Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211010063906.341014-2-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- test/thread-exit.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/thread-exit.c b/test/thread-exit.c index 7f66028..b26d4aa 100644 --- a/test/thread-exit.c +++ b/test/thread-exit.c @@ -26,8 +26,18 @@ struct d { unsigned long off; int pipe_fd; int err; + int i; }; +static char *g_buf[NR_IOS] = {NULL}; + +static void free_g_buf(void) +{ + int i; + for (i = 0; i < NR_IOS; i++) + free(g_buf[i]); +} + static void *do_io(void *data) { struct d *d = data; @@ -36,6 +46,7 @@ static void *do_io(void *data) int ret; buffer = t_malloc(WSIZE); + g_buf[d->i] = buffer; memset(buffer, 0x5a, WSIZE); sqe = io_uring_get_sqe(d->ring); if (!sqe) { @@ -55,8 +66,6 @@ static void *do_io(void *data) ret = io_uring_submit(d->ring); if (ret != 2) d->err++; - - free(buffer); return NULL; } @@ -103,6 +112,7 @@ int main(int argc, char *argv[]) d.pipe_fd = fds[0]; d.err = 0; for (i = 0; i < NR_IOS; i++) { + d.i = i; memset(&thread, 0, sizeof(thread)); pthread_create(&thread, NULL, do_io, &d); pthread_join(thread, NULL); @@ -125,7 +135,9 @@ int main(int argc, char *argv[]) io_uring_cqe_seen(&ring, cqe); } + free_g_buf(); return d.err; err: + free_g_buf(); return 1; } -- cgit v1.2.3 From 2fee8240cda50cc28095313c73eb57b07d2a623c Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 10 Oct 2021 20:53:36 +0700 Subject: Add arch dependent directory and files Create a new directory `src/arch` to save arch dependent sources. Add support start from x86-64, add syscalls crafted in Assembly code and lib (currently the lib only contains get page size function). Link: https://github.com/axboe/liburing/issues/443 Reviewed-by: Jens Axboe Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211010135338.397115-2-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- src/arch/x86/lib.h | 26 +++++++ src/arch/x86/syscall.h | 200 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 src/arch/x86/lib.h create mode 100644 src/arch/x86/syscall.h diff --git a/src/arch/x86/lib.h b/src/arch/x86/lib.h new file mode 100644 index 0000000..65ad396 --- /dev/null +++ b/src/arch/x86/lib.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef LIBURING_ARCH_X86_LIB_H +#define LIBURING_ARCH_X86_LIB_H + +#ifndef LIBURING_LIB_H +# error "This file should be included from src/lib.h (liburing)" +#endif + +#if defined(__x86_64__) + +static inline long __arch_impl_get_page_size(void) +{ + return 4096; +} + +#else /* #if defined(__x86_64__) */ + +/* + * TODO: Add x86 (32-bit) support here. + */ +#error "x86 (32-bit) is currently not supported for nolibc builds" + +#endif /* #if defined(__x86_64__) */ + +#endif /* #ifndef LIBURING_ARCH_X86_LIB_H */ diff --git a/src/arch/x86/syscall.h b/src/arch/x86/syscall.h new file mode 100644 index 0000000..2fb3552 --- /dev/null +++ b/src/arch/x86/syscall.h @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef LIBURING_ARCH_X86_SYSCALL_H +#define LIBURING_ARCH_X86_SYSCALL_H + +#ifndef LIBURING_SYSCALL_H +# error "This file should be included from src/syscall.h (liburing)" +#endif + +#if defined(__x86_64__) +/** + * Note for syscall registers usage (x86-64): + * - %rax is the syscall number. + * - %rax is also the return value. + * - %rdi is the 1st argument. + * - %rsi is the 2nd argument. + * - %rdx is the 3rd argument. + * - %r10 is the 4th argument (**yes it's %r10, not %rcx!**). + * - %r8 is the 5th argument. + * - %r9 is the 6th argument. + * + * `syscall` instruction will clobber %r11 and %rcx. + * + * After the syscall returns to userspace: + * - %r11 will contain %rflags. + * - %rcx will contain the return address. + * + * IOW, after the syscall returns to userspace: + * %r11 == %rflags and %rcx == %rip. + */ + +static inline void *__arch_impl_mmap(void *addr, size_t length, int prot, + int flags, int fd, off_t offset) +{ + void *rax; + register int r10 __asm__("r10") = flags; + register int r8 __asm__("r8") = fd; + register off_t r9 __asm__("r9") = offset; + + __asm__ volatile( + "syscall" + : "=a"(rax) /* %rax */ + : "a"(__NR_mmap), /* %rax */ + "D"(addr), /* %rdi */ + "S"(length), /* %rsi */ + "d"(prot), /* %rdx */ + "r"(r10), /* %r10 */ + "r"(r8), /* %r8 */ + "r"(r9) /* %r9 */ + : "memory", "rcx", "r11" + ); + return rax; +} + +static inline int __arch_impl_munmap(void *addr, size_t length) +{ + long rax; + + __asm__ volatile( + "syscall" + : "=a"(rax) /* %rax */ + : "a"(__NR_munmap), /* %rax */ + "D"(addr), /* %rdi */ + "S"(length) /* %rsi */ + : "memory", "rcx", "r11" + ); + return (int) rax; +} + +static inline int __arch_impl_madvise(void *addr, size_t length, int advice) +{ + long rax; + + __asm__ volatile( + "syscall" + : "=a"(rax) /* %rax */ + : "a"(__NR_madvise), /* %rax */ + "D"(addr), /* %rdi */ + "S"(length), /* %rsi */ + "d"(advice) /* %rdx */ + : "memory", "rcx", "r11" + ); + return (int) rax; +} + +static inline int __arch_impl_getrlimit(int resource, struct rlimit *rlim) +{ + long rax; + + __asm__ volatile( + "syscall" + : "=a"(rax) /* %rax */ + : "a"(__NR_getrlimit), /* %rax */ + "D"(resource), /* %rdi */ + "S"(rlim) /* %rsi */ + : "memory", "rcx", "r11" + ); + return (int) rax; +} + +static inline int __arch_impl_setrlimit(int resource, const struct rlimit *rlim) +{ + long rax; + + __asm__ volatile( + "syscall" + : "=a"(rax) /* %rax */ + : "a"(__NR_setrlimit), /* %rax */ + "D"(resource), /* %rdi */ + "S"(rlim) /* %rsi */ + : "memory", "rcx", "r11" + ); + return (int) rax; +} + +static inline int __arch_impl_close(int fd) +{ + long rax; + + __asm__ volatile( + "syscall" + : "=a"(rax) /* %rax */ + : "a"(__NR_close), /* %rax */ + "D"(fd) /* %rdi */ + : "memory", "rcx", "r11" + ); + return (int) rax; +} + +static inline int __arch_impl_io_uring_register(int fd, unsigned opcode, + const void *arg, + unsigned nr_args) +{ + long rax; + register unsigned r10 __asm__("r10") = nr_args; + + __asm__ volatile( + "syscall" + : "=a"(rax) /* %rax */ + : "a"(__NR_io_uring_register), /* %rax */ + "D"(fd), /* %rdi */ + "S"(opcode), /* %rsi */ + "d"(arg), /* %rdx */ + "r"(r10) /* %r10 */ + : "memory", "rcx", "r11" + ); + return (int) rax; +} + +static inline int __arch_impl_io_uring_setup(unsigned entries, + struct io_uring_params *p) +{ + long rax; + + __asm__ volatile( + "syscall" + : "=a"(rax) /* %rax */ + : "a"(__NR_io_uring_setup), /* %rax */ + "D"(entries), /* %rdi */ + "S"(p) /* %rsi */ + : "memory", "rcx", "r11" + ); + return (int) rax; +} + +static inline int __arch_impl_io_uring_enter(int fd, unsigned to_submit, + unsigned min_complete, + unsigned flags, sigset_t *sig, + int sz) +{ + long rax; + register unsigned r10 __asm__("r10") = flags; + register sigset_t *r8 __asm__("r8") = sig; + register int r9 __asm__("r9") = sz; + + __asm__ volatile( + "syscall" + : "=a"(rax) /* %rax */ + : "a"(__NR_io_uring_enter), /* %rax */ + "D"(fd), /* %rdi */ + "S"(to_submit), /* %rsi */ + "d"(min_complete), /* %rdx */ + "r"(r10), /* %r10 */ + "r"(r8), /* %r8 */ + "r"(r9) /* %r9 */ + : "memory", "rcx", "r11" + ); + return (int) rax; +} + +#else /* #if defined(__x86_64__) */ + +/* + * TODO: Add x86 (32-bit) support here. + */ +#error "x86 (32-bit) is currently not supported for nolibc builds" + +#endif /* #if defined(__x86_64__) */ + +#endif /* #ifndef LIBURING_ARCH_X86_SYSCALL_H */ -- cgit v1.2.3 From f48ee3168cdc325233825603269f304d348d323c Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 10 Oct 2021 20:53:37 +0700 Subject: Add nolibc build support Create `src/nolibc.c` to provide libc functions like `memset()`, `malloc()` and `free()`. Only build this file when we build liburing without libc. Add `get_page_size()` function to get the page size. When we build with libc, it uses `sysconf(_SC_PAGESIZE)`, otherwise it uses arch dependent implementation function that we provide at `src/arch` dir. Add conditional preprocessor in `src/syscall.h` to use arch dependent syscalls written in Assembly when we build liburing without libc. Extra notes for tests: 1) Functions in `src/syscall.c` require libc to work. 2) Tests require functions in `src/syscall.c`. So we build `src/syscall.c` manually from the test's Makefile. The Makefile in `src/` dir still builds `src/syscall.c` when we build liburing with libc. Link: https://github.com/axboe/liburing/issues/443 Reviewed-by: Jens Axboe Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211010135338.397115-3-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- src/lib.h | 44 ++++++++++++++++++++++++++++++++++++ src/nolibc.c | 48 +++++++++++++++++++++++++++++++++++++++ src/queue.c | 14 +++--------- src/register.c | 12 +++------- src/setup.c | 17 ++++---------- src/syscall.c | 11 ++++++++- src/syscall.h | 71 +++++++++++++++++++++++++++++++++++++++++++++------------- test/Makefile | 19 ++++++++++++---- 8 files changed, 183 insertions(+), 53 deletions(-) create mode 100644 src/lib.h create mode 100644 src/nolibc.c diff --git a/src/lib.h b/src/lib.h new file mode 100644 index 0000000..58d91be --- /dev/null +++ b/src/lib.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef LIBURING_LIB_H +#define LIBURING_LIB_H + +#include +#include +#include + +#ifdef CONFIG_NOLIBC +# if defined(__x86_64__) || defined(__i386__) +# include "arch/x86/lib.h" +# else +# error "This arch doesn't support building liburing without libc" +# endif +#endif + +#ifndef offsetof +# define offsetof(TYPE, FIELD) ((size_t) &((TYPE *)0)->FIELD) +#endif + +#ifndef container_of +# define container_of(PTR, TYPE, FIELD) ({ \ + __typeof__(((TYPE *)0)->FIELD) *__FIELD_PTR = (PTR); \ + (TYPE *)((char *) __FIELD_PTR - offsetof(TYPE, FIELD)); \ +}) +#endif + + +static inline long get_page_size(void) +{ +#ifdef CONFIG_NOLIBC + return __arch_impl_get_page_size(); +#else + long page_size; + + page_size = sysconf(_SC_PAGESIZE); + if (page_size < 0) + page_size = 4096; + + return page_size; +#endif +} + +#endif /* #ifndef LIBURING_LIB_H */ diff --git a/src/nolibc.c b/src/nolibc.c new file mode 100644 index 0000000..5582ca0 --- /dev/null +++ b/src/nolibc.c @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef CONFIG_NOLIBC +# error "This file should only be compiled for no libc build" +#endif + +#include "lib.h" +#include "syscall.h" + +void *memset(void *s, int c, size_t n) +{ + size_t i; + unsigned char *p = s; + + for (i = 0; i < n; i++) + p[i] = (unsigned char) c; + + return s; +} + +struct uring_heap { + size_t len; + char user_p[]; +}; + +void *malloc(size_t len) +{ + struct uring_heap *heap; + + heap = uring_mmap(NULL, sizeof(*heap) + len, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (IS_ERR(heap)) + return NULL; + + heap->len = sizeof(*heap) + len; + return heap->user_p; +} + +void free(void *p) +{ + struct uring_heap *heap; + + if (uring_unlikely(!p)) + return; + + heap = container_of(p, struct uring_heap, user_p); + uring_munmap(heap, heap->len); +} diff --git a/src/queue.c b/src/queue.c index 9af29d5..eb0c736 100644 --- a/src/queue.c +++ b/src/queue.c @@ -1,19 +1,11 @@ /* SPDX-License-Identifier: MIT */ #define _POSIX_C_SOURCE 200112L -#include -#include -#include -#include -#include -#include - +#include "lib.h" +#include "syscall.h" +#include "liburing.h" #include "liburing/compat.h" #include "liburing/io_uring.h" -#include "liburing.h" -#include "liburing/barrier.h" - -#include "syscall.h" /* * Returns true if we're not using SQ thread (thus nobody submits but us) diff --git a/src/register.c b/src/register.c index 074223f..1f2c409 100644 --- a/src/register.c +++ b/src/register.c @@ -1,18 +1,12 @@ /* SPDX-License-Identifier: MIT */ #define _POSIX_C_SOURCE 200112L -#include -#include -#include -#include -#include -#include - +#include "lib.h" +#include "syscall.h" +#include "liburing.h" #include "liburing/compat.h" #include "liburing/io_uring.h" -#include "liburing.h" -#include "syscall.h" int io_uring_register_buffers_update_tag(struct io_uring *ring, unsigned off, const struct iovec *iovecs, diff --git a/src/setup.c b/src/setup.c index 4f006de..5543468 100644 --- a/src/setup.c +++ b/src/setup.c @@ -1,18 +1,12 @@ /* SPDX-License-Identifier: MIT */ #define _DEFAULT_SOURCE -#include -#include -#include -#include -#include -#include - +#include "lib.h" +#include "syscall.h" +#include "liburing.h" #include "liburing/compat.h" #include "liburing/io_uring.h" -#include "liburing.h" -#include "syscall.h" static void io_uring_unmap_rings(struct io_uring_sq *sq, struct io_uring_cq *cq) { @@ -336,10 +330,7 @@ ssize_t io_uring_mlock_size_params(unsigned entries, struct io_uring_params *p) cq_entries = 2 * entries; } - page_size = sysconf(_SC_PAGESIZE); - if (page_size < 0) - page_size = 4096; - + page_size = get_page_size(); return rings_size(entries, cq_entries, page_size); } diff --git a/src/syscall.c b/src/syscall.c index 5923fbb..4e28e25 100644 --- a/src/syscall.c +++ b/src/syscall.c @@ -1,6 +1,16 @@ /* SPDX-License-Identifier: MIT */ #define _DEFAULT_SOURCE +/* + * Functions in this file require libc, only build them when we use libc. + * + * Note: + * liburing's tests still need these functions. + */ +#if defined(CONFIG_NOLIBC) && !defined(LIBURING_BUILD_TEST) +# error "This file should only be compiled for libc build, or for liburing tests" +#endif + /* * Will go away once libc support is there */ @@ -11,7 +21,6 @@ #include "liburing/io_uring.h" #include "syscall.h" - int __sys_io_uring_register(int fd, unsigned opcode, const void *arg, unsigned nr_args) { diff --git a/src/syscall.h b/src/syscall.h index 9eff968..4b336f1 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -29,13 +29,13 @@ # endif #elif defined __mips__ # ifndef __NR_io_uring_setup -# define __NR_io_uring_setup (__NR_Linux + 425) +# define __NR_io_uring_setup (__NR_Linux + 425) # endif # ifndef __NR_io_uring_enter -# define __NR_io_uring_enter (__NR_Linux + 426) +# define __NR_io_uring_enter (__NR_Linux + 426) # endif # ifndef __NR_io_uring_register -# define __NR_io_uring_register (__NR_Linux + 427) +# define __NR_io_uring_register (__NR_Linux + 427) # endif #else /* !__alpha__ and !__mips__ */ # ifndef __NR_io_uring_setup @@ -49,9 +49,22 @@ # endif #endif - +/* + * Don't put this below the #include "arch/$arch/syscall.h", that + * file may need it. + */ struct io_uring_params; + +#ifdef CONFIG_NOLIBC +# if defined(__x86_64__) || defined(__i386__) +# include "arch/x86/syscall.h" +# else +# error "This arch doesn't support building liburing without libc" +# endif +#endif + + /* * System calls */ @@ -68,12 +81,12 @@ static inline void *ERR_PTR(intptr_t n) return (void *) n; } -static inline intptr_t PTR_ERR(void *ptr) +static inline intptr_t PTR_ERR(const void *ptr) { return (intptr_t) ptr; } -static inline bool IS_ERR(void *ptr) +static inline bool IS_ERR(const void *ptr) { return uring_unlikely((uintptr_t) ptr >= (uintptr_t) -4095UL); } @@ -81,30 +94,40 @@ static inline bool IS_ERR(void *ptr) static inline int ____sys_io_uring_register(int fd, unsigned opcode, const void *arg, unsigned nr_args) { +#ifdef CONFIG_NOLIBC + return __arch_impl_io_uring_register(fd, opcode, arg, nr_args); +#else int ret; - ret = syscall(__NR_io_uring_register, fd, opcode, arg, nr_args); return (ret < 0) ? -errno : ret; +#endif } static inline int ____sys_io_uring_setup(unsigned entries, struct io_uring_params *p) { +#ifdef CONFIG_NOLIBC + return __arch_impl_io_uring_setup(entries, p); +#else int ret; - ret = syscall(__NR_io_uring_setup, entries, p); return (ret < 0) ? -errno : ret; +#endif } static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, unsigned flags, sigset_t *sig, int sz) { +#ifdef CONFIG_NOLIBC + return __arch_impl_io_uring_enter(fd, to_submit, min_complete, flags, + sig, sz); +#else int ret; - ret = syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, sig, sz); return (ret < 0) ? -errno : ret; +#endif } static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, @@ -118,50 +141,68 @@ static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, static inline void *uring_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { +#ifdef CONFIG_NOLIBC + return __arch_impl_mmap(addr, length, prot, flags, fd, offset); +#else void *ret; - ret = mmap(addr, length, prot, flags, fd, offset); return (ret == MAP_FAILED) ? ERR_PTR(-errno) : ret; +#endif } static inline int uring_munmap(void *addr, size_t length) { +#ifdef CONFIG_NOLIBC + return __arch_impl_munmap(addr, length); +#else int ret; - ret = munmap(addr, length); return (ret < 0) ? -errno : ret; +#endif } static inline int uring_madvise(void *addr, size_t length, int advice) { +#ifdef CONFIG_NOLIBC + return __arch_impl_madvise(addr, length, advice); +#else int ret; - ret = madvise(addr, length, advice); return (ret < 0) ? -errno : ret; +#endif } static inline int uring_getrlimit(int resource, struct rlimit *rlim) { +#ifdef CONFIG_NOLIBC + return __arch_impl_getrlimit(resource, rlim); +#else int ret; - ret = getrlimit(resource, rlim); return (ret < 0) ? -errno : ret; +#endif } static inline int uring_setrlimit(int resource, const struct rlimit *rlim) { +#ifdef CONFIG_NOLIBC + return __arch_impl_setrlimit(resource, rlim); +#else int ret; - ret = setrlimit(resource, rlim); return (ret < 0) ? -errno : ret; +#endif } static inline int uring_close(int fd) { +#ifdef CONFIG_NOLIBC + return __arch_impl_close(fd); +#else int ret; - ret = close(fd); return (ret < 0) ? -errno : ret; +#endif } #endif diff --git a/test/Makefile b/test/Makefile index 2936469..1a10a24 100644 --- a/test/Makefile +++ b/test/Makefile @@ -21,8 +21,8 @@ ifdef CONFIG_HAVE_ARRAY_BOUNDS endif CXXFLAGS ?= $(CFLAGS) -override CFLAGS += $(XCFLAGS) -override CXXFLAGS += $(XCFLAGS) -std=c++11 +override CFLAGS += $(XCFLAGS) -DLIBURING_BUILD_TEST +override CXXFLAGS += $(XCFLAGS) -std=c++11 -DLIBURING_BUILD_TEST LDFLAGS ?= override LDFLAGS += -L../src/ -luring @@ -153,11 +153,22 @@ test_targets += sq-full-cpp endif all_targets += sq-full-cpp -helpers = helpers.o +# +# Build ../src/syscall.c manually from test's Makefile to support +# liburing nolibc. +# +# Functions in ../src/syscall.c require libc to work with, if we +# build liburing without libc, we don't have those functions +# in liburing.a. So build it manually here. +# +helpers = helpers.o ../src/syscall.o all: ${helpers} $(test_targets) -helpers.o: helpers.c helpers.c +../src/syscall.o: ../src/syscall.c + $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< + +helpers.o: helpers.c $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< %: %.c ${helpers} helpers.h -- cgit v1.2.3 From c7d03dc2c123bc2ee85582d8f922acd268d6ac78 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 10 Oct 2021 20:53:38 +0700 Subject: configure: Add `CONFIG_NOLIBC` variable and macro It's for conditonal variable and macro to enable nolibc build. Also add `--nolibc` option to `configure` to enable it. Link: https://github.com/axboe/liburing/issues/443 Reviewed-by: Jens Axboe Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211010135338.397115-4-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- configure | 9 +++++++++ src/Makefile | 17 ++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 92f51bd..d2866b3 100755 --- a/configure +++ b/configure @@ -24,6 +24,8 @@ for opt do ;; --cxx=*) cxx="$optarg" ;; + --nolibc) liburing_nolibc="yes" + ;; *) echo "ERROR: unknown option $opt" echo "Try '$0 --help' for more information" @@ -71,6 +73,7 @@ Options: [defaults in brackets after descriptions] --datadir=PATH install shared data in PATH [$datadir] --cc=CMD use CMD as the C compiler --cxx=CMD use CMD as the C++ compiler + --nolibc build liburing without libc EOF exit 0 fi @@ -358,6 +361,12 @@ print_config "has_memfd_create" "$has_memfd_create" ############################################################################# +if test "$liburing_nolibc" = "yes"; then + output_sym "CONFIG_NOLIBC" +else + liburing_nolibc="no" +fi +print_config "liburing_nolibc" "$liburing_nolibc" if test "$__kernel_rwf_t" = "yes"; then output_sym "CONFIG_HAVE_KERNEL_RWF_T" diff --git a/src/Makefile b/src/Makefile index 5e46a9d..09ff395 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,11 +32,22 @@ endif all: $(all_targets) -liburing_srcs := setup.c queue.c syscall.c register.c +liburing_srcs := setup.c queue.c register.c + +ifeq ($(CONFIG_NOLIBC),y) + liburing_srcs += nolibc.c + override CFLAGS += -nostdlib -nodefaultlibs -ffreestanding -fno-stack-protector + override CPPFLAGS += -nostdlib -nodefaultlibs -ffreestanding -fno-stack-protector + override LINK_FLAGS += -nostdlib -nodefaultlibs +else + liburing_srcs += syscall.c +endif liburing_objs := $(patsubst %.c,%.ol,$(liburing_srcs)) liburing_sobjs := $(patsubst %.c,%.os,$(liburing_srcs)) +$(liburing_srcs): syscall.h lib.h + $(liburing_objs) $(liburing_sobjs): include/liburing/io_uring.h %.os: %.c @@ -73,3 +84,7 @@ clean: @rm -f $(all_targets) $(liburing_objs) $(liburing_sobjs) $(soname).new @rm -f *.so* *.a *.o @rm -f include/liburing/compat.h + + @# When cleaning, we don't include ../config-host.mak, + @# so the nolibc objects are always skipped, clean them up! + @rm -f nolibc.ol nolibc.os -- cgit v1.2.3 From e4b1317c35684cd14cc21b5176ec39d56cbcc329 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 11 Oct 2021 07:40:15 +0700 Subject: .github/workflows/build.yml: Add nolibc build x86-64 for CI Fixes: https://github.com/axboe/liburing/issues/443 Signed-off-by: Ammar Faizi --- .github/workflows/build.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a8c0503..b5157cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,10 +33,12 @@ jobs: - name: Build run: | ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}}; - make V=1 -j$(nproc) \ - CPPFLAGS="-Werror" \ - CFLAGS="$FLAGS" \ - CXXFLAGS="$FLAGS"; + make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS"; + + - name: Build nolibc x86-64 + run: | + ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} --nolibc; + make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS"; - name: Build (32 bit) run: | -- cgit v1.2.3 From 106f2d9f25b6687d1b980353af0c03e9faae5517 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 11 Oct 2021 13:49:27 +0700 Subject: src/nolibc: Fix `malloc()` alignment Add `__attribute__((__aligned__))` to the `user_p` to guarantee pointer returned by the `malloc()` is properly aligned for user. This attribute asks the compiler to align a type to the maximum useful alignment for the target machine we are compiling for, which is often, but by no means always, 8 or 16 bytes [1]. Link: https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes [1] Fixes: https://github.com/axboe/liburing/issues/454 Reported-by: Louvian Lyndal Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211011064927.444704-1-ammar.faizi@students.amikom.ac.id Signed-off-by: Jens Axboe --- src/nolibc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nolibc.c b/src/nolibc.c index 5582ca0..251780b 100644 --- a/src/nolibc.c +++ b/src/nolibc.c @@ -20,7 +20,7 @@ void *memset(void *s, int c, size_t n) struct uring_heap { size_t len; - char user_p[]; + char user_p[] __attribute__((__aligned__)); }; void *malloc(size_t len) -- cgit v1.2.3 From fe927f867fd43f83d95de2482f8c9a1e99ec778f Mon Sep 17 00:00:00 2001 From: Nursan Valeyev Date: Mon, 11 Oct 2021 23:40:49 +0300 Subject: setup.c: rewrite `__fls()` Rewrite handmade `__fls()`: use `__builtin_clz()`. Also add `inline` specifier. Signed-off-by: Nursan Valeyev --- src/setup.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/src/setup.c b/src/setup.c index 5543468..891fc43 100644 --- a/src/setup.c +++ b/src/setup.c @@ -211,33 +211,11 @@ void io_uring_free_probe(struct io_uring_probe *probe) free(probe); } -static int __fls(int x) +static inline int __fls(int x) { - int r = 32; - if (!x) return 0; - if (!(x & 0xffff0000u)) { - x <<= 16; - r -= 16; - } - if (!(x & 0xff000000u)) { - x <<= 8; - r -= 8; - } - if (!(x & 0xf0000000u)) { - x <<= 4; - r -= 4; - } - if (!(x & 0xc0000000u)) { - x <<= 2; - r -= 2; - } - if (!(x & 0x80000000u)) { - x <<= 1; - r -= 1; - } - return r; + return 8 * sizeof(x) - __builtin_clz(x); } static unsigned roundup_pow2(unsigned depth) -- cgit v1.2.3 From 49e3095eb27febf4dd2639430cb554a5c694ccf9 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 18 Oct 2021 19:46:00 +0700 Subject: test/timeout: Fix `-Werror=maybe-uninitialized` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix this: ``` timeout.c: In function ‘test_multi_timeout’: timeout.c:590:20: warning: ‘user_data’ may be used uninitialized in this function [-Wmaybe-uninitialized] 590 | if (cqe->user_data != user_data) { | ^ timeout.c:601:51: warning: ‘time’ may be used uninitialized in this function [-Wmaybe-uninitialized] 601 | if (exp < time / 2 || exp > (time * 3) / 2) { | ~~~~~~^~~~ ``` Fixes: 37136cb4423b27dac2fc663b6a0c513b6d7d7ad1 ("test/timeout: add multi timeout reqs test with different timeout") Cc: zhangyi (F) Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/hgUsvvrR9xY-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- test/timeout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/timeout.c b/test/timeout.c index f8ba973..8c35b00 100644 --- a/test/timeout.c +++ b/test/timeout.c @@ -563,8 +563,8 @@ static int test_multi_timeout(struct io_uring *ring) gettimeofday(&tv, NULL); for (i = 0; i < 2; i++) { - unsigned int time; - __u64 user_data; + unsigned int time = 0; + __u64 user_data = 0; ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { -- cgit v1.2.3 From b3813170f9f24f9e18f068a7a1e29747417e360c Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 18 Oct 2021 19:46:01 +0700 Subject: test/timeout-overflow: Fix `-Werror=maybe-uninitialized` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix this: ``` In file included from timeout-overflow.c:12: timeout-overflow.c: In function ‘test_timeout_overflow’: ../src/include/liburing.h:406:9: error: ‘num’ may be used uninitialized in this function [-Werror=maybe-uninitialized] 406 | io_uring_prep_rw(IORING_OP_TIMEOUT, sqe, -1, ts, 1, count); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ timeout-overflow.c:104:26: note: ‘num’ was declared here 104 | unsigned num; | ^~~ ``` Fixes: a4b465536021ee9c4d6d450a9461ddfc116d08b1 ("Add test for overflow of timeout request's sequence") Cc: yangerkun Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/BULrcXMbevM-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- test/timeout-overflow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/timeout-overflow.c b/test/timeout-overflow.c index f952f80..671f171 100644 --- a/test/timeout-overflow.c +++ b/test/timeout-overflow.c @@ -101,7 +101,7 @@ static int test_timeout_overflow(void) msec_to_ts(&ts, TIMEOUT_MSEC); for (i = 0; i < 4; i++) { - unsigned num; + unsigned num = 0; sqe = io_uring_get_sqe(&ring); switch (i) { case 0: -- cgit v1.2.3 From a50c471578158b4c5d85cefbdbaed61296159eac Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 18 Oct 2021 11:11:50 -0600 Subject: Revert "examples/ucontext-cp.c: Do not use SIGSTKSZ" This reverts commit af31ce2cbfcaecc2a6f342532ede5e293a34f7f7. The commit is buggy and causes ucontext-cp to crash. Just revert it for now. Fixes: https://github.com/axboe/liburing/issues/459 Signed-off-by: Jens Axboe --- examples/ucontext-cp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/ucontext-cp.c b/examples/ucontext-cp.c index b1369e2..ea0c934 100644 --- a/examples/ucontext-cp.c +++ b/examples/ucontext-cp.c @@ -3,7 +3,6 @@ * gcc -Wall -O2 -D_GNU_SOURCE -o ucontext-cp ucontext-cp.c -luring */ #define _POSIX_C_SOURCE 199309L -#include #include #include #include @@ -23,7 +22,9 @@ #define QD 64 #define BS 1024 -size_t sigstksz = (8 * 1024 + sizeof (max_align_t) - 1) / sizeof (max_align_t); +#ifndef SIGSTKSZ +#define SIGSTKSZ 8192 +#endif typedef struct { struct io_uring *ring; @@ -114,13 +115,13 @@ static int setup_context(async_context *pctx, struct io_uring *ring) perror("getcontext"); return -1; } - pctx->stack_buf = malloc(sigstksz); + pctx->stack_buf = malloc(SIGSTKSZ); if (!pctx->stack_buf) { perror("malloc"); return -1; } pctx->ctx_fnew.uc_stack.ss_sp = pctx->stack_buf; - pctx->ctx_fnew.uc_stack.ss_size = sigstksz; + pctx->ctx_fnew.uc_stack.ss_size = SIGSTKSZ; pctx->ctx_fnew.uc_link = &pctx->ctx_main; return 0; -- cgit v1.2.3 From c1c92fd4600f8a257992a02dc5767abdfc151964 Mon Sep 17 00:00:00 2001 From: Roman Gershman Date: Thu, 21 Oct 2021 08:08:30 +0300 Subject: Add io_uring_prep_readv2 and io_uring_prep_writev2 helpers These correspond to preadv2 and pwritev2 calls and include flags argument missing in the original helpers. Signed-off-by: Roman Gershman Link: https://github.com/axboe/liburing/issues/461 --- src/include/liburing.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 99f4f37..fc81542 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -312,6 +312,14 @@ static inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd, io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset); } +static inline void io_uring_prep_readv2(struct io_uring_sqe *sqe, int fd, + const struct iovec *iovecs, + unsigned nr_vecs, __u64 offset, int flags) +{ + io_uring_prep_readv(sqe, fd, iovecs, nr_vecs, offset); + sqe->rw_flags = flags; +} + static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd, void *buf, unsigned nbytes, __u64 offset, int buf_index) @@ -327,6 +335,14 @@ static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd, io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset); } +static inline void io_uring_prep_writev2(struct io_uring_sqe *sqe, int fd, + const struct iovec *iovecs, + unsigned nr_vecs, __u64 offset, int flags) +{ + io_uring_prep_writev(sqe, fd, iovecs, nr_vecs, offset); + sqe->rw_flags = flags; +} + static inline void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd, const void *buf, unsigned nbytes, __u64 offset, int buf_index) -- cgit v1.2.3 From afa42f645102365fc35ed6bb5c4f894e266711eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chaloupka?= Date: Sun, 24 Oct 2021 17:32:23 +0200 Subject: Fix invalid opcode used in io_uring_unregister_iowq_aff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just a trivial fix of used opcode IORING_REGISTER_IOWQ_AFF -> IORING_UNREGISTER_IOWQ_AFF. Signed-off-by: Tomáš Chaloupka Fixes: https://github.com/axboe/liburing/issues/463 --- src/register.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/register.c b/src/register.c index 1f2c409..a1b1a22 100644 --- a/src/register.c +++ b/src/register.c @@ -248,7 +248,7 @@ int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, int io_uring_unregister_iowq_aff(struct io_uring *ring) { return ____sys_io_uring_register(ring->ring_fd, - IORING_REGISTER_IOWQ_AFF, NULL, 0); + IORING_UNREGISTER_IOWQ_AFF, NULL, 0); } int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *val) -- cgit v1.2.3 From eda46b2197f637bc037339502a21c4521bb918ed Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 30 Oct 2021 14:56:13 +0700 Subject: .github: Create pull_request_template.md GitHub throws away the relevant information like having even a valid email address for the person asking to pull. Another common problem on GitHub, people don't do any of the simplest things that the kernel people expect from a commit message, like: - No "short one-line description in the first line". - No sane word-wrap of the long description. GitHub commit messages tend to be (if they have any description at all) one long unreadable line. - No sign-off and other tags that we require for commit message. Let's fix this by creating a pull request template that contains pull request guidelines for GitHub Pull Request. Link: https://github.com/axboe/liburing/pull/464#issuecomment-950950688 Signed-off-by: Ammar Faizi --- .github/pull_request_template.md | 76 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..5c7e29c --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,76 @@ + + + +---- +## git request-pull output: +``` + + +Generate your PR shortlog and diffstat with these commands: + git remote add axboe-tree https://github.com/axboe/liburing + git fetch axboe-tree + git request-pull axboe-tree/master your_fork_URL your_branch_name + +Then replace this with the output of `git request-pull` command. + + +``` +---- +
+Click to show/hide pull request guidelines + +## Pull Request Guidelines +1. To make everyone easily filter pull request from the email +notification, use `[GIT PULL]` as a prefix in your PR title. +``` +[GIT PULL] Your Pull Request Title +``` +2. Follow the commit message format rules below. +3. Follow the Linux kernel coding style (see: https://github.com/torvalds/linux/blob/master/Documentation/process/coding-style.rst). + +### Commit message format rules: +1. The first line is title (don't be more than 72 chars if possible). +2. Then an empty line. +3. Then a description (may be omitted for trivial changes). +4. Then an empty line again (if it has a description). +5. Then a `Signed-off-by` tag with your real name and email. For example: +``` +Signed-off-by: Foo Bar +``` + +Description should be word-wrapped at 72 chars. Some things should not +be word-wrapped. They may be some kind of quoted text - long compiler +error messages, oops reports, Link, etc. (things that have a certain +specific format). + +If the commit is a fix for an issue, add a `Fixes` tag with the issue +URL. + +Don't use GitHub anonymous email like this as the commit author: +``` +123456789+username@users.noreply.github.com +``` + +Use a real email address! + +### Commit message example: +``` +src/queue: don't flush SQ ring for new wait interface + +If we have IORING_FEAT_EXT_ARG, then timeouts are done through the +syscall instead of by posting an internal timeout. This was done +to be both more efficient, but also to enable multi-threaded use +the wait side. If we touch the SQ state by flushing it, that isn't +safe without synchronization. + +Fixes: https://github.com/axboe/liburing/issues/402 +Signed-off-by: Jens Axboe +``` + +
+ +---- +## By submitting this pull request, I acknowledge that: +1. I have followed the above pull request guidelines. +2. I have the rights to submit this work under the same license. +3. I agree to a Developer Certificate of Origin (see https://developercertificate.org for more information). -- cgit v1.2.3 From d543ff1a23d0a9ad7a2628f60194896f9033f27e Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 30 Oct 2021 22:55:53 +0700 Subject: examples/Makefile: Fix missing clean up Several things go wrong with this Makefile: 1) Using `test_srcs` to generate `test_objs`. 2) `test_objs` is an unused variable. So (1) is pointless. 3) `make clean` does not remove `ucontext-cp` binary. I assume (1) and (2) were blindly copied from the test Makefile. For 3, the `make clean` removes $(all_targets) and $(test_objs). But `ucontext-cp` only exists in $(all_targets) if we have `CONFIG_HAVE_UCONTEXT`. When the target goal is `clean`, we will not have any of `CONFIG_*` variables. Thus, `ucontext-cp` is not removed. Clean them up! Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211030114858.320116-2-ammar.faizi@intel.com Signed-off-by: Jens Axboe --- examples/Makefile | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index d3c5000..f966f94 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -10,20 +10,29 @@ ifneq ($(MAKECMDGOALS),clean) include ../config-host.mak endif -all_targets += io_uring-test io_uring-cp link-cp +example_srcs := \ + io_uring-cp.c \ + io_uring-test.c \ + link-cp.c + +all_targets := + ifdef CONFIG_HAVE_UCONTEXT -all_targets += ucontext-cp + example_srcs += ucontext-cp.c endif +all_targets += ucontext-cp -all: $(all_targets) +example_targets := $(patsubst %.c,%,$(patsubst %.cc,%,$(example_srcs))) +all_targets += $(example_targets) -test_srcs := io_uring-test.c io_uring-cp.c link-cp.c -test_objs := $(patsubst %.c,%.ol,$(test_srcs)) +all: $(example_targets) %: %.c $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(LDFLAGS) clean: - @rm -f $(all_targets) $(test_objs) + @rm -f $(all_targets) + +.PHONY: all clean -- cgit v1.2.3 From bceaacc35f9e75469f6179d63436d67dc5bd47d0 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 30 Oct 2021 22:55:54 +0700 Subject: test/Makefile: Refactor the Makefile The Makefile for test is not efficient and reads bad. We have to specify the name for each test 2 times (filename and name without the ext) while we could have just elided the extension from the source filename. Let's make it simpler and easier to manage. Changes summary: - Clean up and reorder things. - Sort the `test_srcs` alphabetically. - Remove `test_objs` (it turned out unused). - Generate `test_targets` variable from `test_srcs` by simply removing the `.c` and `.cc` file extension. Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20211030114858.320116-3-ammar.faizi@intel.com Signed-off-by: Jens Axboe --- test/Makefile | 263 ++++++++++++++++++---------------------------------------- 1 file changed, 83 insertions(+), 180 deletions(-) diff --git a/test/Makefile b/test/Makefile index 1a10a24..f7eafad 100644 --- a/test/Makefile +++ b/test/Makefile @@ -8,177 +8,32 @@ include ../config-host.mak endif CPPFLAGS ?= -override CPPFLAGS += -D_GNU_SOURCE -D__SANE_USERSPACE_TYPES__ \ - -I../src/include/ -include ../config-host.h -CFLAGS ?= -g -O2 -Wall -Wextra +override CPPFLAGS += \ + -D_GNU_SOURCE \ + -D__SANE_USERSPACE_TYPES__ \ + -I../src/include/ \ + -include ../config-host.h + +CFLAGS ?= -g -O2 -Wall -Wextra XCFLAGS = -Wno-unused-parameter -Wno-sign-compare + ifdef CONFIG_HAVE_STRINGOP_OVERFLOW - XCFLAGS += -Wstringop-overflow=0 + XCFLAGS += -Wstringop-overflow=0 endif + ifdef CONFIG_HAVE_ARRAY_BOUNDS - XCFLAGS += -Warray-bounds=0 + XCFLAGS += -Warray-bounds=0 endif CXXFLAGS ?= $(CFLAGS) override CFLAGS += $(XCFLAGS) -DLIBURING_BUILD_TEST override CXXFLAGS += $(XCFLAGS) -std=c++11 -DLIBURING_BUILD_TEST + LDFLAGS ?= override LDFLAGS += -L../src/ -luring -test_targets += \ - 232c93d07b74-test \ - 35fa71a030ca-test \ - 500f9fbadef8-test \ - 7ad0e4b2f83c-test \ - 8a9973408177-test \ - 917257daa0fe-test \ - a0908ae19763-test \ - a4c0b3decb33-test \ - accept \ - accept-link \ - accept-reuse \ - accept-test \ - across-fork splice \ - b19062a56726-test \ - b5837bd5311d-test \ - ce593a6c480a-test \ - close-opath \ - connect \ - cq-full \ - cq-overflow \ - cq-peek-batch \ - cq-ready \ - cq-size \ - d4ae271dfaae-test \ - d77a67ed5f27-test \ - defer \ - double-poll-crash \ - eeed8b54e0df-test \ - empty-eownerdead \ - eventfd \ - eventfd-disable \ - eventfd-ring \ - fadvise \ - fallocate \ - fc2a85cb02ef-test \ - file-register \ - file-verify \ - file-update \ - files-exit-hang-poll \ - files-exit-hang-timeout \ - fixed-link \ - fsync \ - hardlink \ - io-cancel \ - io_uring_enter \ - io_uring_register \ - io_uring_setup \ - iopoll \ - lfs-openat \ - lfs-openat-write \ - link \ - link-timeout \ - link_drain \ - madvise \ - mkdir \ - multicqes_drain \ - nop \ - nop-all-sizes \ - open-close \ - openat2 \ - personality \ - pipe-eof \ - pipe-reuse \ - poll \ - poll-cancel \ - poll-cancel-ton \ - poll-link \ - poll-many \ - poll-mshot-update \ - poll-ring \ - poll-v-poll \ - probe \ - read-write \ - register-restrictions \ - rename \ - ring-leak \ - ring-leak2 \ - rw_merge_test \ - self \ - send_recv \ - send_recvmsg \ - shared-wq \ - short-read \ - shutdown \ - sigfd-deadlock \ - socket-rw \ - socket-rw-eagain \ - sq-full \ - sq-poll-dup \ - sq-poll-kthread \ - sq-poll-share \ - sqpoll-disable-exit \ - sqpoll-exit-hang \ - sqpoll-cancel-hang \ - sqpoll-sleep \ - sq-space_left \ - stdout \ - submit-reuse \ - submit-link-fail \ - symlink \ - teardowns \ - thread-exit \ - timeout \ - timeout-new \ - timeout-overflow \ - unlink \ - wakeup-hang \ - sendmsg_fs_cve \ - rsrc_tags \ - exec-target \ - # EOL - -all_targets += $(test_targets) - -include ../Makefile.quiet - -ifdef CONFIG_HAVE_STATX -test_targets += statx -endif -all_targets += statx - -ifdef CONFIG_HAVE_CXX -test_targets += sq-full-cpp -endif -all_targets += sq-full-cpp - -# -# Build ../src/syscall.c manually from test's Makefile to support -# liburing nolibc. -# -# Functions in ../src/syscall.c require libc to work with, if we -# build liburing without libc, we don't have those functions -# in liburing.a. So build it manually here. -# -helpers = helpers.o ../src/syscall.o - -all: ${helpers} $(test_targets) - -../src/syscall.o: ../src/syscall.c - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< - -helpers.o: helpers.c - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< - -%: %.c ${helpers} helpers.h - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< ${helpers} $(LDFLAGS) - -%: %.cc ${helpers} helpers.h - $(QUIET_CXX)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< ${helpers} $(LDFLAGS) - test_srcs := \ - helpers.c \ 232c93d07b74-test.c \ 35fa71a030ca-test.c \ 500f9fbadef8-test.c \ @@ -187,10 +42,10 @@ test_srcs := \ 917257daa0fe-test.c \ a0908ae19763-test.c \ a4c0b3decb33-test.c \ + accept.c \ accept-link.c \ accept-reuse.c \ accept-test.c \ - accept.c \ across-fork.c \ b19062a56726-test.c \ b5837bd5311d-test.c \ @@ -200,7 +55,7 @@ test_srcs := \ cq-full.c \ cq-overflow.c \ cq-peek-batch.c \ - cq-ready.c\ + cq-ready.c \ cq-size.c \ d4ae271dfaae-test.c \ d77a67ed5f27-test.c \ @@ -208,56 +63,60 @@ test_srcs := \ double-poll-crash.c \ eeed8b54e0df-test.c \ empty-eownerdead.c \ + eventfd.c \ eventfd-disable.c \ eventfd-ring.c \ - eventfd.c \ + exec-target.c \ fadvise.c \ fallocate.c \ fc2a85cb02ef-test.c \ file-register.c \ - file-verify.c \ - file-update.c \ files-exit-hang-poll.c \ files-exit-hang-timeout.c \ + file-update.c \ + file-verify.c \ fixed-link.c \ fsync.c \ hardlink.c \ io-cancel.c \ + iopoll.c \ io_uring_enter.c \ io_uring_register.c \ io_uring_setup.c \ - iopoll.c \ - lfs-openat-write.c \ lfs-openat.c \ - link-timeout.c \ + lfs-openat-write.c \ link.c \ link_drain.c \ + link-timeout.c \ madvise.c \ mkdir.c \ multicqes_drain.c \ nop-all-sizes.c \ nop.c \ - open-close.c \ openat2.c \ + open-close.c \ personality.c \ pipe-eof.c \ pipe-reuse.c \ - poll-cancel-ton.c \ + poll.c \ poll-cancel.c \ + poll-cancel-ton.c \ poll-link.c \ poll-many.c \ poll-mshot-update.c \ poll-ring.c \ poll-v-poll.c \ - poll.c \ probe.c \ read-write.c \ register-restrictions.c \ rename.c \ - ring-leak.c \ ring-leak2.c \ + ring-leak.c \ + rsrc_tags.c \ rw_merge_test.c \ self.c \ + sendmsg_fs_cve.c \ + send_recv.c \ send_recvmsg.c \ shared-wq.c \ short-read.c \ @@ -266,34 +125,74 @@ test_srcs := \ socket-rw.c \ socket-rw-eagain.c \ splice.c \ - sq-full-cpp.cc \ sq-full.c \ + sq-full-cpp.cc \ + sqpoll-cancel-hang.c \ + sqpoll-disable-exit.c \ sq-poll-dup.c \ + sqpoll-exit-hang.c \ sq-poll-kthread.c \ sq-poll-share.c \ - sqpoll-disable-exit.c \ - sqpoll-exit-hang.c \ - sqpoll-cancel-hang.c \ sqpoll-sleep.c \ sq-space_left.c \ statx.c \ stdout.c \ - submit-reuse.c \ submit-link-fail.c \ + submit-reuse.c \ symlink.c \ teardowns.c \ thread-exit.c \ + timeout.c \ timeout-new.c \ timeout-overflow.c \ - timeout.c \ unlink.c \ wakeup-hang.c \ - sendmsg_fs_cve.c \ - rsrc_tags.c \ - exec-target.c \ # EOL -test_objs := $(patsubst %.c,%.ol,$(patsubst %.cc,%.ol,$(test_srcs))) + +all_targets := +include ../Makefile.quiet + + +ifdef CONFIG_HAVE_STATX + test_srcs += statx.c +endif +all_targets += statx + + +ifdef CONFIG_HAVE_CXX + test_srcs += sq-full-cpp.cc +endif +all_targets += sq-full-cpp + + +test_targets := $(patsubst %.c,%,$(patsubst %.cc,%,$(test_srcs))) +all_targets += $(test_targets) + +# +# Build ../src/syscall.c manually from test's Makefile to support +# liburing nolibc. +# +# Functions in ../src/syscall.c require libc to work with, if we +# build liburing without libc, we don't have those functions +# in liburing.a. So build it manually here. +# +helpers = helpers.o ../src/syscall.o + +all: $(test_targets) + +../src/syscall.o: ../src/syscall.c + $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< + +helpers.o: helpers.c + $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< + +%: %.c $(helpers) helpers.h + $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(helpers) $(LDFLAGS) + +%: %.cc $(helpers) helpers.h + $(QUIET_CXX)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< $(helpers) $(LDFLAGS) + 35fa71a030ca-test: override LDFLAGS += -lpthread 232c93d07b74-test: override LDFLAGS += -lpthread @@ -317,11 +216,15 @@ install: $(test_targets) runtests.sh runtests-loop.sh $(INSTALL) -D -m 755 $(test_targets) $(datadir)/liburing-test/ $(INSTALL) -D -m 755 runtests.sh $(datadir)/liburing-test/ $(INSTALL) -D -m 755 runtests-loop.sh $(datadir)/liburing-test/ + clean: - @rm -f $(all_targets) $(test_objs) helpers.o output/* + @rm -f $(all_targets) helpers.o output/* @rm -rf output/ runtests: all @./runtests.sh $(test_targets) + runtests-loop: all @./runtests-loop.sh $(test_targets) + +.PHONY: all install clean runtests runtests-loop -- cgit v1.2.3 From b0f1f96823ae33648c267115989ea61f29d25e2c Mon Sep 17 00:00:00 2001 From: GalaxySnail Date: Fri, 5 Nov 2021 23:18:21 +0800 Subject: man/io_uring_setup.2: add missing `wq_fd` field Add missing `wq_fd` field for `struct io_uring_params`. Fixes: https://github.com/axboe/liburing/issues/473 Signed-off-by: Luchen Yang --- man/io_uring_setup.2 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index 88ce1f9..d527a6a 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -37,7 +37,8 @@ struct io_uring_params { __u32 sq_thread_cpu; __u32 sq_thread_idle; __u32 features; - __u32 resv[4]; + __u32 wq_fd; + __u32 resv[3]; struct io_sqring_offsets sq_off; struct io_cqring_offsets cq_off; }; -- cgit v1.2.3 From 7b5681f82bf53b42afc7cb35482036559d5bad42 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 6 Nov 2021 15:16:23 -0600 Subject: test/io-cancel: -ECANCELED is a valid return value -EINTR relies on io-wq, we can also find and cancel before that. Make sure the test allows it, fixing the following case failure on newer kernels: 1 -125 child failed 1 test_cancel_req_across_fork() failed Signed-off-by: Jens Axboe --- test/io-cancel.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/io-cancel.c b/test/io-cancel.c index b5b443d..703ffa7 100644 --- a/test/io-cancel.c +++ b/test/io-cancel.c @@ -341,8 +341,21 @@ static int test_cancel_req_across_fork(void) fprintf(stderr, "wait_cqe=%d\n", ret); return 1; } - if ((cqe->user_data == 1 && cqe->res != -EINTR) || - (cqe->user_data == 2 && cqe->res != -EALREADY && cqe->res)) { + switch (cqe->user_data) { + case 1: + if (cqe->res != -EINTR && + cqe->res != -ECANCELED) { + fprintf(stderr, "%i %i\n", (int)cqe->user_data, cqe->res); + exit(1); + } + break; + case 2: + if (cqe->res != -EALREADY && cqe->res) { + fprintf(stderr, "%i %i\n", (int)cqe->user_data, cqe->res); + exit(1); + } + break; + default: fprintf(stderr, "%i %i\n", (int)cqe->user_data, cqe->res); exit(1); } -- cgit v1.2.3 From 02044504559ee4e428c8dd05afbb046c1d8ea53b Mon Sep 17 00:00:00 2001 From: Yinan Zhang Date: Mon, 8 Nov 2021 17:22:09 -0800 Subject: Remove unused variable in man page example Signed-off-by: Yinan Zhang --- man/io_uring.7 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring.7 b/man/io_uring.7 index dc76f42..0a47831 100644 --- a/man/io_uring.7 +++ b/man/io_uring.7 @@ -641,7 +641,7 @@ int app_setup_uring(void) { int read_from_cq() { struct io_uring_cqe *cqe; - unsigned head, reaped = 0; + unsigned head; /* Read barrier */ head = io_uring_smp_load_acquire(cring_head); -- cgit v1.2.3 From 890179d06befbed024e3027d91ebe63a1018cfa0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 12 Nov 2021 10:09:51 -0700 Subject: Add more explanations to the github PR template I don't care about what happens on github, the git tree is what is important in terms of commit messages. Add a section on splitting changes up. Each change should do just one thing. If it does more than one thing, most likely it should be in a separate commit. Signed-off-by: Jens Axboe --- .github/pull_request_template.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 5c7e29c..ae9f4de 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -31,17 +31,27 @@ notification, use `[GIT PULL]` as a prefix in your PR title. ### Commit message format rules: 1. The first line is title (don't be more than 72 chars if possible). 2. Then an empty line. -3. Then a description (may be omitted for trivial changes). +3. Then a description (may be omitted for truly trivial changes). 4. Then an empty line again (if it has a description). 5. Then a `Signed-off-by` tag with your real name and email. For example: ``` Signed-off-by: Foo Bar ``` -Description should be word-wrapped at 72 chars. Some things should not -be word-wrapped. They may be some kind of quoted text - long compiler -error messages, oops reports, Link, etc. (things that have a certain -specific format). +The description should be word-wrapped at 72 chars. Some things should +not be word-wrapped. They may be some kind of quoted text - long +compiler error messages, oops reports, Link, etc. (things that have a +certain specific format). + +Note that all of this goes in the commit message, not in the pull +request text. The pull request text should introduce what this pull +request does, and each commit message should explain the rationale for +why that particular change was made. The git tree is canonical source +of truth, not github. + +Each patch should do one thing, and one thing only. If you find yourself +writing an explanation for why a patch is fixing multiple issues, that's +a good indication that the change should be split into separate patches. If the commit is a fix for an issue, add a `Fixes` tag with the issue URL. -- cgit v1.2.3 From 44b12f54191574462df337f0b2a2bcad147fd80b Mon Sep 17 00:00:00 2001 From: Bikal Lem Date: Fri, 12 Nov 2021 17:28:32 +0000 Subject: fix 'make' when using glibc >= 2.28 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit glibc >= 2.28 supports `statx` out of the box. This means we get an error when attempting to build `liburing` when glibc is >= 2.28, for e.g. in my glibc version 2.33 I get the following errors ``` :26:8: error: redefinition of ‘struct statx_timestamp’ 26 | struct statx_timestamp | ^~~~~~~~~~~~~~~ In file included from statx.c:14: ``` or ``` error: redefinition of ‘struct statx’ 30 | struct statx | ^~~~~ In file included from statx.c:14: ``` This commit fixes 'make' error by choosing to use the glibc version of `statx` if available. glibc 2.28 release notes: https://sourceware.org/git/?p=glibc.git;a=blob;f=NEWS;h=154ab22d7ca065af5233406927302bb7f6a66890;hb=3c03baca37fdcb52c3881e653ca392bba7a99c2b#l84 Signed-off-by: Bikal Lem --- configure | 31 ++++++++++++++++++++++++++++++- src/include/liburing.h | 1 - test/Makefile | 4 ++++ test/file-verify.c | 1 + test/rename.c | 1 + test/unlink.c | 1 + 6 files changed, 37 insertions(+), 2 deletions(-) diff --git a/configure b/configure index d2866b3..2061148 100755 --- a/configure +++ b/configure @@ -268,7 +268,6 @@ print_config "__kernel_timespec" "$__kernel_timespec" open_how="no" cat > $TMPC << EOF #include -#include #include #include #include @@ -308,6 +307,27 @@ if compile_prog "" "" "statx"; then fi print_config "statx" "$statx" +########################################## +# check for glibc statx +glibc_statx="no" +cat > $TMPC << EOF +#include +#include +#include +#include +#include +int main(int argc, char **argv) +{ + struct statx x; + + return memset(&x, 0, sizeof(x)) != NULL; +} +EOF +if compile_prog "" "" "glibc_statx"; then + glibc_statx="yes" +fi +print_config "glibc_statx" "$glibc_statx" + ########################################## # check for C++ has_cxx="no" @@ -380,6 +400,9 @@ fi if test "$statx" = "yes"; then output_sym "CONFIG_HAVE_STATX" fi +if test "$glibc_statx" = "yes"; then + output_sym "CONFIG_HAVE_GLIBC_STATX" +fi if test "$has_cxx" = "yes"; then output_sym "CONFIG_HAVE_CXX" fi @@ -446,6 +469,12 @@ EOF else cat >> $compat_h << EOF #include +EOF +fi +if test "$glibc_statx" = "no" && "$statx" = "yes"; then +cat >> $compat_h << EOF +#include + EOF fi diff --git a/src/include/liburing.h b/src/include/liburing.h index fc81542..169e098 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff --git a/test/Makefile b/test/Makefile index f7eafad..d6e7227 100644 --- a/test/Makefile +++ b/test/Makefile @@ -157,6 +157,10 @@ include ../Makefile.quiet ifdef CONFIG_HAVE_STATX test_srcs += statx.c endif + +ifdef CONFIG_HAVE_GLIBC_STATX + test_srcs += statx.c +endif all_targets += statx diff --git a/test/file-verify.c b/test/file-verify.c index 50cad45..327cb1d 100644 --- a/test/file-verify.c +++ b/test/file-verify.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "helpers.h" diff --git a/test/rename.c b/test/rename.c index af09d65..7798d43 100644 --- a/test/rename.c +++ b/test/rename.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "liburing.h" diff --git a/test/unlink.c b/test/unlink.c index f8c7639..e4c210b 100644 --- a/test/unlink.c +++ b/test/unlink.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "liburing.h" -- cgit v1.2.3 From 82b22c8fe33a7250381a956b127955940422c90f Mon Sep 17 00:00:00 2001 From: Bikal Lem Date: Fri, 12 Nov 2021 18:37:12 +0000 Subject: runtests: use env to find bash This commit fixes running 'make runtests' in OSes where '/bin/bash' is not defined. We use a more portable version, i.e. '/usr/bin/env bash' instead. Signed-off-by: Bikal Lem --- test/runtests-loop.sh | 2 +- test/runtests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/runtests-loop.sh b/test/runtests-loop.sh index f56d26d..b80bc76 100755 --- a/test/runtests-loop.sh +++ b/test/runtests-loop.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash TESTS=("$@") ITER=0 diff --git a/test/runtests.sh b/test/runtests.sh index c77df6a..122e482 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash TESTS=("$@") RET=0 -- cgit v1.2.3 From c0b43df28a982747e081343f23289357ab4615db Mon Sep 17 00:00:00 2001 From: Bikal Lem Date: Mon, 15 Nov 2021 13:09:30 +0000 Subject: src/Makefile: use VERSION variable consistently src/Makefile defines incorrect 'liburing.so' version, i.e 2.1 as opposed to 2.2. This commit makes src/Makefile use correct version defined in liburing.spec. Along the way we refactor the use of common variables into Makefile.common and include it into both src/Makefile and Makefile. Signed-off-by: Bikal Lem --- Makefile | 6 ++---- Makefile.common | 5 +++++ liburing.spec | 2 +- src/Makefile | 8 ++++---- 4 files changed, 12 insertions(+), 9 deletions(-) create mode 100644 Makefile.common diff --git a/Makefile b/Makefile index 5d9c4dc..28c0fd8 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,5 @@ -NAME=liburing -SPECFILE=$(NAME).spec -VERSION=$(shell awk '/Version:/ { print $$2 }' $(SPECFILE)) -TAG = $(NAME)-$(VERSION) +include Makefile.common + RPMBUILD=$(shell `which rpmbuild >&/dev/null` && echo "rpmbuild" || echo "rpm") INSTALL=install diff --git a/Makefile.common b/Makefile.common new file mode 100644 index 0000000..e7c9412 --- /dev/null +++ b/Makefile.common @@ -0,0 +1,5 @@ +TOP := $(dir $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) +NAME=liburing +SPECFILE=$(TOP)/$(NAME).spec +VERSION=$(shell awk '/Version:/ { print $$2 }' $(SPECFILE)) +TAG = $(NAME)-$(VERSION) diff --git a/liburing.spec b/liburing.spec index 7eb5731..df62d2f 100644 --- a/liburing.spec +++ b/liburing.spec @@ -1,5 +1,5 @@ Name: liburing -Version: 2.1 +Version: 2.2 Release: 1%{?dist} Summary: Linux-native io_uring I/O access library License: (GPLv2 with exceptions and LGPLv2+) or MIT diff --git a/src/Makefile b/src/Makefile index 09ff395..c29a80d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,3 +1,5 @@ +include ../Makefile.common + prefix ?= /usr includedir ?= $(prefix)/include libdir ?= $(prefix)/lib @@ -14,10 +16,8 @@ LINK_FLAGS= LINK_FLAGS+=$(LDFLAGS) ENABLE_SHARED ?= 1 -soname=liburing.so.2 -minor=1 -micro=0 -libname=$(soname).$(minor).$(micro) +soname=liburing.so +libname=$(soname).$(VERSION) all_targets += liburing.a ifeq ($(ENABLE_SHARED),1) -- cgit v1.2.3 From 2a4091133858c659fb1cb7f42642ebcb44032e86 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Wed, 17 Nov 2021 12:02:04 -0800 Subject: liburing: add missing man pages Add missing man pages for liburing functions. Signed-off-by: Stefan Roesch Signed-off-by: Jens Axboe --- man/io_uring_cqe_seen.3 | 32 ++++++++++++++++++ man/io_uring_prep_read.3 | 38 +++++++++++++++++++++ man/io_uring_prep_readv.3 | 37 +++++++++++++++++++++ man/io_uring_prep_readv2.3 | 60 ++++++++++++++++++++++++++++++++++ man/io_uring_prep_write.3 | 38 +++++++++++++++++++++ man/io_uring_prep_writev.3 | 37 +++++++++++++++++++++ man/io_uring_prep_writev2.3 | 60 ++++++++++++++++++++++++++++++++++ man/io_uring_register_buffers.3 | 34 +++++++++++++++++++ man/io_uring_register_files.3 | 35 ++++++++++++++++++++ man/io_uring_sqe_get_data.3 | 34 +++++++++++++++++++ man/io_uring_sqe_set_data.3 | 30 +++++++++++++++++ man/io_uring_submit.3 | 29 ++++++++++++++++ man/io_uring_submit_and_wait.3 | 34 +++++++++++++++++++ man/io_uring_submit_and_wait_timeout.3 | 49 +++++++++++++++++++++++++++ man/io_uring_unregister_buffers.3 | 26 +++++++++++++++ man/io_uring_unregister_files.3 | 26 +++++++++++++++ man/io_uring_wait_cqe.3 | 33 +++++++++++++++++++ man/io_uring_wait_cqe_nr.3 | 36 ++++++++++++++++++++ man/io_uring_wait_cqe_timeout.3 | 39 ++++++++++++++++++++++ man/io_uring_wait_cqes.3 | 46 ++++++++++++++++++++++++++ 20 files changed, 753 insertions(+) create mode 100644 man/io_uring_cqe_seen.3 create mode 100644 man/io_uring_prep_read.3 create mode 100644 man/io_uring_prep_readv.3 create mode 100644 man/io_uring_prep_readv2.3 create mode 100644 man/io_uring_prep_write.3 create mode 100644 man/io_uring_prep_writev.3 create mode 100644 man/io_uring_prep_writev2.3 create mode 100644 man/io_uring_register_buffers.3 create mode 100644 man/io_uring_register_files.3 create mode 100644 man/io_uring_sqe_get_data.3 create mode 100644 man/io_uring_sqe_set_data.3 create mode 100644 man/io_uring_submit.3 create mode 100644 man/io_uring_submit_and_wait.3 create mode 100644 man/io_uring_submit_and_wait_timeout.3 create mode 100644 man/io_uring_unregister_buffers.3 create mode 100644 man/io_uring_unregister_files.3 create mode 100644 man/io_uring_wait_cqe.3 create mode 100644 man/io_uring_wait_cqe_nr.3 create mode 100644 man/io_uring_wait_cqe_timeout.3 create mode 100644 man/io_uring_wait_cqes.3 diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3 new file mode 100644 index 0000000..6a8b151 --- /dev/null +++ b/man/io_uring_cqe_seen.3 @@ -0,0 +1,32 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_cqe_seen 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_cqe_seen - Mark io_uring completion event as processed +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_cqe_seen(struct io_uring *ring," +.BI " struct io_uring_cqe *cqe)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_cqe_seen() function marks the IO completion +.I cqe +belonging to the +.I ring +param as processed. + +After the caller has submitted a request with io_uring_submit(), he can retrieve +the completion with io_uring_wait_cqe() and mark it then as processed with +io_uring_cqe_seen(). + +Completions must be marked as completed, so their slot can get reused. +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_wait_cqe(3) \ No newline at end of file diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 new file mode 100644 index 0000000..e3feb1f --- /dev/null +++ b/man/io_uring_prep_read.3 @@ -0,0 +1,38 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_read 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_prep_read - prepare I/O read request + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_read(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " void *buf," +.BI " unsigned nbytes," +.BI " __u64 offset)" + +.SH DESCRIPTION +.PP +The io_uring_prep_read() prepares an IO read request. The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start reading +.I nbytes +into the buffer +.I buf +at the +.I offset. + +After the read has been prepared it can be submitted with one of the submit +functions. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_prep_readv (3), io_uring_prep_readv2 (3), io_uring_submit(3) diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 new file mode 100644 index 0000000..31eebc1 --- /dev/null +++ b/man/io_uring_prep_readv.3 @@ -0,0 +1,37 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_readv 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_prep_readv - prepare vector I/O read request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_readv(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " const struct iovec *iovecs," +.BI " unsigned nr_vecs," +.BI " __u64 offset)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_readv() prepares a vectored IO read request. The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start reading +.I nr_vecs +into the +.I iovecs +array at +.I offset. + +After the write has been prepared it can be submitted with one of the submit +functions. +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_prep_read (3), io_uring_prep_readv2 (3), io_uring_submit (3) diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 new file mode 100644 index 0000000..2755281 --- /dev/null +++ b/man/io_uring_prep_readv2.3 @@ -0,0 +1,60 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_readv2 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +.fi +io_uring_prep_readv2 - prepare vector I/O read request with flags + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_readv2(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " const struct iovec *iovecs," +.BI " unsigned nr_vecs," +.BI " __u64 offset," +.BI " int flags)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_readv2() prepares a vectored IO read request. The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start reading +.I nr_vecs +into the +.I iovecs +array at +.I offset. +The behavior of the function can be controlled with the +.I flags +parameter. + +Supported values for flags are: +.TP +.B RWF_HIPRI +High priority request, poll if possible +.TP +.B RWF_DSYNC +per-IO O_DSYNC +.TP +.B RWF_SYNC +per-IO O_SYNC +.TP +.B RWF_NOWAIT +per-IO, return -EAGAIN if operation would block +.TP +.B RWF_APPEND +per-IO O_APPEND +.TP + +After the write has been prepared, it can be submitted with one of the submit functions. +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_prep_read (3), io_uring_prep_readv (3), io_uring_submit (3) diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 new file mode 100644 index 0000000..a03c1e7 --- /dev/null +++ b/man/io_uring_prep_write.3 @@ -0,0 +1,38 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_write 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_prep_write - prepare I/O write request + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_write(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " void *buf," +.BI " unsigned nbytes," +.BI " __u64 offset)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_write() prepares an IO write request. The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start writing +.I nbytes +from the buffer +.I buf +at file +.I offset. + +After the write has been prepared, it can be submitted with one of the submit +functions. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3) \ No newline at end of file diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 new file mode 100644 index 0000000..8f68e29 --- /dev/null +++ b/man/io_uring_prep_writev.3 @@ -0,0 +1,37 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_writev 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_prep_writev - prepare vector I/O write request + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_writev(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " const struct iovec *iovecs," +.BI " unsigned nr_vecs," +.BI " __u64 offset)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_writev() prepares a vectored IO write request. The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start writing +.I nr_vecs +from the +.I iovecs +array at file +.I offset. + +After the write has been prepared it can be submitted with one of the submit +functions. +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev2 (3), io_uring_submit (3) \ No newline at end of file diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 new file mode 100644 index 0000000..f1a4dcc --- /dev/null +++ b/man/io_uring_prep_writev2.3 @@ -0,0 +1,60 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_writev2 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_prep_writev2 - prepare vector I/O write request with flags + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_writev2(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " const struct iovec *iovecs," +.BI " unsigned nr_vecs," +.BI " __u64 offset," +.BI " int flags)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_writev2() prepares a vectored IO write request. The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start writing +.I nr_vecs +from the +.I iovecs +array at file +.I offset. +The behavior of the function can be controlled with the +.I flags +parameter. + +Supported values for flags are: +.TP +.B RWF_HIPRI +High priority request, poll if possible +.TP +.B RWF_DSYNC +per-IO O_DSYNC +.TP +.B RWF_SYNC +per-IO O_SYNC +.TP +.B RWF_NOWAIT +per-IO, return -EAGAIN if operation would block +.TP +.B RWF_APPEND +per-IO O_APPEND + +.TP +After the write has been prepared, it can be submitted with one of the submit functions. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev (3), io_uring_submit (3) \ No newline at end of file diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 new file mode 100644 index 0000000..48cc506 --- /dev/null +++ b/man/io_uring_register_buffers.3 @@ -0,0 +1,34 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_register_buffers 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_register_buffers - register buffers for fixed buffer operations +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_register_buffers(struct io_uring *ring," +.BI " const struct iovec *iovecs, +.BI " unsigned nr_iovecs)" +.PP +.SH DESCRIPTION +.PP +The io_uring_register_buffers() function registers +.I nr_iovecs +number of buffers defined by the array +.I iovecs +belonging to the +.I ring. + +After the caller has registered the buffers, they can be used with one of the +fixed buffers functions. + +.SH RETURN VALUE +On success +.BR io_uring_register_buffers (3) +returns 0. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_unregister_buffers (3) \ No newline at end of file diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 new file mode 100644 index 0000000..9b259a2 --- /dev/null +++ b/man/io_uring_register_files.3 @@ -0,0 +1,35 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_register_files 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_register_files - register file descriptors +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_register_files(struct io_uring *ring," +.BI " const int *files," +.BI " unsigned nr_files)" +.PP +.SH DESCRIPTION +.PP +The io_uring_register_files() function registers +.I nr_files +number of file descriptors defined by the array +.I files +belonging to the +.I ring +for subsequent operations. + +After the caller has registered the buffers, they can be used with the +submission queue polling operations. + +.SH RETURN VALUE +On success +.BR io_uring_register_files (3) +returns 0. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_unregister_files (3) diff --git a/man/io_uring_sqe_get_data.3 b/man/io_uring_sqe_get_data.3 new file mode 100644 index 0000000..0c576f9 --- /dev/null +++ b/man/io_uring_sqe_get_data.3 @@ -0,0 +1,34 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_cqe_get_data 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_cqe_get_data - get user data for completion event +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_cqe_get_data() function returns the user_data +with the completion queue entry +.I cqe. + +After the caller has received a completion queue entry (CQE) with io_uring_wait_cqe(), +he can call he io_uring_cqe_get_data() function to retrieve the +.I user_data +value. This requires that +.I user_data +has been set earlier with the function io_uring_sqe_set_data(). + +.SH RETURN VALUE +If the +.I user_data +value has been set before submitting the request, it will be returned. Otherwise +the functions returns NULL. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_sqe_set_data (3), io_uring_sqe_submit(3) \ No newline at end of file diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3 new file mode 100644 index 0000000..b2dd333 --- /dev/null +++ b/man/io_uring_sqe_set_data.3 @@ -0,0 +1,30 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_sqe_set_data 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_sqe_set_data - set user data for submission queue event +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_sqe_set_data(struct io_uring_sqe *sqe," +.BI " void *user_data)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_sqe_set_data() function stores a +.I user_data +pointer with the submission queue entry +.I sqe. + +After the caller has requested an submission queue entry (SQE) with io_uring_get_sqe(), +he can associate a data pointer with the SQE. Once the completion arrives, the +function io_uring_cqe_get_data() can be called to identify the user request. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_cqe_get_data (3) \ No newline at end of file diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 new file mode 100644 index 0000000..b2fe11f --- /dev/null +++ b/man/io_uring_submit.3 @@ -0,0 +1,29 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_submit 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_submit - submit requests to the submission queue +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_submit(struct io_uring *ring)" +.PP +.SH DESCRIPTION +.PP +The io_uring_submit() function submits the next events to the submission +queue belonging to the +.I ring. + +After the caller retrieves a submission queue entry (SQE) with io_uring_get_sqe(), +prepares the SQE, it can be submitted with io_uring_submit(). + +.SH RETURN VALUE +On success +.BR io_uring_submit (3) +returns the number of submitted submission queue entries. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit_and_wait (3), io_uring_submit_and_wait_timeout (3) \ No newline at end of file diff --git a/man/io_uring_submit_and_wait.3 b/man/io_uring_submit_and_wait.3 new file mode 100644 index 0000000..105cad2 --- /dev/null +++ b/man/io_uring_submit_and_wait.3 @@ -0,0 +1,34 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_submit_and_wait 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_submit_and_wait - submit requests to the submission queue and wait for completion +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_submit_and_wait(struct io_uring *ring," +.fi +.BI " unsigned wait_nr)" +.PP +.SH DESCRIPTION +.PP +The io_uring_submit_and_wait() function submits the next events to the submission +queue belonging to the +.I ring +and waits for +.I wait_nr +completion events. + +After the caller retrieves a submission queue entry (SQE) with io_uring_get_sqe(), +prepares the SQE, it can be submitted with io_uring_submit_and_wait(). + +.SH RETURN VALUE +On success +.BR io_uring_submit_and_wait (3) +returns the number of submitted submission queue entries. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_submit_and_wait_timeout (3) \ No newline at end of file diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 new file mode 100644 index 0000000..d509915 --- /dev/null +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -0,0 +1,49 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_submit_and_wait_timeout 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_submit_and_wait_timeout - submit requests to the submission queue and +wait for the completion with timeout +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_submit_and_wait_timeout(struct io_uring *ring," +.fi +.BI " struct io_uring_cqe **cqe_ptr," +.fi +.BI " unsigned wait_nr," +.fi +.BI " struct __kernel_timespec *ts," +.fi +.BI " sigset_t *sigmask)" +.PP +.SH DESCRIPTION +.PP +The io_uring_submit_and_wait_timeout() function submits the next events to the submission +queue belonging to the +.I ring +and waits for +.I wait_nr +completion events or until the timeout +.I ts +expires.The completion events are stored in the +.I cqe_ptr array. +The +.I sigmask +specifies the set of signals to block. The prevailing signal mask is restored +before returning. + +After the caller retrieves a submission queue entry (SQE) with io_uring_get_sqe(), +prepares the SQE, it can be submitted with io_uring_submit_and_wait_timeout(). + + +.SH RETURN VALUE +On success +.BR io_uring_submit_and_wait_timeout (3) +returns the number of submitted submission queue entries. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_submit_and_wait (3), io_uring_wait_cqe (3) \ No newline at end of file diff --git a/man/io_uring_unregister_buffers.3 b/man/io_uring_unregister_buffers.3 new file mode 100644 index 0000000..4ec1048 --- /dev/null +++ b/man/io_uring_unregister_buffers.3 @@ -0,0 +1,26 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_unregister_buffers 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_unregister_buffers - unregister buffers for fixed buffer operations +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_unregister_buffers(struct io_uring *ring)" +.PP +.SH DESCRIPTION +.PP +The io_uring_unregister_buffers() function unregisters +the fixed buffers previously registered to the +.I ring. + +.SH RETURN VALUE +On success +.BR io_uring_unregister_buffers (3) +returns 0. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_register_buffers (3) \ No newline at end of file diff --git a/man/io_uring_unregister_files.3 b/man/io_uring_unregister_files.3 new file mode 100644 index 0000000..0fadf5d --- /dev/null +++ b/man/io_uring_unregister_files.3 @@ -0,0 +1,26 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_unregister_files 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_unregister_files - unregister file descriptors +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_unregister_files(struct io_uring *ring)" +.PP +.SH DESCRIPTION +.PP +The io_uring_unregister_files() function unregisters +the file descriptors previously registered to the +.I ring. + +.SH RETURN VALUE +On success +.BR io_uring_unregister_files (3) +returns 0. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_register_files (3) \ No newline at end of file diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3 new file mode 100644 index 0000000..85f6d78 --- /dev/null +++ b/man/io_uring_wait_cqe.3 @@ -0,0 +1,33 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_wait_cqe 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_wait_cqe - wait for one io_uring completion event +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_wait_cqe(struct io_uring *ring," +.BI " struct io_uring_cqe **cqe_ptr);" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_wait_cqe() function returns an IO completion from the +queue belonging to the +.I ring +param, waiting for it if necessary. The +.I cqe_ptr +param is filled in on success. + +After the caller has submitted a request with io_uring_submit(), he can retrieve +the completion with io_uring_wait_cqe(). + +.SH RETURN VALUE +On success +.BR io_uring_wait_cqe (3) +returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_wait_cqes(3) \ No newline at end of file diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3 new file mode 100644 index 0000000..a3d9b56 --- /dev/null +++ b/man/io_uring_wait_cqe_nr.3 @@ -0,0 +1,36 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_wait_cqe_nr 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_wait_cqe_nr - wait for one or more io_uring completion events +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_wait_cqe_nr(struct io_uring *ring," +.BI " struct io_uring_cqe **cqe_ptr," +.BI " unsigned wait_nr)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_wait_cqe_nr() function returns +.I wait_nr +IO completion events from the +queue belonging to the +.I ring +param, waiting for it if necessary. The +.I cqe_ptr +param is filled in on success. + +After the caller has submitted a request with io_uring_submit(), he can retrieve +the completion with io_uring_wait_cqe_nr(). + +.SH RETURN VALUE +On success +.BR io_uring_wait_cqe_nr (3) +returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_wait_cqes (3) \ No newline at end of file diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 new file mode 100644 index 0000000..d836352 --- /dev/null +++ b/man/io_uring_wait_cqe_timeout.3 @@ -0,0 +1,39 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_wait_cqe_timeout 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_wait_cqe_timeout - wait for one io_uring completion event with timeout +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_wait_cqe_timeout(struct io_uring *ring," +.BI " struct io_uring_cqe **cqe_ptr," +.BI " struct __kernel_timespec *ts)" +.PP +.SH DESCRIPTION +.PP +The io_uring_wait_cqe_timeout() function returns one IO completion from the +queue belonging to the +.I ring +param, waiting for it if necessary or until the timeout +.I ts +expires. + +The +.I cqe_ptr +param is filled in on success. + +If +.I ts +is specified, the application does not need to call io_uring_submit (3) before +calling io_uring_wait_cqes (3). + +.SH RETURN VALUE +On success +.BR io_uring_wait_cqes (3) +returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). \ No newline at end of file diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3 new file mode 100644 index 0000000..5c732da --- /dev/null +++ b/man/io_uring_wait_cqes.3 @@ -0,0 +1,46 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_wait_cqes 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_wait_cqes - wait for one or more io_uring completion events +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_wait_cqes(struct io_uring *ring," +.BI " struct io_uring_cqe **cqe_ptr," +.BI " unsigned wait_nr," +.BI " struct __kernel_timespec *ts," +.BI " sigset_t *sigmask) +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_wait_cqes() function returns +.I wait_nr +IO completions from the queue belonging to the +.I ring +param, waiting for it if necessary or until the timeout +.I ts +expires. The +.I sigmask +specifies the set of signals to block. The prevailing signal mask is restored +before returning. + +The +.I cqe_ptr +param is filled in on success. + +If +.I ts +is specified, the application does not need to call io_uring_submit (3) before +calling io_uring_wait_cqes (3). + +.SH RETURN VALUE +On success +.BR io_uring_wait_cqes (3) +returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). -- cgit v1.2.3 From 469b5e80ce42be53ec748ddea8523a3c16ea5465 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 17 Nov 2021 19:51:42 -0700 Subject: man/io_uring_get_sqe.3: use "submission queue entry" Event isn't quite appropriate on the submission side. Signed-off-by: Jens Axboe --- man/io_uring_get_sqe.3 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/man/io_uring_get_sqe.3 b/man/io_uring_get_sqe.3 index 24834f3..12ae545 100644 --- a/man/io_uring_get_sqe.3 +++ b/man/io_uring_get_sqe.3 @@ -5,7 +5,8 @@ .\" .TH io_uring_get_sqe 3 "July 10, 2020" "liburing-0.7" "liburing Manual" .SH NAME -io_uring_get_sqe - get the next vacant event from the submission queue +io_uring_get_sqe - get the next available submission queue entry from the +submission queue .SH SYNOPSIS .nf .BR "#include " @@ -15,15 +16,15 @@ io_uring_get_sqe - get the next vacant event from the submission queue .PP .SH DESCRIPTION .PP -The io_uring_get_sqe() function gets the next vacant event from the submission -queue belonging to the +The io_uring_get_sqe() function gets the next available submission queue entry +from the submission queue belonging to the .I ring param. -On success io_uring_get_sqe() returns a pointer to the submission queue event. +On success io_uring_get_sqe() returns a pointer to the submission queue entry. On failure NULL is returned. -If a submission queue event is returned, it should be filled out via one of the +If a submission queue entry is returned, it should be filled out via one of the prep functions such as .BR io_uring_prep_read (3) and submitted via -- cgit v1.2.3 From df9a741895028204b130b6cbe03c5c3dda3cf1a9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 18 Nov 2021 07:27:17 -0700 Subject: Rename man page This one refers to io_uring_cqe_get_data(), so rename it as such. Signed-off-by: Jens Axboe --- man/io_uring_cqe_get_data.3 | 34 ++++++++++++++++++++++++++++++++++ man/io_uring_sqe_get_data.3 | 34 ---------------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) create mode 100644 man/io_uring_cqe_get_data.3 delete mode 100644 man/io_uring_sqe_get_data.3 diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 new file mode 100644 index 0000000..0c576f9 --- /dev/null +++ b/man/io_uring_cqe_get_data.3 @@ -0,0 +1,34 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_cqe_get_data 3 "November 15, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_cqe_get_data - get user data for completion event +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_cqe_get_data() function returns the user_data +with the completion queue entry +.I cqe. + +After the caller has received a completion queue entry (CQE) with io_uring_wait_cqe(), +he can call he io_uring_cqe_get_data() function to retrieve the +.I user_data +value. This requires that +.I user_data +has been set earlier with the function io_uring_sqe_set_data(). + +.SH RETURN VALUE +If the +.I user_data +value has been set before submitting the request, it will be returned. Otherwise +the functions returns NULL. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_sqe_set_data (3), io_uring_sqe_submit(3) \ No newline at end of file diff --git a/man/io_uring_sqe_get_data.3 b/man/io_uring_sqe_get_data.3 deleted file mode 100644 index 0c576f9..0000000 --- a/man/io_uring_sqe_get_data.3 +++ /dev/null @@ -1,34 +0,0 @@ -.\" Copyright (C) 2021 Stefan Roesch -.\" -.\" SPDX-License-Identifier: LGPL-2.0-or-later -.\" -.TH io_uring_cqe_get_data 3 "November 15, 2021" "liburing-2.1" "liburing Manual" -.SH NAME -io_uring_cqe_get_data - get user data for completion event -.SH SYNOPSIS -.nf -.BR "#include " -.PP -.BI "void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)" -.fi -.PP -.SH DESCRIPTION -.PP -The io_uring_cqe_get_data() function returns the user_data -with the completion queue entry -.I cqe. - -After the caller has received a completion queue entry (CQE) with io_uring_wait_cqe(), -he can call he io_uring_cqe_get_data() function to retrieve the -.I user_data -value. This requires that -.I user_data -has been set earlier with the function io_uring_sqe_set_data(). - -.SH RETURN VALUE -If the -.I user_data -value has been set before submitting the request, it will be returned. Otherwise -the functions returns NULL. -.SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_sqe_set_data (3), io_uring_sqe_submit(3) \ No newline at end of file -- cgit v1.2.3 From 2b0b33a7fd274e56d923d8dd027679feb1fd7eeb Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Wed, 24 Nov 2021 20:58:11 +0000 Subject: io_uring.h: update to reflect cqe-skip feature Add IOSQE_CQE_SKIP_SUCCESS and friends Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/665ef6b2f9440105f5826a63be5ac014b179ccbf.1637786880.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 61683bd..a7d193d 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -74,6 +74,7 @@ enum { IOSQE_IO_HARDLINK_BIT, IOSQE_ASYNC_BIT, IOSQE_BUFFER_SELECT_BIT, + IOSQE_CQE_SKIP_SUCCESS_BIT, }; /* @@ -91,6 +92,8 @@ enum { #define IOSQE_ASYNC (1U << IOSQE_ASYNC_BIT) /* select buffer from sqe->buf_group */ #define IOSQE_BUFFER_SELECT (1U << IOSQE_BUFFER_SELECT_BIT) +/* don't post CQE if request succeeded */ +#define IOSQE_CQE_SKIP_SUCCESS (1U << IOSQE_CQE_SKIP_SUCCESS_BIT) /* * io_uring_setup() flags @@ -293,6 +296,7 @@ struct io_uring_params { #define IORING_FEAT_EXT_ARG (1U << 8) #define IORING_FEAT_NATIVE_WORKERS (1U << 9) #define IORING_FEAT_RSRC_TAGS (1U << 10) +#define IORING_FEAT_CQE_SKIP (1U << 11) /* * io_uring_register(2) opcodes and arguments -- cgit v1.2.3 From 78f733007fd0ed50ec12421805716922541d8d47 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Wed, 24 Nov 2021 20:58:12 +0000 Subject: tests: add tests for IOSQE_CQE_SKIP_SUCCESS Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/64a28950287c97b4d5bd11bf288ab6fab5d45b79.1637786880.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 1 + test/skip-cqe.c | 338 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 340 insertions(+) create mode 100644 test/skip-cqe.c diff --git a/.gitignore b/.gitignore index fb3a859..cb08ca0 100644 --- a/.gitignore +++ b/.gitignore @@ -131,6 +131,7 @@ /test/testfile /test/submit-link-fail /test/exec-target +/test/skip-cqe /test/*.dmesg /test/output/ diff --git a/test/Makefile b/test/Makefile index d6e7227..c09078a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -147,6 +147,7 @@ test_srcs := \ timeout-overflow.c \ unlink.c \ wakeup-hang.c \ + skip-cqe.c \ # EOL diff --git a/test/skip-cqe.c b/test/skip-cqe.c new file mode 100644 index 0000000..184932f --- /dev/null +++ b/test/skip-cqe.c @@ -0,0 +1,338 @@ +#include +#include +#include +#include +#include +#include + +#include "liburing.h" + +#define LINK_SIZE 6 +#define TIMEOUT_USER_DATA (-1) + +static int fds[2]; + +/* should be successfully submitted but fails during execution */ +static void prep_exec_fail_req(struct io_uring_sqe *sqe) +{ + io_uring_prep_write(sqe, fds[2], NULL, 100, 0); +} + +static int test_link_success(struct io_uring *ring, int nr, bool skip_last) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int ret, i; + + for (i = 0; i < nr; ++i) { + sqe = io_uring_get_sqe(ring); + io_uring_prep_nop(sqe); + if (i != nr - 1 || skip_last) + sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS; + sqe->user_data = i; + } + + ret = io_uring_submit(ring); + if (ret != nr) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + if (!skip_last) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret != 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + if (cqe->res != 0) { + fprintf(stderr, "nop failed: res %d\n", cqe->res); + goto err; + } + if (cqe->user_data != nr - 1) { + fprintf(stderr, "invalid user_data %i\n", (int)cqe->user_data); + goto err; + } + io_uring_cqe_seen(ring, cqe); + } + + if (io_uring_peek_cqe(ring, &cqe) >= 0) { + fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data); + goto err; + } + return 0; +err: + return 1; +} + +static int test_link_fail(struct io_uring *ring, int nr, int fail_idx) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int ret, i; + + for (i = 0; i < nr; ++i) { + sqe = io_uring_get_sqe(ring); + if (i == fail_idx) + prep_exec_fail_req(sqe); + else + io_uring_prep_nop(sqe); + + if (i != nr - 1) + sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS; + sqe->user_data = i; + } + + ret = io_uring_submit(ring); + if (ret != nr) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + ret = io_uring_wait_cqe(ring, &cqe); + if (ret != 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + if (!cqe->res || cqe->user_data != fail_idx) { + fprintf(stderr, "got: user_data %d res %d, expected data: %d\n", + (int)cqe->user_data, cqe->res, fail_idx); + goto err; + } + io_uring_cqe_seen(ring, cqe); + + if (io_uring_peek_cqe(ring, &cqe) >= 0) { + fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data); + goto err; + } + return 0; +err: + return 1; +} + +static int test_ltimeout_cancel(struct io_uring *ring, int nr, int tout_idx, + bool async, int fail_idx) +{ + struct __kernel_timespec ts = {.tv_sec = 1, .tv_nsec = 0}; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int ret, i; + int e_res = 0, e_idx = nr - 1; + + if (fail_idx >= 0) { + e_res = -EFAULT; + e_idx = fail_idx; + } + + for (i = 0; i < nr; ++i) { + sqe = io_uring_get_sqe(ring); + if (i == fail_idx) + prep_exec_fail_req(sqe); + else + io_uring_prep_nop(sqe); + sqe->user_data = i; + sqe->flags |= IOSQE_IO_LINK; + if (async) + sqe->flags |= IOSQE_ASYNC; + if (i != nr - 1) + sqe->flags |= IOSQE_CQE_SKIP_SUCCESS; + + if (i == tout_idx) { + sqe = io_uring_get_sqe(ring); + io_uring_prep_link_timeout(sqe, &ts, 0); + sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS; + sqe->user_data = TIMEOUT_USER_DATA; + } + } + + ret = io_uring_submit(ring); + if (ret != nr + 1) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + ret = io_uring_wait_cqe(ring, &cqe); + if (ret != 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + if (cqe->user_data != e_idx) { + fprintf(stderr, "invalid user_data %i\n", (int)cqe->user_data); + goto err; + } + if (cqe->res != e_res) { + fprintf(stderr, "unexpected res: %d\n", cqe->res); + goto err; + } + io_uring_cqe_seen(ring, cqe); + + if (io_uring_peek_cqe(ring, &cqe) >= 0) { + fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data); + goto err; + } + return 0; +err: + return 1; +} + +static int test_ltimeout_fire(struct io_uring *ring, bool async, + bool skip_main, bool skip_tout) +{ + char buf[1]; + struct __kernel_timespec ts = {.tv_sec = 0, .tv_nsec = 1000000}; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int ret, i; + int nr = 1 + !skip_tout; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0); + sqe->flags |= IOSQE_IO_LINK; + sqe->flags |= async ? IOSQE_ASYNC : 0; + sqe->flags |= skip_main ? IOSQE_CQE_SKIP_SUCCESS : 0; + sqe->user_data = 0; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_link_timeout(sqe, &ts, 0); + sqe->flags |= skip_tout ? IOSQE_CQE_SKIP_SUCCESS : 0; + sqe->user_data = 1; + + ret = io_uring_submit(ring); + if (ret != 2) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + return 1; + } + + for (i = 0; i < nr; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret != 0) { + fprintf(stderr, "wait completion %d\n", ret); + return 1; + } + switch (cqe->user_data) { + case 0: + if (cqe->res != -ECANCELED && cqe->res != -EINTR) { + fprintf(stderr, "unexpected read return: %d\n", cqe->res); + return 1; + } + break; + case 1: + if (skip_tout) { + fprintf(stderr, "extra timeout cqe, %d\n", cqe->res); + return 1; + } + break; + } + io_uring_cqe_seen(ring, cqe); + } + + + if (io_uring_peek_cqe(ring, &cqe) >= 0) { + fprintf(stderr, "single CQE expected: got data: %i res: %i\n", + (int)cqe->user_data, cqe->res); + return 1; + } + return 0; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + int ret, i; + int mid_idx = LINK_SIZE / 2; + int last_idx = LINK_SIZE - 1; + + if (pipe(fds)) { + fprintf(stderr, "pipe() failed\n"); + return 1; + } + ret = io_uring_queue_init(16, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + if (!(ring.features & IORING_FEAT_CQE_SKIP)) { + printf("IOSQE_CQE_SKIP_SUCCESS is not supported, skip\n"); + return 0; + } + + for (i = 0; i < 4; i++) { + bool skip_last = i & 1; + int sz = (i & 2) ? LINK_SIZE : 1; + + ret = test_link_success(&ring, sz, skip_last); + if (ret) { + fprintf(stderr, "test_link_success sz %d, %d last\n", + skip_last, sz); + return ret; + } + } + + ret = test_link_fail(&ring, LINK_SIZE, mid_idx); + if (ret) { + fprintf(stderr, "test_link_fail mid failed\n"); + return ret; + } + + ret = test_link_fail(&ring, LINK_SIZE, last_idx); + if (ret) { + fprintf(stderr, "test_link_fail last failed\n"); + return ret; + } + + for (i = 0; i < 2; i++) { + bool async = i & 1; + + ret = test_ltimeout_cancel(&ring, 1, 0, async, -1); + if (ret) { + fprintf(stderr, "test_ltimeout_cancel 1 failed, %i\n", + async); + return ret; + } + ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, -1); + if (ret) { + fprintf(stderr, "test_ltimeout_cancel mid failed, %i\n", + async); + return ret; + } + ret = test_ltimeout_cancel(&ring, LINK_SIZE, last_idx, async, -1); + if (ret) { + fprintf(stderr, "test_ltimeout_cancel last failed, %i\n", + async); + return ret; + } + ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, mid_idx); + if (ret) { + fprintf(stderr, "test_ltimeout_cancel fail mid failed, %i\n", + async); + return ret; + } + ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, mid_idx - 1); + if (ret) { + fprintf(stderr, "test_ltimeout_cancel fail2 mid failed, %i\n", + async); + return ret; + } + ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, mid_idx + 1); + if (ret) { + fprintf(stderr, "test_ltimeout_cancel fail3 mid failed, %i\n", + async); + return ret; + } + } + + for (i = 0; i < 8; i++) { + bool async = i & 1; + bool skip1 = i & 2; + bool skip2 = i & 4; + + ret = test_ltimeout_fire(&ring, async, skip1, skip2); + if (ret) { + fprintf(stderr, "test_ltimeout_fire failed\n"); + return ret; + } + } + + close(fds[0]); + close(fds[1]); + io_uring_queue_exit(&ring); + return 0; +} -- cgit v1.2.3 From aabfd74fb908557d32b956e36f33f9dc586e6505 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 26 Nov 2021 19:34:05 +0000 Subject: test: poll cancellation with offset timeouts Test for a recent locking problem during poll cancellation with offset timeouts queued. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/21ed5cd19ba6cff23714dddb07358360a1ac6f91.1637955206.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/poll-cancel.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 4 deletions(-) diff --git a/test/poll-cancel.c b/test/poll-cancel.c index a74e915..408159d 100644 --- a/test/poll-cancel.c +++ b/test/poll-cancel.c @@ -26,7 +26,7 @@ static void sig_alrm(int sig) exit(1); } -int main(int argc, char *argv[]) +static int test_poll_cancel(void) { struct io_uring ring; int pipe1[2]; @@ -36,9 +36,6 @@ int main(int argc, char *argv[]) struct sigaction act; int ret; - if (argc > 1) - return 0; - if (pipe(pipe1) != 0) { perror("pipe"); return 1; @@ -130,6 +127,102 @@ int main(int argc, char *argv[]) return 1; } + close(pipe1[0]); + close(pipe1[1]); io_uring_cqe_seen(&ring, cqe); + io_uring_queue_exit(&ring); + return 0; +} + + +static int __test_poll_cancel_with_timeouts(void) +{ + struct __kernel_timespec ts = { .tv_sec = 10, }; + struct io_uring ring, ring2; + struct io_uring_sqe *sqe; + int ret, off_nr = 1000; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + ret = io_uring_queue_init(1, &ring2, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + /* test timeout-offset triggering path during cancellation */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_timeout(sqe, &ts, off_nr, 0); + + /* poll ring2 to trigger cancellation on exit() */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_poll_add(sqe, ring2.ring_fd, POLLIN); + sqe->flags |= IOSQE_IO_LINK; + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_link_timeout(sqe, &ts, 0); + + ret = io_uring_submit(&ring); + if (ret != 3) { + fprintf(stderr, "sqe submit failed\n"); + return 1; + } + + /* just drop all rings/etc. intact, exit() will clean them up */ + return 0; +} + +static int test_poll_cancel_with_timeouts(void) +{ + int ret; + pid_t p; + + p = fork(); + if (p == -1) { + fprintf(stderr, "fork() failed\n"); + return 1; + } + + if (p == 0) { + ret = __test_poll_cancel_with_timeouts(); + exit(ret); + } else { + int wstatus; + + if (waitpid(p, &wstatus, 0) == (pid_t)-1) { + perror("waitpid()"); + return 1; + } + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) { + fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus)); + return 1; + } + } + return 0; +} + +int main(int argc, char *argv[]) +{ + int ret; + + if (argc > 1) + return 0; + + ret = test_poll_cancel(); + if (ret) { + fprintf(stderr, "test_poll_cancel failed\n"); + return -1; + } + + ret = test_poll_cancel_with_timeouts(); + if (ret) { + fprintf(stderr, "test_poll_cancel_with_timeouts failed\n"); + return -1; + } + return 0; } -- cgit v1.2.3 From 00b7628d9908d12ffe8a0547687055563a2a77e2 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 26 Nov 2021 20:25:42 +0000 Subject: test: skip-cqe with hardlinks Test IOSQE_CQE_SKIP_SUCCESS together with IOSQE_IO_HARDLINK. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/fe5333e8832e6bacb5c9ca9ec8d0004a6fd2646d.1637958333.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/skip-cqe.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/test/skip-cqe.c b/test/skip-cqe.c index 184932f..9de5bae 100644 --- a/test/skip-cqe.c +++ b/test/skip-cqe.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "liburing.h" @@ -232,10 +233,79 @@ static int test_ltimeout_fire(struct io_uring *ring, bool async, return 0; } +static int test_hardlink(struct io_uring *ring, int nr, int fail_idx, + int skip_idx, bool hardlink_last) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int ret, i; + + assert(fail_idx < nr); + assert(skip_idx < nr); + + for (i = 0; i < nr; i++) { + sqe = io_uring_get_sqe(ring); + if (i == fail_idx) + prep_exec_fail_req(sqe); + else + io_uring_prep_nop(sqe); + if (i != nr - 1 || hardlink_last) + sqe->flags |= IOSQE_IO_HARDLINK; + if (i == skip_idx) + sqe->flags |= IOSQE_CQE_SKIP_SUCCESS; + sqe->user_data = i; + } + + ret = io_uring_submit(ring); + if (ret != nr) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + for (i = 0; i < nr; i++) { + if (i == skip_idx && fail_idx != skip_idx) + continue; + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret != 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + if (cqe->user_data != i) { + fprintf(stderr, "invalid user_data %d (%i)\n", + (int)cqe->user_data, i); + goto err; + } + if (i == fail_idx) { + if (cqe->res >= 0) { + fprintf(stderr, "req should've failed %d %d\n", + (int)cqe->user_data, cqe->res); + goto err; + } + } else { + if (cqe->res) { + fprintf(stderr, "req error %d %d\n", + (int)cqe->user_data, cqe->res); + goto err; + } + } + + io_uring_cqe_seen(ring, cqe); + } + + if (io_uring_peek_cqe(ring, &cqe) >= 0) { + fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data); + goto err; + } + return 0; +err: + return 1; +} + int main(int argc, char *argv[]) { struct io_uring ring; - int ret, i; + int ret, i, j, k; int mid_idx = LINK_SIZE / 2; int last_idx = LINK_SIZE - 1; @@ -331,6 +401,23 @@ int main(int argc, char *argv[]) } } + /* test 3 positions, start/middle/end of the link, i.e. indexes 0, 3, 6 */ + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + for (k = 0; k < 2; k++) { + bool mark_last = k & 1; + + ret = test_hardlink(&ring, 7, i * 3, j * 3, mark_last); + if (ret) { + fprintf(stderr, "test_hardlink failed" + "fail %i skip %i mark last %i\n", + i * 3, j * 3, k); + return 1; + } + } + } + } + close(fds[0]); close(fds[1]); io_uring_queue_exit(&ring); -- cgit v1.2.3 From 3cbc199a80f37ad5183e04144b4126bb9c619b8b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 27 Nov 2021 07:01:33 -0700 Subject: test/skip-cqe: use correct index for write side of pipe clang correctly complains about using out-of-array: skip-cqe.c:19:27: error: array index 2 is past the end of the array (which contains 2 elements) [-Werror,-Warray-bounds] io_uring_prep_write(sqe, fds[2], NULL, 100, 0); ^ ~ Fixes: 78f733007fd0 ("tests: add tests for IOSQE_CQE_SKIP_SUCCESS") Signed-off-by: Jens Axboe --- test/skip-cqe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/skip-cqe.c b/test/skip-cqe.c index 9de5bae..ba84d92 100644 --- a/test/skip-cqe.c +++ b/test/skip-cqe.c @@ -16,7 +16,7 @@ static int fds[2]; /* should be successfully submitted but fails during execution */ static void prep_exec_fail_req(struct io_uring_sqe *sqe) { - io_uring_prep_write(sqe, fds[2], NULL, 100, 0); + io_uring_prep_write(sqe, fds[1], NULL, 100, 0); } static int test_link_success(struct io_uring *ring, int nr, bool skip_last) -- cgit v1.2.3 From 509873c4454012c5810c728695c21911c82acdc4 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sat, 27 Nov 2021 01:50:25 +0000 Subject: man/io_uring_enter.2: document IOSQE_CQE_SKIP_SUCCESS Add a section about IOSQE_CQE_SKIP_SUCCESS describing the behaviour and use cases. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/381237725f0f09a2668ea7f38b804d5733595b1f.1637977800.git.asml.silence@gmail.com [axboe: some rewording] Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 93b97e6..b003e05 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -1094,6 +1094,28 @@ are available and this flag is set, then the request will fail with as the error code. Once a buffer has been used, it is no longer available in the kernel pool. The application must re-register the given buffer again when it is ready to recycle it (eg has completed using it). Available since 5.7. +.TP +.B IOSQE_CQE_SKIP_SUCCESS +Don't generate a CQE if the request completes successfully. If the request +fails, an appropriate CQE will be posted as usual and if there is no +.B IOSQE_IO_HARDLINK, +CQEs for all linked requests will be omitted. The notion of failure/success is +opcode specific and is the same as with breaking chains of +.B IOSQE_IO_LINK. +One special case is when the request has a linked timeout, then the CQE +generation for the linked timeout is decided solely by whether it has +.B IOSQE_CQE_SKIP_SUCCESS +set, regardless whether it timed out or was cancelled. In other words, if a +linked timeout has the flag set, it's guaranteed to not post a CQE. + +The semantics are chosen to accommodate several use cases. First, when all but +the last request of a normal link without linked timeouts are marked with the +flag, only one CQE per lin is posted. Additionally, it enables supression of +CQEs in cases where the side effects of a successfully executed operation is +enough for userspace to know the state of the system. One such example would +be writing to a synchronisation file. + +Available since 5.17. .PP .I ioprio -- cgit v1.2.3 From 02158b6ae281776b4db2a5409524f16cc1488fb9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 2 Dec 2021 20:06:32 -0700 Subject: Add test case for hang condition on exit without cleanup Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 2 + test/exit-no-cleanup.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 test/exit-no-cleanup.c diff --git a/.gitignore b/.gitignore index cb08ca0..0a72f03 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,7 @@ /test/eventfd /test/eventfd-disable /test/eventfd-ring +/test/exit-no-cleanup /test/fadvise /test/fallocate /test/fc2a85cb02ef-test diff --git a/test/Makefile b/test/Makefile index c09078a..c70693c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -67,6 +67,7 @@ test_srcs := \ eventfd-disable.c \ eventfd-ring.c \ exec-target.c \ + exit-no-cleanup.c \ fadvise.c \ fallocate.c \ fc2a85cb02ef-test.c \ @@ -215,6 +216,7 @@ timeout-new: override LDFLAGS += -lpthread thread-exit: override LDFLAGS += -lpthread ring-leak2: override LDFLAGS += -lpthread poll-mshot-update: override LDFLAGS += -lpthread +exit-no-cleanup: override LDFLAGS += -lpthread install: $(test_targets) runtests.sh runtests-loop.sh $(INSTALL) -D -d -m 755 $(datadir)/liburing-test/ diff --git a/test/exit-no-cleanup.c b/test/exit-no-cleanup.c new file mode 100644 index 0000000..90ef394 --- /dev/null +++ b/test/exit-no-cleanup.c @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Test case testing exit without cleanup and io-wq work pending or queued. + * + * From Florian Fischer + * Link: https://lore.kernel.org/io-uring/20211202165606.mqryio4yzubl7ms5@pasture/ + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define IORING_ENTRIES 8 + +static pthread_t *threads; +static pthread_barrier_t init_barrier; +static int sleep_fd, notify_fd; +static sem_t sem; + +void *thread_func(void *arg) +{ + struct io_uring ring; + int res; + + res = io_uring_queue_init(IORING_ENTRIES, &ring, 0); + if (res) + err(EXIT_FAILURE, "io_uring_queue_init failed"); + + pthread_barrier_wait(&init_barrier); + + for(;;) { + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + uint64_t buf; + int res; + + sqe = io_uring_get_sqe(&ring); + assert(sqe); + + io_uring_prep_read(sqe, sleep_fd, &buf, sizeof(buf), 0); + + res = io_uring_submit_and_wait(&ring, 1); + if (res < 0) + err(EXIT_FAILURE, "io_uring_submit_and_wait failed"); + + res = io_uring_peek_cqe(&ring, &cqe); + assert(!res); + if (cqe->res < 0) { + errno = -cqe->res; + err(EXIT_FAILURE, "read failed"); + } + assert(cqe->res == sizeof(buf)); + + sem_post(&sem); + + io_uring_cqe_seen(&ring, cqe); + } + + return NULL; +} + +int main(int argc, char *argv[]) +{ + int res, fds[2], i, cpus; + const uint64_t n = 0x42; + + cpus = get_nprocs(); + res = pthread_barrier_init(&init_barrier, NULL, cpus); + if (res) + err(EXIT_FAILURE, "pthread_barrier_init failed"); + + res = sem_init(&sem, 0, 0); + if (res) + err(EXIT_FAILURE, "sem_init failed"); + + threads = t_malloc(sizeof(pthread_t) * cpus); + + res = pipe(fds); + if (res) + err(EXIT_FAILURE, "pipe failed"); + + sleep_fd = fds[0]; + notify_fd = fds[1]; + + for (i = 0; i < cpus; i++) { + errno = pthread_create(&threads[i], NULL, thread_func, NULL); + if (errno) + err(EXIT_FAILURE, "pthread_create failed"); + } + + // Write #cpus notifications + for (i = 0; i < cpus; i++) { + res = write(notify_fd, &n, sizeof(n)); + if (res < 0) + err(EXIT_FAILURE, "write failed"); + assert(res == sizeof(n)); + } + + // Await that all notifications were received + for (i = 0; i < cpus; i++) + sem_wait(&sem); + + // Exit without resource cleanup + exit(EXIT_SUCCESS); +} -- cgit v1.2.3 From a49427fbbe0a2b25cefd77d9a78df2b7d96d661f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 4 Dec 2021 15:07:18 -0700 Subject: liburing.h: don't truncate timeout_update/remove user data value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we're running on 32-bit, with the cast that io_uring_prep_rw() does, we lose the top 32 bits of the user_data for the timeout remove and update commands. If the application also uses a full 64-bit value for the original timeout user_data, then we cannot find the timeout to update. Link: https://github.com/axboe/liburing/issues/490 Signed-off-by: Rémi Bernon Signed-off-by: Jens Axboe --- src/include/liburing.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 169e098..230cd61 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -425,8 +425,8 @@ static inline void io_uring_prep_timeout(struct io_uring_sqe *sqe, static inline void io_uring_prep_timeout_remove(struct io_uring_sqe *sqe, __u64 user_data, unsigned flags) { - io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, - (void *)(unsigned long)user_data, 0, 0); + io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, NULL, 0, 0); + sqe->addr = user_data; sqe->timeout_flags = flags; } @@ -434,9 +434,9 @@ static inline void io_uring_prep_timeout_update(struct io_uring_sqe *sqe, struct __kernel_timespec *ts, __u64 user_data, unsigned flags) { - io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, - (void *)(unsigned long)user_data, 0, - (uintptr_t)ts); + io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1, NULL, 0, + (uintptr_t) ts); + sqe->addr = user_data; sqe->timeout_flags = flags | IORING_TIMEOUT_UPDATE; } -- cgit v1.2.3 From d84c29b19ed0b130000619cff40141bb1fc3615b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 4 Dec 2021 15:55:31 -0700 Subject: Don't truncate addr fields to 32-bit on 32-bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the commands where we use it as a lookup key, then we don't want to rob 32-bit applications from the potential of using the full 64-bit type. This includes commands like: poll_remove, poll_update, prep_cancel Also provide 64-bit u64 types of the sqe set data and the cqe get data helpers, along with a define that allows applications to check for the presence of it. NOTE: this may trigger compile warnings in applications that currently use these helpers, which is also why a few test cases had to get adapted. The fixup is trivial, and the above define can help applications check if one or the other is the current one. Link: https://github.com/axboe/liburing/issues/490 Reported-by: Rémi Bernon Signed-off-by: Jens Axboe --- src/include/liburing.h | 47 ++++++++++++++++++++++++++++++++++++++--------- test/accept.c | 2 +- test/io-cancel.c | 6 +++--- test/multicqes_drain.c | 2 +- test/poll-cancel-ton.c | 2 +- test/poll-cancel.c | 2 +- test/poll-mshot-update.c | 6 +++--- 7 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 230cd61..3705c5b 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -219,6 +219,11 @@ static inline void io_uring_cqe_seen(struct io_uring *ring, /* * Command prep helpers */ + +/* + * Associate pointer @data with the sqe, for later retrieval from the cqe + * at command completion time with io_uring_cqe_get_data(). + */ static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data) { sqe->user_data = (unsigned long) data; @@ -229,6 +234,27 @@ static inline void *io_uring_cqe_get_data(const struct io_uring_cqe *cqe) return (void *) (uintptr_t) cqe->user_data; } +/* + * Assign a 64-bit value to this sqe, which can get retrieved at completion + * time with io_uring_cqe_get_data64. Just like the non-64 variants, except + * these store a 64-bit type rather than a data pointer. + */ +static inline void io_uring_sqe_set_data64(struct io_uring_sqe *sqe, + __u64 data) +{ + sqe->user_data = data; +} + +static inline __u64 io_uring_cqe_get_data64(const struct io_uring_cqe *cqe) +{ + return cqe->user_data; +} + +/* + * Tell the app the have the 64-bit variants of the get/set userdata + */ +#define LIBURING_HAVE_DATA64 + static inline void io_uring_sqe_set_flags(struct io_uring_sqe *sqe, unsigned flags) { @@ -387,18 +413,20 @@ static inline void io_uring_prep_poll_multishot(struct io_uring_sqe *sqe, } static inline void io_uring_prep_poll_remove(struct io_uring_sqe *sqe, - void *user_data) + __u64 user_data) { - io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, user_data, 0, 0); + io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, NULL, 0, 0); + sqe->addr = user_data; } static inline void io_uring_prep_poll_update(struct io_uring_sqe *sqe, - void *old_user_data, - void *new_user_data, + __u64 old_user_data, + __u64 new_user_data, unsigned poll_mask, unsigned flags) { - io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, old_user_data, flags, - (__u64)(uintptr_t)new_user_data); + io_uring_prep_rw(IORING_OP_POLL_REMOVE, sqe, -1, NULL, flags, + new_user_data); + sqe->addr = old_user_data; sqe->poll32_events = __io_uring_prep_poll_mask(poll_mask); } @@ -459,10 +487,11 @@ static inline void io_uring_prep_accept_direct(struct io_uring_sqe *sqe, int fd, __io_uring_set_target_fixed_file(sqe, file_index); } -static inline void io_uring_prep_cancel(struct io_uring_sqe *sqe, void *user_data, - int flags) +static inline void io_uring_prep_cancel(struct io_uring_sqe *sqe, + __u64 user_data, int flags) { - io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, -1, user_data, 0, 0); + io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, -1, NULL, 0, 0); + sqe->addr = user_data; sqe->cancel_flags = (__u32) flags; } diff --git a/test/accept.c b/test/accept.c index a4fc677..af2997f 100644 --- a/test/accept.c +++ b/test/accept.c @@ -329,7 +329,7 @@ static int test_accept_cancel(unsigned usecs) usleep(usecs); sqe = io_uring_get_sqe(&m_io_uring); - io_uring_prep_cancel(sqe, (void *) 1, 0); + io_uring_prep_cancel(sqe, 1, 0); sqe->user_data = 2; ret = io_uring_submit(&m_io_uring); assert(ret == 1); diff --git a/test/io-cancel.c b/test/io-cancel.c index 703ffa7..c1df0df 100644 --- a/test/io-cancel.c +++ b/test/io-cancel.c @@ -128,7 +128,7 @@ static int start_cancel(struct io_uring *ring, int do_partial, int async_cancel) fprintf(stderr, "sqe get failed\n"); goto err; } - io_uring_prep_cancel(sqe, (void *) (unsigned long) i + 1, 0); + io_uring_prep_cancel(sqe, i + 1, 0); if (async_cancel) sqe->flags |= IOSQE_ASYNC; sqe->user_data = 0; @@ -246,7 +246,7 @@ static int test_dont_cancel_another_ring(void) fprintf(stderr, "%s: failed to get sqe\n", __FUNCTION__); return 1; } - io_uring_prep_cancel(sqe, (void *) (unsigned long)1, 0); + io_uring_prep_cancel(sqe, 1, 0); sqe->user_data = 2; ret = io_uring_submit(&ring2); @@ -326,7 +326,7 @@ static int test_cancel_req_across_fork(void) fprintf(stderr, "%s: failed to get sqe\n", __FUNCTION__); return 1; } - io_uring_prep_cancel(sqe, (void *) (unsigned long)1, 0); + io_uring_prep_cancel(sqe, 1, 0); sqe->user_data = 2; ret = io_uring_submit(&ring); diff --git a/test/multicqes_drain.c b/test/multicqes_drain.c index b107a48..148cdd7 100644 --- a/test/multicqes_drain.c +++ b/test/multicqes_drain.c @@ -91,7 +91,7 @@ void io_uring_sqe_prep(int op, struct io_uring_sqe *sqe, unsigned sqe_flags, int io_uring_prep_nop(sqe); break; case cancel: - io_uring_prep_poll_remove(sqe, (void *)(long)arg); + io_uring_prep_poll_remove(sqe, arg); break; } sqe->flags = sqe_flags; diff --git a/test/poll-cancel-ton.c b/test/poll-cancel-ton.c index f0875cd..05bf565 100644 --- a/test/poll-cancel-ton.c +++ b/test/poll-cancel-ton.c @@ -55,7 +55,7 @@ static int del_polls(struct io_uring *ring, int fd, int nr) sqe = io_uring_get_sqe(ring); data = sqe_index[lrand48() % nr]; - io_uring_prep_poll_remove(sqe, data); + io_uring_prep_poll_remove(sqe, (__u64)(uintptr_t)data); } ret = io_uring_submit(ring); diff --git a/test/poll-cancel.c b/test/poll-cancel.c index 408159d..6bddc6c 100644 --- a/test/poll-cancel.c +++ b/test/poll-cancel.c @@ -79,7 +79,7 @@ static int test_poll_cancel(void) pds[1].is_poll = 0; pds[1].is_cancel = 1; - io_uring_prep_poll_remove(sqe, &pds[0]); + io_uring_prep_poll_remove(sqe, (__u64)(uintptr_t)&pds[0]); io_uring_sqe_set_data(sqe, &pds[1]); ret = io_uring_submit(&ring); diff --git a/test/poll-mshot-update.c b/test/poll-mshot-update.c index 75ee52f..d06699a 100644 --- a/test/poll-mshot-update.c +++ b/test/poll-mshot-update.c @@ -42,7 +42,7 @@ static int has_poll_update(void) return -1; sqe = io_uring_get_sqe(&ring); - io_uring_prep_poll_update(sqe, NULL, NULL, POLLIN, IORING_TIMEOUT_UPDATE); + io_uring_prep_poll_update(sqe, 0, 0, POLLIN, IORING_TIMEOUT_UPDATE); ret = io_uring_submit(&ring); if (ret != 1) @@ -86,8 +86,8 @@ static int reap_polls(struct io_uring *ring) sqe = io_uring_get_sqe(ring); /* update event */ - io_uring_prep_poll_update(sqe, (void *)(unsigned long)i, NULL, - POLLIN, IORING_POLL_UPDATE_EVENTS); + io_uring_prep_poll_update(sqe, i, 0, POLLIN, + IORING_POLL_UPDATE_EVENTS); sqe->user_data = 0x12345678; } -- cgit v1.2.3 From 1d86befc0552332fce761a63b2e28e33b743a074 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Wed, 1 Dec 2021 13:20:37 +0000 Subject: man/io_uring_enter.2: notes about cqe-skip & drain interoperability IOSQE_CQE_SKIP_SUCCESS can't be used together with draining in a single ring, add a paragraph explaining what are the restrictions. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/8c81bf9b01a54d1214bb65678c2ff1362a9f9328.1638364791.git.asml.silence@gmail.com [axboe: tweak the wording] Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index b003e05..589f3ef 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -1115,6 +1115,15 @@ CQEs in cases where the side effects of a successfully executed operation is enough for userspace to know the state of the system. One such example would be writing to a synchronisation file. +This flag is incompatible with +.B IOSQE_IO_DRAIN. +Using both of them in a single ring is undefined behavior, even when they are +not used together in a single request. Currently, after the first request with +.B IOSQE_CQE_SKIP_SUCCESS, +all subsequent requests marked with drain will be failed at submission time. +Note that the error reporting is best effort only, and restrictions may change +in the future. + Available since 5.17. .PP -- cgit v1.2.3 From 39d5c150b2754a7074454f90ac510b0281bac190 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 10 Dec 2021 08:54:17 -0700 Subject: test/skip-cqe: skip file based run This test doesn't do anything with the file passed in as an argument, hence it should just skip if that's the case. Signed-off-by: Jens Axboe --- test/skip-cqe.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/skip-cqe.c b/test/skip-cqe.c index ba84d92..a01800a 100644 --- a/test/skip-cqe.c +++ b/test/skip-cqe.c @@ -309,6 +309,9 @@ int main(int argc, char *argv[]) int mid_idx = LINK_SIZE / 2; int last_idx = LINK_SIZE - 1; + if (argc > 1) + return 0; + if (pipe(fds)) { fprintf(stderr, "pipe() failed\n"); return 1; -- cgit v1.2.3 From 56c7bb43bdac67acd808cd88a507c78ac6c56259 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 10 Dec 2021 08:56:07 -0700 Subject: test/exit-no-cleanup: skip file based run This test doesn't do anything with the file passed in as an argument, hence it should just skip if that's the case. While in there, convert from MSDOS file format. Signed-off-by: Jens Axboe --- test/exit-no-cleanup.c | 231 +++++++++++++++++++++++++------------------------ 1 file changed, 117 insertions(+), 114 deletions(-) diff --git a/test/exit-no-cleanup.c b/test/exit-no-cleanup.c index 90ef394..b3fd5a4 100644 --- a/test/exit-no-cleanup.c +++ b/test/exit-no-cleanup.c @@ -1,114 +1,117 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Test case testing exit without cleanup and io-wq work pending or queued. - * - * From Florian Fischer - * Link: https://lore.kernel.org/io-uring/20211202165606.mqryio4yzubl7ms5@pasture/ - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "liburing.h" -#include "helpers.h" - -#define IORING_ENTRIES 8 - -static pthread_t *threads; -static pthread_barrier_t init_barrier; -static int sleep_fd, notify_fd; -static sem_t sem; - -void *thread_func(void *arg) -{ - struct io_uring ring; - int res; - - res = io_uring_queue_init(IORING_ENTRIES, &ring, 0); - if (res) - err(EXIT_FAILURE, "io_uring_queue_init failed"); - - pthread_barrier_wait(&init_barrier); - - for(;;) { - struct io_uring_cqe *cqe; - struct io_uring_sqe *sqe; - uint64_t buf; - int res; - - sqe = io_uring_get_sqe(&ring); - assert(sqe); - - io_uring_prep_read(sqe, sleep_fd, &buf, sizeof(buf), 0); - - res = io_uring_submit_and_wait(&ring, 1); - if (res < 0) - err(EXIT_FAILURE, "io_uring_submit_and_wait failed"); - - res = io_uring_peek_cqe(&ring, &cqe); - assert(!res); - if (cqe->res < 0) { - errno = -cqe->res; - err(EXIT_FAILURE, "read failed"); - } - assert(cqe->res == sizeof(buf)); - - sem_post(&sem); - - io_uring_cqe_seen(&ring, cqe); - } - - return NULL; -} - -int main(int argc, char *argv[]) -{ - int res, fds[2], i, cpus; - const uint64_t n = 0x42; - - cpus = get_nprocs(); - res = pthread_barrier_init(&init_barrier, NULL, cpus); - if (res) - err(EXIT_FAILURE, "pthread_barrier_init failed"); - - res = sem_init(&sem, 0, 0); - if (res) - err(EXIT_FAILURE, "sem_init failed"); - - threads = t_malloc(sizeof(pthread_t) * cpus); - - res = pipe(fds); - if (res) - err(EXIT_FAILURE, "pipe failed"); - - sleep_fd = fds[0]; - notify_fd = fds[1]; - - for (i = 0; i < cpus; i++) { - errno = pthread_create(&threads[i], NULL, thread_func, NULL); - if (errno) - err(EXIT_FAILURE, "pthread_create failed"); - } - - // Write #cpus notifications - for (i = 0; i < cpus; i++) { - res = write(notify_fd, &n, sizeof(n)); - if (res < 0) - err(EXIT_FAILURE, "write failed"); - assert(res == sizeof(n)); - } - - // Await that all notifications were received - for (i = 0; i < cpus; i++) - sem_wait(&sem); - - // Exit without resource cleanup - exit(EXIT_SUCCESS); -} +/* SPDX-License-Identifier: MIT */ +/* + * Test case testing exit without cleanup and io-wq work pending or queued. + * + * From Florian Fischer + * Link: https://lore.kernel.org/io-uring/20211202165606.mqryio4yzubl7ms5@pasture/ + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define IORING_ENTRIES 8 + +static pthread_t *threads; +static pthread_barrier_t init_barrier; +static int sleep_fd, notify_fd; +static sem_t sem; + +void *thread_func(void *arg) +{ + struct io_uring ring; + int res; + + res = io_uring_queue_init(IORING_ENTRIES, &ring, 0); + if (res) + err(EXIT_FAILURE, "io_uring_queue_init failed"); + + pthread_barrier_wait(&init_barrier); + + for(;;) { + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + uint64_t buf; + int res; + + sqe = io_uring_get_sqe(&ring); + assert(sqe); + + io_uring_prep_read(sqe, sleep_fd, &buf, sizeof(buf), 0); + + res = io_uring_submit_and_wait(&ring, 1); + if (res < 0) + err(EXIT_FAILURE, "io_uring_submit_and_wait failed"); + + res = io_uring_peek_cqe(&ring, &cqe); + assert(!res); + if (cqe->res < 0) { + errno = -cqe->res; + err(EXIT_FAILURE, "read failed"); + } + assert(cqe->res == sizeof(buf)); + + sem_post(&sem); + + io_uring_cqe_seen(&ring, cqe); + } + + return NULL; +} + +int main(int argc, char *argv[]) +{ + int res, fds[2], i, cpus; + const uint64_t n = 0x42; + + if (argc > 1) + return 0; + + cpus = get_nprocs(); + res = pthread_barrier_init(&init_barrier, NULL, cpus); + if (res) + err(EXIT_FAILURE, "pthread_barrier_init failed"); + + res = sem_init(&sem, 0, 0); + if (res) + err(EXIT_FAILURE, "sem_init failed"); + + threads = t_malloc(sizeof(pthread_t) * cpus); + + res = pipe(fds); + if (res) + err(EXIT_FAILURE, "pipe failed"); + + sleep_fd = fds[0]; + notify_fd = fds[1]; + + for (i = 0; i < cpus; i++) { + errno = pthread_create(&threads[i], NULL, thread_func, NULL); + if (errno) + err(EXIT_FAILURE, "pthread_create failed"); + } + + // Write #cpus notifications + for (i = 0; i < cpus; i++) { + res = write(notify_fd, &n, sizeof(n)); + if (res < 0) + err(EXIT_FAILURE, "write failed"); + assert(res == sizeof(n)); + } + + // Await that all notifications were received + for (i = 0; i < cpus; i++) + sem_wait(&sem); + + // Exit without resource cleanup + exit(EXIT_SUCCESS); +} -- cgit v1.2.3 From baf0a8c986e0ef6a7472d9b86dc072c1b2f2e390 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Tue, 23 Nov 2021 10:07:50 -0800 Subject: liburing: update io_uring.h header file Update io_uring.h header file with new op code for getdents64. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20211123180753.1598611-2-shr@fb.com Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index a7d193d..d75ca47 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -147,6 +147,7 @@ enum { IORING_OP_MKDIRAT, IORING_OP_SYMLINKAT, IORING_OP_LINKAT, + IORING_OP_GETDENTS, /* this goes last, obviously */ IORING_OP_LAST, -- cgit v1.2.3 From e96303ed7d2725c0b548b4f1df3fdbf207b0385f Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Tue, 23 Nov 2021 10:07:51 -0800 Subject: liburing: add prepare function for getdents64 Adds the io_uring_prep_getdents() function to setup a getdents64 call. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20211123180753.1598611-3-shr@fb.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 3705c5b..c334d04 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -701,6 +701,12 @@ static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd, sqe->hardlink_flags = (__u32) flags; } +static inline void io_uring_prep_getdents(struct io_uring_sqe *sqe, int fd, + void *buf, unsigned int count, uint64_t offset) +{ + io_uring_prep_rw(IORING_OP_GETDENTS, sqe, fd, buf, count, offset); +} + /* * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in * the SQ ring -- cgit v1.2.3 From aab3ca4920827bb2e31e8ff1b69b39066d610b1a Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Tue, 23 Nov 2021 10:07:52 -0800 Subject: liburing: Add test program for getdents call Add test program for getdents64 call. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20211123180753.1598611-4-shr@fb.com Signed-off-by: Jens Axboe --- test/Makefile | 1 + test/getdents.c | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 test/getdents.c diff --git a/test/Makefile b/test/Makefile index c70693c..b93af75 100644 --- a/test/Makefile +++ b/test/Makefile @@ -78,6 +78,7 @@ test_srcs := \ file-verify.c \ fixed-link.c \ fsync.c \ + getdents.c \ hardlink.c \ io-cancel.c \ iopoll.c \ diff --git a/test/getdents.c b/test/getdents.c new file mode 100644 index 0000000..81da36c --- /dev/null +++ b/test/getdents.c @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "liburing.h" + +#define BUFFER_SIZE 512 + +#define LIST_INIT(name) { &(name), &(name) } + +#define CONTAINER_OF(ptr, type, member) ( \ + { \ + const typeof(((type *)0)->member) *__ptr = (ptr); \ + (type *)((char *)__ptr - (intptr_t)(&((type *)0)->member)); \ + }) + +struct list { + struct list *next; + struct list *prev; +}; + +struct dir { + struct list list; + int ret; + + struct dir *parent; + int fd; + uint64_t off; + uint8_t buf[BUFFER_SIZE]; + char name[0]; +}; + +struct linux_dirent64 { + int64_t d_ino; /* 64-bit inode number */ + int64_t d_off; /* 64-bit offset to next structure */ + unsigned short d_reclen; /* Size of this dirent */ + unsigned char d_type; /* File type */ + char d_name[]; /* Filename (null-terminated) */ +}; + +/* Define global variables. */ +static struct io_uring ring; +static struct list active = LIST_INIT(active); +static int sqes_in_flight = 0; +static int num_dir_entries = 0; + +/* Forward declarations. */ +static void drain_cqes(void); +static void schedule_readdir(struct dir *dir); + +/* List helper functions. */ +static inline void +list_add_tail(struct list *l, struct list *head) +{ + l->next = head; + l->prev = head->prev; + head->prev->next = l; + head->prev = l; +} + +static inline void list_del(struct list *l) +{ + l->prev->next = l->next; + l->next->prev = l->prev; + l->prev = NULL; + l->next = NULL; +} + +static inline int is_list_empty(const struct list *l) +{ + return l->next == l; +} + +static struct io_uring_sqe *get_sqe(void) +{ + struct io_uring_sqe *sqe; + + sqe = io_uring_get_sqe(&ring); + while (sqe == NULL) { + drain_cqes(); + + int ret = io_uring_submit(&ring); + if (ret < 0 && errno != EBUSY) { + perror("io_uring_submit"); + exit(EXIT_FAILURE); + } + + sqe = io_uring_get_sqe(&ring); + } + + sqes_in_flight++; + return sqe; +} + +static void drain_cqes(void) +{ + int count; + uint32_t head; + struct io_uring_cqe *cqe; + + count = 0; + io_uring_for_each_cqe (&ring, head, cqe) { + struct dir *dir; + + dir = io_uring_cqe_get_data(cqe); + + list_add_tail(&dir->list, &active); + dir->ret = cqe->res; + + count++; + } + + sqes_in_flight -= count; + io_uring_cq_advance(&ring, count); +} + +static void schedule_opendir(struct dir *parent, const char *name) +{ + int len = strlen(name); + struct dir *dir; + struct io_uring_sqe *sqe; + + dir = malloc(sizeof(*dir) + len + 1); + if (dir == NULL) { + fprintf(stderr, "out of memory\n"); + exit(EXIT_FAILURE); + } + + dir->parent = parent; + dir->fd = -1; + memcpy(dir->name, name, len); + dir->name[len] = 0; + + sqe = get_sqe(); + io_uring_prep_openat(sqe, + (parent != NULL) ? parent->fd : AT_FDCWD, + dir->name, + O_DIRECTORY, + 0); + io_uring_sqe_set_data(sqe, dir); +} + +static void opendir_completion(struct dir *dir, int ret) +{ + if (ret < 0) { + fprintf(stderr, "error opening "); + fprintf(stderr, ": %s\n", strerror(-ret)); + return; + } + + dir->fd = ret; + dir->off = 0; + schedule_readdir(dir); +} + +static void schedule_readdir(struct dir *dir) +{ + struct io_uring_sqe *sqe; + + sqe = get_sqe(); + io_uring_prep_getdents(sqe, dir->fd, dir->buf, sizeof(dir->buf), dir->off); + io_uring_sqe_set_data(sqe, dir); +} + +static void readdir_completion(struct dir *dir, int ret) +{ + uint8_t *bufp; + uint8_t *end; + + if (ret < 0) { + fprintf(stderr, "error reading "); + fprintf(stderr, ": %s (%d)\n", strerror(-ret), ret); + return; + } + + if (ret == 0) { + free(dir); + return; + } + + bufp = dir->buf; + end = bufp + ret; + + while (bufp < end) { + struct linux_dirent64 *dent; + + dent = (struct linux_dirent64 *)bufp; + + if (strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { + if (dent->d_type == DT_DIR) + schedule_opendir(dir, dent->d_name); + } + + dir->off = dent->d_off; + bufp += dent->d_reclen; + ++num_dir_entries; + } + + schedule_readdir(dir); +} + +int main(int argc, char *argv[]) +{ + struct rlimit rlim; + + /* Increase number of files rlimit to 1M. */ + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { + perror("getrlimit"); + return 1; + } + + if (geteuid() == 0 && rlim.rlim_max < 1048576) + rlim.rlim_max = 1048576; + + if (rlim.rlim_cur < rlim.rlim_max) { + rlim.rlim_cur = rlim.rlim_max; + setrlimit(RLIMIT_NOFILE, &rlim); + } + + if (io_uring_queue_init(256, &ring, 0) < 0) { + perror("io_uring_queue_init"); + return 1; + } + + /* Submit and handle requests. */ + schedule_opendir(NULL, "."); + while (sqes_in_flight) { + int ret = io_uring_submit_and_wait(&ring, 1); + if (ret < 0 && errno != EBUSY) { + perror("io_uring_submit_and_wait"); + return 1; + } + + drain_cqes(); + + while (!is_list_empty(&active)) { + struct dir *dir; + + dir = CONTAINER_OF(active.next, struct dir, list); + list_del(&dir->list); + + if (dir->fd == -1) + opendir_completion(dir, dir->ret); + else + readdir_completion(dir, dir->ret); + } + } + + io_uring_queue_exit(&ring); + return num_dir_entries < 50; +} -- cgit v1.2.3 From 736a6e7daeef0413b00f29a20388278e8d205617 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Tue, 23 Nov 2021 10:07:53 -0800 Subject: liburing: Add man page for io_uring_prep_getdents call Adds the man page for the io_uring_prep_getdents call. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20211123180753.1598611-5-shr@fb.com Signed-off-by: Jens Axboe --- man/io_uring_prep_getdents.3 | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 man/io_uring_prep_getdents.3 diff --git a/man/io_uring_prep_getdents.3 b/man/io_uring_prep_getdents.3 new file mode 100644 index 0000000..15279f6 --- /dev/null +++ b/man/io_uring_prep_getdents.3 @@ -0,0 +1,64 @@ +.\" Copyright (C) 2021 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_getdents 3 "November 19, 2021" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_prep_getdents - prepare getdents64 call + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_getdents(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " void *buf," +.BI " unsigned int count," +.BI " uint64_t offset)" + +.SH DESCRIPTION +.PP +The io_uring_prep_getdents() prepares a getdents64 request. The submission queue +entry +.I sqe +is setup to use the file descriptor +.I fd +to start writing up to +.I count +bytes into the buffer +.I buf +starting at +.I offset. + +After the getdents call has been prepared it can be submitted with one of the submit +functions. + +.SH RETURN VALUE +None + +.SH EXAMPLE +A getdents io_uring call can be prepared like in the following code snippet. +The io_uring_sqe_set_data(3) call is not necessary, but it helps to correlate the +request with the results. + +.BI "void schedule_readdir(struct io_uring_sqe *sqe, struct dir *dir)" +.fi +.BI "{" +.fi +.BI " io_uring_prep_getdents(sqe," +.fi +.BI " dir->fd," +.fi +.BI " dir->buf," +.fi +.BI " sizeof(dir->buf)," +.fi +.BI " dir->off);" +.fi +.BI " io_uring_sqe_set_data(sqe, dir); +.fi +.BI "}" + + +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_sqe_set_data (3), io_uring_submit (3), io_uring_sqe_get_data (3) -- cgit v1.2.3 From eeeaa3ed4ce574fd4ddfa13738e7ca000cc14449 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 20 Dec 2021 11:12:49 -0700 Subject: test/getdents: style fixups Signed-off-by: Jens Axboe --- test/getdents.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/test/getdents.c b/test/getdents.c index 81da36c..d23f4cb 100644 --- a/test/getdents.c +++ b/test/getdents.c @@ -56,8 +56,7 @@ static void drain_cqes(void); static void schedule_readdir(struct dir *dir); /* List helper functions. */ -static inline void -list_add_tail(struct list *l, struct list *head) +static inline void list_add_tail(struct list *l, struct list *head) { l->next = head; l->prev = head->prev; @@ -101,9 +100,9 @@ static struct io_uring_sqe *get_sqe(void) static void drain_cqes(void) { - int count; - uint32_t head; - struct io_uring_cqe *cqe; + struct io_uring_cqe *cqe; + uint32_t head; + int count; count = 0; io_uring_for_each_cqe (&ring, head, cqe) { @@ -123,9 +122,9 @@ static void drain_cqes(void) static void schedule_opendir(struct dir *parent, const char *name) { - int len = strlen(name); - struct dir *dir; - struct io_uring_sqe *sqe; + struct io_uring_sqe *sqe; + int len = strlen(name); + struct dir *dir; dir = malloc(sizeof(*dir) + len + 1); if (dir == NULL) { -- cgit v1.2.3 From 7cc81e17c036e383cef7129e5027b76f35ff46e2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 20 Dec 2021 11:24:21 -0700 Subject: test/getdents: don't fail on kernels not supporting the feature Signed-off-by: Jens Axboe --- test/getdents.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/getdents.c b/test/getdents.c index d23f4cb..d4f4c8b 100644 --- a/test/getdents.c +++ b/test/getdents.c @@ -11,6 +11,8 @@ #include "helpers.h" #include "liburing.h" +static int no_getdents; + #define BUFFER_SIZE 512 #define LIST_INIT(name) { &(name), &(name) } @@ -174,6 +176,11 @@ static void readdir_completion(struct dir *dir, int ret) uint8_t *end; if (ret < 0) { + if (ret == -EINVAL) { + fprintf(stdout, "Kernel doesn't support getdents, skipping\n"); + no_getdents = 1; + return; + } fprintf(stderr, "error reading "); fprintf(stderr, ": %s (%d)\n", strerror(-ret), ret); return; @@ -249,9 +256,14 @@ int main(int argc, char *argv[]) opendir_completion(dir, dir->ret); else readdir_completion(dir, dir->ret); + if (no_getdents) { + num_dir_entries = 50; + goto done; + } } } +done: io_uring_queue_exit(&ring); return num_dir_entries < 50; } -- cgit v1.2.3 From 7233a8753cb7a4a137cdc5e534bb31fb2a0d53fd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 22 Dec 2021 19:54:45 -0700 Subject: test/getdents: ignore run if argument specified Signed-off-by: Jens Axboe --- test/getdents.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/getdents.c b/test/getdents.c index d4f4c8b..ac66f28 100644 --- a/test/getdents.c +++ b/test/getdents.c @@ -216,6 +216,9 @@ int main(int argc, char *argv[]) { struct rlimit rlim; + if (argc > 0) + return 0; + /* Increase number of files rlimit to 1M. */ if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { perror("getrlimit"); -- cgit v1.2.3 From 8ecd3fd959634df81d66af8b3a69c16202a014e8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 22 Dec 2021 19:55:20 -0700 Subject: Don't clear sqe->user_data as part of command prep Reasoning: 1) If the app doesn't set it, it should not be reading it. 2) I've gotten more than one report on someone setting user_data before calling io_uring_prep_cmdtype() and it's a bit confusing. I think we'll be fine not clearing this, and it may actually help some cases that end up being a bit confusing, particular for people new to the interface. Signed-off-by: Jens Axboe --- src/include/liburing.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index c334d04..b2683c1 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -280,7 +280,6 @@ static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd, sqe->addr = (unsigned long) addr; sqe->len = len; sqe->rw_flags = 0; - sqe->user_data = 0; sqe->buf_index = 0; sqe->personality = 0; sqe->file_index = 0; -- cgit v1.2.3 From deb00f959d436b8d022276daed54e641eed4df42 Mon Sep 17 00:00:00 2001 From: monte Date: Thu, 23 Dec 2021 10:45:20 +0800 Subject: examples/io_uring_cp: fix bug while re-queuing Add io_uring_submit after queue_prepped while re-queuing sqe. Signed-off-by: monte --- examples/io_uring-cp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/io_uring-cp.c b/examples/io_uring-cp.c index 9322575..43444d8 100644 --- a/examples/io_uring-cp.c +++ b/examples/io_uring-cp.c @@ -189,6 +189,7 @@ static int copy_file(struct io_uring *ring, off_t insize) if (cqe->res < 0) { if (cqe->res == -EAGAIN) { queue_prepped(ring, data); + io_uring_submit(ring); io_uring_cqe_seen(ring, cqe); continue; } @@ -201,6 +202,7 @@ static int copy_file(struct io_uring *ring, off_t insize) data->iov.iov_len -= cqe->res; data->offset += cqe->res; queue_prepped(ring, data); + io_uring_submit(ring); io_uring_cqe_seen(ring, cqe); continue; } -- cgit v1.2.3 From 96686aef79f9d60bd88acef57abc3b5baa0a36fd Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Thu, 23 Dec 2021 17:29:24 +1300 Subject: Clarify behaviour of offset in `prep_read`/`prep_write`. Signed-off-by: Samuel Williams --- man/io_uring_prep_read.3 | 10 +++++++++- man/io_uring_prep_readv.3 | 11 ++++++++++- man/io_uring_prep_readv2.3 | 14 ++++++++++++-- man/io_uring_prep_write.3 | 12 ++++++++++-- man/io_uring_prep_writev.3 | 13 +++++++++++-- man/io_uring_prep_writev2.3 | 16 ++++++++++++---- 6 files changed, 64 insertions(+), 12 deletions(-) diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index e3feb1f..4fc1420 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -26,9 +26,17 @@ to start reading .I nbytes into the buffer .I buf -at the +at the specified .I offset. +On files that support seeking, if the offset is set to -1, the read operation +commences at the file offset, and the file offset is incremented by the number +of bytes read. See +.BR read (2) +for more details. + +On files that are not capable of seeking, the offset is ignored. + After the read has been prepared it can be submitted with one of the submit functions. diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index 31eebc1..b08ccb9 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -26,11 +26,20 @@ to start reading .I nr_vecs into the .I iovecs -array at +array at the specified .I offset. +On files that support seeking, if the offset is set to -1, the read operation +commences at the file offset, and the file offset is incremented by the number +of bytes read. See +.BR read (2) +for more details. + +On files that are not capable of seeking, the offset is ignored. + After the write has been prepared it can be submitted with one of the submit functions. + .SH RETURN VALUE None .SH SEE ALSO diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 2755281..aaad25c 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -29,7 +29,7 @@ to start reading .I nr_vecs into the .I iovecs -array at +array at the specified .I offset. The behavior of the function can be controlled with the .I flags @@ -53,7 +53,17 @@ per-IO, return -EAGAIN if operation would block per-IO O_APPEND .TP -After the write has been prepared, it can be submitted with one of the submit functions. +On files that support seeking, if the offset is set to -1, the read operation +commences at the file offset, and the file offset is incremented by the number +of bytes read. See +.BR read (2) +for more details. + +On files that are not capable of seeking, the offset is ignored. + +After the write has been prepared, it can be submitted with one of the submit +functions. + .SH RETURN VALUE None .SH SEE ALSO diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index a03c1e7..f63dcdc 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -26,13 +26,21 @@ to start writing .I nbytes from the buffer .I buf -at file +at the specified .I offset. +On files that support seeking, if the offset is set to -1, the write operation +commences at the file offset, and the file offset is incremented by the number +of bytes written. See +.BR write (2) +for more details. + +On files that are not capable of seeking, the offset is ignored. + After the write has been prepared, it can be submitted with one of the submit functions. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3) \ No newline at end of file +.BR io_uring_get_sqe (3), io_uring_submit (3) diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 8f68e29..99652d3 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -26,12 +26,21 @@ to start writing .I nr_vecs from the .I iovecs -array at file +array at the specified .I offset. +On files that support seeking, if the offset is set to -1, the write operation +commences at the file offset, and the file offset is incremented by the number +of bytes written. See +.BR write (2) +for more details. + +On files that are not capable of seeking, the offset is ignored. + After the write has been prepared it can be submitted with one of the submit functions. + .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev2 (3), io_uring_submit (3) \ No newline at end of file +.BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev2 (3), io_uring_submit (3) diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index f1a4dcc..4f2ae47 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -28,7 +28,7 @@ to start writing .I nr_vecs from the .I iovecs -array at file +array at the specified .I offset. The behavior of the function can be controlled with the .I flags @@ -51,10 +51,18 @@ per-IO, return -EAGAIN if operation would block .B RWF_APPEND per-IO O_APPEND -.TP -After the write has been prepared, it can be submitted with one of the submit functions. +On files that support seeking, if the offset is set to -1, the write operation +commences at the file offset, and the file offset is incremented by the number +of bytes written. See +.BR write (2) +for more details. + +On files that are not capable of seeking, the offset is ignored. + +After the write has been prepared, it can be submitted with one of the submit +functions. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev (3), io_uring_submit (3) \ No newline at end of file +.BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev (3), io_uring_submit (3) -- cgit v1.2.3 From d3ff18ac5c1b98d47d8a1856654a68b06f5be301 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 23 Dec 2021 09:40:55 -0700 Subject: test: remove dead code Signed-off-by: Jens Axboe --- test/poll-cancel-ton.c | 3 --- test/send_recv.c | 5 ----- 2 files changed, 8 deletions(-) diff --git a/test/poll-cancel-ton.c b/test/poll-cancel-ton.c index 05bf565..1c4234b 100644 --- a/test/poll-cancel-ton.c +++ b/test/poll-cancel-ton.c @@ -128,9 +128,6 @@ int main(int argc, char *argv[]) } add_polls(&ring, pipe1[0], 30000); -#if 0 - usleep(1000); -#endif del_polls(&ring, pipe1[0], 30000); io_uring_queue_exit(&ring); diff --git a/test/send_recv.c b/test/send_recv.c index 1ee0234..ed45f83 100644 --- a/test/send_recv.c +++ b/test/send_recv.c @@ -22,11 +22,6 @@ static char str[] = "This is a test of send and recv over io_uring!"; #define PORT 10200 #define HOST "127.0.0.1" -#if 0 -# define io_uring_prep_send io_uring_prep_write -# define io_uring_prep_recv io_uring_prep_read -#endif - static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock, int registerfiles) { -- cgit v1.2.3 From 03be3e4fbddd491ef0426b6f9c9085a168acc1c4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 23 Dec 2021 09:43:40 -0700 Subject: Add test case for socket read with offset == -1 This should just get ignored by the kernel, so check that it is. This is fixed by kernel commit: commit 7b9762a5e8837b92a027d58d396a9d27f6440c36 Author: Jens Axboe Date: Wed Dec 22 20:26:56 2021 -0700 io_uring: zero iocb->ki_pos for stream file types Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 1 + test/socket-rw-offset.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 test/socket-rw-offset.c diff --git a/.gitignore b/.gitignore index 0a72f03..26458bd 100644 --- a/.gitignore +++ b/.gitignore @@ -103,6 +103,7 @@ /test/sigfd-deadlock /test/socket-rw /test/socket-rw-eagain +/test/socket-rw-offset /test/splice /test/sq-full /test/sq-full-cpp diff --git a/test/Makefile b/test/Makefile index b93af75..ccf4fde 100644 --- a/test/Makefile +++ b/test/Makefile @@ -126,6 +126,7 @@ test_srcs := \ sigfd-deadlock.c \ socket-rw.c \ socket-rw-eagain.c \ + socket-rw-offset.c \ splice.c \ sq-full.c \ sq-full-cpp.cc \ diff --git a/test/socket-rw-offset.c b/test/socket-rw-offset.c new file mode 100644 index 0000000..d44dd8c --- /dev/null +++ b/test/socket-rw-offset.c @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Check that a readv on a socket queued before a writev doesn't hang + * the processing. + * + * From Hrvoje Zeba + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" + +int main(int argc, char *argv[]) +{ + int p_fd[2], ret; + int32_t recv_s0; + int32_t val = 1; + struct sockaddr_in addr; + + if (argc > 1) + return 0; + + srand(getpid()); + + recv_s0 = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); + + ret = setsockopt(recv_s0, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); + assert(ret != -1); + ret = setsockopt(recv_s0, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + assert(ret != -1); + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + + do { + addr.sin_port = htons((rand() % 61440) + 4096); + ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)); + if (!ret) + break; + if (errno != EADDRINUSE) { + perror("bind"); + exit(1); + } + } while (1); + ret = listen(recv_s0, 128); + assert(ret != -1); + + + p_fd[1] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); + + val = 1; + ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + assert(ret != -1); + + int32_t flags = fcntl(p_fd[1], F_GETFL, 0); + assert(flags != -1); + + flags |= O_NONBLOCK; + ret = fcntl(p_fd[1], F_SETFL, flags); + assert(ret != -1); + + ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr)); + assert(ret == -1); + + flags = fcntl(p_fd[1], F_GETFL, 0); + assert(flags != -1); + + flags &= ~O_NONBLOCK; + ret = fcntl(p_fd[1], F_SETFL, flags); + assert(ret != -1); + + p_fd[0] = accept(recv_s0, NULL, NULL); + assert(p_fd[0] != -1); + + while (1) { + int32_t code; + socklen_t code_len = sizeof(code); + + ret = getsockopt(p_fd[1], SOL_SOCKET, SO_ERROR, &code, &code_len); + assert(ret != -1); + + if (!code) + break; + } + + struct io_uring m_io_uring; + + ret = io_uring_queue_init(32, &m_io_uring, 0); + assert(ret >= 0); + + char recv_buff[128]; + char send_buff[128]; + + { + struct iovec iov[1]; + + iov[0].iov_base = recv_buff; + iov[0].iov_len = sizeof(recv_buff); + + struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring); + assert(sqe != NULL); + + io_uring_prep_readv(sqe, p_fd[0], iov, 1, -1); + } + + { + struct iovec iov[1]; + + iov[0].iov_base = send_buff; + iov[0].iov_len = sizeof(send_buff); + + struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring); + assert(sqe != NULL); + + io_uring_prep_writev(sqe, p_fd[1], iov, 1, 0); + } + + ret = io_uring_submit_and_wait(&m_io_uring, 2); + assert(ret != -1); + + struct io_uring_cqe* cqe; + uint32_t head; + uint32_t count = 0; + + ret = 0; + while (count != 2) { + io_uring_for_each_cqe(&m_io_uring, head, cqe) { + if (cqe->res != 128) { + fprintf(stderr, "Got %d, expected 128\n", cqe->res); + ret = 1; + goto err; + } + assert(cqe->res == 128); + count++; + } + + assert(count <= 2); + io_uring_cq_advance(&m_io_uring, count); + } + +err: + io_uring_queue_exit(&m_io_uring); + return ret; +} -- cgit v1.2.3 From 515e03ef1a82e1b866209756bb18bea053988c9d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 23 Dec 2021 09:47:41 -0700 Subject: test/socket-rw-offset: skip for kernels without cur position rw This will fail on kernels that don't have IORING_FEAT_RW_CUR_POS, so just skip the test if we are running on one of those. Signed-off-by: Jens Axboe --- test/socket-rw-offset.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/socket-rw-offset.c b/test/socket-rw-offset.c index d44dd8c..fe6ace3 100644 --- a/test/socket-rw-offset.c +++ b/test/socket-rw-offset.c @@ -95,10 +95,15 @@ int main(int argc, char *argv[]) } struct io_uring m_io_uring; + struct io_uring_params p = { }; - ret = io_uring_queue_init(32, &m_io_uring, 0); + ret = io_uring_queue_init_params(32, &m_io_uring, &p); assert(ret >= 0); + /* skip for kernels without cur position read/write */ + if (!(p.features & IORING_FEAT_RW_CUR_POS)) + return 0; + char recv_buff[128]; char send_buff[128]; -- cgit v1.2.3 From 918d8061ffdfdf253806a1e8e141c71644e678bd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 5 Jan 2022 12:21:28 -0700 Subject: Remove getdents support There are still discussions about the API, and hence the feature will miss the 5.17 kernel release. As the API is likely to change, remove the getdents support for now and we can re-add it when it's finalized. Signed-off-by: Jens Axboe --- man/io_uring_prep_getdents.3 | 64 ---------- src/include/liburing.h | 6 - src/include/liburing/io_uring.h | 1 - test/Makefile | 1 - test/getdents.c | 272 ---------------------------------------- 5 files changed, 344 deletions(-) delete mode 100644 man/io_uring_prep_getdents.3 delete mode 100644 test/getdents.c diff --git a/man/io_uring_prep_getdents.3 b/man/io_uring_prep_getdents.3 deleted file mode 100644 index 15279f6..0000000 --- a/man/io_uring_prep_getdents.3 +++ /dev/null @@ -1,64 +0,0 @@ -.\" Copyright (C) 2021 Stefan Roesch -.\" -.\" SPDX-License-Identifier: LGPL-2.0-or-later -.\" -.TH io_uring_prep_getdents 3 "November 19, 2021" "liburing-2.1" "liburing Manual" -.SH NAME -io_uring_prep_getdents - prepare getdents64 call - -.SH SYNOPSIS -.nf -.BR "#include " -.PP -.BI "void io_uring_prep_getdents(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " void *buf," -.BI " unsigned int count," -.BI " uint64_t offset)" - -.SH DESCRIPTION -.PP -The io_uring_prep_getdents() prepares a getdents64 request. The submission queue -entry -.I sqe -is setup to use the file descriptor -.I fd -to start writing up to -.I count -bytes into the buffer -.I buf -starting at -.I offset. - -After the getdents call has been prepared it can be submitted with one of the submit -functions. - -.SH RETURN VALUE -None - -.SH EXAMPLE -A getdents io_uring call can be prepared like in the following code snippet. -The io_uring_sqe_set_data(3) call is not necessary, but it helps to correlate the -request with the results. - -.BI "void schedule_readdir(struct io_uring_sqe *sqe, struct dir *dir)" -.fi -.BI "{" -.fi -.BI " io_uring_prep_getdents(sqe," -.fi -.BI " dir->fd," -.fi -.BI " dir->buf," -.fi -.BI " sizeof(dir->buf)," -.fi -.BI " dir->off);" -.fi -.BI " io_uring_sqe_set_data(sqe, dir); -.fi -.BI "}" - - -.SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_sqe_set_data (3), io_uring_submit (3), io_uring_sqe_get_data (3) diff --git a/src/include/liburing.h b/src/include/liburing.h index b2683c1..3050fcc 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -700,12 +700,6 @@ static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd, sqe->hardlink_flags = (__u32) flags; } -static inline void io_uring_prep_getdents(struct io_uring_sqe *sqe, int fd, - void *buf, unsigned int count, uint64_t offset) -{ - io_uring_prep_rw(IORING_OP_GETDENTS, sqe, fd, buf, count, offset); -} - /* * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in * the SQ ring diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index d75ca47..a7d193d 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -147,7 +147,6 @@ enum { IORING_OP_MKDIRAT, IORING_OP_SYMLINKAT, IORING_OP_LINKAT, - IORING_OP_GETDENTS, /* this goes last, obviously */ IORING_OP_LAST, diff --git a/test/Makefile b/test/Makefile index ccf4fde..7ccd657 100644 --- a/test/Makefile +++ b/test/Makefile @@ -78,7 +78,6 @@ test_srcs := \ file-verify.c \ fixed-link.c \ fsync.c \ - getdents.c \ hardlink.c \ io-cancel.c \ iopoll.c \ diff --git a/test/getdents.c b/test/getdents.c deleted file mode 100644 index ac66f28..0000000 --- a/test/getdents.c +++ /dev/null @@ -1,272 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "helpers.h" -#include "liburing.h" - -static int no_getdents; - -#define BUFFER_SIZE 512 - -#define LIST_INIT(name) { &(name), &(name) } - -#define CONTAINER_OF(ptr, type, member) ( \ - { \ - const typeof(((type *)0)->member) *__ptr = (ptr); \ - (type *)((char *)__ptr - (intptr_t)(&((type *)0)->member)); \ - }) - -struct list { - struct list *next; - struct list *prev; -}; - -struct dir { - struct list list; - int ret; - - struct dir *parent; - int fd; - uint64_t off; - uint8_t buf[BUFFER_SIZE]; - char name[0]; -}; - -struct linux_dirent64 { - int64_t d_ino; /* 64-bit inode number */ - int64_t d_off; /* 64-bit offset to next structure */ - unsigned short d_reclen; /* Size of this dirent */ - unsigned char d_type; /* File type */ - char d_name[]; /* Filename (null-terminated) */ -}; - -/* Define global variables. */ -static struct io_uring ring; -static struct list active = LIST_INIT(active); -static int sqes_in_flight = 0; -static int num_dir_entries = 0; - -/* Forward declarations. */ -static void drain_cqes(void); -static void schedule_readdir(struct dir *dir); - -/* List helper functions. */ -static inline void list_add_tail(struct list *l, struct list *head) -{ - l->next = head; - l->prev = head->prev; - head->prev->next = l; - head->prev = l; -} - -static inline void list_del(struct list *l) -{ - l->prev->next = l->next; - l->next->prev = l->prev; - l->prev = NULL; - l->next = NULL; -} - -static inline int is_list_empty(const struct list *l) -{ - return l->next == l; -} - -static struct io_uring_sqe *get_sqe(void) -{ - struct io_uring_sqe *sqe; - - sqe = io_uring_get_sqe(&ring); - while (sqe == NULL) { - drain_cqes(); - - int ret = io_uring_submit(&ring); - if (ret < 0 && errno != EBUSY) { - perror("io_uring_submit"); - exit(EXIT_FAILURE); - } - - sqe = io_uring_get_sqe(&ring); - } - - sqes_in_flight++; - return sqe; -} - -static void drain_cqes(void) -{ - struct io_uring_cqe *cqe; - uint32_t head; - int count; - - count = 0; - io_uring_for_each_cqe (&ring, head, cqe) { - struct dir *dir; - - dir = io_uring_cqe_get_data(cqe); - - list_add_tail(&dir->list, &active); - dir->ret = cqe->res; - - count++; - } - - sqes_in_flight -= count; - io_uring_cq_advance(&ring, count); -} - -static void schedule_opendir(struct dir *parent, const char *name) -{ - struct io_uring_sqe *sqe; - int len = strlen(name); - struct dir *dir; - - dir = malloc(sizeof(*dir) + len + 1); - if (dir == NULL) { - fprintf(stderr, "out of memory\n"); - exit(EXIT_FAILURE); - } - - dir->parent = parent; - dir->fd = -1; - memcpy(dir->name, name, len); - dir->name[len] = 0; - - sqe = get_sqe(); - io_uring_prep_openat(sqe, - (parent != NULL) ? parent->fd : AT_FDCWD, - dir->name, - O_DIRECTORY, - 0); - io_uring_sqe_set_data(sqe, dir); -} - -static void opendir_completion(struct dir *dir, int ret) -{ - if (ret < 0) { - fprintf(stderr, "error opening "); - fprintf(stderr, ": %s\n", strerror(-ret)); - return; - } - - dir->fd = ret; - dir->off = 0; - schedule_readdir(dir); -} - -static void schedule_readdir(struct dir *dir) -{ - struct io_uring_sqe *sqe; - - sqe = get_sqe(); - io_uring_prep_getdents(sqe, dir->fd, dir->buf, sizeof(dir->buf), dir->off); - io_uring_sqe_set_data(sqe, dir); -} - -static void readdir_completion(struct dir *dir, int ret) -{ - uint8_t *bufp; - uint8_t *end; - - if (ret < 0) { - if (ret == -EINVAL) { - fprintf(stdout, "Kernel doesn't support getdents, skipping\n"); - no_getdents = 1; - return; - } - fprintf(stderr, "error reading "); - fprintf(stderr, ": %s (%d)\n", strerror(-ret), ret); - return; - } - - if (ret == 0) { - free(dir); - return; - } - - bufp = dir->buf; - end = bufp + ret; - - while (bufp < end) { - struct linux_dirent64 *dent; - - dent = (struct linux_dirent64 *)bufp; - - if (strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { - if (dent->d_type == DT_DIR) - schedule_opendir(dir, dent->d_name); - } - - dir->off = dent->d_off; - bufp += dent->d_reclen; - ++num_dir_entries; - } - - schedule_readdir(dir); -} - -int main(int argc, char *argv[]) -{ - struct rlimit rlim; - - if (argc > 0) - return 0; - - /* Increase number of files rlimit to 1M. */ - if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { - perror("getrlimit"); - return 1; - } - - if (geteuid() == 0 && rlim.rlim_max < 1048576) - rlim.rlim_max = 1048576; - - if (rlim.rlim_cur < rlim.rlim_max) { - rlim.rlim_cur = rlim.rlim_max; - setrlimit(RLIMIT_NOFILE, &rlim); - } - - if (io_uring_queue_init(256, &ring, 0) < 0) { - perror("io_uring_queue_init"); - return 1; - } - - /* Submit and handle requests. */ - schedule_opendir(NULL, "."); - while (sqes_in_flight) { - int ret = io_uring_submit_and_wait(&ring, 1); - if (ret < 0 && errno != EBUSY) { - perror("io_uring_submit_and_wait"); - return 1; - } - - drain_cqes(); - - while (!is_list_empty(&active)) { - struct dir *dir; - - dir = CONTAINER_OF(active.next, struct dir, list); - list_del(&dir->list); - - if (dir->fd == -1) - opendir_completion(dir, dir->ret); - else - readdir_completion(dir, dir->ret); - if (no_getdents) { - num_dir_entries = 50; - goto done; - } - } - } - -done: - io_uring_queue_exit(&ring); - return num_dir_entries < 50; -} -- cgit v1.2.3 From 5ee4feeac88d42c8c4cadee1f242279ff5fc0277 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 7 Jan 2022 20:02:16 +0700 Subject: test/socket-rw-eagain: Fix UB, accessing dead object Dereference to a local variable that has been out of its scope is undefined behavior, it may contain garbage or the compiler may reuse it for other local variables. Fix this by moving the struct iov variable declarations so their lifetime is extended. Cc: Jens Axboe Fixes: 76e3b7921fee98a5627cd270628b6a5160d3857d ("Add nonblock empty socket read test") Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220107130218.1238910-2-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- test/socket-rw-eagain.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/socket-rw-eagain.c b/test/socket-rw-eagain.c index 9854e00..2d6a817 100644 --- a/test/socket-rw-eagain.c +++ b/test/socket-rw-eagain.c @@ -25,6 +25,7 @@ int main(int argc, char *argv[]) int32_t recv_s0; int32_t val = 1; struct sockaddr_in addr; + struct iovec iov_r[1], iov_w[1]; if (argc > 1) return 0; @@ -105,28 +106,24 @@ int main(int argc, char *argv[]) char send_buff[128]; { - struct iovec iov[1]; - - iov[0].iov_base = recv_buff; - iov[0].iov_len = sizeof(recv_buff); + iov_r[0].iov_base = recv_buff; + iov_r[0].iov_len = sizeof(recv_buff); struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring); assert(sqe != NULL); - io_uring_prep_readv(sqe, p_fd[0], iov, 1, 0); + io_uring_prep_readv(sqe, p_fd[0], iov_r, 1, 0); sqe->user_data = 1; } { - struct iovec iov[1]; - - iov[0].iov_base = send_buff; - iov[0].iov_len = sizeof(send_buff); + iov_w[0].iov_base = send_buff; + iov_w[0].iov_len = sizeof(send_buff); struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring); assert(sqe != NULL); - io_uring_prep_writev(sqe, p_fd[1], iov, 1, 0); + io_uring_prep_writev(sqe, p_fd[1], iov_w, 1, 0); sqe->user_data = 2; } -- cgit v1.2.3 From e5bb9f3e65f0e18132b27ba0322e2419d87f4f92 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 7 Jan 2022 20:02:17 +0700 Subject: test/socket-rw: Fix UB, accessing dead object Dereference to a local variable that has been out of its scope is undefined behavior, it may contain garbage or the compiler may reuse it for other local variables. Fix this by moving the struct iov variable declarations so their lifetime is extended. Cc: Jens Axboe Cc: Hrvoje Zeba Fixes: 79ba71a4881fb1cd300520553d7285b3c5ee1293 ("Add deadlock socket read/write test case") Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220107130218.1238910-3-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- test/socket-rw.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/socket-rw.c b/test/socket-rw.c index 5afd14d..4fbf032 100644 --- a/test/socket-rw.c +++ b/test/socket-rw.c @@ -27,6 +27,7 @@ int main(int argc, char *argv[]) int32_t recv_s0; int32_t val = 1; struct sockaddr_in addr; + struct iovec iov_r[1], iov_w[1]; if (argc > 1) return 0; @@ -103,27 +104,23 @@ int main(int argc, char *argv[]) char send_buff[128]; { - struct iovec iov[1]; - - iov[0].iov_base = recv_buff; - iov[0].iov_len = sizeof(recv_buff); + iov_r[0].iov_base = recv_buff; + iov_r[0].iov_len = sizeof(recv_buff); struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring); assert(sqe != NULL); - io_uring_prep_readv(sqe, p_fd[0], iov, 1, 0); + io_uring_prep_readv(sqe, p_fd[0], iov_r, 1, 0); } { - struct iovec iov[1]; - - iov[0].iov_base = send_buff; - iov[0].iov_len = sizeof(send_buff); + iov_w[0].iov_base = send_buff; + iov_w[0].iov_len = sizeof(send_buff); struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring); assert(sqe != NULL); - io_uring_prep_writev(sqe, p_fd[1], iov, 1, 0); + io_uring_prep_writev(sqe, p_fd[1], iov_w, 1, 0); } ret = io_uring_submit_and_wait(&m_io_uring, 2); -- cgit v1.2.3 From 3f10277e6412d56cb52424d07f685128112498fa Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 7 Jan 2022 20:02:18 +0700 Subject: test/socket-rw-offset: Fix UB, accessing dead object Dereference to a local variable that has been out of its scope is undefined behavior, it may contain garbage or the compiler may reuse it for other local variables. Fix this by moving the struct iov variable declarations so their lifetime is extended. Cc: Jens Axboe Cc: Hrvoje Zeba Fixes: 03be3e4fbddd491ef0426b6f9c9085a168acc1c4 ("Add test case for socket read with offset == -1") Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220107130218.1238910-4-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- test/socket-rw-offset.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/socket-rw-offset.c b/test/socket-rw-offset.c index fe6ace3..987b6c9 100644 --- a/test/socket-rw-offset.c +++ b/test/socket-rw-offset.c @@ -27,6 +27,7 @@ int main(int argc, char *argv[]) int32_t recv_s0; int32_t val = 1; struct sockaddr_in addr; + struct iovec iov_r[1], iov_w[1]; if (argc > 1) return 0; @@ -108,27 +109,23 @@ int main(int argc, char *argv[]) char send_buff[128]; { - struct iovec iov[1]; - - iov[0].iov_base = recv_buff; - iov[0].iov_len = sizeof(recv_buff); + iov_r[0].iov_base = recv_buff; + iov_r[0].iov_len = sizeof(recv_buff); struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring); assert(sqe != NULL); - io_uring_prep_readv(sqe, p_fd[0], iov, 1, -1); + io_uring_prep_readv(sqe, p_fd[0], iov_r, 1, -1); } { - struct iovec iov[1]; - - iov[0].iov_base = send_buff; - iov[0].iov_len = sizeof(send_buff); + iov_w[0].iov_base = send_buff; + iov_w[0].iov_len = sizeof(send_buff); struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring); assert(sqe != NULL); - io_uring_prep_writev(sqe, p_fd[1], iov, 1, 0); + io_uring_prep_writev(sqe, p_fd[1], iov_w, 1, 0); } ret = io_uring_submit_and_wait(&m_io_uring, 2); -- cgit v1.2.3 From b865a9eb3f1e2e7d7739a9b0c41ed2e53754212a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 14 Jan 2022 10:15:14 -0700 Subject: Add pollfree test case This is the syzbot test case, testing if POLLFREE is handled correctly. Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 2 + test/pollfree.c | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 401 insertions(+) create mode 100644 test/pollfree.c diff --git a/.gitignore b/.gitignore index 26458bd..6057951 100644 --- a/.gitignore +++ b/.gitignore @@ -87,6 +87,7 @@ /test/poll-many /test/poll-ring /test/poll-v-poll +/test/pollfree /test/probe /test/read-write /test/register-restrictions diff --git a/test/Makefile b/test/Makefile index 7ccd657..1d3dc13 100644 --- a/test/Makefile +++ b/test/Makefile @@ -107,6 +107,7 @@ test_srcs := \ poll-mshot-update.c \ poll-ring.c \ poll-v-poll.c \ + pollfree.c \ probe.c \ read-write.c \ register-restrictions.c \ @@ -218,6 +219,7 @@ thread-exit: override LDFLAGS += -lpthread ring-leak2: override LDFLAGS += -lpthread poll-mshot-update: override LDFLAGS += -lpthread exit-no-cleanup: override LDFLAGS += -lpthread +pollfree: override LDFLAGS += -lpthread install: $(test_targets) runtests.sh runtests-loop.sh $(INSTALL) -D -d -m 755 $(datadir)/liburing-test/ diff --git a/test/pollfree.c b/test/pollfree.c new file mode 100644 index 0000000..f73b6ad --- /dev/null +++ b/test/pollfree.c @@ -0,0 +1,398 @@ +// https://syzkaller.appspot.com/bug?id=5f5a44abb4cba056fe24255c4fcb7e7bbe13de7a +// autogenerated by syzkaller (https://github.com/google/syzkaller) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + int state; +} event_t; + +static void event_init(event_t* ev) +{ + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + if (ev->state) + exit(1); + __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE); + syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000); +} + +static void event_wait(event_t* ev) +{ + while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE)) + syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0); +} + +static int event_isset(event_t* ev) +{ + return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE); +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + for (;;) { + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts); + if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE)) + return 1; + now = current_time_ms(); + if (now - start > timeout) + return 0; + } +} + +#define SIZEOF_IO_URING_SQE 64 +#define SIZEOF_IO_URING_CQE 16 +#define SQ_HEAD_OFFSET 0 +#define SQ_TAIL_OFFSET 64 +#define SQ_RING_MASK_OFFSET 256 +#define SQ_RING_ENTRIES_OFFSET 264 +#define SQ_FLAGS_OFFSET 276 +#define SQ_DROPPED_OFFSET 272 +#define CQ_HEAD_OFFSET 128 +#define CQ_TAIL_OFFSET 192 +#define CQ_RING_MASK_OFFSET 260 +#define CQ_RING_ENTRIES_OFFSET 268 +#define CQ_RING_OVERFLOW_OFFSET 284 +#define CQ_FLAGS_OFFSET 280 +#define CQ_CQES_OFFSET 320 + +struct io_sqring_offsets { + uint32_t head; + uint32_t tail; + uint32_t ring_mask; + uint32_t ring_entries; + uint32_t flags; + uint32_t dropped; + uint32_t array; + uint32_t resv1; + uint64_t resv2; +}; + +struct io_cqring_offsets { + uint32_t head; + uint32_t tail; + uint32_t ring_mask; + uint32_t ring_entries; + uint32_t overflow; + uint32_t cqes; + uint64_t resv[2]; +}; + +struct io_uring_params { + uint32_t sq_entries; + uint32_t cq_entries; + uint32_t flags; + uint32_t sq_thread_cpu; + uint32_t sq_thread_idle; + uint32_t features; + uint32_t resv[4]; + struct io_sqring_offsets sq_off; + struct io_cqring_offsets cq_off; +}; + +#define IORING_OFF_SQ_RING 0 +#define IORING_OFF_SQES 0x10000000ULL + +#define sys_io_uring_setup 425 +static long syz_io_uring_setup(volatile long a0, volatile long a1, + volatile long a2, volatile long a3, + volatile long a4, volatile long a5) +{ + uint32_t entries = (uint32_t)a0; + struct io_uring_params* setup_params = (struct io_uring_params*)a1; + void* vma1 = (void*)a2; + void* vma2 = (void*)a3; + void** ring_ptr_out = (void**)a4; + void** sqes_ptr_out = (void**)a5; + uint32_t fd_io_uring = syscall(sys_io_uring_setup, entries, setup_params); + uint32_t sq_ring_sz = + setup_params->sq_off.array + setup_params->sq_entries * sizeof(uint32_t); + uint32_t cq_ring_sz = setup_params->cq_off.cqes + + setup_params->cq_entries * SIZEOF_IO_URING_CQE; + uint32_t ring_sz = sq_ring_sz > cq_ring_sz ? sq_ring_sz : cq_ring_sz; + *ring_ptr_out = mmap(vma1, ring_sz, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, + IORING_OFF_SQ_RING); + uint32_t sqes_sz = setup_params->sq_entries * SIZEOF_IO_URING_SQE; + *sqes_ptr_out = + mmap(vma2, sqes_sz, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, IORING_OFF_SQES); + return fd_io_uring; +} + +static long syz_io_uring_submit(volatile long a0, volatile long a1, + volatile long a2, volatile long a3) +{ + char* ring_ptr = (char*)a0; + char* sqes_ptr = (char*)a1; + char* sqe = (char*)a2; + uint32_t sqes_index = (uint32_t)a3; + uint32_t sq_ring_entries = *(uint32_t*)(ring_ptr + SQ_RING_ENTRIES_OFFSET); + uint32_t cq_ring_entries = *(uint32_t*)(ring_ptr + CQ_RING_ENTRIES_OFFSET); + uint32_t sq_array_off = + (CQ_CQES_OFFSET + cq_ring_entries * SIZEOF_IO_URING_CQE + 63) & ~63; + if (sq_ring_entries) + sqes_index %= sq_ring_entries; + char* sqe_dest = sqes_ptr + sqes_index * SIZEOF_IO_URING_SQE; + memcpy(sqe_dest, sqe, SIZEOF_IO_URING_SQE); + uint32_t sq_ring_mask = *(uint32_t*)(ring_ptr + SQ_RING_MASK_OFFSET); + uint32_t* sq_tail_ptr = (uint32_t*)(ring_ptr + SQ_TAIL_OFFSET); + uint32_t sq_tail = *sq_tail_ptr & sq_ring_mask; + uint32_t sq_tail_next = *sq_tail_ptr + 1; + uint32_t* sq_array = (uint32_t*)(ring_ptr + sq_array_off); + *(sq_array + sq_tail) = sqes_index; + __atomic_store_n(sq_tail_ptr, sq_tail_next, __ATOMIC_RELEASE); + return 0; +} + +static void kill_and_wait(int pid, int* status) +{ + kill(-pid, SIGKILL); + kill(pid, SIGKILL); + for (int i = 0; i < 100; i++) { + if (waitpid(-1, status, WNOHANG | __WALL) == pid) + return; + usleep(1000); + } + DIR* dir = opendir("/sys/fs/fuse/connections"); + if (dir) { + for (;;) { + struct dirent* ent = readdir(dir); + if (!ent) + break; + if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) + continue; + char abort[300]; + snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", + ent->d_name); + int fd = open(abort, O_WRONLY); + if (fd == -1) { + continue; + } + if (write(fd, abort, 1) < 0) { + } + close(fd); + } + closedir(dir); + } else { + } + while (waitpid(-1, status, __WALL) != pid) { + } +} + +static void setup_test() +{ + prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + setpgrp(); +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + int i, call, thread; + for (call = 0; call < 4; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS __WALL + +static void loop(void) +{ + int iter = 0; + for (; iter < 5000; iter++) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + setup_test(); + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + sleep_ms(1); + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +#ifndef __NR_io_uring_enter +#define __NR_io_uring_enter 426 +#endif + +uint64_t r[4] = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0}; + +void execute_call(int call) +{ + intptr_t res = 0; + switch (call) { + case 0: + *(uint64_t*)0x200000c0 = 0; + res = syscall(__NR_signalfd4, -1, 0x200000c0ul, 8ul, 0ul); + if (res != -1) + r[0] = res; + break; + case 1: + *(uint32_t*)0x20000a84 = 0; + *(uint32_t*)0x20000a88 = 0; + *(uint32_t*)0x20000a8c = 0; + *(uint32_t*)0x20000a90 = 0; + *(uint32_t*)0x20000a98 = -1; + memset((void*)0x20000a9c, 0, 12); + res = -1; + res = syz_io_uring_setup(0x87, 0x20000a80, 0x206d6000, 0x206d7000, + 0x20000000, 0x20000040); + if (res != -1) { + r[1] = res; + r[2] = *(uint64_t*)0x20000000; + r[3] = *(uint64_t*)0x20000040; + } + break; + case 2: + *(uint8_t*)0x20002240 = 6; + *(uint8_t*)0x20002241 = 0; + *(uint16_t*)0x20002242 = 0; + *(uint32_t*)0x20002244 = r[0]; + *(uint64_t*)0x20002248 = 0; + *(uint64_t*)0x20002250 = 0; + *(uint32_t*)0x20002258 = 0; + *(uint16_t*)0x2000225c = 0; + *(uint16_t*)0x2000225e = 0; + *(uint64_t*)0x20002260 = 0; + *(uint16_t*)0x20002268 = 0; + *(uint16_t*)0x2000226a = 0; + memset((void*)0x2000226c, 0, 20); + syz_io_uring_submit(r[2], r[3], 0x20002240, 0); + break; + case 3: + syscall(__NR_io_uring_enter, r[1], 0x1523a, 0, 0ul, 0ul, 0xaul); + break; + } +} +int main(void) +{ + syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); + syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + loop(); + return 0; +} -- cgit v1.2.3 From bbcaabf808b53ef11ad9851c6b968140fb430500 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 19 Jan 2022 18:09:40 -0700 Subject: man/io_uring_enter.2: make it clear that chains terminate at submit The man page does state that: "This flag has no effect on previous SQE submissions [...]" but add some more verbiage to make it absolutely clear that chains cannot persist across submission boundaries. Link: https://github.com/axboe/liburing/issues/510 Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 589f3ef..ec70222 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -1047,12 +1047,14 @@ submitted SQEs have completed, and new SQEs will not be started before this one completes. Available since 5.2. .TP .B IOSQE_IO_LINK -When this flag is specified, it forms a link with the next SQE in the -submission ring. That next SQE will not be started before this one completes. -This, in effect, forms a chain of SQEs, which can be arbitrarily long. The tail -of the chain is denoted by the first SQE that does not have this flag set. -This flag has no effect on previous SQE submissions, nor does it impact SQEs -that are outside of the chain tail. This means that multiple chains can be +When this flag is specified, the SQE forms a link with the next SQE in the +submission ring. That next SQE will not be started before the previous request +completes. This, in effect, forms a chain of SQEs, which can be arbitrarily +long. The tail of the chain is denoted by the first SQE that does not have this +flag set. Chains are not supported across submission boundaries. EVen if the +last SQE in a submission has this flag set, it will still terminate the current +chain. This flag has no effect on previous SQE submissions, nor does it impact +SQEs that are outside of the chain tail. This means that multiple chains can be executing in parallel, or chains and individual SQEs. Only members inside the chain are serialized. A chain of SQEs will be broken, if any request in that chain ends in error. io_uring considers any unexpected result an error. This -- cgit v1.2.3 From 29ff69397fa13478b5619201347c51159874279e Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 23 Jan 2022 14:42:30 +0700 Subject: nolibc: Don't use `malloc()` and `free()` as the function name Miyasaki reports that liburing with CONFIG_NOLIBC breaks apps that use libc. The first spotted issue was a realloc() call that results in an invalid pointer, and then the program exits with SIGABRT. The cause is liburing nolibc overrides malloc() and free() from the libc (especially when we statically link the "liburing.a" to the apps that use libc). The malloc() and free() from liburing nolibc use hand-coded Assembly to invoke mmap() and munmap() syscall directly. That means any allocation from malloc() is not a valid object with respect to the libc, and free() will also break the app if we use it to free a pointer from a libc function (e.g., strdup()). liburing nolibc should not break any libc app. This renames the malloc() and free() to __uring_malloc() and __uring_free(). Also, add new inline functions to wrap the malloc() and free(), they are uring_malloc() and uring_free(). These wrappers will call the appropriate functions depending on CONFIG_NOLIBC. Fixes: f48ee3168cdc325233825603269f304d348d323c ("Add nolibc build support") Cc: Tea Inside Mailing List Reported-by: Miyasaki Kohaku Tested-by: Miyasaki Kohaku Co-authored-by: Alviro Iskandar Setiawan Signed-off-by: Alviro Iskandar Setiawan Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220123074230.3353274-1-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- src/lib.h | 20 ++++++++++++++++++++ src/nolibc.c | 4 ++-- src/setup.c | 6 +++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/lib.h b/src/lib.h index 58d91be..bd02805 100644 --- a/src/lib.h +++ b/src/lib.h @@ -25,6 +25,26 @@ }) #endif +void *__uring_malloc(size_t len); +void __uring_free(void *p); + +static inline void *uring_malloc(size_t len) +{ +#ifdef CONFIG_NOLIBC + return __uring_malloc(len); +#else + return malloc(len); +#endif +} + +static inline void uring_free(void *ptr) +{ +#ifdef CONFIG_NOLIBC + __uring_free(ptr); +#else + free(ptr); +#endif +} static inline long get_page_size(void) { diff --git a/src/nolibc.c b/src/nolibc.c index 251780b..f7848d3 100644 --- a/src/nolibc.c +++ b/src/nolibc.c @@ -23,7 +23,7 @@ struct uring_heap { char user_p[] __attribute__((__aligned__)); }; -void *malloc(size_t len) +void *__uring_malloc(size_t len) { struct uring_heap *heap; @@ -36,7 +36,7 @@ void *malloc(size_t len) return heap->user_p; } -void free(void *p) +void __uring_free(void *p) { struct uring_heap *heap; diff --git a/src/setup.c b/src/setup.c index 891fc43..1e4dbf4 100644 --- a/src/setup.c +++ b/src/setup.c @@ -178,7 +178,7 @@ struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring) int r; len = sizeof(*probe) + 256 * sizeof(struct io_uring_probe_op); - probe = malloc(len); + probe = uring_malloc(len); if (!probe) return NULL; memset(probe, 0, len); @@ -187,7 +187,7 @@ struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring) if (r >= 0) return probe; - free(probe); + uring_free(probe); return NULL; } @@ -208,7 +208,7 @@ struct io_uring_probe *io_uring_get_probe(void) void io_uring_free_probe(struct io_uring_probe *probe) { - free(probe); + uring_free(probe); } static inline int __fls(int x) -- cgit v1.2.3 From af24b1f56b765f8110d39883ac3107604bcf3f78 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Wed, 26 Jan 2022 11:25:02 -0800 Subject: liburing: add man pages for helper functions. This adds man pages for the following functions: - io_uring_cq_advance - io_uring_cq_ready - io_uring_free_probe - io_uring_get_probe - io_uring_opcode_supported - io_uring_sq_ready - io_uring_sq_space_left - io_uring_sqe_set_flags - io_uring_sqring_wait Signed-off-by: Stefan Roesch Signed-off-by: Jens Axboe --- man/io_uring_cq_advance.3 | 35 ++++++++++++++++++++++++ man/io_uring_cq_ready.3 | 25 +++++++++++++++++ man/io_uring_free_probe.3 | 24 +++++++++++++++++ man/io_uring_get_probe.3 | 25 +++++++++++++++++ man/io_uring_opcode_supported.3 | 29 ++++++++++++++++++++ man/io_uring_sq_ready.3 | 25 +++++++++++++++++ man/io_uring_sq_space_left.3 | 25 +++++++++++++++++ man/io_uring_sqe_set_flags.3 | 59 +++++++++++++++++++++++++++++++++++++++++ man/io_uring_sqring_wait.3 | 30 +++++++++++++++++++++ 9 files changed, 277 insertions(+) create mode 100644 man/io_uring_cq_advance.3 create mode 100644 man/io_uring_cq_ready.3 create mode 100644 man/io_uring_free_probe.3 create mode 100644 man/io_uring_get_probe.3 create mode 100644 man/io_uring_opcode_supported.3 create mode 100644 man/io_uring_sq_ready.3 create mode 100644 man/io_uring_sq_space_left.3 create mode 100644 man/io_uring_sqe_set_flags.3 create mode 100644 man/io_uring_sqring_wait.3 diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 new file mode 100644 index 0000000..59bb681 --- /dev/null +++ b/man/io_uring_cq_advance.3 @@ -0,0 +1,35 @@ +.\" Copyright (C) 2022 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_cq_advance 3 "January 25, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_cq_advance - Mark one or more io_uring completion events as processed +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_cqe_advance(struct io_uring *ring," +.BI " unsigned nr)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_cq_advance() function marks +.I nr +IO completions +belonging to the +.I ring +param as processed. + +After the caller has submitted a request with io_uring_submit(), he can retrieve +the completion with io_uring_wait_cqe() and mark it then as processed with +io_uring_cqe_seen(). + +The function io_uring_cqe_seen() calls the function io_uring_cq_advance(). + +Completions must be marked as completed, so their slot can get reused. +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_cqe_seen (3) \ No newline at end of file diff --git a/man/io_uring_cq_ready.3 b/man/io_uring_cq_ready.3 new file mode 100644 index 0000000..a540d2a --- /dev/null +++ b/man/io_uring_cq_ready.3 @@ -0,0 +1,25 @@ +.\" Copyright (C) 2022 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_cq_ready "January 25, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_cq_ready - number of unconsumed ready entries in the CQ ring +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "unsigned io_uring_cq_ready(const struct io_uring *ring)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_cq_ready() function retuns the number of unconsumed entries that +are ready belonging to the +.I ring +param. + +.SH RETURN VALUE +Returns the number of unconsumed ready entries in the CQ ring. +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_wait_cqe (3) \ No newline at end of file diff --git a/man/io_uring_free_probe.3 b/man/io_uring_free_probe.3 new file mode 100644 index 0000000..bc674ca --- /dev/null +++ b/man/io_uring_free_probe.3 @@ -0,0 +1,24 @@ +.\" Copyright (C) 2022 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_free_probe "January 25, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_free_probe - free probe instance +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_free_probe(struct io_uring_probe *probe)" +.fi +.PP +.SH DESCRIPTION +.PP +The function io_uring_free_probe() frees the +.I probe +instance allocated with the io_uring_get_probe() function. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_probe (3) \ No newline at end of file diff --git a/man/io_uring_get_probe.3 b/man/io_uring_get_probe.3 new file mode 100644 index 0000000..1bb8b14 --- /dev/null +++ b/man/io_uring_get_probe.3 @@ -0,0 +1,25 @@ +.\" Copyright (C) 2022 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_get_probe "January 25, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_get_probe - get probe instance +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "io_uring_probe *io_uring_get_probe(void)" +.fi +.PP +.SH DESCRIPTION +.PP +The function io_uring_get_probe() returns an allocated io_uring_probe +structure to the caller. The caller is responsible for freeing the +structure with the function io_uring_free_probe(). + +.SH RETURN VALUE +On success it returns an allocated io_uring_probe structure, otherwise +it returns NULL. +.SH SEE ALSO +.BR io_uring_free_probe (3) \ No newline at end of file diff --git a/man/io_uring_opcode_supported.3 b/man/io_uring_opcode_supported.3 new file mode 100644 index 0000000..4d03027 --- /dev/null +++ b/man/io_uring_opcode_supported.3 @@ -0,0 +1,29 @@ +.\" Copyright (C) 2022 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_opcode_supported "January 25, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_opcode_supported - is op code supported? +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_opcode_supported(struct io_uring_probe *probe," +.BI " int opode) +.fi +.PP +.SH DESCRIPTION +.PP +The function io_uring_opcode_supported allows the caller to determine if +the passed in +.I opcode +belonging to the +.I probe +param is supported. An instance of the io_uring_probe instance can be +obtained by calling the function io_uring_get_probe(). + +.SH RETURN VALUE +On success it returns 1, otherwise it returns 0. +.SH SEE ALSO +.BR io_uring_get_probe (3) \ No newline at end of file diff --git a/man/io_uring_sq_ready.3 b/man/io_uring_sq_ready.3 new file mode 100644 index 0000000..f583903 --- /dev/null +++ b/man/io_uring_sq_ready.3 @@ -0,0 +1,25 @@ +.\" Copyright (C) 2022 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_sq_ready "January 25, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_sq_ready - number of unconsumed or unsubmitted entries in the SQ ring +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "unsigned io_uring_sq_ready(const struct io_uring *ring)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_sq_ready() function retuns the number of unconsumed (if SQPOLL) or +unsubmitted entries that exist in the SQ ring belonging to the +.I ring +param. + +.SH RETURN VALUE +Returns the number of unconsumed or unsubmitted entries in the SQ ring. +.SH SEE ALSO +.BR io_uring_cq_ready (3) \ No newline at end of file diff --git a/man/io_uring_sq_space_left.3 b/man/io_uring_sq_space_left.3 new file mode 100644 index 0000000..45d229a --- /dev/null +++ b/man/io_uring_sq_space_left.3 @@ -0,0 +1,25 @@ +.\" Copyright (C) 2022 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_sq_space-left "January 25, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_sq_space_left - free space in the SQ ring +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "unsigned io_uring_sq_space_left(const struct io_uring *ring)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_sq_space_left() function retuns how much space is left in the +SQ ring belonging to the +.I ring +param. + +.SH RETURN VALUE +Returns the free space in the SQ ring. +.SH SEE ALSO +.BR io_uring_sq_ready (3) \ No newline at end of file diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 new file mode 100644 index 0000000..bbe62b5 --- /dev/null +++ b/man/io_uring_sqe_set_flags.3 @@ -0,0 +1,59 @@ +.\" Copyright (C) 2022 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_sqe_set_flags "January 25, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_sqe_set_flags - set flags for submission queue entry +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_sqe_set_flags(struct io_uring_sqe *sqe," +.BI " unsigned flags)" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_sqe_set_flags() function allows the caller to change the +behavior of the submission queue entry by specifying flags. It enables the +.I flags +belonging to the +.I sqe +submission queue entry param. + +.I flags +is a bit mask of 0 or more of the following values ORed together: +.TP +.B IOSQE_FIXED_FILE +Use registered files that previously registered buffers. +.TP +.B IOSQE_ASYNC +Normal operation for io_uring is to try and issue an sqe as non-blocking first, +and if that fails, execute it in an async manner. To support more efficient +overlapped operation of requests that the application knows/assumes will +always (or most of the time) block, the application can ask for an sqe to be +issued async from the start. +.TP +.B IOSQE_IO_LINK +When this flag is specified, the SQE forms a link with the next SQE in the +submission ring. That next SQE will not be started before the previous request +completes. This, in effect, forms a chain of SQEs, which can be arbitrarily +long. The tail of the chain is denoted by the first SQE that does not have this +flag set. Chains are not supported across submission boundaries. EVen if the +last SQE in a submission has this flag set, it will still terminate the current +chain. This flag has no effect on previous SQE submissions, nor does it impact +SQEs that are outside of the chain tail. This means that multiple chains can be +executing in parallel, or chains and individual SQEs. Only members inside the +chain are serialized. A chain of SQEs will be broken, if any request in that +chain ends in error. +.TP +.B IOSQE_IO_DRAIN +When this flag is specified, the SQE will not be started before previously +submitted SQEs have completed, and new SQEs will not be started before this +one completes. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_register(3) \ No newline at end of file diff --git a/man/io_uring_sqring_wait.3 b/man/io_uring_sqring_wait.3 new file mode 100644 index 0000000..e0fb731 --- /dev/null +++ b/man/io_uring_sqring_wait.3 @@ -0,0 +1,30 @@ +.\" Copyright (C) 2022 Stefan Roesch +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_sqring_wait "January 25, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_sqring_wait - wait for free space in the SQ ring +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_sqring_wait(struct io_uring *ring)" +.fi +.PP +.SH DESCRIPTION +.PP +The function io_uring_sqring_wait() allows the caller to wait for space +to free up in the SQ ring belonging to the +.I ring +param, which happens when the kernel side thread +has consumed one or more entries. If the SQ ring is currently non-full, +no action is taken. + +This feature can only be used when SQPOLL is enabled. + +.SH RETURN VALUE +On success it returns the free space. If the kernel does not support the +feature, -EINVAL is returned. +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_wait_cqes (3) \ No newline at end of file -- cgit v1.2.3 From ffb473d2fe12dfb2d4ad624774ac19017f2bb071 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 26 Jan 2022 13:55:52 -0700 Subject: man page typos Fix a typo, and improve some of the documentation as well. Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 2 +- man/io_uring_sqe_set_flags.3 | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index ec70222..9350652 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -1051,7 +1051,7 @@ When this flag is specified, the SQE forms a link with the next SQE in the submission ring. That next SQE will not be started before the previous request completes. This, in effect, forms a chain of SQEs, which can be arbitrarily long. The tail of the chain is denoted by the first SQE that does not have this -flag set. Chains are not supported across submission boundaries. EVen if the +flag set. Chains are not supported across submission boundaries. Even if the last SQE in a submission has this flag set, it will still terminate the current chain. This flag has no effect on previous SQE submissions, nor does it impact SQEs that are outside of the chain tail. This means that multiple chains can be diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 index bbe62b5..b066f1d 100644 --- a/man/io_uring_sqe_set_flags.3 +++ b/man/io_uring_sqe_set_flags.3 @@ -26,7 +26,8 @@ submission queue entry param. is a bit mask of 0 or more of the following values ORed together: .TP .B IOSQE_FIXED_FILE -Use registered files that previously registered buffers. +The file descriptor in the SQE refers to the index of a previously registered +file or direct file descriptor, not a normal file descriptor. .TP .B IOSQE_ASYNC Normal operation for io_uring is to try and issue an sqe as non-blocking first, @@ -40,7 +41,7 @@ When this flag is specified, the SQE forms a link with the next SQE in the submission ring. That next SQE will not be started before the previous request completes. This, in effect, forms a chain of SQEs, which can be arbitrarily long. The tail of the chain is denoted by the first SQE that does not have this -flag set. Chains are not supported across submission boundaries. EVen if the +flag set. Chains are not supported across submission boundaries. Even if the last SQE in a submission has this flag set, it will still terminate the current chain. This flag has no effect on previous SQE submissions, nor does it impact SQEs that are outside of the chain tail. This means that multiple chains can be @@ -56,4 +57,4 @@ one completes. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_submit (3), io_uring_register(3) \ No newline at end of file +.BR io_uring_submit (3), io_uring_register(3) -- cgit v1.2.3 From 8ee5cf229151d6dd7cf4934f4b4e31688302ab81 Mon Sep 17 00:00:00 2001 From: Mingqiang Sun Date: Fri, 28 Jan 2022 22:06:07 +0800 Subject: examples/link-cp.c: fix the last file-block retry may overflow Signed-off-by: Mingqiang Sun --- examples/link-cp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/link-cp.c b/examples/link-cp.c index 244d21a..018124e 100644 --- a/examples/link-cp.c +++ b/examples/link-cp.c @@ -95,7 +95,7 @@ static int handle_cqe(struct io_uring *ring, struct io_uring_cqe *cqe) if (cqe->res < 0) { if (cqe->res == -ECANCELED) { - queue_rw_pair(ring, BS, data->offset); + queue_rw_pair(ring, data->iov.iov_len, data->offset); inflight += 2; } else { printf("cqe error: %s\n", strerror(-cqe->res)); -- cgit v1.2.3 From 7ad74b99e5a7d5c1f697b60f11f516bd780d0e6d Mon Sep 17 00:00:00 2001 From: Jon Kohler Date: Fri, 28 Jan 2022 09:36:15 -0800 Subject: fix statx configure and build on !CONFIG_HAVE_STATX toolchains Update configure and test/Makefile, such that if !CONFIG_HAVE_STATX will not generate statx.c test. Without this patch, liburing fails to compile on an older toolchain that does not have statx available. Fixes: #516 Signed-off-by: Jon Kohler --- configure | 2 +- test/Makefile | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/configure b/configure index 2061148..805a671 100755 --- a/configure +++ b/configure @@ -471,7 +471,7 @@ else cat >> $compat_h << EOF EOF fi -if test "$glibc_statx" = "no" && "$statx" = "yes"; then +if [ "$glibc_statx" = "no" ] && [ "$statx" = "yes" ]; then cat >> $compat_h << EOF #include diff --git a/test/Makefile b/test/Makefile index 1d3dc13..b74ba06 100644 --- a/test/Makefile +++ b/test/Makefile @@ -138,7 +138,6 @@ test_srcs := \ sq-poll-share.c \ sqpoll-sleep.c \ sq-space_left.c \ - statx.c \ stdout.c \ submit-link-fail.c \ submit-reuse.c \ -- cgit v1.2.3 From 5efa7d07186177612a9da97b1a7cea2f4479f937 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 3 Feb 2022 16:09:32 -0700 Subject: man/io_uring_enter.2: correct kernel version for IORING_OP_ACCEPT Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 9350652..74df569 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -527,7 +527,7 @@ can use them. See and .B IORING_REGISTER_FILES. -Available since 5.15. +Available since 5.5. .TP .B IORING_OP_ASYNC_CANCEL -- cgit v1.2.3 From 5bde26e4587168a439cabdbe73740454249e5204 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 4 Feb 2022 08:52:11 -0700 Subject: test/eventfd-reg.c: add basic test case to exercise reg+unreg Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 1 + test/eventfd-reg.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 test/eventfd-reg.c diff --git a/.gitignore b/.gitignore index 6057951..15559ab 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ /test/empty-eownerdead /test/eventfd /test/eventfd-disable +/test/eventfd-reg /test/eventfd-ring /test/exit-no-cleanup /test/fadvise diff --git a/test/Makefile b/test/Makefile index b74ba06..1e318f7 100644 --- a/test/Makefile +++ b/test/Makefile @@ -65,6 +65,7 @@ test_srcs := \ empty-eownerdead.c \ eventfd.c \ eventfd-disable.c \ + eventfd-reg.c \ eventfd-ring.c \ exec-target.c \ exit-no-cleanup.c \ diff --git a/test/eventfd-reg.c b/test/eventfd-reg.c new file mode 100644 index 0000000..c708a51 --- /dev/null +++ b/test/eventfd-reg.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: test eventfd registration+unregistration + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" + +int main(int argc, char *argv[]) +{ + struct io_uring_params p = {}; + struct io_uring ring; + int ret, evfd[2], i; + + if (argc > 1) + return 0; + + ret = io_uring_queue_init_params(8, &ring, &p); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + evfd[0] = eventfd(0, EFD_CLOEXEC); + evfd[1] = eventfd(0, EFD_CLOEXEC); + if (evfd[0] < 0 || evfd[1] < 0) { + perror("eventfd"); + return 1; + } + + ret = io_uring_register_eventfd(&ring, evfd[0]); + if (ret) { + fprintf(stderr, "failed to register evfd: %d\n", ret); + return 1; + } + + /* Check that registrering again will get -EBUSY */ + ret = io_uring_register_eventfd(&ring, evfd[1]); + if (ret != -EBUSY) { + fprintf(stderr, "unexpected 2nd register: %d\n", ret); + return 1; + } + close(evfd[1]); + + ret = io_uring_unregister_eventfd(&ring); + if (ret) { + fprintf(stderr, "unexpected unregister: %d\n", ret); + return 1; + } + + /* loop 100 registers/unregister */ + for (i = 0; i < 100; i++) { + ret = io_uring_register_eventfd(&ring, evfd[0]); + if (ret) { + fprintf(stderr, "failed to register evfd: %d\n", ret); + return 1; + } + + ret = io_uring_unregister_eventfd(&ring); + if (ret) { + fprintf(stderr, "unexpected unregister: %d\n", ret); + return 1; + } + } + + close(evfd[0]); + return 0; +} -- cgit v1.2.3 From e4170c717ef9a619c1df1a9840613f30db7baf19 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 9 Feb 2022 10:56:59 -0700 Subject: test/double-poll-crash: only run on x86/x86-64 Various syzbot oddities makes this x86 specific, so just disable the run on other archs. Also kill useless mmap() while in there. Signed-off-by: Jens Axboe --- test/double-poll-crash.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/double-poll-crash.c b/test/double-poll-crash.c index d9277be..e932bec 100644 --- a/test/double-poll-crash.c +++ b/test/double-poll-crash.c @@ -107,11 +107,13 @@ uint64_t r[4] = {0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff}; int main(int argc, char *argv[]) { +#if !defined(__i386) && !defined(__x86_64__) + return 0; +#endif if (argc > 1) return 0; - mmap((void *)0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); intptr_t res = 0; -- cgit v1.2.3 From 42df1f30d8f6f759c94e821ce4e04cff39f0c6e1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 9 Feb 2022 11:00:54 -0700 Subject: test/read-write: work on 4kb blocksize devices For some tests, we chop the iovec in two. Since the iovec is 4k in size, this fails on devices that are actually using 4k block sizes. Just bump the iovec size to 8k, then it'll work fine on 4k devices. Signed-off-by: Jens Axboe --- test/read-write.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/read-write.c b/test/read-write.c index d54ad0e..5dc6f87 100644 --- a/test/read-write.c +++ b/test/read-write.c @@ -16,8 +16,8 @@ #include "helpers.h" #include "liburing.h" -#define FILE_SIZE (128 * 1024) -#define BS 4096 +#define FILE_SIZE (256 * 1024) +#define BS 8192 #define BUFFERS (FILE_SIZE / BS) static struct iovec *vecs; -- cgit v1.2.3 From 90a4da4d51f137229a2ef39b25880d81adfcb487 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Feb 2022 10:32:28 -0700 Subject: test/read-write: update EFBIG to work with 256M files A previous commit changed the file size from 128M to 256M, and this caused the EFBIG test case to be buggy. Update it so it works again. Fixes: 42df1f30d8f6 ("test/read-write: work on 4kb blocksize devices") Signed-off-by: Jens Axboe --- test/read-write.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/read-write.c b/test/read-write.c index 5dc6f87..f505f93 100644 --- a/test/read-write.c +++ b/test/read-write.c @@ -658,8 +658,8 @@ static int test_write_efbig(void) return 1; } rlim = old_rlim; - rlim.rlim_cur = 64 * 1024; - rlim.rlim_max = 64 * 1024; + rlim.rlim_cur = 128 * 1024; + rlim.rlim_max = 128 * 1024; if (setrlimit(RLIMIT_FSIZE, &rlim) < 0) { perror("setrlimit"); return 1; -- cgit v1.2.3 From d238216f0d45d7670d7aa10e753ac049c2b9bd61 Mon Sep 17 00:00:00 2001 From: Alviro Iskandar Setiawan Date: Fri, 11 Feb 2022 22:57:50 +0700 Subject: arch/generic: Create arch generic syscall wrappers This is a preparation for refactoring the syscall wrappers. This creates a new file src/arch/generic/syscall.h. This file contains libc syscall wrappers for architectures that don't have arch specific code. In the next patches, we will include this file from src/syscall.h. It aims to reduce the usage of #ifdef/#endif that occurs in every function in src/syscall.h file. Also, it will make the arch specific code structure cleaner and easier to manage. Cc: Nugra Signed-off-by: Alviro Iskandar Setiawan Co-authored-by: Ammar Faizi Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220211155753.143698-2-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- src/arch/generic/syscall.h | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/arch/generic/syscall.h diff --git a/src/arch/generic/syscall.h b/src/arch/generic/syscall.h new file mode 100644 index 0000000..7136290 --- /dev/null +++ b/src/arch/generic/syscall.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef LIBURING_ARCH_GENERIC_SYSCALL_H +#define LIBURING_ARCH_GENERIC_SYSCALL_H + +static inline int ____sys_io_uring_register(int fd, unsigned opcode, + const void *arg, unsigned nr_args) +{ + int ret; + ret = syscall(__NR_io_uring_register, fd, opcode, arg, nr_args); + return (ret < 0) ? -errno : ret; +} + +static inline int ____sys_io_uring_setup(unsigned entries, + struct io_uring_params *p) +{ + int ret; + ret = syscall(__NR_io_uring_setup, entries, p); + return (ret < 0) ? -errno : ret; +} + +static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig, int sz) +{ + int ret; + ret = syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, + sig, sz); + return (ret < 0) ? -errno : ret; +} + +static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig) +{ + return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, + _NSIG / 8); +} + +static inline void *uring_mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) +{ + void *ret; + ret = mmap(addr, length, prot, flags, fd, offset); + return (ret == MAP_FAILED) ? ERR_PTR(-errno) : ret; +} + +static inline int uring_munmap(void *addr, size_t length) +{ + int ret; + ret = munmap(addr, length); + return (ret < 0) ? -errno : ret; +} + +static inline int uring_madvise(void *addr, size_t length, int advice) +{ + int ret; + ret = madvise(addr, length, advice); + return (ret < 0) ? -errno : ret; +} + +static inline int uring_getrlimit(int resource, struct rlimit *rlim) +{ + int ret; + ret = getrlimit(resource, rlim); + return (ret < 0) ? -errno : ret; +} + +static inline int uring_setrlimit(int resource, const struct rlimit *rlim) +{ + int ret; + ret = setrlimit(resource, rlim); + return (ret < 0) ? -errno : ret; +} + +static inline int uring_close(int fd) +{ + int ret; + ret = close(fd); + return (ret < 0) ? -errno : ret; +} + +#endif /* #ifndef LIBURING_ARCH_GENERIC_SYSCALL_H */ -- cgit v1.2.3 From 8347a3d9553a2f31affddacb7bd9eaa14f2e7ed7 Mon Sep 17 00:00:00 2001 From: Alviro Iskandar Setiawan Date: Fri, 11 Feb 2022 22:57:51 +0700 Subject: arch/x86, syscall: Refactor arch specific and generic syscall wrappers In the previous patch, we create a file src/arch/generic/syscall.h. Let's use it. There are 3 things in this patch (a, b, c): a) Remove all ____sys* and uring_* functions from src/syscall.h. We will define them in the src/arch/* files, so we can avoid many #ifdef/#endif. b) Rename all __arch_impl_* functions in src/arch/x86/syscall.h with ____sys* and uring_* to support point (1). c) Always use arch specific code for x86-64 syscalls, even with CONFIG_NOLIBC disabled. For other archs, currently, will still use the libc wrappers (we provided it in src/arch/generic*). Major changes happen in point (c). We will always use inline assembly for invoking syscall for x86-64. Reasoning: 1. It reduces function calls. ------------------------------ If we use libc, we need to call syscall(2) function and deal with a global state via `errno` macro (`errno` macro will expand to a function call too). If we use inline Assembly, we eliminate many functions calls, we don't need to use `errno` or any global state anymore as it will just directly return error code that we can check with a simple comparison. 2. Allow the compiler to reuse caller clobbered registers. ----------------------------------------------------------- By the rule of System V ABI x86-64, a function call clobbers %rax, %rdi, %rsi, %rdx, %rcx, %r8, %r9, %r10 and %r11. On Linux, syscall only clobbers %rax, %rcx and %r11. But since libc syscall(2) wrapper is a function call, the compiler will always miss the opportunity to reuse those clobbered registers. That means it has to preserve the life values on the stack if they happen to be in the clobbered registers (that's also extra memory access). By inlining the syscall instruction, the compiler has an opportunity to reuse all registers after invoking syscall, except %rax, %rcx and %r11. 3. Smaller binary size. ------------------------ Point (1) and (2) will also reduce the data movement, hence smaller Assembly code, smaller binary size. 4. Reduce %rip round trip to libc.so. -------------------------------------- Call to a libc function will make the %rip jump to libc.so memory area. This can have extra overhead and extra icache misses in some scenario. If we inline the syscall instruction, this overhead can be removed. No functional change should be visible to user. At this point, we may stil use libc for malloc(), free() and memset(), so CONFIG_NOLIBC is still meaningful after these changes. Cc: Nugra Signed-off-by: Alviro Iskandar Setiawan Co-authored-by: Ammar Faizi Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220211155753.143698-3-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- src/arch/generic/syscall.h | 4 ++ src/arch/x86/syscall.h | 57 ++++++++++------- src/syscall.h | 155 +++++++-------------------------------------- 3 files changed, 63 insertions(+), 153 deletions(-) diff --git a/src/arch/generic/syscall.h b/src/arch/generic/syscall.h index 7136290..6b10fe3 100644 --- a/src/arch/generic/syscall.h +++ b/src/arch/generic/syscall.h @@ -1,5 +1,9 @@ /* SPDX-License-Identifier: MIT */ +#ifndef __INTERNAL__LIBURING_SYSCALL_H + #error "This file should be included from src/syscall.h (liburing)" +#endif + #ifndef LIBURING_ARCH_GENERIC_SYSCALL_H #define LIBURING_ARCH_GENERIC_SYSCALL_H diff --git a/src/arch/x86/syscall.h b/src/arch/x86/syscall.h index 2fb3552..2d5642c 100644 --- a/src/arch/x86/syscall.h +++ b/src/arch/x86/syscall.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: MIT */ +#ifndef __INTERNAL__LIBURING_SYSCALL_H + #error "This file should be included from src/syscall.h (liburing)" +#endif + #ifndef LIBURING_ARCH_X86_SYSCALL_H #define LIBURING_ARCH_X86_SYSCALL_H -#ifndef LIBURING_SYSCALL_H -# error "This file should be included from src/syscall.h (liburing)" -#endif - #if defined(__x86_64__) /** * Note for syscall registers usage (x86-64): @@ -29,8 +29,8 @@ * %r11 == %rflags and %rcx == %rip. */ -static inline void *__arch_impl_mmap(void *addr, size_t length, int prot, - int flags, int fd, off_t offset) +static inline void *uring_mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) { void *rax; register int r10 __asm__("r10") = flags; @@ -52,7 +52,7 @@ static inline void *__arch_impl_mmap(void *addr, size_t length, int prot, return rax; } -static inline int __arch_impl_munmap(void *addr, size_t length) +static inline int uring_munmap(void *addr, size_t length) { long rax; @@ -67,7 +67,7 @@ static inline int __arch_impl_munmap(void *addr, size_t length) return (int) rax; } -static inline int __arch_impl_madvise(void *addr, size_t length, int advice) +static inline int uring_madvise(void *addr, size_t length, int advice) { long rax; @@ -83,7 +83,7 @@ static inline int __arch_impl_madvise(void *addr, size_t length, int advice) return (int) rax; } -static inline int __arch_impl_getrlimit(int resource, struct rlimit *rlim) +static inline int uring_getrlimit(int resource, struct rlimit *rlim) { long rax; @@ -98,7 +98,7 @@ static inline int __arch_impl_getrlimit(int resource, struct rlimit *rlim) return (int) rax; } -static inline int __arch_impl_setrlimit(int resource, const struct rlimit *rlim) +static inline int uring_setrlimit(int resource, const struct rlimit *rlim) { long rax; @@ -113,7 +113,7 @@ static inline int __arch_impl_setrlimit(int resource, const struct rlimit *rlim) return (int) rax; } -static inline int __arch_impl_close(int fd) +static inline int uring_close(int fd) { long rax; @@ -127,9 +127,9 @@ static inline int __arch_impl_close(int fd) return (int) rax; } -static inline int __arch_impl_io_uring_register(int fd, unsigned opcode, - const void *arg, - unsigned nr_args) +static inline int ____sys_io_uring_register(int fd, unsigned opcode, + const void *arg, + unsigned nr_args) { long rax; register unsigned r10 __asm__("r10") = nr_args; @@ -147,8 +147,8 @@ static inline int __arch_impl_io_uring_register(int fd, unsigned opcode, return (int) rax; } -static inline int __arch_impl_io_uring_setup(unsigned entries, - struct io_uring_params *p) +static inline int ____sys_io_uring_setup(unsigned entries, + struct io_uring_params *p) { long rax; @@ -163,10 +163,9 @@ static inline int __arch_impl_io_uring_setup(unsigned entries, return (int) rax; } -static inline int __arch_impl_io_uring_enter(int fd, unsigned to_submit, - unsigned min_complete, - unsigned flags, sigset_t *sig, - int sz) +static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig, int sz) { long rax; register unsigned r10 __asm__("r10") = flags; @@ -188,12 +187,26 @@ static inline int __arch_impl_io_uring_enter(int fd, unsigned to_submit, return (int) rax; } +static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig) +{ + return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, + _NSIG / 8); +} + #else /* #if defined(__x86_64__) */ /* - * TODO: Add x86 (32-bit) support here. + * For x86 (32-bit), fallback to libc wrapper. + * We can't use CONFIG_NOLIBC for x86 (32-bit) at the moment. + * + * TODO: Add x86 (32-bit) nolibc support. */ -#error "x86 (32-bit) is currently not supported for nolibc builds" +#ifdef CONFIG_NOLIBC + #error "x86 (32-bit) is currently not supported for nolibc builds" +#endif +#include "../generic/syscall.h" #endif /* #if defined(__x86_64__) */ diff --git a/src/syscall.h b/src/syscall.h index 4b336f1..beb357e 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -55,27 +55,6 @@ */ struct io_uring_params; - -#ifdef CONFIG_NOLIBC -# if defined(__x86_64__) || defined(__i386__) -# include "arch/x86/syscall.h" -# else -# error "This arch doesn't support building liburing without libc" -# endif -#endif - - -/* - * System calls - */ -int __sys_io_uring_setup(unsigned entries, struct io_uring_params *p); -int __sys_io_uring_enter(int fd, unsigned to_submit, unsigned min_complete, - unsigned flags, sigset_t *sig); -int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, - unsigned flags, sigset_t *sig, int sz); -int __sys_io_uring_register(int fd, unsigned int opcode, const void *arg, - unsigned int nr_args); - static inline void *ERR_PTR(intptr_t n) { return (void *) n; @@ -91,118 +70,32 @@ static inline bool IS_ERR(const void *ptr) return uring_unlikely((uintptr_t) ptr >= (uintptr_t) -4095UL); } -static inline int ____sys_io_uring_register(int fd, unsigned opcode, - const void *arg, unsigned nr_args) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_io_uring_register(fd, opcode, arg, nr_args); -#else - int ret; - ret = syscall(__NR_io_uring_register, fd, opcode, arg, nr_args); - return (ret < 0) ? -errno : ret; -#endif -} - -static inline int ____sys_io_uring_setup(unsigned entries, - struct io_uring_params *p) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_io_uring_setup(entries, p); +#define __INTERNAL__LIBURING_SYSCALL_H +#if defined(__x86_64__) || defined(__i386__) + #include "arch/x86/syscall.h" #else - int ret; - ret = syscall(__NR_io_uring_setup, entries, p); - return (ret < 0) ? -errno : ret; + /* + * We don't have native syscall wrappers + * for this arch. Must use libc! + */ + #ifdef CONFIG_NOLIBC + #error "This arch doesn't support building liburing without libc" + #endif + /* libc syscall wrappers. */ + #include "arch/generic/syscall.h" #endif -} - -static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, - unsigned min_complete, unsigned flags, - sigset_t *sig, int sz) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_io_uring_enter(fd, to_submit, min_complete, flags, - sig, sz); -#else - int ret; - ret = syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, - sig, sz); - return (ret < 0) ? -errno : ret; -#endif -} - -static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, - unsigned min_complete, unsigned flags, - sigset_t *sig) -{ - return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, - _NSIG / 8); -} - -static inline void *uring_mmap(void *addr, size_t length, int prot, int flags, - int fd, off_t offset) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_mmap(addr, length, prot, flags, fd, offset); -#else - void *ret; - ret = mmap(addr, length, prot, flags, fd, offset); - return (ret == MAP_FAILED) ? ERR_PTR(-errno) : ret; -#endif -} +#undef __INTERNAL__LIBURING_SYSCALL_H -static inline int uring_munmap(void *addr, size_t length) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_munmap(addr, length); -#else - int ret; - ret = munmap(addr, length); - return (ret < 0) ? -errno : ret; -#endif -} - -static inline int uring_madvise(void *addr, size_t length, int advice) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_madvise(addr, length, advice); -#else - int ret; - ret = madvise(addr, length, advice); - return (ret < 0) ? -errno : ret; -#endif -} - -static inline int uring_getrlimit(int resource, struct rlimit *rlim) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_getrlimit(resource, rlim); -#else - int ret; - ret = getrlimit(resource, rlim); - return (ret < 0) ? -errno : ret; -#endif -} - -static inline int uring_setrlimit(int resource, const struct rlimit *rlim) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_setrlimit(resource, rlim); -#else - int ret; - ret = setrlimit(resource, rlim); - return (ret < 0) ? -errno : ret; -#endif -} - -static inline int uring_close(int fd) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_close(fd); -#else - int ret; - ret = close(fd); - return (ret < 0) ? -errno : ret; -#endif -} +/* + * For backward compatibility. + * (these __sys* functions always use libc, see syscall.c) + */ +int __sys_io_uring_setup(unsigned entries, struct io_uring_params *p); +int __sys_io_uring_enter(int fd, unsigned to_submit, unsigned min_complete, + unsigned flags, sigset_t *sig); +int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, + unsigned flags, sigset_t *sig, int sz); +int __sys_io_uring_register(int fd, unsigned int opcode, const void *arg, + unsigned int nr_args); #endif -- cgit v1.2.3 From c099b832a97dc1880b89734ef6a5420497a1be0f Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 11 Feb 2022 22:57:52 +0700 Subject: lib.h: Split off lib header for arch specific and generic 1) Clean up #ifdef/#endif for get_page_size(). 2) Always use arch specific code for x86-64 to reduce libc usage. 3) For other archs, we will use src/arch/generic/lib.h header that contains libc wrapper. At this point, on x86-64, we only use libc for memset(), malloc() and free(). Cc: Nugra Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220211155753.143698-4-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- src/arch/generic/lib.h | 21 +++++++++++++++++++++ src/arch/x86/lib.h | 20 +++++++++++++------- src/lib.h | 45 +++++++++++++++++++-------------------------- 3 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 src/arch/generic/lib.h diff --git a/src/arch/generic/lib.h b/src/arch/generic/lib.h new file mode 100644 index 0000000..737e795 --- /dev/null +++ b/src/arch/generic/lib.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef __INTERNAL__LIBURING_LIB_H + #error "This file should be included from src/lib.h (liburing)" +#endif + +#ifndef LIBURING_ARCH_GENERIC_LIB_H +#define LIBURING_ARCH_GENERIC_LIB_H + +static inline long get_page_size(void) +{ + long page_size; + + page_size = sysconf(_SC_PAGESIZE); + if (page_size < 0) + page_size = 4096; + + return page_size; +} + +#endif /* #ifndef LIBURING_ARCH_GENERIC_LIB_H */ diff --git a/src/arch/x86/lib.h b/src/arch/x86/lib.h index 65ad396..bacf74e 100644 --- a/src/arch/x86/lib.h +++ b/src/arch/x86/lib.h @@ -1,15 +1,15 @@ /* SPDX-License-Identifier: MIT */ +#ifndef __INTERNAL__LIBURING_LIB_H + #error "This file should be included from src/lib.h (liburing)" +#endif + #ifndef LIBURING_ARCH_X86_LIB_H #define LIBURING_ARCH_X86_LIB_H -#ifndef LIBURING_LIB_H -# error "This file should be included from src/lib.h (liburing)" -#endif - #if defined(__x86_64__) -static inline long __arch_impl_get_page_size(void) +static inline long get_page_size(void) { return 4096; } @@ -17,9 +17,15 @@ static inline long __arch_impl_get_page_size(void) #else /* #if defined(__x86_64__) */ /* - * TODO: Add x86 (32-bit) support here. + * For x86 (32-bit), fallback to libc wrapper. + * We can't use CONFIG_NOLIBC for x86 (32-bit) at the moment. + * + * TODO: Add x86 (32-bit) nolibc support. */ -#error "x86 (32-bit) is currently not supported for nolibc builds" +#ifdef CONFIG_NOLIBC + #error "x86 (32-bit) is currently not supported for nolibc builds" +#endif +#include "../generic/lib.h" #endif /* #if defined(__x86_64__) */ diff --git a/src/lib.h b/src/lib.h index bd02805..6672cc5 100644 --- a/src/lib.h +++ b/src/lib.h @@ -6,23 +6,31 @@ #include #include -#ifdef CONFIG_NOLIBC -# if defined(__x86_64__) || defined(__i386__) -# include "arch/x86/lib.h" -# else -# error "This arch doesn't support building liburing without libc" -# endif +#define __INTERNAL__LIBURING_LIB_H +#if defined(__x86_64__) || defined(__i386__) + #include "arch/x86/lib.h" +#else + /* + * We don't have nolibc support for this arch. Must use libc! + */ + #ifdef CONFIG_NOLIBC + #error "This arch doesn't support building liburing without libc" + #endif + /* libc wrappers. */ + #include "arch/generic/lib.h" #endif +#undef __INTERNAL__LIBURING_LIB_H + #ifndef offsetof -# define offsetof(TYPE, FIELD) ((size_t) &((TYPE *)0)->FIELD) + #define offsetof(TYPE, FIELD) ((size_t) &((TYPE *)0)->FIELD) #endif #ifndef container_of -# define container_of(PTR, TYPE, FIELD) ({ \ - __typeof__(((TYPE *)0)->FIELD) *__FIELD_PTR = (PTR); \ - (TYPE *)((char *) __FIELD_PTR - offsetof(TYPE, FIELD)); \ -}) + #define container_of(PTR, TYPE, FIELD) ({ \ + __typeof__(((TYPE *)0)->FIELD) *__FIELD_PTR = (PTR); \ + (TYPE *)((char *) __FIELD_PTR - offsetof(TYPE, FIELD)); \ + }) #endif void *__uring_malloc(size_t len); @@ -46,19 +54,4 @@ static inline void uring_free(void *ptr) #endif } -static inline long get_page_size(void) -{ -#ifdef CONFIG_NOLIBC - return __arch_impl_get_page_size(); -#else - long page_size; - - page_size = sysconf(_SC_PAGESIZE); - if (page_size < 0) - page_size = 4096; - - return page_size; -#endif -} - #endif /* #ifndef LIBURING_LIB_H */ -- cgit v1.2.3 From e1f89765f957accc4c9a0e3ca233532c6564548b Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 11 Feb 2022 22:57:53 +0700 Subject: Change all syscall function name prefix to __sys Instead of using uring_mmap, uring_close, uring_madvise, etc. Let's use __sys_mmap, __sys_close, __sys_madvise, etc. That looks better convention for syscall function name like what we do with __sys_io_uring* functions. Cc: Nugra Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220211155753.143698-5-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- src/arch/generic/syscall.h | 12 ++++++------ src/arch/x86/syscall.h | 12 ++++++------ src/nolibc.c | 4 ++-- src/register.c | 4 ++-- src/setup.c | 22 +++++++++++----------- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/arch/generic/syscall.h b/src/arch/generic/syscall.h index 6b10fe3..fa93064 100644 --- a/src/arch/generic/syscall.h +++ b/src/arch/generic/syscall.h @@ -41,7 +41,7 @@ static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, _NSIG / 8); } -static inline void *uring_mmap(void *addr, size_t length, int prot, int flags, +static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { void *ret; @@ -49,35 +49,35 @@ static inline void *uring_mmap(void *addr, size_t length, int prot, int flags, return (ret == MAP_FAILED) ? ERR_PTR(-errno) : ret; } -static inline int uring_munmap(void *addr, size_t length) +static inline int __sys_munmap(void *addr, size_t length) { int ret; ret = munmap(addr, length); return (ret < 0) ? -errno : ret; } -static inline int uring_madvise(void *addr, size_t length, int advice) +static inline int __sys_madvise(void *addr, size_t length, int advice) { int ret; ret = madvise(addr, length, advice); return (ret < 0) ? -errno : ret; } -static inline int uring_getrlimit(int resource, struct rlimit *rlim) +static inline int __sys_getrlimit(int resource, struct rlimit *rlim) { int ret; ret = getrlimit(resource, rlim); return (ret < 0) ? -errno : ret; } -static inline int uring_setrlimit(int resource, const struct rlimit *rlim) +static inline int __sys_setrlimit(int resource, const struct rlimit *rlim) { int ret; ret = setrlimit(resource, rlim); return (ret < 0) ? -errno : ret; } -static inline int uring_close(int fd) +static inline int __sys_close(int fd) { int ret; ret = close(fd); diff --git a/src/arch/x86/syscall.h b/src/arch/x86/syscall.h index 2d5642c..02677f2 100644 --- a/src/arch/x86/syscall.h +++ b/src/arch/x86/syscall.h @@ -29,7 +29,7 @@ * %r11 == %rflags and %rcx == %rip. */ -static inline void *uring_mmap(void *addr, size_t length, int prot, int flags, +static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { void *rax; @@ -52,7 +52,7 @@ static inline void *uring_mmap(void *addr, size_t length, int prot, int flags, return rax; } -static inline int uring_munmap(void *addr, size_t length) +static inline int __sys_munmap(void *addr, size_t length) { long rax; @@ -67,7 +67,7 @@ static inline int uring_munmap(void *addr, size_t length) return (int) rax; } -static inline int uring_madvise(void *addr, size_t length, int advice) +static inline int __sys_madvise(void *addr, size_t length, int advice) { long rax; @@ -83,7 +83,7 @@ static inline int uring_madvise(void *addr, size_t length, int advice) return (int) rax; } -static inline int uring_getrlimit(int resource, struct rlimit *rlim) +static inline int __sys_getrlimit(int resource, struct rlimit *rlim) { long rax; @@ -98,7 +98,7 @@ static inline int uring_getrlimit(int resource, struct rlimit *rlim) return (int) rax; } -static inline int uring_setrlimit(int resource, const struct rlimit *rlim) +static inline int __sys_setrlimit(int resource, const struct rlimit *rlim) { long rax; @@ -113,7 +113,7 @@ static inline int uring_setrlimit(int resource, const struct rlimit *rlim) return (int) rax; } -static inline int uring_close(int fd) +static inline int __sys_close(int fd) { long rax; diff --git a/src/nolibc.c b/src/nolibc.c index f7848d3..1e17d22 100644 --- a/src/nolibc.c +++ b/src/nolibc.c @@ -27,7 +27,7 @@ void *__uring_malloc(size_t len) { struct uring_heap *heap; - heap = uring_mmap(NULL, sizeof(*heap) + len, PROT_READ | PROT_WRITE, + heap = __sys_mmap(NULL, sizeof(*heap) + len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (IS_ERR(heap)) return NULL; @@ -44,5 +44,5 @@ void __uring_free(void *p) return; heap = container_of(p, struct uring_heap, user_p); - uring_munmap(heap, heap->len); + __sys_munmap(heap, heap->len); } diff --git a/src/register.c b/src/register.c index a1b1a22..cd73fce 100644 --- a/src/register.c +++ b/src/register.c @@ -100,13 +100,13 @@ static int increase_rlimit_nofile(unsigned nr) int ret; struct rlimit rlim; - ret = uring_getrlimit(RLIMIT_NOFILE, &rlim); + ret = __sys_getrlimit(RLIMIT_NOFILE, &rlim); if (ret < 0) return ret; if (rlim.rlim_cur < nr) { rlim.rlim_cur += nr; - uring_setrlimit(RLIMIT_NOFILE, &rlim); + __sys_setrlimit(RLIMIT_NOFILE, &rlim); } return 0; diff --git a/src/setup.c b/src/setup.c index 1e4dbf4..544adaf 100644 --- a/src/setup.c +++ b/src/setup.c @@ -10,9 +10,9 @@ static void io_uring_unmap_rings(struct io_uring_sq *sq, struct io_uring_cq *cq) { - uring_munmap(sq->ring_ptr, sq->ring_sz); + __sys_munmap(sq->ring_ptr, sq->ring_sz); if (cq->ring_ptr && cq->ring_ptr != sq->ring_ptr) - uring_munmap(cq->ring_ptr, cq->ring_sz); + __sys_munmap(cq->ring_ptr, cq->ring_sz); } static int io_uring_mmap(int fd, struct io_uring_params *p, @@ -29,7 +29,7 @@ static int io_uring_mmap(int fd, struct io_uring_params *p, sq->ring_sz = cq->ring_sz; cq->ring_sz = sq->ring_sz; } - sq->ring_ptr = uring_mmap(0, sq->ring_sz, PROT_READ | PROT_WRITE, + sq->ring_ptr = __sys_mmap(0, sq->ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQ_RING); if (IS_ERR(sq->ring_ptr)) @@ -38,7 +38,7 @@ static int io_uring_mmap(int fd, struct io_uring_params *p, if (p->features & IORING_FEAT_SINGLE_MMAP) { cq->ring_ptr = sq->ring_ptr; } else { - cq->ring_ptr = uring_mmap(0, cq->ring_sz, PROT_READ | PROT_WRITE, + cq->ring_ptr = __sys_mmap(0, cq->ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_CQ_RING); if (IS_ERR(cq->ring_ptr)) { @@ -57,7 +57,7 @@ static int io_uring_mmap(int fd, struct io_uring_params *p, sq->array = sq->ring_ptr + p->sq_off.array; size = p->sq_entries * sizeof(struct io_uring_sqe); - sq->sqes = uring_mmap(0, size, PROT_READ | PROT_WRITE, + sq->sqes = __sys_mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQES); if (IS_ERR(sq->sqes)) { ret = PTR_ERR(sq->sqes); @@ -109,18 +109,18 @@ int io_uring_ring_dontfork(struct io_uring *ring) return -EINVAL; len = *ring->sq.kring_entries * sizeof(struct io_uring_sqe); - ret = uring_madvise(ring->sq.sqes, len, MADV_DONTFORK); + ret = __sys_madvise(ring->sq.sqes, len, MADV_DONTFORK); if (ret < 0) return ret; len = ring->sq.ring_sz; - ret = uring_madvise(ring->sq.ring_ptr, len, MADV_DONTFORK); + ret = __sys_madvise(ring->sq.ring_ptr, len, MADV_DONTFORK); if (ret < 0) return ret; if (ring->cq.ring_ptr != ring->sq.ring_ptr) { len = ring->cq.ring_sz; - ret = uring_madvise(ring->cq.ring_ptr, len, MADV_DONTFORK); + ret = __sys_madvise(ring->cq.ring_ptr, len, MADV_DONTFORK); if (ret < 0) return ret; } @@ -139,7 +139,7 @@ int io_uring_queue_init_params(unsigned entries, struct io_uring *ring, ret = io_uring_queue_mmap(fd, p, ring); if (ret) { - uring_close(fd); + __sys_close(fd); return ret; } @@ -166,9 +166,9 @@ void io_uring_queue_exit(struct io_uring *ring) struct io_uring_sq *sq = &ring->sq; struct io_uring_cq *cq = &ring->cq; - uring_munmap(sq->sqes, *sq->kring_entries * sizeof(struct io_uring_sqe)); + __sys_munmap(sq->sqes, *sq->kring_entries * sizeof(struct io_uring_sqe)); io_uring_unmap_rings(sq, cq); - uring_close(ring->ring_fd); + __sys_close(ring->ring_fd); } struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring) -- cgit v1.2.3 From e18f1ce24bf1800721dec9070cda6f172dcea25c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 11 Feb 2022 09:53:35 -0700 Subject: test/pollfree: ignore run if argument is given This test case doesn't use a passed in argument, so just skip the run if one is given. Signed-off-by: Jens Axboe --- test/pollfree.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/pollfree.c b/test/pollfree.c index f73b6ad..cdc7af0 100644 --- a/test/pollfree.c +++ b/test/pollfree.c @@ -388,8 +388,12 @@ void execute_call(int call) break; } } -int main(void) + +int main(int argc, char *argv[]) { + if (argc > 1) + return 0; + syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); -- cgit v1.2.3 From 333561791386112e4801b61be15feaf4044c02c6 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 11 Feb 2022 00:29:24 +0900 Subject: Fix __io_uring_get_cqe() for IORING_SETUP_IOPOLL If __io_uring_get_cqe() is called for the ring setup with IOPOLL, we must enter the kernel to get completion events. Even if that is called with wait_nr is zero. Signed-off-by: Akinobu Mita Link: https://lore.kernel.org/r/20220210152924.14413-1-akinobu.mita@gmail.com Signed-off-by: Jens Axboe --- src/queue.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/queue.c b/src/queue.c index eb0c736..f8384d1 100644 --- a/src/queue.c +++ b/src/queue.c @@ -31,6 +31,11 @@ static inline bool cq_ring_needs_flush(struct io_uring *ring) return IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_CQ_OVERFLOW; } +static inline bool cq_ring_needs_enter(struct io_uring *ring) +{ + return (ring->flags & IORING_SETUP_IOPOLL) || cq_ring_needs_flush(ring); +} + static int __io_uring_peek_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned *nr_available) @@ -84,7 +89,6 @@ static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_pt do { bool need_enter = false; - bool cq_overflow_flush = false; unsigned flags = 0; unsigned nr_available; int ret; @@ -93,13 +97,13 @@ static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_pt if (err) break; if (!cqe && !data->wait_nr && !data->submit) { - if (!cq_ring_needs_flush(ring)) { + if (!cq_ring_needs_enter(ring)) { err = -EAGAIN; break; } - cq_overflow_flush = true; + need_enter = true; } - if (data->wait_nr > nr_available || cq_overflow_flush) { + if (data->wait_nr > nr_available || need_enter) { flags = IORING_ENTER_GETEVENTS | data->get_flags; need_enter = true; } -- cgit v1.2.3 From c193e22a4c9f0844390ac88e67288de3f8df5d20 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Feb 2022 15:59:02 -0700 Subject: man/io_uring_prep_write.3: correct passed in buffer argument It's a write, the buffer argument is const. Signed-off-by: Jens Axboe --- man/io_uring_prep_write.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index f63dcdc..25c5301 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -12,7 +12,7 @@ io_uring_prep_write - prepare I/O write request .PP .BI "void io_uring_prep_write(struct io_uring_sqe *sqe," .BI " int fd," -.BI " void *buf," +.BI " const void *buf," .BI " unsigned nbytes," .BI " __u64 offset)" .PP -- cgit v1.2.3 From 0525c2237098716e4aacb6966f57cdcc37c6f45d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Feb 2022 16:00:06 -0700 Subject: Add man pages for the prep_{read,write}_fixed helpers Fixes: https://github.com/axboe/liburing/issues/522 Signed-off-by: Jens Axboe --- man/io_uring_prep_read_fixed.3 | 54 +++++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_write_fixed.3 | 54 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 man/io_uring_prep_read_fixed.3 create mode 100644 man/io_uring_prep_write_fixed.3 diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 new file mode 100644 index 0000000..c15c697 --- /dev/null +++ b/man/io_uring_prep_read_fixed.3 @@ -0,0 +1,54 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_read 3 "February 13, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_prep_read_fixed - prepare I/O read request with registered buffer + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_read_fixed(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " void *buf," +.BI " unsigned nbytes," +.BI " __u64 offset," +.BI " int buf_index)" + +.SH DESCRIPTION +.PP +The io_uring_prep_read_fixed() prepares an IO read request with a previously +registered IO buffer. The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start reading +.I nbytes +into the buffer +.I buf +at the specified +.I offset, +and with the buffer matching the registered index of +.I buf_index. + +This work just like +.B io_uring_prep_read(3) +except it requires the user of buffers that have been registered with +.B io_uring_register_buffers(3). The +.I buf +and +.I nbytes +arguments must fall within a region specificed by +.I buf_index. +in the previously registered buffer. The buffer need not be aligned with +the start of the registered buffer. + +After the read has been prepared it can be submitted with one of the submit +functions. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_prep_read (3), io_uring_register_buffers (3) diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 new file mode 100644 index 0000000..8667acf --- /dev/null +++ b/man/io_uring_prep_write_fixed.3 @@ -0,0 +1,54 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_write 3 "February 13, 2022" "liburing-2.1" "liburing Manual" +.SH NAME +io_uring_prep_write_fixed - prepare I/O write request with registered buffer + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_write_fixed(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " const void *buf," +.BI " unsigned nbytes," +.BI " __u64 offset," +.BI " int buf_index)" + +.SH DESCRIPTION +.PP +The io_uring_prep_write_fixed() prepares an IO write request with a previously +registered IO buffer. The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start reading +.I nbytes +into the buffer +.I buf +at the specified +.I offset, +and with the buffer matching the registered index of +.I buf_index. + +This work just like +.B io_uring_prep_write(3) +except it requires the user of buffers that have been registered with +.B io_uring_register_buffers(3). The +.I buf +and +.I nbytes +arguments must fall within a region specificed by +.I buf_index. +in the previously registered buffer. The buffer need not be aligned with +the start of the registered buffer. + +After the read has been prepared it can be submitted with one of the submit +functions. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_prep_write (3), io_uring_register_buffers (3) -- cgit v1.2.3 From bd207310a1e93f08e522d0aa89ece33b33a71dee Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Feb 2022 16:01:33 -0700 Subject: man/io_uring_prep_write_fixed.3: fix typo It's "writing from" not "reading into". Too much copy paste from the read fixed man page. Signed-off-by: Jens Axboe --- man/io_uring_prep_write_fixed.3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index 8667acf..8a33387 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -24,9 +24,9 @@ registered IO buffer. The submission queue entry .I sqe is setup to use the file descriptor .I fd -to start reading +to start writing .I nbytes -into the buffer +from the buffer .I buf at the specified .I offset, -- cgit v1.2.3 From 4095eaf5ff3dd08f2c8dd68b3368a6c50ff49d2d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Feb 2022 16:09:32 -0700 Subject: man/io_uring_register_buffers.3: mention why registered buffers are useful There are no details in this man page, so mention why it is in fact beneficial to register buffers. This is specific to O_DIRECT file IO for now, but the kernel side use cases will be expanded in the future. Signed-off-by: Jens Axboe --- man/io_uring_register_buffers.3 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index 48cc506..58cdec7 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -26,9 +26,16 @@ belonging to the After the caller has registered the buffers, they can be used with one of the fixed buffers functions. +Registered buffers is an optimization that is useful in conjunction with +.B O_DIRECT +reads and writes, where maps the specified range into the kernel once when +the buffer is registered, rather than doing a map and unmap for each IO +every time IO is performed to that region. Additionally, it also avoids +manipulating the page reference counts for each IO. + .SH RETURN VALUE On success .BR io_uring_register_buffers (3) returns 0. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_unregister_buffers (3) \ No newline at end of file +.BR io_uring_get_sqe (3), io_uring_unregister_buffers (3), io_uring_prep_read_fixed (3), io_uring_prep_write_fixed (3) -- cgit v1.2.3 From 99258660a4cdba9afce897d22ed7a6e3e2fac20c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Feb 2022 16:23:57 -0700 Subject: man/io_uring_prep_{read,write}v2.3: formatting and style fixes Signed-off-by: Jens Axboe --- man/io_uring_prep_readv2.3 | 13 ++++++++----- man/io_uring_prep_writev2.3 | 12 ++++++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index aaad25c..b05f36e 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -35,7 +35,9 @@ The behavior of the function can be controlled with the .I flags parameter. -Supported values for flags are: +Supported values for +.I flags +are: .TP .B RWF_HIPRI High priority request, poll if possible @@ -51,11 +53,12 @@ per-IO, return -EAGAIN if operation would block .TP .B RWF_APPEND per-IO O_APPEND -.TP -On files that support seeking, if the offset is set to -1, the read operation -commences at the file offset, and the file offset is incremented by the number -of bytes read. See +.P +On files that support seeking, if the offset is set to +.B -1, +the read operation commences at the file offset, and the file offset is +incremented by the number of bytes read. See .BR read (2) for more details. diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index 4f2ae47..4a994d0 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -34,7 +34,9 @@ The behavior of the function can be controlled with the .I flags parameter. -Supported values for flags are: +Supported values for +.I flags +are: .TP .B RWF_HIPRI High priority request, poll if possible @@ -51,9 +53,11 @@ per-IO, return -EAGAIN if operation would block .B RWF_APPEND per-IO O_APPEND -On files that support seeking, if the offset is set to -1, the write operation -commences at the file offset, and the file offset is incremented by the number -of bytes written. See +.P +On files that support seeking, if the offset is set to +.B -1, +the write operation commences at the file offset, and the file offset is +incremented by the number of bytes written. See .BR write (2) for more details. -- cgit v1.2.3 From cce3026ee45a86cfdd104fd1be270b759a161233 Mon Sep 17 00:00:00 2001 From: Nugra Date: Tue, 15 Feb 2022 22:36:50 +0700 Subject: configure: Support busybox mktemp Busybox mktemp does not support `--tmpdir`, it says: mktemp: unrecognized option: tmpdir It can be fixed with: 1. Create a temporary directory. 2. Use touch to create the temporary files inside the directory. 3. Clean up by deleting the temporary directory. [ammarfaizi2: s/fio/liburing/] Signed-off-by: Nugra Link: https://t.me/GNUWeeb/530154 [ammarfaizi2: Rephrase the commit message and add touch command] Co-authored-by: Ammar Faizi Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220215153651.181319-2-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- configure | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 805a671..1f7f1c3 100755 --- a/configure +++ b/configure @@ -78,14 +78,17 @@ EOF exit 0 fi -TMPC="$(mktemp --tmpdir fio-conf-XXXXXXXXXX.c)" -TMPC2="$(mktemp --tmpdir fio-conf-XXXXXXXXXX-2.c)" -TMPO="$(mktemp --tmpdir fio-conf-XXXXXXXXXX.o)" -TMPE="$(mktemp --tmpdir fio-conf-XXXXXXXXXX.exe)" +TMP_DIRECTORY="$(mktemp -d)" +TMPC="$TMP_DIRECTORY/liburing-conf.c" +TMPC2="$TMP_DIRECTORY/liburing-conf-2.c" +TMPO="$TMP_DIRECTORY/liburing-conf.o" +TMPE="$TMP_DIRECTORY/liburing-conf.exe" + +touch $TMPC $TMPC2 $TMPO $TMPE # NB: do not call "exit" in the trap handler; this is buggy with some shells; # see <1285349658-3122-1-git-send-email-loic.minier@linaro.org> -trap "rm -f $TMPC $TMPC2 $TMPO $TMPE" EXIT INT QUIT TERM +trap "rm -rf $TMP_DIRECTORY" EXIT INT QUIT TERM rm -rf config.log -- cgit v1.2.3 From 20bb37e0f828909742f845b8113b2bb7e1065cd1 Mon Sep 17 00:00:00 2001 From: Alviro Iskandar Setiawan Date: Tue, 15 Feb 2022 22:36:51 +0700 Subject: arch/x86: Create syscall __do_syscall{0..6} macros Reduce arch dependent code by creating __do_syscall{0..6} macros. These macros are made of inline Assembly x86-64. Use them to invoke syscall via __sys* functions. By using this design, we don't have to code in inline Assembly again when adding a new syscall. Tested on Linux x86-64, all test passed, but rsrc_tags timedout. Tested-by: Arthur Lapz Tested-by: Nugra Signed-off-by: Alviro Iskandar Setiawan Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220215153651.181319-3-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- src/arch/x86/syscall.h | 242 +++++++++++++++++++++++++------------------------ 1 file changed, 124 insertions(+), 118 deletions(-) diff --git a/src/arch/x86/syscall.h b/src/arch/x86/syscall.h index 02677f2..c4ae24e 100644 --- a/src/arch/x86/syscall.h +++ b/src/arch/x86/syscall.h @@ -29,162 +29,168 @@ * %r11 == %rflags and %rcx == %rip. */ +#define __do_syscall0(NUM) ({ \ + intptr_t rax; \ + \ + __asm__ volatile( \ + "syscall" \ + : "=a"(rax) /* %rax */ \ + : "a"(NUM) /* %rax */ \ + : "rcx", "r11", "memory" \ + ); \ + rax; \ +}) + +#define __do_syscall1(NUM, ARG1) ({ \ + intptr_t rax; \ + \ + __asm__ volatile( \ + "syscall" \ + : "=a"(rax) /* %rax */ \ + : "a"((NUM)), /* %rax */ \ + "D"((ARG1)) /* %rdi */ \ + : "rcx", "r11", "memory" \ + ); \ + rax; \ +}) + +#define __do_syscall2(NUM, ARG1, ARG2) ({ \ + intptr_t rax; \ + \ + __asm__ volatile( \ + "syscall" \ + : "=a"(rax) /* %rax */ \ + : "a"((NUM)), /* %rax */ \ + "D"((ARG1)), /* %rdi */ \ + "S"((ARG2)) /* %rsi */ \ + : "rcx", "r11", "memory" \ + ); \ + rax; \ +}) + +#define __do_syscall3(NUM, ARG1, ARG2, ARG3) ({ \ + intptr_t rax; \ + \ + __asm__ volatile( \ + "syscall" \ + : "=a"(rax) /* %rax */ \ + : "a"((NUM)), /* %rax */ \ + "D"((ARG1)), /* %rdi */ \ + "S"((ARG2)), /* %rsi */ \ + "d"((ARG3)) /* %rdx */ \ + : "rcx", "r11", "memory" \ + ); \ + rax; \ +}) + +#define __do_syscall4(NUM, ARG1, ARG2, ARG3, ARG4) ({ \ + intptr_t rax; \ + register __typeof__(ARG4) __r10 __asm__("r10") = (ARG4); \ + \ + __asm__ volatile( \ + "syscall" \ + : "=a"(rax) /* %rax */ \ + : "a"((NUM)), /* %rax */ \ + "D"((ARG1)), /* %rdi */ \ + "S"((ARG2)), /* %rsi */ \ + "d"((ARG3)), /* %rdx */ \ + "r"(__r10) /* %r10 */ \ + : "rcx", "r11", "memory" \ + ); \ + rax; \ +}) + +#define __do_syscall5(NUM, ARG1, ARG2, ARG3, ARG4, ARG5) ({ \ + intptr_t rax; \ + register __typeof__(ARG4) __r10 __asm__("r10") = (ARG4); \ + register __typeof__(ARG5) __r8 __asm__("r8") = (ARG5); \ + \ + __asm__ volatile( \ + "syscall" \ + : "=a"(rax) /* %rax */ \ + : "a"((NUM)), /* %rax */ \ + "D"((ARG1)), /* %rdi */ \ + "S"((ARG2)), /* %rsi */ \ + "d"((ARG3)), /* %rdx */ \ + "r"(__r10), /* %r10 */ \ + "r"(__r8) /* %r8 */ \ + : "rcx", "r11", "memory" \ + ); \ + rax; \ +}) + +#define __do_syscall6(NUM, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) ({ \ + intptr_t rax; \ + register __typeof__(ARG4) __r10 __asm__("r10") = (ARG4); \ + register __typeof__(ARG5) __r8 __asm__("r8") = (ARG5); \ + register __typeof__(ARG6) __r9 __asm__("r9") = (ARG6); \ + \ + __asm__ volatile( \ + "syscall" \ + : "=a"(rax) /* %rax */ \ + : "a"((NUM)), /* %rax */ \ + "D"((ARG1)), /* %rdi */ \ + "S"((ARG2)), /* %rsi */ \ + "d"((ARG3)), /* %rdx */ \ + "r"(__r10), /* %r10 */ \ + "r"(__r8), /* %r8 */ \ + "r"(__r9) /* %r9 */ \ + : "rcx", "r11", "memory" \ + ); \ + rax; \ +}) + static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { - void *rax; - register int r10 __asm__("r10") = flags; - register int r8 __asm__("r8") = fd; - register off_t r9 __asm__("r9") = offset; - - __asm__ volatile( - "syscall" - : "=a"(rax) /* %rax */ - : "a"(__NR_mmap), /* %rax */ - "D"(addr), /* %rdi */ - "S"(length), /* %rsi */ - "d"(prot), /* %rdx */ - "r"(r10), /* %r10 */ - "r"(r8), /* %r8 */ - "r"(r9) /* %r9 */ - : "memory", "rcx", "r11" - ); - return rax; + return (void *) __do_syscall6(__NR_mmap, addr, length, prot, flags, fd, + offset); } static inline int __sys_munmap(void *addr, size_t length) { - long rax; - - __asm__ volatile( - "syscall" - : "=a"(rax) /* %rax */ - : "a"(__NR_munmap), /* %rax */ - "D"(addr), /* %rdi */ - "S"(length) /* %rsi */ - : "memory", "rcx", "r11" - ); - return (int) rax; + return (int) __do_syscall2(__NR_munmap, addr, length); } static inline int __sys_madvise(void *addr, size_t length, int advice) { - long rax; - - __asm__ volatile( - "syscall" - : "=a"(rax) /* %rax */ - : "a"(__NR_madvise), /* %rax */ - "D"(addr), /* %rdi */ - "S"(length), /* %rsi */ - "d"(advice) /* %rdx */ - : "memory", "rcx", "r11" - ); - return (int) rax; + return (int) __do_syscall2(__NR_madvise, addr, length); } static inline int __sys_getrlimit(int resource, struct rlimit *rlim) { - long rax; - - __asm__ volatile( - "syscall" - : "=a"(rax) /* %rax */ - : "a"(__NR_getrlimit), /* %rax */ - "D"(resource), /* %rdi */ - "S"(rlim) /* %rsi */ - : "memory", "rcx", "r11" - ); - return (int) rax; + return (int) __do_syscall2(__NR_getrlimit, resource, rlim); } static inline int __sys_setrlimit(int resource, const struct rlimit *rlim) { - long rax; - - __asm__ volatile( - "syscall" - : "=a"(rax) /* %rax */ - : "a"(__NR_setrlimit), /* %rax */ - "D"(resource), /* %rdi */ - "S"(rlim) /* %rsi */ - : "memory", "rcx", "r11" - ); - return (int) rax; + return (int) __do_syscall2(__NR_setrlimit, resource, rlim); } static inline int __sys_close(int fd) { - long rax; - - __asm__ volatile( - "syscall" - : "=a"(rax) /* %rax */ - : "a"(__NR_close), /* %rax */ - "D"(fd) /* %rdi */ - : "memory", "rcx", "r11" - ); - return (int) rax; + return (int) __do_syscall1(__NR_close, fd); } static inline int ____sys_io_uring_register(int fd, unsigned opcode, - const void *arg, - unsigned nr_args) + const void *arg, unsigned nr_args) { - long rax; - register unsigned r10 __asm__("r10") = nr_args; - - __asm__ volatile( - "syscall" - : "=a"(rax) /* %rax */ - : "a"(__NR_io_uring_register), /* %rax */ - "D"(fd), /* %rdi */ - "S"(opcode), /* %rsi */ - "d"(arg), /* %rdx */ - "r"(r10) /* %r10 */ - : "memory", "rcx", "r11" - ); - return (int) rax; + return (int) __do_syscall4(__NR_io_uring_register, fd, opcode, arg, + nr_args); } static inline int ____sys_io_uring_setup(unsigned entries, struct io_uring_params *p) { - long rax; - - __asm__ volatile( - "syscall" - : "=a"(rax) /* %rax */ - : "a"(__NR_io_uring_setup), /* %rax */ - "D"(entries), /* %rdi */ - "S"(p) /* %rsi */ - : "memory", "rcx", "r11" - ); - return (int) rax; + return (int) __do_syscall2(__NR_io_uring_setup, entries, p); } static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, unsigned flags, sigset_t *sig, int sz) { - long rax; - register unsigned r10 __asm__("r10") = flags; - register sigset_t *r8 __asm__("r8") = sig; - register int r9 __asm__("r9") = sz; - - __asm__ volatile( - "syscall" - : "=a"(rax) /* %rax */ - : "a"(__NR_io_uring_enter), /* %rax */ - "D"(fd), /* %rdi */ - "S"(to_submit), /* %rsi */ - "d"(min_complete), /* %rdx */ - "r"(r10), /* %r10 */ - "r"(r8), /* %r8 */ - "r"(r9) /* %r9 */ - : "memory", "rcx", "r11" - ); - return (int) rax; + return (int) __do_syscall6(__NR_io_uring_enter, fd, to_submit, + min_complete, flags, sig, sz); } static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, -- cgit v1.2.3 From 37856ad78b605a388b7ae598a55544c7c6d3abe5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 18 Feb 2022 06:09:59 -0700 Subject: man/io_uring_get_probe.3: make a note of returning NULL if not supported 5.5 and earlier don't have the register probe opcode, and hence the library function will return NULL in that case. Signed-off-by: Jens Axboe --- man/io_uring_get_probe.3 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/man/io_uring_get_probe.3 b/man/io_uring_get_probe.3 index 1bb8b14..17b34c1 100644 --- a/man/io_uring_get_probe.3 +++ b/man/io_uring_get_probe.3 @@ -18,8 +18,12 @@ The function io_uring_get_probe() returns an allocated io_uring_probe structure to the caller. The caller is responsible for freeing the structure with the function io_uring_free_probe(). +.SH NOTES +Earlier versions of the Linux kernel does not support probe. If the kernel +doesn't support probe, this function will return NULL. + .SH RETURN VALUE On success it returns an allocated io_uring_probe structure, otherwise it returns NULL. .SH SEE ALSO -.BR io_uring_free_probe (3) \ No newline at end of file +.BR io_uring_free_probe (3) -- cgit v1.2.3 From 37a53a1d211ab8c33b7ed8b8f075061d73955220 Mon Sep 17 00:00:00 2001 From: Mahdi Rakhshandehroo <24380301+mrakh@users.noreply.github.com> Date: Sat, 19 Feb 2022 22:34:12 -0800 Subject: Fix warnings/errors when compiling on Alpine Linux Silences the following: * Error due to no definition for `mode_t` in `liburing.h` * Warning due to use of non-portable `#include ` and `#include ` * Warning due to incorrect `printf` format specifier in `test/io_uring_register.c` * Error due to missing declaration for `strcpy` in `test/sendmsg_fs_cve.c` * Error due to missing declaration for `strerror` in `test/shutdown.c` Signed-off-by: Mahdi Rakhshandehroo --- examples/ucontext-cp.c | 2 +- src/include/liburing.h | 1 + test/eventfd-disable.c | 2 +- test/eventfd-reg.c | 2 +- test/eventfd-ring.c | 2 +- test/eventfd.c | 2 +- test/io-cancel.c | 2 +- test/io_uring_register.c | 3 ++- test/iopoll.c | 2 +- test/link-timeout.c | 2 +- test/multicqes_drain.c | 2 +- test/poll-cancel-ton.c | 4 ++-- test/poll-cancel.c | 4 ++-- test/poll-many.c | 2 +- test/poll-mshot-update.c | 2 +- test/poll-ring.c | 2 +- test/poll-v-poll.c | 2 +- test/poll.c | 2 +- test/read-write.c | 2 +- test/register-restrictions.c | 2 +- test/ring-leak2.c | 2 +- test/sendmsg_fs_cve.c | 1 + test/short-read.c | 2 +- test/shutdown.c | 1 + test/sigfd-deadlock.c | 2 +- test/sq-poll-dup.c | 2 +- test/sq-poll-kthread.c | 2 +- test/sq-poll-share.c | 2 +- test/sqpoll-exit-hang.c | 2 +- test/thread-exit.c | 2 +- 30 files changed, 33 insertions(+), 29 deletions(-) diff --git a/examples/ucontext-cp.c b/examples/ucontext-cp.c index ea0c934..281013f 100644 --- a/examples/ucontext-cp.c +++ b/examples/ucontext-cp.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include "liburing.h" #define QD 64 diff --git a/src/include/liburing.h b/src/include/liburing.h index 3050fcc..c6f3cb8 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -7,6 +7,7 @@ #endif #include +#include #include #include #include diff --git a/test/eventfd-disable.c b/test/eventfd-disable.c index f172fd7..6567be0 100644 --- a/test/eventfd-disable.c +++ b/test/eventfd-disable.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include "liburing.h" diff --git a/test/eventfd-reg.c b/test/eventfd-reg.c index c708a51..b447455 100644 --- a/test/eventfd-reg.c +++ b/test/eventfd-reg.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include "liburing.h" diff --git a/test/eventfd-ring.c b/test/eventfd-ring.c index 67e102c..d217312 100644 --- a/test/eventfd-ring.c +++ b/test/eventfd-ring.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include "liburing.h" diff --git a/test/eventfd.c b/test/eventfd.c index 1a7e3f3..5c49ece 100644 --- a/test/eventfd.c +++ b/test/eventfd.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include "liburing.h" diff --git a/test/io-cancel.c b/test/io-cancel.c index c1df0df..89bb31a 100644 --- a/test/io-cancel.c +++ b/test/io-cancel.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "helpers.h" #include "liburing.h" diff --git a/test/io_uring_register.c b/test/io_uring_register.c index b8a4ea5..eaed2dd 100644 --- a/test/io_uring_register.c +++ b/test/io_uring_register.c @@ -628,7 +628,8 @@ main(int argc, char **argv) return 1; } mlock_limit = rlim.rlim_cur; - printf("RELIMIT_MEMLOCK: %lu (%lu)\n", rlim.rlim_cur, rlim.rlim_max); + printf("RELIMIT_MEMLOCK: %llu (%llu)\n", (unsigned long long) rlim.rlim_cur, + (unsigned long long) rlim.rlim_max); devnull = open("/dev/null", O_RDWR); if (devnull < 0) { perror("open /dev/null"); diff --git a/test/iopoll.c b/test/iopoll.c index 4bfc26a..fec9d18 100644 --- a/test/iopoll.c +++ b/test/iopoll.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include "helpers.h" diff --git a/test/link-timeout.c b/test/link-timeout.c index c8c289c..ad638e9 100644 --- a/test/link-timeout.c +++ b/test/link-timeout.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include "liburing.h" diff --git a/test/multicqes_drain.c b/test/multicqes_drain.c index 148cdd7..ff6fa7d 100644 --- a/test/multicqes_drain.c +++ b/test/multicqes_drain.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "liburing.h" diff --git a/test/poll-cancel-ton.c b/test/poll-cancel-ton.c index 1c4234b..b023394 100644 --- a/test/poll-cancel-ton.c +++ b/test/poll-cancel-ton.c @@ -9,9 +9,9 @@ #include #include #include -#include +#include #include -#include +#include #include "liburing.h" diff --git a/test/poll-cancel.c b/test/poll-cancel.c index 6bddc6c..0714a80 100644 --- a/test/poll-cancel.c +++ b/test/poll-cancel.c @@ -9,9 +9,9 @@ #include #include #include -#include +#include #include -#include +#include #include "liburing.h" diff --git a/test/poll-many.c b/test/poll-many.c index 3f8d08d..dfbeeab 100644 --- a/test/poll-many.c +++ b/test/poll-many.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/poll-mshot-update.c b/test/poll-mshot-update.c index d06699a..caedb6f 100644 --- a/test/poll-mshot-update.c +++ b/test/poll-mshot-update.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/poll-ring.c b/test/poll-ring.c index 1f69e20..2dd3ae6 100644 --- a/test/poll-ring.c +++ b/test/poll-ring.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include "liburing.h" diff --git a/test/poll-v-poll.c b/test/poll-v-poll.c index c8ba6f1..1b277db 100644 --- a/test/poll-v-poll.c +++ b/test/poll-v-poll.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/poll.c b/test/poll.c index f9a89d0..1cd57ba 100644 --- a/test/poll.c +++ b/test/poll.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include "liburing.h" diff --git a/test/read-write.c b/test/read-write.c index f505f93..3951a64 100644 --- a/test/read-write.c +++ b/test/read-write.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/register-restrictions.c b/test/register-restrictions.c index bcae67c..e1cf5bd 100644 --- a/test/register-restrictions.c +++ b/test/register-restrictions.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include "liburing.h" diff --git a/test/ring-leak2.c b/test/ring-leak2.c index 77e7d82..a8c03fe 100644 --- a/test/ring-leak2.c +++ b/test/ring-leak2.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/sendmsg_fs_cve.c b/test/sendmsg_fs_cve.c index 3866e5d..13a1235 100644 --- a/test/sendmsg_fs_cve.c +++ b/test/sendmsg_fs_cve.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include diff --git a/test/short-read.c b/test/short-read.c index 02eee04..a6f2620 100644 --- a/test/short-read.c +++ b/test/short-read.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include "helpers.h" diff --git a/test/shutdown.c b/test/shutdown.c index 20bcc77..14c7407 100644 --- a/test/shutdown.c +++ b/test/shutdown.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/test/sigfd-deadlock.c b/test/sigfd-deadlock.c index 038b094..277b342 100644 --- a/test/sigfd-deadlock.c +++ b/test/sigfd-deadlock.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include "liburing.h" diff --git a/test/sq-poll-dup.c b/test/sq-poll-dup.c index e688c9f..9596866 100644 --- a/test/sq-poll-dup.c +++ b/test/sq-poll-dup.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/sq-poll-kthread.c b/test/sq-poll-kthread.c index 0a0a75a..4bbf131 100644 --- a/test/sq-poll-kthread.c +++ b/test/sq-poll-kthread.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/sq-poll-share.c b/test/sq-poll-share.c index 99227d5..2f1c1dd 100644 --- a/test/sq-poll-share.c +++ b/test/sq-poll-share.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/sqpoll-exit-hang.c b/test/sqpoll-exit-hang.c index 43385ce..e137c41 100644 --- a/test/sqpoll-exit-hang.c +++ b/test/sqpoll-exit-hang.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "liburing.h" static unsigned long long mtime_since(const struct timeval *s, diff --git a/test/thread-exit.c b/test/thread-exit.c index b26d4aa..3e20431 100644 --- a/test/thread-exit.c +++ b/test/thread-exit.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include "helpers.h" -- cgit v1.2.3 From 89b35ac142460401316979a36cde1d9bb5dcb4e1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 20 Feb 2022 08:33:58 -0700 Subject: liburing.h: fix some overly long lines They are hard to read at 80 chars, let's get them wrapped properly. Signed-off-by: Jens Axboe --- src/include/liburing.h | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index c6f3cb8..1269370 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -290,20 +290,23 @@ static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd, /** * @pre Either fd_in or fd_out must be a pipe. * @param off_in If fd_in refers to a pipe, off_in must be (int64_t) -1; - * If fd_in does not refer to a pipe and off_in is (int64_t) -1, then bytes are read - * from fd_in starting from the file offset and it is adjust appropriately; - * If fd_in does not refer to a pipe and off_in is not (int64_t) -1, then the - * starting offset of fd_in will be off_in. + * If fd_in does not refer to a pipe and off_in is (int64_t) -1, + * then bytes are read from fd_in starting from the file offset + * and it is adjust appropriately; + * If fd_in does not refer to a pipe and off_in is not + * (int64_t) -1, then the starting offset of fd_in will be + * off_in. * @param off_out The description of off_in also applied to off_out. * @param splice_flags see man splice(2) for description of flags. * - * This splice operation can be used to implement sendfile by splicing to an intermediate pipe - * first, then splice to the final destination. + * This splice operation can be used to implement sendfile by splicing to an + * intermediate pipe first, then splice to the final destination. * In fact, the implementation of sendfile in kernel uses splice internally. * - * NOTE that even if fd_in or fd_out refers to a pipe, the splice operation can still failed with - * EINVAL if one of the fd doesn't explicitly support splice operation, e.g. reading from terminal - * is unsupported from kernel 5.7 to 5.11. + * NOTE that even if fd_in or fd_out refers to a pipe, the splice operation + * can still failed with EINVAL if one of the fd doesn't explicitly support + * splice operation, e.g. reading from terminal is unsupported from kernel 5.7 + * to 5.11. * Check issue #291 for more information. */ static inline void io_uring_prep_splice(struct io_uring_sqe *sqe, @@ -708,8 +711,9 @@ static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd, static inline unsigned io_uring_sq_ready(const struct io_uring *ring) { /* - * Without a barrier, we could miss an update and think the SQ wasn't ready. - * We don't need the load acquire for non-SQPOLL since then we drive updates. + * Without a barrier, we could miss an update and think the SQ wasn't + * ready. We don't need the load acquire for non-SQPOLL since then we + * drive updates. */ if (ring->flags & IORING_SETUP_SQPOLL) return ring->sq.sqe_tail - io_uring_smp_load_acquire(ring->sq.khead); -- cgit v1.2.3 From fd1d6cfafb4e9fb4d826175247527c7d1ca4ffc1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 21 Feb 2022 05:07:46 -0700 Subject: test/pollfree: use mmap(2) instead of a manual syscall A lot of the syzkaller tests aren't really applicable on non-x86, or just simply assume x86. Replace the syscall(__NR_mmap, ...) usage with a regular mmap(2) call, and check for failure. Looks like some of these assume 4k pages as well, so just bail if we fail mapping. Fixes: https://github.com/axboe/liburing/issues/532 Signed-off-by: Jens Axboe --- test/pollfree.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test/pollfree.c b/test/pollfree.c index cdc7af0..4ef259c 100644 --- a/test/pollfree.c +++ b/test/pollfree.c @@ -391,12 +391,24 @@ void execute_call(int call) int main(int argc, char *argv[]) { + void *ret; + +#if !defined(__i386) && !defined(__x86_64__) + return 0; +#endif + if (argc > 1) return 0; - syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); - syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); - syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + ret = mmap((void *)0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + if (ret == MAP_FAILED) + return 0; + mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); + if (ret == MAP_FAILED) + return 0; + mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + if (ret == MAP_FAILED) + return 0; loop(); return 0; } -- cgit v1.2.3 From e05652f22ee5b5bcc78f69a09ed7a7ba883a928a Mon Sep 17 00:00:00 2001 From: Ioannis Tsakpinis Date: Mon, 21 Feb 2022 15:14:44 +0200 Subject: Fix madvise syscall wrapper Now uses the 3-arity syscall macro so that all parameters are passed. Signed-off-by: Ioannis Tsakpinis --- src/arch/x86/syscall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86/syscall.h b/src/arch/x86/syscall.h index c4ae24e..2efaef0 100644 --- a/src/arch/x86/syscall.h +++ b/src/arch/x86/syscall.h @@ -154,7 +154,7 @@ static inline int __sys_munmap(void *addr, size_t length) static inline int __sys_madvise(void *addr, size_t length, int advice) { - return (int) __do_syscall2(__NR_madvise, addr, length); + return (int) __do_syscall3(__NR_madvise, addr, length, advice); } static inline int __sys_getrlimit(int resource, struct rlimit *rlim) -- cgit v1.2.3 From 52bb74252002fb46d777309d7512cbe35fb902ba Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 21 Feb 2022 08:52:51 -0700 Subject: Add direct syscall support for aarch64 Modeled on the x86-64 code. Signed-off-by: Jens Axboe --- src/arch/aarch64/syscall.h | 155 +++++++++++++++++++++++++++++++++++++++++++++ src/syscall.h | 2 + 2 files changed, 157 insertions(+) create mode 100644 src/arch/aarch64/syscall.h diff --git a/src/arch/aarch64/syscall.h b/src/arch/aarch64/syscall.h new file mode 100644 index 0000000..5387772 --- /dev/null +++ b/src/arch/aarch64/syscall.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef __INTERNAL__LIBURING_SYSCALL_H + #error "This file should be included from src/syscall.h (liburing)" +#endif + +#ifndef LIBURING_ARCH_AARCH64_SYSCALL_H +#define LIBURING_ARCH_AARCH64_SYSCALL_H + +#if defined(__aarch64__) + +#define __do_syscallN(...) ({ \ + __asm__ volatile ( \ + "svc 0" \ + : "=r"(x0) \ + : __VA_ARGS__ \ + : "memory", "cc"); \ + (long) x0; \ +}) + +#define __do_syscall0(__n) ({ \ + register long x8 __asm__("x8") = __n; \ + register long x0 __asm__("x0"); \ + \ + __do_syscallN("r" (x8)); \ +}) + +#define __do_syscall1(__n, __a) ({ \ + register long x8 __asm__("x8") = __n; \ + register __typeof__(__a) x0 __asm__("x0") = __a; \ + \ + __do_syscallN("r" (x8), "0" (x0)); \ +}) + +#define __do_syscall2(__n, __a, __b) ({ \ + register long x8 __asm__("x8") = __n; \ + register __typeof__(__a) x0 __asm__("x0") = __a; \ + register __typeof__(__b) x1 __asm__("x1") = __b; \ + \ + __do_syscallN("r" (x8), "0" (x0), "r" (x1)); \ +}) + +#define __do_syscall3(__n, __a, __b, __c) ({ \ + register long x8 __asm__("x8") = __n; \ + register __typeof__(__a) x0 __asm__("x0") = __a; \ + register __typeof__(__b) x1 __asm__("x1") = __b; \ + register __typeof__(__c) x2 __asm__("x2") = __c; \ + \ + __do_syscallN("r" (x8), "0" (x0), "r" (x1), "r" (x2)); \ +}) + +#define __do_syscall4(__n, __a, __b, __c, __d) ({ \ + register long x8 __asm__("x8") = __n; \ + register __typeof__(__a) x0 __asm__("x0") = __a; \ + register __typeof__(__b) x1 __asm__("x1") = __b; \ + register __typeof__(__c) x2 __asm__("x2") = __c; \ + register __typeof__(__d) x3 __asm__("x3") = __d; \ + \ + __do_syscallN("r" (x8), "0" (x0), "r" (x1), "r" (x2), "r" (x3));\ +}) + +#define __do_syscall5(__n, __a, __b, __c, __d, __e) ({ \ + register long x8 __asm__("x8") = __n; \ + register __typeof__(__a) x0 __asm__("x0") = __a; \ + register __typeof__(__b) x1 __asm__("x1") = __b; \ + register __typeof__(__c) x2 __asm__("x2") = __c; \ + register __typeof__(__d) x3 __asm__("x3") = __d; \ + register __typeof__(__e) x4 __asm__("x4") = __e; \ + \ + __do_syscallN("r" (x8), "0" (x0), "r" (x1), "r" (x2), "r" (x3), \ + "r"(x4)); \ +}) + +#define __do_syscall6(__n, __a, __b, __c, __d, __e, __f) ({ \ + register long x8 __asm__("x8") = __n; \ + register __typeof__(__a) x0 __asm__("x0") = __a; \ + register __typeof__(__b) x1 __asm__("x1") = __b; \ + register __typeof__(__c) x2 __asm__("x2") = __c; \ + register __typeof__(__d) x3 __asm__("x3") = __d; \ + register __typeof__(__e) x4 __asm__("x4") = __e; \ + register __typeof__(__f) x5 __asm__("x5") = __f; \ + \ + __do_syscallN("r" (x8), "0" (x0), "r" (x1), "r" (x2), "r" (x3), \ + "r" (x4), "r"(x5)); \ +}) + + +static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) +{ + return (void *) __do_syscall6(__NR_mmap, addr, length, prot, flags, fd, + offset); +} + +static inline int __sys_munmap(void *addr, size_t length) +{ + return (int) __do_syscall2(__NR_munmap, addr, length); +} + +static inline int __sys_madvise(void *addr, size_t length, int advice) +{ + return (int) __do_syscall3(__NR_madvise, addr, length, advice); +} + +static inline int __sys_getrlimit(int resource, struct rlimit *rlim) +{ + return (int) __do_syscall2(__NR_getrlimit, resource, rlim); +} + +static inline int __sys_setrlimit(int resource, const struct rlimit *rlim) +{ + return (int) __do_syscall2(__NR_setrlimit, resource, rlim); +} + +static inline int __sys_close(int fd) +{ + return (int) __do_syscall1(__NR_close, fd); +} + +static inline int ____sys_io_uring_register(int fd, unsigned opcode, + const void *arg, unsigned nr_args) +{ + return (int) __do_syscall4(__NR_io_uring_register, fd, opcode, arg, + nr_args); +} + +static inline int ____sys_io_uring_setup(unsigned entries, + struct io_uring_params *p) +{ + return (int) __do_syscall2(__NR_io_uring_setup, entries, p); +} + +static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig, int sz) +{ + return (int) __do_syscall6(__NR_io_uring_enter, fd, to_submit, + min_complete, flags, sig, sz); +} + +static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig) +{ + return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, + _NSIG / 8); +} + +#else /* #if defined(__aarch64__) */ + +#include "../generic/syscall.h" + +#endif /* #if defined(__aarch64__) */ + +#endif /* #ifndef LIBURING_ARCH_AARCH64_SYSCALL_H */ diff --git a/src/syscall.h b/src/syscall.h index beb357e..c05d132 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -73,6 +73,8 @@ static inline bool IS_ERR(const void *ptr) #define __INTERNAL__LIBURING_SYSCALL_H #if defined(__x86_64__) || defined(__i386__) #include "arch/x86/syscall.h" +#elif defined(__aarch64__) + #include "arch/aarch64/syscall.h" #else /* * We don't have native syscall wrappers -- cgit v1.2.3 From 6cf23f9a6470d93b3396444f88b5bcd946fc0a55 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 20 Feb 2022 11:33:15 -0700 Subject: Move io_uring_get_sqe() inline in the liburing.h header It's a fast path function, we should not be making it a function call into the library. Signed-off-by: Jens Axboe --- src/include/liburing.h | 22 +++++++++++++++++++++- src/queue.c | 21 --------------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 1269370..3cf314d 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -127,7 +127,6 @@ int io_uring_submit_and_wait_timeout(struct io_uring *ring, unsigned wait_nr, struct __kernel_timespec *ts, sigset_t *sigmask); -struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, unsigned nr_iovecs); @@ -825,6 +824,27 @@ static inline int io_uring_wait_cqe(struct io_uring *ring, return io_uring_wait_cqe_nr(ring, cqe_ptr, 1); } +/* + * Return an sqe to fill. Application must later call io_uring_submit() + * when it's ready to tell the kernel about it. The caller may call this + * function multiple times before calling io_uring_submit(). + * + * Returns a vacant sqe, or NULL if we're full. + */ +static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) +{ + struct io_uring_sq *sq = &ring->sq; + unsigned int head = io_uring_smp_load_acquire(sq->khead); + unsigned int next = sq->sqe_tail + 1; + struct io_uring_sqe *sqe = NULL; + + if (next - head <= *sq->kring_entries) { + sqe = &sq->sqes[sq->sqe_tail & *sq->kring_mask]; + sq->sqe_tail = next; + } + return sqe; +} + ssize_t io_uring_mlock_size(unsigned entries, unsigned flags); ssize_t io_uring_mlock_size_params(unsigned entries, struct io_uring_params *p); diff --git a/src/queue.c b/src/queue.c index f8384d1..e5fd983 100644 --- a/src/queue.c +++ b/src/queue.c @@ -403,27 +403,6 @@ int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr) return __io_uring_submit_and_wait(ring, wait_nr); } -/* - * Return an sqe to fill. Application must later call io_uring_submit() - * when it's ready to tell the kernel about it. The caller may call this - * function multiple times before calling io_uring_submit(). - * - * Returns a vacant sqe, or NULL if we're full. - */ -struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) -{ - struct io_uring_sq *sq = &ring->sq; - unsigned int head = io_uring_smp_load_acquire(sq->khead); - unsigned int next = sq->sqe_tail + 1; - struct io_uring_sqe *sqe = NULL; - - if (next - head <= *sq->kring_entries) { - sqe = &sq->sqes[sq->sqe_tail & *sq->kring_mask]; - sq->sqe_tail = next; - } - return sqe; -} - int __io_uring_sqring_wait(struct io_uring *ring) { return ____sys_io_uring_enter(ring->ring_fd, 0, 0, -- cgit v1.2.3 From 3de6251a2bd6805481e0b0f24ffe9c18454fdd0a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 21 Feb 2022 10:14:01 -0700 Subject: Add generic syscall definitions If an arch provides its own syscall handlers, we can easily share the definitions of the exposed system calls. Share them between x86-64 and aarch64. Signed-off-by: Jens Axboe --- src/arch/aarch64/syscall.h | 62 +------------------------------------------ src/arch/syscall-defs.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++ src/arch/x86/syscall.h | 61 +------------------------------------------ 3 files changed, 67 insertions(+), 121 deletions(-) create mode 100644 src/arch/syscall-defs.h diff --git a/src/arch/aarch64/syscall.h b/src/arch/aarch64/syscall.h index 5387772..c0ab7e2 100644 --- a/src/arch/aarch64/syscall.h +++ b/src/arch/aarch64/syscall.h @@ -84,67 +84,7 @@ "r" (x4), "r"(x5)); \ }) - -static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags, - int fd, off_t offset) -{ - return (void *) __do_syscall6(__NR_mmap, addr, length, prot, flags, fd, - offset); -} - -static inline int __sys_munmap(void *addr, size_t length) -{ - return (int) __do_syscall2(__NR_munmap, addr, length); -} - -static inline int __sys_madvise(void *addr, size_t length, int advice) -{ - return (int) __do_syscall3(__NR_madvise, addr, length, advice); -} - -static inline int __sys_getrlimit(int resource, struct rlimit *rlim) -{ - return (int) __do_syscall2(__NR_getrlimit, resource, rlim); -} - -static inline int __sys_setrlimit(int resource, const struct rlimit *rlim) -{ - return (int) __do_syscall2(__NR_setrlimit, resource, rlim); -} - -static inline int __sys_close(int fd) -{ - return (int) __do_syscall1(__NR_close, fd); -} - -static inline int ____sys_io_uring_register(int fd, unsigned opcode, - const void *arg, unsigned nr_args) -{ - return (int) __do_syscall4(__NR_io_uring_register, fd, opcode, arg, - nr_args); -} - -static inline int ____sys_io_uring_setup(unsigned entries, - struct io_uring_params *p) -{ - return (int) __do_syscall2(__NR_io_uring_setup, entries, p); -} - -static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, - unsigned min_complete, unsigned flags, - sigset_t *sig, int sz) -{ - return (int) __do_syscall6(__NR_io_uring_enter, fd, to_submit, - min_complete, flags, sig, sz); -} - -static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, - unsigned min_complete, unsigned flags, - sigset_t *sig) -{ - return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, - _NSIG / 8); -} +#include "../syscall-defs.h" #else /* #if defined(__aarch64__) */ diff --git a/src/arch/syscall-defs.h b/src/arch/syscall-defs.h new file mode 100644 index 0000000..2c37c4d --- /dev/null +++ b/src/arch/syscall-defs.h @@ -0,0 +1,65 @@ +#ifndef LIBURING_ARCH_SYSCALL_DEFS_H +#define LIBURING_ARCH_SYSCALL_DEFS_H + +static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) +{ + return (void *) __do_syscall6(__NR_mmap, addr, length, prot, flags, fd, + offset); +} + +static inline int __sys_munmap(void *addr, size_t length) +{ + return (int) __do_syscall2(__NR_munmap, addr, length); +} + +static inline int __sys_madvise(void *addr, size_t length, int advice) +{ + return (int) __do_syscall3(__NR_madvise, addr, length, advice); +} + +static inline int __sys_getrlimit(int resource, struct rlimit *rlim) +{ + return (int) __do_syscall2(__NR_getrlimit, resource, rlim); +} + +static inline int __sys_setrlimit(int resource, const struct rlimit *rlim) +{ + return (int) __do_syscall2(__NR_setrlimit, resource, rlim); +} + +static inline int __sys_close(int fd) +{ + return (int) __do_syscall1(__NR_close, fd); +} + +static inline int ____sys_io_uring_register(int fd, unsigned opcode, + const void *arg, unsigned nr_args) +{ + return (int) __do_syscall4(__NR_io_uring_register, fd, opcode, arg, + nr_args); +} + +static inline int ____sys_io_uring_setup(unsigned entries, + struct io_uring_params *p) +{ + return (int) __do_syscall2(__NR_io_uring_setup, entries, p); +} + +static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig, int sz) +{ + return (int) __do_syscall6(__NR_io_uring_enter, fd, to_submit, + min_complete, flags, sig, sz); +} + +static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, + unsigned min_complete, unsigned flags, + sigset_t *sig) +{ + return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, + _NSIG / 8); +} + +#endif diff --git a/src/arch/x86/syscall.h b/src/arch/x86/syscall.h index 2efaef0..89a68f6 100644 --- a/src/arch/x86/syscall.h +++ b/src/arch/x86/syscall.h @@ -140,66 +140,7 @@ rax; \ }) -static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags, - int fd, off_t offset) -{ - return (void *) __do_syscall6(__NR_mmap, addr, length, prot, flags, fd, - offset); -} - -static inline int __sys_munmap(void *addr, size_t length) -{ - return (int) __do_syscall2(__NR_munmap, addr, length); -} - -static inline int __sys_madvise(void *addr, size_t length, int advice) -{ - return (int) __do_syscall3(__NR_madvise, addr, length, advice); -} - -static inline int __sys_getrlimit(int resource, struct rlimit *rlim) -{ - return (int) __do_syscall2(__NR_getrlimit, resource, rlim); -} - -static inline int __sys_setrlimit(int resource, const struct rlimit *rlim) -{ - return (int) __do_syscall2(__NR_setrlimit, resource, rlim); -} - -static inline int __sys_close(int fd) -{ - return (int) __do_syscall1(__NR_close, fd); -} - -static inline int ____sys_io_uring_register(int fd, unsigned opcode, - const void *arg, unsigned nr_args) -{ - return (int) __do_syscall4(__NR_io_uring_register, fd, opcode, arg, - nr_args); -} - -static inline int ____sys_io_uring_setup(unsigned entries, - struct io_uring_params *p) -{ - return (int) __do_syscall2(__NR_io_uring_setup, entries, p); -} - -static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, - unsigned min_complete, unsigned flags, - sigset_t *sig, int sz) -{ - return (int) __do_syscall6(__NR_io_uring_enter, fd, to_submit, - min_complete, flags, sig, sz); -} - -static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, - unsigned min_complete, unsigned flags, - sigset_t *sig) -{ - return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, - _NSIG / 8); -} +#include "../syscall-defs.h" #else /* #if defined(__x86_64__) */ -- cgit v1.2.3 From 63dc2177ed42fd0ae45cb66e169a28305e0fe622 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 21 Feb 2022 10:24:17 -0700 Subject: test/pollfree: fix compile on 32-bit x86 For some reason we don't have __NR_futex or SYS_futex there. Just skip the test if we don't have the proper syscall number, this dates back to the days of every arch having their own syscall numbering. Not worth fixing this one up for real. Signed-off-by: Jens Axboe --- test/pollfree.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/pollfree.c b/test/pollfree.c index 4ef259c..10f842b 100644 --- a/test/pollfree.c +++ b/test/pollfree.c @@ -24,6 +24,8 @@ #include +#ifdef __NR_futex + static void sleep_ms(uint64_t ms) { usleep(ms * 1000); @@ -77,13 +79,13 @@ static void event_set(event_t* ev) if (ev->state) exit(1); __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE); - syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000); + syscall(__NR_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000); } static void event_wait(event_t* ev) { while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE)) - syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0); + syscall(__NR_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0); } static int event_isset(event_t* ev) @@ -100,7 +102,7 @@ static int event_timedwait(event_t* ev, uint64_t timeout) struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; - syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts); + syscall(__NR_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts); if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE)) return 1; now = current_time_ms(); @@ -412,3 +414,12 @@ int main(int argc, char *argv[]) loop(); return 0; } + +#else /* __NR_futex */ + +int main(int argc, char *argv[]) +{ + return 0; +} + +#endif /* __NR_futex */ -- cgit v1.2.3 From f1e75bed0a508177225e3c0fad037a6f1154f53f Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Tue, 22 Feb 2022 18:07:23 +0700 Subject: .github/workflows: Add multiarch GitHub CI build support This adds multiarch build for GitHub bot. Currently, only GCC that supports multiarch build. I couldn't find the clang cross compiler package from the Ubuntu apt, so let's skip it at the moment. New arch supports: - aarch64 - arm (32-bit) Signed-off-by: Ammar Faizi --- .github/workflows/build.yml | 61 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5157cb..30a2fc7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,11 +13,41 @@ jobs: fail-fast: false matrix: include: - - cc: gcc - cxx: g++ - - cc: clang + # x86-64 gcc + - arch: x86_64 + cc_pkg: gcc-x86-64-linux-gnu + cxx_pkg: g++-x86-64-linux-gnu + cc: x86_64-linux-gnu-gcc + cxx: x86_64-linux-gnu-g++ + + # x86-64 clang + - arch: x86_64 + cc_pkg: clang + cxx_pkg: clang + cc: clang cxx: clang++ + # x86 (32-bit) gcc + - arch: i686 + cc_pkg: gcc-i686-linux-gnu + cxx_pkg: g++-i686-linux-gnu + cc: i686-linux-gnu-gcc + cxx: i686-linux-gnu-g++ + + # aarch64 gcc + - arch: aarch64 + cc_pkg: gcc-aarch64-linux-gnu + cxx_pkg: g++-aarch64-linux-gnu + cc: aarch64-linux-gnu-gcc + cxx: aarch64-linux-gnu-g++ + + # arm (32-bit) gcc + - arch: arm + cc_pkg: gcc-arm-linux-gnueabi + cxx_pkg: g++-arm-linux-gnueabi + cc: arm-linux-gnueabi-gcc + cxx: arm-linux-gnueabi-g++ + env: FLAGS: -g -O2 -Wall -Wextra -Werror @@ -25,6 +55,11 @@ jobs: - name: Checkout source uses: actions/checkout@v2 + - name: Install Compilers + run: | + sudo apt-get update -y; + sudo apt-get install -y ${{matrix.cc_pkg}} ${{matrix.cxx_pkg}}; + - name: Display compiler versions run: | ${{matrix.cc}} --version; @@ -35,19 +70,15 @@ jobs: ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}}; make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS"; - - name: Build nolibc x86-64 - run: | - ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} --nolibc; - make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS"; - - - name: Build (32 bit) + - name: Build nolibc run: | - sudo apt-get install libc6-dev-i386 gcc-multilib g++-multilib -y; - make clean; - make V=1 -j$(nproc) \ - CPPFLAGS="-Werror" \ - CFLAGS="$FLAGS -m32" \ - CXXFLAGS="$FLAGS -m32"; + if [[ "${{matrix.arch}}" == "x86_64" ]]; then \ + make clean; \ + ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} --nolibc; \ + make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS"; \ + else \ + echo "Skipping nolibc build, this arch doesn't support building liburing without libc"; \ + fi; - name: Test install command run: | -- cgit v1.2.3 From 3472a5887fe4423664c21136471807bd7f9a99bf Mon Sep 17 00:00:00 2001 From: Alviro Iskandar Setiawan Date: Wed, 23 Feb 2022 00:24:26 +0700 Subject: configure: Fix _GNU_SOURCE redefinition warning ``` gcc -D_GNU_SOURCE -include config-host.h -Werror=implicit-function-declaration \ -o /tmp/tmp.UrAfu1BQqA/liburing-conf.exe /tmp/tmp.UrAfu1BQqA/liburing-conf.c /tmp/tmp.UrAfu1BQqA/liburing-conf.c:1: warning: "_GNU_SOURCE" redefined 1 | #define _GNU_SOURCE | : note: this is the location of the previous definition ``` Introduced by commit 17d25f4c73b89 ("test/io_uring_register: fix -Wimplicit-function-declaration of memfd_create"). Fixes: 17d25f4c73b89dfc722a367914776577e266638c ("test/io_uring_register: fix -Wimplicit-function-declaration of memfd_create") Signed-off-by: Alviro Iskandar Setiawan Signed-off-by: Ammar Faizi --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index 1f7f1c3..b8ecb7b 100755 --- a/configure +++ b/configure @@ -369,7 +369,6 @@ print_config "has_ucontext" "$has_ucontext" # check for memfd_create(2) has_memfd_create="no" cat > $TMPC << EOF -#define _GNU_SOURCE #include int main(int argc, char **argv) { -- cgit v1.2.3 From 2cd9452658b6420e0211ed0a0e1440bed50bdbf7 Mon Sep 17 00:00:00 2001 From: Alviro Iskandar Setiawan Date: Wed, 23 Feb 2022 00:43:33 +0700 Subject: configure: Fix clang-12 warning `-Wdeprecated` ``` clang-12: warning: treating 'c' input as 'c++' when in C++ mode, this \ behvior is deprecated [-Wdeprecated] ``` The target compile is C++ but the file extension is ".c". Got the above warning from clang. Fix it by creating a temporary file with ".cpp" extension and use it. Introduced by commit d9f953770708ad ("configure: test for presence of C++ compiler"). Fixes: d9f953770708ad6893140dc2d11258223ba7abfd ("configure: test for presence of C++ compiler") Cc: Jens Axboe Signed-off-by: Alviro Iskandar Setiawan Signed-off-by: Ammar Faizi --- configure | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configure b/configure index b8ecb7b..512a556 100755 --- a/configure +++ b/configure @@ -81,10 +81,11 @@ fi TMP_DIRECTORY="$(mktemp -d)" TMPC="$TMP_DIRECTORY/liburing-conf.c" TMPC2="$TMP_DIRECTORY/liburing-conf-2.c" +TMPCXX="$TMP_DIRECTORY/liburing-conf-2.cpp" TMPO="$TMP_DIRECTORY/liburing-conf.o" TMPE="$TMP_DIRECTORY/liburing-conf.exe" -touch $TMPC $TMPC2 $TMPO $TMPE +touch $TMPC $TMPC2 $TMPCXX $TMPO $TMPE # NB: do not call "exit" in the trap handler; this is buggy with some shells; # see <1285349658-3122-1-git-send-email-loic.minier@linaro.org> @@ -171,7 +172,7 @@ compile_prog_cxx() { local_cflags="$1" local_ldflags="$2 $LIBS" echo "Compiling test case $3" >> config.log - do_cxx $CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags + do_cxx $CFLAGS $local_cflags -o $TMPE $TMPCXX $LDFLAGS $local_ldflags } has() { @@ -334,7 +335,7 @@ print_config "glibc_statx" "$glibc_statx" ########################################## # check for C++ has_cxx="no" -cat > $TMPC << EOF +cat > $TMPCXX << EOF #include int main(int argc, char **argv) { -- cgit v1.2.3 From 4bc747da1cdf53f4d9fbf5ff22073c2cfc8428e3 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Wed, 23 Feb 2022 17:05:44 +0700 Subject: man/io_uring_get_probe.3: Trivial man cleanup s/does/do/ Signed-off-by: Ammar Faizi --- man/io_uring_get_probe.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_get_probe.3 b/man/io_uring_get_probe.3 index 17b34c1..38f1c53 100644 --- a/man/io_uring_get_probe.3 +++ b/man/io_uring_get_probe.3 @@ -19,7 +19,7 @@ structure to the caller. The caller is responsible for freeing the structure with the function io_uring_free_probe(). .SH NOTES -Earlier versions of the Linux kernel does not support probe. If the kernel +Earlier versions of the Linux kernel do not support probe. If the kernel doesn't support probe, this function will return NULL. .SH RETURN VALUE -- cgit v1.2.3 From f1c6277d4a6ea120c4800903ae0ba4c659c20bab Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Wed, 23 Feb 2022 17:02:49 +0700 Subject: arch/syscall-defs.h: Add missing SPDX-License-Identifier This adds missing SPDX-License-Identifier for: src/arch/syscall-defs.h Signed-off-by: Ammar Faizi --- src/arch/syscall-defs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/arch/syscall-defs.h b/src/arch/syscall-defs.h index 2c37c4d..f79f56a 100644 --- a/src/arch/syscall-defs.h +++ b/src/arch/syscall-defs.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: MIT */ + #ifndef LIBURING_ARCH_SYSCALL_DEFS_H #define LIBURING_ARCH_SYSCALL_DEFS_H -- cgit v1.2.3 From d36db0b72b9399623dee12b61069845d8e1bfa05 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Wed, 23 Feb 2022 17:04:14 +0700 Subject: test: Add missing SPDX-License-Identifier This adds missing SPDX-License-Identifier for: test/ce593a6c480a-test.c test/double-poll-crash.c test/exec-target.c test/lfs-openat-write.c test/lfs-openat.c test/pipe-eof.c test/pollfree.c test/sendmsg_fs_cve.c test/skip-cqe.c test/splice.c test/sq-poll-kthread.c test/sqpoll-cancel-hang.c test/sqpoll-disable-exit.c test/sqpoll-exit-hang.c test/sqpoll-sleep.c Signed-off-by: Ammar Faizi --- test/ce593a6c480a-test.c | 1 + test/double-poll-crash.c | 1 + test/exec-target.c | 2 ++ test/lfs-openat-write.c | 2 ++ test/lfs-openat.c | 2 ++ test/pipe-eof.c | 2 ++ test/pollfree.c | 1 + test/sendmsg_fs_cve.c | 1 + test/skip-cqe.c | 1 + test/splice.c | 1 + test/sq-poll-kthread.c | 1 + test/sqpoll-cancel-hang.c | 1 + test/sqpoll-disable-exit.c | 1 + test/sqpoll-exit-hang.c | 1 + test/sqpoll-sleep.c | 1 + 15 files changed, 19 insertions(+) diff --git a/test/ce593a6c480a-test.c b/test/ce593a6c480a-test.c index c6949f0..47de128 100644 --- a/test/ce593a6c480a-test.c +++ b/test/ce593a6c480a-test.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ /* * Test 5.7 regression with task_work not being run while a task is * waiting on another event in the kernel. diff --git a/test/double-poll-crash.c b/test/double-poll-crash.c index e932bec..5bfce09 100644 --- a/test/double-poll-crash.c +++ b/test/double-poll-crash.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ // https://syzkaller.appspot.com/bug?id=5c9918d20f771265ad0ffae3c8f3859d24850692 // autogenerated by syzkaller (https://github.com/google/syzkaller) diff --git a/test/exec-target.c b/test/exec-target.c index 50bc2c9..2399c2d 100644 --- a/test/exec-target.c +++ b/test/exec-target.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: MIT */ + int main(int argc, char *argv[]) { return 0; diff --git a/test/lfs-openat-write.c b/test/lfs-openat-write.c index ac35e1b..6bbf78d 100644 --- a/test/lfs-openat-write.c +++ b/test/lfs-openat-write.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: MIT */ + #define _LARGEFILE_SOURCE #define _FILE_OFFSET_BITS 64 diff --git a/test/lfs-openat.c b/test/lfs-openat.c index b14238a..4823cc4 100644 --- a/test/lfs-openat.c +++ b/test/lfs-openat.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: MIT */ + #define _LARGEFILE_SOURCE #define _FILE_OFFSET_BITS 64 diff --git a/test/pipe-eof.c b/test/pipe-eof.c index 4c98de9..bf13517 100644 --- a/test/pipe-eof.c +++ b/test/pipe-eof.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: MIT */ + /* * Test that closed pipe reads returns 0, instead of waiting for more * data. diff --git a/test/pollfree.c b/test/pollfree.c index 10f842b..e2511df 100644 --- a/test/pollfree.c +++ b/test/pollfree.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ // https://syzkaller.appspot.com/bug?id=5f5a44abb4cba056fe24255c4fcb7e7bbe13de7a // autogenerated by syzkaller (https://github.com/google/syzkaller) diff --git a/test/sendmsg_fs_cve.c b/test/sendmsg_fs_cve.c index 13a1235..2ce3114 100644 --- a/test/sendmsg_fs_cve.c +++ b/test/sendmsg_fs_cve.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ /* * repro-CVE-2020-29373 -- Reproducer for CVE-2020-29373. * diff --git a/test/skip-cqe.c b/test/skip-cqe.c index a01800a..99b882b 100644 --- a/test/skip-cqe.c +++ b/test/skip-cqe.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ #include #include #include diff --git a/test/splice.c b/test/splice.c index f4f0c9c..5e9b789 100644 --- a/test/splice.c +++ b/test/splice.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ #include #include #include diff --git a/test/sq-poll-kthread.c b/test/sq-poll-kthread.c index 4bbf131..3f4a07b 100644 --- a/test/sq-poll-kthread.c +++ b/test/sq-poll-kthread.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ /* * Description: test if io_uring SQ poll kthread is stopped when the userspace * process ended with or without closing the io_uring fd diff --git a/test/sqpoll-cancel-hang.c b/test/sqpoll-cancel-hang.c index e561478..ef62272 100644 --- a/test/sqpoll-cancel-hang.c +++ b/test/sqpoll-cancel-hang.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ #include #include #include diff --git a/test/sqpoll-disable-exit.c b/test/sqpoll-disable-exit.c index 93bcf42..76b6cf5 100644 --- a/test/sqpoll-disable-exit.c +++ b/test/sqpoll-disable-exit.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ // https://syzkaller.appspot.com/bug?id=99f4ea77bb9b9ef24cefb66469be319f4aa9f162 // autogenerated by syzkaller (https://github.com/google/syzkaller) diff --git a/test/sqpoll-exit-hang.c b/test/sqpoll-exit-hang.c index e137c41..cde2115 100644 --- a/test/sqpoll-exit-hang.c +++ b/test/sqpoll-exit-hang.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ /* * Test that we exit properly with SQPOLL and having a request that * adds a circular reference to the ring itself. diff --git a/test/sqpoll-sleep.c b/test/sqpoll-sleep.c index 7ffd0e5..9d1cff6 100644 --- a/test/sqpoll-sleep.c +++ b/test/sqpoll-sleep.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ /* * Test that the sqthread goes to sleep around the specified time, and that * the NEED_WAKEUP flag is then set. -- cgit v1.2.3 From 071ad6354d1e0a6da48469fbbd750cc4ca400a2c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 23 Feb 2022 16:03:34 -0700 Subject: man: read/write page updates - Add note on some limitations of using -1 for the offset, indicating that the application wants to use the current file position rather than pass on in. - A few style fixups. Signed-off-by: Jens Axboe --- man/io_uring_prep_read.3 | 12 ++++++++---- man/io_uring_prep_readv.3 | 15 ++++++++++----- man/io_uring_prep_readv2.3 | 12 +++++++++--- man/io_uring_prep_write.3 | 12 ++++++++---- man/io_uring_prep_writev.3 | 15 ++++++++++----- man/io_uring_prep_writev2.3 | 12 +++++++++--- 6 files changed, 54 insertions(+), 24 deletions(-) diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index 4fc1420..de3067d 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -29,11 +29,15 @@ into the buffer at the specified .I offset. -On files that support seeking, if the offset is set to -1, the read operation -commences at the file offset, and the file offset is incremented by the number -of bytes read. See +On files that support seeking, if the offset is set to +.B -1, +the read operation commences at the file offset, and the file offset is +incremented by the number of bytes read. See .BR read (2) -for more details. +for more details. Note that for an async API, reading and updating the +current file offset may result in unpredictable behavior, unless access +to the file is serialized. It is not encouraged to use this feature, if it's +possible to provide the desired IO offset from the application or library. On files that are not capable of seeking, the offset is ignored. diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index b08ccb9..8e66bce 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -18,7 +18,8 @@ io_uring_prep_readv - prepare vector I/O read request .PP .SH DESCRIPTION .PP -The io_uring_prep_readv() prepares a vectored IO read request. The submission queue entry +The io_uring_prep_readv() prepares a vectored IO read request. The submission +queue entry .I sqe is setup to use the file descriptor .I fd @@ -29,11 +30,15 @@ into the array at the specified .I offset. -On files that support seeking, if the offset is set to -1, the read operation -commences at the file offset, and the file offset is incremented by the number -of bytes read. See +On files that support seeking, if the offset is set to +.B -1, +the read operation commences at the file offset, and the file offset is +incremented by the number of bytes read. See .BR read (2) -for more details. +for more details. Note that for an async API, reading and updating the +current file offset may result in unpredictable behavior, unless access +to the file is serialized. It is not encouraged to use this feature, if it's +possible to provide the desired IO offset from the application or library. On files that are not capable of seeking, the offset is ignored. diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index b05f36e..0d9d200 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -21,7 +21,8 @@ io_uring_prep_readv2 - prepare vector I/O read request with flags .PP .SH DESCRIPTION .PP -The io_uring_prep_readv2() prepares a vectored IO read request. The submission queue entry +The io_uring_prep_readv2() prepares a vectored IO read request. The submission +queue entry .I sqe is setup to use the file descriptor .I fd @@ -49,7 +50,9 @@ per-IO O_DSYNC per-IO O_SYNC .TP .B RWF_NOWAIT -per-IO, return -EAGAIN if operation would block +per-IO, return +.B -EAGAIN +if operation would block .TP .B RWF_APPEND per-IO O_APPEND @@ -60,7 +63,10 @@ On files that support seeking, if the offset is set to the read operation commences at the file offset, and the file offset is incremented by the number of bytes read. See .BR read (2) -for more details. +for more details. Note that for an async API, reading and updating the +current file offset may result in unpredictable behavior, unless access +to the file is serialized. It is not encouraged to use this feature, if it's +possible to provide the desired IO offset from the application or library. On files that are not capable of seeking, the offset is ignored. diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 25c5301..4bbf7e0 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -29,11 +29,15 @@ from the buffer at the specified .I offset. -On files that support seeking, if the offset is set to -1, the write operation -commences at the file offset, and the file offset is incremented by the number -of bytes written. See +On files that support seeking, if the offset is set to +.B -1, +the write operation commences at the file offset, and the file offset is +incremented by the number of bytes written. See .BR write (2) -for more details. +for more details. Note that for an async API, reading and updating the +current file offset may result in unpredictable behavior, unless access +to the file is serialized. It is not encouraged to use this feature, if it's +possible to provide the desired IO offset from the application or library. On files that are not capable of seeking, the offset is ignored. diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 99652d3..e11f656 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -18,7 +18,8 @@ io_uring_prep_writev - prepare vector I/O write request .PP .SH DESCRIPTION .PP -The io_uring_prep_writev() prepares a vectored IO write request. The submission queue entry +The io_uring_prep_writev() prepares a vectored IO write request. The submission +queue entry .I sqe is setup to use the file descriptor .I fd @@ -29,11 +30,15 @@ from the array at the specified .I offset. -On files that support seeking, if the offset is set to -1, the write operation -commences at the file offset, and the file offset is incremented by the number -of bytes written. See +On files that support seeking, if the offset is set to +.B -1, +the write operation commences at the file offset, and the file offset is +incremented by the number of bytes written. See .BR write (2) -for more details. +for more details. Note that for an async API, reading and updating the +current file offset may result in unpredictable behavior, unless access +to the file is serialized. It is not encouraged to use this feature, if it's +possible to provide the desired IO offset from the application or library. On files that are not capable of seeking, the offset is ignored. diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index 4a994d0..712c4ba 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -20,7 +20,8 @@ io_uring_prep_writev2 - prepare vector I/O write request with flags .PP .SH DESCRIPTION .PP -The io_uring_prep_writev2() prepares a vectored IO write request. The submission queue entry +The io_uring_prep_writev2() prepares a vectored IO write request. The +submission queue entry .I sqe is setup to use the file descriptor .I fd @@ -48,7 +49,9 @@ per-IO O_DSYNC per-IO O_SYNC .TP .B RWF_NOWAIT -per-IO, return -EAGAIN if operation would block +per-IO, return +.B -EAGAIN +if operation would block .TP .B RWF_APPEND per-IO O_APPEND @@ -59,7 +62,10 @@ On files that support seeking, if the offset is set to the write operation commences at the file offset, and the file offset is incremented by the number of bytes written. See .BR write (2) -for more details. +for more details. Note that for an async API, reading and updating the +current file offset may result in unpredictable behavior, unless access +to the file is serialized. It is not encouraged to use this feature, if it's +possible to provide the desired IO offset from the application or library. On files that are not capable of seeking, the offset is ignored. -- cgit v1.2.3 From 0044891891fff576fcf60143a3c70b30642d0f60 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 23 Feb 2022 16:07:58 -0700 Subject: man: ensure that -1 is always bold Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 13 +++++++++---- man/io_uring_register.2 | 19 +++++++++++++------ man/io_uring_setup.2 | 12 +++++++++--- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 74df569..192b76b 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -780,7 +780,9 @@ does not refer to a seekable file, .I off must be set to zero. If .I offs -is set to -1, the offset will use (and advance) the file position, like the +is set to +.B -1 +, the offset will use (and advance) the file position, like the .BR read(2) and .BR write(2) @@ -806,8 +808,9 @@ is an offset to read from, .I fd is the file descriptor to write to, .I off -is an offset from which to start writing to. A sentinel value of -1 is used -to pass the equivalent of a NULL for the offsets to +is an offset from which to start writing to. A sentinel value of +.B -1 +is used to pass the equivalent of a NULL for the offsets to .BR splice(2). .I len contains the number of bytes to copy. @@ -1266,7 +1269,9 @@ completion queue entry (see section rather than through the system call itself. Errors that occur not on behalf of a submission queue entry are returned via the -system call directly. On such an error, -1 is returned and +system call directly. On such an error, +.B -1 +is returned and .I errno is set appropriately. .PP diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index 887567f..2072cb2 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -265,9 +265,11 @@ Available since 5.13. .TP .B IORING_REGISTER_FILES_UPDATE This operation replaces existing files in the registered file set with new -ones, either turning a sparse entry (one where fd is equal to -1) into a -real one, removing an existing entry (new one is set to -1), or replacing -an existing entry with a new existing entry. +ones, either turning a sparse entry (one where fd is equal to +.B -1 +) into a real one, removing an existing entry (new one is set to +.B -1 +), or replacing an existing entry with a new existing entry. .I arg must contain a pointer to a @@ -288,8 +290,11 @@ fd at that index. Available since 5.12. .B IORING_REGISTER_FILES_UPDATE2 Similar to IORING_REGISTER_FILES_UPDATE, replaces existing files in the registered file set with new ones, either turning a sparse entry (one where -fd is equal to -1) into a real one, removing an existing entry (new one is -set to -1), or replacing an existing entry with a new existing entry. +fd is equal to +.B -1 +) into a real one, removing an existing entry (new one is set to +.B -1 +), or replacing an existing entry with a new existing entry. .I arg must contain a pointer to a @@ -496,7 +501,9 @@ Available since 5.15. On success, .BR io_uring_register () -returns 0. On error, -1 is returned, and +returns 0. On error, +.B -1 +is returned, and .I errno is set accordingly. diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index d527a6a..897db6e 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -224,7 +224,9 @@ since kernel 5.5. .B IORING_FEAT_RW_CUR_POS If this flag is set, applications can specify .I offset -== -1 with +== +.B -1 +with .B IORING_OP_{READV,WRITEV} , .B IORING_OP_{READ,WRITE}_FIXED @@ -236,7 +238,9 @@ and .I pwritev2(2) with .I offset -== -1. It'll use (and update) the current file position. This obviously comes +== +.B -1. +It'll use (and update) the current file position. This obviously comes with the caveat that if the application has multiple reads or writes in flight, then the end result will not be as expected. This is similar to threads sharing a file descriptor and doing IO using the current file position. Available since @@ -470,7 +474,9 @@ or .BR io_uring_enter (2) system calls. -On error, -1 is returned and +On error, +.B -1 +is returned and .I errno is set appropriately. .PP -- cgit v1.2.3 From 8be8af4afcb4909104caea5d180dff3bed45a19e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 23 Feb 2022 16:28:09 -0700 Subject: queue: provide io_uring_get_sqe() symbol again With a recent change, io_uring_get_sqe() was moved to the header file to avoid a function call for this hot function. However, this will break updates of the library, where the symbol is then not provided: ./app: symbol lookup error: ./app: undefined symbol: io_uring_get_sqe, version LIBURING_2.0 Provide one internally so we still export it, but allow newly compiled applications to grab the one from the header. That should provide the best of both worlds. Fixes: 6cf23f9a6470 ("Move io_uring_get_sqe() inline in the liburing.h header") Signed-off-by: Jens Axboe --- src/Makefile | 2 +- src/include/liburing.h | 4 ++++ src/queue.c | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index c29a80d..cc6c871 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ CPPFLAGS ?= override CPPFLAGS += -D_GNU_SOURCE \ -Iinclude/ -include ../config-host.h CFLAGS ?= -g -fomit-frame-pointer -O2 -Wall -Wextra -override CFLAGS += -Wno-unused-parameter -Wno-sign-compare +override CFLAGS += -Wno-unused-parameter -Wno-sign-compare -DLIBURING_INTERNAL SO_CFLAGS=-fPIC $(CFLAGS) L_CFLAGS=$(CFLAGS) LINK_FLAGS= diff --git a/src/include/liburing.h b/src/include/liburing.h index 3cf314d..590fe7f 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -831,6 +831,7 @@ static inline int io_uring_wait_cqe(struct io_uring *ring, * * Returns a vacant sqe, or NULL if we're full. */ +#ifndef LIBURING_INTERNAL static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) { struct io_uring_sq *sq = &ring->sq; @@ -844,6 +845,9 @@ static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) } return sqe; } +#else +struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); +#endif ssize_t io_uring_mlock_size(unsigned entries, unsigned flags); ssize_t io_uring_mlock_size_params(unsigned entries, struct io_uring_params *p); diff --git a/src/queue.c b/src/queue.c index e5fd983..6b63490 100644 --- a/src/queue.c +++ b/src/queue.c @@ -403,6 +403,20 @@ int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr) return __io_uring_submit_and_wait(ring, wait_nr); } +struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) +{ + struct io_uring_sq *sq = &ring->sq; + unsigned int head = io_uring_smp_load_acquire(sq->khead); + unsigned int next = sq->sqe_tail + 1; + struct io_uring_sqe *sqe = NULL; + + if (next - head <= *sq->kring_entries) { + sqe = &sq->sqes[sq->sqe_tail & *sq->kring_mask]; + sq->sqe_tail = next; + } + return sqe; +} + int __io_uring_sqring_wait(struct io_uring *ring) { return ____sys_io_uring_enter(ring->ring_fd, 0, 0, -- cgit v1.2.3 From 57352019dd1faa77c2c3b6bf689217207d649560 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Tue, 22 Feb 2022 02:57:12 -0800 Subject: Test consistent file position updates read(2)/write(2) and friends support sequential reads without giving an explicit offset. The result of these should leave the file with an incremented offset. Add tests for both read and write to check that io_uring behaves consistently in these scenarios. Expect that if you queue many reads/writes, and set the IOSQE_IO_LINK flag, that they will behave similarly to calling read(2)/write(2) in sequence. Set IOSQE_ASYNC as well in a set of tests. This exacerbates the problem by forcing work to happen in different threads to submission. Also add tests for not setting IOSQE_IO_LINK, but allow the file offset to progress past the end of the file. Signed-off-by: Dylan Yudaken Signed-off-by: Jens Axboe --- test/Makefile | 1 + test/fpos.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+) create mode 100644 test/fpos.c diff --git a/test/Makefile b/test/Makefile index 1e318f7..f421f53 100644 --- a/test/Makefile +++ b/test/Makefile @@ -78,6 +78,7 @@ test_srcs := \ file-update.c \ file-verify.c \ fixed-link.c \ + fpos.c \ fsync.c \ hardlink.c \ io-cancel.c \ diff --git a/test/fpos.c b/test/fpos.c new file mode 100644 index 0000000..40df613 --- /dev/null +++ b/test/fpos.c @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: test io_uring fpos handling + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "liburing.h" + +#define FILE_SIZE 5000 +#define QUEUE_SIZE 2048 + +static void create_file(const char *file, size_t size) +{ + ssize_t ret; + char *buf; + size_t idx; + int fd; + + buf = t_malloc(size); + for (idx = 0; idx < size; ++idx) { + /* write 0 or 1 */ + buf[idx] = (unsigned char)(idx & 0x01); + } + + fd = open(file, O_WRONLY | O_CREAT, 0644); + assert(fd >= 0); + + ret = write(fd, buf, size); + fsync(fd); + close(fd); + free(buf); + assert(ret == size); +} + +static int test_read(struct io_uring *ring, bool async, bool link, + int blocksize) +{ + int ret, fd, i; + bool done = false; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + loff_t current, expected = 0; + int count_ok; + int count_0 = 0, count_1 = 0; + unsigned char buff[QUEUE_SIZE * blocksize]; + unsigned char reordered[QUEUE_SIZE * blocksize]; + + create_file(".test_fpos_read", FILE_SIZE); + fd = open(".test_fpos_read", O_RDONLY); + unlink(".test_fpos_read"); + assert(fd >= 0); + + while (!done) { + for (i = 0; i < QUEUE_SIZE; ++i) { + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "no sqe\n"); + return -1; + } + io_uring_prep_read(sqe, fd, + buff + i * blocksize, + blocksize, -1); + sqe->user_data = i; + if (async) + sqe->flags |= IOSQE_ASYNC; + if (link && i != QUEUE_SIZE - 1) + sqe->flags |= IOSQE_IO_LINK; + } + ret = io_uring_submit_and_wait(ring, QUEUE_SIZE); + if (ret != QUEUE_SIZE) { + fprintf(stderr, "submit failed: %d\n", ret); + return 1; + } + count_ok = 0; + for (i = 0; i < QUEUE_SIZE; ++i) { + int res; + + ret = io_uring_peek_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "peek failed: %d\n", ret); + return ret; + } + assert(cqe->user_data < QUEUE_SIZE); + memcpy(reordered + count_ok, + buff + cqe->user_data * blocksize, blocksize); + res = cqe->res; + io_uring_cqe_seen(ring, cqe); + if (res == 0) { + done = true; + } else if (res == -ECANCELED) { + /* cancelled, probably ok */ + } else if (res < 0 || res > blocksize) { + fprintf(stderr, "bad read: %d\n", res); + return -1; + } else { + expected += res; + count_ok += res; + } + } + ret = 0; + for (i = 0; i < count_ok; i++) { + if (reordered[i] == 1) { + count_1++; + } else if (reordered[i] == 0) { + count_0++; + } else { + fprintf(stderr, "odd read %d\n", + (int)reordered[i]); + ret = -1; + break; + } + } + if (labs(count_1 - count_0) > 1) { + fprintf(stderr, "inconsistent reads, got 0s:%d 1s:%d\n", + count_0, count_1); + ret = -1; + } + current = lseek(fd, 0, SEEK_CUR); + if (current < expected || (current != expected && link)) { + /* accept that with !link current may be > expected */ + fprintf(stderr, "f_pos incorrect, expected %ld have %ld\n", + expected, current); + ret = -1; + } + if (ret) + return ret; + } + return 0; +} + + +static int test_write(struct io_uring *ring, bool async, + bool link, int blocksize) +{ + int ret, fd, i; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + bool fail = false; + loff_t current; + char data[blocksize+1]; + char readbuff[QUEUE_SIZE*blocksize+1]; + + fd = open(".test_fpos_write", O_RDWR | O_CREAT, 0644); + unlink(".test_fpos_write"); + assert(fd >= 0); + + for (i = 0; i < blocksize; i++) + data[i] = 'A' + i; + + data[blocksize] = '\0'; + + for (i = 0; i < QUEUE_SIZE; ++i) { + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "no sqe\n"); + return -1; + } + io_uring_prep_write(sqe, fd, data + (i % blocksize), 1, -1); + sqe->user_data = 1; + if (async) + sqe->flags |= IOSQE_ASYNC; + if (link && i != QUEUE_SIZE - 1) + sqe->flags |= IOSQE_IO_LINK; + } + ret = io_uring_submit_and_wait(ring, QUEUE_SIZE); + if (ret != QUEUE_SIZE) { + fprintf(stderr, "submit failed: %d\n", ret); + return 1; + } + for (i = 0; i < QUEUE_SIZE; ++i) { + int res; + + ret = io_uring_peek_cqe(ring, &cqe); + res = cqe->res; + if (ret) { + fprintf(stderr, "peek failed: %d\n", ret); + return ret; + } + io_uring_cqe_seen(ring, cqe); + if (!fail && res != 1) { + fprintf(stderr, "bad result %d\n", res); + fail = true; + } + } + current = lseek(fd, 0, SEEK_CUR); + if (current != QUEUE_SIZE) { + fprintf(stderr, "f_pos incorrect, expected %ld have %d\n", + current, QUEUE_SIZE); + fail = true; + } + current = lseek(fd, 0, SEEK_SET); + if (current != 0) { + perror("seek to start"); + return -1; + } + ret = read(fd, readbuff, QUEUE_SIZE); + if (ret != QUEUE_SIZE) { + fprintf(stderr, "did not write enough: %d\n", ret); + return -1; + } + i = 0; + while (i < QUEUE_SIZE - blocksize) { + if (strncmp(readbuff + i, data, blocksize)) { + char bad[QUEUE_SIZE+1]; + + memcpy(bad, readbuff + i, blocksize); + bad[blocksize] = '\0'; + fprintf(stderr, "unexpected data %s\n", bad); + fail = true; + } + i += blocksize; + } + + return fail ? -1 : 0; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + int ret; + + if (argc > 1) + return 0; + + ret = io_uring_queue_init(QUEUE_SIZE, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed\n"); + return 1; + } + + for (int test = 0; test < 16; test++) { + int async = test & 0x01; + int link = test & 0x02; + int write = test & 0x04; + int blocksize = test & 0x08 ? 1 : 7; + + ret = write + ? test_write(&ring, !!async, !!link, blocksize) + : test_read(&ring, !!async, !!link, blocksize); + if (ret) { + fprintf(stderr, "failed %s async=%d link=%d blocksize=%d\n", + write ? "write" : "read", + async, link, blocksize); + return -1; + } + } + return 0; +} -- cgit v1.2.3 From 8a2e43dad6475cfcecf91d79e3c4ed58bb5298e1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 23 Feb 2022 16:50:44 -0700 Subject: test/fpos: fix for 32-bit compiles Fixes: 57352019dd1f ("Test consistent file position updates") Signed-off-by: Jens Axboe --- test/fpos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fpos.c b/test/fpos.c index 40df613..385db63 100644 --- a/test/fpos.c +++ b/test/fpos.c @@ -127,7 +127,7 @@ static int test_read(struct io_uring *ring, bool async, bool link, if (current < expected || (current != expected && link)) { /* accept that with !link current may be > expected */ fprintf(stderr, "f_pos incorrect, expected %ld have %ld\n", - expected, current); + (long) expected, (long) current); ret = -1; } if (ret) @@ -193,7 +193,7 @@ static int test_write(struct io_uring *ring, bool async, current = lseek(fd, 0, SEEK_CUR); if (current != QUEUE_SIZE) { fprintf(stderr, "f_pos incorrect, expected %ld have %d\n", - current, QUEUE_SIZE); + (long) current, QUEUE_SIZE); fail = true; } current = lseek(fd, 0, SEEK_SET); -- cgit v1.2.3 From 896a1d3ab14a8777a45db6e7b67cf557a44923fb Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Thu, 24 Feb 2022 02:50:15 -0800 Subject: Remove fpos tests without linking There are still more discussions ([1]) to see how to have consistent r/w results without link, so do not test these cases. [1] https://lore.kernel.org/io-uring/568473ab-8cf7-8488-8252-e8a2c0ec586f@kernel.dk Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220224105015.1324208-1-dylany@fb.com Signed-off-by: Jens Axboe --- test/fpos.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/test/fpos.c b/test/fpos.c index 385db63..78a6152 100644 --- a/test/fpos.c +++ b/test/fpos.c @@ -40,8 +40,7 @@ static void create_file(const char *file, size_t size) assert(ret == size); } -static int test_read(struct io_uring *ring, bool async, bool link, - int blocksize) +static int test_read(struct io_uring *ring, bool async, int blocksize) { int ret, fd, i; bool done = false; @@ -71,7 +70,7 @@ static int test_read(struct io_uring *ring, bool async, bool link, sqe->user_data = i; if (async) sqe->flags |= IOSQE_ASYNC; - if (link && i != QUEUE_SIZE - 1) + if (i != QUEUE_SIZE - 1) sqe->flags |= IOSQE_IO_LINK; } ret = io_uring_submit_and_wait(ring, QUEUE_SIZE); @@ -124,8 +123,7 @@ static int test_read(struct io_uring *ring, bool async, bool link, ret = -1; } current = lseek(fd, 0, SEEK_CUR); - if (current < expected || (current != expected && link)) { - /* accept that with !link current may be > expected */ + if (current != expected) { fprintf(stderr, "f_pos incorrect, expected %ld have %ld\n", (long) expected, (long) current); ret = -1; @@ -137,8 +135,7 @@ static int test_read(struct io_uring *ring, bool async, bool link, } -static int test_write(struct io_uring *ring, bool async, - bool link, int blocksize) +static int test_write(struct io_uring *ring, bool async, int blocksize) { int ret, fd, i; struct io_uring_sqe *sqe; @@ -167,7 +164,7 @@ static int test_write(struct io_uring *ring, bool async, sqe->user_data = 1; if (async) sqe->flags |= IOSQE_ASYNC; - if (link && i != QUEUE_SIZE - 1) + if (i != QUEUE_SIZE - 1) sqe->flags |= IOSQE_IO_LINK; } ret = io_uring_submit_and_wait(ring, QUEUE_SIZE); @@ -236,19 +233,18 @@ int main(int argc, char *argv[]) return 1; } - for (int test = 0; test < 16; test++) { + for (int test = 0; test < 8; test++) { int async = test & 0x01; - int link = test & 0x02; - int write = test & 0x04; - int blocksize = test & 0x08 ? 1 : 7; + int write = test & 0x02; + int blocksize = test & 0x04 ? 1 : 7; ret = write - ? test_write(&ring, !!async, !!link, blocksize) - : test_read(&ring, !!async, !!link, blocksize); + ? test_write(&ring, !!async, blocksize) + : test_read(&ring, !!async, blocksize); if (ret) { - fprintf(stderr, "failed %s async=%d link=%d blocksize=%d\n", + fprintf(stderr, "failed %s async=%d blocksize=%d\n", write ? "write" : "read", - async, link, blocksize); + async, blocksize); return -1; } } -- cgit v1.2.3 From 15c01fcd1b0d37a12d945ab8dcdf96b3e055a4fd Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 25 Feb 2022 07:58:14 +0700 Subject: queue, liburing.h: Avoid `io_uring_get_sqe()` code duplication Since commit 8be8af4afcb4909104c ("queue: provide io_uring_get_sqe() symbol again"), we have the same definition of `io_uring_get_sqe()` in queue.c and liburing.h. Make it simpler, maintain it in a single place, create a new static inline function wrapper with name `_io_uring_get_sqe()`. Then tail call both `io_uring_get_sqe()` functions to `_io_uring_get_sqe()`. Cc: Nugra Cc: Alviro Iskandar Setiawan Cc: GNU/Weeb Mailing List Cc: Tea Inside Mailing List Cc: io-uring Mailing List Link: https://lore.kernel.org/io-uring/20220225002852.111521-1-ammarfaizi2@gnuweeb.org # v1 Reviewed-by: Alviro Iskandar Setiawan Tested-by: Alviro Iskandar Setiawan Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220225005814.146492-1-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- src/include/liburing.h | 9 +++++++-- src/queue.c | 11 +---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 590fe7f..ef5a4cd 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -831,8 +831,7 @@ static inline int io_uring_wait_cqe(struct io_uring *ring, * * Returns a vacant sqe, or NULL if we're full. */ -#ifndef LIBURING_INTERNAL -static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) +static inline struct io_uring_sqe *_io_uring_get_sqe(struct io_uring *ring) { struct io_uring_sq *sq = &ring->sq; unsigned int head = io_uring_smp_load_acquire(sq->khead); @@ -845,6 +844,12 @@ static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) } return sqe; } + +#ifndef LIBURING_INTERNAL +static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) +{ + return _io_uring_get_sqe(ring); +} #else struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); #endif diff --git a/src/queue.c b/src/queue.c index 6b63490..f9b6c86 100644 --- a/src/queue.c +++ b/src/queue.c @@ -405,16 +405,7 @@ int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr) struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) { - struct io_uring_sq *sq = &ring->sq; - unsigned int head = io_uring_smp_load_acquire(sq->khead); - unsigned int next = sq->sqe_tail + 1; - struct io_uring_sqe *sqe = NULL; - - if (next - head <= *sq->kring_entries) { - sqe = &sq->sqes[sq->sqe_tail & *sq->kring_mask]; - sq->sqe_tail = next; - } - return sqe; + return _io_uring_get_sqe(ring); } int __io_uring_sqring_wait(struct io_uring *ring) -- cgit v1.2.3 From ac154c44e8c2d5b23017111dc44b419068c1ae34 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 25 Feb 2022 08:14:36 +0700 Subject: .gitignore: Add `/test/fpos` to .gitignore Dylan forgot to add it to .gitignore when creating this test. Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220225011436.147898-1-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 15559ab..c9dc77f 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ /test/files-exit-hang-poll /test/files-exit-hang-timeout /test/fixed-link +/test/fpos /test/fsync /test/hardlink /test/io-cancel -- cgit v1.2.3 From 2de98320d5b02951936fc0ab677dd01e4fb2a7a7 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 25 Feb 2022 05:24:27 +0700 Subject: src/Makefile: Don't use stack protector for all builds by default Stack protector adds extra mov, extra stack allocation and extra branch to save and validate the stack canary. While this feature could be useful to detect stack corruption in some scenarios, it is not really needed for liburing which is simple enough to review. Good code shouldn't corrupt the stack. We don't need this extra checking at the moment. Just for comparison, let's take a hot function __io_uring_get_cqe. Before this patch: ``` 0000000000002b80 <__io_uring_get_cqe>: 2b80: f3 0f 1e fa endbr64 2b84: 48 83 ec 28 sub $0x28,%rsp 2b88: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 2b8f: 00 00 2b91: 48 89 44 24 18 mov %rax,0x18(%rsp) 2b96: 31 c0 xor %eax,%eax 2b98: 89 14 24 mov %edx,(%rsp) 2b9b: 48 89 e2 mov %rsp,%rdx 2b9e: 48 b8 00 00 00 00 08 movabs $0x800000000,%rax 2ba5: 00 00 00 2ba8: 89 4c 24 04 mov %ecx,0x4(%rsp) 2bac: 48 89 44 24 08 mov %rax,0x8(%rsp) 2bb1: 4c 89 44 24 10 mov %r8,0x10(%rsp) 2bb6: e8 45 fe ff ff call 2a00 <_io_uring_get_cqe> 2bbb: 48 8b 54 24 18 mov 0x18(%rsp),%rdx 2bc0: 64 48 2b 14 25 28 00 sub %fs:0x28,%rdx 2bc7: 00 00 2bc9: 75 05 jne 2bd0 <__io_uring_get_cqe+0x50> 2bcb: 48 83 c4 28 add $0x28,%rsp 2bcf: c3 ret 2bd0: e8 9b f5 ff ff call 2170 <__stack_chk_fail@plt> 2bd5: 66 66 2e 0f 1f 84 00 data16 cs nopw 0x0(%rax,%rax,1) 2bdc: 00 00 00 00 ``` After this patch: ``` 0000000000002ab0 <__io_uring_get_cqe>: 2ab0: f3 0f 1e fa endbr64 2ab4: 48 b8 00 00 00 00 08 movabs $0x800000000,%rax 2abb: 00 00 00 2abe: 48 83 ec 28 sub $0x28,%rsp 2ac2: 89 14 24 mov %edx,(%rsp) 2ac5: 48 89 e2 mov %rsp,%rdx 2ac8: 89 4c 24 04 mov %ecx,0x4(%rsp) 2acc: 48 89 44 24 08 mov %rax,0x8(%rsp) 2ad1: 4c 89 44 24 10 mov %r8,0x10(%rsp) 2ad6: e8 55 fe ff ff call 2930 <_io_uring_get_cqe> 2adb: 48 83 c4 28 add $0x28,%rsp 2adf: c3 ret ``` Previously, we only use `-fno-stack-protector` for nolibc build as the stack protector needs to call `__stack_chk_fail@plt` function from the libc. Now, we always use `-fno-stack-protector` for both nolibc and libc builds to generate shorter Assembly code. Cc: Nugra Cc: Alviro Iskandar Setiawan Cc: GNU/Weeb Mailing List Cc: Tea Inside Mailing List Cc: io-uring Mailing List Signed-off-by: Ammar Faizi Reviewed-by: Alviro Iskandar Setiawan Link: https://lore.kernel.org/r/20220224222427.66206-1-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- src/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index cc6c871..3e1192f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,7 +8,7 @@ libdevdir ?= $(prefix)/lib CPPFLAGS ?= override CPPFLAGS += -D_GNU_SOURCE \ -Iinclude/ -include ../config-host.h -CFLAGS ?= -g -fomit-frame-pointer -O2 -Wall -Wextra +CFLAGS ?= -g -fomit-frame-pointer -O2 -Wall -Wextra -fno-stack-protector override CFLAGS += -Wno-unused-parameter -Wno-sign-compare -DLIBURING_INTERNAL SO_CFLAGS=-fPIC $(CFLAGS) L_CFLAGS=$(CFLAGS) @@ -36,8 +36,8 @@ liburing_srcs := setup.c queue.c register.c ifeq ($(CONFIG_NOLIBC),y) liburing_srcs += nolibc.c - override CFLAGS += -nostdlib -nodefaultlibs -ffreestanding -fno-stack-protector - override CPPFLAGS += -nostdlib -nodefaultlibs -ffreestanding -fno-stack-protector + override CFLAGS += -nostdlib -nodefaultlibs -ffreestanding + override CPPFLAGS += -nostdlib -nodefaultlibs -ffreestanding override LINK_FLAGS += -nostdlib -nodefaultlibs else liburing_srcs += syscall.c -- cgit v1.2.3 From 744f4156b25d8630fee279cfd852ecc4c73952d4 Mon Sep 17 00:00:00 2001 From: Almog Khaikin Date: Sat, 5 Mar 2022 18:59:07 +0200 Subject: Fix memory ordering in sq_ring_needs_enter A full memory barrier is required between the store to the SQ tail in __io_uring_flush_sq and the load of the flags in sq_ring_needs_enter to prevent a situation where the kernel thread goes to sleep while sq_ring_needs_enter returns false Fixes: https://github.com/axboe/liburing/issues/541 Signed-off-by: Almog Khaikin --- src/include/liburing/barrier.h | 8 ++++++++ src/queue.c | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/include/liburing/barrier.h b/src/include/liburing/barrier.h index 89ac682..aedeb47 100644 --- a/src/include/liburing/barrier.h +++ b/src/include/liburing/barrier.h @@ -52,6 +52,11 @@ static inline T io_uring_smp_load_acquire(const T *p) reinterpret_cast *>(p), std::memory_order_acquire); } + +static inline void io_uring_smp_mb() +{ + std::atomic_thread_fence(std::memory_order_seq_cst); +} #else #include @@ -68,6 +73,9 @@ static inline T io_uring_smp_load_acquire(const T *p) #define io_uring_smp_load_acquire(p) \ atomic_load_explicit((_Atomic __typeof__(*(p)) *)(p), \ memory_order_acquire) + +#define io_uring_smp_mb() \ + atomic_thread_fence(memory_order_seq_cst) #endif #endif /* defined(LIBURING_BARRIER_H) */ diff --git a/src/queue.c b/src/queue.c index f9b6c86..f5ff5a5 100644 --- a/src/queue.c +++ b/src/queue.c @@ -17,6 +17,12 @@ static inline bool sq_ring_needs_enter(struct io_uring *ring, unsigned *flags) if (!(ring->flags & IORING_SETUP_SQPOLL)) return true; + /* + * Ensure the kernel can see the store to the SQ tail before we read + * the flags. + */ + io_uring_smp_mb(); + if (uring_unlikely(IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_NEED_WAKEUP)) { *flags |= IORING_ENTER_SQ_WAKEUP; -- cgit v1.2.3 From 6231f56da7881bde6fb011e1b54d672f8fe5a224 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 5 Mar 2022 15:47:26 -0700 Subject: src/queue: don't keep looping for IOPOLL peek operation A previous commit broke peek with an IOPOLL ring, making it loop continually even if we have wait_for == 0 and submit == 0. It's only necessary to enter the kernel for that condition once, don't keep looping trying to poll for zero events. Fixes: 333561791386 ("Fix __io_uring_get_cqe() for IORING_SETUP_IOPOLL") Signed-off-by: Jens Axboe --- src/queue.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/queue.c b/src/queue.c index f9b6c86..ef09eb5 100644 --- a/src/queue.c +++ b/src/queue.c @@ -85,6 +85,7 @@ static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_pt struct get_data *data) { struct io_uring_cqe *cqe = NULL; + bool looped = false; int err; do { @@ -97,7 +98,12 @@ static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_pt if (err) break; if (!cqe && !data->wait_nr && !data->submit) { - if (!cq_ring_needs_enter(ring)) { + /* + * If we already looped once, we already entererd + * the kernel. Since there's nothing to submit or + * wait for, don't keep retrying. + */ + if (looped || !cq_ring_needs_enter(ring)) { err = -EAGAIN; break; } @@ -123,6 +129,7 @@ static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_pt data->submit -= ret; if (cqe) break; + looped = true; } while (1); *cqe_ptr = cqe; -- cgit v1.2.3 From da4480fcf69e26e3a3cfb4cadb0e30705abde119 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 4 Mar 2022 07:57:43 -0700 Subject: io_uring.h: sync with kernel for registered ring feature Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index a7d193d..5329ba8 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -261,10 +261,11 @@ struct io_cqring_offsets { /* * io_uring_enter(2) flags */ -#define IORING_ENTER_GETEVENTS (1U << 0) -#define IORING_ENTER_SQ_WAKEUP (1U << 1) -#define IORING_ENTER_SQ_WAIT (1U << 2) -#define IORING_ENTER_EXT_ARG (1U << 3) +#define IORING_ENTER_GETEVENTS (1U << 0) +#define IORING_ENTER_SQ_WAKEUP (1U << 1) +#define IORING_ENTER_SQ_WAIT (1U << 2) +#define IORING_ENTER_EXT_ARG (1U << 3) +#define IORING_ENTER_REGISTERED_RING (1U << 4) /* * Passed in for io_uring_setup(2). Copied back with updated info on success @@ -329,6 +330,10 @@ enum { /* set/get max number of io-wq workers */ IORING_REGISTER_IOWQ_MAX_WORKERS = 19, + /* register/unregister io_uring fd with the ring */ + IORING_REGISTER_RING_FDS = 20, + IORING_UNREGISTER_RING_FDS = 21, + /* this goes last */ IORING_REGISTER_LAST }; -- cgit v1.2.3 From b02125e164ea2604efbf443224fe5679ef0047c1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 4 Mar 2022 07:59:04 -0700 Subject: Add preliminary support for using a registered ring fd Add a specific ->enter_ring_fd member to the ring, and just set it to the normal ring fd at init time. Add an internal flag to track whether or not we're actually using a registered fd for the ring itself, and set the appropriate io_uring_enter(2) if so. Signed-off-by: Jens Axboe --- src/include/liburing.h | 5 ++++- src/int_flags.h | 8 ++++++++ src/queue.c | 26 +++++++++++++++++++------- src/setup.c | 3 ++- 4 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 src/int_flags.h diff --git a/src/include/liburing.h b/src/include/liburing.h index ef5a4cd..0799a50 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -76,7 +76,10 @@ struct io_uring { int ring_fd; unsigned features; - unsigned pad[3]; + int enter_ring_fd; + __u8 int_flags; + __u8 pad[3]; + unsigned pad2; }; /* diff --git a/src/int_flags.h b/src/int_flags.h new file mode 100644 index 0000000..b9270ae --- /dev/null +++ b/src/int_flags.h @@ -0,0 +1,8 @@ +#ifndef LIBURING_INT_FLAGS +#define LIBURING_INT_FLAGS + +enum { + INT_FLAG_REG_RING = 1, +}; + +#endif diff --git a/src/queue.c b/src/queue.c index ef09eb5..f17c024 100644 --- a/src/queue.c +++ b/src/queue.c @@ -4,6 +4,7 @@ #include "lib.h" #include "syscall.h" #include "liburing.h" +#include "int_flags.h" #include "liburing/compat.h" #include "liburing/io_uring.h" @@ -118,7 +119,9 @@ static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_pt if (!need_enter) break; - ret = ____sys_io_uring_enter2(ring->ring_fd, data->submit, + if (ring->int_flags & INT_FLAG_REG_RING) + flags |= IORING_ENTER_REGISTERED_RING; + ret = ____sys_io_uring_enter2(ring->enter_ring_fd, data->submit, data->wait_nr, flags, data->arg, data->sz); if (ret < 0) { @@ -180,8 +183,11 @@ again: goto done; if (cq_ring_needs_flush(ring)) { - ____sys_io_uring_enter(ring->ring_fd, 0, 0, - IORING_ENTER_GETEVENTS, NULL); + int flags = IORING_ENTER_GETEVENTS; + + if (ring->int_flags & INT_FLAG_REG_RING) + flags |= IORING_ENTER_REGISTERED_RING; + ____sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL); overflow_checked = true; goto again; } @@ -376,9 +382,11 @@ static int __io_uring_submit(struct io_uring *ring, unsigned submitted, if (sq_ring_needs_enter(ring, &flags) || wait_nr) { if (wait_nr || (ring->flags & IORING_SETUP_IOPOLL)) flags |= IORING_ENTER_GETEVENTS; + if (ring->int_flags & INT_FLAG_REG_RING) + flags |= IORING_ENTER_REGISTERED_RING; - ret = ____sys_io_uring_enter(ring->ring_fd, submitted, wait_nr, - flags, NULL); + ret = ____sys_io_uring_enter(ring->enter_ring_fd, submitted, + wait_nr, flags, NULL); } else ret = submitted; @@ -417,6 +425,10 @@ struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) int __io_uring_sqring_wait(struct io_uring *ring) { - return ____sys_io_uring_enter(ring->ring_fd, 0, 0, - IORING_ENTER_SQ_WAIT, NULL); + int flags = IORING_ENTER_SQ_WAIT; + + if (ring->int_flags & INT_FLAG_REG_RING) + flags |= IORING_ENTER_REGISTERED_RING; + + return ____sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL); } diff --git a/src/setup.c b/src/setup.c index 544adaf..12a1cd5 100644 --- a/src/setup.c +++ b/src/setup.c @@ -91,7 +91,8 @@ int io_uring_queue_mmap(int fd, struct io_uring_params *p, struct io_uring *ring ret = io_uring_mmap(fd, p, &ring->sq, &ring->cq); if (!ret) { ring->flags = p->flags; - ring->ring_fd = fd; + ring->ring_fd = ring->enter_ring_fd = fd; + ring->int_flags = 0; } return ret; } -- cgit v1.2.3 From bbcc0e06b47a2aab828e57e67cd3d592293097fb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 4 Mar 2022 08:03:20 -0700 Subject: Add ring fd registration helpers These just handle registering the ring itself, while the kernel API does allow registering multiple ring fds at the same time.Add ring fd registration helpers These just handle registering the ring itself, while the kernel API does allow registering multiple ring fds at the same time. Signed-off-by: Jens Axboe --- src/include/liburing.h | 2 ++ src/register.c | 34 ++++++++++++++++++++++++++++++++++ src/setup.c | 7 +++++++ 3 files changed, 43 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 0799a50..88418dc 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -170,6 +170,8 @@ int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, int io_uring_unregister_iowq_aff(struct io_uring *ring); int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *values); +int io_uring_register_ring_fd(struct io_uring *ring); +int io_uring_unregister_ring_fd(struct io_uring *ring); /* * Helper for the peek/wait single cqe functions. Exported because of that, diff --git a/src/register.c b/src/register.c index cd73fce..1b96c77 100644 --- a/src/register.c +++ b/src/register.c @@ -4,6 +4,7 @@ #include "lib.h" #include "syscall.h" #include "liburing.h" +#include "int_flags.h" #include "liburing/compat.h" #include "liburing/io_uring.h" @@ -257,3 +258,36 @@ int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *val) IORING_REGISTER_IOWQ_MAX_WORKERS, val, 2); } + +int io_uring_register_ring_fd(struct io_uring *ring) +{ + struct io_uring_rsrc_update up = { + .data = ring->ring_fd, + .offset = -1U, + }; + int ret; + + ret = ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_RING_FDS, + &up, 1); + if (ret == 1) { + ring->enter_ring_fd = up.offset; + ring->int_flags |= INT_FLAG_REG_RING; + } + return ret; +} + +int io_uring_unregister_ring_fd(struct io_uring *ring) +{ + struct io_uring_rsrc_update up = { + .offset = ring->enter_ring_fd, + }; + int ret; + + ret = ____sys_io_uring_register(ring->ring_fd, + IORING_UNREGISTER_RING_FDS, &up, 1); + if (ret == 1) { + ring->enter_ring_fd = ring->ring_fd; + ring->int_flags &= ~INT_FLAG_REG_RING; + } + return ret; +} diff --git a/src/setup.c b/src/setup.c index 12a1cd5..5529784 100644 --- a/src/setup.c +++ b/src/setup.c @@ -4,6 +4,7 @@ #include "lib.h" #include "syscall.h" #include "liburing.h" +#include "int_flags.h" #include "liburing/compat.h" #include "liburing/io_uring.h" @@ -169,6 +170,12 @@ void io_uring_queue_exit(struct io_uring *ring) __sys_munmap(sq->sqes, *sq->kring_entries * sizeof(struct io_uring_sqe)); io_uring_unmap_rings(sq, cq); + /* + * Not strictly required, but frees up the slot we used now rather + * than at process exit time. + */ + if (ring->int_flags & INT_FLAG_REG_RING) + io_uring_unregister_ring_fd(ring); __sys_close(ring->ring_fd); } -- cgit v1.2.3 From 7887833a0d59939f513b74b58a5efb8e94a39342 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 4 Mar 2022 16:35:18 -0700 Subject: test/sq-poll-dup: modify ring fd hack to work with enter_ring_fd No application should be directly modifying the ring_fd, it's done just to test some internals. Make sure it works with the split of ring_fd and enter_ring_fd. Signed-off-by: Jens Axboe --- test/sq-poll-dup.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/sq-poll-dup.c b/test/sq-poll-dup.c index 9596866..0076a31 100644 --- a/test/sq-poll-dup.c +++ b/test/sq-poll-dup.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -29,9 +28,14 @@ static struct io_uring rings[NR_RINGS]; static int wait_io(struct io_uring *ring, int nr_ios) { struct io_uring_cqe *cqe; + int ret; while (nr_ios) { - io_uring_wait_cqe(ring, &cqe); + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "wait_ret=%d\n", ret); + return 1; + } if (cqe->res != BS) { fprintf(stderr, "Unexpected ret %d\n", cqe->res); return 1; @@ -123,7 +127,7 @@ static int test(int fd, int do_dup_and_close, int close_ring) ring_fd = dup(rings[0].ring_fd); if (close_ring) close(rings[0].ring_fd); - rings[0].ring_fd = ring_fd; + rings[0].ring_fd = rings[0].enter_ring_fd = ring_fd; if (do_dup_and_close) goto done; -- cgit v1.2.3 From de214792d38700ba470a560cf3729a9bd62acb35 Mon Sep 17 00:00:00 2001 From: Alviro Iskandar Setiawan Date: Thu, 10 Mar 2022 11:12:28 +0000 Subject: src/Makefile: Remove `-fomit-frame-pointer` from default build -fomit-frame-pointer is already turned on by -O1 optimization flag. The liburing default compilation uses -O2 optimization, -O2 turns on all optimization flags specified by -O1. Therefore, we don't need to specify -fomit-frame-pointer here. Remove it. Link: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html Signed-off-by: Alviro Iskandar Setiawan Link: https://lore.kernel.org/r/20220310111231.1713588-2-alviro.iskandar@gnuweeb.org Signed-off-by: Jens Axboe --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 3e1192f..f19d45e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,7 +8,7 @@ libdevdir ?= $(prefix)/lib CPPFLAGS ?= override CPPFLAGS += -D_GNU_SOURCE \ -Iinclude/ -include ../config-host.h -CFLAGS ?= -g -fomit-frame-pointer -O2 -Wall -Wextra -fno-stack-protector +CFLAGS ?= -g -O2 -Wall -Wextra -fno-stack-protector override CFLAGS += -Wno-unused-parameter -Wno-sign-compare -DLIBURING_INTERNAL SO_CFLAGS=-fPIC $(CFLAGS) L_CFLAGS=$(CFLAGS) -- cgit v1.2.3 From 9ea9df11bbdbbf3bceae38679dd175b092950142 Mon Sep 17 00:00:00 2001 From: Alviro Iskandar Setiawan Date: Thu, 10 Mar 2022 11:12:29 +0000 Subject: src/Makefile: Add header files as dependency When the header files are modified, the compiled objects are not going to be recompiled because the header files are not marked as a dependency for the objects. - Instruct the compiler to generate dependency files. - Include those files from src/Makefile. Ensure if any changes are made, files that depend on the changes are recompiled. Suggested-by: Ammar Faizi Signed-off-by: Alviro Iskandar Setiawan Link: https://lore.kernel.org/r/20220310111231.1713588-3-alviro.iskandar@gnuweeb.org Signed-off-by: Jens Axboe --- .gitignore | 1 + src/Makefile | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index c9dc77f..9b74880 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *~ /*.patch +*.d *.o *.o[ls] diff --git a/src/Makefile b/src/Makefile index f19d45e..0e04986 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,19 +43,20 @@ else liburing_srcs += syscall.c endif +override CPPFLAGS += -MT "$@" -MMD -MP -MF "$@.d" liburing_objs := $(patsubst %.c,%.ol,$(liburing_srcs)) liburing_sobjs := $(patsubst %.c,%.os,$(liburing_srcs)) -$(liburing_srcs): syscall.h lib.h - -$(liburing_objs) $(liburing_sobjs): include/liburing/io_uring.h - %.os: %.c $(QUIET_CC)$(CC) $(CPPFLAGS) $(SO_CFLAGS) -c -o $@ $< %.ol: %.c $(QUIET_CC)$(CC) $(CPPFLAGS) $(L_CFLAGS) -c -o $@ $< +# Include compiler generated dependency files. +-include $(liburing_objs:%=%.d) +-include $(liburing_sobjs:%=%.d) + AR ?= ar RANLIB ?= ranlib liburing.a: $(liburing_objs) @@ -78,11 +79,9 @@ ifeq ($(ENABLE_SHARED),1) ln -sf $(relativelibdir)$(libname) $(libdevdir)/liburing.so endif -$(liburing_objs): include/liburing.h - clean: @rm -f $(all_targets) $(liburing_objs) $(liburing_sobjs) $(soname).new - @rm -f *.so* *.a *.o + @rm -f *.so* *.a *.o *.d @rm -f include/liburing/compat.h @# When cleaning, we don't include ../config-host.mak, -- cgit v1.2.3 From b48d6af787c00fd4a8f3614f8c1a0443a3054eef Mon Sep 17 00:00:00 2001 From: Alviro Iskandar Setiawan Date: Thu, 10 Mar 2022 11:12:30 +0000 Subject: test/Makefile: Add liburing.a as a dependency The test binaries statically link liburing using liburing.a file. When liburing.a is recompiled, make sure the tests are also recompiled to ensure changes are applied to the test binary. It makes "make clean" command optional when making changes. Signed-off-by: Alviro Iskandar Setiawan Link: https://lore.kernel.org/r/20220310111231.1713588-4-alviro.iskandar@gnuweeb.org Signed-off-by: Jens Axboe --- test/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Makefile b/test/Makefile index f421f53..9dae002 100644 --- a/test/Makefile +++ b/test/Makefile @@ -196,10 +196,10 @@ all: $(test_targets) helpers.o: helpers.c $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< -%: %.c $(helpers) helpers.h +%: %.c $(helpers) helpers.h ../src/liburing.a $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(helpers) $(LDFLAGS) -%: %.cc $(helpers) helpers.h +%: %.cc $(helpers) helpers.h ../src/liburing.a $(QUIET_CXX)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< $(helpers) $(LDFLAGS) -- cgit v1.2.3 From 115cca320dd4df9293440d8e410bebb064822265 Mon Sep 17 00:00:00 2001 From: Alviro Iskandar Setiawan Date: Thu, 10 Mar 2022 11:12:31 +0000 Subject: examples/Makefile: Add liburing.a as a dependency The example binaries statically link liburing using liburing.a file. When liburing.a is recompiled, make sure the example binaries are also recompiled to ensure changes are applied to the binaries. It makes "make clean" command optional when making changes. Signed-off-by: Alviro Iskandar Setiawan Link: https://lore.kernel.org/r/20220310111231.1713588-5-alviro.iskandar@gnuweeb.org Signed-off-by: Jens Axboe --- examples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile b/examples/Makefile index f966f94..95a45f9 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -29,7 +29,7 @@ all_targets += $(example_targets) all: $(example_targets) -%: %.c +%: %.c ../src/liburing.a $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(LDFLAGS) clean: -- cgit v1.2.3 From 22718e636826a6ec6f2248433e9e68e35aed914d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 9 Mar 2022 19:39:51 -0700 Subject: Add io_uring_prep_msg_ring() helper The IORING_OP_MSG_RING command type can be used to send a notification to another ring. This can be used to either just wakeup anyone waiting on the ring, for example. Signed-off-by: Jens Axboe --- src/include/liburing.h | 8 ++++++++ src/include/liburing/io_uring.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index ef5a4cd..7f75eb4 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -703,6 +703,14 @@ static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd, sqe->hardlink_flags = (__u32) flags; } +static inline void io_uring_prep_msg_ring(struct io_uring_sqe *sqe, int fd, + unsigned int len, __u64 data, + unsigned int flags) +{ + io_uring_prep_rw(IORING_OP_MSG_RING, sqe, fd, NULL, len, data); + sqe->rw_flags = flags; +} + /* * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in * the SQ ring diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index a7d193d..c7cfe7d 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -147,6 +147,7 @@ enum { IORING_OP_MKDIRAT, IORING_OP_SYMLINKAT, IORING_OP_LINKAT, + IORING_OP_MSG_RING, /* this goes last, obviously */ IORING_OP_LAST, @@ -203,9 +204,11 @@ struct io_uring_cqe { * * IORING_CQE_F_BUFFER If set, the upper 16 bits are the buffer ID * IORING_CQE_F_MORE If set, parent SQE will generate more CQE entries + * IORING_CQE_F_MSG If set, CQE was generated with IORING_OP_MSG_RING */ #define IORING_CQE_F_BUFFER (1U << 0) #define IORING_CQE_F_MORE (1U << 1) +#define IORING_CQE_F_MSG (1U << 2) enum { IORING_CQE_BUFFER_SHIFT = 16, -- cgit v1.2.3 From ab80fef9c929a1adcbce87b672eab0761e2f95d1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 9 Mar 2022 19:31:57 -0700 Subject: test/msg-ring: add test cases for IORING_OP_MSG_RING Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 2 + test/msg-ring.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+) create mode 100644 test/msg-ring.c diff --git a/.gitignore b/.gitignore index 9b74880..ae16633 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ /test/link_drain /test/madvise /test/mkdir +/test/msg-ring /test/nop /test/nop-all-sizes /test/open-close diff --git a/test/Makefile b/test/Makefile index 9dae002..1019113 100644 --- a/test/Makefile +++ b/test/Makefile @@ -93,6 +93,7 @@ test_srcs := \ link-timeout.c \ madvise.c \ mkdir.c \ + msg-ring.c \ multicqes_drain.c \ nop-all-sizes.c \ nop.c \ @@ -221,6 +222,7 @@ ring-leak2: override LDFLAGS += -lpthread poll-mshot-update: override LDFLAGS += -lpthread exit-no-cleanup: override LDFLAGS += -lpthread pollfree: override LDFLAGS += -lpthread +msg-ring: override LDFLAGS += -lpthread install: $(test_targets) runtests.sh runtests-loop.sh $(INSTALL) -D -d -m 755 $(datadir)/liburing-test/ diff --git a/test/msg-ring.c b/test/msg-ring.c new file mode 100644 index 0000000..8930e72 --- /dev/null +++ b/test/msg-ring.c @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: test ring messaging command + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" + +static int no_msg; + +static int test_own(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int ret, i; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + io_uring_prep_msg_ring(sqe, ring->ring_fd, 0x10, 0x1234, 0); + sqe->user_data = 1; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + for (i = 0; i < 2; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + switch (cqe->user_data) { + case 1: + if (cqe->res == -EINVAL || cqe->res == -EOPNOTSUPP) { + no_msg = 1; + return 0; + } + if (cqe->res != 0) { + fprintf(stderr, "cqe res %d\n", cqe->res); + return -1; + } + break; + case 0x1234: + if (!(cqe->flags & IORING_CQE_F_MSG)) { + fprintf(stderr, "invalid flags %x\n", cqe->flags); + return -1; + } + if (cqe->res != 0x10) { + fprintf(stderr, "invalid len %x\n", cqe->res); + return -1; + } + break; + default: + fprintf(stderr, "Invalid user_data\n"); + return -1; + } + io_uring_cqe_seen(ring, cqe); + } + + return 0; +err: + return 1; +} + +static void *wait_cqe_fn(void *data) +{ + struct io_uring *ring = data; + struct io_uring_cqe *cqe; + int ret; + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "wait cqe %d\n", ret); + goto err; + } + + if (!(cqe->flags & IORING_CQE_F_MSG)) { + fprintf(stderr, "invalid flags %x\n", cqe->flags); + goto err; + } + if (cqe->user_data != 0x5aa5) { + fprintf(stderr, "user_data %llx\n", (long long) cqe->user_data); + goto err; + } + if (cqe->res != 0x20) { + fprintf(stderr, "len %x\n", cqe->res); + goto err; + } + + return NULL; +err: + return (void *) (unsigned long) 1; +} + +static int test_remote(struct io_uring *ring, struct io_uring *target) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int ret; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + io_uring_prep_msg_ring(sqe, target->ring_fd, 0x20, 0x5aa5, 0); + sqe->user_data = 1; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + if (cqe->res != 0) { + fprintf(stderr, "cqe res %d\n", cqe->res); + return -1; + } + if (cqe->user_data != 1) { + fprintf(stderr, "user_data %llx\n", (long long) cqe->user_data); + return -1; + } + + io_uring_cqe_seen(ring, cqe); + return 0; +err: + return 1; +} + +static int test_invalid(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int ret; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + io_uring_prep_msg_ring(sqe, 1, 0, 0x8989, 0); + sqe->user_data = 1; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + if (cqe->res != -EBADFD) { + fprintf(stderr, "cqe res %d\n", cqe->res); + return -1; + } + + io_uring_cqe_seen(ring, cqe); + return 0; +err: + return 1; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring, ring2; + pthread_t thread; + void *tret; + int ret; + + if (argc > 1) + return 0; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + ret = io_uring_queue_init(8, &ring2, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + ret = test_own(&ring); + if (ret) { + fprintf(stderr, "test_own failed\n"); + return ret; + } + if (no_msg) { + fprintf(stdout, "Skipped\n"); + return 0; + } + + ret = test_invalid(&ring); + if (ret) { + fprintf(stderr, "test_invalid failed\n"); + return ret; + } + + pthread_create(&thread, NULL, wait_cqe_fn, &ring2); + + ret = test_remote(&ring, &ring2); + if (ret) { + fprintf(stderr, "test_remote failed\n"); + return ret; + } + + pthread_join(thread, &tret); + + return 0; +} -- cgit v1.2.3 From 9236f53a8ffe96cc2430f7131bbcba5756b97bc2 Mon Sep 17 00:00:00 2001 From: Paymon MARANDI Date: Wed, 9 Mar 2022 15:30:45 -0500 Subject: make: let src/Makefile set *dir vars properly prefix suffice for setting *dir variables in src/Makefile; this does away with setting does in in ./Makefile Signed-off-by: Paymon MARANDI --- Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile b/Makefile index 28c0fd8..d6f8520 100644 --- a/Makefile +++ b/Makefile @@ -45,9 +45,6 @@ endif install: $(NAME).pc @$(MAKE) -C src install prefix=$(DESTDIR)$(prefix) \ - includedir=$(DESTDIR)$(includedir) \ - libdir=$(DESTDIR)$(libdir) \ - libdevdir=$(DESTDIR)$(libdevdir) \ relativelibdir=$(relativelibdir) $(INSTALL) -D -m 644 $(NAME).pc $(DESTDIR)$(libdevdir)/pkgconfig/$(NAME).pc $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man2 -- cgit v1.2.3 From 76d4590c1b81c05c92d08e6cd23fa07163315944 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2022 13:10:52 -0700 Subject: test/iopoll: don't error if IOPOLL isn't supported Reported-by: Stefan Roesch Signed-off-by: Jens Axboe --- test/iopoll.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/iopoll.c b/test/iopoll.c index fec9d18..f3c22d6 100644 --- a/test/iopoll.c +++ b/test/iopoll.c @@ -151,6 +151,12 @@ static int __test_io(const char *file, struct io_uring *ring, int write, int sqt ret = io_uring_submit(ring); if (ret != BUFFERS) { + ret = io_uring_peek_cqe(ring, &cqe); + if (!ret && cqe->res == -EOPNOTSUPP) { + no_iopoll = 1; + io_uring_cqe_seen(ring, cqe); + goto out; + } fprintf(stderr, "submit got %d, wanted %d\n", ret, BUFFERS); goto err; } -- cgit v1.2.3 From c56200f72a01e12e8b52191a2735c6d7c6bed40b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2022 17:28:12 -0700 Subject: test/drop-submit: test function of IORING_SETUP_SUBMIT_ALL flag If the ring is created with this flag, then we expect submissions to continue even if we hit an error in a batch. Check if that is the case or not. Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 1 + test/Makefile | 1 + test/drop-submit.c | 92 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 test/drop-submit.c diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index c7cfe7d..975a203 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -105,6 +105,7 @@ enum { #define IORING_SETUP_CLAMP (1U << 4) /* clamp SQ/CQ ring sizes */ #define IORING_SETUP_ATTACH_WQ (1U << 5) /* attach to existing wq */ #define IORING_SETUP_R_DISABLED (1U << 6) /* start with ring disabled */ +#define IORING_SETUP_SUBMIT_ALL (1U << 7) /* continue submit on error */ enum { IORING_OP_NOP, diff --git a/test/Makefile b/test/Makefile index 1019113..f5b2c7c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -61,6 +61,7 @@ test_srcs := \ d77a67ed5f27-test.c \ defer.c \ double-poll-crash.c \ + drop-submit.c \ eeed8b54e0df-test.c \ empty-eownerdead.c \ eventfd.c \ diff --git a/test/drop-submit.c b/test/drop-submit.c new file mode 100644 index 0000000..72e44d9 --- /dev/null +++ b/test/drop-submit.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: test IORING_SETUP_SUBMIT_ALL + * + */ +#include +#include +#include +#include + +#include "liburing.h" + +static int test(struct io_uring *ring, int expect_drops) +{ + struct io_uring_sqe *sqe; + char buf[32]; + int ret, i; + + for (i = 0; i < 4; i++) { + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + io_uring_prep_nop(sqe); + } + + /* prep two invalid reads, these will fail */ + for (i = 0; i < 2; i++) { + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + io_uring_prep_read(sqe, 128, buf, sizeof(buf), 0); + } + + + ret = io_uring_submit(ring); + if (expect_drops) { + if (ret != 5) { + fprintf(stderr, "drops submit failed: %d\n", ret); + goto err; + } + } else { + if (ret != 6) { + fprintf(stderr, "no drops submit failed: %d\n", ret); + goto err; + } + } + + return 0; +err: + return 1; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + int ret; + + if (argc > 1) + return 0; + + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SUBMIT_ALL); + if (ret) + return 0; + + ret = test(&ring, 0); + if (ret) { + fprintf(stderr, "test no drops failed\n"); + return ret; + } + + io_uring_queue_exit(&ring); + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed\n"); + return 0; + } + + ret = test(&ring, 1); + if (ret) { + fprintf(stderr, "test drops failed\n"); + return ret; + } + + return 0; +} -- cgit v1.2.3 From a43ee108b202aaa0d28a769c9ab3898c5133646e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2022 20:01:31 -0700 Subject: man/io_uring_setup.2: document IORING_SETUP_SUBMIT_ALL Signed-off-by: Jens Axboe --- man/io_uring_setup.2 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index 897db6e..c54c5da 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -184,6 +184,18 @@ In this state, restrictions can be registered, but submissions are not allowed. See .BR io_uring_register (2) for details on how to enable the ring. Available since 5.10. +.TP +.B IORING_SETUP_SUBMIT_ALL +Normally io_uring stops submitting a batch of request, if one of these requests +results in an error. This can cause submission of less than what is expected, +if a request ends in error while being submitted. If the ring is creted with +this flag, +.BR io_uring_enter (2) +will continue submitting requests even if it encounters an error submitting +a request. CQEs are still posted for errored request regardless of whether or +not this flag is set at ring creation time, the only difference is if the +submit sequence is halted or continued when an error is observed. Available +since 5.18. .PP If no flags are specified, the io_uring instance is setup for interrupt driven I/O. I/O may be submitted using -- cgit v1.2.3 From ef342c9119306b3403c1e59e7cce9fd7eb84cdd3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2022 20:03:12 -0700 Subject: Export ring fd registration symbols Signed-off-by: Jens Axboe --- src/liburing.map | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/liburing.map b/src/liburing.map index 7f1eeb7..c83a15f 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -48,4 +48,6 @@ LIBURING_2.1 { LIBURING_2.2 { global: io_uring_submit_and_wait_timeout; + io_uring_register_ring_fd; + io_uring_unregister_ring_fd; } LIBURING_2.1; -- cgit v1.2.3 From bddeb9f36b738863573e38b895701b5c187d740d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2022 20:19:28 -0700 Subject: man/io_uring_prep_msg_ring.3: add man page Signed-off-by: Jens Axboe --- man/io_uring_prep_msg_ring.3 | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 man/io_uring_prep_msg_ring.3 diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 new file mode 100644 index 0000000..ad59af0 --- /dev/null +++ b/man/io_uring_prep_msg_ring.3 @@ -0,0 +1,58 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_msg_ring 3 "March 10, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_msg_ring - send a message to another ring + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_msg_ring(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " unsigned int len," +.BI " __u64 data," +.BI " unsigned int flags)" + +.SH DESCRIPTION +.PP +io_uring_prep_msg_ring() prepares a to send a CQE to an io_uring file +descriptor. The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +, which must identify a io_uring context, to post a CQE on that ring where +the target CQE +.BR res +field will contain the content of +.I len +and the +.BR user_data +of +.I data +with the request modifier flags set by +.I flags. +Currently there are no valid flag modifiers, this field must contain +.B 0. + +The targeted ring may be any ring that the user has access to, even the ring +itself. This request can be used for simple message passing to another ring, +allowing 32+64 bits of data to be transferred through the +.I len +and +.I data +fields. The use case may be anything from simply waking up someone waiting +on the targeted ring, or it can be used to pass messages between the two +rings. + +The resulting CQE posted on the target ring will have +.B IORING_CQE_F_MSG +set in its +.I flags +member, indicating to the target ring that this CQE is posted without having +a relationship to an SQE issued on this ring. + +.SH RETURN VALUE +None -- cgit v1.2.3 From 12de49647cc66dd4613ad8fe7c215b43ed6a7c2d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2022 20:39:46 -0700 Subject: man/io_uring_register.2: add IORING_REGISTER_RING_FDS Add documentation for the new register/unregister ring file descriptor opcodes. Signed-off-by: Jens Axboe --- man/io_uring_register.2 | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index 2072cb2..cb63e6b 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -497,6 +497,82 @@ must be set to 2, as the command takes two values. Available since 5.15. +.TP +.B IORING_REGISTER_RING_FDS +Whenever +.BR io_uring_enter (2) +is called to submit request or wait for completions, the kernel must grab a +reference to the file descriptor. If the application using io_uring is threaded, +the file table is marked as shared, and the reference grab and put of the file +descriptor count is more expensive than it is for a non-threaded application. + +Similarly to how io_uring allows registration of files, this allow registration +of the ring file descriptor itself. This reduces the overhead of the +.BR io_uring_enter (2) +system call. + +.I arg +must be set to an unsigned int pointer to an array of type +.I struct io_uring_rsrc_register +of +.I nr_args +number of entries. The +.B data +field of this struct must point to an io_uring file descriptor, and the +.B offset +field can be either +.B -1 +or an explicit offset desired for the registered file descriptor value. If +.B -1 +is used, then upon successful return of this system call, the field will +contain the value of the registered file descriptor to be used for future +.BR io_uring_enter (2) +system calls. + +On successful completion of this request, the returned descriptors may be used +instead of the real file descriptor for +.BR io_uring_enter (2), +provided that +.B IORING_ENTER_REGISTERED_RING +is set in the +.I flags +for the system call. This flag tells the kernel that a registered descriptor +is used rather than a real file descriptor. + +Each thread or process using a ring must register the file descriptor directly +by issuing this request.o + +The maximum number of supported registered ring descriptors is currently +limited to +.B 16. + +Available since 5.18. + +.TP +.B IORING_UNREGISTER_RING_FDS +Unregister descriptors previously registered with +.B IORING_REGISTER_RING_FDS. + +.I arg +must be set to an unsigned int pointer to an array of type +.I struct io_uring_rsrc_register +of +.I nr_args +number of entries. Only the +.B offset +field should be set in the structure, containing the registered file descriptor +offset previously returned from +.B IORING_REGISTER_RING_FDS +that the application wishes to unregister. + +Note that this isn't done automatically on ring exit, if the thread or task +that previously registered a ring file descriptor isn't exiting. It is +recommended to manually unregister any previously registered ring descriptors +if the ring is closed and the task persists. This will free up a registration +slot, making it available for future use. + +Available since 5.18. + .SH RETURN VALUE On success, -- cgit v1.2.3 From 69e42e55ee1516cec819d06a350b006a9360714f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2022 20:45:20 -0700 Subject: man/io_uring_enter.2: add documentation for IORING_OP_MSG_RING Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 192b76b..c16a526 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -1027,6 +1027,27 @@ being passed in to .BR linkat(2). Available since 5.15. +.TP +.B IORING_OP_MSG_RING +Send a message to an io_uring. +.I fd +must be set to a file descriptor of a ring that the application has access to, +.I len +can be set to any 32-bit value that the application wishes to pass on, and +.I off +should be set any 64-bit value that the application wishes to send. On the +target ring, a CQE will be posted with the +.I res +field matching the +.I len +set, and a +.I user_data +field matching the +.I off +value being passed in. This request type can be used to either just wake or +interrupt anyone waiting for completions on the target ring, ot it can be used +to pass messages via the two fields. Available since 5.18. + .PP The .I flags -- cgit v1.2.3 From 97a92145655710cd846e3b6915dd380f32066e2e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2022 21:22:24 -0700 Subject: Make the fast path of CQE checking inline Even the io_uring_peek_cqe() currently requires an indirect call into the library, even if an event is readily available. Inline the CQE check and retrieval for peek, and have io_uring_wait_cqe() check that as well before calling into a library function. Signed-off-by: Jens Axboe --- src/include/liburing.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/queue.c | 37 ------------------------------------- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 7bc0140..2e390a0 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -817,6 +817,44 @@ static inline int io_uring_wait_cqe_nr(struct io_uring *ring, return __io_uring_get_cqe(ring, cqe_ptr, 0, wait_nr, NULL); } +static inline int __io_uring_peek_cqe(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, + unsigned *nr_available) +{ + struct io_uring_cqe *cqe; + int err = 0; + unsigned available; + unsigned mask = *ring->cq.kring_mask; + + do { + unsigned tail = io_uring_smp_load_acquire(ring->cq.ktail); + unsigned head = *ring->cq.khead; + + cqe = NULL; + available = tail - head; + if (!available) + break; + + cqe = &ring->cq.cqes[head & mask]; + if (!(ring->features & IORING_FEAT_EXT_ARG) && + cqe->user_data == LIBURING_UDATA_TIMEOUT) { + if (cqe->res < 0) + err = cqe->res; + io_uring_cq_advance(ring, 1); + if (!err) + continue; + cqe = NULL; + } + + break; + } while (1); + + *cqe_ptr = cqe; + if (nr_available) + *nr_available = available; + return err; +} + /* * Return an IO completion, if one is readily available. Returns 0 with * cqe_ptr filled in on success, -errno on failure. @@ -824,6 +862,9 @@ static inline int io_uring_wait_cqe_nr(struct io_uring *ring, static inline int io_uring_peek_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr) { + if (__io_uring_peek_cqe(ring, cqe_ptr, NULL)) + return 0; + return io_uring_wait_cqe_nr(ring, cqe_ptr, 0); } @@ -834,6 +875,9 @@ static inline int io_uring_peek_cqe(struct io_uring *ring, static inline int io_uring_wait_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr) { + if (__io_uring_peek_cqe(ring, cqe_ptr, NULL)) + return 0; + return io_uring_wait_cqe_nr(ring, cqe_ptr, 1); } diff --git a/src/queue.c b/src/queue.c index 279e5dd..2fec494 100644 --- a/src/queue.c +++ b/src/queue.c @@ -43,43 +43,6 @@ static inline bool cq_ring_needs_enter(struct io_uring *ring) return (ring->flags & IORING_SETUP_IOPOLL) || cq_ring_needs_flush(ring); } -static int __io_uring_peek_cqe(struct io_uring *ring, - struct io_uring_cqe **cqe_ptr, - unsigned *nr_available) -{ - struct io_uring_cqe *cqe; - int err = 0; - unsigned available; - unsigned mask = *ring->cq.kring_mask; - - do { - unsigned tail = io_uring_smp_load_acquire(ring->cq.ktail); - unsigned head = *ring->cq.khead; - - cqe = NULL; - available = tail - head; - if (!available) - break; - - cqe = &ring->cq.cqes[head & mask]; - if (!(ring->features & IORING_FEAT_EXT_ARG) && - cqe->user_data == LIBURING_UDATA_TIMEOUT) { - if (cqe->res < 0) - err = cqe->res; - io_uring_cq_advance(ring, 1); - if (!err) - continue; - cqe = NULL; - } - - break; - } while (1); - - *cqe_ptr = cqe; - *nr_available = available; - return err; -} - struct get_data { unsigned submit; unsigned wait_nr; -- cgit v1.2.3 From ef45ab7d567a13f5a663c176e3d1e5cc38dba11e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 11 Mar 2022 05:56:24 -0700 Subject: Add man pages for io_uring_(un)register_ring_fd() Signed-off-by: Jens Axboe --- man/io_uring_register_ring_fd.3 | 47 +++++++++++++++++++++++++++++++++++++++ man/io_uring_unregister_ring_fd.3 | 32 ++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 man/io_uring_register_ring_fd.3 create mode 100644 man/io_uring_unregister_ring_fd.3 diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3 new file mode 100644 index 0000000..ce3d374 --- /dev/null +++ b/man/io_uring_register_ring_fd.3 @@ -0,0 +1,47 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_register_ring_fd 3 "March 11, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_register_ring_fd - register a ring file descriptor + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_register_ring_fd(struct io_uring *ring)" + +.SH DESCRIPTION +.PP +io_uring_register_ring_fd() registers the file descriptor of the ring. + +Whenever +.BR io_uring_enter (2) +is called to submit request or wait for completions, the kernel must grab a +reference to the file descriptor. If the application using io_uring is threaded, +the file table is marked as shared, and the reference grab and put of the file +descriptor count is more expensive than it is for a non-threaded application. + +Similarly to how io_uring allows registration of files, this allow registration +of the ring file descriptor itself. This reduces the overhead of the +.BR io_uring_enter (2) +system call. + +If an application using liburing is threaded, then an application should call +this function to register the ring descriptor when a ring is set up. See NOTES +for restrictions when a ring is shared. + +.SH NOTES +When the ring descriptor is registered, it is stored internally in the +.I struct io_uring +structure. If an application shares this structure between threads, then this +optimization cannot be used as the threads may get different values for the +registered descriptor. +.SH RETURN VALUE +Returns 1 on success, indicating that one file descriptor was registered, +or +.B -errno +on error. +.SH SEE ALSO +.BR io_uring_unregister_ring_fd (3), io_uring_register_files (3) diff --git a/man/io_uring_unregister_ring_fd.3 b/man/io_uring_unregister_ring_fd.3 new file mode 100644 index 0000000..4a43589 --- /dev/null +++ b/man/io_uring_unregister_ring_fd.3 @@ -0,0 +1,32 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_unregister_ring_fd 3 "March 11, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_unregister_ring_fd - unregister a ring file descriptor + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_unregister_ring_fd(struct io_uring *ring)" + +.SH DESCRIPTION +.PP +io_uring_unregister_ring_fd() unregisters the file descriptor of the ring. + +Unregisters a ring descriptor previously registered with the task. This is +done automatically when +.BR io_uring_queue_exit (3) +is called, but can also be done to free up space for new ring registrations. +For more information on ring descriptor registration, see +.BR io_uring_register_ring_fd (3) + +.SH RETURN VALUE +Returns 1 on success, indicating that one file descriptor was unregistered, +or +.B -errno +on error. +.SH SEE ALSO +.BR io_uring_register_ring_fd (3), io_uring_register_files (3) -- cgit v1.2.3 From 7fed734f70fc3b18e504f75ed52b77192729c874 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 11 Mar 2022 08:16:00 -0700 Subject: man/io_uring_prep_msg_ring.3: add CQE results Signed-off-by: Jens Axboe --- man/io_uring_prep_msg_ring.3 | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index ad59af0..a512a26 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -56,3 +56,24 @@ a relationship to an SQE issued on this ring. .SH RETURN VALUE None + +.SH ERRORS +These are the errors that are reported in the CQE +.I res +field. +.TP +.B -ENOMEM +The kernel was unable to allocate memory for the request. +.TP +.B -EINVAL +One of the fields set in the SQE was invalid. +.TP +.B -EBADFD +The descriptor passed in +.I fd +does not refer to an io_uring file descriptor. +.TP +.B -EOVERFLOW +The kernel was unable to fill a CQE on the target ring. This can happen if +the target CQ ring is in an overflow state and the kernel wasn't able to +allocate memory for a new CQE entry. -- cgit v1.2.3 From 2eda3594c0056079fa3e3b9fba52e72ed4ff6183 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 10:48:06 -0700 Subject: liburing: fix issue with fast-pathed peek There are actually two bugs in that commit: - Assuming that __io_uring_peek_cqe() returns 0 with cqe always filled, like we do for the library functions. It can return 0 and not fill in the cqe, caller should check cqe. The internals do that, but not the new additions. - We were checking for non-zero return, we should check for 0. Link: https://github.com/axboe/liburing/issues/546 Fixes: 97a921456557 ("Make the fast path of CQE checking inline") Signed-off-by: Jens Axboe --- src/include/liburing.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 2e390a0..19cda04 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -862,7 +862,7 @@ static inline int __io_uring_peek_cqe(struct io_uring *ring, static inline int io_uring_peek_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr) { - if (__io_uring_peek_cqe(ring, cqe_ptr, NULL)) + if (!__io_uring_peek_cqe(ring, cqe_ptr, NULL) && *cqe_ptr) return 0; return io_uring_wait_cqe_nr(ring, cqe_ptr, 0); @@ -875,7 +875,7 @@ static inline int io_uring_peek_cqe(struct io_uring *ring, static inline int io_uring_wait_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr) { - if (__io_uring_peek_cqe(ring, cqe_ptr, NULL)) + if (!__io_uring_peek_cqe(ring, cqe_ptr, NULL) && *cqe_ptr) return 0; return io_uring_wait_cqe_nr(ring, cqe_ptr, 1); -- cgit v1.2.3 From e3ab208e39e28d7e9850356a6cb169a69198883a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 10:51:30 -0700 Subject: liburing.h: make it clear that __io_uring_peek_cqe() is an internal helper Don't use it in applications, there are official versions of it that should be used instead. Signed-off-by: Jens Axboe --- src/include/liburing.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 19cda04..a450d56 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -817,6 +817,11 @@ static inline int io_uring_wait_cqe_nr(struct io_uring *ring, return __io_uring_get_cqe(ring, cqe_ptr, 0, wait_nr, NULL); } +/* + * Internal helper, don't use directly in applications. Use one of the + * "official" versions of this, io_uring_peek_cqe(), io_uring_wait_cqe(), + * or io_uring_wait_cqes*(). + */ static inline int __io_uring_peek_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned *nr_available) -- cgit v1.2.3 From 91b607eebf1a8b28c5f5de3f6cb8265eecb11c0e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 10:56:53 -0700 Subject: Add io_uring_peek_cqe man page Signed-off-by: Jens Axboe --- man/io_uring_peek_cqe.3 | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 man/io_uring_peek_cqe.3 diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3 new file mode 100644 index 0000000..2867d21 --- /dev/null +++ b/man/io_uring_peek_cqe.3 @@ -0,0 +1,36 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_peek_cqe 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_peek_cqe - check if an io_uring completion event is available +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_peek_cqe(struct io_uring *ring," +.BI " struct io_uring_cqe **cqe_ptr);" +.fi +.PP +.SH DESCRIPTION +.PP +The io_uring_peek_cqe() function returns an IO completion from the +queue belonging to the +.I ring +param, if one is readily available. On successful return, +.I cqe_ptr +param is filled with a valud CQE entry. + +This function does not enter the kernel to wait for an event, an event +is only returned if it's already available in the CQ ring. + +.SH RETURN VALUE +On success +.BR io_uring_peek_cqe (3) +returns +.B 0 +and the cqe_ptr parameter is filled in. On failure it returns +.B -EAGAIN. +.SH SEE ALSO +.BR io_uring_submit (3), io_uring_wait_cqes (3), io_uring_wait_cqe (3) -- cgit v1.2.3 From 029b65862c5c21757ea0182f6ba013c4fa96ba9d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 10:59:36 -0700 Subject: man/io_uring_cq_advance.3: man page improvements Signed-off-by: Jens Axboe --- man/io_uring_cq_advance.3 | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 index 59bb681..cca269b 100644 --- a/man/io_uring_cq_advance.3 +++ b/man/io_uring_cq_advance.3 @@ -22,14 +22,20 @@ belonging to the .I ring param as processed. -After the caller has submitted a request with io_uring_submit(), he can retrieve -the completion with io_uring_wait_cqe() and mark it then as processed with -io_uring_cqe_seen(). +After the caller has submitted a request with io_uring_submit(), the application +can retrieve the completion with +.BR io_uring_wait_cqe (3) +and mark it as processed with +.BR io_uring_cqe_seen (3). -The function io_uring_cqe_seen() calls the function io_uring_cq_advance(). +The function +.BR io_uring_cqe_seen (3) calls the function +.BR io_uring_cq_advance (3). + +Completions must be marked as seen, so their slot can get reused. Failure to do +so will result in the same completion being returned on the next invocation. -Completions must be marked as completed, so their slot can get reused. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_cqe_seen (3) \ No newline at end of file +.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_cqe_seen (3) -- cgit v1.2.3 From 8cc705c80b58b7f57645c9f7a496ec0e3cf6257d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 11:02:37 -0700 Subject: man: use more inclusive language Let's use 'the application' rather than 'he' to refer to whatever is invoking these functions. Signed-off-by: Jens Axboe --- man/io_uring_cqe_get_data.3 | 8 +++++--- man/io_uring_cqe_seen.3 | 11 +++++++---- man/io_uring_wait_cqe.3 | 8 +++++--- man/io_uring_wait_cqe_nr.3 | 8 +++++--- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index 0c576f9..a3140ca 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -18,8 +18,10 @@ The io_uring_cqe_get_data() function returns the user_data with the completion queue entry .I cqe. -After the caller has received a completion queue entry (CQE) with io_uring_wait_cqe(), -he can call he io_uring_cqe_get_data() function to retrieve the +After the caller has received a completion queue entry (CQE) with +.BR io_uring_wait_cqe (3), +the application can call +.BR io_uring_cqe_get_data (3) function to retrieve the .I user_data value. This requires that .I user_data @@ -31,4 +33,4 @@ If the value has been set before submitting the request, it will be returned. Otherwise the functions returns NULL. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_sqe_set_data (3), io_uring_sqe_submit(3) \ No newline at end of file +.BR io_uring_get_sqe (3), io_uring_sqe_set_data (3), io_uring_sqe_submit(3) diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3 index 6a8b151..77baecb 100644 --- a/man/io_uring_cqe_seen.3 +++ b/man/io_uring_cqe_seen.3 @@ -21,12 +21,15 @@ belonging to the .I ring param as processed. -After the caller has submitted a request with io_uring_submit(), he can retrieve -the completion with io_uring_wait_cqe() and mark it then as processed with -io_uring_cqe_seen(). +After the caller has submitted a request with +.BR io_uring_submit (3), +the application can retrieve the completion with +.BR io_uring_wait_cqe (3) +and mark it then as processed with +.BR io_uring_cqe_seen (3). Completions must be marked as completed, so their slot can get reused. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe(3) \ No newline at end of file +.BR io_uring_submit (3), io_uring_wait_cqe(3) diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3 index 85f6d78..b4c3e98 100644 --- a/man/io_uring_wait_cqe.3 +++ b/man/io_uring_wait_cqe.3 @@ -22,12 +22,14 @@ param, waiting for it if necessary. The .I cqe_ptr param is filled in on success. -After the caller has submitted a request with io_uring_submit(), he can retrieve -the completion with io_uring_wait_cqe(). +After the caller has submitted a request with +.BR io_uring_submit (3), +the application can retrieve the completion with +.BR io_uring_wait_cqe (3). .SH RETURN VALUE On success .BR io_uring_wait_cqe (3) returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqes(3) \ No newline at end of file +.BR io_uring_submit (3), io_uring_wait_cqes(3) diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3 index a3d9b56..7f96300 100644 --- a/man/io_uring_wait_cqe_nr.3 +++ b/man/io_uring_wait_cqe_nr.3 @@ -25,12 +25,14 @@ param, waiting for it if necessary. The .I cqe_ptr param is filled in on success. -After the caller has submitted a request with io_uring_submit(), he can retrieve -the completion with io_uring_wait_cqe_nr(). +After the caller has submitted a request with +.BR io_uring_submit (3), +the application can retrieve the completion with +.BR io_uring_wait_cqe (3). .SH RETURN VALUE On success .BR io_uring_wait_cqe_nr (3) returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqes (3) \ No newline at end of file +.BR io_uring_submit (3), io_uring_wait_cqes (3) -- cgit v1.2.3 From cac7acee9e6edb840eff3276707c220fa597557e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 11:04:40 -0700 Subject: man/io_uring_cq_advance.3: remember line breaks after functions Signed-off-by: Jens Axboe --- man/io_uring_cq_advance.3 | 8 +++++--- man/io_uring_cqe_get_data.3 | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 index cca269b..26f23ca 100644 --- a/man/io_uring_cq_advance.3 +++ b/man/io_uring_cq_advance.3 @@ -22,14 +22,16 @@ belonging to the .I ring param as processed. -After the caller has submitted a request with io_uring_submit(), the application -can retrieve the completion with +After the caller has submitted a request with +.BR io_uring_submit (3), +the application can retrieve the completion with .BR io_uring_wait_cqe (3) and mark it as processed with .BR io_uring_cqe_seen (3). The function -.BR io_uring_cqe_seen (3) calls the function +.BR io_uring_cqe_seen (3) +calls the function .BR io_uring_cq_advance (3). Completions must be marked as seen, so their slot can get reused. Failure to do diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index a3140ca..daa3589 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -21,7 +21,8 @@ with the completion queue entry After the caller has received a completion queue entry (CQE) with .BR io_uring_wait_cqe (3), the application can call -.BR io_uring_cqe_get_data (3) function to retrieve the +.BR io_uring_cqe_get_data (3) +function to retrieve the .I user_data value. This requires that .I user_data -- cgit v1.2.3 From e08db0ddce339d623aec26b443da96be211d8feb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 11:14:11 -0700 Subject: man/io_uring_queue_init.3: mention io_uring_register_ring_fd() Signed-off-by: Jens Axboe --- man/io_uring_queue_init.3 | 1 + 1 file changed, 1 insertion(+) diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index 1980fa4..2d66694 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -40,5 +40,6 @@ should be released via a corresponding call to returns 0 on success and -errno on failure. .SH SEE ALSO .BR io_uring_setup (2), +.BR io_uring_register_ring_fd (3), .BR mmap (2), .BR io_uring_queue_exit (3) -- cgit v1.2.3 From b1ff609cbfbe23fab84810d56b61c57a220a8e71 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 14:02:32 -0700 Subject: Add basic man pages for send/recvmsg prep helpers Signed-off-by: Jens Axboe --- man/io_uring_prep_recvmsg.3 | 40 ++++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_sendmsg.3 | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 man/io_uring_prep_recvmsg.3 create mode 100644 man/io_uring_prep_sendmsg.3 diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 new file mode 100644 index 0000000..21ddb6e --- /dev/null +++ b/man/io_uring_prep_recvmsg.3 @@ -0,0 +1,40 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_recvmsg 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_recvmsg - prepare a recvmsg request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_recvmsg(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " struct msghdr *msg," +.BI " unsigned flags)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_recvmsg() function prepares a recvmsg request. The submission +queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start receiving the data indicated by +.I msg +with the +.BR recvmsg (2) +defined flags in the +.I flags +argument. + +This function prepares an async +.BR recvmsg (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), recvmsg (2) diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 new file mode 100644 index 0000000..2606841 --- /dev/null +++ b/man/io_uring_prep_sendmsg.3 @@ -0,0 +1,40 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_sendmsg 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_sendmsg - prepare a sendmsg request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_sendmsg(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " const struct msghdr *msg," +.BI " unsigned flags)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_sendmsg() function prepares a sendmsg request. The submission +queue entry +.I sqe +is setup to use the file descriptor +.I fd +to start sending the data indicated by +.I msg +with the +.BR sendmsg (2) +defined flags in the +.I flags +argument. + +This function prepares an async +.BR sendmsg (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), sendmsg (2) -- cgit v1.2.3 From f1890732ac513d16569b11e1c7917605916348dd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 14:12:02 -0700 Subject: Add fsync man page Signed-off-by: Jens Axboe --- man/io_uring_prep_fsync.3 | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 man/io_uring_prep_fsync.3 diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 new file mode 100644 index 0000000..5ddfdfc --- /dev/null +++ b/man/io_uring_prep_fsync.3 @@ -0,0 +1,52 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_fsync 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_fsync - prepare an fsync request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_fsync(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " unsigned flags)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_fsync() function prepares an fsync request. The submission +queue entry +.I sqe +is setup to use the file descriptor +.I fd +that should get synced, with the modifier flags indicated by the +.I flags +argument. + +This function prepares an fsync request. It can act either like an +.BR fsync (2) +operation, which is the default behavior. If +.B IORING_FSYNC_DATASYNC +is set in the +.I flags +argument, then it behaves like +.BR fdatasync (2). +If no range is specified, the +.I fd +will be synced from 0 to end-of-file. + +It's possible to specify a range to sync, if one is desired. If the +.I off +field of the SQE is set to non-zero, then that indicates the offset to +start syncing at. If +.I len +is set in the SQE, then that indicates the size in bytes to sync from the +offset. Note that these fields are not accepted by this helper, so they have +to be set manually in the SQE after calling this prep helper. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), fsync (2), fdatasync (2) -- cgit v1.2.3 From c0857c9544a0378f9e4149701e3fadf9acebfc71 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 14:23:44 -0700 Subject: Add cancelation request man page Signed-off-by: Jens Axboe --- man/io_uring_prep_cancel.3 | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 man/io_uring_prep_cancel.3 diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 new file mode 100644 index 0000000..1b22d48 --- /dev/null +++ b/man/io_uring_prep_cancel.3 @@ -0,0 +1,60 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_cancel 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_cancel - prepare a cancelation request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_cancel(struct io_uring_sqe *sqe," +.BI " __u64 user_data," +.BI " int flags)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_cancel() function prepares a cancelation request. The +submission queue entry +.I sqe +is prepared to cancel an existing request identified by +.I user_data. +The +.I flags +argument is currently unused. + +The cancelation request will attempt to find the previously issued request +identified by +.I user_data +and cancel it. The identifier is what the previously issued request has in +their +.I user_data +field in the SQE. + +.SH RETURN VALUE +None +.SH ERRORS +These are the errors that are reported in the CQE +.I res +field. On success, +.B 0 +is returned. +.TP +.B -ENOENT +The request identified by +.I user_data +could not be located. This could be because it completed before the cancelation +request was issued, or if an invalid identifier is used. +.TP +.B -EINVAL +One of the fields set in the SQE was invalid. +.TP +.B -EALREADY +The execution state of the request has progressed far enough that cancelation +is no longer possible. This should normally mean that it will complete shortly, +either successfully, or interrupted due to the cancelation. + +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3) -- cgit v1.2.3 From cec347ed1589e73af7da977c5539f793915dd786 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 14:27:43 -0700 Subject: Add send/recv man pages Signed-off-by: Jens Axboe --- man/io_uring_prep_recv.3 | 40 ++++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_send.3 | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 man/io_uring_prep_recv.3 create mode 100644 man/io_uring_prep_send.3 diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 new file mode 100644 index 0000000..0d23c89 --- /dev/null +++ b/man/io_uring_prep_recv.3 @@ -0,0 +1,40 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_recv 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_recv - prepare a recv request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_recv(struct io_uring_sqe *sqe," +.BI " int sockfd," +.BI " void *buf," +.BI " size_t len," +.BI " int flags)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_recv() function prepares a recv request. The submission +queue entry +.I sqe +is setup to use the file descriptor +.I sockfd +to start receiving the data into the buffer destination +.I buf +of size +.I size +and with modifier flags +.I flags. + +This function prepares an async +.BR recv (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), recv (2) diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 new file mode 100644 index 0000000..d54c3db --- /dev/null +++ b/man/io_uring_prep_send.3 @@ -0,0 +1,40 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_send 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_send - prepare a send request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_send(struct io_uring_sqe *sqe," +.BI " int sockfd," +.BI " const void *buf," +.BI " size_t len," +.BI " int flags)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_send() function prepares a send request. The submission +queue entry +.I sqe +is setup to use the file descriptor +.I sockfd +to start sending the data from +.I buf +of size +.I size +and with modifier flags +.I flags. + +This function prepares an async +.BR send (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), send (2) -- cgit v1.2.3 From 813a0efcac0edefad51f2e8c339098c0a110f209 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 14:29:53 -0700 Subject: Add shutdown man page Signed-off-by: Jens Axboe --- man/io_uring_prep_shutdown.3 | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 man/io_uring_prep_shutdown.3 diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 new file mode 100644 index 0000000..3db0a36 --- /dev/null +++ b/man/io_uring_prep_shutdown.3 @@ -0,0 +1,35 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_shutdown 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_shutdown - prepare a shutdown request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_shutdown(struct io_uring_sqe *sqe," +.BI " int sockfd," +.BI " int how)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_shutdown() function prepares a shutdown request. The +submission queue entry +.I sqe +is setup to use the file descriptor +.I sockfd +that should be shutdown with the +.I how +argument. + +This function prepares an async +.BR shutdown (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), shutdown (2) -- cgit v1.2.3 From 81797359d95b0a7c3dab71294bbdcad1d8337953 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 14:36:00 -0700 Subject: Add sync_file_range man page Signed-off-by: Jens Axboe --- man/io_uring_prep_sync_file_range.3 | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 man/io_uring_prep_sync_file_range.3 diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 new file mode 100644 index 0000000..c0da46b --- /dev/null +++ b/man/io_uring_prep_sync_file_range.3 @@ -0,0 +1,41 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_sync_file_range 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_sync_file_range - prepare a sync_file_range request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_sync_file_range(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " unsigned len," +.BI " __u64 offset," +.BI " int flags)" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_sync_file_range() function prepares a sync_file_range request. +The submission queue entry +.I sqe +is setup to use the file descriptor +.I fd +that should get +.I len +bytes synced started at offset +.I offset +and with modifier flags in the +.I flags +argument. + +This function prepares a +.BR sync_file_range (2) +request. See that man page for details on the arguments. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), sync_file_range (2) -- cgit v1.2.3 From 2d901dcf12294e28f4adb29d23eaf03f3e4e4677 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 14:42:48 -0700 Subject: man: add generic blurb on how io_uring returns errors Add a boilerplate section to the man pages that don't currently have an ERRORS section on finding the appropriate error values in the corresponding man page for the sync version of the operation. Signed-off-by: Jens Axboe --- man/io_uring_prep_fsync.3 | 15 +++++++++++++++ man/io_uring_prep_read.3 | 15 +++++++++++++++ man/io_uring_prep_read_fixed.3 | 15 +++++++++++++++ man/io_uring_prep_readv.3 | 15 +++++++++++++++ man/io_uring_prep_readv2.3 | 15 +++++++++++++++ man/io_uring_prep_recv.3 | 15 +++++++++++++++ man/io_uring_prep_recvmsg.3 | 15 +++++++++++++++ man/io_uring_prep_send.3 | 15 +++++++++++++++ man/io_uring_prep_sendmsg.3 | 15 +++++++++++++++ man/io_uring_prep_shutdown.3 | 15 +++++++++++++++ man/io_uring_prep_sync_file_range.3 | 15 +++++++++++++++ man/io_uring_prep_write.3 | 15 +++++++++++++++ man/io_uring_prep_write_fixed.3 | 15 +++++++++++++++ man/io_uring_prep_writev.3 | 15 +++++++++++++++ man/io_uring_prep_writev2.3 | 15 +++++++++++++++ 15 files changed, 225 insertions(+) diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 index 5ddfdfc..7c676c1 100644 --- a/man/io_uring_prep_fsync.3 +++ b/man/io_uring_prep_fsync.3 @@ -48,5 +48,20 @@ to be set manually in the SQE after calling this prep helper. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), fsync (2), fdatasync (2) diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index de3067d..65a61e3 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -46,5 +46,20 @@ functions. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_prep_readv (3), io_uring_prep_readv2 (3), io_uring_submit(3) diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index c15c697..99f8bcc 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -50,5 +50,20 @@ functions. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_prep_read (3), io_uring_register_buffers (3) diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index 8e66bce..c5df794 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -47,5 +47,20 @@ functions. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_prep_read (3), io_uring_prep_readv2 (3), io_uring_submit (3) diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 0d9d200..20b727d 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -75,5 +75,20 @@ functions. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_prep_read (3), io_uring_prep_readv (3), io_uring_submit (3) diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 index 0d23c89..ec6f513 100644 --- a/man/io_uring_prep_recv.3 +++ b/man/io_uring_prep_recv.3 @@ -36,5 +36,20 @@ request. See that man page for details. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), recv (2) diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index 21ddb6e..b449007 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -36,5 +36,20 @@ request. See that man page for details. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), recvmsg (2) diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 index d54c3db..4adbe4e 100644 --- a/man/io_uring_prep_send.3 +++ b/man/io_uring_prep_send.3 @@ -36,5 +36,20 @@ request. See that man page for details. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), send (2) diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index 2606841..567a93d 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -36,5 +36,20 @@ request. See that man page for details. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), sendmsg (2) diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index 3db0a36..fd26ddf 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -31,5 +31,20 @@ request. See that man page for details. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), shutdown (2) diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index c0da46b..403c948 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -37,5 +37,20 @@ request. See that man page for details on the arguments. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), sync_file_range (2) diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 4bbf7e0..90ee83b 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -46,5 +46,20 @@ functions. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3) diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index 8a33387..58c2ff2 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -50,5 +50,20 @@ functions. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_prep_write (3), io_uring_register_buffers (3) diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index e11f656..d644182 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -47,5 +47,20 @@ functions. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev2 (3), io_uring_submit (3) diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index 712c4ba..c73f5e0 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -74,5 +74,20 @@ functions. .SH RETURN VALUE None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev (3), io_uring_submit (3) -- cgit v1.2.3 From daf676e649246dccb1c88762fdc287cc8d1471c0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 15:27:03 -0700 Subject: Add poll man pages Signed-off-by: Jens Axboe --- man/io_uring_prep_poll_add.3 | 68 ++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_poll_multishot.3 | 1 + 2 files changed, 69 insertions(+) create mode 100644 man/io_uring_prep_poll_add.3 create mode 120000 man/io_uring_prep_poll_multishot.3 diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 new file mode 100644 index 0000000..34189f2 --- /dev/null +++ b/man/io_uring_prep_poll_add.3 @@ -0,0 +1,68 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_poll_add 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_poll_add - prepare a poll request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_poll_add(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " unsigned poll_mask);" +.BI " +.BI "void io_uring_prep_poll_multishot(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " unsigned poll_mask);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_poll_add() function prepares a poll request. The submission +queue entry +.I sqe +is setup to use the file descriptor +.I fd +that should get polled, with the events desired specified in the +.I poll_mask +argument. + +The default behavior is a single-shot poll request. When the specified event +has triggered, a completion CQE is posted and no more events will be generated +by the poll request. +.BR io_uring_prep_multishot (3) +behaves identically in terms of events, but it persist across notifications +and will repeatedly post notifications for the same registration. A CQE +posted from a multishot poll request will have +.B IORING_CQE_F_MORE +set in the CQE +.I flags +member, indicating that the application should expect more completions from +this request. If the multishot poll request gets terminated or experiences +an error, this flag will not be set in the CQE. If this happens, the application +should not expect further CQEs from the original request and must reissue a +new one if it still wishes to get notifications on this file descriptor. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation, which is a bitmask of the +events notified. See the +.BR poll (2) +man page for details. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), poll (2), epoll_ctl (3) diff --git a/man/io_uring_prep_poll_multishot.3 b/man/io_uring_prep_poll_multishot.3 new file mode 120000 index 0000000..ac8fb8f --- /dev/null +++ b/man/io_uring_prep_poll_multishot.3 @@ -0,0 +1 @@ +io_uring_prep_poll_add.3 \ No newline at end of file -- cgit v1.2.3 From d1d7e306f365fabb589bc2bfd1416c7dfe405059 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 15:29:01 -0700 Subject: man: ensure all function declarations are terminated by ';' Signed-off-by: Jens Axboe --- man/io_uring_prep_cancel.3 | 2 +- man/io_uring_prep_fsync.3 | 2 +- man/io_uring_prep_msg_ring.3 | 2 +- man/io_uring_prep_read.3 | 2 +- man/io_uring_prep_read_fixed.3 | 2 +- man/io_uring_prep_readv.3 | 2 +- man/io_uring_prep_readv2.3 | 2 +- man/io_uring_prep_recv.3 | 2 +- man/io_uring_prep_recvmsg.3 | 2 +- man/io_uring_prep_send.3 | 2 +- man/io_uring_prep_sendmsg.3 | 2 +- man/io_uring_prep_shutdown.3 | 2 +- man/io_uring_prep_sync_file_range.3 | 2 +- man/io_uring_prep_write.3 | 2 +- man/io_uring_prep_write_fixed.3 | 2 +- man/io_uring_prep_writev.3 | 2 +- man/io_uring_prep_writev2.3 | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 1b22d48..e7164db 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -12,7 +12,7 @@ io_uring_prep_cancel - prepare a cancelation request .PP .BI "void io_uring_prep_cancel(struct io_uring_sqe *sqe," .BI " __u64 user_data," -.BI " int flags)" +.BI " int flags);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 index 7c676c1..3a01963 100644 --- a/man/io_uring_prep_fsync.3 +++ b/man/io_uring_prep_fsync.3 @@ -12,7 +12,7 @@ io_uring_prep_fsync - prepare an fsync request .PP .BI "void io_uring_prep_fsync(struct io_uring_sqe *sqe," .BI " int fd," -.BI " unsigned flags)" +.BI " unsigned flags);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index a512a26..d71b612 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -14,7 +14,7 @@ io_uring_prep_msg_ring - send a message to another ring .BI " int fd," .BI " unsigned int len," .BI " __u64 data," -.BI " unsigned int flags)" +.BI " unsigned int flags);" .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index 65a61e3..e574046 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -14,7 +14,7 @@ io_uring_prep_read - prepare I/O read request .BI " int fd," .BI " void *buf," .BI " unsigned nbytes," -.BI " __u64 offset)" +.BI " __u64 offset);" .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index 99f8bcc..7e1cafe 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -15,7 +15,7 @@ io_uring_prep_read_fixed - prepare I/O read request with registered buffer .BI " void *buf," .BI " unsigned nbytes," .BI " __u64 offset," -.BI " int buf_index)" +.BI " int buf_index);" .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index c5df794..f0e94df 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -14,7 +14,7 @@ io_uring_prep_readv - prepare vector I/O read request .BI " int fd," .BI " const struct iovec *iovecs," .BI " unsigned nr_vecs," -.BI " __u64 offset)" +.BI " __u64 offset);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 20b727d..961e107 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -16,7 +16,7 @@ io_uring_prep_readv2 - prepare vector I/O read request with flags .BI " const struct iovec *iovecs," .BI " unsigned nr_vecs," .BI " __u64 offset," -.BI " int flags)" +.BI " int flags);" .fi .PP .SH DESCRIPTION diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 index ec6f513..1924343 100644 --- a/man/io_uring_prep_recv.3 +++ b/man/io_uring_prep_recv.3 @@ -14,7 +14,7 @@ io_uring_prep_recv - prepare a recv request .BI " int sockfd," .BI " void *buf," .BI " size_t len," -.BI " int flags)" +.BI " int flags);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index b449007..a30cecf 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -13,7 +13,7 @@ io_uring_prep_recvmsg - prepare a recvmsg request .BI "void io_uring_prep_recvmsg(struct io_uring_sqe *sqe," .BI " int fd," .BI " struct msghdr *msg," -.BI " unsigned flags)" +.BI " unsigned flags);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 index 4adbe4e..b60b6e6 100644 --- a/man/io_uring_prep_send.3 +++ b/man/io_uring_prep_send.3 @@ -14,7 +14,7 @@ io_uring_prep_send - prepare a send request .BI " int sockfd," .BI " const void *buf," .BI " size_t len," -.BI " int flags)" +.BI " int flags);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index 567a93d..6e24124 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -13,7 +13,7 @@ io_uring_prep_sendmsg - prepare a sendmsg request .BI "void io_uring_prep_sendmsg(struct io_uring_sqe *sqe," .BI " int fd," .BI " const struct msghdr *msg," -.BI " unsigned flags)" +.BI " unsigned flags);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index fd26ddf..eb3cc12 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -12,7 +12,7 @@ io_uring_prep_shutdown - prepare a shutdown request .PP .BI "void io_uring_prep_shutdown(struct io_uring_sqe *sqe," .BI " int sockfd," -.BI " int how)" +.BI " int how);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index 403c948..5e7c3ca 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -14,7 +14,7 @@ io_uring_prep_sync_file_range - prepare a sync_file_range request .BI " int fd," .BI " unsigned len," .BI " __u64 offset," -.BI " int flags)" +.BI " int flags);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 90ee83b..11fbddf 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -14,7 +14,7 @@ io_uring_prep_write - prepare I/O write request .BI " int fd," .BI " const void *buf," .BI " unsigned nbytes," -.BI " __u64 offset)" +.BI " __u64 offset);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index 58c2ff2..bad8871 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -15,7 +15,7 @@ io_uring_prep_write_fixed - prepare I/O write request with registered buffer .BI " const void *buf," .BI " unsigned nbytes," .BI " __u64 offset," -.BI " int buf_index)" +.BI " int buf_index);" .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index d644182..d1735be 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -14,7 +14,7 @@ io_uring_prep_writev - prepare vector I/O write request .BI " int fd," .BI " const struct iovec *iovecs," .BI " unsigned nr_vecs," -.BI " __u64 offset)" +.BI " __u64 offset);" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index c73f5e0..095cf76 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -15,7 +15,7 @@ io_uring_prep_writev2 - prepare vector I/O write request with flags .BI " const struct iovec *iovecs," .BI " unsigned nr_vecs," .BI " __u64 offset," -.BI " int flags)" +.BI " int flags);" .fi .PP .SH DESCRIPTION -- cgit v1.2.3 From 1602a0c486b28c714d7cc5fd971a8cd510dd8b41 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 15:32:15 -0700 Subject: Add poll remove man page Signed-off-by: Jens Axboe --- man/io_uring_prep_poll_remove.3 | 53 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 man/io_uring_prep_poll_remove.3 diff --git a/man/io_uring_prep_poll_remove.3 b/man/io_uring_prep_poll_remove.3 new file mode 100644 index 0000000..9458be2 --- /dev/null +++ b/man/io_uring_prep_poll_remove.3 @@ -0,0 +1,53 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_poll_remove 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_poll_remove - prepare a poll deletion request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_poll_remove(struct io_uring_sqe *sqe," +.BI " __u64 user_data);" +.BI " +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_poll_remove() function prepares a poll removal request. The +submission queue entry +.I sqe +is setup to remove a poll request identified by +.I user_data + +Works like +.BR io_uring_prep_cancel (3) +except only looks for poll requests. Apart from that, behavior is identical. +See that man page for specific details. + +.SH RETURN VALUE +None +.SH ERRORS +These are the errors that are reported in the CQE +.I res +field. On success, +.B 0 +is returned. +.TP +.B -ENOENT +The request identified by +.I user_data +could not be located. This could be because it completed before the cancelation +request was issued, or if an invalid identifier is used. +.TP +.B -EINVAL +One of the fields set in the SQE was invalid. +.TP +.B -EALREADY +The execution state of the request has progressed far enough that cancelation +is no longer possible. This should normally mean that it will complete shortly, +either successfully, or interrupted due to the cancelation. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_cancel (3) -- cgit v1.2.3 From 2a523e65507eb04378475f0f3ce1c65f6dedadf1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 15:44:42 -0700 Subject: Add poll update man page Signed-off-by: Jens Axboe --- man/io_uring_prep_poll_update.3 | 85 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 man/io_uring_prep_poll_update.3 diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 new file mode 100644 index 0000000..98e753a --- /dev/null +++ b/man/io_uring_prep_poll_update.3 @@ -0,0 +1,85 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_poll_update 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_poll_update - update an existing poll request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_poll_updatee(struct io_uring_sqe *sqe," +.BI " __u64 old_user_data," +.BI " __u64 new_user_data," +.BI " unsigned poll_mask," +.BI " unsigned flags)" + +.SH DESCRIPTION +.PP +The io_uring_prep_poll_update() function prepares a poll update request. The +submission queue entry +.I sqe +is setup to update a poll request identified by +.I old_user_data, +replacing it with the +.I new_user_data +information. The +.I poll_mask +arguments contains the new mask to use for the poll request, and +.I flags +argument contains modifier flags telling io_uring what fields to update. + +The +.I flags +modifier flags is a bitmask and may contain and OR'ed mask of: +.TP +.B IORING_POLL_UPDATE_EVENTS +If set, the poll update request will replace the existing events being waited +for with the ones specified in the +.I poll_mask +argument to the function. +.TP +.B IORING_POLL_UPDATE_USER_DATA +If set, the poll update request will update the existing user_data of the +request with the value passed in as the +.I new_user_data +argument. +.TP +.B IORING_POLL_ADD_MULTI +If set, this will change the poll request from a singleshot to a multishot +request. This must be used along with +.B IORING_POLL_UPDATE_EVENTS +as the event field must be updated to enable multishot. + +.SH RETURN VALUE +None +.SH ERRORS +These are the errors that are reported in the CQE +.I res +field. On success, +.B 0 +is returned. +.TP +.B -ENOENT +The request identified by +.I user_data +could not be located. This could be because it completed before the cancelation +request was issued, or if an invalid identifier is used. +.TP +.B -EINVAL +One of the fields set in the SQE was invalid. +.TP +.B -EALREADY +The execution state of the request has progressed far enough that cancelation +is no longer possible. This should normally mean that it will complete shortly, +either successfully, or interrupted due to the cancelation. +.TP +.B -ECANCELED +.B IORING_POLL_UPDATE_EVENTS +was set and an error occurred re-arming the poll request with the new mask. +The original poll request is terminated if this happens, and that termination +CQE will contain the reason for the error re-arming. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_cancel (3) -- cgit v1.2.3 From 46998bd07825bd61564c482863a6bcb1e4d45009 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 16:11:49 -0700 Subject: man/io_uring_prep_poll_update.3: correct SEE ALSO section Signed-off-by: Jens Axboe --- man/io_uring_prep_poll_update.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index 98e753a..95588c6 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -82,4 +82,4 @@ was set and an error occurred re-arming the poll request with the new mask. The original poll request is terminated if this happens, and that termination CQE will contain the reason for the error re-arming. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_cancel (3) +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_poll_add (3), io_uring_prep_poll_multishot (3) -- cgit v1.2.3 From ea5ee263a068c4a8dfb5db8cf0e9f44d8005e9a4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 12 Mar 2022 16:13:01 -0700 Subject: Add timeout update/remove man pages Signed-off-by: Jens Axboe --- man/io_uring_prep_timeout.3 | 82 +++++++++++++++++++++++++++++++++++ man/io_uring_prep_timeout_remove.3 | 1 + man/io_uring_prep_timeout_update.3 | 87 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 man/io_uring_prep_timeout.3 create mode 120000 man/io_uring_prep_timeout_remove.3 create mode 100644 man/io_uring_prep_timeout_update.3 diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 new file mode 100644 index 0000000..d0c3093 --- /dev/null +++ b/man/io_uring_prep_timeout.3 @@ -0,0 +1,82 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_poll_timeout 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_timeoute - prepare a timeout request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_timeout(struct io_uring_sqe *sqe," +.BI " struct __kernel_timespec *ts," +.BI " unsigned count," +.BI " unsigned flags);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_timeout() function prepares a timeout request. The submission +queue entry +.I sqe +is setup to arm a timeout specified by +.I ts +and with a timeout count of +.I count +completion entries. The +.I flags +argument holds modifier flags for the request. + +This request type can either be used as a timeout waking anyone sleeping +for events on the CQ ring. The +.I flags +argument may contain: +.TP +.B IORING_TIMEOUT_ABS +The value specified in +.I ts +is an absolute value rather than a relative one. +.TP +.B IORING_TIMEOUT_BOOTTIME +The boottime clock source should be used. +.TP +.B IORING_TIMEOUT_REALTIME +The realtime clock source should be used. +.TP +.B IORING_TIMEOUT_ETIME_SUCCESS +Consider an expirted timeout a success in terms of the posted completion. +Normally a timeout that triggers would return in a +.B -ETIME +CQE +.I res +value. +.PP +The timeout completion event will trigger if either the specified timeout +has occurred, or the specified number of events to wait for have been posted +to the CQ ring. + +.SH RETURN VALUE +None +.SH ERRORS +These are the errors that are reported in the CQE +.I res +field. On success, +.B 0 +is returned. +.TP +.B -ETIME +The specified timeout occurred and triggered the completion event. +.TP +.B -EINVAL +One of the fields set in the SQE was invalid. For example, two clocksources +where given, or the specified timeout seconds or nanoseconds where < 0. +.TP +.B -EFAULT +io_uring was unable to access the data specified by +.I ts. +.TP +.B -ECANCELED +The timeout was canceled by a removal request. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_timeout_remove (3), io_uring_prep_timeout_update (3) diff --git a/man/io_uring_prep_timeout_remove.3 b/man/io_uring_prep_timeout_remove.3 new file mode 120000 index 0000000..5aebd36 --- /dev/null +++ b/man/io_uring_prep_timeout_remove.3 @@ -0,0 +1 @@ +io_uring_prep_timeout_update.3 \ No newline at end of file diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 new file mode 100644 index 0000000..e460779 --- /dev/null +++ b/man/io_uring_prep_timeout_update.3 @@ -0,0 +1,87 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_poll_timeout_update 3 "March 12, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_timeoute_update - prepare a request to update an existing timeout +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_timeout_update(struct io_uring_sqe *sqe," +.BI " struct __kernel_timespec *ts," +.BI " __u64 user_data," +.BI " unsigned flags);" +.BI " +.BI "void io_uring_prep_timeout_remove(struct io_uring_sqe *sqe," +.BI " __u64 user_data," +.BI " unsigned flags);" +.PP +.SH DESCRIPTION +.PP +These functions modify or cancel an existing timeout request. The submission +queue entry +.I sqe +is setup to arm a timeout update or removal specified by +.I user_data +and with modifier flags given by +.I flags. +Additionally, the update request includes a +.I ts +structure, which contains new timeout information. + +For an update request, the +.I flags +member may contain a bitmask of the following values: +.TP +.B IORING_TIMEOUT_ABS +The value specified in +.I ts +is an absolute value rather than a relative one. +.TP +.B IORING_TIMEOUT_BOOTTIME +The boottime clock source should be used. +.TP +.B IORING_TIMEOUT_REALTIME +The realtime clock source should be used. +.TP +.B IORING_TIMEOUT_ETIME_SUCCESS +Consider an expirted timeout a success in terms of the posted completion. +Normally a timeout that triggers would return in a +.B -ETIME +CQE +.I res +value. +.PP + +.SH RETURN VALUE +None +.SH ERRORS +These are the errors that are reported in the CQE +.I res +field. On success, +.B 0 +is returned. +.TP +.B -ENOENT +The timeout identified by +.I user_data +could not be found. It may be invalid, or triggered before the update or +removal request was processed. +.TP +.B -EALREADY +The timeout identified by +.I user_data +is already firing and cannot be canceled. +.TP +.B -EINVAL +One of the fields set in the SQE was invalid. For example, two clocksources +where given, or the specified timeout seconds or nanoseconds where < 0. +.TP +.B -EFAULT +io_uring was unable to access the data specified by +.I ts. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_timeout (3) -- cgit v1.2.3 From 13726214242d00f9b07f545dbb5e7ceb90ddaf05 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 08:00:42 -0600 Subject: Add connect man page Signed-off-by: Jens Axboe --- man/io_uring_prep_connect.3 | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 man/io_uring_prep_connect.3 diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 new file mode 100644 index 0000000..fdbfc28 --- /dev/null +++ b/man/io_uring_prep_connect.3 @@ -0,0 +1,52 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_connect 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_connect - prepare a connect request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_connect(struct io_uring_sqe *sqe," +.BI " int sockfd," +.BI " const struct sockaddr *addr," +.BI " socklen_t addrlen);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_connect() function prepares a connect request. The submission +queue entry +.I sqe +is setup to use the file descriptor +.I sockfd +to start connecting to the destination described by the socket address at +.I addr +and of structure length +.I addrlen. + +This function prepares an async +.BR connect (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), connect (2) -- cgit v1.2.3 From c8a90c0f99f209438151077a1b328d0062af1bd0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 08:08:21 -0600 Subject: Add accept man pages Signed-off-by: Jens Axboe --- man/io_uring_prep_accept.3 | 75 +++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_accept_direct.3 | 1 + 2 files changed, 76 insertions(+) create mode 100644 man/io_uring_prep_accept.3 create mode 120000 man/io_uring_prep_accept_direct.3 diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 new file mode 100644 index 0000000..a7cf4f1 --- /dev/null +++ b/man/io_uring_prep_accept.3 @@ -0,0 +1,75 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_accept 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_accept - prepare a accept request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_accept(struct io_uring_sqe *sqe," +.BI " int sockfd," +.BI " struct sockaddr *addr," +.BI " socklen_t addrlen," +.BI " int flags);" +.BI " +.BI "void io_uring_prep_accept_direct(struct io_uring_sqe *sqe," +.BI " int sockfd," +.BI " struct sockaddr *addr," +.BI " socklen_t addrlen," +.BI " int flags," +.BI " unsigned int file_index);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_accept() function prepares an accept request. The submission +queue entry +.I sqe +is setup to use the file descriptor +.I sockfd +to start accepting a connection request described by the socket address at +.I addr +and of structure length +.I addrlen +and using modifier flags in +.I flags. + +For a direct descriptor accept request, the offset is specified by the +.I file_index +argument. Direct descriptors are io_uring private file descriptors. They +avoid some of the overhead associated with thread shared file tables, and +can be used in any io_uring request that takes a file descriptor. To do so, +.B IOSQE_FIXED_FILE +must be set in the SQE +.I flags +member, and the SQE +.I fd +field should use the direct descriptor value rather than the regular file +descriptor. Direct descriptors are managed like registered files. + +This function prepares an async +.BR accept4 (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), accept4 (2) diff --git a/man/io_uring_prep_accept_direct.3 b/man/io_uring_prep_accept_direct.3 new file mode 120000 index 0000000..0404bf5 --- /dev/null +++ b/man/io_uring_prep_accept_direct.3 @@ -0,0 +1 @@ +io_uring_prep_accept.3 \ No newline at end of file -- cgit v1.2.3 From 0c5ec540d380734919a4a44b68d961dea9bf766e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 08:17:40 -0600 Subject: Add openat man page Signed-off-by: Jens Axboe --- man/io_uring_prep_openat.3 | 78 +++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_openat_direct.3 | 1 + 2 files changed, 79 insertions(+) create mode 100644 man/io_uring_prep_openat.3 create mode 120000 man/io_uring_prep_openat_direct.3 diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 new file mode 100644 index 0000000..9b6f383 --- /dev/null +++ b/man/io_uring_prep_openat.3 @@ -0,0 +1,78 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_openat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_openat - prepare an openat request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_openat(struct io_uring_sqe *sqe," +.BI " int dfd," +.BI " const char *path," +.BI " int flags," +.BI " mode_t mode);" +.BI " +.BI "void io_uring_prep_openat_direct(struct io_uring_sqe *sqe," +.BI " int dfd," +.BI " const char *path," +.BI " int flags," +.BI " mode_t mode," +.BI " unsigned file_index);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_openat() function prepares an openat request. The submission +queue entry +.I sqe +is setup to use the directory file descriptor +.I dfd +to start opening a file described by +.I path +and using the open flags in +.I flags +and using the file mode bits specified in +.I mode. + +For a direct descriptor open request, the offset is specified by the +.I file_index +argument. Direct descriptors are io_uring private file descriptors. They +avoid some of the overhead associated with thread shared file tables, and +can be used in any io_uring request that takes a file descriptor. To do so, +.B IOSQE_FIXED_FILE +must be set in the SQE +.I flags +member, and the SQE +.I fd +field should use the direct descriptor value rather than the regular file +descriptor. Direct descriptors are managed like registered files. + +This function prepares an async +.BR openat (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), openat (2) diff --git a/man/io_uring_prep_openat_direct.3 b/man/io_uring_prep_openat_direct.3 new file mode 120000 index 0000000..67f501e --- /dev/null +++ b/man/io_uring_prep_openat_direct.3 @@ -0,0 +1 @@ +io_uring_prep_openat.3 \ No newline at end of file -- cgit v1.2.3 From 5cf277c93015d05712ab902182df0d3c17cb85f3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 08:23:08 -0600 Subject: Add close man pages Signed-off-by: Jens Axboe --- man/io_uring_prep_close.3 | 56 ++++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_close_direct.3 | 1 + 2 files changed, 57 insertions(+) create mode 100644 man/io_uring_prep_close.3 create mode 120000 man/io_uring_prep_close_direct.3 diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 new file mode 100644 index 0000000..97ecd3d --- /dev/null +++ b/man/io_uring_prep_close.3 @@ -0,0 +1,56 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_close 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_close - prepare a file descriptor close request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_close(struct io_uring_sqe *sqe," +.BI " int fd);" +.BI " +.BI "void io_uring_prep_close_direct(struct io_uring_sqe *sqe," +.BI " unsigned file_index);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_close() function prepares a close request. The submission +queue entry +.I sqe +is setup to close the file descriptor indicated by +.I fd. + +For a direct descriptor close request, the offset is specified by the +.I file_index +argument instead of the +.I fd. +This is identical to unregistering the direct descriptor, and is provided as +a convenience. + +This function prepares an async +.BR close (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), close (2) diff --git a/man/io_uring_prep_close_direct.3 b/man/io_uring_prep_close_direct.3 new file mode 120000 index 0000000..d9ce6a6 --- /dev/null +++ b/man/io_uring_prep_close_direct.3 @@ -0,0 +1 @@ +io_uring_prep_close.3 \ No newline at end of file -- cgit v1.2.3 From 284d8fbab2bce298d3dc72f189161b12a298ee38 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 08:26:31 -0600 Subject: Add openat2 man pages Signed-off-by: Jens Axboe --- man/io_uring_prep_openat2.3 | 79 ++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_openat2_direct.3 | 1 + 2 files changed, 80 insertions(+) create mode 100644 man/io_uring_prep_openat2.3 create mode 120000 man/io_uring_prep_openat2_direct.3 diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 new file mode 100644 index 0000000..57d9219 --- /dev/null +++ b/man/io_uring_prep_openat2.3 @@ -0,0 +1,79 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_openat2 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_openat2 - prepare an openat2 request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.BR "#include " +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_openat2(struct io_uring_sqe *sqe," +.BI " int dfd," +.BI " const char *path," +.BI " int flags," +.BI " struct open_how *how);" +.BI " +.BI "void io_uring_prep_openat2_direct(struct io_uring_sqe *sqe," +.BI " int dfd," +.BI " const char *path," +.BI " int flags," +.BI " struct open_how *how," +.BI " unsigned file_index);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_openat2() function prepares an openat2 request. The submission +queue entry +.I sqe +is setup to use the directory file descriptor +.I dfd +to start opening a file described by +.I path +and using the open flags in +.I flags +and using the instructions on how to open the file given in +.I how. + +For a direct descriptor open request, the offset is specified by the +.I file_index +argument. Direct descriptors are io_uring private file descriptors. They +avoid some of the overhead associated with thread shared file tables, and +can be used in any io_uring request that takes a file descriptor. To do so, +.B IOSQE_FIXED_FILE +must be set in the SQE +.I flags +member, and the SQE +.I fd +field should use the direct descriptor value rather than the regular file +descriptor. Direct descriptors are managed like registered files. + +This function prepares an async +.BR openat2 (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), openat2 (2) diff --git a/man/io_uring_prep_openat2_direct.3 b/man/io_uring_prep_openat2_direct.3 new file mode 120000 index 0000000..2c0e6c9 --- /dev/null +++ b/man/io_uring_prep_openat2_direct.3 @@ -0,0 +1 @@ +io_uring_prep_openat2.3 \ No newline at end of file -- cgit v1.2.3 From 900c481a3845a26860fc8faff4655b097be38e05 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 08:31:42 -0600 Subject: Add fadvise/madvise man pages Signed-off-by: Jens Axboe --- man/io_uring_prep_fadvise.3 | 56 +++++++++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_madvise.3 | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 man/io_uring_prep_fadvise.3 create mode 100644 man/io_uring_prep_madvise.3 diff --git a/man/io_uring_prep_fadvise.3 b/man/io_uring_prep_fadvise.3 new file mode 100644 index 0000000..9df6254 --- /dev/null +++ b/man/io_uring_prep_fadvise.3 @@ -0,0 +1,56 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_fadvise 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_fadvise - prepare a fadvise request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_fadvise(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " __u64 offset," +.BI " off_t len," +.BI " int advice);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_fadvise() function prepares an fadvise request. The submission +queue entry +.I sqe +is setup to use the file descriptor pointed to by +.I fd +to start an fadvise operation at +.I offset +and of +.I len +length in bytes, giving it the advise located in +.I advice. + +This function prepares an async +.BR posix_fadvise (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), posix_fadvise (2) diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 new file mode 100644 index 0000000..db1465e --- /dev/null +++ b/man/io_uring_prep_madvise.3 @@ -0,0 +1,56 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_madvise 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_madvise - prepare a madvise request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_madvise(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " void *addr," +.BI " off_t len," +.BI " int advice);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_madvise() function prepares an madvise request. The submission +queue entry +.I sqe +is setup to use the file descriptor pointed to by +.I fd +to start an madvise operation at the virtual address of +.I addr +and of +.I len +length in bytes, giving it the advise located in +.I advice. + +This function prepares an async +.BR posix_madvise (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), posix_madvise (2) -- cgit v1.2.3 From 08b89ff1bd9587cbff4b0e5389488ad304ea78d6 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 08:37:02 -0600 Subject: man: add necessary other headers to man pages If the command takes arguments that are structs or flags that are specific to the original request, then add the necessary headers. Signed-off-by: Jens Axboe --- man/io_uring_prep_accept.3 | 1 + man/io_uring_prep_connect.3 | 2 ++ man/io_uring_prep_poll_add.3 | 1 + man/io_uring_prep_poll_update.3 | 1 + man/io_uring_prep_readv.3 | 1 + man/io_uring_prep_readv2.3 | 1 + man/io_uring_prep_recvmsg.3 | 2 ++ man/io_uring_prep_sendmsg.3 | 2 ++ man/io_uring_prep_shutdown.3 | 1 + man/io_uring_prep_sync_file_range.3 | 1 + man/io_uring_prep_writev.3 | 1 + man/io_uring_prep_writev2.3 | 1 + 12 files changed, 15 insertions(+) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index a7cf4f1..8d88ea9 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -8,6 +8,7 @@ io_uring_prep_accept - prepare a accept request .fi .SH SYNOPSIS .nf +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_accept(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 index fdbfc28..3203df4 100644 --- a/man/io_uring_prep_connect.3 +++ b/man/io_uring_prep_connect.3 @@ -8,6 +8,8 @@ io_uring_prep_connect - prepare a connect request .fi .SH SYNOPSIS .nf +.BR "#include " +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_connect(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index 34189f2..7021ebc 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -8,6 +8,7 @@ io_uring_prep_poll_add - prepare a poll request .fi .SH SYNOPSIS .nf +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_poll_add(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index 95588c6..361313d 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -8,6 +8,7 @@ io_uring_prep_poll_update - update an existing poll request .fi .SH SYNOPSIS .nf +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_poll_updatee(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index f0e94df..2b7e27f 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -8,6 +8,7 @@ io_uring_prep_readv - prepare vector I/O read request .fi .SH SYNOPSIS .nf +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_readv(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 961e107..be9b027 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -9,6 +9,7 @@ io_uring_prep_readv2 - prepare vector I/O read request with flags .SH SYNOPSIS .nf +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_readv2(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index a30cecf..1186cb8 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -8,6 +8,8 @@ io_uring_prep_recvmsg - prepare a recvmsg request .fi .SH SYNOPSIS .nf +.BR "#include " +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_recvmsg(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index 6e24124..20de5d6 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -8,6 +8,8 @@ io_uring_prep_sendmsg - prepare a sendmsg request .fi .SH SYNOPSIS .nf +.BR "#include " +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_sendmsg(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index eb3cc12..6152eae 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -8,6 +8,7 @@ io_uring_prep_shutdown - prepare a shutdown request .fi .SH SYNOPSIS .nf +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_shutdown(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index 5e7c3ca..680bd31 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -8,6 +8,7 @@ io_uring_prep_sync_file_range - prepare a sync_file_range request .fi .SH SYNOPSIS .nf +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_sync_file_range(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index d1735be..81d460d 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -8,6 +8,7 @@ io_uring_prep_writev - prepare vector I/O write request .SH SYNOPSIS .nf +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_writev(struct io_uring_sqe *sqe," diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index 095cf76..82e2c6e 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -8,6 +8,7 @@ io_uring_prep_writev2 - prepare vector I/O write request with flags .SH SYNOPSIS .nf +.BR "#include " .BR "#include " .PP .BI "void io_uring_prep_writev2(struct io_uring_sqe *sqe," -- cgit v1.2.3 From 7e38902708776ce23f628f3aff54fc55476dc360 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 08:47:31 -0600 Subject: Add splice man page Signed-off-by: Jens Axboe --- man/io_uring_prep_splice.3 | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 man/io_uring_prep_splice.3 diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3 new file mode 100644 index 0000000..c0ee835 --- /dev/null +++ b/man/io_uring_prep_splice.3 @@ -0,0 +1,77 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_splice 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_splice - prepare an splice request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_splice(struct io_uring_sqe *sqe," +.BI " int fd_in," +.BI " int64_t off_in," +.BI " int fd_out," +.BI " int64_t off_out," +.BI " unsigned int nbytes," +.BI " int splice_flags);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_splice() function prepares a splice request. The submission +queue entry +.I sqe +is setup to use as input the file descriptor +.I fd_in +at offset +.I off_in, +splicing data to the file descriptor at +.I fd_out +and at offset +.I off_out. +.I nbytes +bytes of data should be spliced between the two descriptors. +.I splice_flags +are modifier flags for the operation. See +.BR splice (2) +for the generic splice flags. + +If the +.I fd_out +descriptor, +.B IOSQE_FIXED_FILE +can be set in the SQE to indicate that. For the input file, the io_uring +specific +.B SPLICE_F_FD_IN_FIXED +can be set in +.I splice_flags +and +.I fd_in +given as a registered file descriptor offset. + +This function prepares an async +.BR splice (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), splice (2) -- cgit v1.2.3 From 8710a5b5c85e10f4e1eb0917025b6d293c85fcee Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 08:52:07 -0600 Subject: Add tee man page Signed-off-by: Jens Axboe --- man/io_uring_prep_tee.3 | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 man/io_uring_prep_tee.3 diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3 new file mode 100644 index 0000000..e64da26 --- /dev/null +++ b/man/io_uring_prep_tee.3 @@ -0,0 +1,70 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_tee 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_tee - prepare a tee request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_tee(struct io_uring_sqe *sqe," +.BI " int fd_in," +.BI " int fd_out," +.BI " unsigned int nbytes," +.BI " int splice_flags);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_tee() function prepares a tee request. The submission queue +entry +.I sqe +is setup to use as input the file descriptor +.I fd_in +and as output the file descriptor +.I fd_out +duplicating +.I nbytes +bytes worth of data. +.I flags +are modifier flags for the operation. See +.BR tee (2) +for the generic splice flags. + +If the +.I fd_out +descriptor, +.B IOSQE_FIXED_FILE +can be set in the SQE to indicate that. For the input file, the io_uring +specific +.B SPLICE_F_FD_IN_FIXED +can be set and +.I fd_in +given as a registered file descriptor offset. + +This function prepares an async +.BR tee (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), splice (2), tee (2) -- cgit v1.2.3 From 109cb06c35674e77e2b63bd07ae21eea5f4a4999 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 10:20:21 -0600 Subject: Add fallocate man page Signed-off-by: Jens Axboe --- man/io_uring_prep_fallocate.3 | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 man/io_uring_prep_fallocate.3 diff --git a/man/io_uring_prep_fallocate.3 b/man/io_uring_prep_fallocate.3 new file mode 100644 index 0000000..b587119 --- /dev/null +++ b/man/io_uring_prep_fallocate.3 @@ -0,0 +1,57 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_fallocate 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_fallocate - prepare a fallocate request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_fallocate(struct io_uring_sqe *sqe," +.BI " int fd," +.BI " int mode," +.BI " off_t offset," +.BI " off_t len);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_fallocate() function prepares a fallocate request. The +submission queue entry +.I sqe +is setup to use the file descriptor pointed to by +.I fd +to start a fallocate operation described by +.I mode +at offset +.I offset +and +.I len +length in bytes. + +This function prepares an async +.BR fallocate (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), fallocate (2) -- cgit v1.2.3 From 83f5ccb16ca495bbaf989a8af7fc381f24151a7a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 10:34:54 -0600 Subject: Add man page for registered file update request Signed-off-by: Jens Axboe --- man/io_uring_prep_files_update.3 | 70 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 man/io_uring_prep_files_update.3 diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 new file mode 100644 index 0000000..3239a7c --- /dev/null +++ b/man/io_uring_prep_files_update.3 @@ -0,0 +1,70 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_files_update 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_files_update - prepare a registered file update request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_files_update(struct io_uring_sqe *sqe," +.BI " int *fds," +.BI " unsigned nr_fds," +.BI " int offset);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_files_update() function prepares a request for updating +a number of previously registered file descriptors. The +submission queue entry +.I sqe +is setup to use the file descriptor array pointed to by +.I fds +and of +.I nr_fds +in length to update that amount of previously registered files starting at +offset +.I offset. + +One a previously registered file is updated with a new one, the existing +entry is updated the removed from the table. This operation is equivalent to +first unregistering that entry and then inserting a new one, just bundled into +one combined operation. + +.SH RETURN VALUE +None +.SH ERRORS +These are the errors that are reported in the CQE +.I res +field. On success, +.I res +will contain the number of successfully updated file descriptors. On error, +the following errors can occur. +.TP +.B -ENOMEM +The kernel was unable to allocate memory for the request. +.TP +.B -EINVAL +One of the fields set in the SQE was invalid. +.TP +.B -EFAULT +The kernel was unable to copy in the memory pointed to by +.I fds. +.TP +.B -EBADF +On of the descriptors located in +.I fds +didn't refer to a valid file descriptor, or one of the file descriptors in +the array referred to an io_uring instance. +.TP +.B -EOVERFLOW +The product of +.I offset +and +.I nr_fds +exceed the valid amount or overflowed. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2) -- cgit v1.2.3 From 7c20668a784e2c3338a9bb907ca0f7997028d566 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 10:38:45 -0600 Subject: Add statx man page Signed-off-by: Jens Axboe --- man/io_uring_prep_statx.3 | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 man/io_uring_prep_statx.3 diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3 new file mode 100644 index 0000000..9640e69 --- /dev/null +++ b/man/io_uring_prep_statx.3 @@ -0,0 +1,62 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_statx 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_statx - prepare a statx request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.BR "#include " +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_statx(struct io_uring_sqe *sqe," +.BI " int dirfd," +.BI " const char *path," +.BI " int flags," +.BI " unsigned mask," +.BI " struct statx *statxbuf);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_statx() function prepares a statx request. The +submission queue entry +.I sqe +is setup to use the directory file descriptor pointed to by +.I dirfd +to start a statx operation on the path identified by +.I path +and using the flags given in +.I flags +for the fields specified by +.I mask +and into the buffer located at +.I statxbuf. + +This function prepares an async +.BR statx (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), statx (2) -- cgit v1.2.3 From bd81985ae3bd87a84ea81644317258567d6e300f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 10:57:14 -0600 Subject: Add provide buffers man page Signed-off-by: Jens Axboe --- man/io_uring_prep_provide_buffers.3 | 127 ++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 man/io_uring_prep_provide_buffers.3 diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3 new file mode 100644 index 0000000..9f1fc6c --- /dev/null +++ b/man/io_uring_prep_provide_buffers.3 @@ -0,0 +1,127 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_provide_buffers 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_provide_buffers - prepare a provide buffers request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_provide_buffers(struct io_uring_sqe *sqe," +.BI " void *addr," +.BI " int len," +.BI " int nr," +.BI " int bgid," +.BI " int bid);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_provide_buffers() function prepares a request for providing +the kernel with buffers. The submission queue entry +.I sqe +is setup to consume +.I len +number of buffers starting at +.I addr +and identified by the buffer group ID of +.I bgid +and numbered sequentially starting at +.I bid. + +This function sets up a request to provide buffers to the io_uring context +that can be used by read or receive operations. This is done by filling in +the SQE +.I buf_group +field and setting +.B IOSQE_BUFFER_SELECT +in the SQE +.I flags +member. If buffer selection is used for a request, no buffer should be provided +in the address field. Instead, the group ID is set to match one that was +previously provided to the kernel. The kernel will then select a buffer from +this group for the IO operation. On successful completion of the IO request, +the CQE +.I flags +field will have +.B IORING_CQE_F_BUFFER +set and the selected buffer ID will be indicated by the upper 16-bits of the +.I flags +field. + +Different buffer group IDs can be used by the application to have different +sizes or types of buffers available. Once a buffer has been consumed for an +operation, it is no longer known to io_uring. It must be re-provided if so +desired, or freed by the application if no longer needed. + +The buffer IDs are internally tracked from +.I bid +and sequentially ascending from that value. If +.B 16 +buffers are provided start with an initial +.I bid +of 0, then the buffer IDs will range from +.B 0..15. +The application must be aware of this to make sense of the buffer ID passed +back in the CQE. + +Not all requests support buffer selection, as it only really makes sense for +requests that receive data from the kernel rather than write or provide data. +Currently, this mode of operation is supported for any file read or socket +receive request. Attempting to use +.B IOSQE_BUFFER_SELECT +with a command that doesn't support it will result in a CQE +.I res +error of +.B -EINVAL. +Buffer selection will work with operations that take a +.BR struct iovec +as its data destination, but only if 1 iovec is provided. +. +.SH RETURN VALUE +None +.SH ERRORS +These are the errors that are reported in the CQE +.I res +field. On success, +.I res +will contain the number of successfully provided buffers. On error, +the following errors can occur. +.TP +.B -ENOMEM +The kernel was unable to allocate memory for the request. +.TP +.B -EINVAL +One of the fields set in the SQE was invalid. +.TP +.B -E2BIG +The number of buffers provided was too big, or the +.I bid +was too big. A max value of +.B USHRT_MAX +buffers can be specified. +.TP +.B -EFAULT +Some of the user memory given was invalid for the application. +.TP +.B -EBADF +On of the descriptors located in +.I fds +didn't refer to a valid file descriptor, or one of the file descriptors in +the array referred to an io_uring instance. +.TP +.B -EOVERFLOW +The product of +.I len +and +.I nr +exceed the valid amount or overflowed, or the sum of +.I addr +and the length of buffers overflowed. +.TP +.B -EBUSY +Attempt to update a slot that is already used. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), io_uring_prep_remove_buffers (3) -- cgit v1.2.3 From db47f65082924bdb8c8017e2d6aad440d9047ed5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 11:05:32 -0600 Subject: Add buffer remove prep man page Signed-off-by: Jens Axboe --- man/io_uring_prep_remove_buffers.3 | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 man/io_uring_prep_remove_buffers.3 diff --git a/man/io_uring_prep_remove_buffers.3 b/man/io_uring_prep_remove_buffers.3 new file mode 100644 index 0000000..ce6a5ce --- /dev/null +++ b/man/io_uring_prep_remove_buffers.3 @@ -0,0 +1,48 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_remove_buffers 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_remove_buffers - prepare a remove buffers request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_prep_remove_buffers(struct io_uring_sqe *sqe," +.BI " int nr," +.BI " int bgid);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_remove_buffers() function prepares a request for removing +previously supplied buffers. The submission queue entry +.I sqe +is setup to remove +.I nr +number of buffers from the buffer group ID indicated by +.I bgid. + +.SH RETURN VALUE +None +.SH ERRORS +These are the errors that are reported in the CQE +.I res +field. On success, +.I res +will contain the number of successfully removed buffers. On error, +the following errors can occur. +.TP +.B -ENOMEM +The kernel was unable to allocate memory for the request. +.TP +.B -EINVAL +One of the fields set in the SQE was invalid. +.TP +.B -ENOENT +No buffers exist at the specified +.I bgid +buffer group ID. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), io_uring_prep_provide_buffers (3) -- cgit v1.2.3 From 1a97e3a8516b537eaebf4a038d2229d5ccb0be7c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 11:11:32 -0600 Subject: Add unlinkat man page Signed-off-by: Jens Axboe --- man/io_uring_prep_unlinkat.3 | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 man/io_uring_prep_unlinkat.3 diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 new file mode 100644 index 0000000..5c93c0f --- /dev/null +++ b/man/io_uring_prep_unlinkat.3 @@ -0,0 +1,54 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_unlinkat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_unlinkat - prepare an unlinkat request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_unlinkat(struct io_uring_sqe *sqe," +.BI " int dirfd," +.BI " const char *path," +.BI " int flags);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_unlinkat() function prepares an unlinkat request. The +submission queue entry +.I sqe +is setup to use the directory file descriptor pointed to by +.I dirfd +to start an unlinkat operation on the path identified by +.I path +and using the flags given in +.I flags. + +This function prepares an async +.BR unlinkat (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), unlinkat (2) -- cgit v1.2.3 From 1031c133eb228902db0a864cecd25e1f9be8a590 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 11:15:37 -0600 Subject: Add renameat/renameat2 man pages Signed-off-by: Jens Axboe --- man/io_uring_prep_renameat.3 | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 man/io_uring_prep_renameat.3 diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 new file mode 100644 index 0000000..09bdf76 --- /dev/null +++ b/man/io_uring_prep_renameat.3 @@ -0,0 +1,64 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_renameat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_renameat - prepare a renameat request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_renameat(struct io_uring_sqe *sqe," +.BI " int olddirfd," +.BI " const char *oldpath," +.BI " int newdirfd," +.BI " const char *newpath," +.BI " int flags);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_renameat() function prepares a renameat request. The +submission queue entry +.I sqe +is setup to use the old directory file descriptor pointed to by +.I olddirfd +and old path pointed to by +.I oldpath +with the new directory file descriptor pointed to by +.I newdirfd +and the new path pointed to by +.I newpath +and using the specified flags in +.I flags. + +This function prepares an async +.BR renameat2 (2) +request. If +.I flags +is zero, then this call is similar to the +.BR renameat (2) +system call. See those man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), renameat (2), renameat2 (2) -- cgit v1.2.3 From 2b019040fd9ab927d97c9a9a0a0989ad45dd4560 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 11:19:37 -0600 Subject: Add mkdirat man page Signed-off-by: Jens Axboe --- man/io_uring_prep_mkdirat.3 | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 man/io_uring_prep_mkdirat.3 diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 new file mode 100644 index 0000000..e9d3c2a --- /dev/null +++ b/man/io_uring_prep_mkdirat.3 @@ -0,0 +1,54 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_mkdirat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_mkdirat - prepare an mkdirat request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_mkdirat(struct io_uring_sqe *sqe," +.BI " int dirfd," +.BI " const char *path," +.BI " mode_t mode);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_mkdirat() function prepares an mkdirat request. The +submission queue entry +.I sqe +is setup to use the directory file descriptor pointed to by +.I dirfd +to start an mkdirat operation on the path identified by +.I path +with the mode given in +.I mode. + +This function prepares an async +.BR mkdirat (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), mkdirat (2) -- cgit v1.2.3 From 50d5275de9dcd5e346565e47f9c92fe26031b439 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 11:23:38 -0600 Subject: Add symlinkat man page Signed-off-by: Jens Axboe --- man/io_uring_prep_symlinkat.3 | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 man/io_uring_prep_symlinkat.3 diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 new file mode 100644 index 0000000..ec0b5e0 --- /dev/null +++ b/man/io_uring_prep_symlinkat.3 @@ -0,0 +1,54 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_symlinkat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_symlinkat - prepare a symlinkat request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_symlinkat(struct io_uring_sqe *sqe," +.BI " const char *target," +.BI " int newdirfd," +.BI " const char *linkpath);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_symlinkat() function prepares a symlinkat request. The +submission queue entry +.I sqe +is setup to symlink the target path pointed to by +.I target +to the new destination indicated by +.I newdirfd +and +.I linkpath. + +This function prepares an async +.BR symlinkat (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), symlinkat (2) -- cgit v1.2.3 From 3aea5a1b71e35bbf69798ccdf5d5672185e18a0c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 11:25:37 -0600 Subject: Add linkat man page Signed-off-by: Jens Axboe --- man/io_uring_prep_linkat.3 | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 man/io_uring_prep_linkat.3 diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 new file mode 100644 index 0000000..e950219 --- /dev/null +++ b/man/io_uring_prep_linkat.3 @@ -0,0 +1,60 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_linkat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_linkat - prepare a linkat request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_linkat(struct io_uring_sqe *sqe," +.BI " int olddirfd," +.BI " const char *oldpath," +.BI " int newdirfd," +.BI " const char *newpath," +.BI " int flags);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_linkat() function prepares a linkat request. The +submission queue entry +.I sqe +is setup to use the old directory file descriptor pointed to by +.I olddirfd +and old path pointed to by +.I oldpath +with the new directory file descriptor pointed to by +.I newdirfd +and the new path pointed to by +.I newpath +and using the specified flags in +.I flags. + +This function prepares an async +.BR linkat (2) +request. See that man page for details. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), linkat (2) -- cgit v1.2.3 From e97e8641b0ada5849bacab9865a2666fa1fbfecb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 11:45:49 -0600 Subject: Add io_uring_queue_init_params man page Signed-off-by: Jens Axboe --- man/io_uring_queue_init.3 | 23 +++++++++++++++++++---- man/io_uring_queue_init_params.3 | 1 + 2 files changed, 20 insertions(+), 4 deletions(-) create mode 120000 man/io_uring_queue_init_params.3 diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index 2d66694..edde6a4 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -10,14 +10,21 @@ io_uring_queue_init - setup io_uring submission and completion queues .nf .BR "#include " .PP -.BI "int io_uring_queue_init(unsigned " entries ", struct io_uring *" ring , -.BI " unsigned " flags ); +.BI "int io_uring_queue_init(unsigned entries," +.BI " struct io_uring *ring," +.BI " unsigned flags);" +.BI " +.BI "int io_uring_queue_init_params(unsigned entries," +.BI " struct io_uring *ring," +.BI " struct io_uring_params *params);" .fi .PP .SH DESCRIPTION .PP -The io_uring_queue_init() function executes the io_uring_setup syscall to -initialize the submission and completion queues in the kernel with at least +The io_uring_queue_init() function executes the +.BR io_uring_setup (2) +system call to initialize the submission and completion queues in the kernel +with at least .I entries entries and then maps the resulting file descriptor to memory shared between the application and the kernel. @@ -31,6 +38,14 @@ will point to the shared memory containing the io_uring queues. On failure will be passed through to the io_uring_setup syscall (see .BR io_uring_setup (2)). +If the +.BR io_uring_queue_init_params (3) +variant is used, then the parameters indicated by +.I params +will be passed straight through to the +.BR io_uring_setup (2) +system call. + On success, the resources held by .I ring should be released via a corresponding call to diff --git a/man/io_uring_queue_init_params.3 b/man/io_uring_queue_init_params.3 new file mode 120000 index 0000000..c91609e --- /dev/null +++ b/man/io_uring_queue_init_params.3 @@ -0,0 +1 @@ +io_uring_queue_init.3 \ No newline at end of file -- cgit v1.2.3 From 4632a6ac581790c2db6fd5dd1b85905298726afe Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 12:11:05 -0600 Subject: man/io_uring_enter.2: mention IORING_OP_MSG_RING uses cqe flags Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index c16a526..44d38b0 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -1247,7 +1247,9 @@ is used for certain commands, like .B IORING_OP_POLL_ADD or in conjunction with .B IOSQE_BUFFER_SELECT -, see those entries. +or +.B IORING_OP_MSG_RING, +, see those entries for details. .I res is the operation-specific result, but io_uring-specific errors (e.g. flags or opcode invalid) are returned through this field. -- cgit v1.2.3 From 32a68b4cd32cb59dce52086dd21d0b50606c7495 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 12:13:14 -0600 Subject: man/io_uring_enter.2: add description of IORING_ENTER_REGISTERED_RING Signed-off-by: Jens Axboe --- man/io_uring_enter.2 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 44d38b0..22dbbd5 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -93,6 +93,13 @@ is set to a valid pointer, then this time value indicates the timeout for waiting on events. If an application is waiting on events and wishes to stop waiting after a specified amount of time, then this can be accomplished directly in version 5.11 and newer by using this feature. +.TP +.B IORING_ENTER_REGISTERED_RING +If the ring file descriptor has been registered through use of +.B IORING_REGISTER_RING_FDS, +then setting this flag will tell the kernel that the +.I ring_fd +passed in is the registered ring offset rather than a normal file descriptor. .PP .PP -- cgit v1.2.3 From ce8ab00b5c8d6bc063073949b8dacf7e4313da73 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 16:50:52 -0600 Subject: Add io_uring_register_iowq_aff() man page Include io_uring_unregister_iowq_aff() as well. Signed-off-by: Jens Axboe --- man/io_uring_register_iowq_aff.3 | 59 ++++++++++++++++++++++++++ man/io_uring_register_iowq_max_workers.3 | 71 ++++++++++++++++++++++++++++++++ man/io_uring_unregister_iowq_aff.3 | 1 + 3 files changed, 131 insertions(+) create mode 100644 man/io_uring_register_iowq_aff.3 create mode 100644 man/io_uring_register_iowq_max_workers.3 create mode 120000 man/io_uring_unregister_iowq_aff.3 diff --git a/man/io_uring_register_iowq_aff.3 b/man/io_uring_register_iowq_aff.3 new file mode 100644 index 0000000..89a520b --- /dev/null +++ b/man/io_uring_register_iowq_aff.3 @@ -0,0 +1,59 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_register_iowq_aff 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_register_iowq_aff - register async worker CPU affinities +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.PP +.BI "int io_uring_register_iowq_aff(struct io_uring *ring," +.BI " size_t cpusz," +.BI " const cpu_set_t *mask); +.BI " +.BI "void io_uring_unregister_iowq_aff(struct io_uring *ring);" +.PP +.SH DESCRIPTION +.PP +The io_uring_prep_register_iowq_aff() function registers a set of CPU affinities +to be used by the io_uring async workers. By default, io_uring async workers +are allowed to run on any CPU in the system. If this function is called with +.I ring +set to the ring in question and +.I mask +set to a pointer to a +.BR cpu_set_t +value and +.I cpusz +set to the size of the CPU set, then async workers will only be allowed to run +on the CPUs specified in the mask. Existing workers may need to hit a schedule +point before they are migrated. + +For unregistration, +.BR io_uring_unregister_iowq_aff (3) +may be called to restore CPU affinities to the default. + +.SH RETURN VALUE +Returns +.B 0 +on success, or any of the following values in case of error. +.TP +.B -EFAULT +The kernel was unable to copy the memory pointer to by +.I mask +as it was invalid. +.TP +.B -ENOMEM +The kernel was unable to allocate memory for the new CPU mask. +.TP +.B -EINVAL +.I cpusz +or +.I mask +was NULL/0, or any other value specified was invalid. +.SH SEE ALSO +.BR io_uring_queue_init (3), io_uring_register (2) diff --git a/man/io_uring_register_iowq_max_workers.3 b/man/io_uring_register_iowq_max_workers.3 new file mode 100644 index 0000000..ffb895e --- /dev/null +++ b/man/io_uring_register_iowq_max_workers.3 @@ -0,0 +1,71 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_register_iowq_max_workers 3 "March 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_register_iowq_max_workers - modify the maximum allowed async workers +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "void io_uring_register_iowq_max_workers(struct io_uring *ring," +.BI " unsigned int *values);" +.PP +.SH DESCRIPTION +.PP +io_uring async workers are split into two types: +.TP +.B Bounded +These workers have a bounded execution time. Examples of that are filesystem +reads, which normally complete in a relatively short amount of time. In case +of disk failures, they are still bounded by a timeout operation that will +abort them if exceeded. +.TP +.B Unbounded +Work items here may take an indefinite amount of time to complete. Examples +include doing IO to sockets, pipes, or any other non-regular type of file. + +.PP +By default, the amount of bounded IO workers is limited to how many SQ entries +the ring was setup with, or 4 times the number of online CPUs in the system, +whichever is smaller. Unbounded workers are only limited by the process task +limit, as indicated by the rlimit +.B RLIMIT_NPROC +limit. + +This can be modified by calling +.BR io_uring_register_iowq_max_workers +with +.I ring +set to the ring in question, and +.I values +pointing to an array of two values. The first element should contain the number +of desired bounded workers, and the second element should contain the number +of desired unbounded workers. These are both maximum values, io_uring will +not maintain a high count of idle workers, they are reaped when they are not +necessary anymore. + +If called with both values set to 0, the existing values are returned. + +.SH RETURN VALUE +Returns +.B 0 +on success, with +.I values +containing the previous values for the settings. On error, any of the following +may be returned. +.TP +.B -EFAULT +The kernel was unable to copy the memory pointer to by +.I values +as it was invalid. +.TP +.B -EINVAL +.I values +was +.B NULL +or the new values exceeded the maximum allowed value. +.SH SEE ALSO +.BR io_uring_queue_init (3), io_uring_register (2) diff --git a/man/io_uring_unregister_iowq_aff.3 b/man/io_uring_unregister_iowq_aff.3 new file mode 120000 index 0000000..c29bd44 --- /dev/null +++ b/man/io_uring_unregister_iowq_aff.3 @@ -0,0 +1 @@ +io_uring_register_iowq_aff.3 \ No newline at end of file -- cgit v1.2.3 From d88bc35e0b971f78ca1f4478cfa2c0833c88740e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 13 Mar 2022 17:05:53 -0600 Subject: Add io_uring_register_iowq_max_workers() man page Signed-off-by: Jens Axboe --- man/io_uring_register_iowq_max_workers.3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/io_uring_register_iowq_max_workers.3 b/man/io_uring_register_iowq_max_workers.3 index ffb895e..b277828 100644 --- a/man/io_uring_register_iowq_max_workers.3 +++ b/man/io_uring_register_iowq_max_workers.3 @@ -10,8 +10,8 @@ io_uring_register_iowq_max_workers - modify the maximum allowed async workers .nf .BR "#include " .PP -.BI "void io_uring_register_iowq_max_workers(struct io_uring *ring," -.BI " unsigned int *values);" +.BI "int io_uring_register_iowq_max_workers(struct io_uring *ring," +.BI " unsigned int *values);" .PP .SH DESCRIPTION .PP -- cgit v1.2.3 From c34070e08199491fe9653617364f4aea9b9b22be Mon Sep 17 00:00:00 2001 From: Sam James Date: Mon, 14 Mar 2022 14:18:55 +0000 Subject: liburing.h: define GNU_SOURCE for cpu_set_t On musl, cpu_set_t is only exposed if GNU_SOURCE is defined. While in the liburing build system, this is set (43b7ec8d17888df0debccda27dd58f4d1b90245e), it can't be guaranteed that folks including the header externally will set that macro. Noticed while investigating a build failure for glusterfs on a musl system: ``` configure:17701: checking for liburing.h configure:17701: x86_64-gentoo-linux-musl-gcc -c -pipe -march=native -fno-diagnostics-color -O2 conftest.c >&5 In file included from conftest.c:105: /usr/include/liburing.h:162:39: error: unknown type name 'cpu_set_t' 162 | const cpu_set_t *mask); | ^~~~~~~~~ configure:17701: $? = 1 ``` Just like _XOPEN_SOURCE, set if needed. Bug: https://bugs.gentoo.org/829293 Bug: https://github.com/axboe/liburing/issues/422 See: 43b7ec8d17888df0debccda27dd58f4d1b90245e Signed-off-by: Sam James --- src/include/liburing.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index a450d56..b0c8704 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -6,6 +6,10 @@ #define _XOPEN_SOURCE 500 /* Required for glibc to expose sigset_t */ #endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* Required for musl to expose cpu_set_t */ +#endif + #include #include #include -- cgit v1.2.3 From ebf8021dbef26fc76a39ea77867a5c8da02629a5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 14 Mar 2022 09:18:49 -0600 Subject: man/io_uring_prep_poll_add.3: remove extra space Signed-off-by: Jens Axboe --- man/io_uring_prep_poll_add.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index 7021ebc..2ecb1aa 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -13,7 +13,7 @@ io_uring_prep_poll_add - prepare a poll request .PP .BI "void io_uring_prep_poll_add(struct io_uring_sqe *sqe," .BI " int fd," -.BI " unsigned poll_mask);" +.BI " unsigned poll_mask);" .BI " .BI "void io_uring_prep_poll_multishot(struct io_uring_sqe *sqe," .BI " int fd," -- cgit v1.2.3 From 75b9e7b1ba710d6a22c5f295be99feb53219e389 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 14 Mar 2022 09:19:17 -0600 Subject: man/io_uring_prep_poll_update.3: remove extra 'e' Signed-off-by: Jens Axboe --- man/io_uring_prep_poll_update.3 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index 361313d..b767af2 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -11,11 +11,11 @@ io_uring_prep_poll_update - update an existing poll request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_poll_updatee(struct io_uring_sqe *sqe," -.BI " __u64 old_user_data," -.BI " __u64 new_user_data," -.BI " unsigned poll_mask," -.BI " unsigned flags)" +.BI "void io_uring_prep_poll_update(struct io_uring_sqe *sqe," +.BI " __u64 old_user_data," +.BI " __u64 new_user_data," +.BI " unsigned poll_mask," +.BI " unsigned flags)" .SH DESCRIPTION .PP -- cgit v1.2.3 From 888d010cd3cddceaba91ca712d084815ce5492bc Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 14 Mar 2022 09:22:32 -0600 Subject: man: add blurb about data passed in structs being stable across submit All commands that take some kind of state in a struct must ensure that it is stable until the command has been submitted, but can rely on that state being stable in the kernel once submit is done. They need not keep it stable until the command completes. Link: https://github.com/axboe/liburing/issues/486 Signed-off-by: Jens Axboe --- man/io_uring_prep_accept.3 | 10 ++++++++++ man/io_uring_prep_connect.3 | 10 ++++++++++ man/io_uring_prep_files_update.3 | 10 ++++++++++ man/io_uring_prep_linkat.3 | 10 ++++++++++ man/io_uring_prep_mkdirat.3 | 10 ++++++++++ man/io_uring_prep_openat.3 | 10 ++++++++++ man/io_uring_prep_openat2.3 | 10 ++++++++++ man/io_uring_prep_readv.3 | 10 ++++++++++ man/io_uring_prep_readv2.3 | 10 ++++++++++ man/io_uring_prep_recvmsg.3 | 10 ++++++++++ man/io_uring_prep_renameat.3 | 10 ++++++++++ man/io_uring_prep_sendmsg.3 | 10 ++++++++++ man/io_uring_prep_statx.3 | 10 ++++++++++ man/io_uring_prep_symlinkat.3 | 10 ++++++++++ man/io_uring_prep_timeout.3 | 10 ++++++++++ man/io_uring_prep_timeout_update.3 | 10 ++++++++++ man/io_uring_prep_unlinkat.3 | 10 ++++++++++ man/io_uring_prep_writev.3 | 10 ++++++++++ man/io_uring_prep_writev2.3 | 10 ++++++++++ 19 files changed, 190 insertions(+) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 8d88ea9..1af0f0f 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -72,5 +72,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), accept4 (2) diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 index 3203df4..496e4de 100644 --- a/man/io_uring_prep_connect.3 +++ b/man/io_uring_prep_connect.3 @@ -50,5 +50,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), connect (2) diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index 3239a7c..5a9202c 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -66,5 +66,15 @@ The product of and .I nr_fds exceed the valid amount or overflowed. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2) diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index e950219..2ba485a 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -56,5 +56,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), linkat (2) diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index e9d3c2a..7b662e6 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -50,5 +50,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), mkdirat (2) diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index 9b6f383..9d1cb70 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -74,5 +74,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), openat (2) diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 57d9219..97432d4 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -75,5 +75,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), openat2 (2) diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index 2b7e27f..d6979d5 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -63,5 +63,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_prep_read (3), io_uring_prep_readv2 (3), io_uring_submit (3) diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index be9b027..8825eee 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -91,5 +91,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_prep_read (3), io_uring_prep_readv (3), io_uring_submit (3) diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index 1186cb8..1446872 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -53,5 +53,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), recvmsg (2) diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index 09bdf76..4a2b8ab 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -60,5 +60,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), renameat (2), renameat2 (2) diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index 20de5d6..b0e5fa6 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -53,5 +53,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), sendmsg (2) diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3 index 9640e69..eefc021 100644 --- a/man/io_uring_prep_statx.3 +++ b/man/io_uring_prep_statx.3 @@ -58,5 +58,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), statx (2) diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index ec0b5e0..434f064 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -50,5 +50,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), symlinkat (2) diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 index d0c3093..b61c573 100644 --- a/man/io_uring_prep_timeout.3 +++ b/man/io_uring_prep_timeout.3 @@ -78,5 +78,15 @@ io_uring was unable to access the data specified by .TP .B -ECANCELED The timeout was canceled by a removal request. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_timeout_remove (3), io_uring_prep_timeout_update (3) diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 index e460779..247e467 100644 --- a/man/io_uring_prep_timeout_update.3 +++ b/man/io_uring_prep_timeout_update.3 @@ -83,5 +83,15 @@ where given, or the specified timeout seconds or nanoseconds where < 0. .B -EFAULT io_uring was unable to access the data specified by .I ts. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_timeout (3) diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index 5c93c0f..b28b285 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -50,5 +50,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_submit (3), unlinkat (2) diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 81d460d..fc449d0 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -63,5 +63,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev2 (3), io_uring_submit (3) diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index 82e2c6e..6974e97 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -90,5 +90,15 @@ Instead it returns the negated directly in the CQE .I res field. +.SH NOTES +As with any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev (3), io_uring_submit (3) -- cgit v1.2.3 From feab01c123fe4995742e03d380a8fe98ba8112ff Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 14 Mar 2022 09:26:22 -0600 Subject: man/io_uring_submit.3: add blurb on passed in data being stable Link: https://github.com/axboe/liburing/issues/486 Signed-off-by: Jens Axboe --- man/io_uring_submit.3 | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 index b2fe11f..eaed93c 100644 --- a/man/io_uring_submit.3 +++ b/man/io_uring_submit.3 @@ -10,7 +10,7 @@ io_uring_submit - submit requests to the submission queue .nf .BR "#include " .PP -.BI "int io_uring_submit(struct io_uring *ring)" +.BI "int io_uring_submit(struct io_uring *ring);" .PP .SH DESCRIPTION .PP @@ -18,12 +18,26 @@ The io_uring_submit() function submits the next events to the submission queue belonging to the .I ring. -After the caller retrieves a submission queue entry (SQE) with io_uring_get_sqe(), -prepares the SQE, it can be submitted with io_uring_submit(). +After the caller retrieves a submission queue entry (SQE) with +.BR io_uring_get_sqe (3) +and prepares the SQE, it can be submitted with io_uring_submit(). .SH RETURN VALUE On success .BR io_uring_submit (3) -returns the number of submitted submission queue entries. On failure it returns -errno. +returns the number of submitted submission queue entries. On failure it returns +.B -errno. +.SH NOTES +For any request that passes in data in a struct, that data must remain +valid until the request has been successfully submitted. It need not remain +valid until completion. Once a request has been submitted, the in-kernel +state is stable. Very early kernels (5.4 and earlier) required state to be +stable until the completion occurred. Applications can test for this +behavior by inspecting the +.B IORING_FEAT_SUBMIT_STABLE +flag passed back from +.BR io_uring_queue_init_params (3). +In general, the man pages for the individual prep helpers will have a note +mentioning this fact as well, if required for the given command. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit_and_wait (3), io_uring_submit_and_wait_timeout (3) \ No newline at end of file +.BR io_uring_get_sqe (3), io_uring_submit_and_wait (3), io_uring_submit_and_wait_timeout (3) -- cgit v1.2.3 From 60340cbc0ee6e07fd408c265b7a21901527c0f9e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 14 Mar 2022 10:13:12 -0600 Subject: man: updates Mostly just ensuring that parameters are underlined, but also a few general fixes or improvements. Signed-off-by: Jens Axboe --- man/io_uring_cq_advance.3 | 14 +++++++------- man/io_uring_cq_ready.3 | 6 +++--- man/io_uring_cqe_get_data.3 | 9 +++++---- man/io_uring_cqe_seen.3 | 11 ++++++----- man/io_uring_free_probe.3 | 8 +++++--- man/io_uring_get_probe.3 | 5 +++-- man/io_uring_get_sqe.3 | 5 +++-- man/io_uring_opcode_supported.3 | 11 ++++++----- man/io_uring_peek_cqe.3 | 4 ++-- man/io_uring_prep_accept.3 | 22 +++++++++++----------- man/io_uring_prep_cancel.3 | 6 +++--- man/io_uring_prep_close.3 | 8 ++++---- man/io_uring_prep_connect.3 | 8 ++++---- man/io_uring_prep_fadvise.3 | 10 +++++----- man/io_uring_prep_fallocate.3 | 10 +++++----- man/io_uring_prep_files_update.3 | 8 ++++---- man/io_uring_prep_fsync.3 | 6 +++--- man/io_uring_prep_linkat.3 | 12 ++++++------ man/io_uring_prep_madvise.3 | 10 +++++----- man/io_uring_prep_mkdirat.3 | 8 ++++---- man/io_uring_prep_msg_ring.3 | 10 +++++----- man/io_uring_prep_openat.3 | 22 +++++++++++----------- man/io_uring_prep_openat2.3 | 22 +++++++++++----------- man/io_uring_prep_poll_add.3 | 12 ++++++------ man/io_uring_prep_poll_remove.3 | 4 ++-- man/io_uring_prep_poll_update.3 | 10 +++++----- man/io_uring_prep_provide_buffers.3 | 12 ++++++------ man/io_uring_prep_read.3 | 10 +++++----- man/io_uring_prep_read_fixed.3 | 12 ++++++------ man/io_uring_prep_readv.3 | 10 +++++----- man/io_uring_prep_readv2.3 | 12 ++++++------ man/io_uring_prep_recv.3 | 10 +++++----- man/io_uring_prep_recvmsg.3 | 8 ++++---- man/io_uring_prep_remove_buffers.3 | 6 +++--- man/io_uring_prep_renameat.3 | 12 ++++++------ man/io_uring_prep_send.3 | 10 +++++----- man/io_uring_prep_sendmsg.3 | 8 ++++---- man/io_uring_prep_shutdown.3 | 6 +++--- man/io_uring_prep_splice.3 | 14 +++++++------- man/io_uring_prep_statx.3 | 12 ++++++------ man/io_uring_prep_symlinkat.3 | 8 ++++---- man/io_uring_prep_sync_file_range.3 | 10 +++++----- man/io_uring_prep_tee.3 | 10 +++++----- man/io_uring_prep_timeout.3 | 8 ++++---- man/io_uring_prep_timeout_update.3 | 14 +++++++------- man/io_uring_prep_unlinkat.3 | 8 ++++---- man/io_uring_prep_write.3 | 10 +++++----- man/io_uring_prep_write_fixed.3 | 12 ++++++------ man/io_uring_prep_writev.3 | 10 +++++----- man/io_uring_prep_writev2.3 | 12 ++++++------ man/io_uring_queue_exit.3 | 2 +- man/io_uring_queue_init.3 | 15 ++++++++------- man/io_uring_register_buffers.3 | 6 +++--- man/io_uring_register_files.3 | 6 +++--- man/io_uring_register_iowq_aff.3 | 8 ++++---- man/io_uring_register_iowq_max_workers.3 | 4 ++-- man/io_uring_register_ring_fd.3 | 2 +- man/io_uring_sq_ready.3 | 4 ++-- man/io_uring_sq_space_left.3 | 4 ++-- man/io_uring_sqe_set_data.3 | 6 +++--- man/io_uring_sqe_set_flags.3 | 4 ++-- man/io_uring_sqring_wait.3 | 4 ++-- man/io_uring_submit.3 | 2 +- man/io_uring_submit_and_wait.3 | 7 +++---- man/io_uring_submit_and_wait_timeout.3 | 16 ++++++---------- man/io_uring_unregister_buffers.3 | 4 ++-- man/io_uring_unregister_files.3 | 4 ++-- man/io_uring_unregister_ring_fd.3 | 2 +- man/io_uring_wait_cqe.3 | 4 ++-- man/io_uring_wait_cqe_nr.3 | 6 +++--- man/io_uring_wait_cqe_timeout.3 | 8 ++++---- man/io_uring_wait_cqes.3 | 10 +++++----- 72 files changed, 318 insertions(+), 315 deletions(-) diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 index 26f23ca..c75eaba 100644 --- a/man/io_uring_cq_advance.3 +++ b/man/io_uring_cq_advance.3 @@ -9,24 +9,24 @@ io_uring_cq_advance - Mark one or more io_uring completion events as processed .nf .BR "#include " .PP -.BI "void io_uring_cqe_advance(struct io_uring *ring," -.BI " unsigned nr)" +.BI "void io_uring_cqe_advance(struct io_uring *" ring "," +.BI " unsigned " nr ");" .fi .PP .SH DESCRIPTION .PP The io_uring_cq_advance() function marks .I nr -IO completions -belonging to the +IO completions belonging to the .I ring param as processed. After the caller has submitted a request with .BR io_uring_submit (3), the application can retrieve the completion with -.BR io_uring_wait_cqe (3) -and mark it as processed with +.BR io_uring_wait_cqe (3), +.BR io_uring_peek_cqe (3), +or any of the other CQE retrieval helpers, and mark it as processed with .BR io_uring_cqe_seen (3). The function @@ -40,4 +40,4 @@ so will result in the same completion being returned on the next invocation. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_cqe_seen (3) +.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_peek_cqe (3), io_uring_wait_cqes (3), io_uring_wait_cqe_timeout (3), io_uring_cqe_seen (3) diff --git a/man/io_uring_cq_ready.3 b/man/io_uring_cq_ready.3 index a540d2a..548ded1 100644 --- a/man/io_uring_cq_ready.3 +++ b/man/io_uring_cq_ready.3 @@ -4,12 +4,12 @@ .\" .TH io_uring_cq_ready "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_cq_ready - number of unconsumed ready entries in the CQ ring +io_uring_cq_ready - returns number of unconsumed ready entries in the CQ ring .SH SYNOPSIS .nf .BR "#include " .PP -.BI "unsigned io_uring_cq_ready(const struct io_uring *ring)" +.BI "unsigned io_uring_cq_ready(const struct io_uring *" ring ");" .fi .PP .SH DESCRIPTION @@ -22,4 +22,4 @@ param. .SH RETURN VALUE Returns the number of unconsumed ready entries in the CQ ring. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe (3) \ No newline at end of file +.BR io_uring_submit (3), io_uring_wait_cqe (3) diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index daa3589..1f838c2 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -9,13 +9,13 @@ io_uring_cqe_get_data - get user data for completion event .nf .BR "#include " .PP -.BI "void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)" +.BI "void *io_uring_cqe_get_data(struct io_uring_cqe *" cqe ");" .fi .PP .SH DESCRIPTION .PP -The io_uring_cqe_get_data() function returns the user_data -with the completion queue entry +The io_uring_cqe_get_data() function returns the user_data with the completion +queue entry .I cqe. After the caller has received a completion queue entry (CQE) with @@ -26,7 +26,8 @@ function to retrieve the .I user_data value. This requires that .I user_data -has been set earlier with the function io_uring_sqe_set_data(). +has been set earlier with the function +.BR io_uring_sqe_set_data (3). .SH RETURN VALUE If the diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3 index 77baecb..dc7f8e4 100644 --- a/man/io_uring_cqe_seen.3 +++ b/man/io_uring_cqe_seen.3 @@ -9,8 +9,8 @@ io_uring_cqe_seen - Mark io_uring completion event as processed .nf .BR "#include " .PP -.BI "void io_uring_cqe_seen(struct io_uring *ring," -.BI " struct io_uring_cqe *cqe)" +.BI "void io_uring_cqe_seen(struct io_uring *" ring "," +.BI " struct io_uring_cqe *" cqe ");" .fi .PP .SH DESCRIPTION @@ -24,12 +24,13 @@ param as processed. After the caller has submitted a request with .BR io_uring_submit (3), the application can retrieve the completion with -.BR io_uring_wait_cqe (3) -and mark it then as processed with +.BR io_uring_wait_cqe (3), +.BR io_uring_peek_cqe (3), +or any of the other CQE retrieval helpers, and mark it as processed with .BR io_uring_cqe_seen (3). Completions must be marked as completed, so their slot can get reused. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe(3) +.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_peek_cqe (3), io_uring_wait_cqes (3), io_uring_wait_cqe_timeout (3), io_uring_cqe_seen (3) diff --git a/man/io_uring_free_probe.3 b/man/io_uring_free_probe.3 index bc674ca..08d61ca 100644 --- a/man/io_uring_free_probe.3 +++ b/man/io_uring_free_probe.3 @@ -9,16 +9,18 @@ io_uring_free_probe - free probe instance .nf .BR "#include " .PP -.BI "void io_uring_free_probe(struct io_uring_probe *probe)" +.BI "void io_uring_free_probe(struct io_uring_probe *" probe ");" .fi .PP .SH DESCRIPTION .PP The function io_uring_free_probe() frees the .I probe -instance allocated with the io_uring_get_probe() function. +instance allocated with the +.BR io_uring_get_probe (3) +function. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_get_probe (3) \ No newline at end of file +.BR io_uring_get_probe (3) diff --git a/man/io_uring_get_probe.3 b/man/io_uring_get_probe.3 index 38f1c53..8b8a902 100644 --- a/man/io_uring_get_probe.3 +++ b/man/io_uring_get_probe.3 @@ -9,14 +9,15 @@ io_uring_get_probe - get probe instance .nf .BR "#include " .PP -.BI "io_uring_probe *io_uring_get_probe(void)" +.BI "io_uring_probe *io_uring_get_probe(void);" .fi .PP .SH DESCRIPTION .PP The function io_uring_get_probe() returns an allocated io_uring_probe structure to the caller. The caller is responsible for freeing the -structure with the function io_uring_free_probe(). +structure with the function +.BR io_uring_free_probe (3). .SH NOTES Earlier versions of the Linux kernel do not support probe. If the kernel diff --git a/man/io_uring_get_sqe.3 b/man/io_uring_get_sqe.3 index 12ae545..caada9b 100644 --- a/man/io_uring_get_sqe.3 +++ b/man/io_uring_get_sqe.3 @@ -11,7 +11,7 @@ submission queue .nf .BR "#include " .PP -.BI "struct io_uring_sqe *io_uring_get_sqe(struct io_uring " *ring ); +.BI "struct io_uring_sqe *io_uring_get_sqe(struct io_uring *" ring ");" .fi .PP .SH DESCRIPTION @@ -33,6 +33,7 @@ and submitted via .SH RETURN VALUE .BR io_uring_get_sqe (3) returns a pointer to the next submission queue event on success and NULL on -failure. +failure. If NULL is returned, the SQ ring is currently full and entries must +be submitted for processing before new ones can get allocated. .SH SEE ALSO .BR io_uring_submit (3) diff --git a/man/io_uring_opcode_supported.3 b/man/io_uring_opcode_supported.3 index 4d03027..8afbfc6 100644 --- a/man/io_uring_opcode_supported.3 +++ b/man/io_uring_opcode_supported.3 @@ -9,21 +9,22 @@ io_uring_opcode_supported - is op code supported? .nf .BR "#include " .PP -.BI "int io_uring_opcode_supported(struct io_uring_probe *probe," -.BI " int opode) +.BI "int io_uring_opcode_supported(struct io_uring_probe *" probe "," +.BI " int " opode ");" .fi .PP .SH DESCRIPTION .PP -The function io_uring_opcode_supported allows the caller to determine if +The function io_uring_opcode_supported() allows the caller to determine if the passed in .I opcode belonging to the .I probe param is supported. An instance of the io_uring_probe instance can be -obtained by calling the function io_uring_get_probe(). +obtained by calling the function +.BR io_uring_get_probe (3). .SH RETURN VALUE On success it returns 1, otherwise it returns 0. .SH SEE ALSO -.BR io_uring_get_probe (3) \ No newline at end of file +.BR io_uring_get_probe (3) diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3 index 2867d21..ffd6a60 100644 --- a/man/io_uring_peek_cqe.3 +++ b/man/io_uring_peek_cqe.3 @@ -9,8 +9,8 @@ io_uring_peek_cqe - check if an io_uring completion event is available .nf .BR "#include " .PP -.BI "int io_uring_peek_cqe(struct io_uring *ring," -.BI " struct io_uring_cqe **cqe_ptr);" +.BI "int io_uring_peek_cqe(struct io_uring *" ring "," +.BI " struct io_uring_cqe **" cqe_ptr ");" .fi .PP .SH DESCRIPTION diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 1af0f0f..bf912da 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -11,18 +11,18 @@ io_uring_prep_accept - prepare a accept request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_accept(struct io_uring_sqe *sqe," -.BI " int sockfd," -.BI " struct sockaddr *addr," -.BI " socklen_t addrlen," -.BI " int flags);" +.BI "void io_uring_prep_accept(struct io_uring_sqe *" sqe "," +.BI " int " sockfd "," +.BI " struct sockaddr *" addr "," +.BI " socklen_t " addrlen "," +.BI " int " flags ");" .BI " -.BI "void io_uring_prep_accept_direct(struct io_uring_sqe *sqe," -.BI " int sockfd," -.BI " struct sockaddr *addr," -.BI " socklen_t addrlen," -.BI " int flags," -.BI " unsigned int file_index);" +.BI "void io_uring_prep_accept_direct(struct io_uring_sqe *" sqe "," +.BI " int " sockfd "," +.BI " struct sockaddr *" addr "," +.BI " socklen_t " addrlen "," +.BI " int " flags "," +.BI " unsigned int " file_index ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index e7164db..ddf5a89 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -10,9 +10,9 @@ io_uring_prep_cancel - prepare a cancelation request .nf .BR "#include " .PP -.BI "void io_uring_prep_cancel(struct io_uring_sqe *sqe," -.BI " __u64 user_data," -.BI " int flags);" +.BI "void io_uring_prep_cancel(struct io_uring_sqe *" sqe "," +.BI " __u64 " user_data "," +.BI " int " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index 97ecd3d..490c27c 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -10,11 +10,11 @@ io_uring_prep_close - prepare a file descriptor close request .nf .BR "#include " .PP -.BI "void io_uring_prep_close(struct io_uring_sqe *sqe," -.BI " int fd);" +.BI "void io_uring_prep_close(struct io_uring_sqe *" sqe "," +.BI " int " fd ");" .BI " -.BI "void io_uring_prep_close_direct(struct io_uring_sqe *sqe," -.BI " unsigned file_index);" +.BI "void io_uring_prep_close_direct(struct io_uring_sqe *" sqe "," +.BI " unsigned " file_index ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 index 496e4de..12caa2d 100644 --- a/man/io_uring_prep_connect.3 +++ b/man/io_uring_prep_connect.3 @@ -12,10 +12,10 @@ io_uring_prep_connect - prepare a connect request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_connect(struct io_uring_sqe *sqe," -.BI " int sockfd," -.BI " const struct sockaddr *addr," -.BI " socklen_t addrlen);" +.BI "void io_uring_prep_connect(struct io_uring_sqe *" sqe "," +.BI " int " sockfd "," +.BI " const struct sockaddr *" addr "," +.BI " socklen_t " addrlen ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_fadvise.3 b/man/io_uring_prep_fadvise.3 index 9df6254..41e00cb 100644 --- a/man/io_uring_prep_fadvise.3 +++ b/man/io_uring_prep_fadvise.3 @@ -11,11 +11,11 @@ io_uring_prep_fadvise - prepare a fadvise request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_fadvise(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " __u64 offset," -.BI " off_t len," -.BI " int advice);" +.BI "void io_uring_prep_fadvise(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " __u64 " offset "," +.BI " off_t " len "," +.BI " int " advice ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_fallocate.3 b/man/io_uring_prep_fallocate.3 index b587119..49a8b4b 100644 --- a/man/io_uring_prep_fallocate.3 +++ b/man/io_uring_prep_fallocate.3 @@ -11,11 +11,11 @@ io_uring_prep_fallocate - prepare a fallocate request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_fallocate(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " int mode," -.BI " off_t offset," -.BI " off_t len);" +.BI "void io_uring_prep_fallocate(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " int " mode "," +.BI " off_t " offset "," +.BI " off_t " len ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index 5a9202c..0a35e9f 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -10,10 +10,10 @@ io_uring_prep_files_update - prepare a registered file update request .nf .BR "#include " .PP -.BI "void io_uring_prep_files_update(struct io_uring_sqe *sqe," -.BI " int *fds," -.BI " unsigned nr_fds," -.BI " int offset);" +.BI "void io_uring_prep_files_update(struct io_uring_sqe *" sqe "," +.BI " int *" fds "," +.BI " unsigned " nr_fds "," +.BI " int " offset ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 index 3a01963..451407e 100644 --- a/man/io_uring_prep_fsync.3 +++ b/man/io_uring_prep_fsync.3 @@ -10,9 +10,9 @@ io_uring_prep_fsync - prepare an fsync request .nf .BR "#include " .PP -.BI "void io_uring_prep_fsync(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " unsigned flags);" +.BI "void io_uring_prep_fsync(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " unsigned " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index 2ba485a..73563e5 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -12,12 +12,12 @@ io_uring_prep_linkat - prepare a linkat request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_linkat(struct io_uring_sqe *sqe," -.BI " int olddirfd," -.BI " const char *oldpath," -.BI " int newdirfd," -.BI " const char *newpath," -.BI " int flags);" +.BI "void io_uring_prep_linkat(struct io_uring_sqe *" sqe "," +.BI " int " olddirfd "," +.BI " const char *" oldpath "," +.BI " int " newdirfd "," +.BI " const char *" newpath "," +.BI " int " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 index db1465e..5d855a1 100644 --- a/man/io_uring_prep_madvise.3 +++ b/man/io_uring_prep_madvise.3 @@ -11,11 +11,11 @@ io_uring_prep_madvise - prepare a madvise request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_madvise(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " void *addr," -.BI " off_t len," -.BI " int advice);" +.BI "void io_uring_prep_madvise(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " void *" addr "," +.BI " off_t " len "," +.BI " int " advice ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index 7b662e6..d96a1bf 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -12,10 +12,10 @@ io_uring_prep_mkdirat - prepare an mkdirat request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_mkdirat(struct io_uring_sqe *sqe," -.BI " int dirfd," -.BI " const char *path," -.BI " mode_t mode);" +.BI "void io_uring_prep_mkdirat(struct io_uring_sqe *" sqe "," +.BI " int " dirfd "," +.BI " const char *" path "," +.BI " mode_t " mode ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index d71b612..7f03870 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -10,11 +10,11 @@ io_uring_prep_msg_ring - send a message to another ring .nf .BR "#include " .PP -.BI "void io_uring_msg_ring(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " unsigned int len," -.BI " __u64 data," -.BI " unsigned int flags);" +.BI "void io_uring_msg_ring(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " unsigned int " len "," +.BI " __u64 " data "," +.BI " unsigned int " flags ");" .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index 9d1cb70..3fdc58a 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -13,18 +13,18 @@ io_uring_prep_openat - prepare an openat request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_openat(struct io_uring_sqe *sqe," -.BI " int dfd," -.BI " const char *path," -.BI " int flags," -.BI " mode_t mode);" +.BI "void io_uring_prep_openat(struct io_uring_sqe *" sqe "," +.BI " int " dfd "," +.BI " const char *" path "," +.BI " int " flags "," +.BI " mode_t " mode ");" .BI " -.BI "void io_uring_prep_openat_direct(struct io_uring_sqe *sqe," -.BI " int dfd," -.BI " const char *path," -.BI " int flags," -.BI " mode_t mode," -.BI " unsigned file_index);" +.BI "void io_uring_prep_openat_direct(struct io_uring_sqe *" sqe "," +.BI " int " dfd "," +.BI " const char *" path "," +.BI " int " flags "," +.BI " mode_t " mode "," +.BI " unsigned " file_index ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 97432d4..f87d49b 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -14,18 +14,18 @@ io_uring_prep_openat2 - prepare an openat2 request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_openat2(struct io_uring_sqe *sqe," -.BI " int dfd," -.BI " const char *path," -.BI " int flags," -.BI " struct open_how *how);" +.BI "void io_uring_prep_openat2(struct io_uring_sqe *" sqe "," +.BI " int " dfd "," +.BI " const char *" path "," +.BI " int " flags "," +.BI " struct open_how *" how ");" .BI " -.BI "void io_uring_prep_openat2_direct(struct io_uring_sqe *sqe," -.BI " int dfd," -.BI " const char *path," -.BI " int flags," -.BI " struct open_how *how," -.BI " unsigned file_index);" +.BI "void io_uring_prep_openat2_direct(struct io_uring_sqe *" sqe "," +.BI " int " dfd "," +.BI " const char *" path "," +.BI " int " flags "," +.BI " struct open_how *" how "," +.BI " unsigned " file_index ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index 2ecb1aa..c880523 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -11,13 +11,13 @@ io_uring_prep_poll_add - prepare a poll request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_poll_add(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " unsigned poll_mask);" +.BI "void io_uring_prep_poll_add(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " unsigned " poll_mask ");" .BI " -.BI "void io_uring_prep_poll_multishot(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " unsigned poll_mask);" +.BI "void io_uring_prep_poll_multishot(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " unsigned " poll_mask ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_poll_remove.3 b/man/io_uring_prep_poll_remove.3 index 9458be2..cd90fba 100644 --- a/man/io_uring_prep_poll_remove.3 +++ b/man/io_uring_prep_poll_remove.3 @@ -10,8 +10,8 @@ io_uring_prep_poll_remove - prepare a poll deletion request .nf .BR "#include " .PP -.BI "void io_uring_prep_poll_remove(struct io_uring_sqe *sqe," -.BI " __u64 user_data);" +.BI "void io_uring_prep_poll_remove(struct io_uring_sqe *" sqe "," +.BI " __u64 " user_data ");" .BI " .PP .SH DESCRIPTION diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index b767af2..b6bc135 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -11,11 +11,11 @@ io_uring_prep_poll_update - update an existing poll request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_poll_update(struct io_uring_sqe *sqe," -.BI " __u64 old_user_data," -.BI " __u64 new_user_data," -.BI " unsigned poll_mask," -.BI " unsigned flags)" +.BI "void io_uring_prep_poll_update(struct io_uring_sqe *" sqe "," +.BI " __u64 " old_user_data "," +.BI " __u64 " new_user_data "," +.BI " unsigned " poll_mask "," +.BI " unsigned " flags ");" .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3 index 9f1fc6c..b18a6d9 100644 --- a/man/io_uring_prep_provide_buffers.3 +++ b/man/io_uring_prep_provide_buffers.3 @@ -10,12 +10,12 @@ io_uring_prep_provide_buffers - prepare a provide buffers request .nf .BR "#include " .PP -.BI "void io_uring_prep_provide_buffers(struct io_uring_sqe *sqe," -.BI " void *addr," -.BI " int len," -.BI " int nr," -.BI " int bgid," -.BI " int bid);" +.BI "void io_uring_prep_provide_buffers(struct io_uring_sqe *" sqe "," +.BI " void *" addr "," +.BI " int " len "," +.BI " int " nr "," +.BI " int " bgid "," +.BI " int " bid ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index e574046..dd1008d 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -10,11 +10,11 @@ io_uring_prep_read - prepare I/O read request .nf .BR "#include " .PP -.BI "void io_uring_prep_read(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " void *buf," -.BI " unsigned nbytes," -.BI " __u64 offset);" +.BI "void io_uring_prep_read(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " void *" buf "," +.BI " unsigned " nbytes "," +.BI " __u64 " offset ");" .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index 7e1cafe..3433c20 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -10,12 +10,12 @@ io_uring_prep_read_fixed - prepare I/O read request with registered buffer .nf .BR "#include " .PP -.BI "void io_uring_prep_read_fixed(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " void *buf," -.BI " unsigned nbytes," -.BI " __u64 offset," -.BI " int buf_index);" +.BI "void io_uring_prep_read_fixed(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " void *" buf "," +.BI " unsigned " nbytes "," +.BI " __u64 " offset "," +.BI " int " buf_index ");" .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index d6979d5..1817689 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -11,11 +11,11 @@ io_uring_prep_readv - prepare vector I/O read request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_readv(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " const struct iovec *iovecs," -.BI " unsigned nr_vecs," -.BI " __u64 offset);" +.BI "void io_uring_prep_readv(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " const struct iovec *" iovecs "," +.BI " unsigned " nr_vecs "," +.BI " __u64 " offset ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 8825eee..a25c595 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -12,12 +12,12 @@ io_uring_prep_readv2 - prepare vector I/O read request with flags .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_readv2(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " const struct iovec *iovecs," -.BI " unsigned nr_vecs," -.BI " __u64 offset," -.BI " int flags);" +.BI "void io_uring_prep_readv2(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " const struct iovec *" iovecs "," +.BI " unsigned " nr_vecs "," +.BI " __u64 " offset "," +.BI " int " flags ");" .fi .PP .SH DESCRIPTION diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 index 1924343..972ee72 100644 --- a/man/io_uring_prep_recv.3 +++ b/man/io_uring_prep_recv.3 @@ -10,11 +10,11 @@ io_uring_prep_recv - prepare a recv request .nf .BR "#include " .PP -.BI "void io_uring_prep_recv(struct io_uring_sqe *sqe," -.BI " int sockfd," -.BI " void *buf," -.BI " size_t len," -.BI " int flags);" +.BI "void io_uring_prep_recv(struct io_uring_sqe *" sqe "," +.BI " int " sockfd "," +.BI " void *" buf "," +.BI " size_t " len "," +.BI " int " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index 1446872..0236b48 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -12,10 +12,10 @@ io_uring_prep_recvmsg - prepare a recvmsg request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_recvmsg(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " struct msghdr *msg," -.BI " unsigned flags);" +.BI "void io_uring_prep_recvmsg(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " struct msghdr *" msg "," +.BI " unsigned " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_remove_buffers.3 b/man/io_uring_prep_remove_buffers.3 index ce6a5ce..52c45e2 100644 --- a/man/io_uring_prep_remove_buffers.3 +++ b/man/io_uring_prep_remove_buffers.3 @@ -10,9 +10,9 @@ io_uring_prep_remove_buffers - prepare a remove buffers request .nf .BR "#include " .PP -.BI "void io_uring_prep_remove_buffers(struct io_uring_sqe *sqe," -.BI " int nr," -.BI " int bgid);" +.BI "void io_uring_prep_remove_buffers(struct io_uring_sqe *" sqe "," +.BI " int " nr "," +.BI " int " bgid ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index 4a2b8ab..9f93576 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -12,12 +12,12 @@ io_uring_prep_renameat - prepare a renameat request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_renameat(struct io_uring_sqe *sqe," -.BI " int olddirfd," -.BI " const char *oldpath," -.BI " int newdirfd," -.BI " const char *newpath," -.BI " int flags);" +.BI "void io_uring_prep_renameat(struct io_uring_sqe *" sqe "," +.BI " int " olddirfd "," +.BI " const char *" oldpath "," +.BI " int " newdirfd "," +.BI " const char *" newpath "," +.BI " int " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 index b60b6e6..7ffe99b 100644 --- a/man/io_uring_prep_send.3 +++ b/man/io_uring_prep_send.3 @@ -10,11 +10,11 @@ io_uring_prep_send - prepare a send request .nf .BR "#include " .PP -.BI "void io_uring_prep_send(struct io_uring_sqe *sqe," -.BI " int sockfd," -.BI " const void *buf," -.BI " size_t len," -.BI " int flags);" +.BI "void io_uring_prep_send(struct io_uring_sqe *" sqe "," +.BI " int " sockfd "," +.BI " const void *" buf "," +.BI " size_t " len "," +.BI " int " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index b0e5fa6..454d9da 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -12,10 +12,10 @@ io_uring_prep_sendmsg - prepare a sendmsg request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_sendmsg(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " const struct msghdr *msg," -.BI " unsigned flags);" +.BI "void io_uring_prep_sendmsg(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " const struct msghdr *" msg "," +.BI " unsigned " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index 6152eae..733fd89 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -11,9 +11,9 @@ io_uring_prep_shutdown - prepare a shutdown request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_shutdown(struct io_uring_sqe *sqe," -.BI " int sockfd," -.BI " int how);" +.BI "void io_uring_prep_shutdown(struct io_uring_sqe *" sqe "," +.BI " int " sockfd "," +.BI " int " how ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3 index c0ee835..6827131 100644 --- a/man/io_uring_prep_splice.3 +++ b/man/io_uring_prep_splice.3 @@ -11,13 +11,13 @@ io_uring_prep_splice - prepare an splice request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_splice(struct io_uring_sqe *sqe," -.BI " int fd_in," -.BI " int64_t off_in," -.BI " int fd_out," -.BI " int64_t off_out," -.BI " unsigned int nbytes," -.BI " int splice_flags);" +.BI "void io_uring_prep_splice(struct io_uring_sqe *" sqe "," +.BI " int " fd_in "," +.BI " int64_t " off_in "," +.BI " int " fd_out "," +.BI " int64_t " off_out "," +.BI " unsigned int " nbytes "," +.BI " int " splice_flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3 index eefc021..0ead796 100644 --- a/man/io_uring_prep_statx.3 +++ b/man/io_uring_prep_statx.3 @@ -14,12 +14,12 @@ io_uring_prep_statx - prepare a statx request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_statx(struct io_uring_sqe *sqe," -.BI " int dirfd," -.BI " const char *path," -.BI " int flags," -.BI " unsigned mask," -.BI " struct statx *statxbuf);" +.BI "void io_uring_prep_statx(struct io_uring_sqe *" sqe "," +.BI " int " dirfd "," +.BI " const char *" path "," +.BI " int " flags "," +.BI " unsigned " mask "," +.BI " struct statx *" statxbuf ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index 434f064..10f650a 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -12,10 +12,10 @@ io_uring_prep_symlinkat - prepare a symlinkat request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_symlinkat(struct io_uring_sqe *sqe," -.BI " const char *target," -.BI " int newdirfd," -.BI " const char *linkpath);" +.BI "void io_uring_prep_symlinkat(struct io_uring_sqe *" sqe "," +.BI " const char *" target "," +.BI " int " newdirfd "," +.BI " const char *" linkpath ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index 680bd31..0fe96bd 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -11,11 +11,11 @@ io_uring_prep_sync_file_range - prepare a sync_file_range request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_sync_file_range(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " unsigned len," -.BI " __u64 offset," -.BI " int flags);" +.BI "void io_uring_prep_sync_file_range(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " unsigned " len "," +.BI " __u64 " offset "," +.BI " int " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3 index e64da26..086bc18 100644 --- a/man/io_uring_prep_tee.3 +++ b/man/io_uring_prep_tee.3 @@ -11,11 +11,11 @@ io_uring_prep_tee - prepare a tee request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_tee(struct io_uring_sqe *sqe," -.BI " int fd_in," -.BI " int fd_out," -.BI " unsigned int nbytes," -.BI " int splice_flags);" +.BI "void io_uring_prep_tee(struct io_uring_sqe *" sqe "," +.BI " int " fd_in "," +.BI " int " fd_out "," +.BI " unsigned int " nbytes "," +.BI " int " splice_flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 index b61c573..fb2a07c 100644 --- a/man/io_uring_prep_timeout.3 +++ b/man/io_uring_prep_timeout.3 @@ -10,10 +10,10 @@ io_uring_prep_timeoute - prepare a timeout request .nf .BR "#include " .PP -.BI "void io_uring_prep_timeout(struct io_uring_sqe *sqe," -.BI " struct __kernel_timespec *ts," -.BI " unsigned count," -.BI " unsigned flags);" +.BI "void io_uring_prep_timeout(struct io_uring_sqe *" sqe "," +.BI " struct __kernel_timespec *" ts "," +.BI " unsigned " count "," +.BI " unsigned " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 index 247e467..b35e1f0 100644 --- a/man/io_uring_prep_timeout_update.3 +++ b/man/io_uring_prep_timeout_update.3 @@ -10,14 +10,14 @@ io_uring_prep_timeoute_update - prepare a request to update an existing timeout .nf .BR "#include " .PP -.BI "void io_uring_prep_timeout_update(struct io_uring_sqe *sqe," -.BI " struct __kernel_timespec *ts," -.BI " __u64 user_data," -.BI " unsigned flags);" +.BI "void io_uring_prep_timeout_update(struct io_uring_sqe *" sqe "," +.BI " struct __kernel_timespec *" ts "," +.BI " __u64 " user_data "," +.BI " unsigned " flags ");" .BI " -.BI "void io_uring_prep_timeout_remove(struct io_uring_sqe *sqe," -.BI " __u64 user_data," -.BI " unsigned flags);" +.BI "void io_uring_prep_timeout_remove(struct io_uring_sqe *" sqe "," +.BI " __u64 " user_data "," +.BI " unsigned " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index b28b285..c59b9ac 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -12,10 +12,10 @@ io_uring_prep_unlinkat - prepare an unlinkat request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_unlinkat(struct io_uring_sqe *sqe," -.BI " int dirfd," -.BI " const char *path," -.BI " int flags);" +.BI "void io_uring_prep_unlinkat(struct io_uring_sqe *" sqe "," +.BI " int " dirfd "," +.BI " const char *" path "," +.BI " int " flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 11fbddf..817717d 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -10,11 +10,11 @@ io_uring_prep_write - prepare I/O write request .nf .BR "#include " .PP -.BI "void io_uring_prep_write(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " const void *buf," -.BI " unsigned nbytes," -.BI " __u64 offset);" +.BI "void io_uring_prep_write(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " const void *" buf "," +.BI " unsigned " nbytes "," +.BI " __u64 " offset ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index bad8871..c9729b4 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -10,12 +10,12 @@ io_uring_prep_write_fixed - prepare I/O write request with registered buffer .nf .BR "#include " .PP -.BI "void io_uring_prep_write_fixed(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " const void *buf," -.BI " unsigned nbytes," -.BI " __u64 offset," -.BI " int buf_index);" +.BI "void io_uring_prep_write_fixed(struct io_uring_sqe *" sqe "," +.BI " int " fd ", +.BI " const void *" buf "," +.BI " unsigned " nbytes "," +.BI " __u64 " offset "," +.BI " int " buf_index ");" .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index fc449d0..806f4e5 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -11,11 +11,11 @@ io_uring_prep_writev - prepare vector I/O write request .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_writev(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " const struct iovec *iovecs," -.BI " unsigned nr_vecs," -.BI " __u64 offset);" +.BI "void io_uring_prep_writev(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " const struct iovec *" iovecs "," +.BI " unsigned " nr_vecs "," +.BI " __u64 " offset ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index 6974e97..cceae97 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -11,12 +11,12 @@ io_uring_prep_writev2 - prepare vector I/O write request with flags .BR "#include " .BR "#include " .PP -.BI "void io_uring_prep_writev2(struct io_uring_sqe *sqe," -.BI " int fd," -.BI " const struct iovec *iovecs," -.BI " unsigned nr_vecs," -.BI " __u64 offset," -.BI " int flags);" +.BI "void io_uring_prep_writev2(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " const struct iovec *" iovecs "," +.BI " unsigned " nr_vecs "," +.BI " __u64 " offset "," +.BI " int " flags ");" .fi .PP .SH DESCRIPTION diff --git a/man/io_uring_queue_exit.3 b/man/io_uring_queue_exit.3 index 294b5f3..2be51c8 100644 --- a/man/io_uring_queue_exit.3 +++ b/man/io_uring_queue_exit.3 @@ -10,7 +10,7 @@ io_uring_queue_exit - tear down io_uring submission and completion queues .nf .BR "#include " .PP -.BI "void io_uring_queue_exit(struct io_uring * ring );" +.BI "void io_uring_queue_exit(struct io_uring *" ring ");" .fi .PP .SH DESCRIPTION diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index edde6a4..e925589 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -10,13 +10,13 @@ io_uring_queue_init - setup io_uring submission and completion queues .nf .BR "#include " .PP -.BI "int io_uring_queue_init(unsigned entries," -.BI " struct io_uring *ring," -.BI " unsigned flags);" +.BI "int io_uring_queue_init(unsigned " entries "," +.BI " struct io_uring *" ring "," +.BI " unsigned " flags ");" .BI " -.BI "int io_uring_queue_init_params(unsigned entries," -.BI " struct io_uring *ring," -.BI " struct io_uring_params *params);" +.BI "int io_uring_queue_init_params(unsigned " entries "," +.BI " struct io_uring *" ring "," +.BI " struct io_uring_params *" params ");" .fi .PP .SH DESCRIPTION @@ -32,7 +32,8 @@ application and the kernel. On success io_uring_queue_init() returns 0 and .I ring will point to the shared memory containing the io_uring queues. On failure --errno is returned. +.BR -errno +is returned. .I flags will be passed through to the io_uring_setup syscall (see diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index 58cdec7..689de9d 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -10,9 +10,9 @@ io_uring_register_buffers - register buffers for fixed buffer operations .nf .BR "#include " .PP -.BI "int io_uring_register_buffers(struct io_uring *ring," -.BI " const struct iovec *iovecs, -.BI " unsigned nr_iovecs)" +.BI "int io_uring_register_buffers(struct io_uring *" ring ", +.BI " const struct iovec *" iovecs ", +.BI " unsigned " nr_iovecs ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index 9b259a2..e2fed47 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -10,9 +10,9 @@ io_uring_register_files - register file descriptors .nf .BR "#include " .PP -.BI "int io_uring_register_files(struct io_uring *ring," -.BI " const int *files," -.BI " unsigned nr_files)" +.BI "int io_uring_register_files(struct io_uring *" ring "," +.BI " const int *" files "," +.BI " unsigned " nr_files ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_register_iowq_aff.3 b/man/io_uring_register_iowq_aff.3 index 89a520b..b82af8b 100644 --- a/man/io_uring_register_iowq_aff.3 +++ b/man/io_uring_register_iowq_aff.3 @@ -11,11 +11,11 @@ io_uring_register_iowq_aff - register async worker CPU affinities .BR "#include " .BR "#include " .PP -.BI "int io_uring_register_iowq_aff(struct io_uring *ring," -.BI " size_t cpusz," -.BI " const cpu_set_t *mask); +.BI "int io_uring_register_iowq_aff(struct io_uring *" ring "," +.BI " size_t " cpusz "," +.BI " const cpu_set_t *" mask "); .BI " -.BI "void io_uring_unregister_iowq_aff(struct io_uring *ring);" +.BI "void io_uring_unregister_iowq_aff(struct io_uring *" ring ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_register_iowq_max_workers.3 b/man/io_uring_register_iowq_max_workers.3 index b277828..10687cb 100644 --- a/man/io_uring_register_iowq_max_workers.3 +++ b/man/io_uring_register_iowq_max_workers.3 @@ -10,8 +10,8 @@ io_uring_register_iowq_max_workers - modify the maximum allowed async workers .nf .BR "#include " .PP -.BI "int io_uring_register_iowq_max_workers(struct io_uring *ring," -.BI " unsigned int *values);" +.BI "int io_uring_register_iowq_max_workers(struct io_uring *" ring "," +.BI " unsigned int *" values ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3 index ce3d374..0e872bd 100644 --- a/man/io_uring_register_ring_fd.3 +++ b/man/io_uring_register_ring_fd.3 @@ -10,7 +10,7 @@ io_uring_register_ring_fd - register a ring file descriptor .nf .BR "#include " .PP -.BI "int io_uring_register_ring_fd(struct io_uring *ring)" +.BI "int io_uring_register_ring_fd(struct io_uring *" ring ");" .SH DESCRIPTION .PP diff --git a/man/io_uring_sq_ready.3 b/man/io_uring_sq_ready.3 index f583903..80dfa82 100644 --- a/man/io_uring_sq_ready.3 +++ b/man/io_uring_sq_ready.3 @@ -9,7 +9,7 @@ io_uring_sq_ready - number of unconsumed or unsubmitted entries in the SQ ring .nf .BR "#include " .PP -.BI "unsigned io_uring_sq_ready(const struct io_uring *ring)" +.BI "unsigned io_uring_sq_ready(const struct io_uring *" ring ");" .fi .PP .SH DESCRIPTION @@ -22,4 +22,4 @@ param. .SH RETURN VALUE Returns the number of unconsumed or unsubmitted entries in the SQ ring. .SH SEE ALSO -.BR io_uring_cq_ready (3) \ No newline at end of file +.BR io_uring_cq_ready (3) diff --git a/man/io_uring_sq_space_left.3 b/man/io_uring_sq_space_left.3 index 45d229a..be44c0a 100644 --- a/man/io_uring_sq_space_left.3 +++ b/man/io_uring_sq_space_left.3 @@ -9,7 +9,7 @@ io_uring_sq_space_left - free space in the SQ ring .nf .BR "#include " .PP -.BI "unsigned io_uring_sq_space_left(const struct io_uring *ring)" +.BI "unsigned io_uring_sq_space_left(const struct io_uring *" ring ");" .fi .PP .SH DESCRIPTION @@ -22,4 +22,4 @@ param. .SH RETURN VALUE Returns the free space in the SQ ring. .SH SEE ALSO -.BR io_uring_sq_ready (3) \ No newline at end of file +.BR io_uring_sq_ready (3) diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3 index b2dd333..ec22518 100644 --- a/man/io_uring_sqe_set_data.3 +++ b/man/io_uring_sqe_set_data.3 @@ -9,8 +9,8 @@ io_uring_sqe_set_data - set user data for submission queue event .nf .BR "#include " .PP -.BI "void io_uring_sqe_set_data(struct io_uring_sqe *sqe," -.BI " void *user_data)" +.BI "void io_uring_sqe_set_data(struct io_uring_sqe *" sqe "," +.BI " void *" user_data ");" .fi .PP .SH DESCRIPTION @@ -27,4 +27,4 @@ function io_uring_cqe_get_data() can be called to identify the user request. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_cqe_get_data (3) \ No newline at end of file +.BR io_uring_get_sqe (3), io_uring_cqe_get_data (3) diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 index b066f1d..93a41f3 100644 --- a/man/io_uring_sqe_set_flags.3 +++ b/man/io_uring_sqe_set_flags.3 @@ -9,8 +9,8 @@ io_uring_sqe_set_flags - set flags for submission queue entry .nf .BR "#include " .PP -.BI "void io_uring_sqe_set_flags(struct io_uring_sqe *sqe," -.BI " unsigned flags)" +.BI "void io_uring_sqe_set_flags(struct io_uring_sqe *" sqe "," +.BI " unsigned " flags ");" .fi .PP .SH DESCRIPTION diff --git a/man/io_uring_sqring_wait.3 b/man/io_uring_sqring_wait.3 index e0fb731..c0e4e9c 100644 --- a/man/io_uring_sqring_wait.3 +++ b/man/io_uring_sqring_wait.3 @@ -9,7 +9,7 @@ io_uring_sqring_wait - wait for free space in the SQ ring .nf .BR "#include " .PP -.BI "int io_uring_sqring_wait(struct io_uring *ring)" +.BI "int io_uring_sqring_wait(struct io_uring *" ring ");" .fi .PP .SH DESCRIPTION @@ -27,4 +27,4 @@ This feature can only be used when SQPOLL is enabled. On success it returns the free space. If the kernel does not support the feature, -EINVAL is returned. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_wait_cqes (3) \ No newline at end of file +.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_wait_cqes (3) diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 index eaed93c..83ab922 100644 --- a/man/io_uring_submit.3 +++ b/man/io_uring_submit.3 @@ -10,7 +10,7 @@ io_uring_submit - submit requests to the submission queue .nf .BR "#include " .PP -.BI "int io_uring_submit(struct io_uring *ring);" +.BI "int io_uring_submit(struct io_uring *" ring ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_submit_and_wait.3 b/man/io_uring_submit_and_wait.3 index 105cad2..909781a 100644 --- a/man/io_uring_submit_and_wait.3 +++ b/man/io_uring_submit_and_wait.3 @@ -10,9 +10,8 @@ io_uring_submit_and_wait - submit requests to the submission queue and wait for .nf .BR "#include " .PP -.BI "int io_uring_submit_and_wait(struct io_uring *ring," -.fi -.BI " unsigned wait_nr)" +.BI "int io_uring_submit_and_wait(struct io_uring *" ring "," +.BI " unsigned " wait_nr ");" .PP .SH DESCRIPTION .PP @@ -31,4 +30,4 @@ On success .BR io_uring_submit_and_wait (3) returns the number of submitted submission queue entries. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_submit_and_wait_timeout (3) \ No newline at end of file +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_submit_and_wait_timeout (3) diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 index d509915..2fd22ba 100644 --- a/man/io_uring_submit_and_wait_timeout.3 +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -11,15 +11,11 @@ wait for the completion with timeout .nf .BR "#include " .PP -.BI "int io_uring_submit_and_wait_timeout(struct io_uring *ring," -.fi -.BI " struct io_uring_cqe **cqe_ptr," -.fi -.BI " unsigned wait_nr," -.fi -.BI " struct __kernel_timespec *ts," -.fi -.BI " sigset_t *sigmask)" +.BI "int io_uring_submit_and_wait_timeout(struct io_uring *" ring "," +.BI " struct io_uring_cqe **" cqe_ptr "," +.BI " unsigned " wait_nr "," +.BI " struct __kernel_timespec *" ts "," +.BI " sigset_t *" sigmask ");" .PP .SH DESCRIPTION .PP @@ -46,4 +42,4 @@ On success .BR io_uring_submit_and_wait_timeout (3) returns the number of submitted submission queue entries. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_submit_and_wait (3), io_uring_wait_cqe (3) \ No newline at end of file +.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_submit_and_wait (3), io_uring_wait_cqe (3) diff --git a/man/io_uring_unregister_buffers.3 b/man/io_uring_unregister_buffers.3 index 4ec1048..d9d6f06 100644 --- a/man/io_uring_unregister_buffers.3 +++ b/man/io_uring_unregister_buffers.3 @@ -10,7 +10,7 @@ io_uring_unregister_buffers - unregister buffers for fixed buffer operations .nf .BR "#include " .PP -.BI "int io_uring_unregister_buffers(struct io_uring *ring)" +.BI "int io_uring_unregister_buffers(struct io_uring *" ring ");" .PP .SH DESCRIPTION .PP @@ -23,4 +23,4 @@ On success .BR io_uring_unregister_buffers (3) returns 0. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_register_buffers (3) \ No newline at end of file +.BR io_uring_register_buffers (3) diff --git a/man/io_uring_unregister_files.3 b/man/io_uring_unregister_files.3 index 0fadf5d..bcad996 100644 --- a/man/io_uring_unregister_files.3 +++ b/man/io_uring_unregister_files.3 @@ -10,7 +10,7 @@ io_uring_unregister_files - unregister file descriptors .nf .BR "#include " .PP -.BI "int io_uring_unregister_files(struct io_uring *ring)" +.BI "int io_uring_unregister_files(struct io_uring *" ring ");" .PP .SH DESCRIPTION .PP @@ -23,4 +23,4 @@ On success .BR io_uring_unregister_files (3) returns 0. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_register_files (3) \ No newline at end of file +.BR io_uring_register_files (3) diff --git a/man/io_uring_unregister_ring_fd.3 b/man/io_uring_unregister_ring_fd.3 index 4a43589..d4a1cc6 100644 --- a/man/io_uring_unregister_ring_fd.3 +++ b/man/io_uring_unregister_ring_fd.3 @@ -10,7 +10,7 @@ io_uring_unregister_ring_fd - unregister a ring file descriptor .nf .BR "#include " .PP -.BI "int io_uring_unregister_ring_fd(struct io_uring *ring)" +.BI "int io_uring_unregister_ring_fd(struct io_uring *" ring ");" .SH DESCRIPTION .PP diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3 index b4c3e98..1190d9b 100644 --- a/man/io_uring_wait_cqe.3 +++ b/man/io_uring_wait_cqe.3 @@ -9,8 +9,8 @@ io_uring_wait_cqe - wait for one io_uring completion event .nf .BR "#include " .PP -.BI "int io_uring_wait_cqe(struct io_uring *ring," -.BI " struct io_uring_cqe **cqe_ptr);" +.BI "int io_uring_wait_cqe(struct io_uring *" ring "," +.BI " struct io_uring_cqe **" cqe_ptr ");" .fi .PP .SH DESCRIPTION diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3 index 7f96300..3594b0b 100644 --- a/man/io_uring_wait_cqe_nr.3 +++ b/man/io_uring_wait_cqe_nr.3 @@ -9,9 +9,9 @@ io_uring_wait_cqe_nr - wait for one or more io_uring completion events .nf .BR "#include " .PP -.BI "int io_uring_wait_cqe_nr(struct io_uring *ring," -.BI " struct io_uring_cqe **cqe_ptr," -.BI " unsigned wait_nr)" +.BI "int io_uring_wait_cqe_nr(struct io_uring *" ring "," +.BI " struct io_uring_cqe **" cqe_ptr "," +.BI " unsigned " wait_nr ");" .fi .PP .SH DESCRIPTION diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 index d836352..64e920b 100644 --- a/man/io_uring_wait_cqe_timeout.3 +++ b/man/io_uring_wait_cqe_timeout.3 @@ -9,9 +9,9 @@ io_uring_wait_cqe_timeout - wait for one io_uring completion event with timeout .nf .BR "#include " .PP -.BI "int io_uring_wait_cqe_timeout(struct io_uring *ring," -.BI " struct io_uring_cqe **cqe_ptr," -.BI " struct __kernel_timespec *ts)" +.BI "int io_uring_wait_cqe_timeout(struct io_uring *" ring "," +.BI " struct io_uring_cqe **" cqe_ptr "," +.BI " struct __kernel_timespec *" ts ");" .PP .SH DESCRIPTION .PP @@ -36,4 +36,4 @@ On success .BR io_uring_wait_cqes (3) returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). \ No newline at end of file +.BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3 index 5c732da..a9a4a0c 100644 --- a/man/io_uring_wait_cqes.3 +++ b/man/io_uring_wait_cqes.3 @@ -9,11 +9,11 @@ io_uring_wait_cqes - wait for one or more io_uring completion events .nf .BR "#include " .PP -.BI "int io_uring_wait_cqes(struct io_uring *ring," -.BI " struct io_uring_cqe **cqe_ptr," -.BI " unsigned wait_nr," -.BI " struct __kernel_timespec *ts," -.BI " sigset_t *sigmask) +.BI "int io_uring_wait_cqes(struct io_uring *" ring "," +.BI " struct io_uring_cqe **" cqe_ptr "," +.BI " unsigned " wait_nr "," +.BI " struct __kernel_timespec *" ts "," +.BI " sigset_t *" sigmask "); .fi .PP .SH DESCRIPTION -- cgit v1.2.3 From aba7b1552c91b8ba3857f44e65e1fed08b9dbe7c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 14 Mar 2022 17:01:23 -0600 Subject: man: make mention of how direct file descriptors request an existing table Using direct opens/accepts requires that a file descriptor table already be registered with sparse slots, so that direct opens/accepts can just overwrite them. Signed-off-by: Jens Axboe --- man/io_uring_prep_accept.3 | 9 +++++++++ man/io_uring_prep_openat.3 | 9 +++++++++ man/io_uring_prep_openat2.3 | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index bf912da..0fa2466 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -51,6 +51,15 @@ member, and the SQE field should use the direct descriptor value rather than the regular file descriptor. Direct descriptors are managed like registered files. +If the direct variant is used, the application must first have registered +a sparse file table using +.BR io_uring_register_files (3) +of the appropriate size. A sparse table is one where each element is first +registered with a value of +.B -1. +Once registered, a direct accept request may use any sparse entry in that +table, as long as it is within the size of the registered table. + This function prepares an async .BR accept4 (2) request. See that man page for details. diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index 3fdc58a..c5710be 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -53,6 +53,15 @@ member, and the SQE field should use the direct descriptor value rather than the regular file descriptor. Direct descriptors are managed like registered files. +If the direct variant is used, the application must first have registered +a sparse file table using +.BR io_uring_register_files (3) +of the appropriate size. A sparse table is one where each element is first +registered with a value of +.B -1. +Once registered, a direct open request may use any sparse entry in that +table, as long as it is within the size of the registered table. + This function prepares an async .BR openat (2) request. See that man page for details. diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index f87d49b..672fd7c 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -54,6 +54,15 @@ member, and the SQE field should use the direct descriptor value rather than the regular file descriptor. Direct descriptors are managed like registered files. +If the direct variant is used, the application must first have registered +a sparse file table using +.BR io_uring_register_files (3) +of the appropriate size. A sparse table is one where each element is first +registered with a value of +.B -1. +Once registered, a direct open request may use any sparse entry in that +table, as long as it is within the size of the registered table. + This function prepares an async .BR openat2 (2) request. See that man page for details. -- cgit v1.2.3 From 77e374c9c1a04578b845ccdac9773c779aa1518a Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 17 Mar 2022 14:35:22 +0000 Subject: tests: don't sleep too much for rsrc tags check_cq_empty() sleeps for a second, and it's called many times throughout the test. It's too much, reduced it to 1ms. Even if there is a false negative, we don't care and next check_cq_empty() will fail. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/16780e103cfd395ad380bab4dbe6cf35cb581d98.1647527537.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/rsrc_tags.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rsrc_tags.c b/test/rsrc_tags.c index f441b5c..2d11d2a 100644 --- a/test/rsrc_tags.c +++ b/test/rsrc_tags.c @@ -27,7 +27,7 @@ static bool check_cq_empty(struct io_uring *ring) struct io_uring_cqe *cqe = NULL; int ret; - sleep(1); /* doesn't happen immediately, so wait */ + usleep(1000); /* doesn't happen immediately, so wait */ ret = io_uring_peek_cqe(ring, &cqe); /* nothing should be there */ return ret == -EAGAIN; } -- cgit v1.2.3 From eb02ccc00eb18ddf3e7218050be29da8c0d3b3bd Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 17 Mar 2022 15:23:34 +0000 Subject: man: clarifications about direct open/accept Direct open/accept replaces files for slots that are taken, so it's not necessary to use sparse file tables. Update on that, mention the replacing mechanism, and add a note about possible compitability issues for raw io_uring API users. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/4b6736f6da309756027b00f3b294417eb1832506.1647530578.git.asml.silence@gmail.com [axboe: add note on the existing entry being closed as well] Signed-off-by: Jens Axboe --- man/io_uring_prep_accept.3 | 17 +++++++++++------ man/io_uring_prep_openat.3 | 17 +++++++++++------ man/io_uring_prep_openat2.3 | 17 +++++++++++------ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 0fa2466..eec1b58 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -52,13 +52,18 @@ field should use the direct descriptor value rather than the regular file descriptor. Direct descriptors are managed like registered files. If the direct variant is used, the application must first have registered -a sparse file table using +a file table using .BR io_uring_register_files (3) -of the appropriate size. A sparse table is one where each element is first -registered with a value of -.B -1. -Once registered, a direct accept request may use any sparse entry in that -table, as long as it is within the size of the registered table. +of the appropriate size. Once registered, a direct accept request may use any +entry in that table, as long as it is within the size of the registered table. +If a specified entry already contains a file, the file will first be removed +from the table and closed. It's consistent with the behavior of updating an +existing file with +.BR io_uring_register_files_update (3). +Note that old kernels don't check the SQE +.I file_index +field, which is not a problem for liburing helpers, but users of the raw +io_uring interface need to zero SQEs to avoid unexpected behavior. This function prepares an async .BR accept4 (2) diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index c5710be..8094619 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -54,13 +54,18 @@ field should use the direct descriptor value rather than the regular file descriptor. Direct descriptors are managed like registered files. If the direct variant is used, the application must first have registered -a sparse file table using +a file table using .BR io_uring_register_files (3) -of the appropriate size. A sparse table is one where each element is first -registered with a value of -.B -1. -Once registered, a direct open request may use any sparse entry in that -table, as long as it is within the size of the registered table. +of the appropriate size. Once registered, a direct accept request may use any +entry in that table, as long as it is within the size of the registered table. +If a specified entry already contains a file, the file will first be removed +from the table and closed. It's consistent with the behavior of updating an +existing file with +.BR io_uring_register_files_update (3). +Note that old kernels don't check the SQE +.I file_index +field, which is not a problem for liburing helpers, but users of the raw +io_uring interface need to zero SQEs to avoid unexpected behavior. This function prepares an async .BR openat (2) diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 672fd7c..4898e30 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -55,13 +55,18 @@ field should use the direct descriptor value rather than the regular file descriptor. Direct descriptors are managed like registered files. If the direct variant is used, the application must first have registered -a sparse file table using +a file table using .BR io_uring_register_files (3) -of the appropriate size. A sparse table is one where each element is first -registered with a value of -.B -1. -Once registered, a direct open request may use any sparse entry in that -table, as long as it is within the size of the registered table. +of the appropriate size. Once registered, a direct accept request may use any +entry in that table, as long as it is within the size of the registered table. +If a specified entry already contains a file, the file will first be removed +from the table and closed. It's consistent with the behavior of updating an +existing file with +.BR io_uring_register_files_update (3). +Note that old kernels don't check the SQE +.I file_index +field, which is not a problem for liburing helpers, but users of the raw +io_uring interface need to zero SQEs to avoid unexpected behavior. This function prepares an async .BR openat2 (2) -- cgit v1.2.3 From 265236744ccb746d44bb62bc032dd93375d57a1b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 18 Mar 2022 09:47:47 -0600 Subject: man/io_uring_prep_accept.3: mention backwards compatability for direct Since older kernels don't check sqe->file_index and -EINVAL the request, applications cannot rely on this usual compatability way of dealing with whether or not the target host supports direct accept. Signed-off-by: Jens Axboe --- man/io_uring_prep_accept.3 | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index eec1b58..970b187 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -63,7 +63,14 @@ existing file with Note that old kernels don't check the SQE .I file_index field, which is not a problem for liburing helpers, but users of the raw -io_uring interface need to zero SQEs to avoid unexpected behavior. +io_uring interface need to zero SQEs to avoid unexpected behavior. This also +means that applications should check for availability of +.B IORING_OP_ACCEPT_DIRECT +before using it, they cannot rely on a +.B -EINVAL +CQE +.I res +return. This function prepares an async .BR accept4 (2) @@ -74,8 +81,13 @@ None .SH ERRORS The CQE .I res -field will contain the result of the operation. See the related man page for -details on possible values. Note that where synchronous system calls will return +field will contain the result of the operation. While the non-direct accept +returns the installed file descriptor as its value, the direct accept +returns +.B 0 +on success. The caller must know which direct descriptor was picked for this +request. See the related man page for details on possible values for the +non-direct accept. Note that where synchronous system calls will return .B -1 on failure and set .I errno -- cgit v1.2.3 From 12edb77b8f9dc2e508065d1baa6dfba2825d20c1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 18 Mar 2022 11:40:30 -0600 Subject: Add regression case for fixed buffers and non-iterator files A previous fix broke some cases of loop iteration, add a test case for it. Link: https://github.com/axboe/liburing/issues/549 Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 1 + test/fixed-buf-iter.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 test/fixed-buf-iter.c diff --git a/.gitignore b/.gitignore index ae16633..5e3b949 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ /test/file-verify /test/files-exit-hang-poll /test/files-exit-hang-timeout +/test/fixed-buf-iter /test/fixed-link /test/fpos /test/fsync diff --git a/test/Makefile b/test/Makefile index f5b2c7c..84c23c8 100644 --- a/test/Makefile +++ b/test/Makefile @@ -78,6 +78,7 @@ test_srcs := \ files-exit-hang-timeout.c \ file-update.c \ file-verify.c \ + fixed-buf-iter.c \ fixed-link.c \ fpos.c \ fsync.c \ diff --git a/test/fixed-buf-iter.c b/test/fixed-buf-iter.c new file mode 100644 index 0000000..9576993 --- /dev/null +++ b/test/fixed-buf-iter.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Test fixed buffers with non-iterators. + * + * Taken from: https://github.com/axboe/liburing/issues/549 + */ +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define BUF_SIZE 4096 +#define BUFFERS 1 +#define IN_FD "/dev/urandom" +#define OUT_FD "/dev/zero" + +static int test(struct io_uring *ring) +{ + struct iovec iov[BUFFERS]; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + int ret, fd_in, fd_out, i; + + fd_in = open(IN_FD, O_RDONLY, 0644); + if (fd_in < 0) { + perror("open in"); + return 1; + } + + fd_out = open(OUT_FD, O_RDWR, 0644); + if (fd_out < 0) { + perror("open out"); + return 1; + } + + for (i = 0; i < BUFFERS; i++) { + iov[i].iov_base = malloc(BUF_SIZE); + iov[i].iov_len = BUF_SIZE; + memset(iov[i].iov_base, 0, BUF_SIZE); + } + + ret = io_uring_register_buffers(ring, iov, BUFFERS); + if (ret) { + fprintf(stderr, "Error registering buffers: %s", strerror(-ret)); + return 1; + } + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "Could not get SQE.\n"); + return 1; + } + + io_uring_prep_read_fixed(sqe, fd_in, iov[0].iov_base, BUF_SIZE, 0, 0); + io_uring_submit(ring); + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "Error waiting for completion: %s\n", strerror(-ret)); + return 1; + } + + if (cqe->res < 0) { + fprintf(stderr, "Error in async operation: %s\n", strerror(-cqe->res)); + return 1; + } + io_uring_cqe_seen(ring, cqe); + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "Could not get SQE.\n"); + return 1; + } + io_uring_prep_write_fixed(sqe, fd_out, iov[0].iov_base, BUF_SIZE, 0, 0); + io_uring_submit(ring); + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "Error waiting for completion: %s\n", strerror(-ret)); + return 1; + } + if (cqe->res < 0) { + fprintf(stderr, "Error in async operation: %s\n", strerror(-cqe->res)); + return 1; + } + io_uring_cqe_seen(ring, cqe); + return 0; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + int ret; + + if (argc > 1) + return 0; + + ret = t_create_ring(8, &ring, 0); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret < 0) + return 1; + + ret = test(&ring); + if (ret) { + fprintf(stderr, "Test failed\n"); + return 1; + } + + io_uring_queue_exit(&ring); + return 0; +} -- cgit v1.2.3 From 8695f66bccda2170d8af2f99d3c1b8c6ee8bf602 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 19 Mar 2022 11:05:34 -0600 Subject: Style cleanups - No ident for #if/#else/#endif sections - Break up > 80 char lines unless they improve readability No intended functional changes in this patch. Signed-off-by: Jens Axboe --- src/include/liburing.h | 34 ++++++++++++++-------- src/nolibc.c | 2 +- src/queue.c | 7 +++-- src/register.c | 22 ++++++++------- src/setup.c | 4 +-- src/syscall.c | 2 +- src/syscall.h | 76 +++++++++++++++++++++++++------------------------- 7 files changed, 80 insertions(+), 67 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index b0c8704..5c03061 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -25,11 +25,11 @@ #include "liburing/barrier.h" #ifndef uring_unlikely -# define uring_unlikely(cond) __builtin_expect(!!(cond), 0) +#define uring_unlikely(cond) __builtin_expect(!!(cond), 0) #endif #ifndef uring_likely -# define uring_likely(cond) __builtin_expect(!!(cond), 1) +#define uring_likely(cond) __builtin_expect(!!(cond), 1) #endif #ifdef __cplusplus @@ -104,7 +104,8 @@ struct io_uring_probe *io_uring_get_probe(void); */ void io_uring_free_probe(struct io_uring_probe *probe); -static inline int io_uring_opcode_supported(const struct io_uring_probe *p, int op) +static inline int io_uring_opcode_supported(const struct io_uring_probe *p, + int op) { if (op > p->last_op) return 0; @@ -350,7 +351,8 @@ static inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd, static inline void io_uring_prep_readv2(struct io_uring_sqe *sqe, int fd, const struct iovec *iovecs, - unsigned nr_vecs, __u64 offset, int flags) + unsigned nr_vecs, __u64 offset, + int flags) { io_uring_prep_readv(sqe, fd, iovecs, nr_vecs, offset); sqe->rw_flags = flags; @@ -373,7 +375,8 @@ static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd, static inline void io_uring_prep_writev2(struct io_uring_sqe *sqe, int fd, const struct iovec *iovecs, - unsigned nr_vecs, __u64 offset, int flags) + unsigned nr_vecs, __u64 offset, + int flags) { io_uring_prep_writev(sqe, fd, iovecs, nr_vecs, offset); sqe->rw_flags = flags; @@ -395,7 +398,8 @@ static inline void io_uring_prep_recvmsg(struct io_uring_sqe *sqe, int fd, } static inline void io_uring_prep_sendmsg(struct io_uring_sqe *sqe, int fd, - const struct msghdr *msg, unsigned flags) + const struct msghdr *msg, + unsigned flags) { io_uring_prep_rw(IORING_OP_SENDMSG, sqe, fd, msg, 1, 0); sqe->msg_flags = flags; @@ -539,7 +543,8 @@ static inline void io_uring_prep_fallocate(struct io_uring_sqe *sqe, int fd, } static inline void io_uring_prep_openat(struct io_uring_sqe *sqe, int dfd, - const char *path, int flags, mode_t mode) + const char *path, int flags, + mode_t mode) { io_uring_prep_rw(IORING_OP_OPENAT, sqe, dfd, path, mode, 0); sqe->open_flags = (__u32) flags; @@ -575,7 +580,8 @@ static inline void io_uring_prep_read(struct io_uring_sqe *sqe, int fd, } static inline void io_uring_prep_write(struct io_uring_sqe *sqe, int fd, - const void *buf, unsigned nbytes, __u64 offset) + const void *buf, unsigned nbytes, + __u64 offset) { io_uring_prep_rw(IORING_OP_WRITE, sqe, fd, buf, nbytes, offset); } @@ -677,7 +683,8 @@ static inline void io_uring_prep_renameat(struct io_uring_sqe *sqe, int olddfd, const char *oldpath, int newdfd, const char *newpath, int flags) { - io_uring_prep_rw(IORING_OP_RENAMEAT, sqe, olddfd, oldpath, (__u32) newdfd, + io_uring_prep_rw(IORING_OP_RENAMEAT, sqe, olddfd, oldpath, + (__u32) newdfd, (uint64_t) (uintptr_t) newpath); sqe->rename_flags = (__u32) flags; } @@ -697,7 +704,8 @@ static inline void io_uring_prep_mkdirat(struct io_uring_sqe *sqe, int dfd, } static inline void io_uring_prep_symlinkat(struct io_uring_sqe *sqe, - const char *target, int newdirfd, const char *linkpath) + const char *target, int newdirfd, + const char *linkpath) { io_uring_prep_rw(IORING_OP_SYMLINKAT, sqe, newdirfd, target, 0, (uint64_t) (uintptr_t) linkpath); @@ -726,16 +734,18 @@ static inline void io_uring_prep_msg_ring(struct io_uring_sqe *sqe, int fd, */ static inline unsigned io_uring_sq_ready(const struct io_uring *ring) { + unsigned khead = *ring->sq.khead; + /* * Without a barrier, we could miss an update and think the SQ wasn't * ready. We don't need the load acquire for non-SQPOLL since then we * drive updates. */ if (ring->flags & IORING_SETUP_SQPOLL) - return ring->sq.sqe_tail - io_uring_smp_load_acquire(ring->sq.khead); + khead = io_uring_smp_load_acquire(ring->sq.khead); /* always use real head, to avoid losing sync for short submit */ - return ring->sq.sqe_tail - *ring->sq.khead; + return ring->sq.sqe_tail - khead; } /* diff --git a/src/nolibc.c b/src/nolibc.c index 1e17d22..9a04ead 100644 --- a/src/nolibc.c +++ b/src/nolibc.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: MIT */ #ifndef CONFIG_NOLIBC -# error "This file should only be compiled for no libc build" +#error "This file should only be compiled for no libc build" #endif #include "lib.h" diff --git a/src/queue.c b/src/queue.c index 2fec494..2f85756 100644 --- a/src/queue.c +++ b/src/queue.c @@ -51,7 +51,8 @@ struct get_data { void *arg; }; -static int _io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, +static int _io_uring_get_cqe(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, struct get_data *data) { struct io_uring_cqe *cqe = NULL; @@ -214,7 +215,8 @@ out: */ static int io_uring_wait_cqes_new(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, - unsigned wait_nr, struct __kernel_timespec *ts, + unsigned wait_nr, + struct __kernel_timespec *ts, sigset_t *sigmask) { struct io_uring_getevents_arg arg = { @@ -249,7 +251,6 @@ static int io_uring_wait_cqes_new(struct io_uring *ring, * hence this function is safe to use for applications that split SQ and CQ * handling between two threads. */ - static int __io_uring_submit_timeout(struct io_uring *ring, unsigned wait_nr, struct __kernel_timespec *ts) { diff --git a/src/register.c b/src/register.c index 1b96c77..8cdc332 100644 --- a/src/register.c +++ b/src/register.c @@ -8,7 +8,6 @@ #include "liburing/compat.h" #include "liburing/io_uring.h" - int io_uring_register_buffers_update_tag(struct io_uring *ring, unsigned off, const struct iovec *iovecs, const __u64 *tags, @@ -37,8 +36,9 @@ int io_uring_register_buffers_tags(struct io_uring *ring, .tags = (unsigned long)tags, }; - return ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_BUFFERS2, - ®, sizeof(reg)); + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_BUFFERS2, ®, + sizeof(reg)); } int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, @@ -55,8 +55,8 @@ int io_uring_unregister_buffers(struct io_uring *ring) { int ret; - ret = ____sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_BUFFERS, - NULL, 0); + ret = ____sys_io_uring_register(ring->ring_fd, + IORING_UNREGISTER_BUFFERS, NULL, 0); return (ret < 0) ? ret : 0; } @@ -184,8 +184,8 @@ int io_uring_unregister_eventfd(struct io_uring *ring) { int ret; - ret = ____sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_EVENTFD, - NULL, 0); + ret = ____sys_io_uring_register(ring->ring_fd, + IORING_UNREGISTER_EVENTFD, NULL, 0); return (ret < 0) ? ret : 0; } @@ -218,7 +218,8 @@ int io_uring_register_personality(struct io_uring *ring) int io_uring_unregister_personality(struct io_uring *ring, int id) { return ____sys_io_uring_register(ring->ring_fd, - IORING_UNREGISTER_PERSONALITY, NULL, id); + IORING_UNREGISTER_PERSONALITY, NULL, + id); } int io_uring_register_restrictions(struct io_uring *ring, @@ -242,8 +243,8 @@ int io_uring_enable_rings(struct io_uring *ring) int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, const cpu_set_t *mask) { - return ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_IOWQ_AFF, - mask, cpusz); + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_IOWQ_AFF, mask, cpusz); } int io_uring_unregister_iowq_aff(struct io_uring *ring) @@ -276,6 +277,7 @@ int io_uring_register_ring_fd(struct io_uring *ring) return ret; } + int io_uring_unregister_ring_fd(struct io_uring *ring) { struct io_uring_rsrc_update up = { diff --git a/src/setup.c b/src/setup.c index 5529784..35981da 100644 --- a/src/setup.c +++ b/src/setup.c @@ -8,7 +8,6 @@ #include "liburing/compat.h" #include "liburing/io_uring.h" - static void io_uring_unmap_rings(struct io_uring_sq *sq, struct io_uring_cq *cq) { __sys_munmap(sq->ring_ptr, sq->ring_sz); @@ -240,7 +239,8 @@ static size_t npages(size_t size, unsigned page_size) #define KRING_SIZE 320 -static size_t rings_size(unsigned entries, unsigned cq_entries, unsigned page_size) +static size_t rings_size(unsigned entries, unsigned cq_entries, + unsigned page_size) { size_t pages, sq_size, cq_size; diff --git a/src/syscall.c b/src/syscall.c index 4e28e25..362f1f5 100644 --- a/src/syscall.c +++ b/src/syscall.c @@ -8,7 +8,7 @@ * liburing's tests still need these functions. */ #if defined(CONFIG_NOLIBC) && !defined(LIBURING_BUILD_TEST) -# error "This file should only be compiled for libc build, or for liburing tests" +#error "This file should only be compiled for libc build, or for liburing tests" #endif /* diff --git a/src/syscall.h b/src/syscall.h index c05d132..214789d 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -18,35 +18,35 @@ * alpha and mips are exception, other architectures have * common numbers for new system calls. */ -# ifndef __NR_io_uring_setup -# define __NR_io_uring_setup 535 -# endif -# ifndef __NR_io_uring_enter -# define __NR_io_uring_enter 536 -# endif -# ifndef __NR_io_uring_register -# define __NR_io_uring_register 537 -# endif +#ifndef __NR_io_uring_setup +#define __NR_io_uring_setup 535 +#endif +#ifndef __NR_io_uring_enter +#define __NR_io_uring_enter 536 +#endif +#ifndef __NR_io_uring_register +#define __NR_io_uring_register 537 +#endif #elif defined __mips__ -# ifndef __NR_io_uring_setup -# define __NR_io_uring_setup (__NR_Linux + 425) -# endif -# ifndef __NR_io_uring_enter -# define __NR_io_uring_enter (__NR_Linux + 426) -# endif -# ifndef __NR_io_uring_register -# define __NR_io_uring_register (__NR_Linux + 427) -# endif +#ifndef __NR_io_uring_setup +#define __NR_io_uring_setup (__NR_Linux + 425) +#endif +#ifndef __NR_io_uring_enter +#define __NR_io_uring_enter (__NR_Linux + 426) +#endif +#ifndef __NR_io_uring_register +#define __NR_io_uring_register (__NR_Linux + 427) +#endif #else /* !__alpha__ and !__mips__ */ -# ifndef __NR_io_uring_setup -# define __NR_io_uring_setup 425 -# endif -# ifndef __NR_io_uring_enter -# define __NR_io_uring_enter 426 -# endif -# ifndef __NR_io_uring_register -# define __NR_io_uring_register 427 -# endif +#ifndef __NR_io_uring_setup +#define __NR_io_uring_setup 425 +#endif +#ifndef __NR_io_uring_enter +#define __NR_io_uring_enter 426 +#endif +#ifndef __NR_io_uring_register +#define __NR_io_uring_register 427 +#endif #endif /* @@ -72,19 +72,19 @@ static inline bool IS_ERR(const void *ptr) #define __INTERNAL__LIBURING_SYSCALL_H #if defined(__x86_64__) || defined(__i386__) - #include "arch/x86/syscall.h" +#include "arch/x86/syscall.h" #elif defined(__aarch64__) - #include "arch/aarch64/syscall.h" +#include "arch/aarch64/syscall.h" #else - /* - * We don't have native syscall wrappers - * for this arch. Must use libc! - */ - #ifdef CONFIG_NOLIBC - #error "This arch doesn't support building liburing without libc" - #endif - /* libc syscall wrappers. */ - #include "arch/generic/syscall.h" +/* + * We don't have native syscall wrappers + * for this arch. Must use libc! + */ +#ifdef CONFIG_NOLIBC + #error "This arch doesn't support building liburing without libc" +#endif +/* libc syscall wrappers. */ +#include "arch/generic/syscall.h" #endif #undef __INTERNAL__LIBURING_SYSCALL_H -- cgit v1.2.3 From 24908966b850a90256271c6fed020ddd5b9f997a Mon Sep 17 00:00:00 2001 From: Haiyue Wang Date: Sun, 20 Mar 2022 11:26:53 +0800 Subject: .gitignore: Add `test/drop-submit` to .gitignore The commit c56200f72a01 forgot to add it to .gitignore when creating this test. Signed-off-by: Haiyue Wang Link: https://lore.kernel.org/r/20220320032653.5986-1-haiyue.wang@intel.com Signed-off-by: Jens Axboe --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5e3b949..30119dd 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ /test/d77a67ed5f27-test /test/defer /test/double-poll-crash +/test/drop-submit /test/eeed8b54e0df-test /test/empty-eownerdead /test/eventfd -- cgit v1.2.3 From b39b41b45c53806bd145729a428e7a60c8c84f95 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 20 Mar 2022 07:31:08 -0600 Subject: Add citation file Provides an APA/BibTeX easy reference from github. Signed-off-by: Jens Axboe --- CITATION.cff | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 CITATION.cff diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..ed8a8eb --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,11 @@ +cff-version: 1.2.0 +preferred-citation: + type: software + authors: + - family-names: "Axboe" + given-names: "Jens" + email: axboe@kernel.dk + title: "liburing" + year: 2022 + url: "https://github.com/axboe/liburing" +licence: MIT -- cgit v1.2.3 From 15f1cae90aa0ddb9d3fefa1b4e5c3f0e5fd3ccab Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 20 Mar 2022 07:34:04 -0600 Subject: Fixup CITATION file Signed-off-by: Jens Axboe --- CITATION.cff | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index ed8a8eb..089f674 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,11 +1,11 @@ cff-version: 1.2.0 preferred-citation: - type: software - authors: +type: software +authors: - family-names: "Axboe" given-names: "Jens" email: axboe@kernel.dk - title: "liburing" - year: 2022 - url: "https://github.com/axboe/liburing" +title: "liburing library for io_uring" +year: 2022 +url: "https://github.com/axboe/liburing" licence: MIT -- cgit v1.2.3 From 56066e7a41fdc6a0d0c537c94b2e746554449943 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 20 Mar 2022 08:04:20 -0600 Subject: LICENSE: wrap the lines so it's actually readable Signed-off-by: Jens Axboe --- LICENSE | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index ae941fa..d559f33 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,20 @@ Copyright 2020 Jens Axboe -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -- cgit v1.2.3 From c94429f9e277ff102f33d7fad20a8aec98b9240b Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 21 Mar 2022 11:41:01 +0000 Subject: src/Makefile: re-add major version number to soname MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit c0b43df28a982747e081343f23289357ab4615db ("src/Makefile: use VERSION variable consistently") changed the library soname from liburing.so.2 to liburing.so. The idea of soname is that executables linked against liburing.so.2 continue to work with liburing.so.2.1, liburing.so.2.2, etc because the soname matches. They must not work against liburing.so.1 or liburing.so.3 though since those major versions are incompatible. Dropping the major version makes the soname unversioned and executables will link against future liburing releases that are not compatible. Fix the soname compatibility problem by re-adding the major version number. Compute it from the VERSION value instead of hardcoding it in the Makefile. liburing 2.1: $ readelf -a src/liburing.so.2.1 | grep SON 0x000000000000000e (SONAME) Library soname: [liburing.so.2] commit c0b43df28a98: $ readelf -a src/liburing.so.2.2 | grep SON 0x000000000000000e (SONAME) Library soname: [liburing.so] With this fix: $ readelf -a src/liburing.so.2.2 | grep SON 0x000000000000000e (SONAME) Library soname: [liburing.so.2] Fixes: c0b43df28a982747e081343f23289357ab4615db ("src/Makefile: use VERSION variable consistently") Reported-by: Daniel P. Berrangé Cc: Bikal Lem Signed-off-by: Stefan Hajnoczi Link: https://lore.kernel.org/r/20220321114101.682270-1-stefanha@redhat.com Signed-off-by: Jens Axboe --- Makefile.common | 1 + src/Makefile | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile.common b/Makefile.common index e7c9412..27fc233 100644 --- a/Makefile.common +++ b/Makefile.common @@ -2,4 +2,5 @@ TOP := $(dir $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) NAME=liburing SPECFILE=$(TOP)/$(NAME).spec VERSION=$(shell awk '/Version:/ { print $$2 }' $(SPECFILE)) +VERSION_MAJOR=$(shell echo $(VERSION) | cut -d. -f1) TAG = $(NAME)-$(VERSION) diff --git a/src/Makefile b/src/Makefile index 0e04986..12cf49f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,8 +16,8 @@ LINK_FLAGS= LINK_FLAGS+=$(LDFLAGS) ENABLE_SHARED ?= 1 -soname=liburing.so -libname=$(soname).$(VERSION) +soname=liburing.so.$(VERSION_MAJOR) +libname=liburing.so.$(VERSION) all_targets += liburing.a ifeq ($(ENABLE_SHARED),1) -- cgit v1.2.3 From 0faab9eff37e9bea33209e441229e0f4b4fd9007 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 22 Mar 2022 19:39:30 -0600 Subject: test/tty-write-dpoll: add test case for double poll write Test case for the regression fixed by: commit 6e295a664efd083ac9a5c1a8130c45be1db0cde7 Author: Jens Axboe Date: Tue Mar 22 13:11:28 2022 -0600 io_uring: fix assuming triggered poll waitqueue is the single poll Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 1 + test/tty-write-dpoll.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 test/tty-write-dpoll.c diff --git a/.gitignore b/.gitignore index 30119dd..c9f99c6 100644 --- a/.gitignore +++ b/.gitignore @@ -130,6 +130,7 @@ /test/timeout /test/timeout-new /test/timeout-overflow +/test/tty-write-dpoll /test/unlink /test/wakeup-hang /test/multicqes_drain diff --git a/test/Makefile b/test/Makefile index 84c23c8..a8249d6 100644 --- a/test/Makefile +++ b/test/Makefile @@ -152,6 +152,7 @@ test_srcs := \ timeout.c \ timeout-new.c \ timeout-overflow.c \ + tty-write-dpoll.c \ unlink.c \ wakeup-hang.c \ skip-cqe.c \ diff --git a/test/tty-write-dpoll.c b/test/tty-write-dpoll.c new file mode 100644 index 0000000..ea9df1d --- /dev/null +++ b/test/tty-write-dpoll.c @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Test double poll tty write. A test case for the regression fixed by: + * + * commit 6e295a664efd083ac9a5c1a8130c45be1db0cde7 + * Author: Jens Axboe + * Date: Tue Mar 22 13:11:28 2022 -0600 + * + * io_uring: fix assuming triggered poll waitqueue is the single poll + * + */ +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define SQES 128 +#define BUFSIZE 512 + +int main(int argc, char *argv[]) +{ + static char buf[BUFSIZE]; + struct iovec vecs[SQES]; + struct io_uring ring; + int ret, i, fd; + + if (argc > 1) + return 0; + + fd = open("/dev/ttyS0", O_RDWR | O_NONBLOCK); + if (fd < 0) + return 0; + + ret = t_create_ring(SQES, &ring, 0); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret < 0) + return 1; + + for (i = 0; i < SQES; i++) { + struct io_uring_sqe *sqe; + + sqe = io_uring_get_sqe(&ring); + vecs[i].iov_base = buf; + vecs[i].iov_len = sizeof(buf); + io_uring_prep_writev(sqe, fd, &vecs[i], 1, 0); + } + + ret = io_uring_submit(&ring); + if (ret != SQES) { + fprintf(stderr, "submit: %d\n", ret); + return 1; + } + + return 0; +} -- cgit v1.2.3 From b86fdae82f033acf40ba86b4158c9ca2539cde61 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 23 Mar 2022 09:41:09 -0600 Subject: Add test case for recv/recvmsg MSG_WAITALL Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 2 + test/recv-msgall.c | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 282 insertions(+) create mode 100644 test/recv-msgall.c diff --git a/.gitignore b/.gitignore index c9f99c6..49c8fe5 100644 --- a/.gitignore +++ b/.gitignore @@ -96,6 +96,7 @@ /test/pollfree /test/probe /test/read-write +/test/recv-msgall /test/register-restrictions /test/rename /test/ring-leak diff --git a/test/Makefile b/test/Makefile index a8249d6..0a659c5 100644 --- a/test/Makefile +++ b/test/Makefile @@ -115,6 +115,7 @@ test_srcs := \ pollfree.c \ probe.c \ read-write.c \ + recv-msgall.c \ register-restrictions.c \ rename.c \ ring-leak2.c \ @@ -226,6 +227,7 @@ poll-mshot-update: override LDFLAGS += -lpthread exit-no-cleanup: override LDFLAGS += -lpthread pollfree: override LDFLAGS += -lpthread msg-ring: override LDFLAGS += -lpthread +recv-msgall: override LDFLAGS += -lpthread install: $(test_targets) runtests.sh runtests-loop.sh $(INSTALL) -D -d -m 755 $(datadir)/liburing-test/ diff --git a/test/recv-msgall.c b/test/recv-msgall.c new file mode 100644 index 0000000..02af1b2 --- /dev/null +++ b/test/recv-msgall.c @@ -0,0 +1,279 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Test MSG_WAITALL + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define MAX_MSG 128 + +#define PORT 10200 +#define HOST "127.0.0.1" + +static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock, + int use_recvmsg) +{ + struct sockaddr_in saddr; + struct io_uring_sqe *sqe; + int sockfd, ret, val; + struct msghdr msg = { }; + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + saddr.sin_port = htons(PORT); + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror("socket"); + return 1; + } + + val = 1; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + + ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); + if (ret < 0) { + perror("bind"); + goto err; + } + + sqe = io_uring_get_sqe(ring); + if (!use_recvmsg) { + io_uring_prep_recv(sqe, sockfd, iov->iov_base, iov->iov_len, + MSG_WAITALL); + } else { + msg.msg_namelen = sizeof(struct sockaddr_in); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + io_uring_prep_recvmsg(sqe, sockfd, &msg, MSG_WAITALL); + } + + sqe->user_data = 2; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "submit failed: %d\n", ret); + goto err; + } + + *sock = sockfd; + return 0; +err: + close(sockfd); + return 1; +} + +static int do_recv(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + int ret; + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stdout, "wait_cqe: %d\n", ret); + goto err; + } + if (cqe->res == -EINVAL) { + fprintf(stdout, "recv not supported, skipping\n"); + return 0; + } + if (cqe->res < 0) { + fprintf(stderr, "failed cqe: %d\n", cqe->res); + goto err; + } + if (cqe->res != MAX_MSG * sizeof(int)) { + fprintf(stderr, "got wrong length: %d\n", cqe->res); + goto err; + } + + io_uring_cqe_seen(ring, cqe); + return 0; +err: + return 1; +} + +struct recv_data { + pthread_mutex_t mutex; + int use_recvmsg; +}; + +static void *recv_fn(void *data) +{ + struct recv_data *rd = data; + int buf[MAX_MSG]; + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf), + }; + struct io_uring_params p = { }; + struct io_uring ring; + int ret, sock; + + ret = t_create_ring_params(1, &ring, &p); + if (ret == T_SETUP_SKIP) { + pthread_mutex_unlock(&rd->mutex); + ret = 0; + goto err; + } else if (ret < 0) { + pthread_mutex_unlock(&rd->mutex); + goto err; + } + + ret = recv_prep(&ring, &iov, &sock, rd->use_recvmsg); + if (ret) { + fprintf(stderr, "recv_prep failed: %d\n", ret); + goto err; + } + pthread_mutex_unlock(&rd->mutex); + ret = do_recv(&ring); + if (!ret) { + int i; + + for (i = 0; i < MAX_MSG; i++) { + if (buf[i] != i) { + fprintf(stderr, "found %d at %d\n", buf[i], i); + ret = 1; + break; + } + } + } + + close(sock); + io_uring_queue_exit(&ring); +err: + return (void *)(intptr_t)ret; +} + +static int do_send(void) +{ + struct sockaddr_in saddr; + struct io_uring ring; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int sockfd, ret, i; + struct iovec iov; + int *buf; + + ret = io_uring_queue_init(2, &ring, 0); + if (ret) { + fprintf(stderr, "queue init failed: %d\n", ret); + return 1; + } + + buf = malloc(MAX_MSG * sizeof(int)); + for (i = 0; i < MAX_MSG; i++) + buf[i] = i; + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = htons(PORT); + inet_pton(AF_INET, HOST, &saddr.sin_addr); + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror("socket"); + return 1; + } + + ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); + if (ret < 0) { + perror("connect"); + return 1; + } + + iov.iov_base = buf; + iov.iov_len = MAX_MSG * sizeof(int) / 2; + for (i = 0; i < 2; i++) { + sqe = io_uring_get_sqe(&ring); + io_uring_prep_send(sqe, sockfd, iov.iov_base, iov.iov_len, 0); + sqe->user_data = 1; + + ret = io_uring_submit(&ring); + if (ret <= 0) { + fprintf(stderr, "submit failed: %d\n", ret); + goto err; + } + usleep(10000); + iov.iov_base += iov.iov_len; + } + + for (i = 0; i < 2; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (cqe->res == -EINVAL) { + fprintf(stdout, "send not supported, skipping\n"); + close(sockfd); + return 0; + } + if (cqe->res != iov.iov_len) { + fprintf(stderr, "failed cqe: %d\n", cqe->res); + goto err; + } + io_uring_cqe_seen(&ring, cqe); + } + + close(sockfd); + return 0; +err: + close(sockfd); + return 1; +} + +static int test(int use_recvmsg) +{ + pthread_mutexattr_t attr; + pthread_t recv_thread; + struct recv_data rd; + int ret; + void *retval; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_setpshared(&attr, 1); + pthread_mutex_init(&rd.mutex, &attr); + pthread_mutex_lock(&rd.mutex); + rd.use_recvmsg = use_recvmsg; + + ret = pthread_create(&recv_thread, NULL, recv_fn, &rd); + if (ret) { + fprintf(stderr, "Thread create failed: %d\n", ret); + pthread_mutex_unlock(&rd.mutex); + return 1; + } + + pthread_mutex_lock(&rd.mutex); + do_send(); + pthread_join(recv_thread, &retval); + return (int)(intptr_t)retval; +} + +int main(int argc, char *argv[]) +{ + int ret; + + if (argc > 1) + return 0; + + ret = test(0); + if (ret) { + fprintf(stderr, "test recv failed\n"); + // return ret; + } + + ret = test(1); + if (ret) { + fprintf(stderr, "test recvmsg failed\n"); + return ret; + } + + return 0; +} -- cgit v1.2.3 From ac60e50cb537a29ab502285af08da374b358248e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 23 Mar 2022 16:36:38 -0600 Subject: test/msg-recvall: fix test We should expect just half of the requested amount for a DGRAM socket. Signed-off-by: Jens Axboe --- test/recv-msgall.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/test/recv-msgall.c b/test/recv-msgall.c index 02af1b2..d77434d 100644 --- a/test/recv-msgall.c +++ b/test/recv-msgall.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: MIT */ /* - * Test MSG_WAITALL + * Test MSG_WAITALL with datagram sockets, with a send splice into two. */ #include #include @@ -92,7 +92,7 @@ static int do_recv(struct io_uring *ring) fprintf(stderr, "failed cqe: %d\n", cqe->res); goto err; } - if (cqe->res != MAX_MSG * sizeof(int)) { + if (cqe->res != MAX_MSG * sizeof(int) / 2) { fprintf(stderr, "got wrong length: %d\n", cqe->res); goto err; } @@ -137,18 +137,6 @@ static void *recv_fn(void *data) } pthread_mutex_unlock(&rd->mutex); ret = do_recv(&ring); - if (!ret) { - int i; - - for (i = 0; i < MAX_MSG; i++) { - if (buf[i] != i) { - fprintf(stderr, "found %d at %d\n", buf[i], i); - ret = 1; - break; - } - } - } - close(sock); io_uring_queue_exit(&ring); err: @@ -266,7 +254,7 @@ int main(int argc, char *argv[]) ret = test(0); if (ret) { fprintf(stderr, "test recv failed\n"); - // return ret; + return ret; } ret = test(1); -- cgit v1.2.3 From 03d6cdab9ff670e8703f54dd198c99cf399e41b5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 23 Mar 2022 16:38:37 -0600 Subject: test/recv-msgall-stream: add stream based MSG_WAITALL test case Submit two separate writes, and a receiver that asks for the combined length should receive the combined length, not half of it. Signed-off-by: Jens Axboe --- test/recv-msgall-stream.c | 427 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 test/recv-msgall-stream.c diff --git a/test/recv-msgall-stream.c b/test/recv-msgall-stream.c new file mode 100644 index 0000000..3127b5f --- /dev/null +++ b/test/recv-msgall-stream.c @@ -0,0 +1,427 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Test MSG_WAITALL for recv/recvmsg and include normal sync versions just + * for comparison. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define MAX_MSG 128 + +static int port = 31200; + +struct recv_data { + pthread_mutex_t mutex; + int use_recvmsg; + int use_sync; + int port; +}; + +static int get_conn_sock(struct recv_data *rd, int *sockout) +{ + struct sockaddr_in saddr; + int sockfd, ret, val; + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + saddr.sin_port = htons(rd->port); + + sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); + if (sockfd < 0) { + perror("socket"); + goto err; + } + + val = 1; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); + + ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); + if (ret < 0) { + perror("bind"); + goto err; + } + + ret = listen(sockfd, 16); + if (ret < 0) { + perror("listen"); + goto err; + } + + pthread_mutex_unlock(&rd->mutex); + + ret = accept(sockfd, NULL, NULL); + if (ret < 0) { + perror("accept"); + return -1; + } + + *sockout = sockfd; + return ret; +err: + pthread_mutex_unlock(&rd->mutex); + return -1; +} + +static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock, + struct recv_data *rd) +{ + struct io_uring_sqe *sqe; + struct msghdr msg = { }; + int sockfd, sockout = -1, ret; + + sockfd = get_conn_sock(rd, &sockout); + if (sockfd < 0) + goto err; + + sqe = io_uring_get_sqe(ring); + if (!rd->use_recvmsg) { + io_uring_prep_recv(sqe, sockfd, iov->iov_base, iov->iov_len, + MSG_WAITALL); + } else { + msg.msg_namelen = sizeof(struct sockaddr_in); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + io_uring_prep_recvmsg(sqe, sockfd, &msg, MSG_WAITALL); + } + + sqe->user_data = 2; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "submit failed: %d\n", ret); + goto err; + } + + *sock = sockfd; + return 0; +err: + if (sockout != -1) { + shutdown(sockout, SHUT_RDWR); + close(sockout); + } + if (sockfd != -1) { + shutdown(sockfd, SHUT_RDWR); + close(sockfd); + } + return 1; +} + +static int do_recv(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + int ret; + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stdout, "wait_cqe: %d\n", ret); + goto err; + } + if (cqe->res == -EINVAL) { + fprintf(stdout, "recv not supported, skipping\n"); + return 0; + } + if (cqe->res < 0) { + fprintf(stderr, "failed cqe: %d\n", cqe->res); + goto err; + } + if (cqe->res != MAX_MSG * sizeof(int)) { + fprintf(stderr, "got wrong length: %d\n", cqe->res); + goto err; + } + + io_uring_cqe_seen(ring, cqe); + return 0; +err: + return 1; +} + +static int recv_sync(struct recv_data *rd) +{ + int buf[MAX_MSG]; + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf), + }; + int i, ret, sockfd, sockout = -1; + + sockfd = get_conn_sock(rd, &sockout); + + if (rd->use_recvmsg) { + struct msghdr msg = { }; + + msg.msg_namelen = sizeof(struct sockaddr_in); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + ret = recvmsg(sockfd, &msg, MSG_WAITALL); + } else { + ret = recv(sockfd, buf, sizeof(buf), MSG_WAITALL); + } + + if (ret < 0) { + perror("receive"); + goto err; + } + + if (ret != sizeof(buf)) { + ret = -1; + goto err; + } + + for (i = 0; i < MAX_MSG; i++) { + if (buf[i] != i) + goto err; + } + ret = 0; +err: + shutdown(sockout, SHUT_RDWR); + shutdown(sockfd, SHUT_RDWR); + close(sockout); + close(sockfd); + return ret; +} + +static int recv_uring(struct recv_data *rd) +{ + int buf[MAX_MSG]; + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf), + }; + struct io_uring_params p = { }; + struct io_uring ring; + int ret, sock = -1, sockout = -1; + + ret = t_create_ring_params(1, &ring, &p); + if (ret == T_SETUP_SKIP) { + pthread_mutex_unlock(&rd->mutex); + ret = 0; + goto err; + } else if (ret < 0) { + pthread_mutex_unlock(&rd->mutex); + goto err; + } + + sock = recv_prep(&ring, &iov, &sockout, rd); + if (ret) { + fprintf(stderr, "recv_prep failed: %d\n", ret); + goto err; + } + ret = do_recv(&ring); + if (!ret) { + int i; + + for (i = 0; i < MAX_MSG; i++) { + if (buf[i] != i) { + fprintf(stderr, "found %d at %d\n", buf[i], i); + ret = 1; + break; + } + } + } + + shutdown(sockout, SHUT_RDWR); + shutdown(sock, SHUT_RDWR); + close(sock); + close(sockout); + io_uring_queue_exit(&ring); +err: + if (sock != -1) { + shutdown(sock, SHUT_RDWR); + close(sock); + } + if (sockout != -1) { + shutdown(sockout, SHUT_RDWR); + close(sockout); + } + return ret; +} + +static void *recv_fn(void *data) +{ + struct recv_data *rd = data; + + if (rd->use_sync) + return (void *) (uintptr_t) recv_sync(rd); + + return (void *) (uintptr_t) recv_uring(rd); +} + +static int do_send(struct recv_data *rd) +{ + struct sockaddr_in saddr; + struct io_uring ring; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int sockfd, ret, i; + struct iovec iov; + int *buf; + + ret = io_uring_queue_init(2, &ring, 0); + if (ret) { + fprintf(stderr, "queue init failed: %d\n", ret); + return 1; + } + + buf = malloc(MAX_MSG * sizeof(int)); + for (i = 0; i < MAX_MSG; i++) + buf[i] = i; + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = htons(rd->port); + inet_pton(AF_INET, "127.0.0.1", &saddr.sin_addr); + + sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); + if (sockfd < 0) { + perror("socket"); + return 1; + } + + pthread_mutex_lock(&rd->mutex); + + ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); + if (ret < 0) { + struct pollfd pfd = { + .fd = sockfd, + .events = POLLOUT, + }; + + if (errno != EINPROGRESS) { + perror("connect"); + return 1; + } + + if (poll(&pfd, 1, -1) < 0) { + perror("poll"); + return 1; + } + if (!(pfd.revents & POLLOUT)) { + fprintf(stderr, "huh\n"); + return 1; + } + + while (1) { + int out; + socklen_t len = sizeof(out); + + getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &out, &len); + if (!out) + break; + usleep(1000); + } + } + + iov.iov_base = buf; + iov.iov_len = MAX_MSG * sizeof(int) / 2; + for (i = 0; i < 2; i++) { + sqe = io_uring_get_sqe(&ring); + io_uring_prep_send(sqe, sockfd, iov.iov_base, iov.iov_len, 0); + sqe->user_data = 1; + + ret = io_uring_submit(&ring); + if (ret <= 0) { + fprintf(stderr, "submit failed: %d\n", ret); + goto err; + } + usleep(10000); + iov.iov_base += iov.iov_len; + } + + for (i = 0; i < 2; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (cqe->res == -EINVAL) { + fprintf(stdout, "send not supported, skipping\n"); + close(sockfd); + return 0; + } + if (cqe->res != iov.iov_len) { + fprintf(stderr, "failed cqe: %d\n", cqe->res); + goto err; + } + io_uring_cqe_seen(&ring, cqe); + } + + shutdown(sockfd, SHUT_RDWR); + close(sockfd); + return 0; +err: + shutdown(sockfd, SHUT_RDWR); + close(sockfd); + return 1; +} + +static int test(int use_recvmsg, int use_sync) +{ + pthread_mutexattr_t attr; + pthread_t recv_thread; + struct recv_data rd; + int ret; + void *retval; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_setpshared(&attr, 1); + pthread_mutex_init(&rd.mutex, &attr); + pthread_mutex_lock(&rd.mutex); + rd.use_recvmsg = use_recvmsg; + rd.use_sync = use_sync; + rd.port = port++; + + ret = pthread_create(&recv_thread, NULL, recv_fn, &rd); + if (ret) { + fprintf(stderr, "Thread create failed: %d\n", ret); + pthread_mutex_unlock(&rd.mutex); + return 1; + } + + do_send(&rd); + pthread_join(recv_thread, &retval); + return (int)(intptr_t)retval; +} + +int main(int argc, char *argv[]) +{ + int ret; + + if (argc > 1) + return 0; + + ret = test(0, 0); + if (ret) { + fprintf(stderr, "test recv failed\n"); + return ret; + } + + ret = test(1, 0); + if (ret) { + fprintf(stderr, "test recvmsg failed\n"); + return ret; + } + + ret = test(0, 1); + if (ret) { + fprintf(stderr, "test sync recv failed\n"); + return ret; + } + + ret = test(1, 1); + if (ret) { + fprintf(stderr, "test sync recvmsg failed\n"); + return ret; + } + + return 0; +} -- cgit v1.2.3 From a264c2db27df2da90201d8e61f927ddf9320fa0e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 23 Mar 2022 16:45:58 -0600 Subject: Actually wire up recv-msgall-stream test case Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 49c8fe5..36f8ead 100644 --- a/.gitignore +++ b/.gitignore @@ -97,6 +97,7 @@ /test/probe /test/read-write /test/recv-msgall +/test/recv-msgall-stream /test/register-restrictions /test/rename /test/ring-leak diff --git a/test/Makefile b/test/Makefile index 0a659c5..f1accbf 100644 --- a/test/Makefile +++ b/test/Makefile @@ -116,6 +116,7 @@ test_srcs := \ probe.c \ read-write.c \ recv-msgall.c \ + recv-msgall-stream.c \ register-restrictions.c \ rename.c \ ring-leak2.c \ @@ -228,6 +229,7 @@ exit-no-cleanup: override LDFLAGS += -lpthread pollfree: override LDFLAGS += -lpthread msg-ring: override LDFLAGS += -lpthread recv-msgall: override LDFLAGS += -lpthread +recv-msgall-stream: override LDFLAGS += -lpthread install: $(test_targets) runtests.sh runtests-loop.sh $(INSTALL) -D -d -m 755 $(datadir)/liburing-test/ -- cgit v1.2.3 From 8b0529c24be9ed50c4422b479f5b2c7cdc837777 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 23 Mar 2022 16:51:30 -0600 Subject: test/recv-msgall-stream: remove nonblocking connect code Not using nonblocking sockets here anymore, so just kill it. Signed-off-by: Jens Axboe --- test/recv-msgall-stream.c | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/test/recv-msgall-stream.c b/test/recv-msgall-stream.c index 3127b5f..a4dfe6f 100644 --- a/test/recv-msgall-stream.c +++ b/test/recv-msgall-stream.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "liburing.h" #include "helpers.h" @@ -295,34 +294,8 @@ static int do_send(struct recv_data *rd) ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { - struct pollfd pfd = { - .fd = sockfd, - .events = POLLOUT, - }; - - if (errno != EINPROGRESS) { - perror("connect"); - return 1; - } - - if (poll(&pfd, 1, -1) < 0) { - perror("poll"); - return 1; - } - if (!(pfd.revents & POLLOUT)) { - fprintf(stderr, "huh\n"); - return 1; - } - - while (1) { - int out; - socklen_t len = sizeof(out); - - getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &out, &len); - if (!out) - break; - usleep(1000); - } + perror("connect"); + return 1; } iov.iov_base = buf; -- cgit v1.2.3 From da46d0b897c2da8cb5494e3e8f1127f183f11c77 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 24 Mar 2022 06:51:48 -0600 Subject: test/test/msg-ring: don't test for IORING_CQE_F_MSG It's not strictly needed, just don't test for it. We validate the user_data being passed. Signed-off-by: Jens Axboe --- test/msg-ring.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/msg-ring.c b/test/msg-ring.c index 8930e72..209d61c 100644 --- a/test/msg-ring.c +++ b/test/msg-ring.c @@ -54,10 +54,6 @@ static int test_own(struct io_uring *ring) } break; case 0x1234: - if (!(cqe->flags & IORING_CQE_F_MSG)) { - fprintf(stderr, "invalid flags %x\n", cqe->flags); - return -1; - } if (cqe->res != 0x10) { fprintf(stderr, "invalid len %x\n", cqe->res); return -1; @@ -87,10 +83,6 @@ static void *wait_cqe_fn(void *data) goto err; } - if (!(cqe->flags & IORING_CQE_F_MSG)) { - fprintf(stderr, "invalid flags %x\n", cqe->flags); - goto err; - } if (cqe->user_data != 0x5aa5) { fprintf(stderr, "user_data %llx\n", (long long) cqe->user_data); goto err; -- cgit v1.2.3 From 68c8759abcbff6262e7aa758beec3c9f5696ee46 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 24 Mar 2022 06:56:45 -0600 Subject: Remove IORING_CQE_F_MSG Remove it from the io_uring_prep_msg_ring.3 man page as it's no longer being set by the kernel, and remove the definition and comment from the kernel header. Signed-off-by: Jens Axboe --- man/io_uring_prep_msg_ring.3 | 7 ------- src/include/liburing/io_uring.h | 2 -- 2 files changed, 9 deletions(-) diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index 7f03870..68699cb 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -47,13 +47,6 @@ fields. The use case may be anything from simply waking up someone waiting on the targeted ring, or it can be used to pass messages between the two rings. -The resulting CQE posted on the target ring will have -.B IORING_CQE_F_MSG -set in its -.I flags -member, indicating to the target ring that this CQE is posted without having -a relationship to an SQE issued on this ring. - .SH RETURN VALUE None diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 15516b7..d858977 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -205,11 +205,9 @@ struct io_uring_cqe { * * IORING_CQE_F_BUFFER If set, the upper 16 bits are the buffer ID * IORING_CQE_F_MORE If set, parent SQE will generate more CQE entries - * IORING_CQE_F_MSG If set, CQE was generated with IORING_OP_MSG_RING */ #define IORING_CQE_F_BUFFER (1U << 0) #define IORING_CQE_F_MORE (1U << 1) -#define IORING_CQE_F_MSG (1U << 2) enum { IORING_CQE_BUFFER_SHIFT = 16, -- cgit v1.2.3 From 7f17de7928388215eaffbcfeb71c1caac80cb993 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 24 Mar 2022 08:57:51 -0600 Subject: man/io_uring_queue_init.3: add note on CQ ring sizing Signed-off-by: Jens Axboe --- man/io_uring_queue_init.3 | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index e925589..807d8b4 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -26,8 +26,31 @@ The io_uring_queue_init() function executes the system call to initialize the submission and completion queues in the kernel with at least .I entries -entries and then maps the resulting file descriptor to memory shared between the -application and the kernel. +entries in the submission queue and then maps the resulting file descriptor to +memory shared between the application and the kernel. + +By default, the CQ ring will have twice the number of entries as specified by +.I entries +for the SQ ring. This is adequate for regular file or storage workloads, but +may be too small networked workloads. The SQ ring entries do not impose a limit +on the number of in-flight requests that the ring can support, it merely limits +the number that can be submitted to the kernel in one go (batch). if the CQ +ring overflows, eg more entries are generated than fits in the ring before the +application can reap them, then the ring enters a CQ ring overflow state. This +is indicated by +.B IORING_SQ_CQ_OVERFLOW +being set in the SQ ring flags. Unless the kernel runs out of available memory, +entries are not dropped, but it is a much slower completion path and will slow +down request processing. For that reason it should be avoided, and the CQ +ring sized appropriately for the workload. Setting +.I cq_entries +in +.I struct io_uring_params +will tell the kernel to allocate this many entries for the CQ ring, independent +of the SQ ring size in given in +.I entries. +If the value isn't a power of 2, it will be rounded up to the nearest power of +2. On success io_uring_queue_init() returns 0 and .I ring -- cgit v1.2.3 From 7a3a27b6a384f51b67f7e7086f47cf552fa70dc4 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Thu, 24 Mar 2022 07:35:47 -0700 Subject: add tests for nonblocking accept sockets Add tests for accept sockets with O_NONBLOCK. Add a test for queueing the accept both before and after connect(), which tests slightly different code paths. After connect() has always worked, but before required changes to the kernel. Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220324143547.2882041-1-dylany@fb.com Signed-off-by: Jens Axboe --- test/accept.c | 132 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 97 insertions(+), 35 deletions(-) diff --git a/test/accept.c b/test/accept.c index af2997f..e2c6b51 100644 --- a/test/accept.c +++ b/test/accept.c @@ -59,27 +59,32 @@ static void queue_recv(struct io_uring *ring, int fd, bool fixed) sqe->flags |= IOSQE_FIXED_FILE; } -static int accept_conn(struct io_uring *ring, int fd, bool fixed) +static void queue_accept_conn(struct io_uring *ring, int fd, int fixed_idx) { struct io_uring_sqe *sqe; - struct io_uring_cqe *cqe; - int ret, fixed_idx = 0; + int ret; sqe = io_uring_get_sqe(ring); - if (!fixed) + if (fixed_idx < 0) io_uring_prep_accept(sqe, fd, NULL, NULL, 0); else io_uring_prep_accept_direct(sqe, fd, NULL, NULL, 0, fixed_idx); ret = io_uring_submit(ring); assert(ret != -1); +} + +static int accept_conn(struct io_uring *ring, int fixed_idx) +{ + struct io_uring_cqe *cqe; + int ret; ret = io_uring_wait_cqe(ring, &cqe); assert(!ret); ret = cqe->res; io_uring_cqe_seen(ring, cqe); - if (fixed) { + if (fixed_idx >= 0) { if (ret > 0) { close(ret); return -EINVAL; @@ -90,11 +95,13 @@ static int accept_conn(struct io_uring *ring, int fd, bool fixed) return ret; } -static int start_accept_listen(struct sockaddr_in *addr, int port_off) +static int start_accept_listen(struct sockaddr_in *addr, int port_off, + int extra_flags) { int fd, ret; - fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); + fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC | extra_flags, + IPPROTO_TCP); int32_t val = 1; ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); @@ -119,14 +126,23 @@ static int start_accept_listen(struct sockaddr_in *addr, int port_off) return fd; } -static int test(struct io_uring *ring, int accept_should_error, bool fixed) +struct accept_test_args { + int accept_should_error; + bool fixed; + bool nonblock; + bool queue_accept_before_connect; +}; + +static int test(struct io_uring *ring, struct accept_test_args args) { struct io_uring_cqe *cqe; struct sockaddr_in addr; uint32_t head, count = 0; int ret, p_fd[2], done = 0; - int32_t val, recv_s0 = start_accept_listen(&addr, 0); + int32_t val; + int32_t recv_s0 = start_accept_listen(&addr, 0, + args.nonblock ? O_NONBLOCK : 0); p_fd[1] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); @@ -141,6 +157,9 @@ static int test(struct io_uring *ring, int accept_should_error, bool fixed) ret = fcntl(p_fd[1], F_SETFL, flags); assert(ret != -1); + if (args.queue_accept_before_connect) + queue_accept_conn(ring, recv_s0, args.fixed ? 0 : -1); + ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr)); assert(ret == -1); @@ -151,18 +170,21 @@ static int test(struct io_uring *ring, int accept_should_error, bool fixed) ret = fcntl(p_fd[1], F_SETFL, flags); assert(ret != -1); - p_fd[0] = accept_conn(ring, recv_s0, fixed); + if (!args.queue_accept_before_connect) + queue_accept_conn(ring, recv_s0, args.fixed ? 0 : -1); + + p_fd[0] = accept_conn(ring, args.fixed ? 0 : -1); if (p_fd[0] == -EINVAL) { - if (accept_should_error) + if (args.accept_should_error) goto out; - if (fixed) + if (args.fixed) fprintf(stdout, "Fixed accept not supported, skipping\n"); else fprintf(stdout, "Accept not supported, skipping\n"); no_accept = 1; goto out; } else if (p_fd[0] < 0) { - if (accept_should_error && + if (args.accept_should_error && (p_fd[0] == -EBADF || p_fd[0] == -EINVAL)) goto out; fprintf(stderr, "Accept got %d\n", p_fd[0]); @@ -170,7 +192,7 @@ static int test(struct io_uring *ring, int accept_should_error, bool fixed) } queue_send(ring, p_fd[1]); - queue_recv(ring, p_fd[0], fixed); + queue_recv(ring, p_fd[0], args.fixed); ret = io_uring_submit_and_wait(ring, 2); assert(ret != -1); @@ -194,13 +216,13 @@ static int test(struct io_uring *ring, int accept_should_error, bool fixed) } out: - if (!fixed) + if (!args.fixed) close(p_fd[0]); close(p_fd[1]); close(recv_s0); return 0; err: - if (!fixed) + if (!args.fixed) close(p_fd[0]); close(p_fd[1]); close(recv_s0); @@ -222,7 +244,7 @@ static int test_accept_pending_on_exit(void) ret = io_uring_queue_init(32, &m_io_uring, 0); assert(ret >= 0); - fd = start_accept_listen(NULL, 0); + fd = start_accept_listen(NULL, 0, 0); sqe = io_uring_get_sqe(&m_io_uring); io_uring_prep_accept(sqe, fd, NULL, NULL, 0); @@ -242,7 +264,7 @@ static int test_accept_pending_on_exit(void) /* * Test issue many accepts and see if we handle cancellation on exit */ -static int test_accept_many(unsigned nr, unsigned usecs) +static int test_accept_many(unsigned nr, unsigned usecs, bool nonblock) { struct io_uring m_io_uring; struct io_uring_cqe *cqe; @@ -270,7 +292,8 @@ static int test_accept_many(unsigned nr, unsigned usecs) fds = t_calloc(nr, sizeof(int)); for (i = 0; i < nr; i++) - fds[i] = start_accept_listen(NULL, i); + fds[i] = start_accept_listen(NULL, i, + nonblock ? O_NONBLOCK : 0); for (i = 0; i < nr; i++) { sqe = io_uring_get_sqe(&m_io_uring); @@ -286,12 +309,15 @@ static int test_accept_many(unsigned nr, unsigned usecs) for (i = 0; i < nr; i++) { if (io_uring_peek_cqe(&m_io_uring, &cqe)) break; - if (cqe->res != -ECANCELED) { - fprintf(stderr, "Expected cqe to be cancelled\n"); - goto err; + if (cqe->res != -ECANCELED && + !(cqe->res == -EAGAIN && nonblock)) { + fprintf(stderr, "Expected cqe to be cancelled %d\n", cqe->res); + ret = 1; + goto out; } io_uring_cqe_seen(&m_io_uring, cqe); } + ret = 0; out: rlim.rlim_cur = cur_lim; if (setrlimit(RLIMIT_NPROC, &rlim) < 0) { @@ -301,10 +327,7 @@ out: free(fds); io_uring_queue_exit(&m_io_uring); - return 0; -err: - ret = 1; - goto out; + return ret; } static int test_accept_cancel(unsigned usecs) @@ -317,7 +340,7 @@ static int test_accept_cancel(unsigned usecs) ret = io_uring_queue_init(32, &m_io_uring, 0); assert(ret >= 0); - fd = start_accept_listen(NULL, 0); + fd = start_accept_listen(NULL, 0, 0); sqe = io_uring_get_sqe(&m_io_uring); io_uring_prep_accept(sqe, fd, NULL, NULL, 0); @@ -372,10 +395,27 @@ static int test_accept(void) { struct io_uring m_io_uring; int ret; + struct accept_test_args args = { }; ret = io_uring_queue_init(32, &m_io_uring, 0); assert(ret >= 0); - ret = test(&m_io_uring, 0, false); + ret = test(&m_io_uring, args); + io_uring_queue_exit(&m_io_uring); + return ret; +} + +static int test_accept_nonblock(bool queue_before_connect) +{ + struct io_uring m_io_uring; + int ret; + struct accept_test_args args = { + .nonblock = true, + .queue_accept_before_connect = queue_before_connect + }; + + ret = io_uring_queue_init(32, &m_io_uring, 0); + assert(ret >= 0); + ret = test(&m_io_uring, args); io_uring_queue_exit(&m_io_uring); return ret; } @@ -384,12 +424,15 @@ static int test_accept_fixed(void) { struct io_uring m_io_uring; int ret, fd = -1; + struct accept_test_args args = { + .fixed = true + }; ret = io_uring_queue_init(32, &m_io_uring, 0); assert(ret >= 0); ret = io_uring_register_files(&m_io_uring, &fd, 1); assert(ret == 0); - ret = test(&m_io_uring, 0, true); + ret = test(&m_io_uring, args); io_uring_queue_exit(&m_io_uring); return ret; } @@ -398,7 +441,8 @@ static int test_accept_sqpoll(void) { struct io_uring m_io_uring; struct io_uring_params p = { }; - int ret, should_fail; + int ret; + struct accept_test_args args = { }; p.flags = IORING_SETUP_SQPOLL; ret = t_create_ring_params(32, &m_io_uring, &p); @@ -407,11 +451,11 @@ static int test_accept_sqpoll(void) else if (ret < 0) return ret; - should_fail = 1; + args.accept_should_error = 1; if (p.features & IORING_FEAT_SQPOLL_NONFIXED) - should_fail = 0; + args.accept_should_error = 0; - ret = test(&m_io_uring, should_fail, false); + ret = test(&m_io_uring, args); io_uring_queue_exit(&m_io_uring); return ret; } @@ -431,6 +475,18 @@ int main(int argc, char *argv[]) if (no_accept) return 0; + ret = test_accept_nonblock(false); + if (ret) { + fprintf(stderr, "test_accept_nonblock failed\n"); + return ret; + } + + ret = test_accept_nonblock(true); + if (ret) { + fprintf(stderr, "test_accept_nonblock(queue_before) failed\n"); + return ret; + } + ret = test_accept_fixed(); if (ret) { fprintf(stderr, "test_accept_fixed failed\n"); @@ -455,18 +511,24 @@ int main(int argc, char *argv[]) return ret; } - ret = test_accept_many(128, 0); + ret = test_accept_many(128, 0, false); if (ret) { fprintf(stderr, "test_accept_many failed\n"); return ret; } - ret = test_accept_many(128, 100000); + ret = test_accept_many(128, 100000, false); if (ret) { fprintf(stderr, "test_accept_many failed\n"); return ret; } + ret = test_accept_many(128, 0, true); + if (ret) { + fprintf(stderr, "test_accept_many nonblocking failed\n"); + return ret; + } + ret = test_accept_pending_on_exit(); if (ret) { fprintf(stderr, "test_accept_pending_on_exit failed\n"); -- cgit v1.2.3 From cbdf65e0484af93d3966f0f04eeeb7a5a518d673 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Fri, 25 Mar 2022 02:40:13 -0700 Subject: Add test for multiple concurrent accepts Add tests for accept that queues multiple accepts and then ensures the correct things happen. Check that when connections arrive one at a time that only one CQE is posted (in blocking and nonblocking sockets), as well as make sure that closing the accept socket & cancellation all work as expected. This relies on a kernel with [1] for the tests to pass. [1]: https://lore.kernel.org/io-uring/20220325093755.4123343-1-dylany@fb.com/ Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220325094013.4132496-1-dylany@fb.com Signed-off-by: Jens Axboe --- test/accept.c | 203 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 144 insertions(+), 59 deletions(-) diff --git a/test/accept.c b/test/accept.c index e2c6b51..c591e76 100644 --- a/test/accept.c +++ b/test/accept.c @@ -59,19 +59,24 @@ static void queue_recv(struct io_uring *ring, int fd, bool fixed) sqe->flags |= IOSQE_FIXED_FILE; } -static void queue_accept_conn(struct io_uring *ring, int fd, int fixed_idx) +static void queue_accept_conn(struct io_uring *ring, + int fd, int fixed_idx, + int count) { struct io_uring_sqe *sqe; int ret; - sqe = io_uring_get_sqe(ring); - if (fixed_idx < 0) - io_uring_prep_accept(sqe, fd, NULL, NULL, 0); - else - io_uring_prep_accept_direct(sqe, fd, NULL, NULL, 0, fixed_idx); + while (count--) { + sqe = io_uring_get_sqe(ring); + if (fixed_idx < 0) + io_uring_prep_accept(sqe, fd, NULL, NULL, 0); + else + io_uring_prep_accept_direct(sqe, fd, NULL, NULL, 0, + fixed_idx); - ret = io_uring_submit(ring); - assert(ret != -1); + ret = io_uring_submit(ring); + assert(ret != -1); + } } static int accept_conn(struct io_uring *ring, int fixed_idx) @@ -131,18 +136,19 @@ struct accept_test_args { bool fixed; bool nonblock; bool queue_accept_before_connect; + int extra_loops; }; -static int test(struct io_uring *ring, struct accept_test_args args) + +static int test_loop(struct io_uring *ring, + struct accept_test_args args, + int recv_s0, + struct sockaddr_in *addr) { struct io_uring_cqe *cqe; - struct sockaddr_in addr; uint32_t head, count = 0; int ret, p_fd[2], done = 0; - int32_t val; - int32_t recv_s0 = start_accept_listen(&addr, 0, - args.nonblock ? O_NONBLOCK : 0); p_fd[1] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); @@ -157,10 +163,7 @@ static int test(struct io_uring *ring, struct accept_test_args args) ret = fcntl(p_fd[1], F_SETFL, flags); assert(ret != -1); - if (args.queue_accept_before_connect) - queue_accept_conn(ring, recv_s0, args.fixed ? 0 : -1); - - ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr)); + ret = connect(p_fd[1], (struct sockaddr *)addr, sizeof(*addr)); assert(ret == -1); flags = fcntl(p_fd[1], F_GETFL, 0); @@ -171,7 +174,7 @@ static int test(struct io_uring *ring, struct accept_test_args args) assert(ret != -1); if (!args.queue_accept_before_connect) - queue_accept_conn(ring, recv_s0, args.fixed ? 0 : -1); + queue_accept_conn(ring, recv_s0, args.fixed ? 0 : -1, 1); p_fd[0] = accept_conn(ring, args.fixed ? 0 : -1); if (p_fd[0] == -EINVAL) { @@ -219,16 +222,34 @@ out: if (!args.fixed) close(p_fd[0]); close(p_fd[1]); - close(recv_s0); return 0; err: if (!args.fixed) close(p_fd[0]); close(p_fd[1]); - close(recv_s0); return 1; } +static int test(struct io_uring *ring, struct accept_test_args args) +{ + struct sockaddr_in addr; + int ret = 0; + int loop; + int32_t recv_s0 = start_accept_listen(&addr, 0, + args.nonblock ? O_NONBLOCK : 0); + if (args.queue_accept_before_connect) + queue_accept_conn(ring, recv_s0, args.fixed ? 0 : -1, + 1 + args.extra_loops); + for (loop = 0; loop < 1 + args.extra_loops; loop++) { + ret = test_loop(ring, args, recv_s0, &addr); + if (ret) + break; + } + + close(recv_s0); + return ret; +} + static void sig_alrm(int sig) { exit(0); @@ -261,10 +282,17 @@ static int test_accept_pending_on_exit(void) return 0; } +struct test_accept_many_args { + unsigned int usecs; + bool nonblock; + bool single_sock; + bool close_fds; +}; + /* * Test issue many accepts and see if we handle cancellation on exit */ -static int test_accept_many(unsigned nr, unsigned usecs, bool nonblock) +static int test_accept_many(struct test_accept_many_args args) { struct io_uring m_io_uring; struct io_uring_cqe *cqe; @@ -272,6 +300,8 @@ static int test_accept_many(unsigned nr, unsigned usecs, bool nonblock) unsigned long cur_lim; struct rlimit rlim; int *fds, i, ret; + unsigned int nr = 128; + int nr_socks = args.single_sock ? 1 : nr; if (getrlimit(RLIMIT_NPROC, &rlim) < 0) { perror("getrlimit"); @@ -289,28 +319,32 @@ static int test_accept_many(unsigned nr, unsigned usecs, bool nonblock) ret = io_uring_queue_init(2 * nr, &m_io_uring, 0); assert(ret >= 0); - fds = t_calloc(nr, sizeof(int)); + fds = t_calloc(nr_socks, sizeof(int)); - for (i = 0; i < nr; i++) + for (i = 0; i < nr_socks; i++) fds[i] = start_accept_listen(NULL, i, - nonblock ? O_NONBLOCK : 0); + args.nonblock ? O_NONBLOCK : 0); for (i = 0; i < nr; i++) { + int sock_idx = args.single_sock ? 0 : i; sqe = io_uring_get_sqe(&m_io_uring); - io_uring_prep_accept(sqe, fds[i], NULL, NULL, 0); + io_uring_prep_accept(sqe, fds[sock_idx], NULL, NULL, 0); sqe->user_data = 1 + i; ret = io_uring_submit(&m_io_uring); assert(ret == 1); } - if (usecs) - usleep(usecs); + if (args.usecs) + usleep(args.usecs); + + if (args.close_fds) + for (i = 0; i < nr_socks; i++) + close(fds[i]); for (i = 0; i < nr; i++) { if (io_uring_peek_cqe(&m_io_uring, &cqe)) break; - if (cqe->res != -ECANCELED && - !(cqe->res == -EAGAIN && nonblock)) { + if (cqe->res != -ECANCELED) { fprintf(stderr, "Expected cqe to be cancelled %d\n", cqe->res); ret = 1; goto out; @@ -330,7 +364,7 @@ out: return ret; } -static int test_accept_cancel(unsigned usecs) +static int test_accept_cancel(unsigned usecs, unsigned int nr) { struct io_uring m_io_uring; struct io_uring_cqe *cqe; @@ -342,22 +376,25 @@ static int test_accept_cancel(unsigned usecs) fd = start_accept_listen(NULL, 0, 0); - sqe = io_uring_get_sqe(&m_io_uring); - io_uring_prep_accept(sqe, fd, NULL, NULL, 0); - sqe->user_data = 1; - ret = io_uring_submit(&m_io_uring); - assert(ret == 1); + for (i = 1; i <= nr; i++) { + sqe = io_uring_get_sqe(&m_io_uring); + io_uring_prep_accept(sqe, fd, NULL, NULL, 0); + sqe->user_data = i; + ret = io_uring_submit(&m_io_uring); + assert(ret == 1); + } if (usecs) usleep(usecs); - sqe = io_uring_get_sqe(&m_io_uring); - io_uring_prep_cancel(sqe, 1, 0); - sqe->user_data = 2; - ret = io_uring_submit(&m_io_uring); - assert(ret == 1); - - for (i = 0; i < 2; i++) { + for (i = 1; i <= nr; i++) { + sqe = io_uring_get_sqe(&m_io_uring); + io_uring_prep_cancel(sqe, i, 0); + sqe->user_data = nr + i; + ret = io_uring_submit(&m_io_uring); + assert(ret == 1); + } + for (i = 0; i < nr * 2; i++) { ret = io_uring_wait_cqe(&m_io_uring, &cqe); assert(!ret); /* @@ -370,12 +407,15 @@ static int test_accept_cancel(unsigned usecs) * should get '-EALREADY' for the cancel request and * '-EINTR' for the accept request. */ - if (cqe->user_data == 1) { + if (cqe->user_data == 0) { + fprintf(stderr, "unexpected 0 user data\n"); + goto err; + } else if (cqe->user_data <= nr) { if (cqe->res != -EINTR && cqe->res != -ECANCELED) { fprintf(stderr, "Cancelled accept got %d\n", cqe->res); goto err; } - } else if (cqe->user_data == 2) { + } else if (cqe->user_data <= nr * 2) { if (cqe->res != -EALREADY && cqe->res != 0) { fprintf(stderr, "Cancel got %d\n", cqe->res); goto err; @@ -391,11 +431,14 @@ err: return 1; } -static int test_accept(void) +static int test_accept(int count, bool before) { struct io_uring m_io_uring; int ret; - struct accept_test_args args = { }; + struct accept_test_args args = { + .queue_accept_before_connect = before, + .extra_loops = count - 1 + }; ret = io_uring_queue_init(32, &m_io_uring, 0); assert(ret >= 0); @@ -404,13 +447,14 @@ static int test_accept(void) return ret; } -static int test_accept_nonblock(bool queue_before_connect) +static int test_accept_nonblock(bool queue_before_connect, int count) { struct io_uring m_io_uring; int ret; struct accept_test_args args = { .nonblock = true, - .queue_accept_before_connect = queue_before_connect + .queue_accept_before_connect = queue_before_connect, + .extra_loops = count - 1 }; ret = io_uring_queue_init(32, &m_io_uring, 0); @@ -467,7 +511,7 @@ int main(int argc, char *argv[]) if (argc > 1) return 0; - ret = test_accept(); + ret = test_accept(1, false); if (ret) { fprintf(stderr, "test_accept failed\n"); return ret; @@ -475,15 +519,33 @@ int main(int argc, char *argv[]) if (no_accept) return 0; - ret = test_accept_nonblock(false); + ret = test_accept(2, false); + if (ret) { + fprintf(stderr, "test_accept(2) failed\n"); + return ret; + } + + ret = test_accept(2, true); + if (ret) { + fprintf(stderr, "test_accept(2, true) failed\n"); + return ret; + } + + ret = test_accept_nonblock(false, 1); if (ret) { fprintf(stderr, "test_accept_nonblock failed\n"); return ret; } - ret = test_accept_nonblock(true); + ret = test_accept_nonblock(true, 1); + if (ret) { + fprintf(stderr, "test_accept_nonblock(before, 1) failed\n"); + return ret; + } + + ret = test_accept_nonblock(true, 3); if (ret) { - fprintf(stderr, "test_accept_nonblock(queue_before) failed\n"); + fprintf(stderr, "test_accept_nonblock(before,3) failed\n"); return ret; } @@ -499,33 +561,56 @@ int main(int argc, char *argv[]) return ret; } - ret = test_accept_cancel(0); + ret = test_accept_cancel(0, 1); if (ret) { fprintf(stderr, "test_accept_cancel nodelay failed\n"); return ret; } - ret = test_accept_cancel(10000); + ret = test_accept_cancel(10000, 1); if (ret) { fprintf(stderr, "test_accept_cancel delay failed\n"); return ret; } - ret = test_accept_many(128, 0, false); + ret = test_accept_cancel(0, 4); if (ret) { - fprintf(stderr, "test_accept_many failed\n"); + fprintf(stderr, "test_accept_cancel nodelay failed\n"); + return ret; + } + + ret = test_accept_cancel(10000, 4); + if (ret) { + fprintf(stderr, "test_accept_cancel delay failed\n"); return ret; } - ret = test_accept_many(128, 100000, false); + ret = test_accept_many((struct test_accept_many_args) {}); if (ret) { fprintf(stderr, "test_accept_many failed\n"); return ret; } - ret = test_accept_many(128, 0, true); + ret = test_accept_many((struct test_accept_many_args) { + .usecs = 100000 }); + if (ret) { + fprintf(stderr, "test_accept_many(sleep) failed\n"); + return ret; + } + + ret = test_accept_many((struct test_accept_many_args) { + .nonblock = true }); + if (ret) { + fprintf(stderr, "test_accept_many(nonblock) failed\n"); + return ret; + } + + ret = test_accept_many((struct test_accept_many_args) { + .nonblock = true, + .single_sock = true, + .close_fds = true }); if (ret) { - fprintf(stderr, "test_accept_many nonblocking failed\n"); + fprintf(stderr, "test_accept_many(nonblock,close) failed\n"); return ret; } -- cgit v1.2.3 From a339505f1dd3ea0d2626abdcfd44d6ddd56b41e3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 29 Mar 2022 06:37:04 -0600 Subject: man/io_uring_prep_cancel.3: add io_uring_prep_poll_remove(3) to see also Signed-off-by: Jens Axboe --- man/io_uring_prep_cancel.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index ddf5a89..4c6fc28 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -57,4 +57,4 @@ is no longer possible. This should normally mean that it will complete shortly, either successfully, or interrupted due to the cancelation. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3) +.BR io_uring_prep_poll_remove (3), io_uring_get_sqe (3), io_uring_submit (3) -- cgit v1.2.3 From 499b55f07f84a1e4282676a9cbf6f12dd4ce4b51 Mon Sep 17 00:00:00 2001 From: Dmitry Rozhkov Date: Tue, 29 Mar 2022 16:30:06 +0300 Subject: Add SECURITY.md Define an initial security policy in the file SECURITY.md. The content of the file will become the content of the page https://github.com/axboe/liburing/security/policy. Fixes: https://github.com/axboe/liburing/issues/534 Signed-off-by: Dmitry Rozhkov --- SECURITY.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..c9c2ffe --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,6 @@ +# Security Policy + +## Reporting a Vulnerability + +Please report any security issue to axboe@kernel.dk where the issue will be triaged appropriately. +Thank you in advance for helping to keep liburing secure. -- cgit v1.2.3 From bc35807c2fc8b900930c6bfe3b77e49fb2b051f0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 29 Mar 2022 16:16:44 -0600 Subject: test/open-direct-link: add test case for linked open+read+close Test that it works with both LINK and DRAIN. Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 1 + test/open-direct-link.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 test/open-direct-link.c diff --git a/.gitignore b/.gitignore index 36f8ead..6cd5878 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,7 @@ /test/nop /test/nop-all-sizes /test/open-close +/test/open-direct-link /test/openat2 /test/personality /test/pipe-eof diff --git a/test/Makefile b/test/Makefile index f1accbf..8570748 100644 --- a/test/Makefile +++ b/test/Makefile @@ -101,6 +101,7 @@ test_srcs := \ nop.c \ openat2.c \ open-close.c \ + open-direct-link.c \ personality.c \ pipe-eof.c \ pipe-reuse.c \ diff --git a/test/open-direct-link.c b/test/open-direct-link.c new file mode 100644 index 0000000..44f7297 --- /dev/null +++ b/test/open-direct-link.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: link + * + */ +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define MAX_FILES 8 +#define FNAME ".link.direct" + +static int test(struct io_uring *ring, int skip_success, int drain) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + char buf[4096]; + int ret, i; + + /* drain and cqe skip are mutually exclusive */ + if (skip_success && drain) + return 1; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_openat_direct(sqe, AT_FDCWD, FNAME, O_RDONLY, 0, 0); + if (!drain) + sqe->flags |= IOSQE_IO_LINK; + if (skip_success) + sqe->flags |= IOSQE_CQE_SKIP_SUCCESS; + sqe->user_data = 1; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_read(sqe, 0, buf, sizeof(buf), 0); + sqe->flags |= IOSQE_FIXED_FILE; + if (drain) + sqe->flags |= IOSQE_IO_DRAIN; + else + sqe->flags |= IOSQE_IO_LINK; + sqe->user_data = 2; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_close_direct(sqe, 0); + sqe->user_data = 3; + if (skip_success) + sqe->flags |= IOSQE_CQE_SKIP_SUCCESS; + if (drain) + sqe->flags |= IOSQE_IO_DRAIN; + + ret = io_uring_submit(ring); + if (ret != 3) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + if (skip_success) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + if (cqe->user_data != 2) { + fprintf(stderr, "Unexpected cqe %lu/%d\n", + (unsigned long) cqe->user_data, + cqe->res); + goto err; + } + if (cqe->res != sizeof(buf)) { + fprintf(stderr, "bad read %d\n", cqe->res); + goto err; + } + io_uring_cqe_seen(ring, cqe); + return 0; + } + + for (i = 0; i < 3; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + switch (cqe->user_data) { + case 1: + if (cqe->res) { + fprintf(stderr, "bad open %d\n", cqe->res); + goto err; + } + break; + case 2: + if (cqe->res != sizeof(buf)) { + fprintf(stderr, "bad read %d\n", cqe->res); + goto err; + } + break; + case 3: + if (cqe->res) { + fprintf(stderr, "bad close %d\n", cqe->res); + goto err; + } + break; + } + io_uring_cqe_seen(ring, cqe); + } + + return 0; +err: + return 1; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + int ret, files[MAX_FILES]; + + if (argc > 1) + return 0; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + memset(files, -1, sizeof(files)); + ret = io_uring_register_files(&ring, files, ARRAY_SIZE(files)); + if (ret) { + fprintf(stderr, "Failed registering files\n"); + return 1; + } + + t_create_file(FNAME, 4096); + + ret = test(&ring, 0, 0); + if (ret) { + fprintf(stderr, "test 0 0 failed\n"); + goto err; + } + + ret = test(&ring, 0, 1); + if (ret) { + fprintf(stderr, "test 0 1 failed\n"); + goto err; + } + + ret = test(&ring, 1, 0); + if (ret) { + fprintf(stderr, "test 1 0 failed\n"); + goto err; + } + + unlink(FNAME); + return 0; +err: + unlink(FNAME); + return 1; +} -- cgit v1.2.3 From cd63b85f857d87a3e4699b6ee5cc43b5dfb8682e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 29 Mar 2022 16:28:47 -0600 Subject: test/open-direct-link: don't test if CQE_SKIP isn't available This just limits us to a newer kernel, and we use SKIP in testing it anyway. Signed-off-by: Jens Axboe --- test/open-direct-link.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/open-direct-link.c b/test/open-direct-link.c index 44f7297..98a9cc0 100644 --- a/test/open-direct-link.c +++ b/test/open-direct-link.c @@ -115,16 +115,19 @@ err: int main(int argc, char *argv[]) { struct io_uring ring; + struct io_uring_params p = { }; int ret, files[MAX_FILES]; if (argc > 1) return 0; - ret = io_uring_queue_init(8, &ring, 0); + ret = io_uring_queue_init_params(8, &ring, &p); if (ret) { fprintf(stderr, "ring setup failed: %d\n", ret); return 1; } + if (!(p.features & IORING_FEAT_CQE_SKIP)) + return 0; memset(files, -1, sizeof(files)); ret = io_uring_register_files(&ring, files, ARRAY_SIZE(files)); -- cgit v1.2.3 From 000dd873f4da9b6052792c93d4d0978bb4ea3252 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 29 Mar 2022 16:38:27 -0600 Subject: test/open-direct-link: add IOSQE_ASYNC Signed-off-by: Jens Axboe --- test/open-direct-link.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/test/open-direct-link.c b/test/open-direct-link.c index 98a9cc0..33f88f4 100644 --- a/test/open-direct-link.c +++ b/test/open-direct-link.c @@ -16,7 +16,7 @@ #define MAX_FILES 8 #define FNAME ".link.direct" -static int test(struct io_uring *ring, int skip_success, int drain) +static int test(struct io_uring *ring, int skip_success, int drain, int async) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -33,6 +33,8 @@ static int test(struct io_uring *ring, int skip_success, int drain) sqe->flags |= IOSQE_IO_LINK; if (skip_success) sqe->flags |= IOSQE_CQE_SKIP_SUCCESS; + if (async) + sqe->flags |= IOSQE_ASYNC; sqe->user_data = 1; sqe = io_uring_get_sqe(ring); @@ -42,6 +44,8 @@ static int test(struct io_uring *ring, int skip_success, int drain) sqe->flags |= IOSQE_IO_DRAIN; else sqe->flags |= IOSQE_IO_LINK; + if (async) + sqe->flags |= IOSQE_ASYNC; sqe->user_data = 2; sqe = io_uring_get_sqe(ring); @@ -51,6 +55,8 @@ static int test(struct io_uring *ring, int skip_success, int drain) sqe->flags |= IOSQE_CQE_SKIP_SUCCESS; if (drain) sqe->flags |= IOSQE_IO_DRAIN; + if (async) + sqe->flags |= IOSQE_ASYNC; ret = io_uring_submit(ring); if (ret != 3) { @@ -138,21 +144,39 @@ int main(int argc, char *argv[]) t_create_file(FNAME, 4096); - ret = test(&ring, 0, 0); + ret = test(&ring, 0, 0, 0); if (ret) { - fprintf(stderr, "test 0 0 failed\n"); + fprintf(stderr, "test 0 0 0 failed\n"); goto err; } - ret = test(&ring, 0, 1); + ret = test(&ring, 0, 1, 0); if (ret) { - fprintf(stderr, "test 0 1 failed\n"); + fprintf(stderr, "test 0 1 0 failed\n"); goto err; } - ret = test(&ring, 1, 0); + ret = test(&ring, 0, 0, 1); if (ret) { - fprintf(stderr, "test 1 0 failed\n"); + fprintf(stderr, "test 0 0 1 failed\n"); + goto err; + } + + ret = test(&ring, 0, 1, 1); + if (ret) { + fprintf(stderr, "test 0 1 1 failed\n"); + goto err; + } + + ret = test(&ring, 1, 0, 0); + if (ret) { + fprintf(stderr, "test 1 0 0 failed\n"); + goto err; + } + + ret = test(&ring, 1, 0, 1); + if (ret) { + fprintf(stderr, "test 1 0 1 failed\n"); goto err; } -- cgit v1.2.3 From 015be594f11dd8e86e5ade4e7c5426bbea70a56e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 29 Mar 2022 17:16:11 -0600 Subject: man/io_uring.7: line breaks Signed-off-by: Jens Axboe --- man/io_uring.7 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/man/io_uring.7 b/man/io_uring.7 index 0a47831..39865e6 100644 --- a/man/io_uring.7 +++ b/man/io_uring.7 @@ -551,8 +551,8 @@ int io_uring_setup(unsigned entries, struct io_uring_params *p) int io_uring_enter(int ring_fd, unsigned int to_submit, unsigned int min_complete, unsigned int flags) { - return (int) syscall(__NR_io_uring_enter, ring_fd, to_submit, min_complete, - flags, NULL, 0); + return (int) syscall(__NR_io_uring_enter, ring_fd, to_submit, + min_complete, flags, NULL, 0); } int app_setup_uring(void) { @@ -696,10 +696,10 @@ int submit_to_sq(int fd, int op) { io_uring_smp_store_release(sring_tail, tail); /* - * Tell the kernel we have submitted events with the io_uring_enter() system - * call. We also pass in the IOURING_ENTER_GETEVENTS flag which causes the - * io_uring_enter() call to wait until min_complete (the 3rd param) events - * complete. + * Tell the kernel we have submitted events with the io_uring_enter() + * system call. We also pass in the IOURING_ENTER_GETEVENTS flag which + * causes the io_uring_enter() call to wait until min_complete + * (the 3rd param) events complete. * */ int ret = io_uring_enter(ring_fd, 1,1, IORING_ENTER_GETEVENTS); -- cgit v1.2.3 From bf26378a632b983f23a1fc1d78506be0d67239e2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2022 11:09:40 -0600 Subject: test/drop-submit: set invalid ioprio to force request to be dropped We need it dropped at prep time, don't assume that read prep will validate the fd. Signed-off-by: Jens Axboe --- test/drop-submit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/drop-submit.c b/test/drop-submit.c index 72e44d9..7b15f26 100644 --- a/test/drop-submit.c +++ b/test/drop-submit.c @@ -35,6 +35,7 @@ static int test(struct io_uring *ring, int expect_drops) } io_uring_prep_read(sqe, 128, buf, sizeof(buf), 0); + sqe->ioprio = (short) -1; } -- cgit v1.2.3 From 0d44d59d3863f396a68d55d71e5636cafe485470 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2022 11:10:41 -0600 Subject: test/submit-link-fail: set invalid ioprio to force request to be dropped We need it dropped at prep time, don't assume that read prep will validate the fd. Signed-off-by: Jens Axboe --- test/submit-link-fail.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/submit-link-fail.c b/test/submit-link-fail.c index a12bdae..45f6976 100644 --- a/test/submit-link-fail.c +++ b/test/submit-link-fail.c @@ -56,10 +56,12 @@ static int test_underprep_fail(bool hardlink, bool drain, bool link_last, for (i = 0; i < link_size; i++) { sqe = io_uring_get_sqe(&ring); - if (i == fail_idx) + if (i == fail_idx) { io_uring_prep_read(sqe, invalid_fd, buffer, 1, 0); - else + sqe->ioprio = (short) -1; + } else { io_uring_prep_nop(sqe); + } if (i != link_size - 1 || !link_last) sqe->flags |= link_flags; -- cgit v1.2.3 From 1c90b19aa381588dc4f53047a950fda2ddf5feeb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2022 11:33:23 -0600 Subject: helpers: add file creation with pattern Signed-off-by: Jens Axboe --- test/helpers.c | 14 ++++++++++++-- test/helpers.h | 6 ++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/test/helpers.c b/test/helpers.c index 975e7cb..491822e 100644 --- a/test/helpers.c +++ b/test/helpers.c @@ -49,14 +49,14 @@ void *t_calloc(size_t nmemb, size_t size) /* * Helper for creating file and write @size byte buf with 0xaa value in the file. */ -void t_create_file(const char *file, size_t size) +static void __t_create_file(const char *file, size_t size, char pattern) { ssize_t ret; char *buf; int fd; buf = t_malloc(size); - memset(buf, 0xaa, size); + memset(buf, pattern, size); fd = open(file, O_WRONLY | O_CREAT, 0644); assert(fd >= 0); @@ -68,6 +68,16 @@ void t_create_file(const char *file, size_t size) assert(ret == size); } +void t_create_file(const char *file, size_t size) +{ + __t_create_file(file, size, 0xaa); +} + +void t_create_file_pattern(const char *file, size_t size, char pattern) +{ + __t_create_file(file, size, pattern); +} + /* * Helper for creating @buf_num number of iovec * with @buf_size bytes buffer of each iovec. diff --git a/test/helpers.h b/test/helpers.h index 7526d46..d0beb93 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -40,6 +40,12 @@ void *t_calloc(size_t nmemb, size_t size); */ void t_create_file(const char *file, size_t size); +/* + * Helper for creating file and write @size byte buf with @pattern value in + * the file. + */ +void t_create_file_pattern(const char *file, size_t size, char pattern); + /* * Helper for creating @buf_num number of iovec * with @buf_size bytes buffer of each iovec. -- cgit v1.2.3 From 3b52ae980c41b420592e3005199041890a56d6dc Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2022 11:33:38 -0600 Subject: test/fixed-reuse: test that linked file slot reuse is correct If we do: this should be consistent with not having opened fileX first, and the read should be satisfied from fileY. Signed-off-by: Jens Axboe --- .gitignore | 1 + test/Makefile | 1 + test/fixed-reuse.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 test/fixed-reuse.c diff --git a/.gitignore b/.gitignore index 6cd5878..4a6e585 100644 --- a/.gitignore +++ b/.gitignore @@ -63,6 +63,7 @@ /test/files-exit-hang-timeout /test/fixed-buf-iter /test/fixed-link +/test/fixed-reuse /test/fpos /test/fsync /test/hardlink diff --git a/test/Makefile b/test/Makefile index 8570748..1526776 100644 --- a/test/Makefile +++ b/test/Makefile @@ -80,6 +80,7 @@ test_srcs := \ file-verify.c \ fixed-buf-iter.c \ fixed-link.c \ + fixed-reuse.c \ fpos.c \ fsync.c \ hardlink.c \ diff --git a/test/fixed-reuse.c b/test/fixed-reuse.c new file mode 100644 index 0000000..4cd8e37 --- /dev/null +++ b/test/fixed-reuse.c @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: link with an existing + * file present in the opened slot, verifying that we get the new file + * rather than the old one. + * + */ +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define MAX_FILES 8 +#define FNAME1 ".slot.reuse.1" +#define FNAME2 ".slot.reuse.2" +#define PAT1 0xaa +#define PAT2 0x55 +#define BSIZE 4096 + +static int test(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + char buf[BSIZE]; + int ret, i; + + /* open FNAME1 in slot 0 */ + sqe = io_uring_get_sqe(ring); + io_uring_prep_openat_direct(sqe, AT_FDCWD, FNAME1, O_RDONLY, 0, 0); + sqe->user_data = 1; + + ret = io_uring_submit(ring); + if (ret != 1) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + if (cqe->res != 0) { + fprintf(stderr, "open res %d\n", ret); + goto err; + } + io_uring_cqe_seen(ring, cqe); + + /* + * Now open FNAME2 in that same slot, verifying we get data from + * FNAME2 and not FNAME1. + */ + sqe = io_uring_get_sqe(ring); + io_uring_prep_openat_direct(sqe, AT_FDCWD, FNAME2, O_RDONLY, 0, 0); + sqe->flags |= IOSQE_IO_LINK; + sqe->user_data = 2; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_read(sqe, 0, buf, sizeof(buf), 0); + sqe->flags |= IOSQE_FIXED_FILE; + sqe->flags |= IOSQE_IO_LINK; + sqe->user_data = 3; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_close_direct(sqe, 0); + sqe->user_data = 4; + + ret = io_uring_submit(ring); + if (ret != 3) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + for (i = 0; i < 3; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + switch (cqe->user_data) { + case 2: + if (cqe->res) { + fprintf(stderr, "bad open %d\n", cqe->res); + goto err; + } + break; + case 3: + if (cqe->res != sizeof(buf)) { + fprintf(stderr, "bad read %d\n", cqe->res); + goto err; + } + break; + case 4: + if (cqe->res) { + fprintf(stderr, "bad close %d\n", cqe->res); + goto err; + } + break; + } + io_uring_cqe_seen(ring, cqe); + } + + for (i = 0; i < sizeof(buf); i++) { + if (buf[i] == PAT2) + continue; + fprintf(stderr, "Bad pattern %x at %d\n", buf[i], i); + goto err; + } + + return 0; +err: + return 1; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + struct io_uring_params p = { }; + int ret, files[MAX_FILES]; + + if (argc > 1) + return 0; + + ret = io_uring_queue_init_params(8, &ring, &p); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + if (!(p.features & IORING_FEAT_CQE_SKIP)) + return 0; + + memset(files, -1, sizeof(files)); + ret = io_uring_register_files(&ring, files, ARRAY_SIZE(files)); + if (ret) { + fprintf(stderr, "Failed registering files\n"); + return 1; + } + + t_create_file_pattern(FNAME1, 4096, PAT1); + t_create_file_pattern(FNAME2, 4096, PAT2); + + ret = test(&ring); + if (ret) { + fprintf(stderr, "test failed\n"); + goto err; + } + + unlink(FNAME1); + unlink(FNAME2); + return 0; +err: + unlink(FNAME1); + unlink(FNAME2); + return 1; +} -- cgit v1.2.3 From 8b20997546d884f9a1cc37ec463b225fd18e57e3 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Wed, 23 Mar 2022 08:44:54 -0700 Subject: liburing: Update io_uring in liburing Summary: Update liburing with the kernel changes in io_uring. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220323154457.3303391-2-shr@fb.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 3 ++- src/include/liburing/io_uring.h | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 5c03061..949a351 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -293,7 +293,8 @@ static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd, sqe->buf_index = 0; sqe->personality = 0; sqe->file_index = 0; - sqe->__pad2[0] = sqe->__pad2[1] = 0; + sqe->addr3 = 0; + sqe->__pad2[0] = 0; } /** diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index d858977..da1d31f 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -49,6 +49,7 @@ struct io_uring_sqe { __u32 rename_flags; __u32 unlink_flags; __u32 hardlink_flags; + __u32 xattr_flags; }; __u64 user_data; /* data to be passed back at completion time */ /* pack this to avoid bogus arm OABI complaints */ @@ -64,7 +65,8 @@ struct io_uring_sqe { __s32 splice_fd_in; __u32 file_index; }; - __u64 __pad2[2]; + __u64 addr3; + __u64 __pad2[1]; }; enum { @@ -149,6 +151,10 @@ enum { IORING_OP_SYMLINKAT, IORING_OP_LINKAT, IORING_OP_MSG_RING, + IORING_OP_FSETXATTR, + IORING_OP_SETXATTR, + IORING_OP_FGETXATTR, + IORING_OP_GETXATTR, /* this goes last, obviously */ IORING_OP_LAST, @@ -393,7 +399,7 @@ struct io_uring_probe { __u8 ops_len; /* length of ops[] array below */ __u16 resv; __u32 resv2[3]; - struct io_uring_probe_op ops[]; + struct io_uring_probe_op ops[0]; }; struct io_uring_restriction { -- cgit v1.2.3 From 72f55e271377eb2000fd4dc4991ce944440b551c Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Wed, 23 Mar 2022 08:44:55 -0700 Subject: liburing: add helper functions for setxattr and fsetxattr Summary: This adds the helper functions for: - fsetxattr - setxattr Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220323154457.3303391-3-shr@fb.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 949a351..0b5dfab 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -729,6 +729,29 @@ static inline void io_uring_prep_msg_ring(struct io_uring_sqe *sqe, int fd, sqe->rw_flags = flags; } +static inline void io_uring_prep_setxattr(struct io_uring_sqe *sqe, + const char *name, + const char *value, + const char *path, + int flags, + size_t len) +{ + io_uring_prep_rw(IORING_OP_SETXATTR, sqe, 0, name, len, (__u64) value); + sqe->addr3 = (__u64) path; + sqe->xattr_flags = flags; +} + +static inline void io_uring_prep_fsetxattr(struct io_uring_sqe *sqe, + int fd, + const char *name, + const char *value, + int flags, + size_t len) +{ + io_uring_prep_rw(IORING_OP_FSETXATTR, sqe, fd, name, len, (__u64) value); + sqe->xattr_flags = flags; +} + /* * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in * the SQ ring -- cgit v1.2.3 From 73849e908ce0ca8b85e3c890e88d070732d70b4f Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Wed, 23 Mar 2022 08:44:56 -0700 Subject: liburing: Add helper functions for fgetxattr and getxattr Summary: This adds the helper functions for: - fgetxattr - getxattr Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220323154457.3303391-4-shr@fb.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 0b5dfab..105f5dc 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -729,6 +729,17 @@ static inline void io_uring_prep_msg_ring(struct io_uring_sqe *sqe, int fd, sqe->rw_flags = flags; } +static inline void io_uring_prep_getxattr(struct io_uring_sqe *sqe, + const char *name, + const char *value, + const char *path, + size_t len) +{ + io_uring_prep_rw(IORING_OP_GETXATTR, sqe, 0, name, len, (__u64) value); + sqe->addr3 = (__u64) path; + sqe->xattr_flags = 0; +} + static inline void io_uring_prep_setxattr(struct io_uring_sqe *sqe, const char *name, const char *value, @@ -741,6 +752,16 @@ static inline void io_uring_prep_setxattr(struct io_uring_sqe *sqe, sqe->xattr_flags = flags; } +static inline void io_uring_prep_fgetxattr(struct io_uring_sqe *sqe, + int fd, + const char *name, + const char *value, + size_t len) +{ + io_uring_prep_rw(IORING_OP_FGETXATTR, sqe, fd, name, len, (__u64) value); + sqe->xattr_flags = 0; +} + static inline void io_uring_prep_fsetxattr(struct io_uring_sqe *sqe, int fd, const char *name, -- cgit v1.2.3 From d6515e06f73ce6fc9810a74fccca4959ce49f819 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Wed, 23 Mar 2022 08:44:57 -0700 Subject: liburing: Add new test program to verify xattr support Summary: This adds a new test program to test the xattr support: - fgetxattr - fsetxattr - getxattr - setxattr It also includes test cases for failure conditions and for passing in an invalid sqe. The test case for checking of invalid SQE, must be enabled by defining DESTRUCTIVE_TESTING. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220323154457.3303391-5-shr@fb.com Signed-off-by: Jens Axboe --- test/Makefile | 1 + test/xattr.c | 425 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 426 insertions(+) create mode 100644 test/xattr.c diff --git a/test/Makefile b/test/Makefile index 1526776..c32b9bb 100644 --- a/test/Makefile +++ b/test/Makefile @@ -159,6 +159,7 @@ test_srcs := \ tty-write-dpoll.c \ unlink.c \ wakeup-hang.c \ + xattr.c \ skip-cqe.c \ # EOL diff --git a/test/xattr.c b/test/xattr.c new file mode 100644 index 0000000..017017e --- /dev/null +++ b/test/xattr.c @@ -0,0 +1,425 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "liburing.h" + +/* Define constants. */ +#define XATTR_SIZE 255 +#define QUEUE_DEPTH 32 + +#define FILENAME "xattr.test" +#define KEY1 "user.val1" +#define KEY2 "user.val2" +#define VALUE1 "value1" +#define VALUE2 "value2-a-lot-longer" + + +/* Call fsetxattr. */ +int io_uring_fsetxattr(struct io_uring *ring, + int fd, + const char *name, + const void *value, + size_t size, + int flags) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + int ret; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "Error cannot get sqe\n"); + return -1; + } + + io_uring_prep_fsetxattr(sqe, fd, name, value, flags, size); + + ret = io_uring_submit(ring); + if (ret != 1) { + fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret); + return -1; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret); + return -1; + } + + ret = cqe->res; + io_uring_cqe_seen(ring, cqe); + + return ret; +} + +/* Submit fgetxattr request. */ +int io_uring_fgetxattr(struct io_uring *ring, + int fd, + const char *name, + void *value, + size_t size) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + int ret; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "Error cannot get sqe\n"); + return -1; + } + + io_uring_prep_fgetxattr(sqe, fd, name, value, size); + + ret = io_uring_submit(ring); + if (ret != 1) { + fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret); + return -1; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret); + return -1; + } + + ret = cqe->res; + if (ret == -1) { + fprintf(stderr, "Error couldn'tget value\n"); + return -1; + } + + io_uring_cqe_seen(ring, cqe); + return ret; +} + +/* Call setxattr. */ +int io_uring_setxattr(struct io_uring *ring, + const char *path, + const char *name, + const void *value, + size_t size, + int flags) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + int ret; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "Error cannot get sqe\n"); + return -1; + } + + io_uring_prep_setxattr(sqe, name, value, path, flags, size); + + ret = io_uring_submit_and_wait(ring, 1); + if (ret != 1) { + fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret); + return -1; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret); + return -1; + } + + ret = cqe->res; + io_uring_cqe_seen(ring, cqe); + + return ret; +} + +/* Submit getxattr request. */ +int io_uring_getxattr(struct io_uring *ring, + const char *path, + const char *name, + void *value, + size_t size) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + int ret; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "Error cannot get sqe\n"); + return -1; + } + + io_uring_prep_getxattr(sqe, name, value, path, size); + + ret = io_uring_submit(ring); + if (ret != 1) { + fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret); + return -1; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret); + return -1; + } + + ret = cqe->res; + if (ret == -1) { + fprintf(stderr, "Error couldn'tget value\n"); + return -1; + } + + io_uring_cqe_seen(ring, cqe); + return ret; +} + +/* Test driver for fsetxattr and fgetxattr. */ +int test_fxattr(void) +{ + int rc = 0; + size_t value_len; + struct io_uring ring; + char value[XATTR_SIZE]; + + /* Init io-uring queue. */ + int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0); + if (ret) { + fprintf(stderr, "child: ring setup failed: %d\n", ret); + return -1; + } + + /* Create the test file. */ + int fd = open(FILENAME, O_CREAT | O_RDWR); + if (fd < 0) { + fprintf(stderr, "Error: cannot open file: ret=%d\n", fd); + return -1; + } + + /* Test writing attributes. */ + if (io_uring_fsetxattr(&ring, fd, KEY1, VALUE1, strlen(VALUE1), 0) == -1) { + fprintf(stderr, "Error fsetxattr cannot write key1\n"); + rc = -1; + goto Exit; + } + + if (io_uring_fsetxattr(&ring, fd, KEY2, VALUE2, strlen(VALUE2), 0) == -1) { + fprintf(stderr, "Error fsetxattr cannot write key1\n"); + rc = -1; + goto Exit; + } + + /* Test reading attributes. */ + value_len = io_uring_fgetxattr(&ring, fd, KEY1, value, XATTR_SIZE); + if (value_len != strlen(value) || strncmp(value, VALUE1, value_len)) { + fprintf(stderr, "Error: fgetxattr expectd value: %s, returned value: %s\n", VALUE1, value); + rc = -1; + goto Exit; + } + + value_len = io_uring_fgetxattr(&ring, fd, KEY2, value, XATTR_SIZE); + if (value_len != strlen(value)|| strncmp(value, VALUE2, value_len)) { + fprintf(stderr, "Error: fgetxattr expectd value: %s, returned value: %s\n", VALUE2, value); + rc = -1; + goto Exit; + } + + /* Cleanup. */ +Exit: + close(fd); + unlink(FILENAME); + + io_uring_queue_exit(&ring); + + return rc; +} + +/* Test driver for setxattr and getxattr. */ +int test_xattr(void) +{ + int rc = 0; + int value_len; + struct io_uring ring; + char value[XATTR_SIZE]; + + /* Init io-uring queue. */ + int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0); + if (ret) { + fprintf(stderr, "child: ring setup failed: %d\n", ret); + return -1; + } + + /* Create the test file. */ + t_create_file(FILENAME, 0); + + /* Test writing attributes. */ + if (io_uring_setxattr(&ring, FILENAME, KEY1, VALUE1, strlen(VALUE1), 0) == -1) { + fprintf(stderr, "Error setxattr cannot write key1\n"); + rc = -1; + goto Exit; + } + + if (io_uring_setxattr(&ring, FILENAME, KEY2, VALUE2, strlen(VALUE2), 0) == -1) { + fprintf(stderr, "Error setxattr cannot write key1\n"); + rc = -1; + goto Exit; + } + + /* Test reading attributes. */ + value_len = io_uring_getxattr(&ring, FILENAME, KEY1, value, XATTR_SIZE); + if (value_len != strlen(VALUE1) || strncmp(value, VALUE1, value_len)) { + fprintf(stderr, "Error: getxattr expectd value: %s, returned value: %s\n", VALUE1, value); + rc = -1; + goto Exit; + } + + value_len = io_uring_getxattr(&ring, FILENAME, KEY2, value, XATTR_SIZE); + if (value_len != strlen(VALUE2) || strncmp(value, VALUE2, value_len)) { + fprintf(stderr, "Error: getxattr expectd value: %s, returned value: %s\n", VALUE2, value); + rc = -1; + goto Exit; + } + + /* Cleanup. */ +Exit: + io_uring_queue_exit(&ring); + unlink(FILENAME); + + return rc; +} + +/* Test driver for failure cases of fsetxattr and fgetxattr. */ +int test_failure_fxattr(void) +{ + int rc = 0; + struct io_uring ring; + char value[XATTR_SIZE]; + + /* Init io-uring queue. */ + int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0); + if (ret) { + fprintf(stderr, "child: ring setup failed: %d\n", ret); + return -1; + } + + /* Create the test file. */ + int fd = open(FILENAME, O_CREAT | O_RDWR); + if (fd < 0) { + fprintf(stderr, "Error: cannot open file: ret=%d\n", fd); + return -1; + } + + /* Test writing attributes. */ + assert(io_uring_fsetxattr(&ring, -1, KEY1, VALUE1, strlen(VALUE1), 0) < 0); + assert(io_uring_fsetxattr(&ring, fd, NULL, VALUE1, strlen(VALUE1), 0) < 0); + assert(io_uring_fsetxattr(&ring, fd, KEY1, NULL, strlen(VALUE1), 0) < 0); + assert(io_uring_fsetxattr(&ring, fd, KEY1, VALUE1, 0, 0) == 0); + assert(io_uring_fsetxattr(&ring, fd, KEY1, VALUE1, -1, 0) < 0); + + /* Test reading attributes. */ + assert(io_uring_fgetxattr(&ring, -1, KEY1, value, XATTR_SIZE) < 0); + assert(io_uring_fgetxattr(&ring, fd, NULL, value, XATTR_SIZE) < 0); + assert(io_uring_fgetxattr(&ring, fd, KEY1, value, 0) == 0); + + /* Cleanup. */ + close(fd); + unlink(FILENAME); + + io_uring_queue_exit(&ring); + + return rc; +} + + +/* Test driver for failure cases for setxattr and getxattr. */ +int test_failure_xattr(void) +{ + int rc = 0; + struct io_uring ring; + char value[XATTR_SIZE]; + + /* Init io-uring queue. */ + int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0); + if (ret) { + fprintf(stderr, "child: ring setup failed: %d\n", ret); + return -1; + } + + /* Create the test file. */ + t_create_file(FILENAME, 0); + + /* Test writing attributes. */ + assert(io_uring_setxattr(&ring, "complete garbage", KEY1, VALUE1, strlen(VALUE1), 0) < 0); + assert(io_uring_setxattr(&ring, NULL, KEY1, VALUE1, strlen(VALUE1), 0) < 0); + assert(io_uring_setxattr(&ring, FILENAME, NULL, VALUE1, strlen(VALUE1), 0) < 0); + assert(io_uring_setxattr(&ring, FILENAME, KEY1, NULL, strlen(VALUE1), 0) < 0); + assert(io_uring_setxattr(&ring, FILENAME, KEY1, VALUE1, 0, 0) == 0); + + /* Test reading attributes. */ + assert(io_uring_getxattr(&ring, "complete garbage", KEY1, value, XATTR_SIZE) < 0); + assert(io_uring_getxattr(&ring, NULL, KEY1, value, XATTR_SIZE) < 0); + assert(io_uring_getxattr(&ring, FILENAME, NULL, value, XATTR_SIZE) < 0); + assert(io_uring_getxattr(&ring, FILENAME, KEY1, NULL, XATTR_SIZE) == 0); + assert(io_uring_getxattr(&ring, FILENAME, KEY1, value, 0) == 0); + + /* Cleanup. */ + io_uring_queue_exit(&ring); + unlink(FILENAME); + + return rc; +} + +/* Test for invalid SQE, this will cause a segmentation fault if enabled. */ +int test_invalid_sqe(void) +{ +#ifdef DESTRUCTIVE_TEST + struct io_uring_sqe *sqe = NULL; + struct io_uring_cqe *cqe = NULL; + struct io_uring ring; + + /* Init io-uring queue. */ + int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0); + if (ret) { + fprintf(stderr, "child: ring setup failed: %d\n", ret); + return -1; + } + + /* Pass invalid SQE. */ + io_uring_prep_setxattr(sqe, FILENAME, KEY1, VALUE1, strlen(VALUE1), 0); + + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "Error io_uring_submit_and_wait: ret=%d\n", ret); + return -1; + } + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "Error io_uring_wait_cqe: ret=%d\n", ret); + return -1; + } + + ret = cqe->res; + io_uring_cqe_seen(&ring, cqe); + + return ret; +#else + return 0; +#endif +} + +/* Test driver. */ +int main(int argc, char **argv) { + if (test_fxattr() + || test_xattr() + || test_failure_fxattr() + || test_failure_xattr() + || test_invalid_sqe()) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} -- cgit v1.2.3 From f88e96ff2bd1bc3be84f11f37cd49d614de58a68 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 20 Dec 2021 11:03:02 -0700 Subject: test/xattr: specify file mode with O_CREAT Signed-off-by: Jens Axboe --- test/xattr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/xattr.c b/test/xattr.c index 017017e..52195ed 100644 --- a/test/xattr.c +++ b/test/xattr.c @@ -194,7 +194,7 @@ int test_fxattr(void) } /* Create the test file. */ - int fd = open(FILENAME, O_CREAT | O_RDWR); + int fd = open(FILENAME, O_CREAT | O_RDWR, 0644); if (fd < 0) { fprintf(stderr, "Error: cannot open file: ret=%d\n", fd); return -1; @@ -307,7 +307,7 @@ int test_failure_fxattr(void) } /* Create the test file. */ - int fd = open(FILENAME, O_CREAT | O_RDWR); + int fd = open(FILENAME, O_CREAT | O_RDWR, 0644); if (fd < 0) { fprintf(stderr, "Error: cannot open file: ret=%d\n", fd); return -1; -- cgit v1.2.3 From 54faa4b2c76d90eaaf529532bb20cdee217ce9c2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 20 Dec 2021 11:09:36 -0700 Subject: test/xattr: style fixups Signed-off-by: Jens Axboe --- test/xattr.c | 54 +++++++++++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/test/xattr.c b/test/xattr.c index 52195ed..5e9c392 100644 --- a/test/xattr.c +++ b/test/xattr.c @@ -21,12 +21,8 @@ /* Call fsetxattr. */ -int io_uring_fsetxattr(struct io_uring *ring, - int fd, - const char *name, - const void *value, - size_t size, - int flags) +static int io_uring_fsetxattr(struct io_uring *ring, int fd, const char *name, + const void *value, size_t size, int flags) { struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; @@ -59,11 +55,8 @@ int io_uring_fsetxattr(struct io_uring *ring, } /* Submit fgetxattr request. */ -int io_uring_fgetxattr(struct io_uring *ring, - int fd, - const char *name, - void *value, - size_t size) +static int io_uring_fgetxattr(struct io_uring *ring, int fd, const char *name, + void *value, size_t size) { struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; @@ -100,12 +93,9 @@ int io_uring_fgetxattr(struct io_uring *ring, } /* Call setxattr. */ -int io_uring_setxattr(struct io_uring *ring, - const char *path, - const char *name, - const void *value, - size_t size, - int flags) +static int io_uring_setxattr(struct io_uring *ring, const char *path, + const char *name, const void *value, size_t size, + int flags) { struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; @@ -138,11 +128,8 @@ int io_uring_setxattr(struct io_uring *ring, } /* Submit getxattr request. */ -int io_uring_getxattr(struct io_uring *ring, - const char *path, - const char *name, - void *value, - size_t size) +static int io_uring_getxattr(struct io_uring *ring, const char *path, + const char *name, void *value, size_t size) { struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; @@ -179,7 +166,7 @@ int io_uring_getxattr(struct io_uring *ring, } /* Test driver for fsetxattr and fgetxattr. */ -int test_fxattr(void) +static int test_fxattr(void) { int rc = 0; size_t value_len; @@ -239,7 +226,7 @@ Exit: } /* Test driver for setxattr and getxattr. */ -int test_xattr(void) +static int test_xattr(void) { int rc = 0; int value_len; @@ -293,7 +280,7 @@ Exit: } /* Test driver for failure cases of fsetxattr and fgetxattr. */ -int test_failure_fxattr(void) +static int test_failure_fxattr(void) { int rc = 0; struct io_uring ring; @@ -336,7 +323,7 @@ int test_failure_fxattr(void) /* Test driver for failure cases for setxattr and getxattr. */ -int test_failure_xattr(void) +static int test_failure_xattr(void) { int rc = 0; struct io_uring ring; @@ -374,7 +361,7 @@ int test_failure_xattr(void) } /* Test for invalid SQE, this will cause a segmentation fault if enabled. */ -int test_invalid_sqe(void) +static int test_invalid_sqe(void) { #ifdef DESTRUCTIVE_TEST struct io_uring_sqe *sqe = NULL; @@ -413,12 +400,13 @@ int test_invalid_sqe(void) } /* Test driver. */ -int main(int argc, char **argv) { - if (test_fxattr() - || test_xattr() - || test_failure_fxattr() - || test_failure_xattr() - || test_invalid_sqe()) +int main(int argc, char *argv[]) +{ + if (argc > 1) + return 0; + + if (test_fxattr() || test_xattr() || test_failure_fxattr() || + test_failure_xattr() || test_invalid_sqe()) return EXIT_FAILURE; return EXIT_SUCCESS; -- cgit v1.2.3 From 894d32dc15a2919642f2d326f36d9126933055ae Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 20 Dec 2021 11:24:35 -0700 Subject: test/xattr: don't fail on kernels not supporting the feature Also a few -1 vs < 0 fixups. Signed-off-by: Jens Axboe --- test/xattr.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/test/xattr.c b/test/xattr.c index 5e9c392..d88059c 100644 --- a/test/xattr.c +++ b/test/xattr.c @@ -9,6 +9,8 @@ #include "helpers.h" #include "liburing.h" +static int no_xattr; + /* Define constants. */ #define XATTR_SIZE 255 #define QUEUE_DEPTH 32 @@ -49,6 +51,8 @@ static int io_uring_fsetxattr(struct io_uring *ring, int fd, const char *name, } ret = cqe->res; + if (ret == -EINVAL) + no_xattr = 1; io_uring_cqe_seen(ring, cqe); return ret; @@ -188,13 +192,17 @@ static int test_fxattr(void) } /* Test writing attributes. */ - if (io_uring_fsetxattr(&ring, fd, KEY1, VALUE1, strlen(VALUE1), 0) == -1) { + if (io_uring_fsetxattr(&ring, fd, KEY1, VALUE1, strlen(VALUE1), 0) < 0) { + if (no_xattr) { + fprintf(stdout, "No xattr support, skipping\n"); + goto Exit; + } fprintf(stderr, "Error fsetxattr cannot write key1\n"); rc = -1; goto Exit; } - if (io_uring_fsetxattr(&ring, fd, KEY2, VALUE2, strlen(VALUE2), 0) == -1) { + if (io_uring_fsetxattr(&ring, fd, KEY2, VALUE2, strlen(VALUE2), 0) < 0) { fprintf(stderr, "Error fsetxattr cannot write key1\n"); rc = -1; goto Exit; @@ -203,14 +211,14 @@ static int test_fxattr(void) /* Test reading attributes. */ value_len = io_uring_fgetxattr(&ring, fd, KEY1, value, XATTR_SIZE); if (value_len != strlen(value) || strncmp(value, VALUE1, value_len)) { - fprintf(stderr, "Error: fgetxattr expectd value: %s, returned value: %s\n", VALUE1, value); + fprintf(stderr, "Error: fgetxattr expected value: %s, returned value: %s\n", VALUE1, value); rc = -1; goto Exit; } value_len = io_uring_fgetxattr(&ring, fd, KEY2, value, XATTR_SIZE); if (value_len != strlen(value)|| strncmp(value, VALUE2, value_len)) { - fprintf(stderr, "Error: fgetxattr expectd value: %s, returned value: %s\n", VALUE2, value); + fprintf(stderr, "Error: fgetxattr expected value: %s, returned value: %s\n", VALUE2, value); rc = -1; goto Exit; } @@ -244,13 +252,13 @@ static int test_xattr(void) t_create_file(FILENAME, 0); /* Test writing attributes. */ - if (io_uring_setxattr(&ring, FILENAME, KEY1, VALUE1, strlen(VALUE1), 0) == -1) { + if (io_uring_setxattr(&ring, FILENAME, KEY1, VALUE1, strlen(VALUE1), 0) < 0) { fprintf(stderr, "Error setxattr cannot write key1\n"); rc = -1; goto Exit; } - if (io_uring_setxattr(&ring, FILENAME, KEY2, VALUE2, strlen(VALUE2), 0) == -1) { + if (io_uring_setxattr(&ring, FILENAME, KEY2, VALUE2, strlen(VALUE2), 0) < 0) { fprintf(stderr, "Error setxattr cannot write key1\n"); rc = -1; goto Exit; @@ -259,14 +267,14 @@ static int test_xattr(void) /* Test reading attributes. */ value_len = io_uring_getxattr(&ring, FILENAME, KEY1, value, XATTR_SIZE); if (value_len != strlen(VALUE1) || strncmp(value, VALUE1, value_len)) { - fprintf(stderr, "Error: getxattr expectd value: %s, returned value: %s\n", VALUE1, value); + fprintf(stderr, "Error: getxattr expected value: %s, returned value: %s\n", VALUE1, value); rc = -1; goto Exit; } value_len = io_uring_getxattr(&ring, FILENAME, KEY2, value, XATTR_SIZE); if (value_len != strlen(VALUE2) || strncmp(value, VALUE2, value_len)) { - fprintf(stderr, "Error: getxattr expectd value: %s, returned value: %s\n", VALUE2, value); + fprintf(stderr, "Error: getxattr expected value: %s, returned value: %s\n", VALUE2, value); rc = -1; goto Exit; } @@ -405,8 +413,12 @@ int main(int argc, char *argv[]) if (argc > 1) return 0; - if (test_fxattr() || test_xattr() || test_failure_fxattr() || - test_failure_xattr() || test_invalid_sqe()) + if (test_fxattr()) + return EXIT_FAILURE; + if (no_xattr) + return EXIT_SUCCESS; + if (test_xattr() || test_failure_fxattr() || test_failure_xattr() || + test_invalid_sqe()) return EXIT_FAILURE; return EXIT_SUCCESS; -- cgit v1.2.3 From e5dcfbf4c94135a2ba188d475eba60f63b10e5d0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 20 Dec 2021 11:36:39 -0700 Subject: 32-bit build warning cleanups We need to cast pointers to uintptr_t first before casting to 64-bit, or they complain about the differences in size. Signed-off-by: Jens Axboe --- src/include/liburing.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 105f5dc..b5aab6e 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -735,8 +735,9 @@ static inline void io_uring_prep_getxattr(struct io_uring_sqe *sqe, const char *path, size_t len) { - io_uring_prep_rw(IORING_OP_GETXATTR, sqe, 0, name, len, (__u64) value); - sqe->addr3 = (__u64) path; + io_uring_prep_rw(IORING_OP_GETXATTR, sqe, 0, name, len, + (__u64) (uintptr_t) value); + sqe->addr3 = (__u64) (uintptr_t) path; sqe->xattr_flags = 0; } @@ -747,8 +748,9 @@ static inline void io_uring_prep_setxattr(struct io_uring_sqe *sqe, int flags, size_t len) { - io_uring_prep_rw(IORING_OP_SETXATTR, sqe, 0, name, len, (__u64) value); - sqe->addr3 = (__u64) path; + io_uring_prep_rw(IORING_OP_SETXATTR, sqe, 0, name, len, + (__u64) (uintptr_t) value); + sqe->addr3 = (__u64) (uintptr_t) path; sqe->xattr_flags = flags; } @@ -758,7 +760,8 @@ static inline void io_uring_prep_fgetxattr(struct io_uring_sqe *sqe, const char *value, size_t len) { - io_uring_prep_rw(IORING_OP_FGETXATTR, sqe, fd, name, len, (__u64) value); + io_uring_prep_rw(IORING_OP_FGETXATTR, sqe, fd, name, len, + (__u64) (uintptr_t) value); sqe->xattr_flags = 0; } @@ -769,7 +772,8 @@ static inline void io_uring_prep_fsetxattr(struct io_uring_sqe *sqe, int flags, size_t len) { - io_uring_prep_rw(IORING_OP_FSETXATTR, sqe, fd, name, len, (__u64) value); + io_uring_prep_rw(IORING_OP_FSETXATTR, sqe, fd, name, len, + (__u64) (uintptr_t) value); sqe->xattr_flags = flags; } -- cgit v1.2.3 From 30830bddbfbe9503836bdcb3ed90ec3f945d122d Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 1 Apr 2022 14:07:43 +0300 Subject: configure: Allow the configure script to fail with a non-zero exit code For poorly configured environments, configure may fail but will still exit with code 0. This, in turn, causes cryptic build errors later. Fix this by adding "set -e". Also, append "|| true" to prevent the `expr` command breaks because it will return a non-zero exit code if the regex doesn't match. Closes: https://github.com/axboe/liburing/pull/553 Co-authored-by: Roman Gershman Signed-off-by: Roman Gershman Signed-off-by: Ammar Faizi --- configure | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 512a556..f2bf041 100755 --- a/configure +++ b/configure @@ -1,10 +1,12 @@ #!/bin/sh +set -e + cc=${CC:-gcc} cxx=${CXX:-g++} for opt do - optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)') + optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)' || true) case "$opt" in --help|-h) show_help=yes ;; -- cgit v1.2.3 From c0a2850e7192edbf3679265db20e2fb2a828e830 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sun, 3 Apr 2022 16:56:01 +0700 Subject: src/int_flags.h: Add missing SPDX-License-Identifier Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220403095602.133862-2-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- src/int_flags.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/int_flags.h b/src/int_flags.h index b9270ae..90505ec 100644 --- a/src/int_flags.h +++ b/src/int_flags.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: MIT */ #ifndef LIBURING_INT_FLAGS #define LIBURING_INT_FLAGS -- cgit v1.2.3 From 20b5edad904af8873ed06f683dee6dbfb05d9fcb Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 4 Apr 2022 01:21:58 +0700 Subject: test: Rename `[0-9a-f]-test.c` to `[0-9a-f].c` Simplify the test filename. mv -v test/232c93d07b74-test.c test/232c93d07b74.c mv -v test/35fa71a030ca-test.c test/35fa71a030ca.c mv -v test/500f9fbadef8-test.c test/500f9fbadef8.c mv -v test/7ad0e4b2f83c-test.c test/7ad0e4b2f83c.c mv -v test/8a9973408177-test.c test/8a9973408177.c mv -v test/917257daa0fe-test.c test/917257daa0fe.c mv -v test/a0908ae19763-test.c test/a0908ae19763.c mv -v test/a4c0b3decb33-test.c test/a4c0b3decb33.c mv -v test/b19062a56726-test.c test/b19062a56726.c mv -v test/b5837bd5311d-test.c test/b5837bd5311d.c mv -v test/ce593a6c480a-test.c test/ce593a6c480a.c mv -v test/d4ae271dfaae-test.c test/d4ae271dfaae.c mv -v test/d77a67ed5f27-test.c test/d77a67ed5f27.c mv -v test/eeed8b54e0df-test.c test/eeed8b54e0df.c mv -v test/fc2a85cb02ef-test.c test/fc2a85cb02ef.c Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220403182200.259937-2-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- .gitignore | 30 ++--- test/232c93d07b74-test.c | 306 ------------------------------------------- test/232c93d07b74.c | 306 +++++++++++++++++++++++++++++++++++++++++++ test/35fa71a030ca-test.c | 329 ----------------------------------------------- test/35fa71a030ca.c | 329 +++++++++++++++++++++++++++++++++++++++++++++++ test/500f9fbadef8-test.c | 89 ------------- test/500f9fbadef8.c | 89 +++++++++++++ test/7ad0e4b2f83c-test.c | 93 -------------- test/7ad0e4b2f83c.c | 93 ++++++++++++++ test/8a9973408177-test.c | 106 --------------- test/8a9973408177.c | 106 +++++++++++++++ test/917257daa0fe-test.c | 53 -------- test/917257daa0fe.c | 53 ++++++++ test/Makefile | 36 +++--- test/a0908ae19763-test.c | 58 --------- test/a0908ae19763.c | 58 +++++++++ test/a4c0b3decb33-test.c | 180 -------------------------- test/a4c0b3decb33.c | 180 ++++++++++++++++++++++++++ test/b19062a56726-test.c | 53 -------- test/b19062a56726.c | 53 ++++++++ test/b5837bd5311d-test.c | 77 ----------- test/b5837bd5311d.c | 77 +++++++++++ test/ce593a6c480a-test.c | 136 -------------------- test/ce593a6c480a.c | 136 ++++++++++++++++++++ test/d4ae271dfaae-test.c | 96 -------------- test/d4ae271dfaae.c | 96 ++++++++++++++ test/d77a67ed5f27-test.c | 65 ---------- test/d77a67ed5f27.c | 65 ++++++++++ test/eeed8b54e0df-test.c | 114 ---------------- test/eeed8b54e0df.c | 114 ++++++++++++++++ test/fc2a85cb02ef-test.c | 131 ------------------- test/fc2a85cb02ef.c | 131 +++++++++++++++++++ 32 files changed, 1919 insertions(+), 1919 deletions(-) delete mode 100644 test/232c93d07b74-test.c create mode 100644 test/232c93d07b74.c delete mode 100644 test/35fa71a030ca-test.c create mode 100644 test/35fa71a030ca.c delete mode 100644 test/500f9fbadef8-test.c create mode 100644 test/500f9fbadef8.c delete mode 100644 test/7ad0e4b2f83c-test.c create mode 100644 test/7ad0e4b2f83c.c delete mode 100644 test/8a9973408177-test.c create mode 100644 test/8a9973408177.c delete mode 100644 test/917257daa0fe-test.c create mode 100644 test/917257daa0fe.c delete mode 100644 test/a0908ae19763-test.c create mode 100644 test/a0908ae19763.c delete mode 100644 test/a4c0b3decb33-test.c create mode 100644 test/a4c0b3decb33.c delete mode 100644 test/b19062a56726-test.c create mode 100644 test/b19062a56726.c delete mode 100644 test/b5837bd5311d-test.c create mode 100644 test/b5837bd5311d.c delete mode 100644 test/ce593a6c480a-test.c create mode 100644 test/ce593a6c480a.c delete mode 100644 test/d4ae271dfaae-test.c create mode 100644 test/d4ae271dfaae.c delete mode 100644 test/d77a67ed5f27-test.c create mode 100644 test/d77a67ed5f27.c delete mode 100644 test/eeed8b54e0df-test.c create mode 100644 test/eeed8b54e0df.c delete mode 100644 test/fc2a85cb02ef-test.c create mode 100644 test/fc2a85cb02ef.c diff --git a/.gitignore b/.gitignore index 4a6e585..58fff7f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,22 +16,22 @@ /examples/link-cp /examples/ucontext-cp -/test/232c93d07b74-test -/test/35fa71a030ca-test -/test/500f9fbadef8-test -/test/7ad0e4b2f83c-test -/test/8a9973408177-test -/test/917257daa0fe-test -/test/a0908ae19763-test -/test/a4c0b3decb33-test +/test/232c93d07b74 +/test/35fa71a030ca +/test/500f9fbadef8 +/test/7ad0e4b2f83c +/test/8a9973408177 +/test/917257daa0fe +/test/a0908ae19763 +/test/a4c0b3decb33 /test/accept /test/accept-link /test/accept-reuse /test/accept-test /test/across-fork -/test/b19062a56726-test -/test/b5837bd5311d-test -/test/ce593a6c480a-test +/test/b19062a56726 +/test/b5837bd5311d +/test/ce593a6c480a /test/close-opath /test/config.local /test/connect @@ -41,12 +41,12 @@ /test/cq-peek-batch /test/cq-ready /test/cq-size -/test/d4ae271dfaae-test -/test/d77a67ed5f27-test +/test/d4ae271dfaae +/test/d77a67ed5f27 /test/defer /test/double-poll-crash /test/drop-submit -/test/eeed8b54e0df-test +/test/eeed8b54e0df /test/empty-eownerdead /test/eventfd /test/eventfd-disable @@ -55,7 +55,7 @@ /test/exit-no-cleanup /test/fadvise /test/fallocate -/test/fc2a85cb02ef-test +/test/fc2a85cb02ef /test/file-register /test/file-update /test/file-verify diff --git a/test/232c93d07b74-test.c b/test/232c93d07b74-test.c deleted file mode 100644 index 4153aef..0000000 --- a/test/232c93d07b74-test.c +++ /dev/null @@ -1,306 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Test case for socket read/write through IORING_OP_READV and - * IORING_OP_WRITEV, using both TCP and sockets and blocking and - * non-blocking IO. - * - * Heavily based on a test case from Hrvoje Zeba - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "liburing.h" - -#define RECV_BUFF_SIZE 2 -#define SEND_BUFF_SIZE 3 - -#define PORT 0x1235 - -struct params { - int tcp; - int non_blocking; -}; - -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -int rcv_ready = 0; - -static void set_rcv_ready(void) -{ - pthread_mutex_lock(&mutex); - - rcv_ready = 1; - pthread_cond_signal(&cond); - - pthread_mutex_unlock(&mutex); -} - -static void wait_for_rcv_ready(void) -{ - pthread_mutex_lock(&mutex); - - while (!rcv_ready) - pthread_cond_wait(&cond, &mutex); - - pthread_mutex_unlock(&mutex); -} - -static void *rcv(void *arg) -{ - struct params *p = arg; - int s0; - int res; - - if (p->tcp) { - int val = 1; - - - s0 = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); - res = setsockopt(s0, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); - assert(res != -1); - res = setsockopt(s0, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); - assert(res != -1); - - struct sockaddr_in addr; - - addr.sin_family = AF_INET; - addr.sin_port = htons(PORT); - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - res = bind(s0, (struct sockaddr *) &addr, sizeof(addr)); - assert(res != -1); - } else { - s0 = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - assert(s0 != -1); - - struct sockaddr_un addr; - memset(&addr, 0, sizeof(addr)); - - addr.sun_family = AF_UNIX; - memcpy(addr.sun_path, "\0sock", 6); - res = bind(s0, (struct sockaddr *) &addr, sizeof(addr)); - assert(res != -1); - } - res = listen(s0, 128); - assert(res != -1); - - set_rcv_ready(); - - int s1 = accept(s0, NULL, NULL); - assert(s1 != -1); - - if (p->non_blocking) { - int flags = fcntl(s1, F_GETFL, 0); - assert(flags != -1); - - flags |= O_NONBLOCK; - res = fcntl(s1, F_SETFL, flags); - assert(res != -1); - } - - struct io_uring m_io_uring; - void *ret = NULL; - - res = io_uring_queue_init(32, &m_io_uring, 0); - assert(res >= 0); - - int bytes_read = 0; - int expected_byte = 0; - int done = 0; - - while (!done && bytes_read != 33) { - char buff[RECV_BUFF_SIZE]; - struct iovec iov; - - iov.iov_base = buff; - iov.iov_len = sizeof(buff); - - struct io_uring_sqe *sqe = io_uring_get_sqe(&m_io_uring); - assert(sqe != NULL); - - io_uring_prep_readv(sqe, s1, &iov, 1, 0); - - res = io_uring_submit(&m_io_uring); - assert(res != -1); - - struct io_uring_cqe *cqe; - unsigned head; - unsigned count = 0; - - while (!done && count != 1) { - io_uring_for_each_cqe(&m_io_uring, head, cqe) { - if (cqe->res < 0) - assert(cqe->res == -EAGAIN); - else { - int i; - - for (i = 0; i < cqe->res; i++) { - if (buff[i] != expected_byte) { - fprintf(stderr, - "Received %d, wanted %d\n", - buff[i], expected_byte); - ret++; - done = 1; - } - expected_byte++; - } - bytes_read += cqe->res; - } - - count++; - } - - assert(count <= 1); - io_uring_cq_advance(&m_io_uring, count); - } - } - - shutdown(s1, SHUT_RDWR); - close(s1); - close(s0); - io_uring_queue_exit(&m_io_uring); - return ret; -} - -static void *snd(void *arg) -{ - struct params *p = arg; - int s0; - int ret; - - wait_for_rcv_ready(); - - if (p->tcp) { - int val = 1; - - s0 = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); - ret = setsockopt(s0, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); - assert(ret != -1); - - struct sockaddr_in addr; - - addr.sin_family = AF_INET; - addr.sin_port = htons(PORT); - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - ret = connect(s0, (struct sockaddr*) &addr, sizeof(addr)); - assert(ret != -1); - } else { - s0 = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - assert(s0 != -1); - - struct sockaddr_un addr; - memset(&addr, 0, sizeof(addr)); - - addr.sun_family = AF_UNIX; - memcpy(addr.sun_path, "\0sock", 6); - ret = connect(s0, (struct sockaddr*) &addr, sizeof(addr)); - assert(ret != -1); - } - - if (p->non_blocking) { - int flags = fcntl(s0, F_GETFL, 0); - assert(flags != -1); - - flags |= O_NONBLOCK; - ret = fcntl(s0, F_SETFL, flags); - assert(ret != -1); - } - - struct io_uring m_io_uring; - - ret = io_uring_queue_init(32, &m_io_uring, 0); - assert(ret >= 0); - - int bytes_written = 0; - int done = 0; - - while (!done && bytes_written != 33) { - char buff[SEND_BUFF_SIZE]; - int i; - - for (i = 0; i < SEND_BUFF_SIZE; i++) - buff[i] = i + bytes_written; - - struct iovec iov; - - iov.iov_base = buff; - iov.iov_len = sizeof(buff); - - struct io_uring_sqe *sqe = io_uring_get_sqe(&m_io_uring); - assert(sqe != NULL); - - io_uring_prep_writev(sqe, s0, &iov, 1, 0); - - ret = io_uring_submit(&m_io_uring); - assert(ret != -1); - - struct io_uring_cqe *cqe; - unsigned head; - unsigned count = 0; - - while (!done && count != 1) { - io_uring_for_each_cqe(&m_io_uring, head, cqe) { - if (cqe->res < 0) { - if (cqe->res == -EPIPE) { - done = 1; - break; - } - assert(cqe->res == -EAGAIN); - } else { - bytes_written += cqe->res; - } - - count++; - } - - assert(count <= 1); - io_uring_cq_advance(&m_io_uring, count); - } - usleep(100000); - } - - shutdown(s0, SHUT_RDWR); - close(s0); - io_uring_queue_exit(&m_io_uring); - return NULL; -} - -int main(int argc, char *argv[]) -{ - struct params p; - pthread_t t1, t2; - void *res1, *res2; - int i, exit_val = 0; - - if (argc > 1) - return 0; - - for (i = 0; i < 4; i++) { - p.tcp = i & 1; - p.non_blocking = (i & 2) >> 1; - - rcv_ready = 0; - - pthread_create(&t1, NULL, rcv, &p); - pthread_create(&t2, NULL, snd, &p); - pthread_join(t1, &res1); - pthread_join(t2, &res2); - if (res1 || res2) { - fprintf(stderr, "Failed tcp=%d, non_blocking=%d\n", p.tcp, p.non_blocking); - exit_val = 1; - } - } - - return exit_val; -} diff --git a/test/232c93d07b74.c b/test/232c93d07b74.c new file mode 100644 index 0000000..4153aef --- /dev/null +++ b/test/232c93d07b74.c @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Test case for socket read/write through IORING_OP_READV and + * IORING_OP_WRITEV, using both TCP and sockets and blocking and + * non-blocking IO. + * + * Heavily based on a test case from Hrvoje Zeba + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" + +#define RECV_BUFF_SIZE 2 +#define SEND_BUFF_SIZE 3 + +#define PORT 0x1235 + +struct params { + int tcp; + int non_blocking; +}; + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +int rcv_ready = 0; + +static void set_rcv_ready(void) +{ + pthread_mutex_lock(&mutex); + + rcv_ready = 1; + pthread_cond_signal(&cond); + + pthread_mutex_unlock(&mutex); +} + +static void wait_for_rcv_ready(void) +{ + pthread_mutex_lock(&mutex); + + while (!rcv_ready) + pthread_cond_wait(&cond, &mutex); + + pthread_mutex_unlock(&mutex); +} + +static void *rcv(void *arg) +{ + struct params *p = arg; + int s0; + int res; + + if (p->tcp) { + int val = 1; + + + s0 = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); + res = setsockopt(s0, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); + assert(res != -1); + res = setsockopt(s0, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + assert(res != -1); + + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_port = htons(PORT); + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + res = bind(s0, (struct sockaddr *) &addr, sizeof(addr)); + assert(res != -1); + } else { + s0 = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + assert(s0 != -1); + + struct sockaddr_un addr; + memset(&addr, 0, sizeof(addr)); + + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, "\0sock", 6); + res = bind(s0, (struct sockaddr *) &addr, sizeof(addr)); + assert(res != -1); + } + res = listen(s0, 128); + assert(res != -1); + + set_rcv_ready(); + + int s1 = accept(s0, NULL, NULL); + assert(s1 != -1); + + if (p->non_blocking) { + int flags = fcntl(s1, F_GETFL, 0); + assert(flags != -1); + + flags |= O_NONBLOCK; + res = fcntl(s1, F_SETFL, flags); + assert(res != -1); + } + + struct io_uring m_io_uring; + void *ret = NULL; + + res = io_uring_queue_init(32, &m_io_uring, 0); + assert(res >= 0); + + int bytes_read = 0; + int expected_byte = 0; + int done = 0; + + while (!done && bytes_read != 33) { + char buff[RECV_BUFF_SIZE]; + struct iovec iov; + + iov.iov_base = buff; + iov.iov_len = sizeof(buff); + + struct io_uring_sqe *sqe = io_uring_get_sqe(&m_io_uring); + assert(sqe != NULL); + + io_uring_prep_readv(sqe, s1, &iov, 1, 0); + + res = io_uring_submit(&m_io_uring); + assert(res != -1); + + struct io_uring_cqe *cqe; + unsigned head; + unsigned count = 0; + + while (!done && count != 1) { + io_uring_for_each_cqe(&m_io_uring, head, cqe) { + if (cqe->res < 0) + assert(cqe->res == -EAGAIN); + else { + int i; + + for (i = 0; i < cqe->res; i++) { + if (buff[i] != expected_byte) { + fprintf(stderr, + "Received %d, wanted %d\n", + buff[i], expected_byte); + ret++; + done = 1; + } + expected_byte++; + } + bytes_read += cqe->res; + } + + count++; + } + + assert(count <= 1); + io_uring_cq_advance(&m_io_uring, count); + } + } + + shutdown(s1, SHUT_RDWR); + close(s1); + close(s0); + io_uring_queue_exit(&m_io_uring); + return ret; +} + +static void *snd(void *arg) +{ + struct params *p = arg; + int s0; + int ret; + + wait_for_rcv_ready(); + + if (p->tcp) { + int val = 1; + + s0 = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); + ret = setsockopt(s0, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + assert(ret != -1); + + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_port = htons(PORT); + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + ret = connect(s0, (struct sockaddr*) &addr, sizeof(addr)); + assert(ret != -1); + } else { + s0 = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + assert(s0 != -1); + + struct sockaddr_un addr; + memset(&addr, 0, sizeof(addr)); + + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, "\0sock", 6); + ret = connect(s0, (struct sockaddr*) &addr, sizeof(addr)); + assert(ret != -1); + } + + if (p->non_blocking) { + int flags = fcntl(s0, F_GETFL, 0); + assert(flags != -1); + + flags |= O_NONBLOCK; + ret = fcntl(s0, F_SETFL, flags); + assert(ret != -1); + } + + struct io_uring m_io_uring; + + ret = io_uring_queue_init(32, &m_io_uring, 0); + assert(ret >= 0); + + int bytes_written = 0; + int done = 0; + + while (!done && bytes_written != 33) { + char buff[SEND_BUFF_SIZE]; + int i; + + for (i = 0; i < SEND_BUFF_SIZE; i++) + buff[i] = i + bytes_written; + + struct iovec iov; + + iov.iov_base = buff; + iov.iov_len = sizeof(buff); + + struct io_uring_sqe *sqe = io_uring_get_sqe(&m_io_uring); + assert(sqe != NULL); + + io_uring_prep_writev(sqe, s0, &iov, 1, 0); + + ret = io_uring_submit(&m_io_uring); + assert(ret != -1); + + struct io_uring_cqe *cqe; + unsigned head; + unsigned count = 0; + + while (!done && count != 1) { + io_uring_for_each_cqe(&m_io_uring, head, cqe) { + if (cqe->res < 0) { + if (cqe->res == -EPIPE) { + done = 1; + break; + } + assert(cqe->res == -EAGAIN); + } else { + bytes_written += cqe->res; + } + + count++; + } + + assert(count <= 1); + io_uring_cq_advance(&m_io_uring, count); + } + usleep(100000); + } + + shutdown(s0, SHUT_RDWR); + close(s0); + io_uring_queue_exit(&m_io_uring); + return NULL; +} + +int main(int argc, char *argv[]) +{ + struct params p; + pthread_t t1, t2; + void *res1, *res2; + int i, exit_val = 0; + + if (argc > 1) + return 0; + + for (i = 0; i < 4; i++) { + p.tcp = i & 1; + p.non_blocking = (i & 2) >> 1; + + rcv_ready = 0; + + pthread_create(&t1, NULL, rcv, &p); + pthread_create(&t2, NULL, snd, &p); + pthread_join(t1, &res1); + pthread_join(t2, &res2); + if (res1 || res2) { + fprintf(stderr, "Failed tcp=%d, non_blocking=%d\n", p.tcp, p.non_blocking); + exit_val = 1; + } + } + + return exit_val; +} diff --git a/test/35fa71a030ca-test.c b/test/35fa71a030ca-test.c deleted file mode 100644 index f83cc9d..0000000 --- a/test/35fa71a030ca-test.c +++ /dev/null @@ -1,329 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -// autogenerated by syzkaller (https://github.com/google/syzkaller) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "liburing.h" -#include "../src/syscall.h" - -#if !defined(SYS_futex) && defined(SYS_futex_time64) -# define SYS_futex SYS_futex_time64 -#endif - -static void sleep_ms(uint64_t ms) -{ - usleep(ms * 1000); -} - -static uint64_t current_time_ms(void) -{ - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts)) - exit(1); - return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; -} - -static void thread_start(void* (*fn)(void*), void* arg) -{ - pthread_t th; - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, 128 << 10); - int i; - for (i = 0; i < 100; i++) { - if (pthread_create(&th, &attr, fn, arg) == 0) { - pthread_attr_destroy(&attr); - return; - } - if (errno == EAGAIN) { - usleep(50); - continue; - } - break; - } - exit(1); -} - -typedef struct { - int state; -} event_t; - -static void event_init(event_t* ev) -{ - ev->state = 0; -} - -static void event_reset(event_t* ev) -{ - ev->state = 0; -} - -static void event_set(event_t* ev) -{ - if (ev->state) - exit(1); - __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE); - syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG); -} - -static void event_wait(event_t* ev) -{ - while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE)) - syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0); -} - -static int event_isset(event_t* ev) -{ - return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE); -} - -static int event_timedwait(event_t* ev, uint64_t timeout) -{ - uint64_t start = current_time_ms(); - uint64_t now = start; - for (;;) { - uint64_t remain = timeout - (now - start); - struct timespec ts; - ts.tv_sec = remain / 1000; - ts.tv_nsec = (remain % 1000) * 1000 * 1000; - syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts); - if (__atomic_load_n(&ev->state, __ATOMIC_RELAXED)) - return 1; - now = current_time_ms(); - if (now - start > timeout) - return 0; - } -} - -static bool write_file(const char* file, const char* what, ...) -{ - char buf[1024]; - va_list args; - va_start(args, what); - vsnprintf(buf, sizeof(buf), what, args); - va_end(args); - buf[sizeof(buf) - 1] = 0; - int len = strlen(buf); - int fd = open(file, O_WRONLY | O_CLOEXEC); - if (fd == -1) - return false; - if (write(fd, buf, len) != len) { - int err = errno; - close(fd); - errno = err; - return false; - } - close(fd); - return true; -} - -static void kill_and_wait(int pid, int* status) -{ - kill(-pid, SIGKILL); - kill(pid, SIGKILL); - int i; - for (i = 0; i < 100; i++) { - if (waitpid(-1, status, WNOHANG | __WALL) == pid) - return; - usleep(1000); - } - DIR* dir = opendir("/sys/fs/fuse/connections"); - if (dir) { - for (;;) { - struct dirent* ent = readdir(dir); - if (!ent) - break; - if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) - continue; - char abort[300]; - snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", - ent->d_name); - int fd = open(abort, O_WRONLY); - if (fd == -1) { - continue; - } - if (write(fd, abort, 1) < 0) { - } - close(fd); - } - closedir(dir); - } else { - } - while (waitpid(-1, status, __WALL) != pid) { - } -} - -#define SYZ_HAVE_SETUP_TEST 1 -static void setup_test() -{ - prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); - setpgrp(); - write_file("/proc/self/oom_score_adj", "1000"); -} - -struct thread_t { - int created, call; - event_t ready, done; -}; - -static struct thread_t threads[16]; -static void execute_call(int call); -static int running; - -static void* thr(void* arg) -{ - struct thread_t* th = (struct thread_t*)arg; - for (;;) { - event_wait(&th->ready); - event_reset(&th->ready); - execute_call(th->call); - __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); - event_set(&th->done); - } - return 0; -} - -static void execute_one(void) -{ - int i, call, thread; - for (call = 0; call < 3; call++) { - for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); - thread++) { - struct thread_t* th = &threads[thread]; - if (!th->created) { - th->created = 1; - event_init(&th->ready); - event_init(&th->done); - event_set(&th->done); - thread_start(thr, th); - } - if (!event_isset(&th->done)) - continue; - event_reset(&th->done); - th->call = call; - __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); - event_set(&th->ready); - event_timedwait(&th->done, 45); - break; - } - } - for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) - sleep_ms(1); -} - -static void execute_one(void); - -#define WAIT_FLAGS __WALL - -static void loop(void) -{ - int iter; - for (iter = 0;; iter++) { - int pid = fork(); - if (pid < 0) - exit(1); - if (pid == 0) { - setup_test(); - execute_one(); - exit(0); - } - int status = 0; - uint64_t start = current_time_ms(); - for (;;) { - if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) - break; - sleep_ms(1); - if (current_time_ms() - start < 5 * 1000) - continue; - kill_and_wait(pid, &status); - break; - } - } -} - -uint64_t r[1] = {0xffffffffffffffff}; - -void execute_call(int call) -{ - long res; - switch (call) { - case 0: - *(uint32_t*)0x20000040 = 0; - *(uint32_t*)0x20000044 = 0; - *(uint32_t*)0x20000048 = 0; - *(uint32_t*)0x2000004c = 0; - *(uint32_t*)0x20000050 = 0; - *(uint32_t*)0x20000054 = 0; - *(uint32_t*)0x20000058 = 0; - *(uint32_t*)0x2000005c = 0; - *(uint32_t*)0x20000060 = 0; - *(uint32_t*)0x20000064 = 0; - *(uint32_t*)0x20000068 = 0; - *(uint32_t*)0x2000006c = 0; - *(uint32_t*)0x20000070 = 0; - *(uint32_t*)0x20000074 = 0; - *(uint32_t*)0x20000078 = 0; - *(uint32_t*)0x2000007c = 0; - *(uint32_t*)0x20000080 = 0; - *(uint32_t*)0x20000084 = 0; - *(uint64_t*)0x20000088 = 0; - *(uint32_t*)0x20000090 = 0; - *(uint32_t*)0x20000094 = 0; - *(uint32_t*)0x20000098 = 0; - *(uint32_t*)0x2000009c = 0; - *(uint32_t*)0x200000a0 = 0; - *(uint32_t*)0x200000a4 = 0; - *(uint32_t*)0x200000a8 = 0; - *(uint32_t*)0x200000ac = 0; - *(uint64_t*)0x200000b0 = 0; - res = __sys_io_uring_setup(0x64, (struct io_uring_params *) 0x20000040UL); - if (res != -1) - r[0] = res; - break; - case 1: - __sys_io_uring_register((long)r[0], 0, 0, 0); - break; - case 2: - __sys_io_uring_register((long)r[0], 0, 0, 0); - break; - } -} - -static void sig_int(int sig) -{ - exit(0); -} - -int main(int argc, char *argv[]) -{ - if (argc > 1) - return 0; - signal(SIGINT, sig_int); - mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); - signal(SIGALRM, sig_int); - alarm(5); - - loop(); - return 0; -} diff --git a/test/35fa71a030ca.c b/test/35fa71a030ca.c new file mode 100644 index 0000000..f83cc9d --- /dev/null +++ b/test/35fa71a030ca.c @@ -0,0 +1,329 @@ +/* SPDX-License-Identifier: MIT */ +// autogenerated by syzkaller (https://github.com/google/syzkaller) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "liburing.h" +#include "../src/syscall.h" + +#if !defined(SYS_futex) && defined(SYS_futex_time64) +# define SYS_futex SYS_futex_time64 +#endif + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i; + for (i = 0; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + int state; +} event_t; + +static void event_init(event_t* ev) +{ + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + if (ev->state) + exit(1); + __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE); + syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG); +} + +static void event_wait(event_t* ev) +{ + while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE)) + syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0); +} + +static int event_isset(event_t* ev) +{ + return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE); +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + for (;;) { + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts); + if (__atomic_load_n(&ev->state, __ATOMIC_RELAXED)) + return 1; + now = current_time_ms(); + if (now - start > timeout) + return 0; + } +} + +static bool write_file(const char* file, const char* what, ...) +{ + char buf[1024]; + va_list args; + va_start(args, what); + vsnprintf(buf, sizeof(buf), what, args); + va_end(args); + buf[sizeof(buf) - 1] = 0; + int len = strlen(buf); + int fd = open(file, O_WRONLY | O_CLOEXEC); + if (fd == -1) + return false; + if (write(fd, buf, len) != len) { + int err = errno; + close(fd); + errno = err; + return false; + } + close(fd); + return true; +} + +static void kill_and_wait(int pid, int* status) +{ + kill(-pid, SIGKILL); + kill(pid, SIGKILL); + int i; + for (i = 0; i < 100; i++) { + if (waitpid(-1, status, WNOHANG | __WALL) == pid) + return; + usleep(1000); + } + DIR* dir = opendir("/sys/fs/fuse/connections"); + if (dir) { + for (;;) { + struct dirent* ent = readdir(dir); + if (!ent) + break; + if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) + continue; + char abort[300]; + snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", + ent->d_name); + int fd = open(abort, O_WRONLY); + if (fd == -1) { + continue; + } + if (write(fd, abort, 1) < 0) { + } + close(fd); + } + closedir(dir); + } else { + } + while (waitpid(-1, status, __WALL) != pid) { + } +} + +#define SYZ_HAVE_SETUP_TEST 1 +static void setup_test() +{ + prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + setpgrp(); + write_file("/proc/self/oom_score_adj", "1000"); +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + int i, call, thread; + for (call = 0; call < 3; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 45); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS __WALL + +static void loop(void) +{ + int iter; + for (iter = 0;; iter++) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + setup_test(); + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + sleep_ms(1); + if (current_time_ms() - start < 5 * 1000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +uint64_t r[1] = {0xffffffffffffffff}; + +void execute_call(int call) +{ + long res; + switch (call) { + case 0: + *(uint32_t*)0x20000040 = 0; + *(uint32_t*)0x20000044 = 0; + *(uint32_t*)0x20000048 = 0; + *(uint32_t*)0x2000004c = 0; + *(uint32_t*)0x20000050 = 0; + *(uint32_t*)0x20000054 = 0; + *(uint32_t*)0x20000058 = 0; + *(uint32_t*)0x2000005c = 0; + *(uint32_t*)0x20000060 = 0; + *(uint32_t*)0x20000064 = 0; + *(uint32_t*)0x20000068 = 0; + *(uint32_t*)0x2000006c = 0; + *(uint32_t*)0x20000070 = 0; + *(uint32_t*)0x20000074 = 0; + *(uint32_t*)0x20000078 = 0; + *(uint32_t*)0x2000007c = 0; + *(uint32_t*)0x20000080 = 0; + *(uint32_t*)0x20000084 = 0; + *(uint64_t*)0x20000088 = 0; + *(uint32_t*)0x20000090 = 0; + *(uint32_t*)0x20000094 = 0; + *(uint32_t*)0x20000098 = 0; + *(uint32_t*)0x2000009c = 0; + *(uint32_t*)0x200000a0 = 0; + *(uint32_t*)0x200000a4 = 0; + *(uint32_t*)0x200000a8 = 0; + *(uint32_t*)0x200000ac = 0; + *(uint64_t*)0x200000b0 = 0; + res = __sys_io_uring_setup(0x64, (struct io_uring_params *) 0x20000040UL); + if (res != -1) + r[0] = res; + break; + case 1: + __sys_io_uring_register((long)r[0], 0, 0, 0); + break; + case 2: + __sys_io_uring_register((long)r[0], 0, 0, 0); + break; + } +} + +static void sig_int(int sig) +{ + exit(0); +} + +int main(int argc, char *argv[]) +{ + if (argc > 1) + return 0; + signal(SIGINT, sig_int); + mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); + signal(SIGALRM, sig_int); + alarm(5); + + loop(); + return 0; +} diff --git a/test/500f9fbadef8-test.c b/test/500f9fbadef8-test.c deleted file mode 100644 index dbd5751..0000000 --- a/test/500f9fbadef8-test.c +++ /dev/null @@ -1,89 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Description: Single depth submit+wait poll hang test - * - */ -#include -#include -#include -#include -#include -#include - -#include "helpers.h" -#include "liburing.h" - -#define BLOCKS 4096 - -int main(int argc, char *argv[]) -{ - struct io_uring ring; - struct io_uring_sqe *sqe; - struct io_uring_cqe *cqe; - struct iovec iov; - char buf[32]; - off_t offset; - unsigned blocks; - int ret, fd; - - if (argc > 1) - return 0; - - t_posix_memalign(&iov.iov_base, 4096, 4096); - iov.iov_len = 4096; - - ret = io_uring_queue_init(1, &ring, IORING_SETUP_IOPOLL); - if (ret) { - fprintf(stderr, "ring setup failed\n"); - return 1; - - } - - sprintf(buf, "./XXXXXX"); - fd = mkostemp(buf, O_WRONLY | O_DIRECT | O_CREAT); - if (fd < 0) { - perror("mkostemp"); - return 1; - } - - offset = 0; - blocks = BLOCKS; - do { - sqe = io_uring_get_sqe(&ring); - if (!sqe) { - fprintf(stderr, "get sqe failed\n"); - goto err; - } - io_uring_prep_writev(sqe, fd, &iov, 1, offset); - ret = io_uring_submit_and_wait(&ring, 1); - if (ret < 0) { - fprintf(stderr, "submit_and_wait: %d\n", ret); - goto err; - } - ret = io_uring_wait_cqe(&ring, &cqe); - if (ret < 0) { - fprintf(stderr, "wait completion: %d\n", ret); - goto err; - } - if (cqe->res != 4096) { - if (cqe->res == -EOPNOTSUPP) - goto skipped; - goto err; - } - io_uring_cqe_seen(&ring, cqe); - offset += 4096; - } while (--blocks); - - close(fd); - unlink(buf); - return 0; -err: - close(fd); - unlink(buf); - return 1; -skipped: - fprintf(stderr, "Polling not supported in current dir, test skipped\n"); - close(fd); - unlink(buf); - return 0; -} diff --git a/test/500f9fbadef8.c b/test/500f9fbadef8.c new file mode 100644 index 0000000..dbd5751 --- /dev/null +++ b/test/500f9fbadef8.c @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: Single depth submit+wait poll hang test + * + */ +#include +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "liburing.h" + +#define BLOCKS 4096 + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct iovec iov; + char buf[32]; + off_t offset; + unsigned blocks; + int ret, fd; + + if (argc > 1) + return 0; + + t_posix_memalign(&iov.iov_base, 4096, 4096); + iov.iov_len = 4096; + + ret = io_uring_queue_init(1, &ring, IORING_SETUP_IOPOLL); + if (ret) { + fprintf(stderr, "ring setup failed\n"); + return 1; + + } + + sprintf(buf, "./XXXXXX"); + fd = mkostemp(buf, O_WRONLY | O_DIRECT | O_CREAT); + if (fd < 0) { + perror("mkostemp"); + return 1; + } + + offset = 0; + blocks = BLOCKS; + do { + sqe = io_uring_get_sqe(&ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + io_uring_prep_writev(sqe, fd, &iov, 1, offset); + ret = io_uring_submit_and_wait(&ring, 1); + if (ret < 0) { + fprintf(stderr, "submit_and_wait: %d\n", ret); + goto err; + } + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion: %d\n", ret); + goto err; + } + if (cqe->res != 4096) { + if (cqe->res == -EOPNOTSUPP) + goto skipped; + goto err; + } + io_uring_cqe_seen(&ring, cqe); + offset += 4096; + } while (--blocks); + + close(fd); + unlink(buf); + return 0; +err: + close(fd); + unlink(buf); + return 1; +skipped: + fprintf(stderr, "Polling not supported in current dir, test skipped\n"); + close(fd); + unlink(buf); + return 0; +} diff --git a/test/7ad0e4b2f83c-test.c b/test/7ad0e4b2f83c-test.c deleted file mode 100644 index 4d760e1..0000000 --- a/test/7ad0e4b2f83c-test.c +++ /dev/null @@ -1,93 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#include -#include -#include -#include "liburing.h" - -static unsigned long long mtime_since(const struct timeval *s, - const struct timeval *e) -{ - long long sec, usec; - - sec = e->tv_sec - s->tv_sec; - usec = (e->tv_usec - s->tv_usec); - if (sec > 0 && usec < 0) { - sec--; - usec += 1000000; - } - - sec *= 1000; - usec /= 1000; - return sec + usec; -} - -static unsigned long long mtime_since_now(struct timeval *tv) -{ - struct timeval end; - - gettimeofday(&end, NULL); - return mtime_since(tv, &end); -} - -int main(int argc, char *argv[]) -{ - struct __kernel_timespec ts1, ts2; - struct io_uring_cqe *cqe; - struct io_uring_sqe *sqe; - struct io_uring ring; - unsigned long msec; - struct timeval tv; - int ret; - - if (argc > 1) - return 0; - - ret = io_uring_queue_init(32, &ring, 0); - if (ret) { - fprintf(stderr, "io_uring_queue_init=%d\n", ret); - return 1; - } - - sqe = io_uring_get_sqe(&ring); - io_uring_prep_nop(sqe); - ret = io_uring_submit(&ring); - if (ret != 1) { - fprintf(stderr, "io_uring_submit1=%d\n", ret); - return 1; - } - - - ts1.tv_sec = 5, - ts1.tv_nsec = 0; - ret = io_uring_wait_cqe_timeout(&ring, &cqe, &ts1); - if (ret) { - fprintf(stderr, "io_uring_wait_cqe_timeout=%d\n", ret); - return 1; - } - io_uring_cqe_seen(&ring, cqe); - gettimeofday(&tv, NULL); - - ts2.tv_sec = 1; - ts2.tv_nsec = 0; - sqe = io_uring_get_sqe(&ring); - io_uring_prep_timeout(sqe, &ts2, 0, 0); - sqe->user_data = 89; - ret = io_uring_submit(&ring); - if (ret != 1) { - fprintf(stderr, "io_uring_submit2=%d\n", ret); - return 1; - } - - io_uring_wait_cqe(&ring, &cqe); - io_uring_cqe_seen(&ring, cqe); - msec = mtime_since_now(&tv); - if (msec >= 900 && msec <= 1100) { - io_uring_queue_exit(&ring); - return 0; - } - - fprintf(stderr, "%s: Timeout seems wonky (got %lu)\n", __FUNCTION__, - msec); - io_uring_queue_exit(&ring); - return 1; -} diff --git a/test/7ad0e4b2f83c.c b/test/7ad0e4b2f83c.c new file mode 100644 index 0000000..4d760e1 --- /dev/null +++ b/test/7ad0e4b2f83c.c @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: MIT */ +#include +#include +#include +#include "liburing.h" + +static unsigned long long mtime_since(const struct timeval *s, + const struct timeval *e) +{ + long long sec, usec; + + sec = e->tv_sec - s->tv_sec; + usec = (e->tv_usec - s->tv_usec); + if (sec > 0 && usec < 0) { + sec--; + usec += 1000000; + } + + sec *= 1000; + usec /= 1000; + return sec + usec; +} + +static unsigned long long mtime_since_now(struct timeval *tv) +{ + struct timeval end; + + gettimeofday(&end, NULL); + return mtime_since(tv, &end); +} + +int main(int argc, char *argv[]) +{ + struct __kernel_timespec ts1, ts2; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + struct io_uring ring; + unsigned long msec; + struct timeval tv; + int ret; + + if (argc > 1) + return 0; + + ret = io_uring_queue_init(32, &ring, 0); + if (ret) { + fprintf(stderr, "io_uring_queue_init=%d\n", ret); + return 1; + } + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_nop(sqe); + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "io_uring_submit1=%d\n", ret); + return 1; + } + + + ts1.tv_sec = 5, + ts1.tv_nsec = 0; + ret = io_uring_wait_cqe_timeout(&ring, &cqe, &ts1); + if (ret) { + fprintf(stderr, "io_uring_wait_cqe_timeout=%d\n", ret); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + gettimeofday(&tv, NULL); + + ts2.tv_sec = 1; + ts2.tv_nsec = 0; + sqe = io_uring_get_sqe(&ring); + io_uring_prep_timeout(sqe, &ts2, 0, 0); + sqe->user_data = 89; + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "io_uring_submit2=%d\n", ret); + return 1; + } + + io_uring_wait_cqe(&ring, &cqe); + io_uring_cqe_seen(&ring, cqe); + msec = mtime_since_now(&tv); + if (msec >= 900 && msec <= 1100) { + io_uring_queue_exit(&ring); + return 0; + } + + fprintf(stderr, "%s: Timeout seems wonky (got %lu)\n", __FUNCTION__, + msec); + io_uring_queue_exit(&ring); + return 1; +} diff --git a/test/8a9973408177-test.c b/test/8a9973408177-test.c deleted file mode 100644 index 94bf781..0000000 --- a/test/8a9973408177-test.c +++ /dev/null @@ -1,106 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#include -#include -#include -#include -#include -#include - -#include "liburing.h" - -static int register_file(struct io_uring *ring) -{ - char buf[32]; - int ret, fd; - - sprintf(buf, "./XXXXXX"); - fd = mkstemp(buf); - if (fd < 0) { - perror("open"); - return 1; - } - - ret = io_uring_register_files(ring, &fd, 1); - if (ret) { - fprintf(stderr, "file register %d\n", ret); - return 1; - } - - ret = io_uring_unregister_files(ring); - if (ret) { - fprintf(stderr, "file register %d\n", ret); - return 1; - } - - unlink(buf); - close(fd); - return 0; -} - -static int test_single_fsync(struct io_uring *ring) -{ - struct io_uring_cqe *cqe; - struct io_uring_sqe *sqe; - char buf[32]; - int fd, ret; - - sprintf(buf, "./XXXXXX"); - fd = mkstemp(buf); - if (fd < 0) { - perror("open"); - return 1; - } - - sqe = io_uring_get_sqe(ring); - if (!sqe) { - printf("get sqe failed\n"); - goto err; - } - - io_uring_prep_fsync(sqe, fd, 0); - - ret = io_uring_submit(ring); - if (ret <= 0) { - printf("sqe submit failed: %d\n", ret); - goto err; - } - - ret = io_uring_wait_cqe(ring, &cqe); - if (ret < 0) { - printf("wait completion %d\n", ret); - goto err; - } - - io_uring_cqe_seen(ring, cqe); - unlink(buf); - return 0; -err: - unlink(buf); - return 1; -} - -int main(int argc, char *argv[]) -{ - struct io_uring ring; - int ret; - - if (argc > 1) - return 0; - - ret = io_uring_queue_init(8, &ring, 0); - if (ret) { - printf("ring setup failed\n"); - return 1; - } - - ret = register_file(&ring); - if (ret) - return ret; - ret = test_single_fsync(&ring); - if (ret) { - printf("test_single_fsync failed\n"); - return ret; - } - - return 0; -} diff --git a/test/8a9973408177.c b/test/8a9973408177.c new file mode 100644 index 0000000..94bf781 --- /dev/null +++ b/test/8a9973408177.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: MIT */ +#include +#include +#include +#include +#include +#include + +#include "liburing.h" + +static int register_file(struct io_uring *ring) +{ + char buf[32]; + int ret, fd; + + sprintf(buf, "./XXXXXX"); + fd = mkstemp(buf); + if (fd < 0) { + perror("open"); + return 1; + } + + ret = io_uring_register_files(ring, &fd, 1); + if (ret) { + fprintf(stderr, "file register %d\n", ret); + return 1; + } + + ret = io_uring_unregister_files(ring); + if (ret) { + fprintf(stderr, "file register %d\n", ret); + return 1; + } + + unlink(buf); + close(fd); + return 0; +} + +static int test_single_fsync(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + char buf[32]; + int fd, ret; + + sprintf(buf, "./XXXXXX"); + fd = mkstemp(buf); + if (fd < 0) { + perror("open"); + return 1; + } + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + printf("get sqe failed\n"); + goto err; + } + + io_uring_prep_fsync(sqe, fd, 0); + + ret = io_uring_submit(ring); + if (ret <= 0) { + printf("sqe submit failed: %d\n", ret); + goto err; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + printf("wait completion %d\n", ret); + goto err; + } + + io_uring_cqe_seen(ring, cqe); + unlink(buf); + return 0; +err: + unlink(buf); + return 1; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + int ret; + + if (argc > 1) + return 0; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + printf("ring setup failed\n"); + return 1; + } + + ret = register_file(&ring); + if (ret) + return ret; + ret = test_single_fsync(&ring); + if (ret) { + printf("test_single_fsync failed\n"); + return ret; + } + + return 0; +} diff --git a/test/917257daa0fe-test.c b/test/917257daa0fe-test.c deleted file mode 100644 index 1d00ef1..0000000 --- a/test/917257daa0fe-test.c +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -// autogenerated by syzkaller (https://github.com/google/syzkaller) - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "liburing.h" -#include "../src/syscall.h" - -int main(int argc, char *argv[]) -{ - if (argc > 1) - return 0; - - mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); - - *(uint32_t*)0x20000000 = 0; - *(uint32_t*)0x20000004 = 0; - *(uint32_t*)0x20000008 = 6; - *(uint32_t*)0x2000000c = 0; - *(uint32_t*)0x20000010 = 0x3af; - *(uint32_t*)0x20000014 = 0; - *(uint32_t*)0x20000018 = 0; - *(uint32_t*)0x2000001c = 0; - *(uint32_t*)0x20000020 = 0; - *(uint32_t*)0x20000024 = 0; - *(uint32_t*)0x20000028 = 0; - *(uint32_t*)0x2000002c = 0; - *(uint32_t*)0x20000030 = 0; - *(uint32_t*)0x20000034 = 0; - *(uint32_t*)0x20000038 = 0; - *(uint32_t*)0x2000003c = 0; - *(uint32_t*)0x20000040 = 0; - *(uint32_t*)0x20000044 = 0; - *(uint64_t*)0x20000048 = 0; - *(uint32_t*)0x20000050 = 0; - *(uint32_t*)0x20000054 = 0; - *(uint32_t*)0x20000058 = 0; - *(uint32_t*)0x2000005c = 0; - *(uint32_t*)0x20000060 = 0; - *(uint32_t*)0x20000064 = 0; - *(uint32_t*)0x20000068 = 0; - *(uint32_t*)0x2000006c = 0; - *(uint64_t*)0x20000070 = 0; - __sys_io_uring_setup(0x7a6, (struct io_uring_params *) 0x20000000UL); - return 0; -} diff --git a/test/917257daa0fe.c b/test/917257daa0fe.c new file mode 100644 index 0000000..1d00ef1 --- /dev/null +++ b/test/917257daa0fe.c @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: MIT */ +// autogenerated by syzkaller (https://github.com/google/syzkaller) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "../src/syscall.h" + +int main(int argc, char *argv[]) +{ + if (argc > 1) + return 0; + + mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); + + *(uint32_t*)0x20000000 = 0; + *(uint32_t*)0x20000004 = 0; + *(uint32_t*)0x20000008 = 6; + *(uint32_t*)0x2000000c = 0; + *(uint32_t*)0x20000010 = 0x3af; + *(uint32_t*)0x20000014 = 0; + *(uint32_t*)0x20000018 = 0; + *(uint32_t*)0x2000001c = 0; + *(uint32_t*)0x20000020 = 0; + *(uint32_t*)0x20000024 = 0; + *(uint32_t*)0x20000028 = 0; + *(uint32_t*)0x2000002c = 0; + *(uint32_t*)0x20000030 = 0; + *(uint32_t*)0x20000034 = 0; + *(uint32_t*)0x20000038 = 0; + *(uint32_t*)0x2000003c = 0; + *(uint32_t*)0x20000040 = 0; + *(uint32_t*)0x20000044 = 0; + *(uint64_t*)0x20000048 = 0; + *(uint32_t*)0x20000050 = 0; + *(uint32_t*)0x20000054 = 0; + *(uint32_t*)0x20000058 = 0; + *(uint32_t*)0x2000005c = 0; + *(uint32_t*)0x20000060 = 0; + *(uint32_t*)0x20000064 = 0; + *(uint32_t*)0x20000068 = 0; + *(uint32_t*)0x2000006c = 0; + *(uint64_t*)0x20000070 = 0; + __sys_io_uring_setup(0x7a6, (struct io_uring_params *) 0x20000000UL); + return 0; +} diff --git a/test/Makefile b/test/Makefile index 1526776..44a96b2 100644 --- a/test/Makefile +++ b/test/Makefile @@ -34,22 +34,22 @@ LDFLAGS ?= override LDFLAGS += -L../src/ -luring test_srcs := \ - 232c93d07b74-test.c \ - 35fa71a030ca-test.c \ - 500f9fbadef8-test.c \ - 7ad0e4b2f83c-test.c \ - 8a9973408177-test.c \ - 917257daa0fe-test.c \ - a0908ae19763-test.c \ - a4c0b3decb33-test.c \ + 232c93d07b74.c \ + 35fa71a030ca.c \ + 500f9fbadef8.c \ + 7ad0e4b2f83c.c \ + 8a9973408177.c \ + 917257daa0fe.c \ + a0908ae19763.c \ + a4c0b3decb33.c \ accept.c \ accept-link.c \ accept-reuse.c \ accept-test.c \ across-fork.c \ - b19062a56726-test.c \ - b5837bd5311d-test.c \ - ce593a6c480a-test.c \ + b19062a56726.c \ + b5837bd5311d.c \ + ce593a6c480a.c \ close-opath.c \ connect.c \ cq-full.c \ @@ -57,12 +57,12 @@ test_srcs := \ cq-peek-batch.c \ cq-ready.c \ cq-size.c \ - d4ae271dfaae-test.c \ - d77a67ed5f27-test.c \ + d4ae271dfaae.c \ + d77a67ed5f27.c \ defer.c \ double-poll-crash.c \ drop-submit.c \ - eeed8b54e0df-test.c \ + eeed8b54e0df.c \ empty-eownerdead.c \ eventfd.c \ eventfd-disable.c \ @@ -72,7 +72,7 @@ test_srcs := \ exit-no-cleanup.c \ fadvise.c \ fallocate.c \ - fc2a85cb02ef-test.c \ + fc2a85cb02ef.c \ file-register.c \ files-exit-hang-poll.c \ files-exit-hang-timeout.c \ @@ -211,8 +211,8 @@ helpers.o: helpers.c $(QUIET_CXX)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< $(helpers) $(LDFLAGS) -35fa71a030ca-test: override LDFLAGS += -lpthread -232c93d07b74-test: override LDFLAGS += -lpthread +35fa71a030ca: override LDFLAGS += -lpthread +232c93d07b74: override LDFLAGS += -lpthread send_recv: override LDFLAGS += -lpthread send_recvmsg: override LDFLAGS += -lpthread poll-link: override LDFLAGS += -lpthread @@ -220,7 +220,7 @@ accept-link: override LDFLAGS += -lpthread submit-reuse: override LDFLAGS += -lpthread poll-v-poll: override LDFLAGS += -lpthread across-fork: override LDFLAGS += -lpthread -ce593a6c480a-test: override LDFLAGS += -lpthread +ce593a6c480a: override LDFLAGS += -lpthread wakeup-hang: override LDFLAGS += -lpthread pipe-eof: override LDFLAGS += -lpthread timeout-new: override LDFLAGS += -lpthread diff --git a/test/a0908ae19763-test.c b/test/a0908ae19763-test.c deleted file mode 100644 index 00cb559..0000000 --- a/test/a0908ae19763-test.c +++ /dev/null @@ -1,58 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -// autogenerated by syzkaller (https://github.com/google/syzkaller) - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "liburing.h" -#include "../src/syscall.h" - -uint64_t r[1] = {0xffffffffffffffff}; - -int main(int argc, char *argv[]) -{ - if (argc > 1) - return 0; - mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); - intptr_t res = 0; - *(uint32_t*)0x20000080 = 0; - *(uint32_t*)0x20000084 = 0; - *(uint32_t*)0x20000088 = 0; - *(uint32_t*)0x2000008c = 0; - *(uint32_t*)0x20000090 = 0; - *(uint32_t*)0x20000094 = 0; - *(uint32_t*)0x20000098 = 0; - *(uint32_t*)0x2000009c = 0; - *(uint32_t*)0x200000a0 = 0; - *(uint32_t*)0x200000a4 = 0; - *(uint32_t*)0x200000a8 = 0; - *(uint32_t*)0x200000ac = 0; - *(uint32_t*)0x200000b0 = 0; - *(uint32_t*)0x200000b4 = 0; - *(uint32_t*)0x200000b8 = 0; - *(uint32_t*)0x200000bc = 0; - *(uint32_t*)0x200000c0 = 0; - *(uint32_t*)0x200000c4 = 0; - *(uint64_t*)0x200000c8 = 0; - *(uint32_t*)0x200000d0 = 0; - *(uint32_t*)0x200000d4 = 0; - *(uint32_t*)0x200000d8 = 0; - *(uint32_t*)0x200000dc = 0; - *(uint32_t*)0x200000e0 = 0; - *(uint32_t*)0x200000e4 = 0; - *(uint32_t*)0x200000e8 = 0; - *(uint32_t*)0x200000ec = 0; - *(uint64_t*)0x200000f0 = 0; - res = __sys_io_uring_setup(0xa4, (struct io_uring_params *) 0x20000080); - if (res != -1) - r[0] = res; - *(uint32_t*)0x20000280 = -1; - __sys_io_uring_register(r[0], 2, (const void *) 0x20000280, 1); - return 0; -} diff --git a/test/a0908ae19763.c b/test/a0908ae19763.c new file mode 100644 index 0000000..00cb559 --- /dev/null +++ b/test/a0908ae19763.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: MIT */ +// autogenerated by syzkaller (https://github.com/google/syzkaller) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "../src/syscall.h" + +uint64_t r[1] = {0xffffffffffffffff}; + +int main(int argc, char *argv[]) +{ + if (argc > 1) + return 0; + mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); + intptr_t res = 0; + *(uint32_t*)0x20000080 = 0; + *(uint32_t*)0x20000084 = 0; + *(uint32_t*)0x20000088 = 0; + *(uint32_t*)0x2000008c = 0; + *(uint32_t*)0x20000090 = 0; + *(uint32_t*)0x20000094 = 0; + *(uint32_t*)0x20000098 = 0; + *(uint32_t*)0x2000009c = 0; + *(uint32_t*)0x200000a0 = 0; + *(uint32_t*)0x200000a4 = 0; + *(uint32_t*)0x200000a8 = 0; + *(uint32_t*)0x200000ac = 0; + *(uint32_t*)0x200000b0 = 0; + *(uint32_t*)0x200000b4 = 0; + *(uint32_t*)0x200000b8 = 0; + *(uint32_t*)0x200000bc = 0; + *(uint32_t*)0x200000c0 = 0; + *(uint32_t*)0x200000c4 = 0; + *(uint64_t*)0x200000c8 = 0; + *(uint32_t*)0x200000d0 = 0; + *(uint32_t*)0x200000d4 = 0; + *(uint32_t*)0x200000d8 = 0; + *(uint32_t*)0x200000dc = 0; + *(uint32_t*)0x200000e0 = 0; + *(uint32_t*)0x200000e4 = 0; + *(uint32_t*)0x200000e8 = 0; + *(uint32_t*)0x200000ec = 0; + *(uint64_t*)0x200000f0 = 0; + res = __sys_io_uring_setup(0xa4, (struct io_uring_params *) 0x20000080); + if (res != -1) + r[0] = res; + *(uint32_t*)0x20000280 = -1; + __sys_io_uring_register(r[0], 2, (const void *) 0x20000280, 1); + return 0; +} diff --git a/test/a4c0b3decb33-test.c b/test/a4c0b3decb33-test.c deleted file mode 100644 index 34b0af2..0000000 --- a/test/a4c0b3decb33-test.c +++ /dev/null @@ -1,180 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -// autogenerated by syzkaller (https://github.com/google/syzkaller) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "liburing.h" -#include "../src/syscall.h" - -static void sleep_ms(uint64_t ms) -{ - usleep(ms * 1000); -} - -static uint64_t current_time_ms(void) -{ - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts)) - exit(1); - return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; -} - -static bool write_file(const char* file, const char* what, ...) -{ - char buf[1024]; - va_list args; - va_start(args, what); - vsnprintf(buf, sizeof(buf), what, args); - va_end(args); - buf[sizeof(buf) - 1] = 0; - int len = strlen(buf); - int fd = open(file, O_WRONLY | O_CLOEXEC); - if (fd == -1) - return false; - if (write(fd, buf, len) != len) { - int err = errno; - close(fd); - errno = err; - return false; - } - close(fd); - return true; -} - -static void kill_and_wait(int pid, int* status) -{ - kill(-pid, SIGKILL); - kill(pid, SIGKILL); - int i; - for (i = 0; i < 100; i++) { - if (waitpid(-1, status, WNOHANG | __WALL) == pid) - return; - usleep(1000); - } - DIR* dir = opendir("/sys/fs/fuse/connections"); - if (dir) { - for (;;) { - struct dirent* ent = readdir(dir); - if (!ent) - break; - if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) - continue; - char abort[300]; - snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", - ent->d_name); - int fd = open(abort, O_WRONLY); - if (fd == -1) { - continue; - } - if (write(fd, abort, 1) < 0) { - } - close(fd); - } - closedir(dir); - } else { - } - while (waitpid(-1, status, __WALL) != pid) { - } -} - -static void setup_test() -{ - prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); - setpgrp(); - write_file("/proc/self/oom_score_adj", "1000"); -} - -static void execute_one(void); - -#define WAIT_FLAGS __WALL - -static void loop(void) -{ - int iter; - for (iter = 0; iter < 5000; iter++) { - int pid = fork(); - if (pid < 0) - exit(1); - if (pid == 0) { - setup_test(); - execute_one(); - exit(0); - } - int status = 0; - uint64_t start = current_time_ms(); - for (;;) { - if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) - break; - sleep_ms(1); - if (current_time_ms() - start < 5 * 1000) - continue; - kill_and_wait(pid, &status); - break; - } - } -} - -void execute_one(void) -{ - *(uint32_t*)0x20000080 = 0; - *(uint32_t*)0x20000084 = 0; - *(uint32_t*)0x20000088 = 3; - *(uint32_t*)0x2000008c = 3; - *(uint32_t*)0x20000090 = 0x175; - *(uint32_t*)0x20000094 = 0; - *(uint32_t*)0x20000098 = 0; - *(uint32_t*)0x2000009c = 0; - *(uint32_t*)0x200000a0 = 0; - *(uint32_t*)0x200000a4 = 0; - *(uint32_t*)0x200000a8 = 0; - *(uint32_t*)0x200000ac = 0; - *(uint32_t*)0x200000b0 = 0; - *(uint32_t*)0x200000b4 = 0; - *(uint32_t*)0x200000b8 = 0; - *(uint32_t*)0x200000bc = 0; - *(uint32_t*)0x200000c0 = 0; - *(uint32_t*)0x200000c4 = 0; - *(uint64_t*)0x200000c8 = 0; - *(uint32_t*)0x200000d0 = 0; - *(uint32_t*)0x200000d4 = 0; - *(uint32_t*)0x200000d8 = 0; - *(uint32_t*)0x200000dc = 0; - *(uint32_t*)0x200000e0 = 0; - *(uint32_t*)0x200000e4 = 0; - *(uint32_t*)0x200000e8 = 0; - *(uint32_t*)0x200000ec = 0; - *(uint64_t*)0x200000f0 = 0; - __sys_io_uring_setup(0x983, (struct io_uring_params *) 0x20000080); -} - -static void sig_int(int sig) -{ - exit(0); -} - -int main(int argc, char *argv[]) -{ - if (argc > 1) - return 0; - signal(SIGINT, sig_int); - mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); - loop(); - return 0; -} diff --git a/test/a4c0b3decb33.c b/test/a4c0b3decb33.c new file mode 100644 index 0000000..34b0af2 --- /dev/null +++ b/test/a4c0b3decb33.c @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: MIT */ +// autogenerated by syzkaller (https://github.com/google/syzkaller) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "../src/syscall.h" + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static bool write_file(const char* file, const char* what, ...) +{ + char buf[1024]; + va_list args; + va_start(args, what); + vsnprintf(buf, sizeof(buf), what, args); + va_end(args); + buf[sizeof(buf) - 1] = 0; + int len = strlen(buf); + int fd = open(file, O_WRONLY | O_CLOEXEC); + if (fd == -1) + return false; + if (write(fd, buf, len) != len) { + int err = errno; + close(fd); + errno = err; + return false; + } + close(fd); + return true; +} + +static void kill_and_wait(int pid, int* status) +{ + kill(-pid, SIGKILL); + kill(pid, SIGKILL); + int i; + for (i = 0; i < 100; i++) { + if (waitpid(-1, status, WNOHANG | __WALL) == pid) + return; + usleep(1000); + } + DIR* dir = opendir("/sys/fs/fuse/connections"); + if (dir) { + for (;;) { + struct dirent* ent = readdir(dir); + if (!ent) + break; + if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) + continue; + char abort[300]; + snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", + ent->d_name); + int fd = open(abort, O_WRONLY); + if (fd == -1) { + continue; + } + if (write(fd, abort, 1) < 0) { + } + close(fd); + } + closedir(dir); + } else { + } + while (waitpid(-1, status, __WALL) != pid) { + } +} + +static void setup_test() +{ + prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + setpgrp(); + write_file("/proc/self/oom_score_adj", "1000"); +} + +static void execute_one(void); + +#define WAIT_FLAGS __WALL + +static void loop(void) +{ + int iter; + for (iter = 0; iter < 5000; iter++) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + setup_test(); + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + sleep_ms(1); + if (current_time_ms() - start < 5 * 1000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +void execute_one(void) +{ + *(uint32_t*)0x20000080 = 0; + *(uint32_t*)0x20000084 = 0; + *(uint32_t*)0x20000088 = 3; + *(uint32_t*)0x2000008c = 3; + *(uint32_t*)0x20000090 = 0x175; + *(uint32_t*)0x20000094 = 0; + *(uint32_t*)0x20000098 = 0; + *(uint32_t*)0x2000009c = 0; + *(uint32_t*)0x200000a0 = 0; + *(uint32_t*)0x200000a4 = 0; + *(uint32_t*)0x200000a8 = 0; + *(uint32_t*)0x200000ac = 0; + *(uint32_t*)0x200000b0 = 0; + *(uint32_t*)0x200000b4 = 0; + *(uint32_t*)0x200000b8 = 0; + *(uint32_t*)0x200000bc = 0; + *(uint32_t*)0x200000c0 = 0; + *(uint32_t*)0x200000c4 = 0; + *(uint64_t*)0x200000c8 = 0; + *(uint32_t*)0x200000d0 = 0; + *(uint32_t*)0x200000d4 = 0; + *(uint32_t*)0x200000d8 = 0; + *(uint32_t*)0x200000dc = 0; + *(uint32_t*)0x200000e0 = 0; + *(uint32_t*)0x200000e4 = 0; + *(uint32_t*)0x200000e8 = 0; + *(uint32_t*)0x200000ec = 0; + *(uint64_t*)0x200000f0 = 0; + __sys_io_uring_setup(0x983, (struct io_uring_params *) 0x20000080); +} + +static void sig_int(int sig) +{ + exit(0); +} + +int main(int argc, char *argv[]) +{ + if (argc > 1) + return 0; + signal(SIGINT, sig_int); + mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); + loop(); + return 0; +} diff --git a/test/b19062a56726-test.c b/test/b19062a56726-test.c deleted file mode 100644 index 6a0f686..0000000 --- a/test/b19062a56726-test.c +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -// autogenerated by syzkaller (https://github.com/google/syzkaller) - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "liburing.h" -#include "../src/syscall.h" - -int main(int argc, char *argv[]) -{ - if (argc > 1) - return 0; - - mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); - - *(uint32_t*)0x20000200 = 0; - *(uint32_t*)0x20000204 = 0; - *(uint32_t*)0x20000208 = 5; - *(uint32_t*)0x2000020c = 0x400; - *(uint32_t*)0x20000210 = 0; - *(uint32_t*)0x20000214 = 0; - *(uint32_t*)0x20000218 = 0; - *(uint32_t*)0x2000021c = 0; - *(uint32_t*)0x20000220 = 0; - *(uint32_t*)0x20000224 = 0; - *(uint32_t*)0x20000228 = 0; - *(uint32_t*)0x2000022c = 0; - *(uint32_t*)0x20000230 = 0; - *(uint32_t*)0x20000234 = 0; - *(uint32_t*)0x20000238 = 0; - *(uint32_t*)0x2000023c = 0; - *(uint32_t*)0x20000240 = 0; - *(uint32_t*)0x20000244 = 0; - *(uint64_t*)0x20000248 = 0; - *(uint32_t*)0x20000250 = 0; - *(uint32_t*)0x20000254 = 0; - *(uint32_t*)0x20000258 = 0; - *(uint32_t*)0x2000025c = 0; - *(uint32_t*)0x20000260 = 0; - *(uint32_t*)0x20000264 = 0; - *(uint32_t*)0x20000268 = 0; - *(uint32_t*)0x2000026c = 0; - *(uint64_t*)0x20000270 = 0; - __sys_io_uring_setup(0xc9f, (struct io_uring_params *) 0x20000200); - return 0; -} diff --git a/test/b19062a56726.c b/test/b19062a56726.c new file mode 100644 index 0000000..6a0f686 --- /dev/null +++ b/test/b19062a56726.c @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: MIT */ +// autogenerated by syzkaller (https://github.com/google/syzkaller) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "../src/syscall.h" + +int main(int argc, char *argv[]) +{ + if (argc > 1) + return 0; + + mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); + + *(uint32_t*)0x20000200 = 0; + *(uint32_t*)0x20000204 = 0; + *(uint32_t*)0x20000208 = 5; + *(uint32_t*)0x2000020c = 0x400; + *(uint32_t*)0x20000210 = 0; + *(uint32_t*)0x20000214 = 0; + *(uint32_t*)0x20000218 = 0; + *(uint32_t*)0x2000021c = 0; + *(uint32_t*)0x20000220 = 0; + *(uint32_t*)0x20000224 = 0; + *(uint32_t*)0x20000228 = 0; + *(uint32_t*)0x2000022c = 0; + *(uint32_t*)0x20000230 = 0; + *(uint32_t*)0x20000234 = 0; + *(uint32_t*)0x20000238 = 0; + *(uint32_t*)0x2000023c = 0; + *(uint32_t*)0x20000240 = 0; + *(uint32_t*)0x20000244 = 0; + *(uint64_t*)0x20000248 = 0; + *(uint32_t*)0x20000250 = 0; + *(uint32_t*)0x20000254 = 0; + *(uint32_t*)0x20000258 = 0; + *(uint32_t*)0x2000025c = 0; + *(uint32_t*)0x20000260 = 0; + *(uint32_t*)0x20000264 = 0; + *(uint32_t*)0x20000268 = 0; + *(uint32_t*)0x2000026c = 0; + *(uint64_t*)0x20000270 = 0; + __sys_io_uring_setup(0xc9f, (struct io_uring_params *) 0x20000200); + return 0; +} diff --git a/test/b5837bd5311d-test.c b/test/b5837bd5311d-test.c deleted file mode 100644 index 57a2b58..0000000 --- a/test/b5837bd5311d-test.c +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Description: Check to see if wait_nr is being honored. - */ -#include -#include "liburing.h" - -int main(int argc, char *argv[]) -{ - struct io_uring_sqe *sqe; - struct io_uring_cqe *cqe; - struct io_uring ring; - int ret; - struct __kernel_timespec ts = { - .tv_sec = 0, - .tv_nsec = 10000000 - }; - - if (argc > 1) - return 0; - - if (io_uring_queue_init(4, &ring, 0) != 0) { - fprintf(stderr, "ring setup failed\n"); - return 1; - } - - /* - * First, submit the timeout sqe so we can actually finish the test - * if everything is in working order. - */ - sqe = io_uring_get_sqe(&ring); - if (!sqe) { - fprintf(stderr, "get sqe failed\n"); - return 1; - } - io_uring_prep_timeout(sqe, &ts, (unsigned)-1, 0); - - ret = io_uring_submit(&ring); - if (ret != 1) { - fprintf(stderr, "Got submit %d, expected 1\n", ret); - return 1; - } - - /* - * Next, submit a nop and wait for two events. If everything is working - * as it should, we should be waiting for more than a millisecond and we - * should see two cqes. Otherwise, execution continues immediately - * and we see only one cqe. - */ - sqe = io_uring_get_sqe(&ring); - if (!sqe) { - fprintf(stderr, "get sqe failed\n"); - return 1; - } - io_uring_prep_nop(sqe); - - ret = io_uring_submit_and_wait(&ring, 2); - if (ret != 1) { - fprintf(stderr, "Got submit %d, expected 1\n", ret); - return 1; - } - - if (io_uring_peek_cqe(&ring, &cqe) != 0) { - fprintf(stderr, "Unable to peek cqe!\n"); - return 1; - } - - io_uring_cqe_seen(&ring, cqe); - - if (io_uring_peek_cqe(&ring, &cqe) != 0) { - fprintf(stderr, "Unable to peek cqe!\n"); - return 1; - } - - io_uring_queue_exit(&ring); - return 0; -} diff --git a/test/b5837bd5311d.c b/test/b5837bd5311d.c new file mode 100644 index 0000000..57a2b58 --- /dev/null +++ b/test/b5837bd5311d.c @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: Check to see if wait_nr is being honored. + */ +#include +#include "liburing.h" + +int main(int argc, char *argv[]) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + int ret; + struct __kernel_timespec ts = { + .tv_sec = 0, + .tv_nsec = 10000000 + }; + + if (argc > 1) + return 0; + + if (io_uring_queue_init(4, &ring, 0) != 0) { + fprintf(stderr, "ring setup failed\n"); + return 1; + } + + /* + * First, submit the timeout sqe so we can actually finish the test + * if everything is in working order. + */ + sqe = io_uring_get_sqe(&ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + return 1; + } + io_uring_prep_timeout(sqe, &ts, (unsigned)-1, 0); + + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "Got submit %d, expected 1\n", ret); + return 1; + } + + /* + * Next, submit a nop and wait for two events. If everything is working + * as it should, we should be waiting for more than a millisecond and we + * should see two cqes. Otherwise, execution continues immediately + * and we see only one cqe. + */ + sqe = io_uring_get_sqe(&ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + return 1; + } + io_uring_prep_nop(sqe); + + ret = io_uring_submit_and_wait(&ring, 2); + if (ret != 1) { + fprintf(stderr, "Got submit %d, expected 1\n", ret); + return 1; + } + + if (io_uring_peek_cqe(&ring, &cqe) != 0) { + fprintf(stderr, "Unable to peek cqe!\n"); + return 1; + } + + io_uring_cqe_seen(&ring, cqe); + + if (io_uring_peek_cqe(&ring, &cqe) != 0) { + fprintf(stderr, "Unable to peek cqe!\n"); + return 1; + } + + io_uring_queue_exit(&ring); + return 0; +} diff --git a/test/ce593a6c480a-test.c b/test/ce593a6c480a-test.c deleted file mode 100644 index 47de128..0000000 --- a/test/ce593a6c480a-test.c +++ /dev/null @@ -1,136 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Test 5.7 regression with task_work not being run while a task is - * waiting on another event in the kernel. - */ -#include -#include -#include -#include -#include -#include -#include -#include "liburing.h" -#include "helpers.h" - -static int use_sqpoll = 0; - -void notify_fd(int fd) -{ - char buf[8] = {0, 0, 0, 0, 0, 0, 1}; - int ret; - - ret = write(fd, &buf, 8); - if (ret < 0) - perror("write"); -} - -void *delay_set_fd_from_thread(void *data) -{ - int fd = (intptr_t) data; - - sleep(1); - notify_fd(fd); - return NULL; -} - -int main(int argc, char *argv[]) -{ - struct io_uring_params p = {}; - struct io_uring ring; - int loop_fd, other_fd; - struct io_uring_sqe *sqe; - struct io_uring_cqe *cqe = NULL; - int ret, use_fd; - char buf[8] = {0, 0, 0, 0, 0, 0, 1}; - pthread_t tid; - - if (argc > 1) - return 0; - - /* Create an eventfd to be registered with the loop to be - * notified of events being ready - */ - loop_fd = eventfd(0, EFD_CLOEXEC); - if (loop_fd == -1) { - fprintf(stderr, "eventfd errno=%d\n", errno); - return 1; - } - - /* Create an eventfd that can create events */ - use_fd = other_fd = eventfd(0, EFD_CLOEXEC); - if (other_fd == -1) { - fprintf(stderr, "eventfd errno=%d\n", errno); - return 1; - } - - if (use_sqpoll) - p.flags = IORING_SETUP_SQPOLL; - - /* Setup the ring with a registered event fd to be notified on events */ - ret = t_create_ring_params(8, &ring, &p); - if (ret == T_SETUP_SKIP) - return 0; - else if (ret < 0) - return ret; - - ret = io_uring_register_eventfd(&ring, loop_fd); - if (ret < 0) { - fprintf(stderr, "register_eventfd=%d\n", ret); - return 1; - } - - if (use_sqpoll) { - ret = io_uring_register_files(&ring, &other_fd, 1); - if (ret < 0) { - fprintf(stderr, "register_files=%d\n", ret); - return 1; - } - use_fd = 0; - } - - /* Submit a poll operation to wait on an event in other_fd */ - sqe = io_uring_get_sqe(&ring); - io_uring_prep_poll_add(sqe, use_fd, POLLIN); - sqe->user_data = 1; - if (use_sqpoll) - sqe->flags |= IOSQE_FIXED_FILE; - ret = io_uring_submit(&ring); - if (ret != 1) { - fprintf(stderr, "submit=%d\n", ret); - return 1; - } - - /* - * CASE 3: Hangs forever in Linux 5.7.5; Works in Linux 5.6.0 When this - * code is uncommented, we don't se a notification on other_fd until - * _after_ we have started the read on loop_fd. In that case, the read() on - * loop_fd seems to hang forever. - */ - pthread_create(&tid, NULL, delay_set_fd_from_thread, - (void*) (intptr_t) other_fd); - - /* Wait on the event fd for an event to be ready */ - ret = read(loop_fd, buf, 8); - if (ret < 0) { - perror("read"); - return 1; - } else if (ret != 8) { - fprintf(stderr, "Odd-sized eventfd read: %d\n", ret); - return 1; - } - - - ret = io_uring_wait_cqe(&ring, &cqe); - if (ret) { - fprintf(stderr, "wait_cqe=%d\n", ret); - return ret; - } - if (cqe->res < 0) { - fprintf(stderr, "cqe->res=%d\n", cqe->res); - return 1; - } - - io_uring_cqe_seen(&ring, cqe); - return 0; -} diff --git a/test/ce593a6c480a.c b/test/ce593a6c480a.c new file mode 100644 index 0000000..47de128 --- /dev/null +++ b/test/ce593a6c480a.c @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Test 5.7 regression with task_work not being run while a task is + * waiting on another event in the kernel. + */ +#include +#include +#include +#include +#include +#include +#include +#include "liburing.h" +#include "helpers.h" + +static int use_sqpoll = 0; + +void notify_fd(int fd) +{ + char buf[8] = {0, 0, 0, 0, 0, 0, 1}; + int ret; + + ret = write(fd, &buf, 8); + if (ret < 0) + perror("write"); +} + +void *delay_set_fd_from_thread(void *data) +{ + int fd = (intptr_t) data; + + sleep(1); + notify_fd(fd); + return NULL; +} + +int main(int argc, char *argv[]) +{ + struct io_uring_params p = {}; + struct io_uring ring; + int loop_fd, other_fd; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe = NULL; + int ret, use_fd; + char buf[8] = {0, 0, 0, 0, 0, 0, 1}; + pthread_t tid; + + if (argc > 1) + return 0; + + /* Create an eventfd to be registered with the loop to be + * notified of events being ready + */ + loop_fd = eventfd(0, EFD_CLOEXEC); + if (loop_fd == -1) { + fprintf(stderr, "eventfd errno=%d\n", errno); + return 1; + } + + /* Create an eventfd that can create events */ + use_fd = other_fd = eventfd(0, EFD_CLOEXEC); + if (other_fd == -1) { + fprintf(stderr, "eventfd errno=%d\n", errno); + return 1; + } + + if (use_sqpoll) + p.flags = IORING_SETUP_SQPOLL; + + /* Setup the ring with a registered event fd to be notified on events */ + ret = t_create_ring_params(8, &ring, &p); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret < 0) + return ret; + + ret = io_uring_register_eventfd(&ring, loop_fd); + if (ret < 0) { + fprintf(stderr, "register_eventfd=%d\n", ret); + return 1; + } + + if (use_sqpoll) { + ret = io_uring_register_files(&ring, &other_fd, 1); + if (ret < 0) { + fprintf(stderr, "register_files=%d\n", ret); + return 1; + } + use_fd = 0; + } + + /* Submit a poll operation to wait on an event in other_fd */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_poll_add(sqe, use_fd, POLLIN); + sqe->user_data = 1; + if (use_sqpoll) + sqe->flags |= IOSQE_FIXED_FILE; + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "submit=%d\n", ret); + return 1; + } + + /* + * CASE 3: Hangs forever in Linux 5.7.5; Works in Linux 5.6.0 When this + * code is uncommented, we don't se a notification on other_fd until + * _after_ we have started the read on loop_fd. In that case, the read() on + * loop_fd seems to hang forever. + */ + pthread_create(&tid, NULL, delay_set_fd_from_thread, + (void*) (intptr_t) other_fd); + + /* Wait on the event fd for an event to be ready */ + ret = read(loop_fd, buf, 8); + if (ret < 0) { + perror("read"); + return 1; + } else if (ret != 8) { + fprintf(stderr, "Odd-sized eventfd read: %d\n", ret); + return 1; + } + + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe=%d\n", ret); + return ret; + } + if (cqe->res < 0) { + fprintf(stderr, "cqe->res=%d\n", cqe->res); + return 1; + } + + io_uring_cqe_seen(&ring, cqe); + return 0; +} diff --git a/test/d4ae271dfaae-test.c b/test/d4ae271dfaae-test.c deleted file mode 100644 index 397b94b..0000000 --- a/test/d4ae271dfaae-test.c +++ /dev/null @@ -1,96 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Test case for SQPOLL missing a 'ret' clear in case of busy. - * - * Heavily based on a test case from - * Xiaoguang Wang - */ -#include -#include -#include -#include -#include - -#include "helpers.h" -#include "liburing.h" - -#define FILE_SIZE (128 * 1024) - -int main(int argc, char *argv[]) -{ - struct io_uring ring; - int i, fd, ret; - struct io_uring_sqe *sqe; - struct io_uring_cqe *cqe; - struct iovec *iovecs; - struct io_uring_params p; - char *fname; - void *buf; - - memset(&p, 0, sizeof(p)); - p.flags = IORING_SETUP_SQPOLL; - ret = t_create_ring_params(4, &ring, &p); - if (ret == T_SETUP_SKIP) - return 0; - else if (ret < 0) - return 1; - - if (argc > 1) { - fname = argv[1]; - } else { - fname = ".sqpoll.tmp"; - t_create_file(fname, FILE_SIZE); - } - - fd = open(fname, O_RDONLY | O_DIRECT); - if (fname != argv[1]) - unlink(fname); - if (fd < 0) { - perror("open"); - goto out; - } - - iovecs = t_calloc(10, sizeof(struct iovec)); - for (i = 0; i < 10; i++) { - t_posix_memalign(&buf, 4096, 4096); - iovecs[i].iov_base = buf; - iovecs[i].iov_len = 4096; - } - - ret = io_uring_register_files(&ring, &fd, 1); - if (ret < 0) { - fprintf(stderr, "register files %d\n", ret); - goto out; - } - - for (i = 0; i < 10; i++) { - sqe = io_uring_get_sqe(&ring); - if (!sqe) - break; - - io_uring_prep_readv(sqe, 0, &iovecs[i], 1, 0); - sqe->flags |= IOSQE_FIXED_FILE; - - ret = io_uring_submit(&ring); - usleep(1000); - } - - for (i = 0; i < 10; i++) { - ret = io_uring_wait_cqe(&ring, &cqe); - if (ret) { - fprintf(stderr, "wait_cqe=%d\n", ret); - break; - } - if (cqe->res != 4096) { - fprintf(stderr, "ret=%d, wanted 4096\n", cqe->res); - ret = 1; - break; - } - io_uring_cqe_seen(&ring, cqe); - } - - close(fd); -out: - io_uring_queue_exit(&ring); - return ret; -} diff --git a/test/d4ae271dfaae.c b/test/d4ae271dfaae.c new file mode 100644 index 0000000..397b94b --- /dev/null +++ b/test/d4ae271dfaae.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Test case for SQPOLL missing a 'ret' clear in case of busy. + * + * Heavily based on a test case from + * Xiaoguang Wang + */ +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "liburing.h" + +#define FILE_SIZE (128 * 1024) + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + int i, fd, ret; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct iovec *iovecs; + struct io_uring_params p; + char *fname; + void *buf; + + memset(&p, 0, sizeof(p)); + p.flags = IORING_SETUP_SQPOLL; + ret = t_create_ring_params(4, &ring, &p); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret < 0) + return 1; + + if (argc > 1) { + fname = argv[1]; + } else { + fname = ".sqpoll.tmp"; + t_create_file(fname, FILE_SIZE); + } + + fd = open(fname, O_RDONLY | O_DIRECT); + if (fname != argv[1]) + unlink(fname); + if (fd < 0) { + perror("open"); + goto out; + } + + iovecs = t_calloc(10, sizeof(struct iovec)); + for (i = 0; i < 10; i++) { + t_posix_memalign(&buf, 4096, 4096); + iovecs[i].iov_base = buf; + iovecs[i].iov_len = 4096; + } + + ret = io_uring_register_files(&ring, &fd, 1); + if (ret < 0) { + fprintf(stderr, "register files %d\n", ret); + goto out; + } + + for (i = 0; i < 10; i++) { + sqe = io_uring_get_sqe(&ring); + if (!sqe) + break; + + io_uring_prep_readv(sqe, 0, &iovecs[i], 1, 0); + sqe->flags |= IOSQE_FIXED_FILE; + + ret = io_uring_submit(&ring); + usleep(1000); + } + + for (i = 0; i < 10; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe=%d\n", ret); + break; + } + if (cqe->res != 4096) { + fprintf(stderr, "ret=%d, wanted 4096\n", cqe->res); + ret = 1; + break; + } + io_uring_cqe_seen(&ring, cqe); + } + + close(fd); +out: + io_uring_queue_exit(&ring); + return ret; +} diff --git a/test/d77a67ed5f27-test.c b/test/d77a67ed5f27-test.c deleted file mode 100644 index e56fdcd..0000000 --- a/test/d77a67ed5f27-test.c +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#include -#include -#include -#include -#include -#include "liburing.h" -#include "helpers.h" - -static void sig_alrm(int sig) -{ - fprintf(stderr, "Timed out!\n"); - exit(1); -} - -int main(int argc, char *argv[]) -{ - struct io_uring_sqe *sqe; - struct io_uring_cqe *cqe; - struct io_uring_params p; - struct io_uring ring; - int ret, data; - - if (argc > 1) - return 0; - - signal(SIGALRM, sig_alrm); - - memset(&p, 0, sizeof(p)); - p.sq_thread_idle = 100; - p.flags = IORING_SETUP_SQPOLL; - ret = t_create_ring_params(4, &ring, &p); - if (ret == T_SETUP_SKIP) - return 0; - else if (ret < 0) - return 1; - - /* make sure sq thread is sleeping at this point */ - usleep(150000); - alarm(1); - - sqe = io_uring_get_sqe(&ring); - if (!sqe) { - fprintf(stderr, "sqe get failed\n"); - return 1; - } - - io_uring_prep_nop(sqe); - io_uring_sqe_set_data(sqe, (void *) (unsigned long) 42); - io_uring_submit_and_wait(&ring, 1); - - ret = io_uring_peek_cqe(&ring, &cqe); - if (ret) { - fprintf(stderr, "cqe get failed\n"); - return 1; - } - - data = (unsigned long) io_uring_cqe_get_data(cqe); - if (data != 42) { - fprintf(stderr, "invalid data: %d\n", data); - return 1; - } - - return 0; -} diff --git a/test/d77a67ed5f27.c b/test/d77a67ed5f27.c new file mode 100644 index 0000000..e56fdcd --- /dev/null +++ b/test/d77a67ed5f27.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: MIT */ +#include +#include +#include +#include +#include +#include "liburing.h" +#include "helpers.h" + +static void sig_alrm(int sig) +{ + fprintf(stderr, "Timed out!\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring_params p; + struct io_uring ring; + int ret, data; + + if (argc > 1) + return 0; + + signal(SIGALRM, sig_alrm); + + memset(&p, 0, sizeof(p)); + p.sq_thread_idle = 100; + p.flags = IORING_SETUP_SQPOLL; + ret = t_create_ring_params(4, &ring, &p); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret < 0) + return 1; + + /* make sure sq thread is sleeping at this point */ + usleep(150000); + alarm(1); + + sqe = io_uring_get_sqe(&ring); + if (!sqe) { + fprintf(stderr, "sqe get failed\n"); + return 1; + } + + io_uring_prep_nop(sqe); + io_uring_sqe_set_data(sqe, (void *) (unsigned long) 42); + io_uring_submit_and_wait(&ring, 1); + + ret = io_uring_peek_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "cqe get failed\n"); + return 1; + } + + data = (unsigned long) io_uring_cqe_get_data(cqe); + if (data != 42) { + fprintf(stderr, "invalid data: %d\n", data); + return 1; + } + + return 0; +} diff --git a/test/eeed8b54e0df-test.c b/test/eeed8b54e0df-test.c deleted file mode 100644 index 62f6f45..0000000 --- a/test/eeed8b54e0df-test.c +++ /dev/null @@ -1,114 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Description: -EAGAIN handling - * - */ -#include -#include -#include -#include -#include -#include - -#include "helpers.h" -#include "liburing.h" - -#define BLOCK 4096 - -#ifndef RWF_NOWAIT -#define RWF_NOWAIT 8 -#endif - -static int get_file_fd(void) -{ - ssize_t ret; - char *buf; - int fd; - - fd = open("testfile", O_RDWR | O_CREAT, 0644); - unlink("testfile"); - if (fd < 0) { - perror("open file"); - return -1; - } - - buf = t_malloc(BLOCK); - ret = write(fd, buf, BLOCK); - if (ret != BLOCK) { - if (ret < 0) - perror("write"); - else - printf("Short write\n"); - goto err; - } - fsync(fd); - - if (posix_fadvise(fd, 0, 4096, POSIX_FADV_DONTNEED)) { - perror("fadvise"); -err: - close(fd); - free(buf); - return -1; - } - - free(buf); - return fd; -} - -int main(int argc, char *argv[]) -{ - struct io_uring ring; - struct io_uring_sqe *sqe; - struct io_uring_cqe *cqe; - struct iovec iov; - int ret, fd; - - if (argc > 1) - return 0; - - iov.iov_base = t_malloc(4096); - iov.iov_len = 4096; - - ret = io_uring_queue_init(2, &ring, 0); - if (ret) { - printf("ring setup failed\n"); - return 1; - - } - - sqe = io_uring_get_sqe(&ring); - if (!sqe) { - printf("get sqe failed\n"); - return 1; - } - - fd = get_file_fd(); - if (fd < 0) - return 1; - - io_uring_prep_readv(sqe, fd, &iov, 1, 0); - sqe->rw_flags = RWF_NOWAIT; - - ret = io_uring_submit(&ring); - if (ret != 1) { - printf("Got submit %d, expected 1\n", ret); - goto err; - } - - ret = io_uring_peek_cqe(&ring, &cqe); - if (ret) { - printf("Ring peek got %d\n", ret); - goto err; - } - - if (cqe->res != -EAGAIN && cqe->res != 4096) { - printf("cqe error: %d\n", cqe->res); - goto err; - } - - close(fd); - return 0; -err: - close(fd); - return 1; -} diff --git a/test/eeed8b54e0df.c b/test/eeed8b54e0df.c new file mode 100644 index 0000000..62f6f45 --- /dev/null +++ b/test/eeed8b54e0df.c @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: -EAGAIN handling + * + */ +#include +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "liburing.h" + +#define BLOCK 4096 + +#ifndef RWF_NOWAIT +#define RWF_NOWAIT 8 +#endif + +static int get_file_fd(void) +{ + ssize_t ret; + char *buf; + int fd; + + fd = open("testfile", O_RDWR | O_CREAT, 0644); + unlink("testfile"); + if (fd < 0) { + perror("open file"); + return -1; + } + + buf = t_malloc(BLOCK); + ret = write(fd, buf, BLOCK); + if (ret != BLOCK) { + if (ret < 0) + perror("write"); + else + printf("Short write\n"); + goto err; + } + fsync(fd); + + if (posix_fadvise(fd, 0, 4096, POSIX_FADV_DONTNEED)) { + perror("fadvise"); +err: + close(fd); + free(buf); + return -1; + } + + free(buf); + return fd; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct iovec iov; + int ret, fd; + + if (argc > 1) + return 0; + + iov.iov_base = t_malloc(4096); + iov.iov_len = 4096; + + ret = io_uring_queue_init(2, &ring, 0); + if (ret) { + printf("ring setup failed\n"); + return 1; + + } + + sqe = io_uring_get_sqe(&ring); + if (!sqe) { + printf("get sqe failed\n"); + return 1; + } + + fd = get_file_fd(); + if (fd < 0) + return 1; + + io_uring_prep_readv(sqe, fd, &iov, 1, 0); + sqe->rw_flags = RWF_NOWAIT; + + ret = io_uring_submit(&ring); + if (ret != 1) { + printf("Got submit %d, expected 1\n", ret); + goto err; + } + + ret = io_uring_peek_cqe(&ring, &cqe); + if (ret) { + printf("Ring peek got %d\n", ret); + goto err; + } + + if (cqe->res != -EAGAIN && cqe->res != 4096) { + printf("cqe error: %d\n", cqe->res); + goto err; + } + + close(fd); + return 0; +err: + close(fd); + return 1; +} diff --git a/test/fc2a85cb02ef-test.c b/test/fc2a85cb02ef-test.c deleted file mode 100644 index bdc3c48..0000000 --- a/test/fc2a85cb02ef-test.c +++ /dev/null @@ -1,131 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -// https://syzkaller.appspot.com/bug?id=1f2ecd7a23dba87e5ca3505ec44514a462cfe8c0 -// autogenerated by syzkaller (https://github.com/google/syzkaller) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "liburing.h" -#include "../src/syscall.h" - -static bool write_file(const char* file, const char* what, ...) -{ - char buf[1024]; - va_list args; - va_start(args, what); - vsnprintf(buf, sizeof(buf), what, args); - va_end(args); - buf[sizeof(buf) - 1] = 0; - int len = strlen(buf); - int fd = open(file, O_WRONLY | O_CLOEXEC); - if (fd == -1) - return false; - if (write(fd, buf, len) != len) { - int err = errno; - close(fd); - errno = err; - return false; - } - close(fd); - return true; -} - -static int inject_fault(int nth) -{ - int fd; - fd = open("/proc/thread-self/fail-nth", O_RDWR); - if (fd == -1) - exit(1); - char buf[16]; - sprintf(buf, "%d", nth + 1); - if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) - exit(1); - return fd; -} - -static int setup_fault() -{ - static struct { - const char* file; - const char* val; - bool fatal; - } files[] = { - {"/sys/kernel/debug/failslab/ignore-gfp-wait", "N", true}, - {"/sys/kernel/debug/failslab/verbose", "0", false}, - {"/sys/kernel/debug/fail_futex/ignore-private", "N", false}, - {"/sys/kernel/debug/fail_page_alloc/verbose", "0", false}, - {"/sys/kernel/debug/fail_page_alloc/ignore-gfp-highmem", "N", false}, - {"/sys/kernel/debug/fail_page_alloc/ignore-gfp-wait", "N", false}, - {"/sys/kernel/debug/fail_page_alloc/min-order", "0", false}, - }; - unsigned i; - for (i = 0; i < sizeof(files) / sizeof(files[0]); i++) { - if (!write_file(files[i].file, files[i].val)) { - if (files[i].fatal) - return 1; - } - } - return 0; -} - -uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff}; - -int main(int argc, char *argv[]) -{ - if (argc > 1) - return 0; - mmap((void *) 0x20000000ul, 0x1000000ul, 3ul, 0x32ul, -1, 0); - if (setup_fault()) { - printf("Test needs failslab/fail_futex/fail_page_alloc enabled, skipped\n"); - return 0; - } - intptr_t res = 0; - *(uint32_t*)0x20000000 = 0; - *(uint32_t*)0x20000004 = 0; - *(uint32_t*)0x20000008 = 0; - *(uint32_t*)0x2000000c = 0; - *(uint32_t*)0x20000010 = 0; - *(uint32_t*)0x20000014 = 0; - *(uint32_t*)0x20000018 = 0; - *(uint32_t*)0x2000001c = 0; - *(uint32_t*)0x20000020 = 0; - *(uint32_t*)0x20000024 = 0; - *(uint32_t*)0x20000028 = 0; - *(uint32_t*)0x2000002c = 0; - *(uint32_t*)0x20000030 = 0; - *(uint32_t*)0x20000034 = 0; - *(uint32_t*)0x20000038 = 0; - *(uint32_t*)0x2000003c = 0; - *(uint32_t*)0x20000040 = 0; - *(uint32_t*)0x20000044 = 0; - *(uint64_t*)0x20000048 = 0; - *(uint32_t*)0x20000050 = 0; - *(uint32_t*)0x20000054 = 0; - *(uint32_t*)0x20000058 = 0; - *(uint32_t*)0x2000005c = 0; - *(uint32_t*)0x20000060 = 0; - *(uint32_t*)0x20000064 = 0; - *(uint32_t*)0x20000068 = 0; - *(uint32_t*)0x2000006c = 0; - *(uint64_t*)0x20000070 = 0; - res = __sys_io_uring_setup(0x6a6, (struct io_uring_params *) 0x20000000ul); - if (res != -1) - r[0] = res; - res = socket(0x11ul, 2ul, 0x300ul); - if (res != -1) - r[1] = res; - *(uint32_t*)0x20000080 = r[1]; - inject_fault(1); - __sys_io_uring_register(r[0], 2ul, (const void *) 0x20000080ul, 1ul); - return 0; -} diff --git a/test/fc2a85cb02ef.c b/test/fc2a85cb02ef.c new file mode 100644 index 0000000..bdc3c48 --- /dev/null +++ b/test/fc2a85cb02ef.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: MIT */ +// https://syzkaller.appspot.com/bug?id=1f2ecd7a23dba87e5ca3505ec44514a462cfe8c0 +// autogenerated by syzkaller (https://github.com/google/syzkaller) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "../src/syscall.h" + +static bool write_file(const char* file, const char* what, ...) +{ + char buf[1024]; + va_list args; + va_start(args, what); + vsnprintf(buf, sizeof(buf), what, args); + va_end(args); + buf[sizeof(buf) - 1] = 0; + int len = strlen(buf); + int fd = open(file, O_WRONLY | O_CLOEXEC); + if (fd == -1) + return false; + if (write(fd, buf, len) != len) { + int err = errno; + close(fd); + errno = err; + return false; + } + close(fd); + return true; +} + +static int inject_fault(int nth) +{ + int fd; + fd = open("/proc/thread-self/fail-nth", O_RDWR); + if (fd == -1) + exit(1); + char buf[16]; + sprintf(buf, "%d", nth + 1); + if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) + exit(1); + return fd; +} + +static int setup_fault() +{ + static struct { + const char* file; + const char* val; + bool fatal; + } files[] = { + {"/sys/kernel/debug/failslab/ignore-gfp-wait", "N", true}, + {"/sys/kernel/debug/failslab/verbose", "0", false}, + {"/sys/kernel/debug/fail_futex/ignore-private", "N", false}, + {"/sys/kernel/debug/fail_page_alloc/verbose", "0", false}, + {"/sys/kernel/debug/fail_page_alloc/ignore-gfp-highmem", "N", false}, + {"/sys/kernel/debug/fail_page_alloc/ignore-gfp-wait", "N", false}, + {"/sys/kernel/debug/fail_page_alloc/min-order", "0", false}, + }; + unsigned i; + for (i = 0; i < sizeof(files) / sizeof(files[0]); i++) { + if (!write_file(files[i].file, files[i].val)) { + if (files[i].fatal) + return 1; + } + } + return 0; +} + +uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff}; + +int main(int argc, char *argv[]) +{ + if (argc > 1) + return 0; + mmap((void *) 0x20000000ul, 0x1000000ul, 3ul, 0x32ul, -1, 0); + if (setup_fault()) { + printf("Test needs failslab/fail_futex/fail_page_alloc enabled, skipped\n"); + return 0; + } + intptr_t res = 0; + *(uint32_t*)0x20000000 = 0; + *(uint32_t*)0x20000004 = 0; + *(uint32_t*)0x20000008 = 0; + *(uint32_t*)0x2000000c = 0; + *(uint32_t*)0x20000010 = 0; + *(uint32_t*)0x20000014 = 0; + *(uint32_t*)0x20000018 = 0; + *(uint32_t*)0x2000001c = 0; + *(uint32_t*)0x20000020 = 0; + *(uint32_t*)0x20000024 = 0; + *(uint32_t*)0x20000028 = 0; + *(uint32_t*)0x2000002c = 0; + *(uint32_t*)0x20000030 = 0; + *(uint32_t*)0x20000034 = 0; + *(uint32_t*)0x20000038 = 0; + *(uint32_t*)0x2000003c = 0; + *(uint32_t*)0x20000040 = 0; + *(uint32_t*)0x20000044 = 0; + *(uint64_t*)0x20000048 = 0; + *(uint32_t*)0x20000050 = 0; + *(uint32_t*)0x20000054 = 0; + *(uint32_t*)0x20000058 = 0; + *(uint32_t*)0x2000005c = 0; + *(uint32_t*)0x20000060 = 0; + *(uint32_t*)0x20000064 = 0; + *(uint32_t*)0x20000068 = 0; + *(uint32_t*)0x2000006c = 0; + *(uint64_t*)0x20000070 = 0; + res = __sys_io_uring_setup(0x6a6, (struct io_uring_params *) 0x20000000ul); + if (res != -1) + r[0] = res; + res = socket(0x11ul, 2ul, 0x300ul); + if (res != -1) + r[1] = res; + *(uint32_t*)0x20000080 = r[1]; + inject_fault(1); + __sys_io_uring_register(r[0], 2ul, (const void *) 0x20000080ul, 1ul); + return 0; +} -- cgit v1.2.3 From 664bf782a6d78f701301ef6ebdd7cf63b2e3ee09 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 4 Apr 2022 01:21:59 +0700 Subject: test/Makefile: Append `-lpthread` to `LDFLAGS` for all tests Instead of overriding LDFLAGS one by one for tests that need pthread, append -lpthread to LDFLAGS for all tests. This makes the Makefile script simpler. It also saves some hassle when we add a new test that does use pthread. Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220403182200.259937-3-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- test/Makefile | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/test/Makefile b/test/Makefile index 44a96b2..eb1e7d5 100644 --- a/test/Makefile +++ b/test/Makefile @@ -31,7 +31,7 @@ override CFLAGS += $(XCFLAGS) -DLIBURING_BUILD_TEST override CXXFLAGS += $(XCFLAGS) -std=c++11 -DLIBURING_BUILD_TEST LDFLAGS ?= -override LDFLAGS += -L../src/ -luring +override LDFLAGS += -L../src/ -luring -lpthread test_srcs := \ 232c93d07b74.c \ @@ -211,28 +211,6 @@ helpers.o: helpers.c $(QUIET_CXX)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< $(helpers) $(LDFLAGS) -35fa71a030ca: override LDFLAGS += -lpthread -232c93d07b74: override LDFLAGS += -lpthread -send_recv: override LDFLAGS += -lpthread -send_recvmsg: override LDFLAGS += -lpthread -poll-link: override LDFLAGS += -lpthread -accept-link: override LDFLAGS += -lpthread -submit-reuse: override LDFLAGS += -lpthread -poll-v-poll: override LDFLAGS += -lpthread -across-fork: override LDFLAGS += -lpthread -ce593a6c480a: override LDFLAGS += -lpthread -wakeup-hang: override LDFLAGS += -lpthread -pipe-eof: override LDFLAGS += -lpthread -timeout-new: override LDFLAGS += -lpthread -thread-exit: override LDFLAGS += -lpthread -ring-leak2: override LDFLAGS += -lpthread -poll-mshot-update: override LDFLAGS += -lpthread -exit-no-cleanup: override LDFLAGS += -lpthread -pollfree: override LDFLAGS += -lpthread -msg-ring: override LDFLAGS += -lpthread -recv-msgall: override LDFLAGS += -lpthread -recv-msgall-stream: override LDFLAGS += -lpthread - install: $(test_targets) runtests.sh runtests-loop.sh $(INSTALL) -D -d -m 755 $(datadir)/liburing-test/ $(INSTALL) -D -m 755 $(test_targets) $(datadir)/liburing-test/ -- cgit v1.2.3 From f200b5bba7017de7658bd44441322949182a4749 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Mon, 4 Apr 2022 01:22:00 +0700 Subject: test/Makefile: Append `.t` to the test binary When adding a new test, we often forget to add the new test binary to `.gitignore`. Append `.t` to the test binary filename, this way we can use a wildcard matching "test/*.t" in `.gitignore` to ignore all test binary files. Goals: - Make the .gitignore simpler. - Avoid the burden of adding a new test to .gitignore. Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220403182200.259937-4-ammarfaizi2@gnuweeb.org Signed-off-by: Jens Axboe --- .gitignore | 131 +--------------------------------------------------------- test/Makefile | 8 ++-- 2 files changed, 6 insertions(+), 133 deletions(-) diff --git a/.gitignore b/.gitignore index 58fff7f..60fddd7 100644 --- a/.gitignore +++ b/.gitignore @@ -16,136 +16,7 @@ /examples/link-cp /examples/ucontext-cp -/test/232c93d07b74 -/test/35fa71a030ca -/test/500f9fbadef8 -/test/7ad0e4b2f83c -/test/8a9973408177 -/test/917257daa0fe -/test/a0908ae19763 -/test/a4c0b3decb33 -/test/accept -/test/accept-link -/test/accept-reuse -/test/accept-test -/test/across-fork -/test/b19062a56726 -/test/b5837bd5311d -/test/ce593a6c480a -/test/close-opath -/test/config.local -/test/connect -/test/cq-full -/test/cq-overflow -/test/cq-overflow-peek -/test/cq-peek-batch -/test/cq-ready -/test/cq-size -/test/d4ae271dfaae -/test/d77a67ed5f27 -/test/defer -/test/double-poll-crash -/test/drop-submit -/test/eeed8b54e0df -/test/empty-eownerdead -/test/eventfd -/test/eventfd-disable -/test/eventfd-reg -/test/eventfd-ring -/test/exit-no-cleanup -/test/fadvise -/test/fallocate -/test/fc2a85cb02ef -/test/file-register -/test/file-update -/test/file-verify -/test/files-exit-hang-poll -/test/files-exit-hang-timeout -/test/fixed-buf-iter -/test/fixed-link -/test/fixed-reuse -/test/fpos -/test/fsync -/test/hardlink -/test/io-cancel -/test/io_uring_enter -/test/io_uring_register -/test/io_uring_setup -/test/iopoll -/test/lfs-openat -/test/lfs-openat-write -/test/link -/test/link-timeout -/test/link_drain -/test/madvise -/test/mkdir -/test/msg-ring -/test/nop -/test/nop-all-sizes -/test/open-close -/test/open-direct-link -/test/openat2 -/test/personality -/test/pipe-eof -/test/pipe-reuse -/test/poll -/test/poll-cancel -/test/poll-cancel-ton -/test/poll-link -/test/poll-many -/test/poll-ring -/test/poll-v-poll -/test/pollfree -/test/probe -/test/read-write -/test/recv-msgall -/test/recv-msgall-stream -/test/register-restrictions -/test/rename -/test/ring-leak -/test/ring-leak2 -/test/self -/test/send_recv -/test/send_recvmsg -/test/sendmsg_fs_cve -/test/shared-wq -/test/short-read -/test/shutdown -/test/sigfd-deadlock -/test/socket-rw -/test/socket-rw-eagain -/test/socket-rw-offset -/test/splice -/test/sq-full -/test/sq-full-cpp -/test/sq-poll-dup -/test/sq-poll-kthread -/test/sq-poll-share -/test/sqpoll-disable-exit -/test/sqpoll-exit-hang -/test/sqpoll-sleep -/test/sq-space_left -/test/statx -/test/stdout -/test/submit-reuse -/test/symlink -/test/teardowns -/test/thread-exit -/test/timeout -/test/timeout-new -/test/timeout-overflow -/test/tty-write-dpoll -/test/unlink -/test/wakeup-hang -/test/multicqes_drain -/test/poll-mshot-update -/test/rsrc_tags -/test/rw_merge_test -/test/sqpoll-cancel-hang -/test/testfile -/test/submit-link-fail -/test/exec-target -/test/skip-cqe +/test/*.t /test/*.dmesg /test/output/ diff --git a/test/Makefile b/test/Makefile index eb1e7d5..d97341c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -183,7 +183,9 @@ endif all_targets += sq-full-cpp -test_targets := $(patsubst %.c,%,$(patsubst %.cc,%,$(test_srcs))) +test_targets := $(patsubst %.c,%,$(test_srcs)) +test_targets := $(patsubst %.cc,%,$(test_targets)) +test_targets := $(patsubst %,%.t,$(test_targets)) all_targets += $(test_targets) # @@ -204,10 +206,10 @@ all: $(test_targets) helpers.o: helpers.c $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< -%: %.c $(helpers) helpers.h ../src/liburing.a +%.t: %.c $(helpers) helpers.h ../src/liburing.a $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(helpers) $(LDFLAGS) -%: %.cc $(helpers) helpers.h ../src/liburing.a +%.t: %.cc $(helpers) helpers.h ../src/liburing.a $(QUIET_CXX)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $< $(helpers) $(LDFLAGS) -- cgit v1.2.3 From 11e64b528a0d66948500a5821ebdbf010148d296 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 3 Apr 2022 17:17:08 -0600 Subject: test/Makefile statx target is now statx.t, make sure it's correct in all_targets. Signed-off-by: Jens Axboe --- test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index d97341c..c4129f6 100644 --- a/test/Makefile +++ b/test/Makefile @@ -174,7 +174,7 @@ endif ifdef CONFIG_HAVE_GLIBC_STATX test_srcs += statx.c endif -all_targets += statx +all_targets += statx.t ifdef CONFIG_HAVE_CXX -- cgit v1.2.3 From 318b08a98f1dc3c03fab3795de7fcd0290b36328 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 3 Apr 2022 17:18:30 -0600 Subject: test/Makefile: fixup sq-full-cpp target Signed-off-by: Jens Axboe --- test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index c4129f6..cb7e15e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -180,7 +180,7 @@ all_targets += statx.t ifdef CONFIG_HAVE_CXX test_srcs += sq-full-cpp.cc endif -all_targets += sq-full-cpp +all_targets += sq-full-cpp.t test_targets := $(patsubst %.c,%,$(test_srcs)) -- cgit v1.2.3 From 1b437f50fbfc74c1814cb909766147457d079a5f Mon Sep 17 00:00:00 2001 From: nick black Date: Mon, 4 Apr 2022 10:57:27 -0400 Subject: remove double casts Signed-off-by: nick black --- test/recv-msgall-stream.c | 2 +- test/recv-msgall.c | 2 +- test/send_recv.c | 2 +- test/send_recvmsg.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/recv-msgall-stream.c b/test/recv-msgall-stream.c index a4dfe6f..a188cc1 100644 --- a/test/recv-msgall-stream.c +++ b/test/recv-msgall-stream.c @@ -362,7 +362,7 @@ static int test(int use_recvmsg, int use_sync) do_send(&rd); pthread_join(recv_thread, &retval); - return (int)(intptr_t)retval; + return (intptr_t)retval; } int main(int argc, char *argv[]) diff --git a/test/recv-msgall.c b/test/recv-msgall.c index d77434d..5f202b4 100644 --- a/test/recv-msgall.c +++ b/test/recv-msgall.c @@ -241,7 +241,7 @@ static int test(int use_recvmsg) pthread_mutex_lock(&rd.mutex); do_send(); pthread_join(recv_thread, &retval); - return (int)(intptr_t)retval; + return (intptr_t)retval; } int main(int argc, char *argv[]) diff --git a/test/send_recv.c b/test/send_recv.c index ed45f83..ad8ea0e 100644 --- a/test/send_recv.c +++ b/test/send_recv.c @@ -254,7 +254,7 @@ static int test(int use_sqthread, int regfiles) pthread_mutex_lock(&rd.mutex); do_send(); pthread_join(recv_thread, &retval); - return (int)(intptr_t)retval; + return (intptr_t)retval; } int main(int argc, char *argv[]) diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index 2ff8d9d..43121f0 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -305,7 +305,7 @@ static int test(int buf_select, int no_buf_add, int iov_count) pthread_mutex_lock(&mutex); do_sendmsg(); pthread_join(recv_thread, &retval); - ret = (int)(intptr_t)retval; + ret = (intptr_t)retval; return ret; } -- cgit v1.2.3 From 30a3c697057e4457aadbd71b282b21a39f578bbd Mon Sep 17 00:00:00 2001 From: Eric Wyler Date: Mon, 4 Apr 2022 16:02:44 -0400 Subject: Review and update .3 and .7 man pages - Use of "consumed" vs "processed" was inconsistent - "consumed" was more common, so I changed the few instances of "processed" to that. It was non-obvious to me if consumption was different from processing, so this removes that ambiguity. - Fixed a few comma splices and typos in both function names and descriptions. Signed-off-by: Eric Wyler --- man/io_uring.7 | 5 +++-- man/io_uring_cq_advance.3 | 8 ++++---- man/io_uring_cqe_seen.3 | 8 ++++---- man/io_uring_opcode_supported.3 | 2 +- man/io_uring_peek_cqe.3 | 2 +- man/io_uring_prep_accept.3 | 4 ++-- man/io_uring_prep_files_update.3 | 4 ++-- man/io_uring_prep_msg_ring.3 | 2 +- man/io_uring_prep_provide_buffers.3 | 4 ++-- man/io_uring_prep_read_fixed.3 | 9 +++++---- man/io_uring_prep_splice.3 | 2 +- man/io_uring_prep_tee.3 | 4 ++-- man/io_uring_prep_timeout.3 | 4 ++-- man/io_uring_prep_timeout_update.3 | 2 +- man/io_uring_prep_write.3 | 2 +- man/io_uring_prep_write_fixed.3 | 8 ++++---- man/io_uring_prep_writev.3 | 2 +- man/io_uring_prep_writev2.3 | 2 +- man/io_uring_queue_init.3 | 6 +++--- man/io_uring_register_buffers.3 | 4 ++-- man/io_uring_sqe_set_flags.3 | 2 +- man/io_uring_submit_and_wait_timeout.3 | 2 +- 22 files changed, 45 insertions(+), 43 deletions(-) diff --git a/man/io_uring.7 b/man/io_uring.7 index 39865e6..8c71d93 100644 --- a/man/io_uring.7 +++ b/man/io_uring.7 @@ -277,7 +277,8 @@ you need to acquire a submission queue entry (SQE) from the submission queue (SQ), fill it up with details of the operation you want to submit and call .BR io_uring_enter (2). -If you want to avoid calling +There are helper functions of the form io_uring_prep_X to enable proper +setup of the SQE. If you want to avoid calling .BR io_uring_enter (2), you have the option of setting up Submission Queue Polling. .PP @@ -484,7 +485,7 @@ them to the submission queue. This avoids the .BR io_uring_enter (2) call you need to make to tell the kernel to pick SQEs up. For high-performance applications, -this means even lesser system call overheads. +this means even fewer system call overheads. .SH CONFORMING TO .B io_uring is Linux-specific. diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 index c75eaba..5aaf287 100644 --- a/man/io_uring_cq_advance.3 +++ b/man/io_uring_cq_advance.3 @@ -4,12 +4,12 @@ .\" .TH io_uring_cq_advance 3 "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_cq_advance - Mark one or more io_uring completion events as processed +io_uring_cq_advance - Mark one or more io_uring completion events as consumed .SH SYNOPSIS .nf .BR "#include " .PP -.BI "void io_uring_cqe_advance(struct io_uring *" ring "," +.BI "void io_uring_cq_advance(struct io_uring *" ring "," .BI " unsigned " nr ");" .fi .PP @@ -19,14 +19,14 @@ The io_uring_cq_advance() function marks .I nr IO completions belonging to the .I ring -param as processed. +param as consumed. After the caller has submitted a request with .BR io_uring_submit (3), the application can retrieve the completion with .BR io_uring_wait_cqe (3), .BR io_uring_peek_cqe (3), -or any of the other CQE retrieval helpers, and mark it as processed with +or any of the other CQE retrieval helpers, and mark it as consumed with .BR io_uring_cqe_seen (3). The function diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3 index dc7f8e4..41d276c 100644 --- a/man/io_uring_cqe_seen.3 +++ b/man/io_uring_cqe_seen.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_cqe_seen 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_cqe_seen - Mark io_uring completion event as processed +io_uring_cqe_seen - Mark io_uring completion event as consumed .SH SYNOPSIS .nf .BR "#include " @@ -19,17 +19,17 @@ The io_uring_cqe_seen() function marks the IO completion .I cqe belonging to the .I ring -param as processed. +param as consumed. After the caller has submitted a request with .BR io_uring_submit (3), the application can retrieve the completion with .BR io_uring_wait_cqe (3), .BR io_uring_peek_cqe (3), -or any of the other CQE retrieval helpers, and mark it as processed with +or any of the other CQE retrieval helpers, and mark it as consumed with .BR io_uring_cqe_seen (3). -Completions must be marked as completed, so their slot can get reused. +Completions must be marked as completed so their slot can get reused. .SH RETURN VALUE None .SH SEE ALSO diff --git a/man/io_uring_opcode_supported.3 b/man/io_uring_opcode_supported.3 index 8afbfc6..293d643 100644 --- a/man/io_uring_opcode_supported.3 +++ b/man/io_uring_opcode_supported.3 @@ -10,7 +10,7 @@ io_uring_opcode_supported - is op code supported? .BR "#include " .PP .BI "int io_uring_opcode_supported(struct io_uring_probe *" probe "," -.BI " int " opode ");" +.BI " int " opcode ");" .fi .PP .SH DESCRIPTION diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3 index ffd6a60..4c6e507 100644 --- a/man/io_uring_peek_cqe.3 +++ b/man/io_uring_peek_cqe.3 @@ -20,7 +20,7 @@ queue belonging to the .I ring param, if one is readily available. On successful return, .I cqe_ptr -param is filled with a valud CQE entry. +param is filled with a valid CQE entry. This function does not enter the kernel to wait for an event, an event is only returned if it's already available in the CQ ring. diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 970b187..779bcd9 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_prep_accept 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_accept - prepare a accept request +io_uring_prep_accept - prepare an accept request .fi .SH SYNOPSIS .nf @@ -41,7 +41,7 @@ and using modifier flags in For a direct descriptor accept request, the offset is specified by the .I file_index argument. Direct descriptors are io_uring private file descriptors. They -avoid some of the overhead associated with thread shared file tables, and +avoid some of the overhead associated with thread shared file tables and can be used in any io_uring request that takes a file descriptor. To do so, .B IOSQE_FIXED_FILE must be set in the SQE diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index 0a35e9f..eac1603 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -29,8 +29,8 @@ in length to update that amount of previously registered files starting at offset .I offset. -One a previously registered file is updated with a new one, the existing -entry is updated the removed from the table. This operation is equivalent to +Once a previously registered file is updated with a new one, the existing +entry is updated and then removed from the table. This operation is equivalent to first unregistering that entry and then inserting a new one, just bundled into one combined operation. diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index 68699cb..a68121f 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -10,7 +10,7 @@ io_uring_prep_msg_ring - send a message to another ring .nf .BR "#include " .PP -.BI "void io_uring_msg_ring(struct io_uring_sqe *" sqe "," +.BI "void io_uring_prep_msg_ring(struct io_uring_sqe *" sqe "," .BI " int " fd "," .BI " unsigned int " len "," .BI " __u64 " data "," diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3 index b18a6d9..bcfe4d8 100644 --- a/man/io_uring_prep_provide_buffers.3 +++ b/man/io_uring_prep_provide_buffers.3 @@ -54,13 +54,13 @@ field. Different buffer group IDs can be used by the application to have different sizes or types of buffers available. Once a buffer has been consumed for an operation, it is no longer known to io_uring. It must be re-provided if so -desired, or freed by the application if no longer needed. +desired or freed by the application if no longer needed. The buffer IDs are internally tracked from .I bid and sequentially ascending from that value. If .B 16 -buffers are provided start with an initial +buffers are provided and start with an initial .I bid of 0, then the buffer IDs will range from .B 0..15. diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index 3433c20..2d8dcd9 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -33,15 +33,16 @@ at the specified and with the buffer matching the registered index of .I buf_index. -This work just like +This works just like .B io_uring_prep_read(3) -except it requires the user of buffers that have been registered with -.B io_uring_register_buffers(3). The +except it requires the use of buffers that have been registered with +.B io_uring_register_buffers(3). +The .I buf and .I nbytes arguments must fall within a region specificed by -.I buf_index. +.I buf_index in the previously registered buffer. The buffer need not be aligned with the start of the registered buffer. diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3 index 6827131..8aea3c1 100644 --- a/man/io_uring_prep_splice.3 +++ b/man/io_uring_prep_splice.3 @@ -17,7 +17,7 @@ io_uring_prep_splice - prepare an splice request .BI " int " fd_out "," .BI " int64_t " off_out "," .BI " unsigned int " nbytes "," -.BI " int " splice_flags ");" +.BI " unsigned int " splice_flags ");" .PP .SH DESCRIPTION .PP diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3 index 086bc18..8b41a6f 100644 --- a/man/io_uring_prep_tee.3 +++ b/man/io_uring_prep_tee.3 @@ -15,7 +15,7 @@ io_uring_prep_tee - prepare a tee request .BI " int " fd_in "," .BI " int " fd_out "," .BI " unsigned int " nbytes "," -.BI " int " splice_flags ");" +.BI " unsigned int " splice_flags ");" .PP .SH DESCRIPTION .PP @@ -29,7 +29,7 @@ and as output the file descriptor duplicating .I nbytes bytes worth of data. -.I flags +.I splice_flags are modifier flags for the operation. See .BR tee (2) for the generic splice flags. diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 index fb2a07c..38c4bf5 100644 --- a/man/io_uring_prep_timeout.3 +++ b/man/io_uring_prep_timeout.3 @@ -28,7 +28,7 @@ completion entries. The .I flags argument holds modifier flags for the request. -This request type can either be used as a timeout waking anyone sleeping +This request type can be used as a timeout waking anyone sleeping for events on the CQ ring. The .I flags argument may contain: @@ -45,7 +45,7 @@ The boottime clock source should be used. The realtime clock source should be used. .TP .B IORING_TIMEOUT_ETIME_SUCCESS -Consider an expirted timeout a success in terms of the posted completion. +Consider an expired timeout a success in terms of the posted completion. Normally a timeout that triggers would return in a .B -ETIME CQE diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 index b35e1f0..a52ba86 100644 --- a/man/io_uring_prep_timeout_update.3 +++ b/man/io_uring_prep_timeout_update.3 @@ -48,7 +48,7 @@ The boottime clock source should be used. The realtime clock source should be used. .TP .B IORING_TIMEOUT_ETIME_SUCCESS -Consider an expirted timeout a success in terms of the posted completion. +Consider an expired timeout a success in terms of the posted completion. Normally a timeout that triggers would return in a .B -ETIME CQE diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 817717d..c935f8b 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -36,7 +36,7 @@ incremented by the number of bytes written. See .BR write (2) for more details. Note that for an async API, reading and updating the current file offset may result in unpredictable behavior, unless access -to the file is serialized. It is not encouraged to use this feature, if it's +to the file is serialized. It is not encouraged to use this feature if it's possible to provide the desired IO offset from the application or library. On files that are not capable of seeking, the offset is ignored. diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index c9729b4..77143ca 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -29,19 +29,19 @@ to start writing from the buffer .I buf at the specified -.I offset, +.I offset and with the buffer matching the registered index of .I buf_index. -This work just like +This works just like .B io_uring_prep_write(3) -except it requires the user of buffers that have been registered with +except it requires the use of buffers that have been registered with .B io_uring_register_buffers(3). The .I buf and .I nbytes arguments must fall within a region specificed by -.I buf_index. +.I buf_index in the previously registered buffer. The buffer need not be aligned with the start of the registered buffer. diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 806f4e5..ff1a6d5 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -38,7 +38,7 @@ incremented by the number of bytes written. See .BR write (2) for more details. Note that for an async API, reading and updating the current file offset may result in unpredictable behavior, unless access -to the file is serialized. It is not encouraged to use this feature, if it's +to the file is serialized. It is not encouraged to use this feature if it's possible to provide the desired IO offset from the application or library. On files that are not capable of seeking, the offset is ignored. diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index cceae97..cc646f3 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -65,7 +65,7 @@ incremented by the number of bytes written. See .BR write (2) for more details. Note that for an async API, reading and updating the current file offset may result in unpredictable behavior, unless access -to the file is serialized. It is not encouraged to use this feature, if it's +to the file is serialized. It is not encouraged to use this feature if it's possible to provide the desired IO offset from the application or library. On files that are not capable of seeking, the offset is ignored. diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index 807d8b4..d2c4d47 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -35,13 +35,13 @@ for the SQ ring. This is adequate for regular file or storage workloads, but may be too small networked workloads. The SQ ring entries do not impose a limit on the number of in-flight requests that the ring can support, it merely limits the number that can be submitted to the kernel in one go (batch). if the CQ -ring overflows, eg more entries are generated than fits in the ring before the +ring overflows, e.g. more entries are generated than fits in the ring before the application can reap them, then the ring enters a CQ ring overflow state. This is indicated by .B IORING_SQ_CQ_OVERFLOW being set in the SQ ring flags. Unless the kernel runs out of available memory, entries are not dropped, but it is a much slower completion path and will slow -down request processing. For that reason it should be avoided, and the CQ +down request processing. For that reason it should be avoided and the CQ ring sized appropriately for the workload. Setting .I cq_entries in @@ -59,7 +59,7 @@ will point to the shared memory containing the io_uring queues. On failure is returned. .I flags -will be passed through to the io_uring_setup syscall (see +will be passed through to the io_uring_setup syscall (see .BR io_uring_setup (2)). If the diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index 689de9d..ce5ca4c 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -28,8 +28,8 @@ fixed buffers functions. Registered buffers is an optimization that is useful in conjunction with .B O_DIRECT -reads and writes, where maps the specified range into the kernel once when -the buffer is registered, rather than doing a map and unmap for each IO +reads and writes, where it maps the specified range into the kernel once when +the buffer is registered rather than doing a map and unmap for each IO every time IO is performed to that region. Additionally, it also avoids manipulating the page reference counts for each IO. diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 index 93a41f3..10ed8d3 100644 --- a/man/io_uring_sqe_set_flags.3 +++ b/man/io_uring_sqe_set_flags.3 @@ -46,7 +46,7 @@ last SQE in a submission has this flag set, it will still terminate the current chain. This flag has no effect on previous SQE submissions, nor does it impact SQEs that are outside of the chain tail. This means that multiple chains can be executing in parallel, or chains and individual SQEs. Only members inside the -chain are serialized. A chain of SQEs will be broken, if any request in that +chain are serialized. A chain of SQEs will be broken if any request in that chain ends in error. .TP .B IOSQE_IO_DRAIN diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 index 2fd22ba..299d7b1 100644 --- a/man/io_uring_submit_and_wait_timeout.3 +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -26,7 +26,7 @@ and waits for .I wait_nr completion events or until the timeout .I ts -expires.The completion events are stored in the +expires. The completion events are stored in the .I cqe_ptr array. The .I sigmask -- cgit v1.2.3 From 706bd23d05bd656ba0aca5974ebcb03d7610e6e9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 8 Apr 2022 07:13:54 -0600 Subject: man/io_uring_register_ring_fd.3: try to improve NOTES section Threaded applications can use this optimization, but they cannot use it if they share any given ring between multiple threads. Link: https://github.com/axboe/liburing/issues/559 Signed-off-by: Jens Axboe --- man/io_uring_register_ring_fd.3 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3 index 0e872bd..144262f 100644 --- a/man/io_uring_register_ring_fd.3 +++ b/man/io_uring_register_ring_fd.3 @@ -35,9 +35,10 @@ for restrictions when a ring is shared. .SH NOTES When the ring descriptor is registered, it is stored internally in the .I struct io_uring -structure. If an application shares this structure between threads, then this -optimization cannot be used as the threads may get different values for the -registered descriptor. +structure. For applications that share a ring between threads, for example +having one thread do submits and another reap events, then this optimization +cannot be used as each thread may have a different index for the registered +ring fd. .SH RETURN VALUE Returns 1 on success, indicating that one file descriptor was registered, or -- cgit v1.2.3 From 52dcdbba35c828d425ce5a0b5228b0584f588fbb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 9 Apr 2022 09:27:07 -0600 Subject: src/queue: protect io_uring_get_sqe() with LIBURING_INTERNAL This isn't important to liburing itself, but may be to users that do odd things like include this file. And it makes it consistent with the exported header. Fixes: https://github.com/axboe/liburing/issues/560 Signed-off-by: Jens Axboe --- src/queue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/queue.c b/src/queue.c index 2f85756..856d270 100644 --- a/src/queue.c +++ b/src/queue.c @@ -388,10 +388,12 @@ int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr) return __io_uring_submit_and_wait(ring, wait_nr); } +#ifdef LIBURING_INTERNAL struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) { return _io_uring_get_sqe(ring); } +#endif int __io_uring_sqring_wait(struct io_uring *ring) { -- cgit v1.2.3 From c47b44afb686d794f8ed62feb77e9c42431c8444 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 11 Apr 2022 14:52:59 -0600 Subject: test/timeout: fix exec-target naming A previous commit renamed all test targets to foo.t, but didn't update the timeout test case. Hence it now tries to exec something that isn't there and rightfully complains about it: Running test timeout.t Can't find exec-target, skipping Update the test to use the right target. Fixes: f200b5bba701 ("test/Makefile: Append `.t` to the test binary") Signed-off-by: Jens Axboe --- test/timeout.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/timeout.c b/test/timeout.c index 8c35b00..2fd4736 100644 --- a/test/timeout.c +++ b/test/timeout.c @@ -1179,7 +1179,7 @@ static int fill_exec_target(char *dst, char *path) struct stat sb; /* - * Should either be ./exec-target or test/exec-target + * Should either be ./exec-target.t or test/exec-target.t */ sprintf(dst, "%s", path); return stat(dst, &sb); @@ -1193,8 +1193,8 @@ static int test_timeout_link_cancel(void) pid_t p; int ret, i, wstatus; - if (fill_exec_target(prog_path, "./exec-target") && - fill_exec_target(prog_path, "test/exec-target")) { + if (fill_exec_target(prog_path, "./exec-target.t") && + fill_exec_target(prog_path, "test/exec-target.t")) { fprintf(stdout, "Can't find exec-target, skipping\n"); return 0; } -- cgit v1.2.3 From 415c62fca6b8014bf9b03517c4d6e0e2e7ad02a9 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 14 Apr 2022 07:36:51 +0100 Subject: Revert "make: let src/Makefile set *dir vars properly" This reverts commit 9236f53a8ffe96cc2430f7131bbcba5756b97bc2. "make install DESTDIR=..." specifies a root directory where files are installed. For example, includedir=/usr/include DESTDIR=/a should install header files into /a/usr/include. Commit 9236f53a8ffe removed the includedir=, etc arguments on the make command-line in ./Makefile, leaving only prefix=$(DESTDIR)$(prefix). It claimed "prefix suffice for setting *dir variables in src/Makefile" but this is incorrect. "make install DESTDIR=..." now has no effect and files are not installed with a DESTDIR prefix. The GNU make manual 9.5 Overriding Variables says: all ordinary assignments of the same variable in the makefile are ignored; we say they have been overridden by the command line argument. This explains why it was necessary to set includedir=, etc on the make command-line in ./Makefile. We need to override these variables with DESTDIR from the command-line so they are not clobbered in src/Makefile when config-host.mak is included. Cc: Paymon MARANDI Signed-off-by: Stefan Hajnoczi Link: https://lore.kernel.org/r/20220414063651.81341-1-stefanha@redhat.com Signed-off-by: Jens Axboe --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index d6f8520..28c0fd8 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,9 @@ endif install: $(NAME).pc @$(MAKE) -C src install prefix=$(DESTDIR)$(prefix) \ + includedir=$(DESTDIR)$(includedir) \ + libdir=$(DESTDIR)$(libdir) \ + libdevdir=$(DESTDIR)$(libdevdir) \ relativelibdir=$(relativelibdir) $(INSTALL) -D -m 644 $(NAME).pc $(DESTDIR)$(libdevdir)/pkgconfig/$(NAME).pc $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man2 -- cgit v1.2.3 From b418e563026380ee697c7cf9d9fbb26ea62d6cb8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 14 Apr 2022 11:17:34 -0600 Subject: io_uring.h: add IORING_FEAT_LINKED_FILE If this is set in features, applications can rely on file assignments being done sanely in deferred execution setups (like links, or drain). Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index d858977..bfb3548 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -300,6 +300,7 @@ struct io_uring_params { #define IORING_FEAT_NATIVE_WORKERS (1U << 9) #define IORING_FEAT_RSRC_TAGS (1U << 10) #define IORING_FEAT_CQE_SKIP (1U << 11) +#define IORING_FEAT_LINKED_FILE (1U << 12) /* * io_uring_register(2) opcodes and arguments -- cgit v1.2.3 From 7cea31e742c175b8df2895b57f472b49ff514ee0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 14 Apr 2022 11:22:51 -0600 Subject: man/io_uring_setup.2: document recent FEAT flag additions The man page was missing IORING_FEAT_CQE_SKIP and IORING_FEAT_LINKED_FILE, add an explanation for them. Signed-off-by: Jens Axboe --- man/io_uring_setup.2 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index c54c5da..f3911af 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -337,6 +337,25 @@ If this flag is set, then io_uring supports a variety of features related to fixed files and buffers. In particular, it indicates that registered buffers can be updated in-place, whereas before the full set would have to be unregistered first. Available since kernel 5.13. +.TP +.B IORING_FEAT_CQE_SKIP +If this flag is set, then io_uring supports setting +.B IOSQE_CQE_SKIP_SUCCESS +in the submitted SQE, indicating that no CQE should be generated for this +SQE if it executes normally. If an error happens processing the SQE, a +CQE with the appropriate error value will still be generated. Available since +kernel 5.17. +.TP +.B IORING_FEAT_LINKED_FILE +If this flag is set, then io_uring supports sane assignment of files for SQEs +that have dependencies. For example, if a chain of SQEs are submitted with +.B IOSQE_IO_LINK, +then kernels without this flag will prepare the file for each link upfront. +If a previous link opens a file with a known index, eg if direct descriptors +are used with open or accept, then file assignment needs to happen post +execution of that SQE. If this flag is set, then the kernel will defer +file assignment until execution of a given request is started. Available since +kernel 5.17. .PP The rest of the fields in the -- cgit v1.2.3 From f315941786b574f7586dbee4096c940610755141 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 15 Apr 2022 04:03:51 +0700 Subject: test/rw_merge_test: Fix the wrong assertion condition and unlink testfile The following code: ``` ret = pipe(pipe1); assert(!ret); fd = open("testfile", O_RDWR | O_CREAT, 0644); assert(ret >= 0); // wrong assertion condition here ``` is wrong, we should check the @fd after open(), not @ret. While in there, add unlink("testfile") to make the "git status" clean after running this test. Fixes: d731f67819523f76520994b8408a76da4ec30309 ("add test case for 5.4 io merge regression logic") Signed-off-by: Ammar Faizi --- test/rw_merge_test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/rw_merge_test.c b/test/rw_merge_test.c index 43feed4..03f6467 100644 --- a/test/rw_merge_test.c +++ b/test/rw_merge_test.c @@ -35,7 +35,8 @@ int main(int argc, char *argv[]) assert(!ret); fd = open("testfile", O_RDWR | O_CREAT, 0644); - assert(ret >= 0); + assert(fd >= 0); + unlink("testfile"); ret = ftruncate(fd, 4096); assert(!ret); -- cgit v1.2.3 From 7e3f7d6030fb6ce0872b876147d29fe230e7b2ba Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 15 Apr 2022 04:15:47 +0700 Subject: test/35fa71a030ca: Fix `-Wunused-but-set-variable` warning from clang-15 clang-15 correctly warns: ``` 35fa71a030ca.c:241:7: error: variable 'iter' set but not used \ [-Werror,-Wunused-but-set-variable] int iter; ^ 1 error generated. make[1]: *** [Makefile:210: 35fa71a030ca.t] Error 1 ``` Remove the iter variable here, it's not used. Fixes: 78f59df3339191a500d9a27e2fe9d2eea888a2e0 ("Add regression test cases for three recent issues") Signed-off-by: Ammar Faizi --- test/35fa71a030ca.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/35fa71a030ca.c b/test/35fa71a030ca.c index f83cc9d..9a6ddb6 100644 --- a/test/35fa71a030ca.c +++ b/test/35fa71a030ca.c @@ -238,8 +238,7 @@ static void execute_one(void); static void loop(void) { - int iter; - for (iter = 0;; iter++) { + for (;;) { int pid = fork(); if (pid < 0) exit(1); -- cgit v1.2.3 From 045b8c5b183859fbc481ec7ab6b818442cc57ab0 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 15 Apr 2022 04:21:23 +0700 Subject: test/submit-reuse: Fix `-Wunused-but-set-variable` warning from clang-15 clang-15 correctly warns: ``` submit-reuse.c:29:6: error: variable 'i' set but not used \ [-Werror,-Wunused-but-set-variable] int i = 0; ^ 1 error generated. make[1]: *** [Makefile:210: submit-reuse.t] Error 1 ``` Remove the i variable here, it's not used. Fixes: ad543701a816d0d84383a8aafb1ce27ee2f93053 ("Add test case for -EFAULT triggered by iov reuse") Signed-off-by: Ammar Faizi --- test/submit-reuse.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/submit-reuse.c b/test/submit-reuse.c index ca30e98..d5ccdd4 100644 --- a/test/submit-reuse.c +++ b/test/submit-reuse.c @@ -26,13 +26,11 @@ struct thread_data { static void *flusher(void *__data) { struct thread_data *data = __data; - int i = 0; while (!data->do_exit) { posix_fadvise(data->fd1, 0, FILE_SIZE, POSIX_FADV_DONTNEED); posix_fadvise(data->fd2, 0, FILE_SIZE, POSIX_FADV_DONTNEED); usleep(10); - i++; } return NULL; -- cgit v1.2.3 From cdc632f1145f4862bbfe443b4329cc82bd847469 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 15 Apr 2022 19:43:37 -0600 Subject: io_uring: add new cancel flags Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index bfb3548..2816f6c 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -191,6 +191,16 @@ enum { #define IORING_POLL_UPDATE_EVENTS (1U << 1) #define IORING_POLL_UPDATE_USER_DATA (1U << 2) +/* + * ASYNC_CANCEL flags. + * + * IORING_ASYNC_CANCEL_ALL Cancel all requests that match the given key + * IORING_ASYNC_CANCEL_FD Key off 'fd' for cancelation rather than the + * request 'user_data' + */ +#define IORING_ASYNC_CANCEL_ALL (1U << 0) +#define IORING_ASYNC_CANCEL_FD (1U << 1) + /* * IO completion data structure (Completion Queue Entry) */ -- cgit v1.2.3 From aa801a8541154ae38559b14bc24cd4a3f5939e80 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 15 Apr 2022 19:43:47 -0600 Subject: liburing.h: add io_uring_prep_cancel_fd() This sets up the cancelation request to be fd based. Signed-off-by: Jens Axboe --- src/include/liburing.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 5c03061..798dc1c 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -510,6 +510,13 @@ static inline void io_uring_prep_cancel(struct io_uring_sqe *sqe, sqe->cancel_flags = (__u32) flags; } +static inline void io_uring_prep_cancel_fd(struct io_uring_sqe *sqe, int fd, + unsigned int flags) +{ + io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, fd, NULL, 0, 0); + sqe->cancel_flags = (__u32) flags | IORING_ASYNC_CANCEL_FD; +} + static inline void io_uring_prep_link_timeout(struct io_uring_sqe *sqe, struct __kernel_timespec *ts, unsigned flags) -- cgit v1.2.3 From 5579f1ebdc7e1d0b4370bdeb9a03dab4d95e8bff Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 15 Apr 2022 19:44:17 -0600 Subject: test/poll-cancel-all: test issuing CANCEL_ALL | CANCEL_FD Not complete yet, but tests the basic functionality of canceling based on a file descriptor and canceling all requests pending with just a single cancelation request. Signed-off-by: Jens Axboe --- test/Makefile | 1 + test/poll-cancel-all.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 test/poll-cancel-all.c diff --git a/test/Makefile b/test/Makefile index cb7e15e..56f13c4 100644 --- a/test/Makefile +++ b/test/Makefile @@ -108,6 +108,7 @@ test_srcs := \ pipe-reuse.c \ poll.c \ poll-cancel.c \ + poll-cancel-all.c \ poll-cancel-ton.c \ poll-link.c \ poll-many.c \ diff --git a/test/poll-cancel-all.c b/test/poll-cancel-all.c new file mode 100644 index 0000000..6ad835f --- /dev/null +++ b/test/poll-cancel-all.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: Test IORING_ASYNC_CANCEL_{ALL,FD} + * + */ +#include +#include +#include +#include +#include +#include + +#include "liburing.h" + +int main(int argc, char *argv[]) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + int ret, i, fd[2]; + + if (argc > 1) + return 0; + + if (pipe(fd) < 0) { + perror("pipe"); + return 1; + } + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "child: ring setup failed: %d\n", ret); + return 1; + } + + for (i = 0; i < 8; i++) { + sqe = io_uring_get_sqe(&ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + return 1; + } + + io_uring_prep_poll_add(sqe, fd[0], POLLIN); + sqe->user_data = i + 1; + } + + ret = io_uring_submit(&ring); + if (ret < 8) { + fprintf(stderr, "child: sqe submit failed: %d\n", ret); + return 1; + } + + sqe = io_uring_get_sqe(&ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + return 1; + } + + /* + * Mark CANCEL_ALL to cancel all matching the key, and use + * CANCEL_FD to cancel requests matching the specified fd. + * This should cancel all the pending poll requests on the pipe + * input. + */ + io_uring_prep_cancel_fd(sqe, fd[0], IORING_ASYNC_CANCEL_ALL); + sqe->user_data = 100; + + ret = io_uring_submit(&ring); + if (ret < 1) { + fprintf(stderr, "child: sqe submit failed: %d\n", ret); + return 1; + } + + for (i = 0; i < 9; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait=%d\n", ret); + return 1; + } + switch (cqe->user_data) { + case 100: + if (cqe->res != 8) { + fprintf(stderr, "canceled %d\n", cqe->res); + return 1; + } + break; + case 1 ... 8: + if (cqe->res != -ECANCELED) { + fprintf(stderr, "poll res %d\n", cqe->res); + return 1; + } + break; + default: + fprintf(stderr, "invalid user_data %lu\n", + (unsigned long) cqe->user_data); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + } + + return 0; +} -- cgit v1.2.3 From 8b205b8b82104589b869364bc11e1d9156be8dfa Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 16 Apr 2022 07:38:19 -0600 Subject: man/io_uring_register.2: clarify eventfd notification counts We may see both spurious eventfd notifications (eg an eventfd notification was posted, yet no CQEs are available), as well as batched notifications where a batch of CQEs are posted but only a single eventfd notification generated. Signed-off-by: Jens Axboe --- man/io_uring_register.2 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/man/io_uring_register.2 b/man/io_uring_register.2 index cb63e6b..1e91caf 100644 --- a/man/io_uring_register.2 +++ b/man/io_uring_register.2 @@ -328,7 +328,13 @@ registered through this operation. .I arg must contain a pointer to the eventfd file descriptor, and .I nr_args -must be 1. Available since 5.2. +must be 1. Note that while io_uring generally takes care to avoid spurious +events, they can occur. Similarly, batched completions of CQEs may only trigger +a single eventfd notification even if multiple CQEs are posted. The application +should make no assumptions on number of events being available having a direct +correlation to eventfd notifications posted. An eventfd notification must thus +only be treated as a hint to check the CQ ring for completions. Available since +5.2. An application can temporarily disable notifications, coming through the registered eventfd, by setting the -- cgit v1.2.3 From 6e3bbbdec6f8602f77dbc3b3c13f87024625a9e8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 16 Apr 2022 07:51:06 -0600 Subject: Add eventfd register/unregister man pages Signed-off-by: Jens Axboe --- man/io_uring_register_eventfd.3 | 49 +++++++++++++++++++++++++++++++++++ man/io_uring_register_eventfd_async.3 | 1 + man/io_uring_unregister_eventfd.3 | 1 + 3 files changed, 51 insertions(+) create mode 100644 man/io_uring_register_eventfd.3 create mode 120000 man/io_uring_register_eventfd_async.3 create mode 120000 man/io_uring_unregister_eventfd.3 diff --git a/man/io_uring_register_eventfd.3 b/man/io_uring_register_eventfd.3 new file mode 100644 index 0000000..c88c3bf --- /dev/null +++ b/man/io_uring_register_eventfd.3 @@ -0,0 +1,49 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_register_eventfd 3 "April 16, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_register_eventfd - register an eventfd with a ring + +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_register_eventfd(struct io_uring *" ring "," +.BI " int " fd ");" +.BI "int io_uring_register_eventfd_async(struct io_uring *" ring "," +.BI " int " fd ");" +.BI "int io_uring_unregister_eventfd(struct io_uring *" ring ");" + +.SH DESCRIPTION +.PP +io_uring_register_eventfd() registers the eventfd file descriptor +.I fd +with the ring identified by +.I ring. + +Whenever completions are posted to the CQ ring, an eventfd notification +is generated with the registered eventfd descriptor. If +.BR io_uring_register_eventfd_async (3) +is used, only events that completed out-of-line will trigger a notification. + +It notifications are no longer desired, +.BR io_uring_unregister_eventfd (3) +may be called to remove the eventfd registration. No eventfd argument is +needed, as a ring can only have a single eventfd registered. + +.SH NOTES +While io_uring generally takes care to avoid spurious events, they can occur. +Similarly, batched completions of CQEs may only trigger a single eventfd +notification even if multiple CQEs are posted. The application should make no +assumptions on number of events being available having a direct correlation to +eventfd notifications posted. An eventfd notification must thus only be treated +as a hint to check the CQ ring for completions. +.SH RETURN VALUE +Returns 0 on success, or +or +.B -errno +on error. +.SH SEE ALSO +.BR eventfd (2) diff --git a/man/io_uring_register_eventfd_async.3 b/man/io_uring_register_eventfd_async.3 new file mode 120000 index 0000000..6659957 --- /dev/null +++ b/man/io_uring_register_eventfd_async.3 @@ -0,0 +1 @@ +io_uring_register_eventfd.3 \ No newline at end of file diff --git a/man/io_uring_unregister_eventfd.3 b/man/io_uring_unregister_eventfd.3 new file mode 120000 index 0000000..6659957 --- /dev/null +++ b/man/io_uring_unregister_eventfd.3 @@ -0,0 +1 @@ +io_uring_register_eventfd.3 \ No newline at end of file -- cgit v1.2.3 From 67b1d7ad568cec6cc4216fc55513cd17bf66e950 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 16 Apr 2022 14:21:07 -0600 Subject: test/poll-cancel-all: add test case canceling a subset of pending Have two different files active, cancel each set separately and check we get the expected results. Signed-off-by: Jens Axboe --- test/poll-cancel-all.c | 222 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 197 insertions(+), 25 deletions(-) diff --git a/test/poll-cancel-all.c b/test/poll-cancel-all.c index 6ad835f..f16ffaa 100644 --- a/test/poll-cancel-all.c +++ b/test/poll-cancel-all.c @@ -12,29 +12,14 @@ #include "liburing.h" -int main(int argc, char *argv[]) +static int test1(struct io_uring *ring, int *fd) { struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; - struct io_uring ring; - int ret, i, fd[2]; - - if (argc > 1) - return 0; - - if (pipe(fd) < 0) { - perror("pipe"); - return 1; - } - - ret = io_uring_queue_init(8, &ring, 0); - if (ret) { - fprintf(stderr, "child: ring setup failed: %d\n", ret); - return 1; - } + int ret, i; for (i = 0; i < 8; i++) { - sqe = io_uring_get_sqe(&ring); + sqe = io_uring_get_sqe(ring); if (!sqe) { fprintf(stderr, "get sqe failed\n"); return 1; @@ -44,13 +29,13 @@ int main(int argc, char *argv[]) sqe->user_data = i + 1; } - ret = io_uring_submit(&ring); + ret = io_uring_submit(ring); if (ret < 8) { - fprintf(stderr, "child: sqe submit failed: %d\n", ret); + fprintf(stderr, "sqe submit failed: %d\n", ret); return 1; } - sqe = io_uring_get_sqe(&ring); + sqe = io_uring_get_sqe(ring); if (!sqe) { fprintf(stderr, "get sqe failed\n"); return 1; @@ -62,17 +47,19 @@ int main(int argc, char *argv[]) * This should cancel all the pending poll requests on the pipe * input. */ - io_uring_prep_cancel_fd(sqe, fd[0], IORING_ASYNC_CANCEL_ALL); + io_uring_prep_cancel(sqe, 0, IORING_ASYNC_CANCEL_ALL); + sqe->cancel_flags |= IORING_ASYNC_CANCEL_FD; + sqe->fd = fd[0]; sqe->user_data = 100; - ret = io_uring_submit(&ring); + ret = io_uring_submit(ring); if (ret < 1) { fprintf(stderr, "child: sqe submit failed: %d\n", ret); return 1; } for (i = 0; i < 9; i++) { - ret = io_uring_wait_cqe(&ring, &cqe); + ret = io_uring_wait_cqe(ring, &cqe); if (ret) { fprintf(stderr, "wait=%d\n", ret); return 1; @@ -95,7 +82,192 @@ int main(int argc, char *argv[]) (unsigned long) cqe->user_data); return 1; } - io_uring_cqe_seen(&ring, cqe); + io_uring_cqe_seen(ring, cqe); + } + + return 0; +} + +static int test2(struct io_uring *ring, int *fd) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + int ret, i, fd2[2]; + + if (pipe(fd2) < 0) { + perror("pipe"); + return 1; + } + + for (i = 0; i < 8; i++) { + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + if (!(i & 1)) + io_uring_prep_poll_add(sqe, fd[0], POLLIN); + else + io_uring_prep_poll_add(sqe, fd2[0], POLLIN); + sqe->user_data = i & 1; + } + + ret = io_uring_submit(ring); + if (ret < 8) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + /* + * Mark CANCEL_ALL to cancel all matching the key, and use + * CANCEL_FD to cancel requests matching the specified fd. + * This should cancel all the pending poll requests on the pipe + * input. + */ + io_uring_prep_cancel(sqe, 0, IORING_ASYNC_CANCEL_ALL); + sqe->cancel_flags |= IORING_ASYNC_CANCEL_FD; + sqe->fd = fd[0]; + sqe->user_data = 100; + + ret = io_uring_submit(ring); + if (ret < 1) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + for (i = 0; i < 5; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "wait=%d\n", ret); + goto err; + } + switch (cqe->user_data) { + case 100: + if (cqe->res != 4) { + fprintf(stderr, "canceled %d\n", cqe->res); + goto err; + } + break; + case 0: + if (cqe->res != -ECANCELED) { + fprintf(stderr, "poll res %d\n", cqe->res); + goto err; + } + break; + default: + fprintf(stderr, "invalid user_data %lu\n", + (unsigned long) cqe->user_data); + goto err; + } + io_uring_cqe_seen(ring, cqe); + } + + usleep(1000); + + /* + * Should not have any pending CQEs now + */ + ret = io_uring_peek_cqe(ring, &cqe); + if (!ret) { + fprintf(stderr, "Unexpected extra cancel cqe\n"); + goto err; + } + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + /* + * Mark CANCEL_ALL to cancel all matching the key, and use + * CANCEL_FD to cancel requests matching the specified fd. + * This should cancel all the pending poll requests on the pipe + * input. + */ + io_uring_prep_cancel(sqe, 0, IORING_ASYNC_CANCEL_ALL); + sqe->cancel_flags |= IORING_ASYNC_CANCEL_FD; + sqe->fd = fd2[0]; + sqe->user_data = 100; + + ret = io_uring_submit(ring); + if (ret < 1) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + + for (i = 0; i < 5; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "wait=%d\n", ret); + goto err; + } + switch (cqe->user_data) { + case 100: + if (cqe->res != 4) { + fprintf(stderr, "canceled %d\n", cqe->res); + goto err; + } + break; + case 1: + if (cqe->res != -ECANCELED) { + fprintf(stderr, "poll res %d\n", cqe->res); + goto err; + } + break; + default: + fprintf(stderr, "invalid user_data %lu\n", + (unsigned long) cqe->user_data); + goto err; + } + io_uring_cqe_seen(ring, cqe); + } + + close(fd2[0]); + close(fd2[1]); + return 0; +err: + close(fd2[0]); + close(fd2[1]); + return 1; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + int ret, fd[2]; + + if (argc > 1) + return 0; + + if (pipe(fd) < 0) { + perror("pipe"); + return 1; + } + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + ret = test1(&ring, fd); + if (ret) { + fprintf(stderr, "test1 failed\n"); + return ret; + } + + ret = test2(&ring, fd); + if (ret) { + fprintf(stderr, "test1 failed\n"); + return ret; } return 0; -- cgit v1.2.3 From 6a504852c2c5fa8af18e54263515ab5723cad2c9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 16 Apr 2022 14:29:35 -0600 Subject: test/poll-cancel-all: abort test if cancel flags not supported Signed-off-by: Jens Axboe --- test/poll-cancel-all.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/poll-cancel-all.c b/test/poll-cancel-all.c index f16ffaa..754ec4f 100644 --- a/test/poll-cancel-all.c +++ b/test/poll-cancel-all.c @@ -12,6 +12,8 @@ #include "liburing.h" +static int no_cancel_flags; + static int test1(struct io_uring *ring, int *fd) { struct io_uring_sqe *sqe; @@ -59,6 +61,8 @@ static int test1(struct io_uring *ring, int *fd) } for (i = 0; i < 9; i++) { + if (no_cancel_flags) + break; ret = io_uring_wait_cqe(ring, &cqe); if (ret) { fprintf(stderr, "wait=%d\n", ret); @@ -66,6 +70,10 @@ static int test1(struct io_uring *ring, int *fd) } switch (cqe->user_data) { case 100: + if (cqe->res == -EINVAL) { + no_cancel_flags = 1; + break; + } if (cqe->res != 8) { fprintf(stderr, "canceled %d\n", cqe->res); return 1; @@ -263,10 +271,12 @@ int main(int argc, char *argv[]) fprintf(stderr, "test1 failed\n"); return ret; } + if (no_cancel_flags) + return 0; ret = test2(&ring, fd); if (ret) { - fprintf(stderr, "test1 failed\n"); + fprintf(stderr, "test2 failed\n"); return ret; } -- cgit v1.2.3 From d02460d876daec91293aa025f0cfb3af59dcccd4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 16 Apr 2022 14:45:38 -0600 Subject: io_uring.h: add IORING_ASYNC_CANCEL_ANY Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 2816f6c..55f8869 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -197,9 +197,11 @@ enum { * IORING_ASYNC_CANCEL_ALL Cancel all requests that match the given key * IORING_ASYNC_CANCEL_FD Key off 'fd' for cancelation rather than the * request 'user_data' + * IORING_ASYNC_CANCEL_ANY Match any request */ #define IORING_ASYNC_CANCEL_ALL (1U << 0) #define IORING_ASYNC_CANCEL_FD (1U << 1) +#define IORING_ASYNC_CANCEL_ANY (1U << 2) /* * IO completion data structure (Completion Queue Entry) -- cgit v1.2.3 From c091b912bc9c6fb64c68c7b0056c4923b327cd9e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 16 Apr 2022 14:45:50 -0600 Subject: test/poll-cancel-all: test IORING_ASYNC_CANCEL_ANY _ANY will match any request, no keys needed. Allows canceling any request on the ring. Signed-off-by: Jens Axboe --- test/poll-cancel-all.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/test/poll-cancel-all.c b/test/poll-cancel-all.c index 754ec4f..c724823 100644 --- a/test/poll-cancel-all.c +++ b/test/poll-cancel-all.c @@ -247,6 +247,100 @@ err: return 1; } +static int test3(struct io_uring *ring, int *fd) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + int ret, i, fd2[2]; + + if (pipe(fd2) < 0) { + perror("pipe"); + return 1; + } + + for (i = 0; i < 8; i++) { + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + if (!(i & 1)) { + io_uring_prep_poll_add(sqe, fd[0], POLLIN); + sqe->flags |= IOSQE_ASYNC; + } else + io_uring_prep_poll_add(sqe, fd2[0], POLLIN); + sqe->user_data = i & 1; + } + + ret = io_uring_submit(ring); + if (ret < 8) { + fprintf(stderr, "child: sqe submit failed: %d\n", ret); + goto err; + } + + usleep(10000); + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + /* + * Mark CANCEL_ALL to cancel all matching the key, and use + * CANCEL_FD to cancel requests matching the specified fd. + * This should cancel all the pending poll requests on the pipe + * input. + */ + io_uring_prep_cancel(sqe, 0, IORING_ASYNC_CANCEL_ALL); + sqe->cancel_flags |= IORING_ASYNC_CANCEL_ANY; + sqe->fd = 0; + sqe->user_data = 100; + + ret = io_uring_submit(ring); + if (ret < 1) { + fprintf(stderr, "child: sqe submit failed: %d\n", ret); + goto err; + } + + for (i = 0; i < 9; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "wait=%d\n", ret); + goto err; + } + switch (cqe->user_data) { + case 100: + if (cqe->res != 8) { + fprintf(stderr, "canceled %d\n", cqe->res); + goto err; + } + break; + case 0: + case 1: + if (cqe->res != -ECANCELED) { + fprintf(stderr, "poll res %d\n", cqe->res); + goto err; + } + break; + default: + fprintf(stderr, "invalid user_data %lu\n", + (unsigned long) cqe->user_data); + goto err; + } + io_uring_cqe_seen(ring, cqe); + } + + close(fd2[0]); + close(fd2[1]); + return 0; +err: + close(fd2[0]); + close(fd2[1]); + return 1; +} + int main(int argc, char *argv[]) { struct io_uring ring; @@ -280,5 +374,11 @@ int main(int argc, char *argv[]) return ret; } + ret = test3(&ring, fd); + if (ret) { + fprintf(stderr, "test3 failed\n"); + return ret; + } + return 0; } -- cgit v1.2.3 From 6977ce1f49d38c496a3781bd2f1d39c6f23b8639 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 16 Apr 2022 18:53:57 -0600 Subject: test/poll-cancel-all: add async read test case Signed-off-by: Jens Axboe --- test/poll-cancel-all.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/test/poll-cancel-all.c b/test/poll-cancel-all.c index c724823..35116f5 100644 --- a/test/poll-cancel-all.c +++ b/test/poll-cancel-all.c @@ -341,6 +341,88 @@ err: return 1; } +static int test4(struct io_uring *ring, int *fd) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + char buffer[32]; + int ret, i; + + for (i = 0; i < 8; i++) { + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + io_uring_prep_read(sqe, fd[0], &buffer, sizeof(buffer), 0); + sqe->flags |= IOSQE_ASYNC; + sqe->user_data = i + 1; + } + + ret = io_uring_submit(ring); + if (ret < 8) { + fprintf(stderr, "child: sqe submit failed: %d\n", ret); + goto err; + } + + usleep(10000); + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + + /* + * Mark CANCEL_ALL to cancel all matching the key, and use + * CANCEL_FD to cancel requests matching the specified fd. + * This should cancel all the pending poll requests on the pipe + * input. + */ + io_uring_prep_cancel(sqe, 0, IORING_ASYNC_CANCEL_ALL); + sqe->cancel_flags |= IORING_ASYNC_CANCEL_ANY; + sqe->fd = 0; + sqe->user_data = 100; + + ret = io_uring_submit(ring); + if (ret < 1) { + fprintf(stderr, "child: sqe submit failed: %d\n", ret); + goto err; + } + + for (i = 0; i < 9; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "wait=%d\n", ret); + goto err; + } + switch (cqe->user_data) { + case 100: + if (cqe->res != 8) { + fprintf(stderr, "canceled %d\n", cqe->res); + goto err; + } + break; + case 1 ... 8: + if (cqe->res != -ECANCELED) { + fprintf(stderr, "poll res %d\n", cqe->res); + goto err; + } + break; + default: + fprintf(stderr, "invalid user_data %lu\n", + (unsigned long) cqe->user_data); + goto err; + } + io_uring_cqe_seen(ring, cqe); + } + + return 0; +err: + return 1; +} + int main(int argc, char *argv[]) { struct io_uring ring; @@ -380,5 +462,11 @@ int main(int argc, char *argv[]) return ret; } + ret = test4(&ring, fd); + if (ret) { + fprintf(stderr, "test4 failed\n"); + return ret; + } + return 0; } -- cgit v1.2.3 From e0aa6fceed8e9a36325ae3d6d83b0dfb73aea2ca Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 17 Apr 2022 10:09:23 +0100 Subject: tests: reduce multicqe_drain waiting time sleep(4) is too long and not needed, wait just for one second, should be good enough. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/5f2ddf9fb44d4b746c12654dad649db1470c2748.1650186365.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/multicqes_drain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/multicqes_drain.c b/test/multicqes_drain.c index ff6fa7d..b16dc52 100644 --- a/test/multicqes_drain.c +++ b/test/multicqes_drain.c @@ -224,7 +224,7 @@ static int test_generic_drain(struct io_uring *ring) goto err; } - sleep(4); + sleep(1); // TODO: randomize event triggerring order for (i = 0; i < max_entry; i++) { if (si[i].op != multi && si[i].op != single) @@ -233,7 +233,7 @@ static int test_generic_drain(struct io_uring *ring) if (trigger_event(pipes[i])) goto err; } - sleep(5); + sleep(1); i = 0; while (!io_uring_peek_cqe(ring, &cqe)) { cqe_data[i] = cqe->user_data; -- cgit v1.2.3 From c1459b2c99f0bb2554d181d9bf55388814add1a5 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 17 Apr 2022 10:09:24 +0100 Subject: tests: extend scm cycle breaking tests Add a test with file ref dependency, which is actually checks that the files are removed and put. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/bf406c7d141b46f1fa94e72b9ba853dd72f27561.1650186365.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/ring-leak.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test/ring-leak.c b/test/ring-leak.c index f8f043c..5b739ad 100644 --- a/test/ring-leak.c +++ b/test/ring-leak.c @@ -131,12 +131,84 @@ static int test_iowq_request_cancel(void) ret = read(fds[0], buffer, 10); if (ret < 0) perror("read"); + close(fds[0]); + return 0; +} + +static int test_scm_cycles(bool update) +{ + char buffer[128]; + struct io_uring ring; + int i, ret; + int sp[2], fds[2], reg_fds[4]; + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) != 0) { + perror("Failed to create Unix-domain socket pair\n"); + return 1; + } + ret = io_uring_queue_init(8, &ring, 0); + if (ret < 0) { + fprintf(stderr, "failed to init io_uring: %s\n", strerror(-ret)); + return ret; + } + if (pipe(fds)) { + perror("pipe"); + return -1; + } + send_fd(sp[0], ring.ring_fd); + + /* register an empty set for updates */ + if (update) { + for (i = 0; i < 4; i++) + reg_fds[i] = -1; + ret = io_uring_register_files(&ring, reg_fds, 4); + if (ret) { + fprintf(stderr, "file_register: %d\n", ret); + return ret; + } + } + + reg_fds[0] = fds[0]; + reg_fds[1] = fds[1]; + reg_fds[2] = sp[0]; + reg_fds[3] = sp[1]; + if (update) { + ret = io_uring_register_files_update(&ring, 0, reg_fds, 4); + if (ret != 4) { + fprintf(stderr, "file_register: %d\n", ret); + return ret; + } + } else { + ret = io_uring_register_files(&ring, reg_fds, 4); + if (ret) { + fprintf(stderr, "file_register: %d\n", ret); + return ret; + } + } + + close(fds[1]); + close(sp[0]); + close(sp[1]); + + /* should unregister files and close the write fd */ + io_uring_queue_exit(&ring); + + /* + * We're trying to wait for the ring to "really" exit, that will be + * done async. For that rely on the registered write end to be closed + * after ring quiesce, so failing read from the other pipe end. + */ + ret = read(fds[0], buffer, 10); + if (ret < 0) + perror("read"); + close(fds[0]); return 0; } int main(int argc, char *argv[]) { int sp[2], pid, ring_fd, ret; + int i; if (argc > 1) return 0; @@ -147,6 +219,18 @@ int main(int argc, char *argv[]) return 1; } + for (i = 0; i < 2; i++) { + bool update = !!(i & 1); + + ret = test_scm_cycles(update); + if (ret) { + fprintf(stderr, "test_scm_cycles() failed %i\n", + update); + return 1; + } + break; + } + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) != 0) { perror("Failed to create Unix-domain socket pair\n"); return 1; -- cgit v1.2.3 From da2f4ce1722b38fcf72641fea0bf6a296f0cfdc0 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 17 Apr 2022 15:29:27 +0100 Subject: tests: add more file registration tests Add tests for file registration failing in the middle of the fd set, and mixing files that need and don't SCM accounting + checking for underflows. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/b868cdd8d996a53a196e9cfb8807d07d318ef876.1650205541.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/file-register.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/test/file-register.c b/test/file-register.c index bd15408..6889dbf 100644 --- a/test/file-register.c +++ b/test/file-register.c @@ -745,7 +745,90 @@ static int test_fixed_removal_ordering(void) return 0; } +/* mix files requiring SCM-accounting and not in a single register */ +static int test_mixed_af_unix(void) +{ + struct io_uring ring; + int i, ret, fds[2]; + int reg_fds[32]; + int sp[2]; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret < 0) { + fprintf(stderr, "failed to init io_uring: %s\n", strerror(-ret)); + return ret; + } + if (pipe(fds)) { + perror("pipe"); + return -1; + } + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) != 0) { + perror("Failed to create Unix-domain socket pair\n"); + return 1; + } + + for (i = 0; i < 16; i++) { + reg_fds[i * 2] = fds[0]; + reg_fds[i * 2 + 1] = sp[0]; + } + + ret = io_uring_register_files(&ring, reg_fds, 32); + if (ret) { + fprintf(stderr, "file_register: %d\n", ret); + return ret; + } + close(fds[0]); + close(fds[1]); + close(sp[0]); + close(sp[1]); + io_uring_queue_exit(&ring); + return 0; +} + +static int test_partial_register_fail(void) +{ + char buffer[128]; + struct io_uring ring; + int ret, fds[2]; + int reg_fds[5]; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret < 0) { + fprintf(stderr, "failed to init io_uring: %s\n", strerror(-ret)); + return ret; + } + if (pipe(fds)) { + perror("pipe"); + return -1; + } + + /* + * Expect register to fail as it doesn't support io_uring fds, shouldn't + * leave any fds referenced afterwards. + */ + reg_fds[0] = fds[0]; + reg_fds[1] = fds[1]; + reg_fds[2] = -1; + reg_fds[3] = ring.ring_fd; + reg_fds[4] = -1; + ret = io_uring_register_files(&ring, reg_fds, 5); + if (!ret) { + fprintf(stderr, "file_register unexpectedly succeeded\n"); + return 1; + } + + /* ring should have fds referenced, can close them */ + close(fds[1]); + + /* confirm that fds[1] is actually close and to ref'ed by io_uring */ + ret = read(fds[0], buffer, 10); + if (ret < 0) + perror("read"); + close(fds[0]); + io_uring_queue_exit(&ring); + return 0; +} int main(int argc, char *argv[]) { @@ -854,5 +937,17 @@ int main(int argc, char *argv[]) return 1; } + ret = test_mixed_af_unix(); + if (ret) { + printf("test_mixed_af_unix failed\n"); + return 1; + } + + ret = test_partial_register_fail(); + if (ret) { + printf("test_partial_register_fail failed\n"); + return ret; + } + return 0; } -- cgit v1.2.3 From 2afb268164ba99ebe720add3632b4051651296b6 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 15 Apr 2022 05:41:38 +0700 Subject: arch/syscall-defs: Use `__NR_mmap2` instead of `__NR_mmap` for x86 32-bit A preparation to add x86 32-bit native syscall support for the nolibc build. On x86 32-bit, the __NR_mmap maps to sys_old_mmap: long sys_old_mmap(struct mmap_arg_struct __user *arg); which only receives one argument and is not suitable with the canonical mmap() definition we use. As such, use __NR_mmap2 that maps to sys_mmap_pgoff: long sys_mmap_pgoff(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff); Note: For __NR_mmap2, the offset must be shifted-right by 12-bit. Co-authored-by: Alviro Iskandar Setiawan Signed-off-by: Alviro Iskandar Setiawan Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220414224001.187778-2-ammar.faizi@intel.com Signed-off-by: Jens Axboe --- src/arch/syscall-defs.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/arch/syscall-defs.h b/src/arch/syscall-defs.h index f79f56a..1e8ae1b 100644 --- a/src/arch/syscall-defs.h +++ b/src/arch/syscall-defs.h @@ -6,8 +6,15 @@ static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { - return (void *) __do_syscall6(__NR_mmap, addr, length, prot, flags, fd, - offset); + int nr; + +#if defined(__i386__) + nr = __NR_mmap2; + offset >>= 12; +#else + nr = __NR_mmap; +#endif + return (void *) __do_syscall6(nr, addr, length, prot, flags, fd, offset); } static inline int __sys_munmap(void *addr, size_t length) -- cgit v1.2.3 From 48342e4c482349718eeecd34b3026d3d6aa78794 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 15 Apr 2022 05:41:39 +0700 Subject: arch/x86/lib: Provide `get_page_size()` function for x86 32-bit A preparation to add nolibc support for x86 32-bit. Provide get_page_size() function for x86 32-bit. x86 32-bit and x86-64, both have the same page size 4K, and they can share the same function definition. Just remove the #ifdef here. Co-authored-by: Alviro Iskandar Setiawan Signed-off-by: Alviro Iskandar Setiawan Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220414224001.187778-3-ammar.faizi@intel.com Signed-off-by: Jens Axboe --- src/arch/x86/lib.h | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/arch/x86/lib.h b/src/arch/x86/lib.h index bacf74e..e6a74f3 100644 --- a/src/arch/x86/lib.h +++ b/src/arch/x86/lib.h @@ -7,26 +7,9 @@ #ifndef LIBURING_ARCH_X86_LIB_H #define LIBURING_ARCH_X86_LIB_H -#if defined(__x86_64__) - static inline long get_page_size(void) { return 4096; } -#else /* #if defined(__x86_64__) */ - -/* - * For x86 (32-bit), fallback to libc wrapper. - * We can't use CONFIG_NOLIBC for x86 (32-bit) at the moment. - * - * TODO: Add x86 (32-bit) nolibc support. - */ -#ifdef CONFIG_NOLIBC - #error "x86 (32-bit) is currently not supported for nolibc builds" -#endif -#include "../generic/lib.h" - -#endif /* #if defined(__x86_64__) */ - #endif /* #ifndef LIBURING_ARCH_X86_LIB_H */ -- cgit v1.2.3 From b7d8dd8bbf5b8550c8a0c1ed70431cd8050709f0 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Fri, 15 Apr 2022 05:41:40 +0700 Subject: arch/x86/syscall: Add x86 32-bit native syscall support Create __do_syscall{0..6} macros for x86 32-bit. Unlike x86-64, only use these macros when CONFIG_NOLIBC is enabled for a 32-bit build. The reason is that the libc syscall wrapper can do better in 32-bit. libc syscall wrapper can dispatch the best syscall instruction that the environment is supported, there are at least two variants of syscall instruction for x86 32-bit, they are: `int $0x80` and `sysenter`. The `int $0x80` instruction is always available, but `sysenter` is not, it relies on VDSO. liburing always uses `int $0x80` for syscall if it's compiled with CONFIG_NOLIBC, otherwise, it uses whatever the libc provides. Extra notes for __do_syscall6() macro: On i386, the 6th argument of syscall goes in %ebp. However, both Clang and GCC cannot use %ebp in the clobber list and the "r" constraint without using -fomit-frame-pointer. To make it always available for any kind of compilation, the below workaround is implemented: 1) Push the 6-th argument. 2) Push %ebp. 3) Load the 6-th argument from 4(%esp) to %ebp. 4) Do the syscall (int $0x80). 5) Pop %ebp (restore the old value of %ebp). 6) Add %esp by 4 (undo the stack pointer). WARNING: Don't use register variables for __do_syscall6(), there is a known GCC bug that results in an endless loop. BugLink: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105032 Link: https://lore.kernel.org/lkml/2e335ac54db44f1d8496583d97f9dab0@AcuMS.aculab.com Suggested-by: David Laight Co-authored-by: Alviro Iskandar Setiawan Signed-off-by: Alviro Iskandar Setiawan Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220414224001.187778-4-ammar.faizi@intel.com Signed-off-by: Jens Axboe --- src/arch/x86/syscall.h | 150 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 2 deletions(-) diff --git a/src/arch/x86/syscall.h b/src/arch/x86/syscall.h index 89a68f6..8cd24dd 100644 --- a/src/arch/x86/syscall.h +++ b/src/arch/x86/syscall.h @@ -151,10 +151,156 @@ * TODO: Add x86 (32-bit) nolibc support. */ #ifdef CONFIG_NOLIBC - #error "x86 (32-bit) is currently not supported for nolibc builds" -#endif +/** + * Note for syscall registers usage (x86, 32-bit): + * - %eax is the syscall number. + * - %eax is also the return value. + * - %ebx is the 1st argument. + * - %ecx is the 2nd argument. + * - %edx is the 3rd argument. + * - %esi is the 4th argument. + * - %edi is the 5th argument. + * - %ebp is the 6th argument. + */ + +#define __do_syscall0(NUM) ({ \ + intptr_t eax; \ + \ + __asm__ volatile( \ + "int $0x80" \ + : "=a"(eax) /* %eax */ \ + : "a"(NUM) /* %eax */ \ + : "memory" \ + ); \ + eax; \ +}) + +#define __do_syscall1(NUM, ARG1) ({ \ + intptr_t eax; \ + \ + __asm__ volatile( \ + "int $0x80" \ + : "=a"(eax) /* %eax */ \ + : "a"(NUM), /* %eax */ \ + "b"((ARG1)) /* %ebx */ \ + : "memory" \ + ); \ + eax; \ +}) + +#define __do_syscall2(NUM, ARG1, ARG2) ({ \ + intptr_t eax; \ + \ + __asm__ volatile( \ + "int $0x80" \ + : "=a" (eax) /* %eax */ \ + : "a"(NUM), /* %eax */ \ + "b"((ARG1)), /* %ebx */ \ + "c"((ARG2)) /* %ecx */ \ + : "memory" \ + ); \ + eax; \ +}) + +#define __do_syscall3(NUM, ARG1, ARG2, ARG3) ({ \ + intptr_t eax; \ + \ + __asm__ volatile( \ + "int $0x80" \ + : "=a" (eax) /* %eax */ \ + : "a"(NUM), /* %eax */ \ + "b"((ARG1)), /* %ebx */ \ + "c"((ARG2)), /* %ecx */ \ + "d"((ARG3)) /* %edx */ \ + : "memory" \ + ); \ + eax; \ +}) + +#define __do_syscall4(NUM, ARG1, ARG2, ARG3, ARG4) ({ \ + intptr_t eax; \ + \ + __asm__ volatile( \ + "int $0x80" \ + : "=a" (eax) /* %eax */ \ + : "a"(NUM), /* %eax */ \ + "b"((ARG1)), /* %ebx */ \ + "c"((ARG2)), /* %ecx */ \ + "d"((ARG3)), /* %edx */ \ + "S"((ARG4)) /* %esi */ \ + : "memory" \ + ); \ + eax; \ +}) + +#define __do_syscall5(NUM, ARG1, ARG2, ARG3, ARG4, ARG5) ({ \ + intptr_t eax; \ + \ + __asm__ volatile( \ + "int $0x80" \ + : "=a" (eax) /* %eax */ \ + : "a"(NUM), /* %eax */ \ + "b"((ARG1)), /* %ebx */ \ + "c"((ARG2)), /* %ecx */ \ + "d"((ARG3)), /* %edx */ \ + "S"((ARG4)), /* %esi */ \ + "D"((ARG5)) /* %edi */ \ + : "memory" \ + ); \ + eax; \ +}) + + +/* + * On i386, the 6th argument of syscall goes in %ebp. However, both Clang + * and GCC cannot use %ebp in the clobber list and in the "r" constraint + * without using -fomit-frame-pointer. To make it always available for + * any kind of compilation, the below workaround is implemented: + * + * 1) Push the 6-th argument. + * 2) Push %ebp. + * 3) Load the 6-th argument from 4(%esp) to %ebp. + * 4) Do the syscall (int $0x80). + * 5) Pop %ebp (restore the old value of %ebp). + * 6) Add %esp by 4 (undo the stack pointer). + * + * WARNING: + * Don't use register variables for __do_syscall6(), there is a known + * GCC bug that results in an endless loop. + * + * BugLink: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105032 + * + */ +#define __do_syscall6(NUM, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) ({ \ + intptr_t eax = (intptr_t)(NUM); \ + intptr_t arg6 = (intptr_t)(ARG6); /* Always in memory */ \ + __asm__ volatile ( \ + "pushl %[_arg6]\n\t" \ + "pushl %%ebp\n\t" \ + "movl 4(%%esp),%%ebp\n\t" \ + "int $0x80\n\t" \ + "popl %%ebp\n\t" \ + "addl $4,%%esp" \ + : "+a"(eax) /* %eax */ \ + : "b"(ARG1), /* %ebx */ \ + "c"(ARG2), /* %ecx */ \ + "d"(ARG3), /* %edx */ \ + "S"(ARG4), /* %esi */ \ + "D"(ARG5), /* %edi */ \ + [_arg6]"m"(arg6) /* memory */ \ + : "memory", "cc" \ + ); \ + eax; \ +}) + +#include "../syscall-defs.h" + +#else /* #ifdef CONFIG_NOLIBC */ + #include "../generic/syscall.h" +#endif /* #ifdef CONFIG_NOLIBC */ + #endif /* #if defined(__x86_64__) */ #endif /* #ifndef LIBURING_ARCH_X86_SYSCALL_H */ -- cgit v1.2.3 From 4ad972d6d1b16e4fb069fc2f006265942cf33103 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 21 Apr 2022 14:52:30 +0700 Subject: arch/x86/syscall: Remove TODO comment nolibc support for x86 32-bit has been added in commit b7d8dd8bbf5b855 ("arch/x86/syscall: Add x86 32-bit native syscall support"). But I forgot to remove the comment that says "We can't use CONFIG_NOLIBC for x86 (32-bit)". Remove it. Signed-off-by: Ammar Faizi Link: https://lore.kernel.org/r/20220421075205.98770-1-ammar.faizi@intel.com Signed-off-by: Jens Axboe --- src/arch/x86/syscall.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/arch/x86/syscall.h b/src/arch/x86/syscall.h index 8cd24dd..43c576b 100644 --- a/src/arch/x86/syscall.h +++ b/src/arch/x86/syscall.h @@ -144,12 +144,6 @@ #else /* #if defined(__x86_64__) */ -/* - * For x86 (32-bit), fallback to libc wrapper. - * We can't use CONFIG_NOLIBC for x86 (32-bit) at the moment. - * - * TODO: Add x86 (32-bit) nolibc support. - */ #ifdef CONFIG_NOLIBC /** * Note for syscall registers usage (x86, 32-bit): -- cgit v1.2.3 From 861c121c931d33dae4fbeeab3eac86544d856d9a Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Fri, 22 Apr 2022 09:01:26 -0700 Subject: test: handle mmap return failures in pollfree test Sometimes these mmap's fail, and it causes SEGFAULTS. I assume this was accidentally left off when this was originally landed. Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220422160132.2891927-2-dylany@fb.com Signed-off-by: Jens Axboe --- test/pollfree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/pollfree.c b/test/pollfree.c index e2511df..d753ffe 100644 --- a/test/pollfree.c +++ b/test/pollfree.c @@ -406,10 +406,10 @@ int main(int argc, char *argv[]) ret = mmap((void *)0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); if (ret == MAP_FAILED) return 0; - mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); + ret = mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); if (ret == MAP_FAILED) return 0; - mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + ret = mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); if (ret == MAP_FAILED) return 0; loop(); -- cgit v1.2.3 From 44673763e7467d49a1ef4bba8a641f9dd4c6ff70 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Fri, 22 Apr 2022 09:01:27 -0700 Subject: test: use unique path for socket Do not collide if multiple tests are running at once. Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220422160132.2891927-3-dylany@fb.com Signed-off-by: Jens Axboe --- test/accept-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/accept-test.c b/test/accept-test.c index 71d9d80..4a904e4 100644 --- a/test/accept-test.c +++ b/test/accept-test.c @@ -35,7 +35,7 @@ int main(int argc, char *argv[]) memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; - memcpy(addr.sun_path, "\0sock", 6); + memcpy(addr.sun_path, "\0sock2", 7); ret = bind(fd, (struct sockaddr *)&addr, addrlen); assert(ret != -1); -- cgit v1.2.3 From 736667aa9e31cecded9474d28f5666fa900d0b77 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Fri, 22 Apr 2022 09:01:28 -0700 Subject: test: use unique ports In preparation for running tests in parallel remove some collisions in ports. In the future this should probably use ephemeral ports, but for now there are not too many places to change. Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220422160132.2891927-4-dylany@fb.com Signed-off-by: Jens Axboe --- test/232c93d07b74.c | 2 +- test/recv-msgall.c | 2 +- test/send_recv.c | 2 +- test/send_recvmsg.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/232c93d07b74.c b/test/232c93d07b74.c index 4153aef..8a7810b 100644 --- a/test/232c93d07b74.c +++ b/test/232c93d07b74.c @@ -26,7 +26,7 @@ #define RECV_BUFF_SIZE 2 #define SEND_BUFF_SIZE 3 -#define PORT 0x1235 +#define PORT 0x1234 struct params { int tcp; diff --git a/test/recv-msgall.c b/test/recv-msgall.c index 5f202b4..a6f7cfc 100644 --- a/test/recv-msgall.c +++ b/test/recv-msgall.c @@ -17,7 +17,7 @@ #define MAX_MSG 128 -#define PORT 10200 +#define PORT 10201 #define HOST "127.0.0.1" static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock, diff --git a/test/send_recv.c b/test/send_recv.c index ad8ea0e..a7b001a 100644 --- a/test/send_recv.c +++ b/test/send_recv.c @@ -19,7 +19,7 @@ static char str[] = "This is a test of send and recv over io_uring!"; #define MAX_MSG 128 -#define PORT 10200 +#define PORT 10202 #define HOST "127.0.0.1" static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock, diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index 43121f0..f607b5c 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -19,7 +19,7 @@ static char str[] = "This is a test of sendmsg and recvmsg over io_uring!"; #define MAX_MSG 128 -#define PORT 10200 +#define PORT 10203 #define HOST "127.0.0.1" #define BUF_BGID 10 -- cgit v1.2.3 From 16d9366b9f9ca44d2a4da7320663a06fb9df7a28 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Fri, 22 Apr 2022 09:01:29 -0700 Subject: test: use unique filenames Allow tests to be run in parallel Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220422160132.2891927-5-dylany@fb.com Signed-off-by: Jens Axboe --- test/openat2.c | 6 +++--- test/sq-poll-dup.c | 2 +- test/sq-poll-share.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/openat2.c b/test/openat2.c index 379c61e..34c0f85 100644 --- a/test/openat2.c +++ b/test/openat2.c @@ -246,12 +246,12 @@ int main(int argc, char *argv[]) } if (argc > 1) { - path = "/tmp/.open.close"; + path = "/tmp/.open.at2"; path_rel = argv[1]; do_unlink = 0; } else { - path = "/tmp/.open.close"; - path_rel = ".open.close"; + path = "/tmp/.open.at2"; + path_rel = ".open.at2"; do_unlink = 1; } diff --git a/test/sq-poll-dup.c b/test/sq-poll-dup.c index 0076a31..6a72b82 100644 --- a/test/sq-poll-dup.c +++ b/test/sq-poll-dup.c @@ -164,7 +164,7 @@ int main(int argc, char *argv[]) if (argc > 1) { fname = argv[1]; } else { - fname = ".basic-rw"; + fname = ".basic-rw-poll-dup"; t_create_file(fname, FILE_SIZE); } diff --git a/test/sq-poll-share.c b/test/sq-poll-share.c index 2f1c1dd..7bb7626 100644 --- a/test/sq-poll-share.c +++ b/test/sq-poll-share.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) if (argc > 1) { fname = argv[1]; } else { - fname = ".basic-rw"; + fname = ".basic-rw-poll-share"; t_create_file(fname, FILE_SIZE); } -- cgit v1.2.3 From fddf8e6fd0ec06ca84a1d6a769dbd891e7cdaf08 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Fri, 22 Apr 2022 09:01:30 -0700 Subject: test: mkdir -p output folder In case multiple mkdir are running at once, do not log an error if it exists due to a race condition. Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220422160132.2891927-6-dylany@fb.com Signed-off-by: Jens Axboe --- test/runtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.sh b/test/runtests.sh index 122e482..6d8f7af 100755 --- a/test/runtests.sh +++ b/test/runtests.sh @@ -139,7 +139,7 @@ run_test() # Run all specified tests for tst in "${TESTS[@]}"; do if [ ! -d output ]; then - mkdir output + mkdir -p output fi if [ -z "${TEST_MAP[$tst]}" ]; then run_test "$tst" -- cgit v1.2.3 From 6480f692d62afbebb088febc369b30a63dbc2ea7 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Fri, 22 Apr 2022 09:01:31 -0700 Subject: test: add make targets for each test Add a make target runtests-parallel which can run tests in parallel. This is very useful to quickly run all the tests locally with $ make -j runtests-parallel Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220422160132.2891927-7-dylany@fb.com Signed-off-by: Jens Axboe --- Makefile | 2 ++ test/Makefile | 10 +++++++++- test/runtests-quiet.sh | 11 +++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100755 test/runtests-quiet.sh diff --git a/Makefile b/Makefile index 28c0fd8..d54551e 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,8 @@ runtests: all @$(MAKE) -C test runtests runtests-loop: @$(MAKE) -C test runtests-loop +runtests-parallel: + @$(MAKE) -C test runtests-parallel config-host.mak: configure @if [ ! -e "$@" ]; then \ diff --git a/test/Makefile b/test/Makefile index cb7e15e..fe35ff9 100644 --- a/test/Makefile +++ b/test/Makefile @@ -185,6 +185,7 @@ all_targets += sq-full-cpp.t test_targets := $(patsubst %.c,%,$(test_srcs)) test_targets := $(patsubst %.cc,%,$(test_targets)) +run_test_targets := $(patsubst %,%.run_test,$(test_targets)) test_targets := $(patsubst %,%.t,$(test_targets)) all_targets += $(test_targets) @@ -229,4 +230,11 @@ runtests: all runtests-loop: all @./runtests-loop.sh $(test_targets) -.PHONY: all install clean runtests runtests-loop +%.run_test: %.t + @./runtests-quiet.sh $< + +runtests-parallel: $(run_test_targets) + @echo "All tests passed" + +.PHONY: all install clean runtests runtests-loop runtests-parallel +.PHONY += $(run_test_targets) diff --git a/test/runtests-quiet.sh b/test/runtests-quiet.sh new file mode 100755 index 0000000..438a00a --- /dev/null +++ b/test/runtests-quiet.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +TESTS=("$@") +RESULT_FILE=$(mktemp) +./runtests.sh "${TESTS[@]}" 2>&1 > $RESULT_FILE +RET="$?" +if [ "${RET}" -ne 0 ]; then + cat $RESULT_FILE +fi +rm $RESULT_FILE +exit $RET -- cgit v1.2.3 From 473e16399327ff1a05cb58b256c9bc86b47561c3 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Fri, 22 Apr 2022 09:01:32 -0700 Subject: test: use remove_buffers instead of nop to generate error codes This is in prep for allwoing NOP to be used in IOPOLL mode. remove_buffers will consistently return ENOENT if asked to remove buffers from a nonexistent group, and so this is a suitable replacement. Other opcodes return -EINVAL in IOPOLL from the prep stage, which has slightly different behaviour. Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220422160132.2891927-8-dylany@fb.com Signed-off-by: Jens Axboe --- test/defer.c | 28 ++++++++++++++++++++-------- test/link.c | 6 +++--- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/test/defer.c b/test/defer.c index 825b69f..68ee4b4 100644 --- a/test/defer.c +++ b/test/defer.c @@ -12,6 +12,10 @@ #include "liburing.h" #define RING_SIZE 128 +enum { + OP_NOP, + OP_REMOVE_BUFFERS +}; struct test_context { struct io_uring *ring; @@ -27,7 +31,8 @@ static void free_context(struct test_context *ctx) memset(ctx, 0, sizeof(*ctx)); } -static int init_context(struct test_context *ctx, struct io_uring *ring, int nr) +static int init_context(struct test_context *ctx, struct io_uring *ring, int nr, + int op) { struct io_uring_sqe *sqe; int i; @@ -45,7 +50,14 @@ static int init_context(struct test_context *ctx, struct io_uring *ring, int nr) sqe = io_uring_get_sqe(ring); if (!sqe) goto err; - io_uring_prep_nop(sqe); + switch (op) { + case OP_NOP: + io_uring_prep_nop(sqe); + break; + case OP_REMOVE_BUFFERS: + io_uring_prep_remove_buffers(sqe, 10, 1); + break; + }; sqe->user_data = i; ctx->sqes[i] = sqe; } @@ -81,7 +93,7 @@ static int test_cancelled_userdata(struct io_uring *ring) struct test_context ctx; int ret, i, nr = 100; - if (init_context(&ctx, ring, nr)) + if (init_context(&ctx, ring, nr, OP_NOP)) return 1; for (i = 0; i < nr; i++) @@ -115,7 +127,7 @@ static int test_thread_link_cancel(struct io_uring *ring) struct test_context ctx; int ret, i, nr = 100; - if (init_context(&ctx, ring, nr)) + if (init_context(&ctx, ring, nr, OP_REMOVE_BUFFERS)) return 1; for (i = 0; i < nr; i++) @@ -134,12 +146,12 @@ static int test_thread_link_cancel(struct io_uring *ring) bool fail = false; if (i == 0) - fail = (ctx.cqes[i].res != -EINVAL); + fail = (ctx.cqes[i].res != -ENOENT); else fail = (ctx.cqes[i].res != -ECANCELED); if (fail) { - printf("invalid status\n"); + printf("invalid status %d\n", ctx.cqes[i].res); goto err; } } @@ -158,7 +170,7 @@ static int test_drain_with_linked_timeout(struct io_uring *ring) struct test_context ctx; int ret, i; - if (init_context(&ctx, ring, nr * 2)) + if (init_context(&ctx, ring, nr * 2, OP_NOP)) return 1; for (i = 0; i < nr; i++) { @@ -188,7 +200,7 @@ static int run_drained(struct io_uring *ring, int nr) struct test_context ctx; int ret, i; - if (init_context(&ctx, ring, nr)) + if (init_context(&ctx, ring, nr, OP_NOP)) return 1; for (i = 0; i < nr; i++) diff --git a/test/link.c b/test/link.c index c89d6b2..41d3899 100644 --- a/test/link.c +++ b/test/link.c @@ -178,7 +178,7 @@ static int test_single_link_fail(struct io_uring *ring) goto err; } - io_uring_prep_nop(sqe); + io_uring_prep_remove_buffers(sqe, 10, 1); sqe->flags |= IOSQE_IO_LINK; sqe = io_uring_get_sqe(ring); @@ -205,8 +205,8 @@ static int test_single_link_fail(struct io_uring *ring) printf("failed to get cqe\n"); goto err; } - if (i == 0 && cqe->res != -EINVAL) { - printf("sqe0 failed with %d, wanted -EINVAL\n", cqe->res); + if (i == 0 && cqe->res != -ENOENT) { + printf("sqe0 failed with %d, wanted -ENOENT\n", cqe->res); goto err; } if (i == 1 && cqe->res != -ECANCELED) { -- cgit v1.2.3 From 15e670a801cd9a4c0d4ce69099be9c163b7dfa66 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 22 Apr 2022 11:23:07 -0600 Subject: test/runtests-quiet.sh: quote file names Signed-off-by: Jens Axboe --- test/runtests-quiet.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/runtests-quiet.sh b/test/runtests-quiet.sh index 438a00a..63c46bd 100755 --- a/test/runtests-quiet.sh +++ b/test/runtests-quiet.sh @@ -2,10 +2,10 @@ TESTS=("$@") RESULT_FILE=$(mktemp) -./runtests.sh "${TESTS[@]}" 2>&1 > $RESULT_FILE +./runtests.sh "${TESTS[@]}" 2>&1 > "$RESULT_FILE" RET="$?" if [ "${RET}" -ne 0 ]; then - cat $RESULT_FILE + cat "$RESULT_FILE" fi -rm $RESULT_FILE +rm "$RESULT_FILE" exit $RET -- cgit v1.2.3 From 770efd14e8b17ccf23a45c95ecc9d38de4e17011 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 22 Apr 2022 11:30:13 -0600 Subject: test/runtests-quiet.sh: fixup redirection Signed-off-by: Jens Axboe --- test/runtests-quiet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests-quiet.sh b/test/runtests-quiet.sh index 63c46bd..2b84b9f 100755 --- a/test/runtests-quiet.sh +++ b/test/runtests-quiet.sh @@ -2,7 +2,7 @@ TESTS=("$@") RESULT_FILE=$(mktemp) -./runtests.sh "${TESTS[@]}" 2>&1 > "$RESULT_FILE" +{ ./runtests.sh "${TESTS[@]}"; } 2>&1 > "$RESULT_FILE" RET="$?" if [ "${RET}" -ne 0 ]; then cat "$RESULT_FILE" -- cgit v1.2.3 From 2a2e58225cdb9f0c6f86c610c4d2d137a914e41d Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 23 Apr 2022 03:35:37 +0700 Subject: test/runtests-quiet.sh: Fixup redirection 1) command > file.txt will redirect the stdout to file.txt. 2) command > file.txt 2>&1 will redirect the stdout and stderr to file.txt. What we want is (2). Previous commits placed the "2>&1" wrong. Cc: Dylan Yudaken Fixes: 770efd14e8b17ccf23a45c95ecc9d38de4e17011 ("test/runtests-quiet.sh: fixup redirection") Fixes: 6480f692d62afbebb088febc369b30a63dbc2ea7 ("test: add make targets for each test") Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- test/runtests-quiet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests-quiet.sh b/test/runtests-quiet.sh index 2b84b9f..2bc7da0 100755 --- a/test/runtests-quiet.sh +++ b/test/runtests-quiet.sh @@ -2,7 +2,7 @@ TESTS=("$@") RESULT_FILE=$(mktemp) -{ ./runtests.sh "${TESTS[@]}"; } 2>&1 > "$RESULT_FILE" +./runtests.sh "${TESTS[@]}" > "$RESULT_FILE" 2>&1 RET="$?" if [ "${RET}" -ne 0 ]; then cat "$RESULT_FILE" -- cgit v1.2.3 From c36cd51eef30c81a0ce3398057672f3c03498b86 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 23 Apr 2022 03:35:38 +0700 Subject: Makefile: Make sure we build everything before runtests A recent commit added `runtests-parallel` target to run the tests in parallel. But it doesn't have a proper build dependency. As such, when doing: make -j clean; make -j runtests-parallel; we got this error: ``` make[1]: Entering directory '/home/ammarfaizi2/app/liburing/test' make[1]: *** No rule to make target '232c93d07b74.t', needed by '232c93d07b74.run_test'. Stop. make[1]: Leaving directory '/home/ammarfaizi2/app/liburing/test' make: *** [Makefile:25: runtests-parallel] Error 2 ``` Add `all` target as the dependency of `runtests-parallel`. While in there, I found the same issue on `runtests-loop` target. Do the same thing for it too. This way the main Makefile will build everything first before trying to execute the tests. Cc: Dylan Yudaken Fixes: 4fb3c9e9c737c2cf2d4df4e1972e68d596a626f7 ("Add runtests-loop target") Fixes: 6480f692d62afbebb088febc369b30a63dbc2ea7 ("test: add make targets for each test") Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d54551e..686be4f 100644 --- a/Makefile +++ b/Makefile @@ -19,9 +19,9 @@ partcheck: all runtests: all @$(MAKE) -C test runtests -runtests-loop: +runtests-loop: all @$(MAKE) -C test runtests-loop -runtests-parallel: +runtests-parallel: all @$(MAKE) -C test runtests-parallel config-host.mak: configure -- cgit v1.2.3 From 0664b331b30842d1576748604bfa4193f470cd67 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 23 Apr 2022 03:35:39 +0700 Subject: test/Makefile: Remove `.PHONY` variable What we want is a .PHONY build target that depends on runtests-parallel, not a .PHONY variable. This variable doesn't do anything. Remove it. Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- test/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index fe35ff9..444c749 100644 --- a/test/Makefile +++ b/test/Makefile @@ -237,4 +237,3 @@ runtests-parallel: $(run_test_targets) @echo "All tests passed" .PHONY: all install clean runtests runtests-loop runtests-parallel -.PHONY += $(run_test_targets) -- cgit v1.2.3 From 6966b0a9e62f2b1c1b9a72156de4ae908f2b23b9 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 23 Apr 2022 03:35:40 +0700 Subject: test/Makefile: Sort the test file list alphabetically Make it easy to manage and find by sorting it alphabetically. Also, add a comment to remind us to keep it sorted alphabetically. Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- test/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index 444c749..923f984 100644 --- a/test/Makefile +++ b/test/Makefile @@ -33,6 +33,7 @@ override CXXFLAGS += $(XCFLAGS) -std=c++11 -DLIBURING_BUILD_TEST LDFLAGS ?= override LDFLAGS += -L../src/ -luring -lpthread +# Please keep this list sorted alphabetically. test_srcs := \ 232c93d07b74.c \ 35fa71a030ca.c \ @@ -133,6 +134,7 @@ test_srcs := \ short-read.c \ shutdown.c \ sigfd-deadlock.c \ + skip-cqe.c \ socket-rw.c \ socket-rw-eagain.c \ socket-rw-offset.c \ @@ -159,7 +161,6 @@ test_srcs := \ tty-write-dpoll.c \ unlink.c \ wakeup-hang.c \ - skip-cqe.c \ # EOL -- cgit v1.2.3 From b07accbc2035c607443936fc0c1f78ae1bc46db7 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 23 Apr 2022 03:35:41 +0700 Subject: .github/workflows: Run the nolibc build for x86 32-bit Since commit: b7d8dd8bbf5b ("arch/x86/syscall: Add x86 32-bit native syscall support") liburing supports nolibc build for x86 32-bit. Run the nolibc build for this arch on the GitHub bot too. Currently, liburing nolibc is only available for: - x86-64. - x86 (32-bit). Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 30a2fc7..39f4314 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,7 +72,7 @@ jobs: - name: Build nolibc run: | - if [[ "${{matrix.arch}}" == "x86_64" ]]; then \ + if [[ "${{matrix.arch}}" == "x86_64" || "${{matrix.arch}}" == "i686" ]]; then \ make clean; \ ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} --nolibc; \ make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS"; \ -- cgit v1.2.3 From 7ad5e52d4d2f91203615cd738e56aba10ad8b8f6 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Sat, 23 Apr 2022 03:35:42 +0700 Subject: test/double-poll-crash: Skip this test if the `mmap()` fails This test is very prone to hiting a SIGSEGV signal due to missing error handling on mmap() calls. This especially often happens when executing `runtests-parallel`. Let's just skip this test if those calls fail instead of having a random segfault with no clear resolution. Signed-off-by: Ammar Faizi Signed-off-by: Jens Axboe --- test/double-poll-crash.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/double-poll-crash.c b/test/double-poll-crash.c index 5bfce09..231c7da 100644 --- a/test/double-poll-crash.c +++ b/test/double-poll-crash.c @@ -52,10 +52,14 @@ static long syz_io_uring_setup(volatile long a0, volatile long a1, *ring_ptr_out = mmap(vma1, ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, IORING_OFF_SQ_RING); + if (*ring_ptr_out == MAP_FAILED) + exit(0); uint32_t sqes_sz = setup_params->sq_entries * SIZEOF_IO_URING_SQE; *sqes_ptr_out = mmap(vma2, sqes_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, IORING_OFF_SQES); + if (*sqes_ptr_out == MAP_FAILED) + exit(0); return fd_io_uring; } @@ -108,6 +112,7 @@ uint64_t r[4] = {0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff}; int main(int argc, char *argv[]) { + void *mmap_ret; #if !defined(__i386) && !defined(__x86_64__) return 0; #endif @@ -115,8 +120,12 @@ int main(int argc, char *argv[]) if (argc > 1) return 0; - mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); - mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + mmap_ret = mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); + if (mmap_ret == MAP_FAILED) + return 0; + mmap_ret = mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + if (mmap_ret == MAP_FAILED) + return 0; intptr_t res = 0; *(uint32_t*)0x20000484 = 0; *(uint32_t*)0x20000488 = 0; -- cgit v1.2.3 From 95bcdd2f4bdd0dc702d9eb77675a31c0f0935dc6 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 2 May 2022 08:26:03 -0600 Subject: test/statx: use regular stat include Link: https://github.com/axboe/liburing/issues/578 Signed-off-by: Jens Axboe --- test/statx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/statx.c b/test/statx.c index c0f9e9c..5fa086e 100644 --- a/test/statx.c +++ b/test/statx.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "helpers.h" #include "liburing.h" -- cgit v1.2.3 From e597622672fcfdab486337b5a80be49cfe25a99c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 10 May 2022 14:38:19 -0600 Subject: man: update man pages for waiting on a CQE with a timeout On older kernels, it was indeed true that you did not need to separately submit before doing a wait, IFF you used a timeout. However, this is not true since kernels supported IORING_ENTER_EXT_ARG. Link: https://github.com/axboe/liburing/issues/579 Signed-off-by: Jens Axboe --- man/io_uring_wait_cqe_timeout.3 | 10 ++++++++-- man/io_uring_wait_cqes.3 | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 index 64e920b..e81018a 100644 --- a/man/io_uring_wait_cqe_timeout.3 +++ b/man/io_uring_wait_cqe_timeout.3 @@ -28,8 +28,14 @@ param is filled in on success. If .I ts -is specified, the application does not need to call io_uring_submit (3) before -calling io_uring_wait_cqes (3). +is specified and an older kernel without +.B IORING_FEAT_EXT_ARG +is used, the application does not need to call +.BR io_uring_submit (3) +before calling +.BR io_uring_wait_cqes (3). +For newer kernels with that feature flag set, there is no implied submit +when waiting for a request. .SH RETURN VALUE On success diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3 index a9a4a0c..2fb727c 100644 --- a/man/io_uring_wait_cqes.3 +++ b/man/io_uring_wait_cqes.3 @@ -35,8 +35,14 @@ param is filled in on success. If .I ts -is specified, the application does not need to call io_uring_submit (3) before -calling io_uring_wait_cqes (3). +is specified and an older kernel without +.B IORING_FEAT_EXT_ARG +is used, the application does not need to call +.BR io_uring_submit (3) +before calling +.BR io_uring_wait_cqes (3). +For newer kernels with that feature flag set, there is no implied submit +when waiting for a request. .SH RETURN VALUE On success -- cgit v1.2.3 From 19b0d25193330d3cfcd636d4cc2e4ec1ec019271 Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Sat, 14 May 2022 22:35:29 +0800 Subject: test/accept.c: close the listen fd at the end of the test Close the listen fd when it goes to the end, otherwise it may causes issues for the next tests Signed-off-by: Hao Xu Link: https://lore.kernel.org/r/20220514143534.59162-2-haoxu.linux@gmail.com Signed-off-by: Jens Axboe --- test/accept.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/accept.c b/test/accept.c index c591e76..a0f4a13 100644 --- a/test/accept.c +++ b/test/accept.c @@ -425,9 +425,11 @@ static int test_accept_cancel(unsigned usecs, unsigned int nr) } io_uring_queue_exit(&m_io_uring); + close(fd); return 0; err: io_uring_queue_exit(&m_io_uring); + close(fd); return 1; } -- cgit v1.2.3 From e7c7089e352f5a6ead9c409a7d8a43ffe9cd59a5 Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Sat, 14 May 2022 22:35:30 +0800 Subject: liburing.h: support multishot accept Add a new api to leverage the multishot mode accept, this feature is to achieve one accept request for all listened events. Signed-off-by: Hao Xu Link: https://lore.kernel.org/r/20220514143534.59162-3-haoxu.linux@gmail.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 10 ++++++++++ src/include/liburing/io_uring.h | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 5c03061..cf50383 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -502,6 +502,16 @@ static inline void io_uring_prep_accept_direct(struct io_uring_sqe *sqe, int fd, __io_uring_set_target_fixed_file(sqe, file_index); } +static inline void io_uring_prep_multishot_accept(struct io_uring_sqe *sqe, + int fd, struct sockaddr *addr, + socklen_t *addrlen, int flags) +{ + io_uring_prep_rw(IORING_OP_ACCEPT, sqe, fd, addr, 0, + (__u64) (unsigned long) addrlen); + sqe->accept_flags = (__u32) flags; + sqe->ioprio |= IORING_ACCEPT_MULTISHOT; +} + static inline void io_uring_prep_cancel(struct io_uring_sqe *sqe, __u64 user_data, int flags) { diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index bfb3548..46765d2 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -434,6 +434,11 @@ struct io_uring_getevents_arg { __u64 ts; }; +/* + * accept flags stored in sqe->ioprio + */ +#define IORING_ACCEPT_MULTISHOT (1U << 0) + #ifdef __cplusplus } #endif -- cgit v1.2.3 From 305eb96b9dbb84a3dd3151d0debde753a354d81e Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Sat, 14 May 2022 22:35:31 +0800 Subject: liburing.h: add api to support multishot accept direct This is to support the multishot accept directly to the fixed table, the file_Index should be set to IORING_FILE_INDEX_ALLOC in this case. Signed-off-by: Hao Xu Link: https://lore.kernel.org/r/20220514143534.59162-4-haoxu.linux@gmail.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 11 +++++++++++ src/include/liburing/io_uring.h | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index cf50383..9065555 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -512,6 +512,17 @@ static inline void io_uring_prep_multishot_accept(struct io_uring_sqe *sqe, sqe->ioprio |= IORING_ACCEPT_MULTISHOT; } +/* multishot accept directly into the fixed file table */ +static inline void io_uring_prep_multishot_accept_direct(struct io_uring_sqe *sqe, + int fd, + struct sockaddr *addr, + socklen_t *addrlen, + int flags) +{ + io_uring_prep_multishot_accept(sqe, fd, addr, addrlen, flags); + __io_uring_set_target_fixed_file(sqe, IORING_FILE_INDEX_ALLOC - 1); +} + static inline void io_uring_prep_cancel(struct io_uring_sqe *sqe, __u64 user_data, int flags) { diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 46765d2..6260e0d 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -67,6 +67,15 @@ struct io_uring_sqe { __u64 __pad2[2]; }; +/* + * If sqe->file_index is set to this for opcodes that instantiate a new + * direct descriptor (like openat/openat2/accept), then io_uring will allocate + * an available direct descriptor instead of having the application pass one + * in. The picked direct descriptor will be returned in cqe->res, or -ENFILE + * if the space is full. + */ +#define IORING_FILE_INDEX_ALLOC (~0U) + enum { IOSQE_FIXED_FILE_BIT, IOSQE_IO_DRAIN_BIT, -- cgit v1.2.3 From 66cf84527c34acf8ea37b5cc048f04018b22ed2c Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Sat, 14 May 2022 22:35:32 +0800 Subject: test/accept.c: add test for multishot mode accept Add an test for multishot mode accept Signed-off-by: Hao Xu Link: https://lore.kernel.org/r/20220514143534.59162-5-haoxu.linux@gmail.com Signed-off-by: Jens Axboe --- test/accept.c | 281 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 216 insertions(+), 65 deletions(-) diff --git a/test/accept.c b/test/accept.c index a0f4a13..897278a 100644 --- a/test/accept.c +++ b/test/accept.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -22,6 +23,7 @@ #include "helpers.h" #include "liburing.h" +#define MAX_FDS 32 static int no_accept; struct data { @@ -29,6 +31,15 @@ struct data { struct iovec iov; }; +struct accept_test_args { + int accept_should_error; + bool fixed; + bool nonblock; + bool queue_accept_before_connect; + bool multishot; + int extra_loops; +}; + static void queue_send(struct io_uring *ring, int fd) { struct io_uring_sqe *sqe; @@ -59,20 +70,32 @@ static void queue_recv(struct io_uring *ring, int fd, bool fixed) sqe->flags |= IOSQE_FIXED_FILE; } -static void queue_accept_conn(struct io_uring *ring, - int fd, int fixed_idx, - int count) +static void queue_accept_conn(struct io_uring *ring, int fd, + struct accept_test_args args) { struct io_uring_sqe *sqe; int ret; + int fixed_idx = args.fixed ? 0 : -1; + int count = 1 + args.extra_loops; + bool multishot = args.multishot; while (count--) { sqe = io_uring_get_sqe(ring); - if (fixed_idx < 0) - io_uring_prep_accept(sqe, fd, NULL, NULL, 0); - else - io_uring_prep_accept_direct(sqe, fd, NULL, NULL, 0, - fixed_idx); + if (fixed_idx < 0) { + if (!multishot) + io_uring_prep_accept(sqe, fd, NULL, NULL, 0); + else + io_uring_prep_multishot_accept(sqe, fd, NULL, + NULL, 0); + } else { + if (!multishot) + io_uring_prep_accept_direct(sqe, fd, NULL, NULL, + 0, fixed_idx); + else + io_uring_prep_multishot_accept_direct(sqe, fd, + NULL, NULL, + 0); + } ret = io_uring_submit(ring); assert(ret != -1); @@ -131,71 +154,103 @@ static int start_accept_listen(struct sockaddr_in *addr, int port_off, return fd; } -struct accept_test_args { - int accept_should_error; - bool fixed; - bool nonblock; - bool queue_accept_before_connect; - int extra_loops; -}; - - -static int test_loop(struct io_uring *ring, - struct accept_test_args args, - int recv_s0, - struct sockaddr_in *addr) +static int set_client_fd(struct sockaddr_in *addr) { - struct io_uring_cqe *cqe; - uint32_t head, count = 0; - int ret, p_fd[2], done = 0; int32_t val; + int fd, ret; - p_fd[1] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); + fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); val = 1; - ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); assert(ret != -1); - int32_t flags = fcntl(p_fd[1], F_GETFL, 0); + int32_t flags = fcntl(fd, F_GETFL, 0); assert(flags != -1); flags |= O_NONBLOCK; - ret = fcntl(p_fd[1], F_SETFL, flags); + ret = fcntl(fd, F_SETFL, flags); assert(ret != -1); - ret = connect(p_fd[1], (struct sockaddr *)addr, sizeof(*addr)); + ret = connect(fd, (struct sockaddr *)addr, sizeof(*addr)); assert(ret == -1); - flags = fcntl(p_fd[1], F_GETFL, 0); + flags = fcntl(fd, F_GETFL, 0); assert(flags != -1); flags &= ~O_NONBLOCK; - ret = fcntl(p_fd[1], F_SETFL, flags); + ret = fcntl(fd, F_SETFL, flags); assert(ret != -1); - if (!args.queue_accept_before_connect) - queue_accept_conn(ring, recv_s0, args.fixed ? 0 : -1, 1); + return fd; +} - p_fd[0] = accept_conn(ring, args.fixed ? 0 : -1); - if (p_fd[0] == -EINVAL) { - if (args.accept_should_error) +static int test_loop(struct io_uring *ring, + struct accept_test_args args, + int recv_s0, + struct sockaddr_in *addr) +{ + struct io_uring_cqe *cqe; + uint32_t head, count = 0; + int i, ret, s_fd[MAX_FDS], c_fd[MAX_FDS], done = 0; + bool fixed = args.fixed; + bool multishot = args.multishot; + unsigned int multishot_mask = 0; + + for (i = 0; i < MAX_FDS; i++) { + c_fd[i] = set_client_fd(addr); + if (!multishot) + break; + } + + if (!args.queue_accept_before_connect) + queue_accept_conn(ring, recv_s0, args); + + for (i = 0; i < MAX_FDS; i++) { + s_fd[i] = accept_conn(ring, args.fixed ? 0 : -1); + if (s_fd[i] == -EINVAL) { + if (args.accept_should_error) + goto out; + fprintf(stdout, + "%s %s Accept not supported, skipping\n", + fixed ? "Fixed" : "", + multishot ? "Multishot" : ""); + no_accept = 1; goto out; - if (args.fixed) - fprintf(stdout, "Fixed accept not supported, skipping\n"); - else - fprintf(stdout, "Accept not supported, skipping\n"); - no_accept = 1; + } else if (s_fd[i] < 0) { + if (args.accept_should_error && + (s_fd[i] == -EBADF || s_fd[i] == -EINVAL)) + goto out; + fprintf(stderr, "%s %s Accept[%d] got %d\n", + fixed ? "Fixed" : "", + multishot ? "Multishot" : "", + i, s_fd[i]); + goto err; + } + + if (multishot && fixed) { + if (s_fd[i] >= MAX_FDS) { + fprintf(stderr, + "Fixed Multishot Accept[%d] got outbound index: %d\n", + i, s_fd[i]); + goto err; + } + multishot_mask |= (1 << (s_fd[i] - 1)); + } + if (!multishot) + break; + } + + if (multishot) { + if (fixed && multishot_mask != UINT_MAX) { + fprintf(stderr, "Fixed Multishot Accept misses events\n"); + goto err; + } goto out; - } else if (p_fd[0] < 0) { - if (args.accept_should_error && - (p_fd[0] == -EBADF || p_fd[0] == -EINVAL)) - goto out; - fprintf(stderr, "Accept got %d\n", p_fd[0]); - goto err; } - queue_send(ring, p_fd[1]); - queue_recv(ring, p_fd[0], args.fixed); + queue_send(ring, c_fd[0]); + queue_recv(ring, s_fd[0], args.fixed); ret = io_uring_submit_and_wait(ring, 2); assert(ret != -1); @@ -219,14 +274,32 @@ static int test_loop(struct io_uring *ring, } out: - if (!args.fixed) - close(p_fd[0]); - close(p_fd[1]); + if (!args.fixed) { + for (i = 0; i < MAX_FDS; i++) { + close(s_fd[i]); + if (!multishot) + break; + } + } + for (i = 0; i < MAX_FDS; i++) { + close(c_fd[i]); + if (!multishot) + break; + } return 0; err: - if (!args.fixed) - close(p_fd[0]); - close(p_fd[1]); + if (!args.fixed) { + for (i = 0; i < MAX_FDS; i++) { + close(s_fd[i]); + if (!multishot) + break; + } + } + for (i = 0; i < MAX_FDS; i++) { + close(c_fd[i]); + if (!multishot) + break; + } return 1; } @@ -238,8 +311,7 @@ static int test(struct io_uring *ring, struct accept_test_args args) int32_t recv_s0 = start_accept_listen(&addr, 0, args.nonblock ? O_NONBLOCK : 0); if (args.queue_accept_before_connect) - queue_accept_conn(ring, recv_s0, args.fixed ? 0 : -1, - 1 + args.extra_loops); + queue_accept_conn(ring, recv_s0, args); for (loop = 0; loop < 1 + args.extra_loops; loop++) { ret = test_loop(ring, args, recv_s0, &addr); if (ret) @@ -364,7 +436,7 @@ out: return ret; } -static int test_accept_cancel(unsigned usecs, unsigned int nr) +static int test_accept_cancel(unsigned usecs, unsigned int nr, bool multishot) { struct io_uring m_io_uring; struct io_uring_cqe *cqe; @@ -378,7 +450,10 @@ static int test_accept_cancel(unsigned usecs, unsigned int nr) for (i = 1; i <= nr; i++) { sqe = io_uring_get_sqe(&m_io_uring); - io_uring_prep_accept(sqe, fd, NULL, NULL, 0); + if (!multishot) + io_uring_prep_accept(sqe, fd, NULL, NULL, 0); + else + io_uring_prep_multishot_accept(sqe, fd, NULL, NULL, 0); sqe->user_data = i; ret = io_uring_submit(&m_io_uring); assert(ret == 1); @@ -449,6 +524,23 @@ static int test_accept(int count, bool before) return ret; } +static int test_multishot_accept(int count, bool before) +{ + struct io_uring m_io_uring; + int ret; + struct accept_test_args args = { + .queue_accept_before_connect = before, + .multishot = true, + .extra_loops = count - 1 + }; + + ret = io_uring_queue_init(MAX_FDS + 10, &m_io_uring, 0); + assert(ret >= 0); + ret = test(&m_io_uring, args); + io_uring_queue_exit(&m_io_uring); + return ret; +} + static int test_accept_nonblock(bool queue_before_connect, int count) { struct io_uring m_io_uring; @@ -483,6 +575,25 @@ static int test_accept_fixed(void) return ret; } +static int test_multishot_fixed_accept(void) +{ + struct io_uring m_io_uring; + int ret, fd[100]; + struct accept_test_args args = { + .fixed = true, + .multishot = true + }; + + memset(fd, -1, sizeof(fd)); + ret = io_uring_queue_init(MAX_FDS + 10, &m_io_uring, 0); + assert(ret >= 0); + ret = io_uring_register_files(&m_io_uring, fd, MAX_FDS); + assert(ret == 0); + ret = test(&m_io_uring, args); + io_uring_queue_exit(&m_io_uring); + return ret; +} + static int test_accept_sqpoll(void) { struct io_uring m_io_uring; @@ -512,7 +623,6 @@ int main(int argc, char *argv[]) if (argc > 1) return 0; - ret = test_accept(1, false); if (ret) { fprintf(stderr, "test_accept failed\n"); @@ -557,36 +667,78 @@ int main(int argc, char *argv[]) return ret; } + ret = test_multishot_fixed_accept(); + if (ret) { + fprintf(stderr, "test_multishot_fixed_accept failed\n"); + return ret; + } + ret = test_accept_sqpoll(); if (ret) { fprintf(stderr, "test_accept_sqpoll failed\n"); return ret; } - ret = test_accept_cancel(0, 1); + ret = test_accept_cancel(0, 1, false); if (ret) { fprintf(stderr, "test_accept_cancel nodelay failed\n"); return ret; } - ret = test_accept_cancel(10000, 1); + ret = test_accept_cancel(10000, 1, false); if (ret) { fprintf(stderr, "test_accept_cancel delay failed\n"); return ret; } - ret = test_accept_cancel(0, 4); + ret = test_accept_cancel(0, 4, false); if (ret) { fprintf(stderr, "test_accept_cancel nodelay failed\n"); return ret; } - ret = test_accept_cancel(10000, 4); + ret = test_accept_cancel(10000, 4, false); if (ret) { fprintf(stderr, "test_accept_cancel delay failed\n"); return ret; } + ret = test_accept_cancel(0, 1, true); + if (ret) { + fprintf(stderr, "test_accept_cancel multishot nodelay failed\n"); + return ret; + } + + ret = test_accept_cancel(10000, 1, true); + if (ret) { + fprintf(stderr, "test_accept_cancel multishot delay failed\n"); + return ret; + } + + ret = test_accept_cancel(0, 4, true); + if (ret) { + fprintf(stderr, "test_accept_cancel multishot nodelay failed\n"); + return ret; + } + + ret = test_accept_cancel(10000, 4, true); + if (ret) { + fprintf(stderr, "test_accept_cancel multishot delay failed\n"); + return ret; + } + + ret = test_multishot_accept(1, false); + if (ret) { + fprintf(stderr, "test_multishot_accept(1, false) failed\n"); + return ret; + } + + ret = test_multishot_accept(1, true); + if (ret) { + fprintf(stderr, "test_multishot_accept(1, true) failed\n"); + return ret; + } + ret = test_accept_many((struct test_accept_many_args) {}); if (ret) { fprintf(stderr, "test_accept_many failed\n"); @@ -621,6 +773,5 @@ int main(int argc, char *argv[]) fprintf(stderr, "test_accept_pending_on_exit failed\n"); return ret; } - return 0; } -- cgit v1.2.3 From 70e40d8de2ce5e3196c84344f611ca70f34e8182 Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Sat, 14 May 2022 22:35:33 +0800 Subject: test/accept.c: test for multishot direct accept with wrong arg Add a test for multishot direct accept, where don't set the file index to IORING_FILE_INDEX_ALLOC. Signed-off-by: Hao Xu Link: https://lore.kernel.org/r/20220514143534.59162-6-haoxu.linux@gmail.com Signed-off-by: Jens Axboe --- test/accept.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/accept.c b/test/accept.c index 897278a..921c79b 100644 --- a/test/accept.c +++ b/test/accept.c @@ -541,6 +541,43 @@ static int test_multishot_accept(int count, bool before) return ret; } +static int test_accept_multishot_wrong_arg() +{ + struct io_uring m_io_uring; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int fd, ret; + + ret = io_uring_queue_init(4, &m_io_uring, 0); + assert(ret >= 0); + + fd = start_accept_listen(NULL, 0, 0); + + sqe = io_uring_get_sqe(&m_io_uring); + io_uring_prep_multishot_accept_direct(sqe, fd, NULL, NULL, 0); + sqe->file_index = 1; + ret = io_uring_submit(&m_io_uring); + assert(ret == 1); + + ret = io_uring_wait_cqe(&m_io_uring, &cqe); + assert(!ret); + if (cqe->res != -EINVAL) { + fprintf(stderr, "file index should be IORING_FILE_INDEX_ALLOC \ + if its accept in multishot direct mode\n"); + goto err; + } + io_uring_cqe_seen(&m_io_uring, cqe); + + io_uring_queue_exit(&m_io_uring); + close(fd); + return 0; +err: + io_uring_queue_exit(&m_io_uring); + close(fd); + return 1; +} + + static int test_accept_nonblock(bool queue_before_connect, int count) { struct io_uring m_io_uring; @@ -673,6 +710,12 @@ int main(int argc, char *argv[]) return ret; } + ret = test_accept_multishot_wrong_arg(); + if (ret) { + fprintf(stderr, "test_accept_multishot_wrong_arg failed\n"); + return ret; + } + ret = test_accept_sqpoll(); if (ret) { fprintf(stderr, "test_accept_sqpoll failed\n"); -- cgit v1.2.3 From 9997778eed96c4ba2240c1a18773e3047be95290 Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Sat, 14 May 2022 22:35:34 +0800 Subject: man/io_uring_prep_accept.3: add man info for multishot accept Add man info for multishot accept APIs, including non-direct and direct. Signed-off-by: Hao Xu Link: https://lore.kernel.org/r/20220514143534.59162-7-haoxu.linux@gmail.com Signed-off-by: Jens Axboe --- man/io_uring_prep_accept.3 | 51 ++++++++++++++++++++++++----- man/io_uring_prep_multishot_accept.3 | 1 + man/io_uring_prep_multishot_accept_direct.3 | 1 + 3 files changed, 44 insertions(+), 9 deletions(-) create mode 120000 man/io_uring_prep_multishot_accept.3 create mode 120000 man/io_uring_prep_multishot_accept_direct.3 diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 779bcd9..e52c13e 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -18,11 +18,23 @@ io_uring_prep_accept - prepare an accept request .BI " int " flags ");" .BI " .BI "void io_uring_prep_accept_direct(struct io_uring_sqe *" sqe "," -.BI " int " sockfd "," -.BI " struct sockaddr *" addr "," -.BI " socklen_t " addrlen "," -.BI " int " flags "," -.BI " unsigned int " file_index ");" +.BI " int " sockfd "," +.BI " struct sockaddr *" addr "," +.BI " socklen_t " addrlen "," +.BI " int " flags "," +.BI " unsigned int " file_index ");" +.BI " +.BI "void io_uring_prep_multishot_accept(struct io_uring_sqe *" sqe "," +.BI " int " sockfd "," +.BI " struct sockaddr *" addr "," +.BI " socklen_t " addrlen "," +.BI " int " flags ");" +.BI " +.BI "void io_uring_prep_multishot_accept_direct(struct io_uring_sqe *" sqe "," +.BI " int " sockfd "," +.BI " struct sockaddr *" addr "," +.BI " socklen_t " addrlen "," +.BI " int " flags ");" .PP .SH DESCRIPTION .PP @@ -72,6 +84,25 @@ CQE .I res return. +For a direct descriptor accept request, the +.I file_index +argument can be set to +.B IORING_FILE_INDEX_ALLOC +In this case a free entry in io_uring file table will +be used automatically and the file index will be returned as CQE +.I res. +.B -ENFILE +is otherwise returned if there is no free entries in the io_uring file table. + +The multishot version accept and accept_direct perform a bit different with the +normal ones. Users only need to issue one this kind of request to listen all +the comming fds, each fd accepted is returned in a CQE. One thing to notice is +io_uring_prep_multishot_accept_direct() only works in +.B IORING_FILE_INDEX_ALLOC +mode, which means the CQE +.I res +returned is a file index counted from 1 not a real fd. + This function prepares an async .BR accept4 (2) request. See that man page for details. @@ -81,12 +112,14 @@ None .SH ERRORS The CQE .I res -field will contain the result of the operation. While the non-direct accept -returns the installed file descriptor as its value, the direct accept -returns +field will contain the result of the operation. For singleshot accept,the +non-direct accept returns the installed file descriptor as its value, the +direct accept returns .B 0 on success. The caller must know which direct descriptor was picked for this -request. See the related man page for details on possible values for the +request. For multishot accept, the non-direct accept returns the installed +file descriptor as its value, the direct accept returns the file index used on +success. See the related man page for details on possible values for the non-direct accept. Note that where synchronous system calls will return .B -1 on failure and set diff --git a/man/io_uring_prep_multishot_accept.3 b/man/io_uring_prep_multishot_accept.3 new file mode 120000 index 0000000..0404bf5 --- /dev/null +++ b/man/io_uring_prep_multishot_accept.3 @@ -0,0 +1 @@ +io_uring_prep_accept.3 \ No newline at end of file diff --git a/man/io_uring_prep_multishot_accept_direct.3 b/man/io_uring_prep_multishot_accept_direct.3 new file mode 120000 index 0000000..0404bf5 --- /dev/null +++ b/man/io_uring_prep_multishot_accept_direct.3 @@ -0,0 +1 @@ +io_uring_prep_accept.3 \ No newline at end of file -- cgit v1.2.3 From 2894a54a29e5466b4554f186e23856cf0e984eb9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 09:22:32 -0600 Subject: man/io_uring_prep_accept.3: fixup some phrasing Signed-off-by: Jens Axboe --- man/io_uring_prep_accept.3 | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index e52c13e..bebc262 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -87,21 +87,32 @@ return. For a direct descriptor accept request, the .I file_index argument can be set to -.B IORING_FILE_INDEX_ALLOC +.B IORING_FILE_INDEX_ALLOC, In this case a free entry in io_uring file table will be used automatically and the file index will be returned as CQE .I res. .B -ENFILE is otherwise returned if there is no free entries in the io_uring file table. -The multishot version accept and accept_direct perform a bit different with the -normal ones. Users only need to issue one this kind of request to listen all -the comming fds, each fd accepted is returned in a CQE. One thing to notice is -io_uring_prep_multishot_accept_direct() only works in +The multishot version accept and accept_direct allow an application to issue +a single accept request, which will repeatedly trigger a CQE when a connection +request comes in. Like other multishot type requests, the application should +look at the CQE +.I flags +and see if +.B IORING_CQE_F_MORE +is set on completion as an indication of whether or not the accept request +will generate further CQEs. + +For multishot with direct descriptors, .B IORING_FILE_INDEX_ALLOC -mode, which means the CQE +must be used as the file descriptor. This tells io_uring to allocate a free +direct descriptor from our table, rather than the application passing one in. +Failure to do so will result in the accept request being terminated with +.B -EINVAL. +The allocated descriptor will be returned in the CQE .I res -returned is a file index counted from 1 not a real fd. +field, like a non-direct accept request. This function prepares an async .BR accept4 (2) @@ -112,7 +123,7 @@ None .SH ERRORS The CQE .I res -field will contain the result of the operation. For singleshot accept,the +field will contain the result of the operation. For singleshot accept, the non-direct accept returns the installed file descriptor as its value, the direct accept returns .B 0 -- cgit v1.2.3 From c519d1928a631873a622a3b81afdc1f2982ba35b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 09:25:07 -0600 Subject: liburing.h: use helper for io_uring_prep_multishot_accept() Signed-off-by: Jens Axboe --- src/include/liburing.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 9065555..8e69167 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -506,9 +506,7 @@ static inline void io_uring_prep_multishot_accept(struct io_uring_sqe *sqe, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) { - io_uring_prep_rw(IORING_OP_ACCEPT, sqe, fd, addr, 0, - (__u64) (unsigned long) addrlen); - sqe->accept_flags = (__u32) flags; + io_uring_prep_accept(sqe, fd, addr, addrlen, flags); sqe->ioprio |= IORING_ACCEPT_MULTISHOT; } @@ -581,7 +579,6 @@ static inline void io_uring_prep_openat_direct(struct io_uring_sqe *sqe, __io_uring_set_target_fixed_file(sqe, file_index); } - static inline void io_uring_prep_close(struct io_uring_sqe *sqe, int fd) { io_uring_prep_rw(IORING_OP_CLOSE, sqe, fd, NULL, 0, 0); -- cgit v1.2.3 From 91040e8b1e22de8ec79161bba6ced308cdf6b8fd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 09:28:11 -0600 Subject: open/openat2: update man page to include IORING_FILE_INDEX_ALLOC Signed-off-by: Jens Axboe --- man/io_uring_prep_openat.3 | 12 ++++++++++++ man/io_uring_prep_openat2.3 | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index 8094619..b0f0946 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -67,6 +67,18 @@ Note that old kernels don't check the SQE field, which is not a problem for liburing helpers, but users of the raw io_uring interface need to zero SQEs to avoid unexpected behavior. +If +.B IORING_FILE_INDEX_ALLOC +is used as the +.I file_index +for a direct open, then io_uring will allocate a free direct descriptor in +the existing table. The allocated descriptor is returned in the CQE +.I res +field just like it would be for a non-direct open request. If no more entries +are available in the direct descriptor table, +.B -ENFILE +is returned instead. + This function prepares an async .BR openat (2) request. See that man page for details. diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 4898e30..96682d8 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -67,6 +67,17 @@ Note that old kernels don't check the SQE .I file_index field, which is not a problem for liburing helpers, but users of the raw io_uring interface need to zero SQEs to avoid unexpected behavior. +If +.B IORING_FILE_INDEX_ALLOC +is used as the +.I file_index +for a direct open, then io_uring will allocate a free direct descriptor in +the existing table. The allocated descriptor is returned in the CQE +.I res +field just like it would be for a non-direct open request. If no more entries +are available in the direct descriptor table, +.B -ENFILE +is returned instead. This function prepares an async .BR openat2 (2) -- cgit v1.2.3 From 846097febe8eedfbce550c584f023459d614fbf4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 09:35:04 -0600 Subject: queue: add new IORING_SQ_TASKRUN flag Check it in cq_ring_needs_flush(), so that a peek operation will notice and enter the kernel to flush completions. Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 1 + src/queue.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index bfb3548..3225d04 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -240,6 +240,7 @@ struct io_sqring_offsets { */ #define IORING_SQ_NEED_WAKEUP (1U << 0) /* needs io_uring_enter wakeup */ #define IORING_SQ_CQ_OVERFLOW (1U << 1) /* CQ ring is overflown */ +#define IORING_SQ_TASKRUN (1U << 2) /* task should enter the kernel */ struct io_cqring_offsets { __u32 head; diff --git a/src/queue.c b/src/queue.c index 856d270..36b4b29 100644 --- a/src/queue.c +++ b/src/queue.c @@ -35,7 +35,8 @@ static inline bool sq_ring_needs_enter(struct io_uring *ring, unsigned *flags) static inline bool cq_ring_needs_flush(struct io_uring *ring) { - return IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_CQ_OVERFLOW; + return IO_URING_READ_ONCE(*ring->sq.kflags) & + (IORING_SQ_CQ_OVERFLOW | IORING_SQ_TASKRUN); } static inline bool cq_ring_needs_enter(struct io_uring *ring) -- cgit v1.2.3 From 15af89d0d906791639ac7950f4f12ed9f30341d3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 09:42:22 -0600 Subject: Add sparse registration helper and kernel definition Signed-off-by: Jens Axboe --- man/io_uring_register_files.3 | 20 +++++++++++++++++--- src/include/liburing.h | 1 + src/include/liburing/io_uring.h | 6 ++++-- src/liburing.map | 1 + src/register.c | 25 +++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index e2fed47..cf31460 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -13,10 +13,15 @@ io_uring_register_files - register file descriptors .BI "int io_uring_register_files(struct io_uring *" ring "," .BI " const int *" files "," .BI " unsigned " nr_files ");" +.BI +.BI "int io_uring_register_files_sparse(struct io_uring *" ring "," +.BI " unsigned " nr_files ");" .PP .SH DESCRIPTION .PP -The io_uring_register_files() function registers +The +.BR io_uring_register_files() +function registers .I nr_files number of file descriptors defined by the array .I files @@ -24,12 +29,21 @@ belonging to the .I ring for subsequent operations. -After the caller has registered the buffers, they can be used with the -submission queue polling operations. +The +.BR io_uring_register_files_sparse() +function registers an empty file table of +.I nr_files +number of file descriptors. The sparse variant is available in kernels 5.19 +and later. + +Registering a file table is a prerequisite for using any request that uses +direct descriptors. .SH RETURN VALUE On success .BR io_uring_register_files (3) +and +.BR io_uring_register_files_sparse (3) returns 0. On failure it returns -errno. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_unregister_files (3) diff --git a/src/include/liburing.h b/src/include/liburing.h index 5c03061..c220e90 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -151,6 +151,7 @@ int io_uring_register_files(struct io_uring *ring, const int *files, unsigned nr_files); int io_uring_register_files_tags(struct io_uring *ring, const int *files, const __u64 *tags, unsigned nr); +int io_uring_register_files_sparse(struct io_uring *ring, unsigned nr); int io_uring_register_files_update_tag(struct io_uring *ring, unsigned off, const int *files, const __u64 *tags, unsigned nr_files); diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 3225d04..2541573 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -355,10 +355,12 @@ struct io_uring_files_update { __aligned_u64 /* __s32 * */ fds; }; +#define IORING_RSRC_REGISTER_SPARSE (1U << 0) + struct io_uring_rsrc_register { __u32 nr; - __u32 resv; - __u64 resv2; + __u32 flags; + __u32 resv2; __aligned_u64 data; __aligned_u64 tags; }; diff --git a/src/liburing.map b/src/liburing.map index c83a15f..1e66849 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -50,4 +50,5 @@ LIBURING_2.2 { io_uring_submit_and_wait_timeout; io_uring_register_ring_fd; io_uring_unregister_ring_fd; + io_uring_register_files_sparse; } LIBURING_2.1; diff --git a/src/register.c b/src/register.c index 8cdc332..dde2038 100644 --- a/src/register.c +++ b/src/register.c @@ -113,6 +113,31 @@ static int increase_rlimit_nofile(unsigned nr) return 0; } +int io_uring_register_files_sparse(struct io_uring *ring, unsigned nr) +{ + struct io_uring_rsrc_register reg = { + .flags = IORING_RSRC_REGISTER_SPARSE, + .nr = nr, + }; + int ret, did_increase = 0; + + do { + ret = ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_FILES2, ®, + sizeof(reg)); + if (ret >= 0) + break; + if (ret == -EMFILE && !did_increase) { + did_increase = 1; + increase_rlimit_nofile(nr); + continue; + } + break; + } while (1); + + return ret; +} + int io_uring_register_files_tags(struct io_uring *ring, const int *files, const __u64 *tags, unsigned nr) { -- cgit v1.2.3 From 961bfbda2d4b6995d598dd2bf59176aa738a9cd1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 15:07:19 -0600 Subject: test/open-direct-pick.c: add test case for open direct with alloc Test case that tests the basic functionality of openat with direct descriptors and asking io_uring to allocate the descriptors. Signed-off-by: Jens Axboe --- test/Makefile | 1 + test/open-direct-pick.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 test/open-direct-pick.c diff --git a/test/Makefile b/test/Makefile index 60b204b..7cb7178 100644 --- a/test/Makefile +++ b/test/Makefile @@ -104,6 +104,7 @@ test_srcs := \ openat2.c \ open-close.c \ open-direct-link.c \ + open-direct-pick.c \ personality.c \ pipe-eof.c \ pipe-reuse.c \ diff --git a/test/open-direct-pick.c b/test/open-direct-pick.c new file mode 100644 index 0000000..b1597e7 --- /dev/null +++ b/test/open-direct-pick.c @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: run various openat(2) tests + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "liburing.h" + +#define FDS 800 + +static int no_direct_pick; + +static int submit_wait(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + int ret; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + return 1; + } + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + return 1; + } + + ret = cqe->res; + io_uring_cqe_seen(ring, cqe); + return ret; +} + +static inline int try_close(struct io_uring *ring, int slot) +{ + struct io_uring_sqe *sqe; + + sqe = io_uring_get_sqe(ring); + io_uring_prep_close_direct(sqe, slot); + return submit_wait(ring); +} + +static int do_opens(struct io_uring *ring, const char *path, int nr, + int expect_enfile) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int i, ret; + + for (i = 0; i < nr; i++) { + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + goto err; + } + io_uring_prep_openat_direct(sqe, -1, path, O_RDONLY, 0, 0); + sqe->file_index = UINT_MAX; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + goto err; + } + } + + for (i = 0; i < nr; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + goto err; + } + ret = cqe->res; + if (ret < 0) { + if (!expect_enfile || ret != -ENFILE) { + printf("open=%d, %d\n", cqe->res, i); + goto err; + } + if (!i && ret == -EINVAL) { + no_direct_pick = 1; + return 0; + } + } + io_uring_cqe_seen(ring, cqe); + } + return 0; +err: + return 1; +} + +static int test_openat(struct io_uring *ring, const char *path) +{ + int ret, i; + + /* open all */ + ret = do_opens(ring, path, FDS, 0); + if (ret) + goto err; + if (no_direct_pick) + return 0; + + /* now close 100 randomly */ + for (i = 0; i < 100; i++) { + do { + int slot = rand() % FDS; + ret = try_close(ring, slot); + if (ret == -EBADF) + continue; + break; + } while (1); + } + + /* opening 100 should work, we closed 100 */ + ret = do_opens(ring, path, 100, 0); + if (ret) + goto err; + + /* we should be full now, expect -ENFILE */ + ret = do_opens(ring, path, 1, 1); + if (ret) + goto err; + + return ret; +err: + fprintf(stderr,"%s: err=%d\n", __FUNCTION__, ret); + return -1; +} + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + const char *path; + int ret; + + if (argc > 1) + return 0; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed\n"); + return 1; + } + + ret = io_uring_register_files_sparse(&ring, FDS); + if (ret ) { + if (ret != -EINVAL) { + fprintf(stderr, "Sparse file registration failed\n"); + return 1; + } + /* skip, kernel doesn't support sparse file array */ + return 0; + } + + path = "/tmp/.open.close"; + t_create_file(path, 4096); + + ret = test_openat(&ring, path); + if (ret < 0) { + if (ret == -EINVAL) { + fprintf(stdout, "Open not supported, skipping\n"); + goto done; + } + fprintf(stderr, "test_openat absolute failed: %d\n", ret); + goto err; + } + +done: + unlink(path); + return 0; +err: + unlink(path); + return 1; +} -- cgit v1.2.3 From 36d6378c70e682bbacb4625c4ae1b72e4435c8da Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 15:31:58 -0600 Subject: io_uring.h: add IORING_CQE_F_SOCK_NONEMPTY Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index c9b3593..fac6518 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -217,9 +217,11 @@ struct io_uring_cqe { * * IORING_CQE_F_BUFFER If set, the upper 16 bits are the buffer ID * IORING_CQE_F_MORE If set, parent SQE will generate more CQE entries + * IORING_CQE_F_SOCK_NONEMPTY If set, more data to read after socket recv */ #define IORING_CQE_F_BUFFER (1U << 0) #define IORING_CQE_F_MORE (1U << 1) +#define IORING_CQE_F_SOCK_NONEMPTY (1U << 2) enum { IORING_CQE_BUFFER_SHIFT = 16, -- cgit v1.2.3 From 5d52bb71eeecb92134bd4cea42c280a08f5714c7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 15:35:05 -0600 Subject: io_uring.h: add IORING_RECVSEND_POLL_FIRST This flag can be used by send/sendmsg or recv/recvmsg to tell io_uring that it expects the socket to not be immediately ready for send or recv. For that case, it's worthless trying to do IO first, it's better to just arm poll internally and let that drive the first attempt. Can be used in conjunction with the IORING_CQE_F_SOCK_NONEMPTY feedback from the kernel, or independently. Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index fac6518..ce533cd 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -203,6 +203,16 @@ enum { #define IORING_ASYNC_CANCEL_FD (1U << 1) #define IORING_ASYNC_CANCEL_ANY (1U << 2) +/* + * send/sendmsg and recv/recvmsg flags (sqe->addr2) + * + * IORING_RECVSEND_POLL_FIRST If set, instead of first attempting to send + * or receive and arm poll if that yields an + * -EAGAIN result, arm poll upfront and skip + * the initial transfer attempt. + */ +#define IORING_RECVSEND_POLL_FIRST (1U << 0) + /* * IO completion data structure (Completion Queue Entry) */ -- cgit v1.2.3 From a886f04557c676270152660816eeba1f3d54560b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 15:44:40 -0600 Subject: test/send_recvmsg.c: only check buffer group ID if set This test assumes that the only valid flag being set for a send/recv is IORING_CQE_F_BUFFER. But that isn't necessarily true, so check specifically for whether this is a provided buffer return before checking the buffer group ID. Signed-off-by: Jens Axboe --- test/send_recvmsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index f607b5c..2d9315b 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -112,7 +112,7 @@ static int do_recvmsg(struct io_uring *ring, char buf[MAX_MSG + 1], fprintf(stderr, "%s: failed cqe: %d\n", __FUNCTION__, cqe->res); goto err; } - if (cqe->flags) { + if (cqe->flags & IORING_CQE_F_BUFFER) { int bid = cqe->flags >> 16; if (bid != BUF_BID) fprintf(stderr, "Buffer ID mismatch %d\n", bid); -- cgit v1.2.3 From d6927ea5786d3056dabf696c6861cc10a864de79 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 20 Feb 2022 11:36:35 -0700 Subject: io_uring.h: add IORING_SETUP_SQE128 This asks the kernel to setup a ring with 128-byte SQE entries. May fail with -EINVAL if the kernel doesn't support this feature. If the kernel does support the feature, then the ring will support big sqe entries which some commands may require. Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 166d8ca..ad9c929 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -108,6 +108,7 @@ enum { #define IORING_SETUP_ATTACH_WQ (1U << 5) /* attach to existing wq */ #define IORING_SETUP_R_DISABLED (1U << 6) /* start with ring disabled */ #define IORING_SETUP_SUBMIT_ALL (1U << 7) /* continue submit on error */ +#define IORING_SETUP_SQE128 (1U << 8) /* SQEs are 128b */ enum { IORING_OP_NOP, -- cgit v1.2.3 From 1efee07cc554c0d59ffbc323b577e28bc96fac24 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 20 Feb 2022 11:34:46 -0700 Subject: setup: add basic support for SQE128 Adjust the helpers for getting ring size and knowing how much memory we need for a ring of a given size, and basic support for knowing how much to increment a ring when an SQE is allocated. Signed-off-by: Jens Axboe --- src/include/liburing.h | 13 ++++++++++--- src/setup.c | 28 ++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 89b2e5b..eebb23a 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -969,13 +969,20 @@ static inline struct io_uring_sqe *_io_uring_get_sqe(struct io_uring *ring) struct io_uring_sq *sq = &ring->sq; unsigned int head = io_uring_smp_load_acquire(sq->khead); unsigned int next = sq->sqe_tail + 1; - struct io_uring_sqe *sqe = NULL; + int shift = 0; + + if (ring->flags & IORING_SETUP_SQE128) + shift = 1; if (next - head <= *sq->kring_entries) { - sqe = &sq->sqes[sq->sqe_tail & *sq->kring_mask]; + struct io_uring_sqe *sqe; + + sqe = &sq->sqes[(sq->sqe_tail & *sq->kring_mask) << shift]; sq->sqe_tail = next; + return sqe; } - return sqe; + + return NULL; } #ifndef LIBURING_INTERNAL diff --git a/src/setup.c b/src/setup.c index 35981da..aec8b33 100644 --- a/src/setup.c +++ b/src/setup.c @@ -56,8 +56,10 @@ static int io_uring_mmap(int fd, struct io_uring_params *p, sq->kdropped = sq->ring_ptr + p->sq_off.dropped; sq->array = sq->ring_ptr + p->sq_off.array; - size = p->sq_entries * sizeof(struct io_uring_sqe); - sq->sqes = __sys_mmap(0, size, PROT_READ | PROT_WRITE, + size = sizeof(struct io_uring_sqe); + if (p->flags & IORING_SETUP_SQE128) + size += 64; + sq->sqes = __sys_mmap(0, size * p->sq_entries, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQES); if (IS_ERR(sq->sqes)) { ret = PTR_ERR(sq->sqes); @@ -109,7 +111,10 @@ int io_uring_ring_dontfork(struct io_uring *ring) if (!ring->sq.ring_ptr || !ring->sq.sqes || !ring->cq.ring_ptr) return -EINVAL; - len = *ring->sq.kring_entries * sizeof(struct io_uring_sqe); + len = sizeof(struct io_uring_sqe); + if (ring->flags & IORING_SETUP_SQE128) + len += 64; + len *= *ring->sq.kring_entries; ret = __sys_madvise(ring->sq.sqes, len, MADV_DONTFORK); if (ret < 0) return ret; @@ -166,8 +171,12 @@ void io_uring_queue_exit(struct io_uring *ring) { struct io_uring_sq *sq = &ring->sq; struct io_uring_cq *cq = &ring->cq; + size_t sqe_size; - __sys_munmap(sq->sqes, *sq->kring_entries * sizeof(struct io_uring_sqe)); + sqe_size = sizeof(struct io_uring_sqe); + if (ring->flags & IORING_SETUP_SQE128) + sqe_size += 64; + __sys_munmap(sq->sqes, sqe_size * *sq->kring_entries); io_uring_unmap_rings(sq, cq); /* * Not strictly required, but frees up the slot we used now rather @@ -239,8 +248,8 @@ static size_t npages(size_t size, unsigned page_size) #define KRING_SIZE 320 -static size_t rings_size(unsigned entries, unsigned cq_entries, - unsigned page_size) +static size_t rings_size(struct io_uring_params *p, unsigned entries, + unsigned cq_entries, unsigned page_size) { size_t pages, sq_size, cq_size; @@ -249,7 +258,10 @@ static size_t rings_size(unsigned entries, unsigned cq_entries, cq_size = (cq_size + 63) & ~63UL; pages = (size_t) 1 << npages(cq_size, page_size); - sq_size = sizeof(struct io_uring_sqe) * entries; + sq_size = sizeof(struct io_uring_sqe); + if (p->flags & IORING_SETUP_SQE128) + sq_size += 64; + sq_size *= entries; pages += (size_t) 1 << npages(sq_size, page_size); return pages * page_size; } @@ -317,7 +329,7 @@ ssize_t io_uring_mlock_size_params(unsigned entries, struct io_uring_params *p) } page_size = get_page_size(); - return rings_size(entries, cq_entries, page_size); + return rings_size(p, entries, cq_entries, page_size); } /* -- cgit v1.2.3 From e6f6a2d0e4ff10cadd13d115c48b36df11b846b4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 20 Feb 2022 12:08:42 -0700 Subject: test/nop: add basic IORING_SETUP_SQE128 tests Just repeats the original test cases, but using a big ring. Assign and check for user_data never being NULL, which would be a common issue with mistakes between big and normal SQEs. Signed-off-by: Jens Axboe --- test/nop.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/test/nop.c b/test/nop.c index 82201bd..d477a1b 100644 --- a/test/nop.c +++ b/test/nop.c @@ -12,6 +12,8 @@ #include "liburing.h" +static int seq; + static int test_single_nop(struct io_uring *ring) { struct io_uring_cqe *cqe; @@ -25,6 +27,7 @@ static int test_single_nop(struct io_uring *ring) } io_uring_prep_nop(sqe); + sqe->user_data = ++seq; ret = io_uring_submit(ring); if (ret <= 0) { @@ -37,7 +40,10 @@ static int test_single_nop(struct io_uring *ring) fprintf(stderr, "wait completion %d\n", ret); goto err; } - + if (!cqe->user_data) { + fprintf(stderr, "Unexpected 0 user_data\n"); + goto err; + } io_uring_cqe_seen(ring, cqe); return 0; err: @@ -60,6 +66,7 @@ static int test_barrier_nop(struct io_uring *ring) io_uring_prep_nop(sqe); if (i == 4) sqe->flags = IOSQE_IO_DRAIN; + sqe->user_data = ++seq; } ret = io_uring_submit(ring); @@ -77,6 +84,10 @@ static int test_barrier_nop(struct io_uring *ring) fprintf(stderr, "wait completion %d\n", ret); goto err; } + if (!cqe->user_data) { + fprintf(stderr, "Unexpected 0 user_data\n"); + goto err; + } io_uring_cqe_seen(ring, cqe); } @@ -85,15 +96,12 @@ err: return 1; } -int main(int argc, char *argv[]) +static int test_p(struct io_uring_params *p) { struct io_uring ring; int ret; - if (argc > 1) - return 0; - - ret = io_uring_queue_init(8, &ring, 0); + ret = io_uring_queue_init_params(8, &ring, p); if (ret) { fprintf(stderr, "ring setup failed: %d\n", ret); return 1; @@ -102,12 +110,54 @@ int main(int argc, char *argv[]) ret = test_single_nop(&ring); if (ret) { fprintf(stderr, "test_single_nop failed\n"); - return ret; + goto err; } ret = test_barrier_nop(&ring); if (ret) { fprintf(stderr, "test_barrier_nop failed\n"); + goto err; + } + + io_uring_queue_exit(&ring); + return 0; +err: + io_uring_queue_exit(&ring); + return ret; +} + +static int test_normal_ring(void) +{ + struct io_uring_params p = { }; + + return test_p(&p); +} + +static int test_big_ring(void) +{ + struct io_uring_params p = { }; + + p.flags = IORING_SETUP_SQE128; + return test_p(&p); +} + + +int main(int argc, char *argv[]) +{ + int ret; + + if (argc > 1) + return 0; + + ret = test_normal_ring(); + if (ret) { + fprintf(stderr, "Normal ring test failed\n"); + return ret; + } + + ret = test_big_ring(); + if (ret) { + fprintf(stderr, "Big ring test failed\n"); return ret; } -- cgit v1.2.3 From 5fa7867d8c5b027a421c72dfc68c7c4ac186dbb9 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Mon, 25 Apr 2022 11:26:34 -0700 Subject: liburing: Update io_uring.h with large CQE kernel changes This updates the io_uring.h file with the changes in the kernel. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220425182639.2446370-2-shr@fb.com Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index ad9c929..4e1f994 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -109,6 +109,7 @@ enum { #define IORING_SETUP_R_DISABLED (1U << 6) /* start with ring disabled */ #define IORING_SETUP_SUBMIT_ALL (1U << 7) /* continue submit on error */ #define IORING_SETUP_SQE128 (1U << 8) /* SQEs are 128b */ +#define IORING_SETUP_CQE32 (1U << 9) /* CQEs are 32b */ enum { IORING_OP_NOP, @@ -227,6 +228,12 @@ struct io_uring_cqe { __u64 user_data; /* sqe->data submission passed back */ __s32 res; /* result code for this event */ __u32 flags; + + /* + * If the ring is initialized wit IORING_SETUP_CQE32, then this field + * contains 16-bytes of padding, doubling the size fo the CQE. + */ + __u64 big_cqe[]; }; /* -- cgit v1.2.3 From 7eb8df1b627cce6ccb1ce1b422a713a06943eb6e Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Mon, 25 Apr 2022 11:26:35 -0700 Subject: liburing: increase mmap size for large CQE's This doubles the mmap size for large CQE's. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220425182639.2446370-3-shr@fb.com Signed-off-by: Jens Axboe --- src/setup.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/setup.c b/src/setup.c index aec8b33..dd6a712 100644 --- a/src/setup.c +++ b/src/setup.c @@ -21,8 +21,12 @@ static int io_uring_mmap(int fd, struct io_uring_params *p, size_t size; int ret; + size = sizeof(struct io_uring_cqe); + if (p->flags & IORING_SETUP_CQE32) + size += sizeof(struct io_uring_cqe); + sq->ring_sz = p->sq_off.array + p->sq_entries * sizeof(unsigned); - cq->ring_sz = p->cq_off.cqes + p->cq_entries * sizeof(struct io_uring_cqe); + cq->ring_sz = p->cq_off.cqes + p->cq_entries * size; if (p->features & IORING_FEAT_SINGLE_MMAP) { if (cq->ring_sz > sq->ring_sz) -- cgit v1.2.3 From 0ba877d0e76f378c01a34c221bf1dc67d158744c Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Mon, 25 Apr 2022 11:26:36 -0700 Subject: liburing: return correct ring size for large CQE's Return the correct ring_size when large CQE's are used. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220425182639.2446370-4-shr@fb.com Signed-off-by: Jens Axboe --- src/setup.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/setup.c b/src/setup.c index dd6a712..d2adc7f 100644 --- a/src/setup.c +++ b/src/setup.c @@ -257,8 +257,11 @@ static size_t rings_size(struct io_uring_params *p, unsigned entries, { size_t pages, sq_size, cq_size; - cq_size = KRING_SIZE; - cq_size += cq_entries * sizeof(struct io_uring_cqe); + cq_size = sizeof(struct io_uring_cqe); + if (p->flags & IORING_SETUP_CQE32) + cq_size += sizeof(struct io_uring_cqe); + cq_size *= cq_entries; + cq_size += KRING_SIZE; cq_size = (cq_size + 63) & ~63UL; pages = (size_t) 1 << npages(cq_size, page_size); -- cgit v1.2.3 From 406176e9a0e7c023a6572d734d4e2d40e3e2c4d6 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Mon, 25 Apr 2022 11:26:37 -0700 Subject: liburing: index large CQE's correctly Large CQE's need to take into account that each CQE has double the size. When the CQE array is indexed, the offset into the array needs to be changed accordingly. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220425182639.2446370-5-shr@fb.com Signed-off-by: Jens Axboe --- src/include/liburing.h | 18 ++++++++++++++++-- src/queue.c | 6 +++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index eebb23a..1aedc35 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -189,6 +189,16 @@ int __io_uring_get_cqe(struct io_uring *ring, #define LIBURING_UDATA_TIMEOUT ((__u64) -1) +/* + * Calculates the step size for CQE iteration. + * For standard CQE's its 1, for big CQE's its two. + */ +#define io_uring_cqe_shift(ring) \ + (!!((ring)->flags & IORING_SETUP_CQE32)) + +#define io_uring_cqe_index(ring,ptr,mask) \ + (((ptr) & (mask)) << io_uring_cqe_shift(ring)) + #define io_uring_for_each_cqe(ring, head, cqe) \ /* \ * io_uring_smp_load_acquire() enforces the order of tail \ @@ -196,7 +206,7 @@ int __io_uring_get_cqe(struct io_uring *ring, */ \ for (head = *(ring)->cq.khead; \ (cqe = (head != io_uring_smp_load_acquire((ring)->cq.ktail) ? \ - &(ring)->cq.cqes[head & (*(ring)->cq.kring_mask)] : NULL)); \ + &(ring)->cq.cqes[io_uring_cqe_index(ring, head, *(ring)->cq.kring_mask)] : NULL)); \ head++) \ /* @@ -901,6 +911,10 @@ static inline int __io_uring_peek_cqe(struct io_uring *ring, int err = 0; unsigned available; unsigned mask = *ring->cq.kring_mask; + int shift = 0; + + if (ring->flags & IORING_SETUP_CQE32) + shift = 1; do { unsigned tail = io_uring_smp_load_acquire(ring->cq.ktail); @@ -911,7 +925,7 @@ static inline int __io_uring_peek_cqe(struct io_uring *ring, if (!available) break; - cqe = &ring->cq.cqes[head & mask]; + cqe = &ring->cq.cqes[(head & mask) << shift]; if (!(ring->features & IORING_FEAT_EXT_ARG) && cqe->user_data == LIBURING_UDATA_TIMEOUT) { if (cqe->res < 0) diff --git a/src/queue.c b/src/queue.c index 36b4b29..ce0ecf6 100644 --- a/src/queue.c +++ b/src/queue.c @@ -133,6 +133,10 @@ unsigned io_uring_peek_batch_cqe(struct io_uring *ring, { unsigned ready; bool overflow_checked = false; + int shift = 0; + + if (ring->flags & IORING_SETUP_CQE32) + shift = 1; again: ready = io_uring_cq_ready(ring); @@ -145,7 +149,7 @@ again: count = count > ready ? ready : count; last = head + count; for (;head != last; head++, i++) - cqes[i] = &ring->cq.cqes[head & mask]; + cqes[i] = &ring->cq.cqes[(head & mask) << shift]; return count; } -- cgit v1.2.3 From a2b20bcad03706101c3fffe77f0ced1ebcc1b9ff Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Mon, 25 Apr 2022 11:26:38 -0700 Subject: liburing: add large CQE tests to nop test This adds two test cases for large CQE's: - Single NOP test, which checks that the new extra1 and extra2 fields are set. - Multiple NOP submission test which also checks for the new fields. Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220425182639.2446370-6-shr@fb.com [axboe: fixup cqe naming] Signed-off-by: Jens Axboe --- test/nop.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/nop.c b/test/nop.c index d477a1b..8656373 100644 --- a/test/nop.c +++ b/test/nop.c @@ -19,6 +19,7 @@ static int test_single_nop(struct io_uring *ring) struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; int ret; + bool cqe32 = (ring->flags & IORING_SETUP_CQE32); sqe = io_uring_get_sqe(ring); if (!sqe) { @@ -27,6 +28,10 @@ static int test_single_nop(struct io_uring *ring) } io_uring_prep_nop(sqe); + if (cqe32) { + sqe->addr = 1234; + sqe->addr2 = 5678; + } sqe->user_data = ++seq; ret = io_uring_submit(ring); @@ -44,6 +49,17 @@ static int test_single_nop(struct io_uring *ring) fprintf(stderr, "Unexpected 0 user_data\n"); goto err; } + if (cqe32) { + if (cqe->big_cqe[0] != 1234) { + fprintf(stderr, "Unexpected extra1\n"); + goto err; + + } + if (cqe->big_cqe[1] != 5678) { + fprintf(stderr, "Unexpected extra2\n"); + goto err; + } + } io_uring_cqe_seen(ring, cqe); return 0; err: @@ -55,6 +71,7 @@ static int test_barrier_nop(struct io_uring *ring) struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; int ret, i; + bool cqe32 = (ring->flags & IORING_SETUP_CQE32); for (i = 0; i < 8; i++) { sqe = io_uring_get_sqe(ring); @@ -66,6 +83,10 @@ static int test_barrier_nop(struct io_uring *ring) io_uring_prep_nop(sqe); if (i == 4) sqe->flags = IOSQE_IO_DRAIN; + if (cqe32) { + sqe->addr = 1234; + sqe->addr2 = 5678; + } sqe->user_data = ++seq; } @@ -88,6 +109,16 @@ static int test_barrier_nop(struct io_uring *ring) fprintf(stderr, "Unexpected 0 user_data\n"); goto err; } + if (cqe32) { + if (cqe->big_cqe[0] != 1234) { + fprintf(stderr, "Unexpected extra1\n"); + goto err; + } + if (cqe->big_cqe[1] != 5678) { + fprintf(stderr, "Unexpected extra2\n"); + goto err; + } + } io_uring_cqe_seen(ring, cqe); } -- cgit v1.2.3 From 855ffa0d9fc7875ada65ec23a086489dac59e2c9 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Mon, 25 Apr 2022 11:26:39 -0700 Subject: liburing: Test all configurations with NOP test This runs the NOP test with all four configurations: - default SQE and CQE size - large SQE size - large CQE size - large SQE and large CQE size Signed-off-by: Stefan Roesch Link: https://lore.kernel.org/r/20220425182639.2446370-7-shr@fb.com Signed-off-by: Jens Axboe --- test/nop.c | 43 +++++++++++++------------------------------ test/test.h | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 test/test.h diff --git a/test/nop.c b/test/nop.c index 8656373..59da22c 100644 --- a/test/nop.c +++ b/test/nop.c @@ -11,6 +11,7 @@ #include #include "liburing.h" +#include "test.h" static int seq; @@ -127,12 +128,14 @@ err: return 1; } -static int test_p(struct io_uring_params *p) +static int test_ring(unsigned flags) { struct io_uring ring; + struct io_uring_params p = { }; int ret; - ret = io_uring_queue_init_params(8, &ring, p); + p.flags = flags; + ret = io_uring_queue_init_params(8, &ring, &p); if (ret) { fprintf(stderr, "ring setup failed: %d\n", ret); return 1; @@ -150,29 +153,11 @@ static int test_p(struct io_uring_params *p) goto err; } - io_uring_queue_exit(&ring); - return 0; err: io_uring_queue_exit(&ring); return ret; } -static int test_normal_ring(void) -{ - struct io_uring_params p = { }; - - return test_p(&p); -} - -static int test_big_ring(void) -{ - struct io_uring_params p = { }; - - p.flags = IORING_SETUP_SQE128; - return test_p(&p); -} - - int main(int argc, char *argv[]) { int ret; @@ -180,17 +165,15 @@ int main(int argc, char *argv[]) if (argc > 1) return 0; - ret = test_normal_ring(); - if (ret) { - fprintf(stderr, "Normal ring test failed\n"); - return ret; - } - - ret = test_big_ring(); - if (ret) { - fprintf(stderr, "Big ring test failed\n"); - return ret; + FOR_ALL_TEST_CONFIGS { + fprintf(stderr, "Testing %s config\n", IORING_GET_TEST_CONFIG_DESCRIPTION()); + ret = test_ring(IORING_GET_TEST_CONFIG_FLAGS()); + if (ret) { + fprintf(stderr, "Normal ring test failed\n"); + return ret; + } } + fprintf(stderr, "PASS\n"); return 0; } diff --git a/test/test.h b/test/test.h new file mode 100644 index 0000000..3628163 --- /dev/null +++ b/test/test.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: Test configs for tests. + */ +#ifndef LIBURING_TEST_H +#define LIBURING_TEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct io_uring_test_config { + unsigned int flags; + const char *description; +} io_uring_test_config; + +io_uring_test_config io_uring_test_configs[] = { + { 0, "default" }, + { IORING_SETUP_SQE128, "large SQE"}, + { IORING_SETUP_CQE32, "large CQE"}, + { IORING_SETUP_SQE128 | IORING_SETUP_CQE32, "large SQE/CQE" }, +}; + +#define FOR_ALL_TEST_CONFIGS \ + for (int i = 0; i < sizeof(io_uring_test_configs) / sizeof(io_uring_test_configs[0]); i++) + +#define IORING_GET_TEST_CONFIG_FLAGS() (io_uring_test_configs[i].flags) +#define IORING_GET_TEST_CONFIG_DESCRIPTION() (io_uring_test_configs[i].description) + + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.2.3 From 707550cb0d7c60caa1f788cb416ea52c5a1a4535 Mon Sep 17 00:00:00 2001 From: Krishna Kanth Reddy Date: Wed, 11 May 2022 14:54:46 +0530 Subject: liburing: Update io_uring.h This updates the io_uring.h file with the changes in the kernel. Fixed the build issue that arises because of the updated fields. Signed-off-by: Krishna Kanth Reddy --- src/include/liburing/io_uring.h | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 4e1f994..0acf05d 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -108,10 +108,25 @@ enum { #define IORING_SETUP_ATTACH_WQ (1U << 5) /* attach to existing wq */ #define IORING_SETUP_R_DISABLED (1U << 6) /* start with ring disabled */ #define IORING_SETUP_SUBMIT_ALL (1U << 7) /* continue submit on error */ -#define IORING_SETUP_SQE128 (1U << 8) /* SQEs are 128b */ -#define IORING_SETUP_CQE32 (1U << 9) /* CQEs are 32b */ +/* + * Cooperative task running. When requests complete, they often require + * forcing the submitter to transition to the kernel to complete. If this + * flag is set, work will be done when the task transitions anyway, rather + * than force an inter-processor interrupt reschedule. This avoids interrupting + * a task running in userspace, and saves an IPI. + */ +#define IORING_SETUP_COOP_TASKRUN (1U << 8) +/* + * If COOP_TASKRUN is set, get notified if task work is available for + * running and a kernel transition would be needed to run it. This sets + * IORING_SQ_TASKRUN in the sq ring flags. Not valid with COOP_TASKRUN. + */ +#define IORING_SETUP_TASKRUN_FLAG (1U << 9) -enum { +#define IORING_SETUP_SQE128 (1U << 10) /* SQEs are 128 byte */ +#define IORING_SETUP_CQE32 (1U << 11) /* CQEs are 32 byte */ + +enum io_uring_op { IORING_OP_NOP, IORING_OP_READV, IORING_OP_WRITEV, @@ -230,8 +245,8 @@ struct io_uring_cqe { __u32 flags; /* - * If the ring is initialized wit IORING_SETUP_CQE32, then this field - * contains 16-bytes of padding, doubling the size fo the CQE. + * If the ring is initialized with IORING_SETUP_CQE32, then this field + * contains 16-bytes of padding, doubling the size of the CQE. */ __u64 big_cqe[]; }; -- cgit v1.2.3 From 797439af0962b65451425032c1559f0800fca13e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 13 May 2022 11:40:55 -0600 Subject: test/nop: make less verbose and don't fail on older kernels Signed-off-by: Jens Axboe --- test/nop.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/nop.c b/test/nop.c index 59da22c..ce223b3 100644 --- a/test/nop.c +++ b/test/nop.c @@ -137,6 +137,8 @@ static int test_ring(unsigned flags) p.flags = flags; ret = io_uring_queue_init_params(8, &ring, &p); if (ret) { + if (ret == -EINVAL) + return 0; fprintf(stderr, "ring setup failed: %d\n", ret); return 1; } @@ -166,14 +168,13 @@ int main(int argc, char *argv[]) return 0; FOR_ALL_TEST_CONFIGS { - fprintf(stderr, "Testing %s config\n", IORING_GET_TEST_CONFIG_DESCRIPTION()); ret = test_ring(IORING_GET_TEST_CONFIG_FLAGS()); if (ret) { - fprintf(stderr, "Normal ring test failed\n"); + fprintf(stderr, "Normal ring test failed: %s\n", + IORING_GET_TEST_CONFIG_DESCRIPTION()); return ret; } } - fprintf(stderr, "PASS\n"); return 0; } -- cgit v1.2.3 From f6d47365e01235a717038cd291f6b45c0960e39d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 May 2022 20:14:00 -0600 Subject: man/io_uring_setup.2: document 5.19 ring setup flags Signed-off-by: Jens Axboe --- man/io_uring_setup.2 | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index f3911af..0b09667 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -196,6 +196,49 @@ a request. CQEs are still posted for errored request regardless of whether or not this flag is set at ring creation time, the only difference is if the submit sequence is halted or continued when an error is observed. Available since 5.18. +.TP +.B IORING_SETUP_COOP_TASKRUN +By default, io_uring will interrupt a task running in userspace when a +completion event comes in. This is to ensure that completions run in a timely +manner. For a lot of use cases, this is overkill and can cause reduced +performance from both the inter-processor interrupt used to do this, the +kernel/user transition, the needless interruption of the tasks userspace +activities, and reduced batching if completions come in at a rapid rate. Most +applications don't need the forceful interruption, as the events are processed +at any kernel/user transition. The exception are setups where the application +uses multiple threads operating on the same ring, where the application +waiting on completions isn't the one that submitted them. For most other +use cases, setting this flag will improve performance. Available since 5.19. +.TP +.B IORING_SETUP_TASKRUN_FLAG +Used in conjunction with +.B IORING_SETUP_COOP_TASKRUN, +this provides a flag, +.B IORING_SQ_TASKRUN, +which is set in the SQ ring +.I flags +whenever completions are pending that should be processed. liburing will check +for this flag even when doing +.BR io_uring_peek_cqe (3) +and enter the kernel to process them, and applications can do the same. This +makes +.B IORING_SETUP_TASKRUN_FLAG +safe to use even when applications rely on a peek style operation on the CQ +ring to see if anything might be pending to reap. Available since 5.10. +.TP +.B IORING_SETUP_SQE128 +If set, io_uring will use 128-byte SQEs rather than the normal 64-byte sized +variant. This is a requirement for using certain request types, as of 5.19 +only the +.B IORING_OP_URING_CMD +passthrough command for NVMe passthrough needs this. Available since 5.19. +.TP +.B IORING_SETUP_CQE32 +If set, io_uring will use 32-byte CQEs rather than the normal 32-byte sized +variant. This is a requirement for using certain request types, as of 5.19 +only the +.B IORING_OP_URING_CMD +passthrough command for NVMe passthrough needs this. Available since 5.19. .PP If no flags are specified, the io_uring instance is setup for interrupt driven I/O. I/O may be submitted using -- cgit v1.2.3 From a2dcf19a32cfb1c4580ef3a377d4ccb17ba61ddc Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 May 2022 20:29:31 -0600 Subject: man/io_uring_prep_cancel.3: document new 5.19 cancelation flags Signed-off-by: Jens Axboe --- man/io_uring_prep_cancel.3 | 52 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 4c6fc28..0dc574a 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -13,17 +13,22 @@ io_uring_prep_cancel - prepare a cancelation request .BI "void io_uring_prep_cancel(struct io_uring_sqe *" sqe "," .BI " __u64 " user_data "," .BI " int " flags ");" +.BI " +.BI "void io_uring_prep_cancel_fd(struct io_uring_sqe *" sqe "," +.BI " int " fd "," +.BI " int " flags ");" .PP .SH DESCRIPTION .PP -The io_uring_prep_cancel() function prepares a cancelation request. The -submission queue entry +The +.BR io_uring_prep_cancel() +function prepares a cancelation request. The submission queue entry .I sqe is prepared to cancel an existing request identified by .I user_data. -The +For the .I flags -argument is currently unused. +argument, see below. The cancelation request will attempt to find the previously issued request identified by @@ -33,14 +38,49 @@ their .I user_data field in the SQE. +The +.BR io_uring_prep_cancel_fd() +function prepares a cancelation request. The submission queue entry +.I sqe +is prepared to cancel an existing request that used the file descriptor +.I fd. +For the +.I flags +argument, see below. + +The cancelation request will attempt to find the previously issued request +that used +.I fd +as the file descriptor and cancel it. + +By default, the first request matching the criteria given will be canceled. +This can be modified with any of the following flags passed in: +.TP +.B IORING_ASYNC_CANCEL_ALL +Cancel all requests that match the given criteria, rather than just canceling +the first one found. Available since 5.19. +.TP +.B IORING_ASYNC_CANCEL_FD +Match based on the file descriptor used in the original request rather than +the user_data. This is what +.BR io_uring_prep_cancel_fd (3) +sets up. Available since 5.19. +.TP +.B IORING_ASYNC_CANCEL_ANY +Match any request in the ring, regardless of user_data or file descriptor. +Can be used to cancel any pending request in the ring. Available since 5.19. +.P + .SH RETURN VALUE None .SH ERRORS These are the errors that are reported in the CQE .I res -field. On success, +field. If no flags are used to cancel multiple requests, .B 0 -is returned. +is returned on success. If flags are used to match multiple requests, then +a positive value is returned indicating how many requests were found and +canceled. .TP .B -ENOENT The request identified by -- cgit v1.2.3 From cd3f9fff5aa69a91bf412a36c444d8b1e048d439 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 May 2022 20:37:17 -0600 Subject: man/io_uring_prep_recv{msg}.3: add new 5.19 flags Signed-off-by: Jens Axboe --- man/io_uring_prep_recv.3 | 31 +++++++++++++++++++++++++++++-- man/io_uring_prep_recvmsg.3 | 32 +++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 index 972ee72..071a300 100644 --- a/man/io_uring_prep_recv.3 +++ b/man/io_uring_prep_recv.3 @@ -18,7 +18,9 @@ io_uring_prep_recv - prepare a recv request .PP .SH DESCRIPTION .PP -The io_uring_prep_recv() function prepares a recv request. The submission +The +.BR io_uring_prep_recv (3) +function prepares a recv request. The submission queue entry .I sqe is setup to use the file descriptor @@ -32,7 +34,32 @@ and with modifier flags This function prepares an async .BR recv (2) -request. See that man page for details. +request. See that man page for details on the arguments specified to this +prep helper. + +After calling this function, additional io_uring internal modifier flags +may be set in the SQE +.I off +field. The following flags are supported: +.TP +.B IORING_RECVSEND_POLL_FIRST +If set, io_uring will assume the socket is currently empty and attempting to +receive data will be unsuccessful. For this case, io_uring will arm internal +poll and trigger a receive of the data when the socket has data to be read. +This initial receive attempt can be wasteful for the case where the socket +is expected to be empty, setting this flag will bypass the initial receive +attempt and go straight to arming poll. If poll does indicate that data is +ready to be received, the operation will proceed. + +Can be used with the CQE +.B IORING_CQE_F_SOCK_NONEMPTY +flag, which io_uring will set on CQEs after a +.BR recv (2) +or +.BR recvmsg (2) +operation. If set, the socket still had data to be read after the operation +completed. Both these flags are available since 5.19. +.P .SH RETURN VALUE None diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index 0236b48..a8cf001 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -19,8 +19,9 @@ io_uring_prep_recvmsg - prepare a recvmsg request .PP .SH DESCRIPTION .PP -The io_uring_prep_recvmsg() function prepares a recvmsg request. The submission -queue entry +The +.BR io_uring_prep_recvmsg (3) +function prepares a recvmsg request. The submission queue entry .I sqe is setup to use the file descriptor .I fd @@ -34,7 +35,32 @@ argument. This function prepares an async .BR recvmsg (2) -request. See that man page for details. +request. See that man page for details on the arguments specified to this +prep helper. + +After calling this function, additional io_uring internal modifier flags +may be set in the SQE +.I off +field. The following flags are supported: +.TP +.B IORING_RECVSEND_POLL_FIRST +If set, io_uring will assume the socket is currently empty and attempting to +receive data will be unsuccessful. For this case, io_uring will arm internal +poll and trigger a receive of the data when the socket has data to be read. +This initial receive attempt can be wasteful for the case where the socket +is expected to be empty, setting this flag will bypass the initial receive +attempt and go straight to arming poll. If poll does indicate that data is +ready to be received, the operation will proceed. + +Can be used with the CQE +.B IORING_CQE_F_SOCK_NONEMPTY +flag, which io_uring will set on CQEs after a +.BR recv (2) +or +.BR recvmsg (2) +operation. If set, the socket still had data to be read after the operation +completed. Both these flags are available since 5.19. +.P .SH RETURN VALUE None -- cgit v1.2.3 From 5d84cc6037e3e7abfd0c90be585a05e0e83c36af Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 May 2022 20:40:00 -0600 Subject: man/io_uring_prep_accept.3: note availability of the multishot variants Signed-off-by: Jens Axboe --- man/io_uring_prep_accept.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index bebc262..4f2d6da 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -102,7 +102,7 @@ look at the CQE and see if .B IORING_CQE_F_MORE is set on completion as an indication of whether or not the accept request -will generate further CQEs. +will generate further CQEs. The multishot variants are available since 5.19. For multishot with direct descriptors, .B IORING_FILE_INDEX_ALLOC -- cgit v1.2.3 From 1e8625ad0bc3f6b07eb935bbc6a8203693a7792b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 May 2022 06:03:46 -0600 Subject: io_uring.h: fix merge error The registered buffer rings haven't been added yet, but a hunk snuck into the release anyway. Fix it up. Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 4d736d2..60f12ee 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -417,12 +417,16 @@ struct io_uring_files_update { __aligned_u64 /* __s32 * */ fds; }; +/* + * Register a fully sparse file space, rather than pass in an array of all + * -1 file descriptors. + */ #define IORING_RSRC_REGISTER_SPARSE (1U << 0) struct io_uring_rsrc_register { __u32 nr; __u32 flags; - __u32 resv2; + __u64 resv2; __aligned_u64 data; __aligned_u64 tags; }; -- cgit v1.2.3 From b2d28aea257d0eee40bcdc5c0613712c9e4e8184 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 May 2022 06:04:15 -0600 Subject: io_uring.h: sync with 5.19 io_uring release A few missing bits due to the topic branches not being synced. Signed-off-by: Jens Axboe --- src/include/liburing/io_uring.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 60f12ee..c85f274 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -76,7 +76,7 @@ struct io_uring_sqe { * in. The picked direct descriptor will be returned in cqe->res, or -ENFILE * if the space is full. */ -#define IORING_FILE_INDEX_ALLOC (~0U) +#define IORING_FILE_INDEX_ALLOC (~0U) enum { IOSQE_FIXED_FILE_BIT, @@ -181,6 +181,8 @@ enum io_uring_op { IORING_OP_SETXATTR, IORING_OP_FGETXATTR, IORING_OP_GETXATTR, + IORING_OP_SOCKET, + IORING_OP_URING_CMD, /* this goes last, obviously */ IORING_OP_LAST, @@ -245,6 +247,11 @@ enum io_uring_op { */ #define IORING_RECVSEND_POLL_FIRST (1U << 0) +/* + * accept flags stored in sqe->ioprio + */ +#define IORING_ACCEPT_MULTISHOT (1U << 0) + /* * IO completion data structure (Completion Queue Entry) */ -- cgit v1.2.3 From 45969ce39dc764e12541681ed3ddbafcf7f0de85 Mon Sep 17 00:00:00 2001 From: "Simon A. F. Lund" Date: Tue, 17 May 2022 15:41:28 +0200 Subject: configure: fix compile-checks for statx This is related to the the issue reported here: https://github.com/axboe/liburing/issues/578 A fix for the reported issue changed ``linux/stat.h`` to ``sys/stat.h`` in ``test/statx.c``, however, it did not change the compile-check in ``configure``. This change is needed on Alpine Linux / muslc, where 'statx' is detected by ``configure/compile-check`` but ``sys/stat.h`` does not provide what is needed by ``test/statx.c``. Resulting in a build-error. This changes the compiler-check to match the usage in `tests/statx.c`, thereby fixing the build-error on Alpine Linux / muslc. Signed-off-by: Simon A. F. Lund --- configure | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure b/configure index f2bf041..2c2441b 100755 --- a/configure +++ b/configure @@ -300,7 +300,6 @@ cat > $TMPC << EOF #include #include #include -#include int main(int argc, char **argv) { struct statx x; @@ -321,7 +320,7 @@ cat > $TMPC << EOF #include #include #include -#include +#include int main(int argc, char **argv) { struct statx x; -- cgit v1.2.3 From bb756586aa03e88a9b0b4beb09d9880fffa8cfc7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 May 2022 12:56:12 -0600 Subject: test/msg-ring.c: add IOPOLL test We do allow MSG_RING on an IOPOLL ring, add a test case for it. syzbot found an issue with attempting to poll the MSG_RING request, which would crash. This would trigger it too. Link: https://git.kernel.dk/cgit/linux-block/commit/?h=io_uring-5.18&id=aa184e8671f0f911fc2fb3f68cd506e4d7838faa Signed-off-by: Jens Axboe --- test/msg-ring.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/msg-ring.c b/test/msg-ring.c index 209d61c..48c4a64 100644 --- a/test/msg-ring.c +++ b/test/msg-ring.c @@ -177,7 +177,7 @@ err: int main(int argc, char *argv[]) { - struct io_uring ring, ring2; + struct io_uring ring, ring2, pring; pthread_t thread; void *tret; int ret; @@ -195,6 +195,11 @@ int main(int argc, char *argv[]) fprintf(stderr, "ring setup failed: %d\n", ret); return 1; } + ret = io_uring_queue_init(8, &pring, IORING_SETUP_IOPOLL); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } ret = test_own(&ring); if (ret) { @@ -205,6 +210,11 @@ int main(int argc, char *argv[]) fprintf(stdout, "Skipped\n"); return 0; } + ret = test_own(&pring); + if (ret) { + fprintf(stderr, "test_own iopoll failed\n"); + return ret; + } ret = test_invalid(&ring); if (ret) { -- cgit v1.2.3 From e37c1774b2fd5440d591612ddbc93f4cca1eed5c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 09:10:42 -0600 Subject: Add regression test case for IO submit before exit Impacts 5.15 and earlier. Signed-off-by: Jens Axboe --- test/Makefile | 1 + test/read-before-exit.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 test/read-before-exit.c diff --git a/test/Makefile b/test/Makefile index 8259b15..1545339 100644 --- a/test/Makefile +++ b/test/Makefile @@ -119,6 +119,7 @@ test_srcs := \ poll-v-poll.c \ pollfree.c \ probe.c \ + read-before-exit.c \ read-write.c \ recv-msgall.c \ recv-msgall-stream.c \ diff --git a/test/read-before-exit.c b/test/read-before-exit.c new file mode 100644 index 0000000..be36bd4 --- /dev/null +++ b/test/read-before-exit.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: test if issuing IO from thread and immediately exiting will + * proceed correctly. + * + * Original test case from: https://github.com/axboe/liburing/issues/582 + */ +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +struct data { + struct io_uring *ring; + int timer_fd1; + int timer_fd2; + uint64_t buf1; + uint64_t buf2; +}; + +void *submit(void *data) +{ + struct io_uring_sqe *sqe; + struct data *d = data; + int ret; + + sqe = io_uring_get_sqe(d->ring); + io_uring_prep_read(sqe, d->timer_fd1, &d->buf1, sizeof(d->buf1), 0); + + sqe = io_uring_get_sqe(d->ring); + io_uring_prep_read(sqe, d->timer_fd2, &d->buf2, sizeof(d->buf2), 0); + + ret = io_uring_submit(d->ring); + if (ret != 2) + return (void *) (uintptr_t) 1; + + /* Exit suddenly. */ + return NULL; +} + +static int test(int flags) +{ + struct io_uring_params params = { .flags = flags, }; + struct io_uring ring; + struct data d = { .ring = &ring, }; + pthread_t thread; + void *res; + int ret; + + ret = t_create_ring_params(8, &ring, ¶ms); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret != T_SETUP_OK) + return 1; + + d.timer_fd1 = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + if (d.timer_fd1 < 0) { + perror("timerfd_create"); + return 1; + } + d.timer_fd2 = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + if (d.timer_fd2 < 0) { + perror("timerfd_create"); + return 1; + } + + pthread_create(&thread, NULL, submit, &d); + pthread_join(thread, &res); + + /** Wait for completions and do stuff ... **/ + + io_uring_queue_exit(&ring); + + close(d.timer_fd1); + close(d.timer_fd2); + return !!res; +} + +int main(int argc, char *argv[]) +{ + int ret, i; + + for (i = 0; i < 1000; i++) { + ret = test(0); + if (ret) { + fprintf(stderr, "Test failed\n"); + return ret; + } + } + + for (i = 0; i < 1000; i++) { + ret = test(IORING_SETUP_IOPOLL); + if (ret) { + fprintf(stderr, "Test IOPOLL failed\n"); + return ret; + } + } + + for (i = 0; i < 100; i++) { + ret = test(IORING_SETUP_SQPOLL); + if (ret) { + fprintf(stderr, "Test SQPOLL failed\n"); + return ret; + } + } + + return 0; +} -- cgit v1.2.3 From 73bd005abc29936d36f242f8960af07a4e0fabee Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 13:21:04 -0600 Subject: Add helper for sparse buffer registration Signed-off-by: Jens Axboe --- src/include/liburing.h | 1 + src/liburing.map | 1 + src/register.c | 12 ++++++++++++ 3 files changed, 14 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 4bdf0f6..5fca316 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -141,6 +141,7 @@ int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, int io_uring_register_buffers_tags(struct io_uring *ring, const struct iovec *iovecs, const __u64 *tags, unsigned nr); +int io_uring_register_buffers_sparse(struct io_uring *ring, unsigned nr); int io_uring_register_buffers_update_tag(struct io_uring *ring, unsigned off, const struct iovec *iovecs, diff --git a/src/liburing.map b/src/liburing.map index 1e66849..c314efb 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -51,4 +51,5 @@ LIBURING_2.2 { io_uring_register_ring_fd; io_uring_unregister_ring_fd; io_uring_register_files_sparse; + io_uring_register_buffers_sparse; } LIBURING_2.1; diff --git a/src/register.c b/src/register.c index dde2038..be61c65 100644 --- a/src/register.c +++ b/src/register.c @@ -41,6 +41,18 @@ int io_uring_register_buffers_tags(struct io_uring *ring, sizeof(reg)); } +int io_uring_register_buffers_sparse(struct io_uring *ring, unsigned nr) +{ + struct io_uring_rsrc_register reg = { + .flags = IORING_RSRC_REGISTER_SPARSE, + .nr = nr, + }; + + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_BUFFERS2, ®, + sizeof(reg)); +} + int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, unsigned nr_iovecs) { -- cgit v1.2.3 From afafe2e570bd191599329550ed9bb0a8056cce70 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 13:25:12 -0600 Subject: man/io_uring_register_buffers.3: add sparse buffer helper Signed-off-by: Jens Axboe --- man/io_uring_register_buffers.3 | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index ce5ca4c..e7c3498 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -13,16 +13,30 @@ io_uring_register_buffers - register buffers for fixed buffer operations .BI "int io_uring_register_buffers(struct io_uring *" ring ", .BI " const struct iovec *" iovecs ", .BI " unsigned " nr_iovecs ");" +.BI " +.BI "int io_uring_register_buffers_sparse(struct io_uring *" ring ", +.BI " unsigned " nr_iovecs ");" .PP .SH DESCRIPTION .PP -The io_uring_register_buffers() function registers +The +.BR io_uring_register_buffers (3) +function registers .I nr_iovecs number of buffers defined by the array .I iovecs belonging to the .I ring. +The +.BR io_uring_register_buffers_sparse (3) +function registers +.I nr_iovecs +empty buffers belonging to the +.I ring. +These buffers must be updated before use, using eg +.BR io_uring_register_buffers_update_tag (3). + After the caller has registered the buffers, they can be used with one of the fixed buffers functions. @@ -36,6 +50,9 @@ manipulating the page reference counts for each IO. .SH RETURN VALUE On success .BR io_uring_register_buffers (3) -returns 0. On failure it returns -errno. +and +.BR io_uring_register_buffers_sparse (3) +return 0. On failure they return +.B -errno. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_unregister_buffers (3), io_uring_prep_read_fixed (3), io_uring_prep_write_fixed (3) -- cgit v1.2.3 From b219a8746b78b53d69b8fca745838cd8b96c228e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 13:25:31 -0600 Subject: man/io_uring_register_files.3: fix grammatical error Signed-off-by: Jens Axboe --- man/io_uring_register_files.3 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index cf31460..8a627a9 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -44,6 +44,7 @@ On success .BR io_uring_register_files (3) and .BR io_uring_register_files_sparse (3) -returns 0. On failure it returns -errno. +return 0. On failure they return +.B -errno. .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_unregister_files (3) -- cgit v1.2.3 From c5988858dafe56dcdcce2c15731904c2a62104d8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 14 May 2022 09:45:03 -0600 Subject: Add ring based registered buffers Add definitions and a helper to set them up. Signed-off-by: Jens Axboe --- src/include/liburing.h | 1 + src/include/liburing/io_uring.h | 36 ++++++++++++++++++++++++++++++++++++ src/liburing.map | 1 + src/register.c | 7 +++++++ 4 files changed, 45 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 4bdf0f6..16f10e1 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -178,6 +178,7 @@ int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *values); int io_uring_register_ring_fd(struct io_uring *ring); int io_uring_unregister_ring_fd(struct io_uring *ring); +int io_uring_register_buf_ring(struct io_uring *ring, struct io_uring_buf_reg *reg); /* * Helper for the peek/wait single cqe functions. Exported because of that, diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index c85f274..2f391c9 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -407,6 +407,10 @@ enum { IORING_REGISTER_RING_FDS = 20, IORING_UNREGISTER_RING_FDS = 21, + /* register ring based provide buffer group */ + IORING_REGISTER_PBUF_RING = 22, + IORING_UNREGISTER_PBUF_RING = 23, + /* this goes last */ IORING_REGISTER_LAST }; @@ -484,6 +488,38 @@ struct io_uring_restriction { __u32 resv2[3]; }; +struct io_uring_buf { + __u64 addr; + __u32 len; + __u16 bid; + __u16 resv; +}; + +struct io_uring_buf_ring { + union { + /* + * To avoid spilling into more pages than we need to, the + * ring tail is overlaid with the io_uring_buf->resv field. + */ + struct { + __u64 resv1; + __u32 resv2; + __u16 resv3; + __u16 tail; + }; + struct io_uring_buf bufs[0]; + }; +}; + +/* argument for IORING_(UN)REGISTER_PBUF_RING */ +struct io_uring_buf_reg { + __u64 ring_addr; + __u32 ring_entries; + __u16 bgid; + __u16 pad; + __u64 resv[3]; +}; + /* * io_uring_restriction->opcode values */ diff --git a/src/liburing.map b/src/liburing.map index 1e66849..287d683 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -51,4 +51,5 @@ LIBURING_2.2 { io_uring_register_ring_fd; io_uring_unregister_ring_fd; io_uring_register_files_sparse; + io_uring_register_buf_ring; } LIBURING_2.1; diff --git a/src/register.c b/src/register.c index dde2038..986e968 100644 --- a/src/register.c +++ b/src/register.c @@ -318,3 +318,10 @@ int io_uring_unregister_ring_fd(struct io_uring *ring) } return ret; } + +int io_uring_register_buf_ring(struct io_uring *ring, + struct io_uring_buf_reg *reg) +{ + return ____sys_io_uring_register(ring->ring_fd, + IORING_REGISTER_PBUF_RING, reg, 1); +} -- cgit v1.2.3 From f58c664278a32046b3203acc731f94de6eadd6f0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 May 2022 09:50:51 -0600 Subject: test/send_recvmsg: add buffer ring test cases Signed-off-by: Jens Axboe --- test/send_recvmsg.c | 212 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 160 insertions(+), 52 deletions(-) diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index 2d9315b..585f5be 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -17,6 +17,8 @@ static char str[] = "This is a test of sendmsg and recvmsg over io_uring!"; +static int ud; + #define MAX_MSG 128 #define PORT 10203 @@ -27,31 +29,32 @@ static char str[] = "This is a test of sendmsg and recvmsg over io_uring!"; #define MAX_IOV_COUNT 10 -static int recv_prep(struct io_uring *ring, struct iovec iov[], int iov_count, - int bgid) +static int no_pbuf_ring; + +static int recv_prep(struct io_uring *ring, int *sockfd, struct iovec iov[], + int iov_count, int bgid, int async) { struct sockaddr_in saddr; struct msghdr msg; struct io_uring_sqe *sqe; - int sockfd, ret; - int val = 1; + int ret, val = 1; memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(PORT); - sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) { + *sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (*sockfd < 0) { perror("socket"); return 1; } val = 1; - setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + setsockopt(*sockfd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); + setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); - ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); + ret = bind(*sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { perror("bind"); goto err; @@ -63,13 +66,16 @@ static int recv_prep(struct io_uring *ring, struct iovec iov[], int iov_count, return 1; } - io_uring_prep_recvmsg(sqe, sockfd, &msg, 0); + io_uring_prep_recvmsg(sqe, *sockfd, &msg, 0); if (bgid) { iov->iov_base = NULL; sqe->flags |= IOSQE_BUFFER_SELECT; sqe->buf_group = bgid; iov_count = 1; } + sqe->user_data = ++ud; + if (async) + sqe->flags |= IOSQE_ASYNC; memset(&msg, 0, sizeof(msg)); msg.msg_namelen = sizeof(struct sockaddr_in); msg.msg_iov = iov; @@ -81,18 +87,19 @@ static int recv_prep(struct io_uring *ring, struct iovec iov[], int iov_count, goto err; } - close(sockfd); return 0; err: - close(sockfd); + close(*sockfd); return 1; } struct recv_data { pthread_mutex_t *mutex; int buf_select; + int buf_ring; int no_buf_add; int iov_count; + int async; }; static int do_recvmsg(struct io_uring *ring, char buf[MAX_MSG + 1], @@ -107,7 +114,7 @@ static int do_recvmsg(struct io_uring *ring, char buf[MAX_MSG + 1], goto err; } if (cqe->res < 0) { - if (rd->no_buf_add && rd->buf_select) + if (rd->no_buf_add && (rd->buf_select || rd->buf_ring)) return 0; fprintf(stderr, "%s: failed cqe: %d\n", __FUNCTION__, cqe->res); goto err; @@ -118,7 +125,7 @@ static int do_recvmsg(struct io_uring *ring, char buf[MAX_MSG + 1], fprintf(stderr, "Buffer ID mismatch %d\n", bid); } - if (rd->no_buf_add && rd->buf_select) { + if (rd->no_buf_add && (rd->buf_ring || rd->buf_select)) { fprintf(stderr, "Expected -ENOBUFS: %d\n", cqe->res); goto err; } @@ -160,10 +167,11 @@ static void *recv_fn(void *data) pthread_mutex_t *mutex = rd->mutex; char buf[MAX_MSG + 1]; struct iovec iov[MAX_IOV_COUNT]; - struct io_uring_sqe *sqe; - struct io_uring_cqe *cqe; struct io_uring ring; - int ret; + int ret, sockfd; + + if (rd->buf_ring && no_pbuf_ring) + goto out_no_ring; init_iov(iov, rd->iov_count, buf); @@ -173,34 +181,62 @@ static void *recv_fn(void *data) goto err; } - if (rd->buf_select && !rd->no_buf_add) { - sqe = io_uring_get_sqe(&ring); - io_uring_prep_provide_buffers(sqe, buf, sizeof(buf) -1, 1, - BUF_BGID, BUF_BID); - ret = io_uring_submit(&ring); - if (ret != 1) { - fprintf(stderr, "submit ret=%d\n", ret); - goto err; - } - - ret = io_uring_wait_cqe(&ring, &cqe); - if (ret) { - fprintf(stderr, "wait_cqe=%d\n", ret); - goto err; - } - ret = cqe->res; - io_uring_cqe_seen(&ring, cqe); - if (ret == -EINVAL) { - fprintf(stdout, "PROVIDE_BUFFERS not supported, skip\n"); - goto out; - goto err; - } else if (ret < 0) { - fprintf(stderr, "PROVIDER_BUFFERS %d\n", ret); - goto err; + if ((rd->buf_ring || rd->buf_select) && !rd->no_buf_add) { + if (rd->buf_ring) { + struct io_uring_buf_reg reg = { }; + struct io_uring_buf_ring *br; + void *ptr; + + if (posix_memalign(&ptr, 4096, 4096)) + goto err; + + reg.ring_addr = (unsigned long) ptr; + reg.ring_entries = 1; + reg.bgid = BUF_BGID; + if (io_uring_register_buf_ring(&ring, ®)) { + no_pbuf_ring = 1; + goto out; + } + + br = ptr; + br->bufs[0].addr = (unsigned long) buf; + br->bufs[0].len = sizeof(buf); + br->bufs[0].bid = BUF_BID; + io_uring_smp_store_release(&br->head, 1); + } else { + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_provide_buffers(sqe, buf, sizeof(buf) -1, + 1, BUF_BGID, BUF_BID); + sqe->user_data = ++ud; + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "submit ret=%d\n", ret); + goto err; + } + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe=%d\n", ret); + goto err; + } + ret = cqe->res; + io_uring_cqe_seen(&ring, cqe); + if (ret == -EINVAL) { + fprintf(stdout, "PROVIDE_BUFFERS not supported, skip\n"); + goto out; + } else if (ret < 0) { + fprintf(stderr, "PROVIDER_BUFFERS %d\n", ret); + goto err; + } } } - ret = recv_prep(&ring, iov, rd->iov_count, rd->buf_select ? BUF_BGID : 0); + ret = recv_prep(&ring, &sockfd, iov, rd->iov_count, + (rd->buf_ring || rd->buf_select) ? BUF_BGID : 0, + rd->async); if (ret) { fprintf(stderr, "recv_prep failed: %d\n", ret); goto err; @@ -208,14 +244,15 @@ static void *recv_fn(void *data) pthread_mutex_unlock(mutex); ret = do_recvmsg(&ring, buf, rd); + close(sockfd); io_uring_queue_exit(&ring); - err: return (void *)(intptr_t)ret; out: - pthread_mutex_unlock(mutex); io_uring_queue_exit(&ring); +out_no_ring: + pthread_mutex_unlock(mutex); return NULL; } @@ -255,8 +292,11 @@ static int do_sendmsg(void) return 1; } + usleep(10000); + sqe = io_uring_get_sqe(&ring); io_uring_prep_sendmsg(sqe, sockfd, &msg, 0); + sqe->user_data = ++ud; ret = io_uring_submit(&ring); if (ret <= 0) { @@ -277,7 +317,8 @@ err: return 1; } -static int test(int buf_select, int no_buf_add, int iov_count) +static int test(int buf_select, int buf_ring, int no_buf_add, int iov_count, + int async) { struct recv_data rd; pthread_mutexattr_t attr; @@ -286,6 +327,9 @@ static int test(int buf_select, int no_buf_add, int iov_count) int ret; void *retval; + if (buf_select || buf_ring) + assert(iov_count == 1); + pthread_mutexattr_init(&attr); pthread_mutexattr_setpshared(&attr, 1); pthread_mutex_init(&mutex, &attr); @@ -293,8 +337,10 @@ static int test(int buf_select, int no_buf_add, int iov_count) rd.mutex = &mutex; rd.buf_select = buf_select; + rd.buf_ring = buf_ring; rd.no_buf_add = no_buf_add; rd.iov_count = iov_count; + rd.async = async; ret = pthread_create(&recv_thread, NULL, recv_fn, &rd); if (ret) { pthread_mutex_unlock(&mutex); @@ -317,27 +363,89 @@ int main(int argc, char *argv[]) if (argc > 1) return 0; - ret = test(0, 0, 1); +goto foo; + ret = test(0, 0, 0, 1, 0); if (ret) { - fprintf(stderr, "send_recvmsg 0 failed\n"); + fprintf(stderr, "send_recvmsg 0 0 0 1 0 failed\n"); return 1; } - ret = test(0, 0, 10); + ret = test(0, 0, 0, 10, 0); if (ret) { fprintf(stderr, "send_recvmsg multi iov failed\n"); return 1; } - ret = test(1, 0, 1); + ret = test(1, 0, 0, 1, 0); + if (ret) { + fprintf(stderr, "send_recvmsg 1 0 0 1 0 failed\n"); + return 1; + } + + ret = test(1, 0, 1, 1, 0); + if (ret) { + fprintf(stderr, "send_recvmsg 1 0 1 1 0 failed\n"); + return 1; + } + + ret = test(0, 1, 0, 1, 0); + if (ret) { + fprintf(stderr, "send_recvmsg 0 1 0 1 0 failed\n"); + return 1; + } + + ret = test(1, 1, 0, 1, 0); + if (ret) { + fprintf(stderr, "send_recvmsg 1 1 0 1 0 failed\n"); + return 1; + } + + ret = test(1, 1, 1, 1, 0); + if (ret) { + fprintf(stderr, "send_recvmsg 1 1 1 1 0 failed\n"); + return 1; + } + + ret = test(0, 0, 0, 1, 1); + if (ret) { + fprintf(stderr, "send_recvmsg async 0 0 0 1 1 failed\n"); + return 1; + } + + ret = test(0, 0, 0, 10, 1); + if (ret) { + fprintf(stderr, "send_recvmsg async multi iov failed\n"); + return 1; + } + + ret = test(1, 0, 0, 1, 1); + if (ret) { + fprintf(stderr, "send_recvmsg async 1 0 0 1 1 failed\n"); + return 1; + } + + ret = test(1, 0, 1, 1, 1); + if (ret) { + fprintf(stderr, "send_recvmsg async 1 0 1 1 1 failed\n"); + return 1; + } + +foo: + ret = test(0, 1, 0, 1, 1); + if (ret) { + fprintf(stderr, "send_recvmsg async 0 1 0 1 1 failed\n"); + return 1; + } + + ret = test(1, 1, 0, 1, 1); if (ret) { - fprintf(stderr, "send_recvmsg 1 0 failed\n"); + fprintf(stderr, "send_recvmsg async 1 1 0 1 1 failed\n"); return 1; } - ret = test(1, 1, 1); + ret = test(1, 1, 1, 1, 1); if (ret) { - fprintf(stderr, "send_recvmsg 1 1 failed\n"); + fprintf(stderr, "send_recvmsg async 1 1 1 1 1 failed\n"); return 1; } -- cgit v1.2.3 From e85c8b511c4898b4ab570caffc5ae5b629813be7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 May 2022 10:06:28 -0600 Subject: liburing.c: add buffer ring supply/commit helpers Signed-off-by: Jens Axboe --- src/include/liburing.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 16f10e1..ee65fe8 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -1018,6 +1018,31 @@ static inline struct io_uring_sqe *_io_uring_get_sqe(struct io_uring *ring) return NULL; } +/* + * Assign 'buf' with the addr/len/buffer ID supplied + */ +static inline void io_uring_buf_ring_add(struct io_uring_buf *buf, + void *addr, unsigned int len, + unsigned short bid) +{ + buf->addr = (unsigned long) (uintptr_t) addr; + buf->len = len; + buf->bid = bid; +} + +/* + * Make 'count' new buffers visible to the kernel. Called after + * io_uring_buf_ring_add() has been called 'count' times to fill in new + * buffers. + */ +static inline void io_uring_buf_ring_increment(struct io_uring_buf_ring *br, + int count) +{ + unsigned short new_tail = br->tail + count; + + io_uring_smp_store_release(&br->tail, new_tail); +} + #ifndef LIBURING_INTERNAL static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) { -- cgit v1.2.3 From f5776b4371a0036875b6173f0673db9079a0381f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 May 2022 10:09:47 -0600 Subject: test/send_recvmsg.c: use buffer ring helpers Signed-off-by: Jens Axboe --- test/send_recvmsg.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index 585f5be..e989d2c 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -165,6 +165,7 @@ static void *recv_fn(void *data) { struct recv_data *rd = data; pthread_mutex_t *mutex = rd->mutex; + struct io_uring_buf_ring *br = NULL; char buf[MAX_MSG + 1]; struct iovec iov[MAX_IOV_COUNT]; struct io_uring ring; @@ -184,7 +185,6 @@ static void *recv_fn(void *data) if ((rd->buf_ring || rd->buf_select) && !rd->no_buf_add) { if (rd->buf_ring) { struct io_uring_buf_reg reg = { }; - struct io_uring_buf_ring *br; void *ptr; if (posix_memalign(&ptr, 4096, 4096)) @@ -199,10 +199,9 @@ static void *recv_fn(void *data) } br = ptr; - br->bufs[0].addr = (unsigned long) buf; - br->bufs[0].len = sizeof(buf); - br->bufs[0].bid = BUF_BID; - io_uring_smp_store_release(&br->head, 1); + io_uring_buf_ring_add(&br->bufs[0], buf, sizeof(buf), + BUF_BID); + io_uring_buf_ring_increment(br, 1); } else { struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; @@ -247,12 +246,16 @@ static void *recv_fn(void *data) close(sockfd); io_uring_queue_exit(&ring); + if (br) + free(br); err: return (void *)(intptr_t)ret; out: io_uring_queue_exit(&ring); out_no_ring: pthread_mutex_unlock(mutex); + if (br) + free(br); return NULL; } -- cgit v1.2.3 From c4a10701bd63a11aefe2ee6e0e48006382bd4de0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 May 2022 10:00:28 -0600 Subject: Add combined cq+buf ring advance helper Signed-off-by: Jens Axboe --- src/include/liburing.h | 19 +++++++++++++++++-- test/send_recvmsg.c | 4 +--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index ee65fe8..9a0d23e 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -1035,14 +1035,29 @@ static inline void io_uring_buf_ring_add(struct io_uring_buf *buf, * io_uring_buf_ring_add() has been called 'count' times to fill in new * buffers. */ -static inline void io_uring_buf_ring_increment(struct io_uring_buf_ring *br, - int count) +static inline void io_uring_buf_ring_advance(struct io_uring_buf_ring *br, + int count) { unsigned short new_tail = br->tail + count; io_uring_smp_store_release(&br->tail, new_tail); } +/* + * Make 'count' new buffers visible to the kernel while at the same time + * advancing the CQ ring seen entries. This can be used when the application + * is using ring provided buffers and returns buffers while processing CQEs, + * avoiding an extra atomic when needing to increment both the CQ ring and + * the ring buffer index at the same time. + */ +static inline void io_uring_buf_ring_cq_advance(struct io_uring *ring, + struct io_uring_buf_ring *br, + int count) +{ + br->tail += count; + io_uring_cq_advance(ring, count); +} + #ifndef LIBURING_INTERNAL static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) { diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index e989d2c..1fed4af 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -201,7 +201,7 @@ static void *recv_fn(void *data) br = ptr; io_uring_buf_ring_add(&br->bufs[0], buf, sizeof(buf), BUF_BID); - io_uring_buf_ring_increment(br, 1); + io_uring_buf_ring_advance(br, 1); } else { struct io_uring_sqe *sqe; struct io_uring_cqe *cqe; @@ -366,7 +366,6 @@ int main(int argc, char *argv[]) if (argc > 1) return 0; -goto foo; ret = test(0, 0, 0, 1, 0); if (ret) { fprintf(stderr, "send_recvmsg 0 0 0 1 0 failed\n"); @@ -433,7 +432,6 @@ goto foo; return 1; } -foo: ret = test(0, 1, 0, 1, 1); if (ret) { fprintf(stderr, "send_recvmsg async 0 1 0 1 1 failed\n"); -- cgit v1.2.3 From bef8c8acae801b30924d074fb8bb31e79f87549c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 13:48:03 -0600 Subject: Add io_uring_unregister_buf_ring() This is the unregister part of registering a shared buffer ring. Signed-off-by: Jens Axboe --- src/liburing.map | 1 + src/register.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/liburing.map b/src/liburing.map index 287d683..bebdb1d 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -52,4 +52,5 @@ LIBURING_2.2 { io_uring_unregister_ring_fd; io_uring_register_files_sparse; io_uring_register_buf_ring; + io_uring_unregister_buf_ring; } LIBURING_2.1; diff --git a/src/register.c b/src/register.c index 986e968..1b5171a 100644 --- a/src/register.c +++ b/src/register.c @@ -325,3 +325,11 @@ int io_uring_register_buf_ring(struct io_uring *ring, return ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_PBUF_RING, reg, 1); } + +int io_uring_unregister_buf_ring(struct io_uring *ring, int bgid) +{ + struct io_uring_buf_reg reg = { .bgid = bgid }; + + return ____sys_io_uring_register(ring->ring_fd, + IORING_UNREGISTER_PBUF_RING, ®, 1); +} -- cgit v1.2.3 From 82bb24abd65d5a2e6106657e239a490254766dd2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 13:51:42 -0600 Subject: Change io_uring_register_buf_ring() to take a flags argument Unused so far, but future proofing so we can add some if needed. Signed-off-by: Jens Axboe --- src/include/liburing.h | 3 ++- src/register.c | 2 +- test/send_recvmsg.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 9a0d23e..2175a75 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -178,7 +178,8 @@ int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *values); int io_uring_register_ring_fd(struct io_uring *ring); int io_uring_unregister_ring_fd(struct io_uring *ring); -int io_uring_register_buf_ring(struct io_uring *ring, struct io_uring_buf_reg *reg); +int io_uring_register_buf_ring(struct io_uring *ring, + struct io_uring_buf_reg *reg, unsigned int flags); /* * Helper for the peek/wait single cqe functions. Exported because of that, diff --git a/src/register.c b/src/register.c index 1b5171a..5214b52 100644 --- a/src/register.c +++ b/src/register.c @@ -320,7 +320,7 @@ int io_uring_unregister_ring_fd(struct io_uring *ring) } int io_uring_register_buf_ring(struct io_uring *ring, - struct io_uring_buf_reg *reg) + struct io_uring_buf_reg *reg, unsigned int flags) { return ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_PBUF_RING, reg, 1); diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index 1fed4af..c30cebd 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -193,7 +193,7 @@ static void *recv_fn(void *data) reg.ring_addr = (unsigned long) ptr; reg.ring_entries = 1; reg.bgid = BUF_BGID; - if (io_uring_register_buf_ring(&ring, ®)) { + if (io_uring_register_buf_ring(&ring, ®, 0)) { no_pbuf_ring = 1; goto out; } -- cgit v1.2.3 From c41c48558809e9332afe99f6665ed488b1634ac0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 14:04:12 -0600 Subject: Change io_uring_buf_ring_add() to take ring and buffer offset Start inserting at tail + offset passed in, this is more natural than having to index the buffer from the application. Signed-off-by: Jens Axboe --- src/include/liburing.h | 6 ++++-- test/send_recvmsg.c | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index 2175a75..089753c 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -1022,10 +1022,12 @@ static inline struct io_uring_sqe *_io_uring_get_sqe(struct io_uring *ring) /* * Assign 'buf' with the addr/len/buffer ID supplied */ -static inline void io_uring_buf_ring_add(struct io_uring_buf *buf, +static inline void io_uring_buf_ring_add(struct io_uring_buf_ring *br, void *addr, unsigned int len, - unsigned short bid) + unsigned short bid, int buf_offset) { + struct io_uring_buf *buf = &br->bufs[br->tail + buf_offset]; + buf->addr = (unsigned long) (uintptr_t) addr; buf->len = len; buf->bid = bid; diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index c30cebd..44a01b0 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -199,8 +199,7 @@ static void *recv_fn(void *data) } br = ptr; - io_uring_buf_ring_add(&br->bufs[0], buf, sizeof(buf), - BUF_BID); + io_uring_buf_ring_add(br, buf, sizeof(buf), BUF_BID, 0); io_uring_buf_ring_advance(br, 1); } else { struct io_uring_sqe *sqe; -- cgit v1.2.3 From f01ed8b0037457ff845adecb39a01540eaa332c0 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 14:16:32 -0600 Subject: Add man pages for shared provided buffer rings Signed-off-by: Jens Axboe --- man/io_uring_buf_ring_add.3 | 47 +++++++++++++ man/io_uring_buf_ring_advance.3 | 30 +++++++++ man/io_uring_buf_ring_cq_advance.3 | 40 +++++++++++ man/io_uring_register_buf_ring.3 | 133 +++++++++++++++++++++++++++++++++++++ man/io_uring_unregister_buf_ring.3 | 30 +++++++++ 5 files changed, 280 insertions(+) create mode 100644 man/io_uring_buf_ring_add.3 create mode 100644 man/io_uring_buf_ring_advance.3 create mode 100644 man/io_uring_buf_ring_cq_advance.3 create mode 100644 man/io_uring_register_buf_ring.3 create mode 100644 man/io_uring_unregister_buf_ring.3 diff --git a/man/io_uring_buf_ring_add.3 b/man/io_uring_buf_ring_add.3 new file mode 100644 index 0000000..7fd751e --- /dev/null +++ b/man/io_uring_buf_ring_add.3 @@ -0,0 +1,47 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_buf_ring_add 3 "May 18, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_buf_ring_add - add buffers to a shared buffer ring +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_buf_ring_add(struct io_uring_buf_ring *" br ", +.BI " void *" addr ", +.BI " unsigned int " len ", +.BI " unsigned short " bid ", +.BI " int " buf_offset ");" +.PP +.SH DESCRIPTION +.PP +The +.BR io_uring_buf_ring_add (3) +adds a new buffer to the shared buffer ring +.I br. +The buffer address is indicated by +.I addr +and is of +.I len +bytes of length. +.I bid +is the buffer ID, which will be returned in the CQE. +.I buf_offset +is the offset to insert at from the current tail. If just one buffer is provided +before the ring tail is committed with +.BR io_uring_buf_ring_advance (3) +or +.BR io_uring_buf_ring_cq_advance (3), +then +.I buf_offset +should be 0. If buffers are provided in a loop before being committed, the +.I buf_offset +must be incremented by one for each buffer added. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_register_buf_ring (3), io_uring_buf_ring_advance (3), io_uring_buf_ring_cq_advance (3) diff --git a/man/io_uring_buf_ring_advance.3 b/man/io_uring_buf_ring_advance.3 new file mode 100644 index 0000000..60c16a1 --- /dev/null +++ b/man/io_uring_buf_ring_advance.3 @@ -0,0 +1,30 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_buf_ring_advance 3 "May 18, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_buf_ring_advance - advance index of provided buffer in buffer ring +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_buf_ring_advance(struct io_uring_buf_ring *" br ", +.BI " int " count ");" +.PP +.SH DESCRIPTION +.PP +The +.BR io_uring_buf_ring_advance (3) +commits +.I count +previously added buffers to the shared buffer ring +.I br, +making them visible to the kernel and hence consumable. This passes ownership +of the buffer to the ring. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_register_buf_ring (3), io_uring_buf_ring_add (3), io_uring_buf_ring_cq_advance (3) diff --git a/man/io_uring_buf_ring_cq_advance.3 b/man/io_uring_buf_ring_cq_advance.3 new file mode 100644 index 0000000..5b693b7 --- /dev/null +++ b/man/io_uring_buf_ring_cq_advance.3 @@ -0,0 +1,40 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_buf_ring_cq_advance 3 "May 18, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_buf_ring_cq_advance - advance index of provided buffer and CQ ring +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_buf_ring_cq_advance(struct io_uring *" ring ", +.BI " struct io_uring_buf_ring *" br ", +.BI " int " count ");" +.PP +.SH DESCRIPTION +.PP +The +.BR io_uring_buf_ring_cq_advance (3) +commits +.I count +previously added buffers to the shared buffer ring +.I br, +making them visible to the kernel and hence consumable. This passes ownership +of the buffer to the ring. At the same time, it advances the CQ ring of +.I ring +by +.I count +amount. This effectively bundles both a +.BR io_uring_buf_ring_advance (3) +call and a +.BR io_uring_cq_avance (3) +into one operation. Since updating either ring index entails a store memory +barrier, doing both at once is more efficient. + +.SH RETURN VALUE +None +.SH SEE ALSO +.BR io_uring_register_buf_ring (3), io_uring_buf_ring_add (3), io_uring_buf_ring_advance (3) diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3 new file mode 100644 index 0000000..28cbf96 --- /dev/null +++ b/man/io_uring_register_buf_ring.3 @@ -0,0 +1,133 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_register_buf_ring 3 "May 18, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_register_buf_ring - register buffer ring for provided buffers +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_register_buf_ring(struct io_uring *" ring ", +.BI " struct io_uring_buf_reg *" reg ", +.BI " unsigned int " flags ");" +.BI " +.PP +.SH DESCRIPTION +.PP +The +.BR io_uring_register_buf_ring (3) +function registers a shared buffer ring to be used with provided buffers. For +the request types that support it, provided buffers are given to the ring and +one is selected by a request if it has +.B IOSQE_BUFFER_SELECT +set in the SQE +.I flags, +when the request is ready to receive data. This allows both clear ownership +of the buffer lifetime, and a way to have more read/receive type of operations +in flight than buffers available. + +The +.I reg +argument must be filled in with the appropriate information. It looks as +follows: +.PP +.in +4n +.EX +struct io_uring_buf_reg { + __u64 ring_addr; + __u32 ring_entries; + __u16 bgid; + __u16 pad; + __u64 resv[3]; +}; +.EE +.in +.PP +The +.I ring_addr +field must contain the address to the memory allocated to fit this ring. +The memory must be page aligned and hence allocated appropriately using eg +.BR posix_memalign (3) +or similar. The size of the ring is the product of +.I ring_entries +and the size of +.I struct io_uring_buf. +.I ring_entries +is the desired size of the ring, and must be a power-of-2 in size. +.I bgid +is the buffer group ID associated with this ring. SQEs that select a buffer +has a buffer group associated with them in their +.I buf_group +field, and the associated CQE will have +.B IORING_CQE_F_BUFFER +set in their +.I flags +member, which will also contain the specific ID of the buffer seleted. The rest +of the fields are reserved and must be cleared to zero. + +The +.I flags +argument is currently unused and must be set to zero. + +A shared buffer ring looks as follows: +.PP +.in +4n +.EX +struct io_uring_buf_ring { + union { + struct { + __u64 resv1; + __u32 resv2; + __u16 resv3; + __u16 tail; + }; + struct io_uring_buf bufs[0]; + }; +}; +.EE +.in +.PP +where +.I tail +is the index at which the application can insert new buffers for consumption +by requests, and +.I struct io_uring_buf +is buffer definition: +.PP +.in +4n +.EX +struct io_uring_buf { + __u64 addr; + __u32 len; + __u16 bid; + __u16 resv; +}; +.EE +.in +.PP +where +.I addr +is the address for the buffer, +.I len +is the length of the buffer in bytes, and +.I bid +is the buffer ID that will be returned in the CQE once consumed. + +Reserved fields must not be touched. Applications may use +.BR io_uring_buf_ring_add (3) +and +.BR io_uring_buf_ring_advance (3) +or +.BR io_uring_buf_ring_advance (3) +to provide buffers, which will set these fields and update the tail. + +.SH RETURN VALUE +On success +.BR io_uring_register_buf_ring (3) +returns 0. On failure it returns +.B -errno. +.SH SEE ALSO +.BR io_uring_buf_ring_alloc (3), io_uring_buf_ring_add (3), io_uring_buf_ring_advance (3), io_uring_buf_ring_cq_advance (3) diff --git a/man/io_uring_unregister_buf_ring.3 b/man/io_uring_unregister_buf_ring.3 new file mode 100644 index 0000000..8743328 --- /dev/null +++ b/man/io_uring_unregister_buf_ring.3 @@ -0,0 +1,30 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_unregister_buf_ring 3 "May 18, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_unregister_buf_ring - unregister a previously registered buffer ring +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.PP +.BI "int io_uring_unregister_buf_ring(struct io_uring *" ring ", +.BI " int " bgid ");" +.BI " +.PP +.SH DESCRIPTION +.PP +The +.BR io_uring_unregister_buf_ring (3) +function unregisters a previously registered shared buffer ring indicated by +.I bgid. + +.SH RETURN VALUE +On success +.BR io_uring_unregister_buf_ring (3) +returns 0. On failure it returns +.B -errno. +.SH SEE ALSO +.BR io_uring_register_buf_ring (3), io_uring_buf_ring_free (3) -- cgit v1.2.3 From e7f9744c9e4dcc04a07e5f261b0861b57be19025 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 14:16:50 -0600 Subject: man/io_uring_register_buffers.3: add reference to buffer rings Signed-off-by: Jens Axboe --- man/io_uring_register_buffers.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index ce5ca4c..84aa5b9 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -38,4 +38,4 @@ On success .BR io_uring_register_buffers (3) returns 0. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_unregister_buffers (3), io_uring_prep_read_fixed (3), io_uring_prep_write_fixed (3) +.BR io_uring_get_sqe (3), io_uring_unregister_buffers (3), io_uring_register_buf_ring (3), io_uring_prep_read_fixed (3), io_uring_prep_write_fixed (3) -- cgit v1.2.3 From a35f5076eada95b0672201da388cf39d5162d89d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 14:29:20 -0600 Subject: Add missing io_uring_unregister_buf_ring() declaration Signed-off-by: Jens Axboe --- src/include/liburing.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 80b8c13..8974949 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -181,6 +181,7 @@ int io_uring_register_ring_fd(struct io_uring *ring); int io_uring_unregister_ring_fd(struct io_uring *ring); int io_uring_register_buf_ring(struct io_uring *ring, struct io_uring_buf_reg *reg, unsigned int flags); +int io_uring_unregister_buf_ring(struct io_uring *ring, int bgid); /* * Helper for the peek/wait single cqe functions. Exported because of that, -- cgit v1.2.3 From cfdd37632fc1b1c898af0f8241874ba42fc2e293 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 May 2022 16:26:57 -0600 Subject: Add basic buffer ring test case send_recvmsg uses it for actual IO, this one is more about just testing the various cases for registration and mixing with classic buffers that should not work. Signed-off-by: Jens Axboe --- test/Makefile | 1 + test/buf-ring.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 test/buf-ring.c diff --git a/test/Makefile b/test/Makefile index 1545339..76f71cb 100644 --- a/test/Makefile +++ b/test/Makefile @@ -50,6 +50,7 @@ test_srcs := \ across-fork.c \ b19062a56726.c \ b5837bd5311d.c \ + buf-ring.c \ ce593a6c480a.c \ close-opath.c \ connect.c \ diff --git a/test/buf-ring.c b/test/buf-ring.c new file mode 100644 index 0000000..5fd1e53 --- /dev/null +++ b/test/buf-ring.c @@ -0,0 +1,246 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: run various shared buffer ring sanity checks + * + */ +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +static int no_buf_ring; + +/* test trying to register classic group when ring group exists */ +static int test_mixed_reg2(int bgid) +{ + struct io_uring_buf_reg reg = { }; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + void *ptr, *bufs; + int ret; + + ret = t_create_ring(1, &ring, 0); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret != T_SETUP_OK) + return 1; + + if (posix_memalign(&ptr, 4096, 4096)) + return 1; + + reg.ring_addr = (unsigned long) ptr; + reg.ring_entries = 32; + reg.bgid = bgid; + + ret = io_uring_register_buf_ring(&ring, ®, 0); + if (ret) { + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + /* provide classic buffers, group 1 */ + bufs = malloc(8 * 1024); + sqe = io_uring_get_sqe(&ring); + io_uring_prep_provide_buffers(sqe, bufs, 1024, 8, bgid, 0); + io_uring_submit(&ring); + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe %d\n", ret); + return 1; + } + if (cqe->res != -EEXIST && cqe->res != -EINVAL) { + fprintf(stderr, "cqe res %d\n", cqe->res); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + io_uring_queue_exit(&ring); + return 0; +} + +/* test trying to register ring group when classic group exists */ +static int test_mixed_reg(int bgid) +{ + struct io_uring_buf_reg reg = { }; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + void *ptr, *bufs; + int ret; + + ret = t_create_ring(1, &ring, 0); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret != T_SETUP_OK) + return 1; + + /* provide classic buffers, group 1 */ + bufs = malloc(8 * 1024); + sqe = io_uring_get_sqe(&ring); + io_uring_prep_provide_buffers(sqe, bufs, 1024, 8, bgid, 0); + io_uring_submit(&ring); + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe %d\n", ret); + return 1; + } + if (cqe->res) { + fprintf(stderr, "cqe res %d\n", cqe->res); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + if (posix_memalign(&ptr, 4096, 4096)) + return 1; + + reg.ring_addr = (unsigned long) ptr; + reg.ring_entries = 32; + reg.bgid = bgid; + + ret = io_uring_register_buf_ring(&ring, ®, 0); + if (ret != -EEXIST) { + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + io_uring_queue_exit(&ring); + return 0; +} + +static int test_double_reg_unreg(int bgid) +{ + struct io_uring_buf_reg reg = { }; + struct io_uring ring; + void *ptr; + int ret; + + ret = t_create_ring(1, &ring, 0); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret != T_SETUP_OK) + return 1; + + if (posix_memalign(&ptr, 4096, 4096)) + return 1; + + reg.ring_addr = (unsigned long) ptr; + reg.ring_entries = 32; + reg.bgid = bgid; + + ret = io_uring_register_buf_ring(&ring, ®, 0); + if (ret) { + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + /* check that 2nd register with same bgid fails */ + reg.ring_addr = (unsigned long) ptr; + reg.ring_entries = 32; + reg.bgid = bgid; + + ret = io_uring_register_buf_ring(&ring, ®, 0); + if (ret != -EEXIST) { + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + ret = io_uring_unregister_buf_ring(&ring, bgid); + if (ret) { + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + ret = io_uring_unregister_buf_ring(&ring, bgid); + if (ret != -EINVAL && ret != -ENOENT) { + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + io_uring_queue_exit(&ring); + return 0; +} + +static int test_reg_unreg(int bgid) +{ + struct io_uring_buf_reg reg = { }; + struct io_uring ring; + void *ptr; + int ret; + + ret = t_create_ring(1, &ring, 0); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret != T_SETUP_OK) + return 1; + + if (posix_memalign(&ptr, 4096, 4096)) + return 1; + + reg.ring_addr = (unsigned long) ptr; + reg.ring_entries = 32; + reg.bgid = bgid; + + ret = io_uring_register_buf_ring(&ring, ®, 0); + if (ret) { + if (ret == -EINVAL) { + no_buf_ring = 1; + return 0; + } + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + ret = io_uring_unregister_buf_ring(&ring, bgid); + if (ret) { + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + io_uring_queue_exit(&ring); + return 0; +} + +int main(int argc, char *argv[]) +{ + int bgids[] = { 1, 127, -1 }; + int ret, i; + + if (argc > 1) + return 0; + + for (i = 0; bgids[i] != -1; i++) { + ret = test_reg_unreg(bgids[i]); + if (ret) { + fprintf(stderr, "test_reg_unreg failed\n"); + return 1; + } + if (no_buf_ring) + break; + + ret = test_double_reg_unreg(bgids[i]); + if (ret) { + fprintf(stderr, "test_double_reg_unreg failed\n"); + return 1; + } + + ret = test_mixed_reg(bgids[i]); + if (ret) { + fprintf(stderr, "test_mixed_reg failed\n"); + return 1; + } + + ret = test_mixed_reg2(bgids[i]); + if (ret) { + fprintf(stderr, "test_mixed_reg2 failed\n"); + return 1; + } + } + + return 0; +} -- cgit v1.2.3 From b79117627d66806eaa4798db59ebaf44234926cf Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 19 May 2022 10:06:17 -0600 Subject: Add CHANGELOG file This should be used to fill in entries for new release, hopefully done as they are added. Since this is the first one, it details changes in 2.2 from 2.1. Signed-off-by: Jens Axboe --- CHANGELOG | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 CHANGELOG diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..bdef787 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,30 @@ +liburing-2.2 release + +- Support non-libc builds. +- Optimized syscall handling for x86-64/x86/aarch64. +- IOPOLL fixes. +- Enable non-lib function calls for fast path functions. +- Add support for multishot accept. +- io_uring_register_files() will set RLIMIT_NOFILE if necessary. +- Add support for registered ring fds, io_uring_register_ring_fd(), + reducingthe overhead of an io_uring_enter() system call. +- Add support for the message ring opcode. +- Add support for newer request cancelation features. +- Add support for IORING_SETUP_COOP_TASKRUN, which can help reduce the + overhead of io_uring in general. Most applications should set this flag, + see the io_uring_enter.3 man page for details. +- Add support for registering a sparse buffer and file set. +- Add support for a new buffer provide scheme, see + io_uring_register_buf_ring.3 for details. +- Add io_uring_submit_and_wait_timeout() for submitting IO and waiting + for completions with a timeout. +- Add io_uring_prep_{read,write}v2 prep helpers. +- Add io_uring_prep_close_direct() helper. +- Add support for SQE128 and CQE32, which are doubly sized SQE and CQE + rings. This is needed for some cases of the new IORING_OP_URING_CMD, + notably for NVMe passthrough. +- ~5000 lines of man page additions, including adding 87 new man pages. +- Synced with the 5.19 kernel release, supporting all the features of + 5.19 and earlier. +- 23 new regression test cases, and ~6000 lines of new tests in general. +- General optimizations and fixes. -- cgit v1.2.3 From bc50c49b0be3c3b6dc18bbbec1b44188c9420d30 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 19 May 2022 10:18:56 -0600 Subject: Update README Signed-off-by: Jens Axboe --- README | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/README b/README index a76021e..afd14b0 100644 --- a/README +++ b/README @@ -16,6 +16,15 @@ and development for both kernel and userspace. The list is archived here: https://lore.kernel.org/io-uring/ +kernel version dependency +-------------------------- + +liburing itself is not tied to any specific kernel release, and hence it's +possible to use the newest liburing release even on older kernels (and vice +versa). Newer features may only be available on more recent kernels, +obviously. + + ulimit settings --------------- @@ -26,7 +35,9 @@ it quickly. root isn't under this restriction, but regular users are. Going into detail on how to bump the limit on various systems is beyond the scope of this little blurb, but check /etc/security/limits.conf for user specific settings, or /etc/systemd/user.conf and /etc/systemd/system.conf for systemd -setups. +setups. This affects 5.11 and earlier, new kernels are less dependent +on RLIMIT_MEMLOCK. + Regressions tests ----------------- @@ -35,6 +46,7 @@ The bulk of liburing is actually regression/unit tests for both liburing and the kernel io_uring support. Please note that this suite isn't expected to pass on older kernels, and may even crash or hang older kernels! + License ------- @@ -43,4 +55,4 @@ COPYING and LICENSE, except for a header coming from the kernel which is dual licensed GPL with a Linux-syscall-note exception and MIT, see COPYING.GPL and . -Jens Axboe 2020-01-20 +Jens Axboe 2022-05-19 -- cgit v1.2.3 From 298f2cd6ef2f7819dfcd4a67eb49db348c3906d7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 19 May 2022 10:23:21 -0600 Subject: CHANGELOG update Signed-off-by: Jens Axboe --- CHANGELOG | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index bdef787..8d28592 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,7 +2,6 @@ liburing-2.2 release - Support non-libc builds. - Optimized syscall handling for x86-64/x86/aarch64. -- IOPOLL fixes. - Enable non-lib function calls for fast path functions. - Add support for multishot accept. - io_uring_register_files() will set RLIMIT_NOFILE if necessary. -- cgit v1.2.3 From d23d7b670b28a04e8f9a659f353c67632032534e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 19 May 2022 10:23:30 -0600 Subject: man/io_uring_register_buf_ring.3: note 5.19 availability Signed-off-by: Jens Axboe --- man/io_uring_register_buf_ring.3 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3 index 28cbf96..9abb59b 100644 --- a/man/io_uring_register_buf_ring.3 +++ b/man/io_uring_register_buf_ring.3 @@ -124,6 +124,8 @@ or .BR io_uring_buf_ring_advance (3) to provide buffers, which will set these fields and update the tail. +Available since 5.19. + .SH RETURN VALUE On success .BR io_uring_register_buf_ring (3) -- cgit v1.2.3 From 047f4f98dffebaa7a0c9b8247a7d11a2b41f011d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 22 May 2022 20:53:39 -0600 Subject: test/accept: don't be too verbose or fail if multishot not available Signed-off-by: Jens Axboe --- test/accept.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/accept.c b/test/accept.c index 921c79b..4e2f587 100644 --- a/test/accept.c +++ b/test/accept.c @@ -25,6 +25,7 @@ #define MAX_FDS 32 static int no_accept; +static int no_accept_multi; struct data { char buf[128]; @@ -215,7 +216,10 @@ static int test_loop(struct io_uring *ring, "%s %s Accept not supported, skipping\n", fixed ? "Fixed" : "", multishot ? "Multishot" : ""); - no_accept = 1; + if (multishot) + no_accept_multi = 1; + else + no_accept = 1; goto out; } else if (s_fd[i] < 0) { if (args.accept_should_error && @@ -443,6 +447,9 @@ static int test_accept_cancel(unsigned usecs, unsigned int nr, bool multishot) struct io_uring_sqe *sqe; int fd, i, ret; + if (multishot && no_accept_multi) + return 0; + ret = io_uring_queue_init(32, &m_io_uring, 0); assert(ret >= 0); @@ -534,6 +541,9 @@ static int test_multishot_accept(int count, bool before) .extra_loops = count - 1 }; + if (no_accept_multi) + return 0; + ret = io_uring_queue_init(MAX_FDS + 10, &m_io_uring, 0); assert(ret >= 0); ret = test(&m_io_uring, args); @@ -621,6 +631,9 @@ static int test_multishot_fixed_accept(void) .multishot = true }; + if (no_accept_multi) + return 0; + memset(fd, -1, sizeof(fd)); ret = io_uring_queue_init(MAX_FDS + 10, &m_io_uring, 0); assert(ret >= 0); -- cgit v1.2.3 From 77f3bffb3fabdf19513b675b680baedef4df92d9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 26 May 2022 17:36:35 -0600 Subject: liburing: add socket prep helpers Signed-off-by: Jens Axboe --- src/include/liburing.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 8974949..b1a6ae4 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -817,6 +817,34 @@ static inline void io_uring_prep_fsetxattr(struct io_uring_sqe *sqe, sqe->xattr_flags = flags; } +static inline void io_uring_prep_socket(struct io_uring_sqe *sqe, int domain, + int type, int protocol, + unsigned int flags) +{ + io_uring_prep_rw(IORING_OP_SOCKET, sqe, domain, NULL, protocol, type); + sqe->rw_flags = flags; +} + +static inline void io_uring_prep_socket_direct(struct io_uring_sqe *sqe, + int domain, int type, + int protocol, + unsigned int flags, + unsigned file_index) +{ + io_uring_prep_rw(IORING_OP_SOCKET, sqe, domain, NULL, protocol, type); + sqe->rw_flags = flags; + __io_uring_set_target_fixed_file(sqe, file_index); +} + +static inline void io_uring_prep_socket_direct_alloc(struct io_uring_sqe *sqe, + int domain, int type, int protocol, + unsigned int flags) +{ + io_uring_prep_rw(IORING_OP_SOCKET, sqe, domain, NULL, protocol, type); + sqe->rw_flags = flags; + __io_uring_set_target_fixed_file(sqe, IORING_FILE_INDEX_ALLOC - 1); +} + /* * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in * the SQ ring -- cgit v1.2.3 From 87c12755a6ae65e4fea0bbcb39dccb18618c2a97 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 26 May 2022 17:36:49 -0600 Subject: test/socKet: add socket test case Tests both normal and direct descriptors, and the latter with allocation as well. Signed-off-by: Jens Axboe --- test/Makefile | 1 + test/socket.c | 408 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 409 insertions(+) create mode 100644 test/socket.c diff --git a/test/Makefile b/test/Makefile index 76f71cb..51c35a9 100644 --- a/test/Makefile +++ b/test/Makefile @@ -139,6 +139,7 @@ test_srcs := \ shutdown.c \ sigfd-deadlock.c \ skip-cqe.c \ + socket.c \ socket-rw.c \ socket-rw-eagain.c \ socket-rw-offset.c \ diff --git a/test/socket.c b/test/socket.c new file mode 100644 index 0000000..131a3a6 --- /dev/null +++ b/test/socket.c @@ -0,0 +1,408 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Simple test case using the socket op + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +static char str[] = "This is a test of send and recv over io_uring!"; + +#define MAX_MSG 128 + +#define PORT 10202 +#define HOST "127.0.0.1" + +static int no_socket; + +static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock, + int registerfiles) +{ + struct sockaddr_in saddr; + struct io_uring_sqe *sqe; + int sockfd, ret, val, use_fd; + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + saddr.sin_port = htons(PORT); + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror("socket"); + return 1; + } + + val = 1; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + + ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); + if (ret < 0) { + perror("bind"); + goto err; + } + + if (registerfiles) { + ret = io_uring_register_files(ring, &sockfd, 1); + if (ret) { + fprintf(stderr, "file reg failed\n"); + goto err; + } + use_fd = 0; + } else { + use_fd = sockfd; + } + + sqe = io_uring_get_sqe(ring); + io_uring_prep_recv(sqe, use_fd, iov->iov_base, iov->iov_len, 0); + if (registerfiles) + sqe->flags |= IOSQE_FIXED_FILE; + sqe->user_data = 2; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "submit failed: %d\n", ret); + goto err; + } + + *sock = sockfd; + return 0; +err: + close(sockfd); + return 1; +} + +static int do_recv(struct io_uring *ring, struct iovec *iov) +{ + struct io_uring_cqe *cqe; + int ret; + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stdout, "wait_cqe: %d\n", ret); + goto err; + } + if (cqe->res == -EINVAL) { + fprintf(stdout, "recv not supported, skipping\n"); + return 0; + } + if (cqe->res < 0) { + fprintf(stderr, "failed cqe: %d\n", cqe->res); + goto err; + } + + if (cqe->res -1 != strlen(str)) { + fprintf(stderr, "got wrong length: %d/%d\n", cqe->res, + (int) strlen(str) + 1); + goto err; + } + + if (strcmp(str, iov->iov_base)) { + fprintf(stderr, "string mismatch\n"); + goto err; + } + + return 0; +err: + return 1; +} + +struct recv_data { + pthread_mutex_t mutex; + int use_sqthread; + int registerfiles; +}; + +static void *recv_fn(void *data) +{ + struct recv_data *rd = data; + char buf[MAX_MSG + 1]; + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf) - 1, + }; + struct io_uring_params p = { }; + struct io_uring ring; + int ret, sock; + + if (rd->use_sqthread) + p.flags = IORING_SETUP_SQPOLL; + ret = t_create_ring_params(1, &ring, &p); + if (ret == T_SETUP_SKIP) { + pthread_mutex_unlock(&rd->mutex); + ret = 0; + goto err; + } else if (ret < 0) { + pthread_mutex_unlock(&rd->mutex); + goto err; + } + + if (rd->use_sqthread && !rd->registerfiles) { + if (!(p.features & IORING_FEAT_SQPOLL_NONFIXED)) { + fprintf(stdout, "Non-registered SQPOLL not available, skipping\n"); + pthread_mutex_unlock(&rd->mutex); + goto err; + } + } + + ret = recv_prep(&ring, &iov, &sock, rd->registerfiles); + if (ret) { + fprintf(stderr, "recv_prep failed: %d\n", ret); + goto err; + } + pthread_mutex_unlock(&rd->mutex); + ret = do_recv(&ring, &iov); + + close(sock); + io_uring_queue_exit(&ring); +err: + return (void *)(intptr_t)ret; +} + +static int fallback_send(struct io_uring *ring, struct sockaddr_in *saddr) +{ + struct iovec iov = { + .iov_base = str, + .iov_len = sizeof(str), + }; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int sockfd, ret; + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror("socket"); + return 1; + } + + ret = connect(sockfd, (struct sockaddr *)saddr, sizeof(*saddr)); + if (ret < 0) { + perror("connect"); + return 1; + } + + sqe = io_uring_get_sqe(ring); + io_uring_prep_send(sqe, sockfd, iov.iov_base, iov.iov_len, 0); + sqe->user_data = 1; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "submit failed: %d\n", ret); + goto err; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (cqe->res == -EINVAL) { + fprintf(stdout, "send not supported, skipping\n"); + close(sockfd); + return 0; + } + if (cqe->res != iov.iov_len) { + fprintf(stderr, "failed cqe: %d\n", cqe->res); + goto err; + } + + close(sockfd); + return 0; +err: + close(sockfd); + return 1; +} + +static int do_send(int socket_direct, int alloc) +{ + struct sockaddr_in saddr; + struct iovec iov = { + .iov_base = str, + .iov_len = sizeof(str), + }; + struct io_uring ring; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + int sockfd, ret, fd = -1; + + ret = io_uring_queue_init(1, &ring, 0); + if (ret) { + fprintf(stderr, "queue init failed: %d\n", ret); + return 1; + } + + if (socket_direct) { + ret = io_uring_register_files(&ring, &fd, 1); + if (ret) { + fprintf(stderr, "file register %d\n", ret); + return 1; + } + } + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = htons(PORT); + inet_pton(AF_INET, HOST, &saddr.sin_addr); + + sqe = io_uring_get_sqe(&ring); + if (socket_direct) { + unsigned file_index = 0; + if (alloc) + file_index = IORING_FILE_INDEX_ALLOC - 1; + io_uring_prep_socket_direct(sqe, AF_INET, SOCK_DGRAM, 0, 0, + file_index); + } else { + io_uring_prep_socket(sqe, AF_INET, SOCK_DGRAM, 0, 0); + } + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "socket submit: %d\n", ret); + return 1; + } + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe: %d\n", ret); + return 1; + } + if (cqe->res < 0) { + if (cqe->res == -EINVAL) { + fprintf(stdout, "No socket support, skipping\n"); + no_socket = 1; + io_uring_cqe_seen(&ring, cqe); + return fallback_send(&ring, &saddr); + } + + fprintf(stderr, "socket res: %d\n", ret); + return 1; + } + + sockfd = cqe->res; + if (socket_direct && !alloc) + sockfd = 0; + io_uring_cqe_seen(&ring, cqe); + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_connect(sqe, sockfd, (struct sockaddr *) &saddr, + sizeof(saddr)); + if (socket_direct) + sqe->flags |= IOSQE_FIXED_FILE; + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "connect submit: %d\n", ret); + return 1; + } + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe: %d\n", ret); + return 1; + } + if (cqe->res < 0) { + fprintf(stderr, "connect res: %d\n", cqe->res); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_send(sqe, sockfd, iov.iov_base, iov.iov_len, 0); + sqe->user_data = 1; + if (socket_direct) + sqe->flags |= IOSQE_FIXED_FILE; + + ret = io_uring_submit(&ring); + if (ret <= 0) { + fprintf(stderr, "submit failed: %d\n", ret); + goto err; + } + + ret = io_uring_wait_cqe(&ring, &cqe); + if (cqe->res == -EINVAL) { + fprintf(stdout, "send not supported, skipping\n"); + close(sockfd); + return 0; + } + if (cqe->res != iov.iov_len) { + fprintf(stderr, "failed cqe: %d\n", cqe->res); + goto err; + } + + close(sockfd); + return 0; +err: + close(sockfd); + return 1; +} + +static int test(int use_sqthread, int regfiles, int socket_direct, int alloc) +{ + pthread_mutexattr_t attr; + pthread_t recv_thread; + struct recv_data rd; + int ret; + void *retval; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_setpshared(&attr, 1); + pthread_mutex_init(&rd.mutex, &attr); + pthread_mutex_lock(&rd.mutex); + rd.use_sqthread = use_sqthread; + rd.registerfiles = regfiles; + + ret = pthread_create(&recv_thread, NULL, recv_fn, &rd); + if (ret) { + fprintf(stderr, "Thread create failed: %d\n", ret); + pthread_mutex_unlock(&rd.mutex); + return 1; + } + + pthread_mutex_lock(&rd.mutex); + do_send(socket_direct, alloc); + pthread_join(recv_thread, &retval); + return (intptr_t)retval; +} + +int main(int argc, char *argv[]) +{ + int ret; + + if (argc > 1) + return 0; + + ret = test(0, 0, 0, 0); + if (ret) { + fprintf(stderr, "test sqthread=0 failed\n"); + return ret; + } + if (no_socket) + return 0; + + ret = test(1, 1, 0, 0); + if (ret) { + fprintf(stderr, "test sqthread=1 reg=1 failed\n"); + return ret; + } + + ret = test(1, 0, 0, 0); + if (ret) { + fprintf(stderr, "test sqthread=1 reg=0 failed\n"); + return ret; + } + + ret = test(0, 0, 1, 0); + if (ret) { + fprintf(stderr, "test sqthread=0 direct=1 failed\n"); + return ret; + } + + ret = test(0, 0, 1, 1); + if (ret) { + fprintf(stderr, "test sqthread=0 direct=alloc failed\n"); + return ret; + } + + return 0; +} -- cgit v1.2.3 From 2ff9f7fe0c37662bc162d4eed57c2977d4d933a1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 May 2022 09:26:57 -0600 Subject: man: further clarify return value of the wait primitives They are in no way tied to a specific completion result, the returned value is only related to the act of getting a new completion event. Signed-off-by: Jens Axboe --- man/io_uring_wait_cqe.3 | 13 +++++++++---- man/io_uring_wait_cqe_nr.3 | 15 ++++++++++----- man/io_uring_wait_cqe_timeout.3 | 10 +++++++--- man/io_uring_wait_cqes.3 | 9 ++++++--- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3 index 1190d9b..3bd10f7 100644 --- a/man/io_uring_wait_cqe.3 +++ b/man/io_uring_wait_cqe.3 @@ -15,10 +15,12 @@ io_uring_wait_cqe - wait for one io_uring completion event .PP .SH DESCRIPTION .PP -The io_uring_wait_cqe() function returns an IO completion from the -queue belonging to the +The +.BR io_uring_wait_cqe (3) +function waits for an IO completion from the queue belonging to the .I ring -param, waiting for it if necessary. The +param, waiting for it if necessary. If an event is already available in +the ring when invoked, no waiting will occur. The .I cqe_ptr param is filled in on success. @@ -30,6 +32,9 @@ the application can retrieve the completion with .SH RETURN VALUE On success .BR io_uring_wait_cqe (3) -returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. +returns 0 and the cqe_ptr parm is filled in. On failure it returns +.B -errno. +The return value indicates the result of waiting for a CQE, and it has no +relation to the CQE result itself. .SH SEE ALSO .BR io_uring_submit (3), io_uring_wait_cqes(3) diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3 index 3594b0b..e4cf259 100644 --- a/man/io_uring_wait_cqe_nr.3 +++ b/man/io_uring_wait_cqe_nr.3 @@ -16,12 +16,14 @@ io_uring_wait_cqe_nr - wait for one or more io_uring completion events .PP .SH DESCRIPTION .PP -The io_uring_wait_cqe_nr() function returns +The +.BR io_uring_wait_cqe_nr (3) +function returns .I wait_nr -IO completion events from the -queue belonging to the +IO completion events from the queue belonging to the .I ring -param, waiting for it if necessary. The +param, waiting for it if necessary. If the requested number of events are +already available in the ring when invoked, no waiting will occur. The .I cqe_ptr param is filled in on success. @@ -33,6 +35,9 @@ the application can retrieve the completion with .SH RETURN VALUE On success .BR io_uring_wait_cqe_nr (3) -returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. +returns 0 and the cqe_ptr parm is filled in. On failure it returns +.B -errno. +The return value indicates the result of waiting for a CQE, and it has no +relation to the CQE result itself. .SH SEE ALSO .BR io_uring_submit (3), io_uring_wait_cqes (3) diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 index e81018a..1e27aed 100644 --- a/man/io_uring_wait_cqe_timeout.3 +++ b/man/io_uring_wait_cqe_timeout.3 @@ -15,12 +15,14 @@ io_uring_wait_cqe_timeout - wait for one io_uring completion event with timeout .PP .SH DESCRIPTION .PP -The io_uring_wait_cqe_timeout() function returns one IO completion from the -queue belonging to the +The +.BR io_uring_wait_cqe_timeout (3) function waits for one IO completion to be +available from the queue belonging to the .I ring param, waiting for it if necessary or until the timeout .I ts -expires. +expires.If an event is already available in the ring when invoked, no waiting +will occur. The .I cqe_ptr @@ -41,5 +43,7 @@ when waiting for a request. On success .BR io_uring_wait_cqes (3) returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. +The return value indicates the result of waiting for a CQE, and it has no +relation to the CQE result itself. .SH SEE ALSO .BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3 index 2fb727c..fc200bb 100644 --- a/man/io_uring_wait_cqes.3 +++ b/man/io_uring_wait_cqes.3 @@ -18,11 +18,13 @@ io_uring_wait_cqes - wait for one or more io_uring completion events .PP .SH DESCRIPTION .PP -The io_uring_wait_cqes() function returns +The +.BR io_uring_wait_cqes (3) +function returns .I wait_nr IO completions from the queue belonging to the .I ring -param, waiting for it if necessary or until the timeout +param, waiting for them if necessary or until the timeout .I ts expires. The .I sigmask @@ -47,6 +49,7 @@ when waiting for a request. .SH RETURN VALUE On success .BR io_uring_wait_cqes (3) -returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. +returns 0 and the cqe_ptr parm is filled in. On failure it returns +.B -errno. .SH SEE ALSO .BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). -- cgit v1.2.3 From 971f3cf0f134d32fd1aa0d691675165b89e83fe7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 May 2022 14:13:17 -0600 Subject: Fix type for io_uring_prep_socket_direct() The flags should always go last. Signed-off-by: Jens Axboe --- src/include/liburing.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/liburing.h b/src/include/liburing.h index b1a6ae4..6429dff 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -828,8 +828,8 @@ static inline void io_uring_prep_socket(struct io_uring_sqe *sqe, int domain, static inline void io_uring_prep_socket_direct(struct io_uring_sqe *sqe, int domain, int type, int protocol, - unsigned int flags, - unsigned file_index) + unsigned file_index, + unsigned int flags) { io_uring_prep_rw(IORING_OP_SOCKET, sqe, domain, NULL, protocol, type); sqe->rw_flags = flags; -- cgit v1.2.3 From 214d53c7c5a167082921bf400599896951e91a22 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 May 2022 14:20:46 -0600 Subject: man: add man page for io_uring_prep_socket() Includes the _direct() variant as well. Signed-off-by: Jens Axboe --- man/io_uring_prep_socket.3 | 96 +++++++++++++++++++++++++++++++++++++++ man/io_uring_prep_socket_direct.3 | 1 + 2 files changed, 97 insertions(+) create mode 100644 man/io_uring_prep_socket.3 create mode 120000 man/io_uring_prep_socket_direct.3 diff --git a/man/io_uring_prep_socket.3 b/man/io_uring_prep_socket.3 new file mode 100644 index 0000000..41d33ec --- /dev/null +++ b/man/io_uring_prep_socket.3 @@ -0,0 +1,96 @@ +.\" Copyright (C) 2022 Jens Axboe +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_prep_socket 3 "May 27, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_prep_socket - prepare a socket creation request +.fi +.SH SYNOPSIS +.nf +.BR "#include " +.BR "#include " +.PP +.BI "void io_uring_prep_socket(struct io_uring_sqe *" sqe "," +.BI " int " domain "," +.BI " int " type "," +.BI " int " protocol "," +.BI " unsigned int " flags ");" +.BI " +.BI "void io_uring_prep_socket_direct(struct io_uring_sqe *" sqe "," +.BI " int " domain "," +.BI " int " type "," +.BI " int " protocol "," +.BI " unsigned int " file_index "," +.BI " unsigned int " flags ");" +.PP +.SH DESCRIPTION +.PP +The +.BR io_uring_prep_socket (3) +function prepares a socket creation request. The submission queue entry +.I sqe +is setup to use the communication domain defined by +.I domain +and use the communication type defined by +.I type +and the protocol set by +.I protocol. +The +.I flags +argument are currently unused. + +The +.BR io_uring_prep_socket_direct (3) +works just like +.BR io_uring_prep_socket (3), +except it maps the socket to a direct descriptor rather than return a normal +file descriptor. The +.I file_index +argument should be set to the slot that should be used for this socket, or +.B IORING_FILE_INDEX_ALLOC +if io_uring should allocate a free one. + +This function prepares an async +.BR socket (2) +request. See that man page for details. + +If the direct variant is used, the application must first have registered +a file table using +.BR io_uring_register_files (3) +of the appropriate size. Once registered, a direct socket request may use any +entry in that table, as long as it is within the size of the registered table. +If a specified entry already contains a file, the file will first be removed +from the table and closed. It's consistent with the behavior of updating an +existing file with +.BR io_uring_register_files_update (3). + +For a direct descriptor socket request, the +.I file_index +argument can be set to +.B IORING_FILE_INDEX_ALLOC, +In this case a free entry in io_uring file table will +be used automatically and the file index will be returned as CQE +.I res. +.B -ENFILE +is otherwise returned if there is no free entries in the io_uring file table. + +.SH RETURN VALUE +None +.SH ERRORS +The CQE +.I res +field will contain the result of the operation. See the related man page for +details on possible values. Note that where synchronous system calls will return +.B -1 +on failure and set +.I errno +to the actual error value, io_uring never uses +.I errno. +Instead it returns the negated +.I errno +directly in the CQE +.I res +field. +.SH SEE ALSO +.BR io_uring_get_sqe (3), io_uring_submit (3), socket (2) diff --git a/man/io_uring_prep_socket_direct.3 b/man/io_uring_prep_socket_direct.3 new file mode 120000 index 0000000..15d7b7f --- /dev/null +++ b/man/io_uring_prep_socket_direct.3 @@ -0,0 +1 @@ +io_uring_prep_socket.3 \ No newline at end of file -- cgit v1.2.3 From 50b3d7b47ba0eea68798b335d18fd6ccfe3d01f3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 May 2022 14:33:22 -0600 Subject: man: be consistent in how the function is presented Signed-off-by: Jens Axboe --- man/io_uring_cq_advance.3 | 4 +++- man/io_uring_cq_ready.3 | 5 +++-- man/io_uring_cqe_get_data.3 | 3 ++- man/io_uring_cqe_seen.3 | 4 +++- man/io_uring_free_probe.3 | 4 +++- man/io_uring_get_probe.3 | 7 ++++--- man/io_uring_get_sqe.3 | 6 ++++-- man/io_uring_opcode_supported.3 | 5 +++-- man/io_uring_peek_cqe.3 | 5 +++-- man/io_uring_prep_accept.3 | 3 ++- man/io_uring_prep_cancel.3 | 2 +- man/io_uring_prep_close.3 | 5 +++-- man/io_uring_prep_connect.3 | 5 +++-- man/io_uring_prep_fadvise.3 | 5 +++-- man/io_uring_prep_fallocate.3 | 5 +++-- man/io_uring_prep_files_update.3 | 7 ++++--- man/io_uring_prep_fsync.3 | 5 +++-- man/io_uring_prep_linkat.3 | 5 +++-- man/io_uring_prep_madvise.3 | 5 +++-- man/io_uring_prep_mkdirat.3 | 5 +++-- man/io_uring_prep_msg_ring.3 | 5 +++-- man/io_uring_prep_openat.3 | 5 +++-- man/io_uring_prep_openat2.3 | 5 +++-- man/io_uring_prep_poll_add.3 | 5 +++-- man/io_uring_prep_poll_remove.3 | 5 +++-- man/io_uring_prep_poll_update.3 | 5 +++-- man/io_uring_prep_provide_buffers.3 | 6 ++++-- man/io_uring_prep_read.3 | 4 +++- man/io_uring_prep_read_fixed.3 | 6 ++++-- man/io_uring_prep_readv.3 | 5 +++-- man/io_uring_prep_readv2.3 | 5 +++-- man/io_uring_prep_remove_buffers.3 | 6 ++++-- man/io_uring_prep_renameat.3 | 5 +++-- man/io_uring_prep_send.3 | 5 +++-- man/io_uring_prep_sendmsg.3 | 5 +++-- man/io_uring_prep_shutdown.3 | 5 +++-- man/io_uring_prep_splice.3 | 5 +++-- man/io_uring_prep_statx.3 | 5 +++-- man/io_uring_prep_symlinkat.3 | 5 +++-- man/io_uring_prep_sync_file_range.3 | 5 +++-- man/io_uring_prep_tee.3 | 5 +++-- man/io_uring_prep_timeout.3 | 5 +++-- man/io_uring_prep_unlinkat.3 | 5 +++-- man/io_uring_prep_write.3 | 4 +++- man/io_uring_prep_write_fixed.3 | 6 ++++-- man/io_uring_prep_writev.3 | 5 +++-- man/io_uring_prep_writev2.3 | 5 +++-- man/io_uring_queue_init.3 | 4 +++- man/io_uring_register_eventfd.3 | 3 ++- man/io_uring_register_files.3 | 2 +- man/io_uring_register_iowq_aff.3 | 8 +++++--- man/io_uring_register_ring_fd.3 | 3 ++- man/io_uring_sq_ready.3 | 6 ++++-- man/io_uring_sq_space_left.3 | 5 +++-- man/io_uring_sqe_set_data.3 | 4 +++- man/io_uring_sqe_set_flags.3 | 6 ++++-- man/io_uring_sqring_wait.3 | 5 +++-- man/io_uring_submit.3 | 5 +++-- man/io_uring_submit_and_wait.3 | 5 +++-- man/io_uring_submit_and_wait_timeout.3 | 5 +++-- man/io_uring_unregister_buffers.3 | 5 +++-- man/io_uring_unregister_files.3 | 5 +++-- man/io_uring_unregister_ring_fd.3 | 3 ++- 63 files changed, 191 insertions(+), 115 deletions(-) diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 index 5aaf287..560a1d0 100644 --- a/man/io_uring_cq_advance.3 +++ b/man/io_uring_cq_advance.3 @@ -15,7 +15,9 @@ io_uring_cq_advance - Mark one or more io_uring completion events as consumed .PP .SH DESCRIPTION .PP -The io_uring_cq_advance() function marks +The +.BR io_uring_cq_advance (3) +function marks .I nr IO completions belonging to the .I ring diff --git a/man/io_uring_cq_ready.3 b/man/io_uring_cq_ready.3 index 548ded1..a03cda7 100644 --- a/man/io_uring_cq_ready.3 +++ b/man/io_uring_cq_ready.3 @@ -14,8 +14,9 @@ io_uring_cq_ready - returns number of unconsumed ready entries in the CQ ring .PP .SH DESCRIPTION .PP -The io_uring_cq_ready() function retuns the number of unconsumed entries that -are ready belonging to the +The +.BR io_uring_cq_ready (3) +function retuns the number of unconsumed entries that are ready belonging to the .I ring param. diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index 1f838c2..4c97a66 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -14,7 +14,8 @@ io_uring_cqe_get_data - get user data for completion event .PP .SH DESCRIPTION .PP -The io_uring_cqe_get_data() function returns the user_data with the completion +The +.BR io_uring_cqe_get_data (3) function returns the user_data with the completion queue entry .I cqe. diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3 index 41d276c..3e48df1 100644 --- a/man/io_uring_cqe_seen.3 +++ b/man/io_uring_cqe_seen.3 @@ -15,7 +15,9 @@ io_uring_cqe_seen - Mark io_uring completion event as consumed .PP .SH DESCRIPTION .PP -The io_uring_cqe_seen() function marks the IO completion +The +.BR io_uring_cqe_seen (3) +function marks the IO completion .I cqe belonging to the .I ring diff --git a/man/io_uring_free_probe.3 b/man/io_uring_free_probe.3 index 08d61ca..ba98a1b 100644 --- a/man/io_uring_free_probe.3 +++ b/man/io_uring_free_probe.3 @@ -14,7 +14,9 @@ io_uring_free_probe - free probe instance .PP .SH DESCRIPTION .PP -The function io_uring_free_probe() frees the +The function +.BR io_uring_free_probe (3) +frees the .I probe instance allocated with the .BR io_uring_get_probe (3) diff --git a/man/io_uring_get_probe.3 b/man/io_uring_get_probe.3 index 8b8a902..17841bf 100644 --- a/man/io_uring_get_probe.3 +++ b/man/io_uring_get_probe.3 @@ -14,9 +14,10 @@ io_uring_get_probe - get probe instance .PP .SH DESCRIPTION .PP -The function io_uring_get_probe() returns an allocated io_uring_probe -structure to the caller. The caller is responsible for freeing the -structure with the function +The function +.BR io_uring_get_probe (3) +returns an allocated io_uring_probe structure to the caller. The caller is +responsible for freeing the structure with the function .BR io_uring_free_probe (3). .SH NOTES diff --git a/man/io_uring_get_sqe.3 b/man/io_uring_get_sqe.3 index caada9b..48ffe01 100644 --- a/man/io_uring_get_sqe.3 +++ b/man/io_uring_get_sqe.3 @@ -16,8 +16,10 @@ submission queue .PP .SH DESCRIPTION .PP -The io_uring_get_sqe() function gets the next available submission queue entry -from the submission queue belonging to the +The +.BR io_uring_get_sqe (3) +function gets the next available submission queue entry from the submission +queue belonging to the .I ring param. diff --git a/man/io_uring_opcode_supported.3 b/man/io_uring_opcode_supported.3 index 293d643..9b3db98 100644 --- a/man/io_uring_opcode_supported.3 +++ b/man/io_uring_opcode_supported.3 @@ -15,8 +15,9 @@ io_uring_opcode_supported - is op code supported? .PP .SH DESCRIPTION .PP -The function io_uring_opcode_supported() allows the caller to determine if -the passed in +The function +.BR io_uring_opcode_supported (3) +allows the caller to determine if the passed in .I opcode belonging to the .I probe diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3 index 4c6e507..ae108b3 100644 --- a/man/io_uring_peek_cqe.3 +++ b/man/io_uring_peek_cqe.3 @@ -15,8 +15,9 @@ io_uring_peek_cqe - check if an io_uring completion event is available .PP .SH DESCRIPTION .PP -The io_uring_peek_cqe() function returns an IO completion from the -queue belonging to the +The +.BR io_uring_peek_cqe (3) +function returns an IO completion from the queue belonging to the .I ring param, if one is readily available. On successful return, .I cqe_ptr diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 4f2d6da..3aced88 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -38,7 +38,8 @@ io_uring_prep_accept - prepare an accept request .PP .SH DESCRIPTION .PP -The io_uring_prep_accept() function prepares an accept request. The submission +The +.BR io_uring_prep_accept (3) function prepares an accept request. The submission queue entry .I sqe is setup to use the file descriptor diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 0dc574a..31bfa41 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -21,7 +21,7 @@ io_uring_prep_cancel - prepare a cancelation request .SH DESCRIPTION .PP The -.BR io_uring_prep_cancel() +.BR io_uring_prep_cancel (3) function prepares a cancelation request. The submission queue entry .I sqe is prepared to cancel an existing request identified by diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index 490c27c..055e824 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -18,8 +18,9 @@ io_uring_prep_close - prepare a file descriptor close request .PP .SH DESCRIPTION .PP -The io_uring_prep_close() function prepares a close request. The submission -queue entry +The +.BR io_uring_prep_close (3) +function prepares a close request. The submission queue entry .I sqe is setup to close the file descriptor indicated by .I fd. diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 index 12caa2d..4bcbf0f 100644 --- a/man/io_uring_prep_connect.3 +++ b/man/io_uring_prep_connect.3 @@ -19,8 +19,9 @@ io_uring_prep_connect - prepare a connect request .PP .SH DESCRIPTION .PP -The io_uring_prep_connect() function prepares a connect request. The submission -queue entry +The +.BR io_uring_prep_connect (3) +function prepares a connect request. The submission queue entry .I sqe is setup to use the file descriptor .I sockfd diff --git a/man/io_uring_prep_fadvise.3 b/man/io_uring_prep_fadvise.3 index 41e00cb..a8c9d1d 100644 --- a/man/io_uring_prep_fadvise.3 +++ b/man/io_uring_prep_fadvise.3 @@ -19,8 +19,9 @@ io_uring_prep_fadvise - prepare a fadvise request .PP .SH DESCRIPTION .PP -The io_uring_prep_fadvise() function prepares an fadvise request. The submission -queue entry +The +.BR io_uring_prep_fadvise (3) +function prepares an fadvise request. The submission queue entry .I sqe is setup to use the file descriptor pointed to by .I fd diff --git a/man/io_uring_prep_fallocate.3 b/man/io_uring_prep_fallocate.3 index 49a8b4b..168251a 100644 --- a/man/io_uring_prep_fallocate.3 +++ b/man/io_uring_prep_fallocate.3 @@ -19,8 +19,9 @@ io_uring_prep_fallocate - prepare a fallocate request .PP .SH DESCRIPTION .PP -The io_uring_prep_fallocate() function prepares a fallocate request. The -submission queue entry +The +.BR io_uring_prep_fallocate (3) +function prepares a fallocate request. The submission queue entry .I sqe is setup to use the file descriptor pointed to by .I fd diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index eac1603..c9b88b8 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -17,9 +17,10 @@ io_uring_prep_files_update - prepare a registered file update request .PP .SH DESCRIPTION .PP -The io_uring_prep_files_update() function prepares a request for updating -a number of previously registered file descriptors. The -submission queue entry +The +.BR io_uring_prep_files_update (3) +function prepares a request for updating a number of previously registered file +descriptors. The submission queue entry .I sqe is setup to use the file descriptor array pointed to by .I fds diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 index 451407e..42f5742 100644 --- a/man/io_uring_prep_fsync.3 +++ b/man/io_uring_prep_fsync.3 @@ -16,8 +16,9 @@ io_uring_prep_fsync - prepare an fsync request .PP .SH DESCRIPTION .PP -The io_uring_prep_fsync() function prepares an fsync request. The submission -queue entry +The +.BR io_uring_prep_fsync (3) +function prepares an fsync request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index 73563e5..1dae9f3 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -21,8 +21,9 @@ io_uring_prep_linkat - prepare a linkat request .PP .SH DESCRIPTION .PP -The io_uring_prep_linkat() function prepares a linkat request. The -submission queue entry +The +.BR io_uring_prep_linkat (3) +function prepares a linkat request. The submission queue entry .I sqe is setup to use the old directory file descriptor pointed to by .I olddirfd diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 index 5d855a1..c7aac37 100644 --- a/man/io_uring_prep_madvise.3 +++ b/man/io_uring_prep_madvise.3 @@ -19,8 +19,9 @@ io_uring_prep_madvise - prepare a madvise request .PP .SH DESCRIPTION .PP -The io_uring_prep_madvise() function prepares an madvise request. The submission -queue entry +The +.BR io_uring_prep_madvise (3) +function prepares an madvise request. The submission queue entry .I sqe is setup to use the file descriptor pointed to by .I fd diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index d96a1bf..3278396 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -19,8 +19,9 @@ io_uring_prep_mkdirat - prepare an mkdirat request .PP .SH DESCRIPTION .PP -The io_uring_prep_mkdirat() function prepares an mkdirat request. The -submission queue entry +The +.BR io_uring_prep_mkdirat (3) +function prepares an mkdirat request. The submission queue entry .I sqe is setup to use the directory file descriptor pointed to by .I dirfd diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index a68121f..3f0f97d 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -18,8 +18,9 @@ io_uring_prep_msg_ring - send a message to another ring .SH DESCRIPTION .PP -io_uring_prep_msg_ring() prepares a to send a CQE to an io_uring file -descriptor. The submission queue entry +.BR io_uring_prep_msg_ring (3) +prepares a to send a CQE to an io_uring file descriptor. The submission queue +entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index b0f0946..5464945 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -28,8 +28,9 @@ io_uring_prep_openat - prepare an openat request .PP .SH DESCRIPTION .PP -The io_uring_prep_openat() function prepares an openat request. The submission -queue entry +The +.BR io_uring_prep_openat (3) +function prepares an openat request. The submission queue entry .I sqe is setup to use the directory file descriptor .I dfd diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 96682d8..07eadbc 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -29,8 +29,9 @@ io_uring_prep_openat2 - prepare an openat2 request .PP .SH DESCRIPTION .PP -The io_uring_prep_openat2() function prepares an openat2 request. The submission -queue entry +The +.BR io_uring_prep_openat2 (3) +function prepares an openat2 request. The submission queue entry .I sqe is setup to use the directory file descriptor .I dfd diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index c880523..2ba8d32 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -21,8 +21,9 @@ io_uring_prep_poll_add - prepare a poll request .PP .SH DESCRIPTION .PP -The io_uring_prep_poll_add() function prepares a poll request. The submission -queue entry +The +.BR io_uring_prep_poll_add (3) +function prepares a poll request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_poll_remove.3 b/man/io_uring_prep_poll_remove.3 index cd90fba..a04c0c2 100644 --- a/man/io_uring_prep_poll_remove.3 +++ b/man/io_uring_prep_poll_remove.3 @@ -16,8 +16,9 @@ io_uring_prep_poll_remove - prepare a poll deletion request .PP .SH DESCRIPTION .PP -The io_uring_prep_poll_remove() function prepares a poll removal request. The -submission queue entry +The +.BR io_uring_prep_poll_remove (3) +function prepares a poll removal request. The submission queue entry .I sqe is setup to remove a poll request identified by .I user_data diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index b6bc135..af9d542 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -19,8 +19,9 @@ io_uring_prep_poll_update - update an existing poll request .SH DESCRIPTION .PP -The io_uring_prep_poll_update() function prepares a poll update request. The -submission queue entry +The +.BR io_uring_prep_poll_update (3) +function prepares a poll update request. The submission queue entry .I sqe is setup to update a poll request identified by .I old_user_data, diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3 index bcfe4d8..d099a35 100644 --- a/man/io_uring_prep_provide_buffers.3 +++ b/man/io_uring_prep_provide_buffers.3 @@ -19,8 +19,10 @@ io_uring_prep_provide_buffers - prepare a provide buffers request .PP .SH DESCRIPTION .PP -The io_uring_prep_provide_buffers() function prepares a request for providing -the kernel with buffers. The submission queue entry +The +.BR io_uring_prep_provide_buffers (3) +function prepares a request for providing the kernel with buffers. The +submission queue entry .I sqe is setup to consume .I len diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index dd1008d..5d2c916 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -18,7 +18,9 @@ io_uring_prep_read - prepare I/O read request .SH DESCRIPTION .PP -The io_uring_prep_read() prepares an IO read request. The submission queue entry +The +.BR io_uring_prep_read (3) +prepares an IO read request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index 2d8dcd9..2156427 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -19,8 +19,10 @@ io_uring_prep_read_fixed - prepare I/O read request with registered buffer .SH DESCRIPTION .PP -The io_uring_prep_read_fixed() prepares an IO read request with a previously -registered IO buffer. The submission queue entry +The +.BR io_uring_prep_read_fixed (3) +prepares an IO read request with a previously registered IO buffer. The +submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index 1817689..3df7318 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -19,8 +19,9 @@ io_uring_prep_readv - prepare vector I/O read request .PP .SH DESCRIPTION .PP -The io_uring_prep_readv() prepares a vectored IO read request. The submission -queue entry +The +.BR io_uring_prep_readv (3) +prepares a vectored IO read request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index a25c595..64102f0 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -22,8 +22,9 @@ io_uring_prep_readv2 - prepare vector I/O read request with flags .PP .SH DESCRIPTION .PP -The io_uring_prep_readv2() prepares a vectored IO read request. The submission -queue entry +The +.BR io_uring_prep_readv2 (3) +prepares a vectored IO read request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_remove_buffers.3 b/man/io_uring_prep_remove_buffers.3 index 52c45e2..ff78d70 100644 --- a/man/io_uring_prep_remove_buffers.3 +++ b/man/io_uring_prep_remove_buffers.3 @@ -16,8 +16,10 @@ io_uring_prep_remove_buffers - prepare a remove buffers request .PP .SH DESCRIPTION .PP -The io_uring_prep_remove_buffers() function prepares a request for removing -previously supplied buffers. The submission queue entry +The +.BR io_uring_prep_remove_buffers (3) +function prepares a request for removing previously supplied buffers. The +submission queue entry .I sqe is setup to remove .I nr diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index 9f93576..5eefe33 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -21,8 +21,9 @@ io_uring_prep_renameat - prepare a renameat request .PP .SH DESCRIPTION .PP -The io_uring_prep_renameat() function prepares a renameat request. The -submission queue entry +The +.BR io_uring_prep_renameat (3) +function prepares a renameat request. The submission queue entry .I sqe is setup to use the old directory file descriptor pointed to by .I olddirfd diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 index 7ffe99b..fdd6423 100644 --- a/man/io_uring_prep_send.3 +++ b/man/io_uring_prep_send.3 @@ -18,8 +18,9 @@ io_uring_prep_send - prepare a send request .PP .SH DESCRIPTION .PP -The io_uring_prep_send() function prepares a send request. The submission -queue entry +The +.BR io_uring_prep_send (3) +function prepares a send request. The submission queue entry .I sqe is setup to use the file descriptor .I sockfd diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index 454d9da..8986399 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -19,8 +19,9 @@ io_uring_prep_sendmsg - prepare a sendmsg request .PP .SH DESCRIPTION .PP -The io_uring_prep_sendmsg() function prepares a sendmsg request. The submission -queue entry +The +.BR io_uring_prep_sendmsg (3) +function prepares a sendmsg request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index 733fd89..96948eb 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -17,8 +17,9 @@ io_uring_prep_shutdown - prepare a shutdown request .PP .SH DESCRIPTION .PP -The io_uring_prep_shutdown() function prepares a shutdown request. The -submission queue entry +The +.BR io_uring_prep_shutdown (3) +function prepares a shutdown request. The submission queue entry .I sqe is setup to use the file descriptor .I sockfd diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3 index 8aea3c1..eb6f1fe 100644 --- a/man/io_uring_prep_splice.3 +++ b/man/io_uring_prep_splice.3 @@ -21,8 +21,9 @@ io_uring_prep_splice - prepare an splice request .PP .SH DESCRIPTION .PP -The io_uring_prep_splice() function prepares a splice request. The submission -queue entry +The +.BR io_uring_prep_splice (3) +function prepares a splice request. The submission queue entry .I sqe is setup to use as input the file descriptor .I fd_in diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3 index 0ead796..63cf8cd 100644 --- a/man/io_uring_prep_statx.3 +++ b/man/io_uring_prep_statx.3 @@ -23,8 +23,9 @@ io_uring_prep_statx - prepare a statx request .PP .SH DESCRIPTION .PP -The io_uring_prep_statx() function prepares a statx request. The -submission queue entry +The +.BR io_uring_prep_statx (3) +function prepares a statx request. The submission queue entry .I sqe is setup to use the directory file descriptor pointed to by .I dirfd diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index 10f650a..be5169a 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -19,8 +19,9 @@ io_uring_prep_symlinkat - prepare a symlinkat request .PP .SH DESCRIPTION .PP -The io_uring_prep_symlinkat() function prepares a symlinkat request. The -submission queue entry +The +.BR io_uring_prep_symlinkat (3) +function prepares a symlinkat request. The submission queue entry .I sqe is setup to symlink the target path pointed to by .I target diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index 0fe96bd..0eacc7e 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -19,8 +19,9 @@ io_uring_prep_sync_file_range - prepare a sync_file_range request .PP .SH DESCRIPTION .PP -The io_uring_prep_sync_file_range() function prepares a sync_file_range request. -The submission queue entry +The +.BR io_uring_prep_sync_file_range (3) +function prepares a sync_file_range request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3 index 8b41a6f..af775be 100644 --- a/man/io_uring_prep_tee.3 +++ b/man/io_uring_prep_tee.3 @@ -19,8 +19,9 @@ io_uring_prep_tee - prepare a tee request .PP .SH DESCRIPTION .PP -The io_uring_prep_tee() function prepares a tee request. The submission queue -entry +The +.BR io_uring_prep_tee (3) +function prepares a tee request. The submission queue entry .I sqe is setup to use as input the file descriptor .I fd_in diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 index 38c4bf5..2bfbfb3 100644 --- a/man/io_uring_prep_timeout.3 +++ b/man/io_uring_prep_timeout.3 @@ -17,8 +17,9 @@ io_uring_prep_timeoute - prepare a timeout request .PP .SH DESCRIPTION .PP -The io_uring_prep_timeout() function prepares a timeout request. The submission -queue entry +The +.BR io_uring_prep_timeout (3) +function prepares a timeout request. The submission queue entry .I sqe is setup to arm a timeout specified by .I ts diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index c59b9ac..5f1c3b4 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -19,8 +19,9 @@ io_uring_prep_unlinkat - prepare an unlinkat request .PP .SH DESCRIPTION .PP -The io_uring_prep_unlinkat() function prepares an unlinkat request. The -submission queue entry +The +.BR io_uring_prep_unlinkat (3) +function prepares an unlinkat request. The submission queue entry .I sqe is setup to use the directory file descriptor pointed to by .I dirfd diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index c935f8b..3b44651 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -18,7 +18,9 @@ io_uring_prep_write - prepare I/O write request .PP .SH DESCRIPTION .PP -The io_uring_prep_write() prepares an IO write request. The submission queue entry +The +.BR io_uring_prep_write (3) +prepares an IO write request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index 77143ca..91d1107 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -19,8 +19,10 @@ io_uring_prep_write_fixed - prepare I/O write request with registered buffer .SH DESCRIPTION .PP -The io_uring_prep_write_fixed() prepares an IO write request with a previously -registered IO buffer. The submission queue entry +The +.BR io_uring_prep_write_fixed (3) +prepares an IO write request with a previously registered IO buffer. The +submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index ff1a6d5..13e4f95 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -19,8 +19,9 @@ io_uring_prep_writev - prepare vector I/O write request .PP .SH DESCRIPTION .PP -The io_uring_prep_writev() prepares a vectored IO write request. The submission -queue entry +The +.BR io_uring_prep_writev (3) +prepares a vectored IO write request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index cc646f3..27ed781 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -21,8 +21,9 @@ io_uring_prep_writev2 - prepare vector I/O write request with flags .PP .SH DESCRIPTION .PP -The io_uring_prep_writev2() prepares a vectored IO write request. The -submission queue entry +The +.BR io_uring_prep_writev2 (3) +prepares a vectored IO write request. The submission queue entry .I sqe is setup to use the file descriptor .I fd diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index d2c4d47..f34d163 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -21,7 +21,9 @@ io_uring_queue_init - setup io_uring submission and completion queues .PP .SH DESCRIPTION .PP -The io_uring_queue_init() function executes the +The +.BR io_uring_queue_init (3) +function executes the .BR io_uring_setup (2) system call to initialize the submission and completion queues in the kernel with at least diff --git a/man/io_uring_register_eventfd.3 b/man/io_uring_register_eventfd.3 index c88c3bf..ec2295c 100644 --- a/man/io_uring_register_eventfd.3 +++ b/man/io_uring_register_eventfd.3 @@ -18,7 +18,8 @@ io_uring_register_eventfd - register an eventfd with a ring .SH DESCRIPTION .PP -io_uring_register_eventfd() registers the eventfd file descriptor +.BR io_uring_register_eventfd (3) +registers the eventfd file descriptor .I fd with the ring identified by .I ring. diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index 8a627a9..e342506 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -20,7 +20,7 @@ io_uring_register_files - register file descriptors .SH DESCRIPTION .PP The -.BR io_uring_register_files() +.BR io_uring_register_files (3) function registers .I nr_files number of file descriptors defined by the array diff --git a/man/io_uring_register_iowq_aff.3 b/man/io_uring_register_iowq_aff.3 index b82af8b..cf5cd73 100644 --- a/man/io_uring_register_iowq_aff.3 +++ b/man/io_uring_register_iowq_aff.3 @@ -19,9 +19,11 @@ io_uring_register_iowq_aff - register async worker CPU affinities .PP .SH DESCRIPTION .PP -The io_uring_prep_register_iowq_aff() function registers a set of CPU affinities -to be used by the io_uring async workers. By default, io_uring async workers -are allowed to run on any CPU in the system. If this function is called with +The +.BR io_uring_prep_register_iowq_aff (3) +function registers a set of CPU affinities to be used by the io_uring async +workers. By default, io_uring async workers are allowed to run on any CPU in +the system. If this function is called with .I ring set to the ring in question and .I mask diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3 index 144262f..9d86b0d 100644 --- a/man/io_uring_register_ring_fd.3 +++ b/man/io_uring_register_ring_fd.3 @@ -14,7 +14,8 @@ io_uring_register_ring_fd - register a ring file descriptor .SH DESCRIPTION .PP -io_uring_register_ring_fd() registers the file descriptor of the ring. +.BR io_uring_register_ring_fd (3) +registers the file descriptor of the ring. Whenever .BR io_uring_enter (2) diff --git a/man/io_uring_sq_ready.3 b/man/io_uring_sq_ready.3 index 80dfa82..53f5be5 100644 --- a/man/io_uring_sq_ready.3 +++ b/man/io_uring_sq_ready.3 @@ -14,8 +14,10 @@ io_uring_sq_ready - number of unconsumed or unsubmitted entries in the SQ ring .PP .SH DESCRIPTION .PP -The io_uring_sq_ready() function retuns the number of unconsumed (if SQPOLL) or -unsubmitted entries that exist in the SQ ring belonging to the +The +.BR io_uring_sq_ready (3) +function retuns the number of unconsumed (if SQPOLL) or unsubmitted entries +that exist in the SQ ring belonging to the .I ring param. diff --git a/man/io_uring_sq_space_left.3 b/man/io_uring_sq_space_left.3 index be44c0a..e167097 100644 --- a/man/io_uring_sq_space_left.3 +++ b/man/io_uring_sq_space_left.3 @@ -14,8 +14,9 @@ io_uring_sq_space_left - free space in the SQ ring .PP .SH DESCRIPTION .PP -The io_uring_sq_space_left() function retuns how much space is left in the -SQ ring belonging to the +The +.BR io_uring_sq_space_left (3) +function retuns how much space is left in the SQ ring belonging to the .I ring param. diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3 index ec22518..a30bbf8 100644 --- a/man/io_uring_sqe_set_data.3 +++ b/man/io_uring_sqe_set_data.3 @@ -15,7 +15,9 @@ io_uring_sqe_set_data - set user data for submission queue event .PP .SH DESCRIPTION .PP -The io_uring_sqe_set_data() function stores a +The +.BR io_uring_sqe_set_data (3) +function stores a .I user_data pointer with the submission queue entry .I sqe. diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 index 10ed8d3..76964e5 100644 --- a/man/io_uring_sqe_set_flags.3 +++ b/man/io_uring_sqe_set_flags.3 @@ -15,8 +15,10 @@ io_uring_sqe_set_flags - set flags for submission queue entry .PP .SH DESCRIPTION .PP -The io_uring_sqe_set_flags() function allows the caller to change the -behavior of the submission queue entry by specifying flags. It enables the +The +.BR io_uring_sqe_set_flags (3) +function allows the caller to change the behavior of the submission queue entry +by specifying flags. It enables the .I flags belonging to the .I sqe diff --git a/man/io_uring_sqring_wait.3 b/man/io_uring_sqring_wait.3 index c0e4e9c..7bdff65 100644 --- a/man/io_uring_sqring_wait.3 +++ b/man/io_uring_sqring_wait.3 @@ -14,8 +14,9 @@ io_uring_sqring_wait - wait for free space in the SQ ring .PP .SH DESCRIPTION .PP -The function io_uring_sqring_wait() allows the caller to wait for space -to free up in the SQ ring belonging to the +The function +.BR io_uring_sqring_wait (3) +allows the caller to wait for space to free up in the SQ ring belonging to the .I ring param, which happens when the kernel side thread has consumed one or more entries. If the SQ ring is currently non-full, diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 index 83ab922..c26c20d 100644 --- a/man/io_uring_submit.3 +++ b/man/io_uring_submit.3 @@ -14,8 +14,9 @@ io_uring_submit - submit requests to the submission queue .PP .SH DESCRIPTION .PP -The io_uring_submit() function submits the next events to the submission -queue belonging to the +The +.BR io_uring_submit (3) +function submits the next events to the submission queue belonging to the .I ring. After the caller retrieves a submission queue entry (SQE) with diff --git a/man/io_uring_submit_and_wait.3 b/man/io_uring_submit_and_wait.3 index 909781a..320df9d 100644 --- a/man/io_uring_submit_and_wait.3 +++ b/man/io_uring_submit_and_wait.3 @@ -15,8 +15,9 @@ io_uring_submit_and_wait - submit requests to the submission queue and wait for .PP .SH DESCRIPTION .PP -The io_uring_submit_and_wait() function submits the next events to the submission -queue belonging to the +The +.BR io_uring_submit_and_wait (3) +function submits the next events to the submission queue belonging to the .I ring and waits for .I wait_nr diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 index 299d7b1..2aba4cf 100644 --- a/man/io_uring_submit_and_wait_timeout.3 +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -19,8 +19,9 @@ wait for the completion with timeout .PP .SH DESCRIPTION .PP -The io_uring_submit_and_wait_timeout() function submits the next events to the submission -queue belonging to the +The +.BR io_uring_submit_and_wait_timeout (3) +function submits the next events to the submission queue belonging to the .I ring and waits for .I wait_nr diff --git a/man/io_uring_unregister_buffers.3 b/man/io_uring_unregister_buffers.3 index d9d6f06..26ff806 100644 --- a/man/io_uring_unregister_buffers.3 +++ b/man/io_uring_unregister_buffers.3 @@ -14,8 +14,9 @@ io_uring_unregister_buffers - unregister buffers for fixed buffer operations .PP .SH DESCRIPTION .PP -The io_uring_unregister_buffers() function unregisters -the fixed buffers previously registered to the +The +.BR io_uring_unregister_buffers (3) +function unregisters the fixed buffers previously registered to the .I ring. .SH RETURN VALUE diff --git a/man/io_uring_unregister_files.3 b/man/io_uring_unregister_files.3 index bcad996..a08bbd0 100644 --- a/man/io_uring_unregister_files.3 +++ b/man/io_uring_unregister_files.3 @@ -14,8 +14,9 @@ io_uring_unregister_files - unregister file descriptors .PP .SH DESCRIPTION .PP -The io_uring_unregister_files() function unregisters -the file descriptors previously registered to the +The +.BR io_uring_unregister_files (3) +function unregisters the file descriptors previously registered to the .I ring. .SH RETURN VALUE diff --git a/man/io_uring_unregister_ring_fd.3 b/man/io_uring_unregister_ring_fd.3 index d4a1cc6..c958ec1 100644 --- a/man/io_uring_unregister_ring_fd.3 +++ b/man/io_uring_unregister_ring_fd.3 @@ -14,7 +14,8 @@ io_uring_unregister_ring_fd - unregister a ring file descriptor .SH DESCRIPTION .PP -io_uring_unregister_ring_fd() unregisters the file descriptor of the ring. +.BR io_uring_unregister_ring_fd (3) +unregisters the file descriptor of the ring. Unregisters a ring descriptor previously registered with the task. This is done automatically when -- cgit v1.2.3 From ecf66cc2a49c69e9c9d224ef54b95082844a7b7a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 May 2022 14:46:48 -0600 Subject: man: add note on vectored reads and writes Applications tend to use vectored IO even for a single segment IO request, but this is less efficient than a non-vectored one. This is true for the normal readv(2)/writev(2) and related system calls as well, but it doesn't seem that this is common knowledge. In short, unless you have more than 1 segment for an IO request, use the non-vectored version! Signed-off-by: Jens Axboe --- man/io_uring_prep_readv.3 | 5 +++++ man/io_uring_prep_readv2.3 | 5 +++++ man/io_uring_prep_writev.3 | 5 +++++ man/io_uring_prep_writev2.3 | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index 3df7318..e758de9 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -65,6 +65,11 @@ directly in the CQE .I res field. .SH NOTES +Unless an application explicitly needs to pass in more than iovec, it is more +efficient to use +.BR io_uring_prep_read (3) +rather than this function, as no state has to be maintained for a +non-vectored IO request. As with any request that passes in data in a struct, that data must remain valid until the request has been successfully submitted. It need not remain valid until completion. Once a request has been submitted, the in-kernel diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 64102f0..0279fa3 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -93,6 +93,11 @@ directly in the CQE .I res field. .SH NOTES +Unless an application explicitly needs to pass in more than iovec, it is more +efficient to use +.BR io_uring_prep_read (3) +rather than this function, as no state has to be maintained for a +non-vectored IO request. As with any request that passes in data in a struct, that data must remain valid until the request has been successfully submitted. It need not remain valid until completion. Once a request has been submitted, the in-kernel diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 13e4f95..4ccfadc 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -65,6 +65,11 @@ directly in the CQE .I res field. .SH NOTES +Unless an application explicitly needs to pass in more than iovec, it is more +efficient to use +.BR io_uring_prep_write (3) +rather than this function, as no state has to be maintained for a +non-vectored IO request. As with any request that passes in data in a struct, that data must remain valid until the request has been successfully submitted. It need not remain valid until completion. Once a request has been submitted, the in-kernel diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index 27ed781..bab62a6 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -92,6 +92,11 @@ directly in the CQE .I res field. .SH NOTES +Unless an application explicitly needs to pass in more than iovec, it is more +efficient to use +.BR io_uring_prep_write (3) +rather than this function, as no state has to be maintained for a +non-vectored IO request. As with any request that passes in data in a struct, that data must remain valid until the request has been successfully submitted. It need not remain valid until completion. Once a request has been submitted, the in-kernel -- cgit v1.2.3 From 87b6b2112c3de7be7b6c0a32974cbd6ee61ddcb7 Mon Sep 17 00:00:00 2001 From: Xiaoguang Wang Date: Tue, 31 May 2022 01:36:04 +0800 Subject: Let IORING_OP_FILES_UPDATE support to choose fixed file slots Allocate available direct descriptors instead of having the application pass free fixed file slots. To use it, pass IORING_FILE_INDEX_ALLOC to io_uring_prep_files_update(), then io_uring in kernel will store picked fixed file slots in fd array and let cqe return the number of slots allocated. Signed-off-by: Xiaoguang Wang Link: https://lore.kernel.org/r/20220530173604.38000-1-xiaoguang.wang@linux.alibaba.com Signed-off-by: Jens Axboe --- man/io_uring_prep_close.3 | 10 +++ man/io_uring_prep_files_update.3 | 10 +++ src/include/liburing.h | 8 +++ src/include/liburing/io_uring.h | 6 ++ test/Makefile | 1 + test/file-update-index-alloc.c | 139 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 174 insertions(+) create mode 100644 test/file-update-index-alloc.c diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index 055e824..9e924a1 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -15,6 +15,9 @@ io_uring_prep_close - prepare a file descriptor close request .BI " .BI "void io_uring_prep_close_direct(struct io_uring_sqe *" sqe "," .BI " unsigned " file_index ");" +.BI " +.BI "void io_uring_prep_close_all(struct io_uring_sqe *" sqe "," +.BI " int " fd ", unsigned " file_index ");" .PP .SH DESCRIPTION .PP @@ -32,6 +35,13 @@ argument instead of the This is identical to unregistering the direct descriptor, and is provided as a convenience. +For a close request which also has a direct descriptor, the +.BR io_uring_prep_close_all(3) +function is identical to close file descriptor indicated by +.I fd +and unregister the direct descriptor specified by the +.I file_index. + This function prepares an async .BR close (2) request. See that man page for details. diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index c9b88b8..95c6c4f 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -35,6 +35,16 @@ entry is updated and then removed from the table. This operation is equivalent t first unregistering that entry and then inserting a new one, just bundled into one combined operation. +If +.I offset +is specified as IORING_FILE_INDEX_ALLOC, io_uring will allocate free direct +descriptors instead of having the application to pass, and store allocated +direct descriptors into +.I fds +array, +.I cqe->res +will return the number of direct descriptors allocated. + .SH RETURN VALUE None .SH ERRORS diff --git a/src/include/liburing.h b/src/include/liburing.h index 6429dff..bc82d99 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -614,6 +614,14 @@ static inline void io_uring_prep_close_direct(struct io_uring_sqe *sqe, __io_uring_set_target_fixed_file(sqe, file_index); } +static inline void io_uring_prep_close_all(struct io_uring_sqe *sqe, + int fd, unsigned file_index) +{ + io_uring_prep_close(sqe, fd); + __io_uring_set_target_fixed_file(sqe, file_index); + sqe->close_flags = IORING_CLOSE_FD_AND_FILE_SLOT; +} + static inline void io_uring_prep_read(struct io_uring_sqe *sqe, int fd, void *buf, unsigned nbytes, __u64 offset) { diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 2f391c9..15d9fbd 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -50,6 +50,7 @@ struct io_uring_sqe { __u32 unlink_flags; __u32 hardlink_flags; __u32 xattr_flags; + __u32 close_flags; }; __u64 user_data; /* data to be passed back at completion time */ /* pack this to avoid bogus arm OABI complaints */ @@ -78,6 +79,11 @@ struct io_uring_sqe { */ #define IORING_FILE_INDEX_ALLOC (~0U) +/* + * close flags, store in sqe->close_flags. + */ +#define IORING_CLOSE_FD_AND_FILE_SLOT (1U << 0) + enum { IOSQE_FIXED_FILE_BIT, IOSQE_IO_DRAIN_BIT, diff --git a/test/Makefile b/test/Makefile index 51c35a9..ab031e0 100644 --- a/test/Makefile +++ b/test/Makefile @@ -79,6 +79,7 @@ test_srcs := \ files-exit-hang-poll.c \ files-exit-hang-timeout.c \ file-update.c \ + file-update-index-alloc.c \ file-verify.c \ fixed-buf-iter.c \ fixed-link.c \ diff --git a/test/file-update-index-alloc.c b/test/file-update-index-alloc.c new file mode 100644 index 0000000..e4bc73c --- /dev/null +++ b/test/file-update-index-alloc.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: test IORING_OP_FILES_UPDATE can support io_uring + * allocates an available direct descriptor instead of having the + * application pass one. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "helpers.h" +#include "liburing.h" + +int main(int argc, char *argv[]) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + char wbuf[1] = { 0xef }, rbuf[1] = {0x0}; + struct io_uring ring; + int i, ret, pipe_fds[2], fds[2] = { -1, -1}; + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed\n"); + return -1; + } + + ret = io_uring_register_files(&ring, fds, 2); + if (ret) { + fprintf(stderr, "%s: register ret=%d\n", __func__, ret); + return -1; + } + + if (pipe2(pipe_fds, O_NONBLOCK)) { + fprintf(stderr, "pipe() failed\n"); + return -1; + } + + /* + * Pass IORING_FILE_INDEX_ALLOC, so io_uring in kernel will allocate + * available direct descriptors. + */ + fds[0] = pipe_fds[0]; + fds[1] = pipe_fds[1]; + sqe = io_uring_get_sqe(&ring); + io_uring_prep_files_update(sqe, fds, 2, IORING_FILE_INDEX_ALLOC); + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + return -1; + } + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait files update completion failed: %d\n", ret); + return ret; + } + + if (cqe->res < 0) { + if (cqe->res == -EINVAL) { + fprintf(stdout, "files update(IORING_FILE_INDEX_ALLOC) not " + "supported, skipping\n"); + return 0; + } + fprintf(stderr, "files update(IORING_FILE_INDEX_ALLOC) failed: %d\n", ret); + return ret; + } + ret = cqe->res; + if (ret != 2) { + fprintf(stderr, "should allocate 2 direct descriptors, but get:%d\n", ret); + return -1; + } + if (fds[0] != 0 || fds[1] != 1) { + fprintf(stderr, "allocate wrong direct descriptors:%d %d\n", + fds[0], fds[1]); + return -1; + } + io_uring_cqe_seen(&ring, cqe); + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_write(sqe, fds[1], wbuf, sizeof(wbuf), 0); + sqe->flags |= IOSQE_FIXED_FILE; + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + return -1; + } + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0 || cqe->res < 0) { + fprintf(stderr, "write failed %d\n", ret); + return ret; + } + io_uring_cqe_seen(&ring, cqe); + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_read(sqe, fds[0], rbuf, sizeof(rbuf), 0); + sqe->flags |= IOSQE_FIXED_FILE; + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + return -1; + } + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0 || cqe->res < 0) { + fprintf(stderr, "read failed %d\n", ret); + return ret; + } + if (rbuf[0] != (char)0xef) { + fprintf(stderr, "read wrong data %x\n", rbuf[0]); + return ret; + } + io_uring_cqe_seen(&ring, cqe); + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_close_all(sqe, pipe_fds[0], fds[0]); + sqe = io_uring_get_sqe(&ring); + io_uring_prep_close_all(sqe, pipe_fds[1], fds[1]); + ret = io_uring_submit(&ring); + if (ret != 2) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + return -1; + } + + for (i = 0; i < 2; i++) { + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0 || cqe->res < 0) { + fprintf(stderr, "wait close completion %d\n", ret); + return ret; + } + io_uring_cqe_seen(&ring, cqe); + } + + io_uring_queue_exit(&ring); + return 0; +} -- cgit v1.2.3 From c7d274054fea5e0a2fc2aa645b0c728643c355a6 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 30 May 2022 16:53:47 -0600 Subject: Tweaks to close+unregister of direct descriptor Rename it to io_uring_prep_close_direct_unregister(), which is quite long but more descriptive. Fix up test case for naming, and also ensure that it doesn't fail on some older kernels where -EOVERFLOW would be returned because of the large index. Signed-off-by: Jens Axboe --- man/io_uring_prep_close.3 | 14 ++++++++------ src/include/liburing.h | 5 +++-- test/file-update-index-alloc.c | 8 ++++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index 9e924a1..d171879 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -16,8 +16,9 @@ io_uring_prep_close - prepare a file descriptor close request .BI "void io_uring_prep_close_direct(struct io_uring_sqe *" sqe "," .BI " unsigned " file_index ");" .BI " -.BI "void io_uring_prep_close_all(struct io_uring_sqe *" sqe "," -.BI " int " fd ", unsigned " file_index ");" +.BI "void io_uring_prep_close_direct_unregister(struct io_uring_sqe *" sqe "," +.BI " int " fd ", +.BI " unsigned " file_index ");" .PP .SH DESCRIPTION .PP @@ -35,11 +36,12 @@ argument instead of the This is identical to unregistering the direct descriptor, and is provided as a convenience. -For a close request which also has a direct descriptor, the -.BR io_uring_prep_close_all(3) -function is identical to close file descriptor indicated by +For a close request of a direct descriptor where the application also wants +to unregister it, +.BR io_uring_prep_close_direct_unregister (3) +function is identical to closing a file descriptor indicated by .I fd -and unregister the direct descriptor specified by the +and unregistering the direct descriptor specified by the .I file_index. This function prepares an async diff --git a/src/include/liburing.h b/src/include/liburing.h index bc82d99..771e150 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -614,8 +614,9 @@ static inline void io_uring_prep_close_direct(struct io_uring_sqe *sqe, __io_uring_set_target_fixed_file(sqe, file_index); } -static inline void io_uring_prep_close_all(struct io_uring_sqe *sqe, - int fd, unsigned file_index) +static inline void +io_uring_prep_close_direct_unregister(struct io_uring_sqe *sqe, int fd, + unsigned file_index) { io_uring_prep_close(sqe, fd); __io_uring_set_target_fixed_file(sqe, file_index); diff --git a/test/file-update-index-alloc.c b/test/file-update-index-alloc.c index e4bc73c..ea5b420 100644 --- a/test/file-update-index-alloc.c +++ b/test/file-update-index-alloc.c @@ -61,12 +61,12 @@ int main(int argc, char *argv[]) } if (cqe->res < 0) { - if (cqe->res == -EINVAL) { + if (cqe->res == -EINVAL || cqe->res == -EOVERFLOW) { fprintf(stdout, "files update(IORING_FILE_INDEX_ALLOC) not " "supported, skipping\n"); return 0; } - fprintf(stderr, "files update(IORING_FILE_INDEX_ALLOC) failed: %d\n", ret); + fprintf(stderr, "files update(IORING_FILE_INDEX_ALLOC) failed: %d\n", cqe->res); return ret; } ret = cqe->res; @@ -116,9 +116,9 @@ int main(int argc, char *argv[]) io_uring_cqe_seen(&ring, cqe); sqe = io_uring_get_sqe(&ring); - io_uring_prep_close_all(sqe, pipe_fds[0], fds[0]); + io_uring_prep_close_direct_unregister(sqe, pipe_fds[0], fds[0]); sqe = io_uring_get_sqe(&ring); - io_uring_prep_close_all(sqe, pipe_fds[1], fds[1]); + io_uring_prep_close_direct_unregister(sqe, pipe_fds[1], fds[1]); ret = io_uring_submit(&ring); if (ret != 2) { fprintf(stderr, "sqe submit failed: %d\n", ret); -- cgit v1.2.3 From 4d9e52c62df1eb225486cc1636b2f679b621f065 Mon Sep 17 00:00:00 2001 From: Otto Modinos Date: Tue, 31 May 2022 11:39:55 +0300 Subject: man: keep the function names in their own lines Signed-off-by: Otto Modinos --- man/io_uring_cqe_get_data.3 | 4 ++-- man/io_uring_prep_accept.3 | 4 ++-- man/io_uring_wait_cqe_timeout.3 | 13 +++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index 4c97a66..8d26415 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -15,8 +15,8 @@ io_uring_cqe_get_data - get user data for completion event .SH DESCRIPTION .PP The -.BR io_uring_cqe_get_data (3) function returns the user_data with the completion -queue entry +.BR io_uring_cqe_get_data (3) +function returns the user_data with the completion queue entry .I cqe. After the caller has received a completion queue entry (CQE) with diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 3aced88..9fd7ea5 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -39,8 +39,8 @@ io_uring_prep_accept - prepare an accept request .SH DESCRIPTION .PP The -.BR io_uring_prep_accept (3) function prepares an accept request. The submission -queue entry +.BR io_uring_prep_accept (3) +function prepares an accept request. The submission queue entry .I sqe is setup to use the file descriptor .I sockfd diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 index 1e27aed..07bc9b4 100644 --- a/man/io_uring_wait_cqe_timeout.3 +++ b/man/io_uring_wait_cqe_timeout.3 @@ -16,12 +16,13 @@ io_uring_wait_cqe_timeout - wait for one io_uring completion event with timeout .SH DESCRIPTION .PP The -.BR io_uring_wait_cqe_timeout (3) function waits for one IO completion to be -available from the queue belonging to the +.BR io_uring_wait_cqe_timeout (3) +function waits for one IO completion to be available from the queue belonging +to the .I ring param, waiting for it if necessary or until the timeout .I ts -expires.If an event is already available in the ring when invoked, no waiting +expires. If an event is already available in the ring when invoked, no waiting will occur. The @@ -42,8 +43,8 @@ when waiting for a request. .SH RETURN VALUE On success .BR io_uring_wait_cqes (3) -returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. -The return value indicates the result of waiting for a CQE, and it has no -relation to the CQE result itself. +returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. The +return value indicates the result of waiting for a CQE, and it has no relation +to the CQE result itself. .SH SEE ALSO .BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). -- cgit v1.2.3 From 834ed0eec883f73483a2869cbe24d7c4e51002e0 Mon Sep 17 00:00:00 2001 From: Otto Modinos Date: Tue, 31 May 2022 19:22:51 +0300 Subject: man: be consistent with description dash Looking at other projects' manpages, most escaped the dash so I did too. I also fixed some spacing issues before the dash and some casing issues in the description. Also, I removed some `.fi`s. They don't do anything as far as I can tell. Signed-off-by: Otto Modinos --- man/io_uring_buf_ring_add.3 | 3 +-- man/io_uring_buf_ring_advance.3 | 3 +-- man/io_uring_buf_ring_cq_advance.3 | 3 +-- man/io_uring_cq_advance.3 | 2 +- man/io_uring_cq_ready.3 | 2 +- man/io_uring_cqe_get_data.3 | 2 +- man/io_uring_cqe_seen.3 | 2 +- man/io_uring_free_probe.3 | 2 +- man/io_uring_get_probe.3 | 2 +- man/io_uring_get_sqe.3 | 2 +- man/io_uring_opcode_supported.3 | 2 +- man/io_uring_peek_cqe.3 | 2 +- man/io_uring_prep_accept.3 | 3 +-- man/io_uring_prep_cancel.3 | 3 +-- man/io_uring_prep_close.3 | 3 +-- man/io_uring_prep_connect.3 | 3 +-- man/io_uring_prep_fadvise.3 | 3 +-- man/io_uring_prep_fallocate.3 | 3 +-- man/io_uring_prep_files_update.3 | 3 +-- man/io_uring_prep_fsync.3 | 3 +-- man/io_uring_prep_linkat.3 | 3 +-- man/io_uring_prep_madvise.3 | 3 +-- man/io_uring_prep_mkdirat.3 | 3 +-- man/io_uring_prep_msg_ring.3 | 3 +-- man/io_uring_prep_openat.3 | 3 +-- man/io_uring_prep_openat2.3 | 3 +-- man/io_uring_prep_poll_add.3 | 3 +-- man/io_uring_prep_poll_remove.3 | 3 +-- man/io_uring_prep_poll_update.3 | 3 +-- man/io_uring_prep_provide_buffers.3 | 3 +-- man/io_uring_prep_read.3 | 3 +-- man/io_uring_prep_read_fixed.3 | 3 +-- man/io_uring_prep_readv.3 | 3 +-- man/io_uring_prep_readv2.3 | 4 +--- man/io_uring_prep_recv.3 | 3 +-- man/io_uring_prep_recvmsg.3 | 3 +-- man/io_uring_prep_remove_buffers.3 | 3 +-- man/io_uring_prep_renameat.3 | 3 +-- man/io_uring_prep_send.3 | 3 +-- man/io_uring_prep_sendmsg.3 | 3 +-- man/io_uring_prep_shutdown.3 | 3 +-- man/io_uring_prep_socket.3 | 3 +-- man/io_uring_prep_splice.3 | 3 +-- man/io_uring_prep_statx.3 | 3 +-- man/io_uring_prep_symlinkat.3 | 3 +-- man/io_uring_prep_sync_file_range.3 | 3 +-- man/io_uring_prep_tee.3 | 3 +-- man/io_uring_prep_timeout.3 | 3 +-- man/io_uring_prep_timeout_update.3 | 3 +-- man/io_uring_prep_unlinkat.3 | 3 +-- man/io_uring_prep_write.3 | 3 +-- man/io_uring_prep_write_fixed.3 | 3 +-- man/io_uring_prep_writev.3 | 3 +-- man/io_uring_prep_writev2.3 | 3 +-- man/io_uring_queue_exit.3 | 2 +- man/io_uring_queue_init.3 | 2 +- man/io_uring_register_buf_ring.3 | 3 +-- man/io_uring_register_buffers.3 | 3 +-- man/io_uring_register_eventfd.3 | 3 +-- man/io_uring_register_files.3 | 3 +-- man/io_uring_register_iowq_aff.3 | 3 +-- man/io_uring_register_iowq_max_workers.3 | 3 +-- man/io_uring_register_ring_fd.3 | 3 +-- man/io_uring_sq_ready.3 | 2 +- man/io_uring_sq_space_left.3 | 2 +- man/io_uring_sqe_set_data.3 | 2 +- man/io_uring_sqe_set_flags.3 | 2 +- man/io_uring_sqring_wait.3 | 2 +- man/io_uring_submit.3 | 3 +-- man/io_uring_submit_and_wait.3 | 3 +-- man/io_uring_submit_and_wait_timeout.3 | 3 +-- man/io_uring_unregister_buf_ring.3 | 3 +-- man/io_uring_unregister_buffers.3 | 3 +-- man/io_uring_unregister_files.3 | 3 +-- man/io_uring_unregister_ring_fd.3 | 3 +-- man/io_uring_wait_cqe.3 | 2 +- man/io_uring_wait_cqe_nr.3 | 2 +- man/io_uring_wait_cqe_timeout.3 | 2 +- man/io_uring_wait_cqes.3 | 2 +- 79 files changed, 79 insertions(+), 139 deletions(-) diff --git a/man/io_uring_buf_ring_add.3 b/man/io_uring_buf_ring_add.3 index 7fd751e..0b10665 100644 --- a/man/io_uring_buf_ring_add.3 +++ b/man/io_uring_buf_ring_add.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_buf_ring_add 3 "May 18, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_buf_ring_add - add buffers to a shared buffer ring -.fi +io_uring_buf_ring_add \- add buffers to a shared buffer ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_buf_ring_advance.3 b/man/io_uring_buf_ring_advance.3 index 60c16a1..41ede49 100644 --- a/man/io_uring_buf_ring_advance.3 +++ b/man/io_uring_buf_ring_advance.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_buf_ring_advance 3 "May 18, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_buf_ring_advance - advance index of provided buffer in buffer ring -.fi +io_uring_buf_ring_advance \- advance index of provided buffer in buffer ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_buf_ring_cq_advance.3 b/man/io_uring_buf_ring_cq_advance.3 index 5b693b7..6a5aa45 100644 --- a/man/io_uring_buf_ring_cq_advance.3 +++ b/man/io_uring_buf_ring_cq_advance.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_buf_ring_cq_advance 3 "May 18, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_buf_ring_cq_advance - advance index of provided buffer and CQ ring -.fi +io_uring_buf_ring_cq_advance \- advance index of provided buffer and CQ ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 index 560a1d0..f9d8550 100644 --- a/man/io_uring_cq_advance.3 +++ b/man/io_uring_cq_advance.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_cq_advance 3 "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_cq_advance - Mark one or more io_uring completion events as consumed +io_uring_cq_advance \- mark one or more io_uring completion events as consumed .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_cq_ready.3 b/man/io_uring_cq_ready.3 index a03cda7..1458159 100644 --- a/man/io_uring_cq_ready.3 +++ b/man/io_uring_cq_ready.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_cq_ready "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_cq_ready - returns number of unconsumed ready entries in the CQ ring +io_uring_cq_ready \- returns number of unconsumed ready entries in the CQ ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index 8d26415..1e0f537 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_cqe_get_data 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_cqe_get_data - get user data for completion event +io_uring_cqe_get_data \- get user data for completion event .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3 index 3e48df1..8bc6ed4 100644 --- a/man/io_uring_cqe_seen.3 +++ b/man/io_uring_cqe_seen.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_cqe_seen 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_cqe_seen - Mark io_uring completion event as consumed +io_uring_cqe_seen \- mark io_uring completion event as consumed .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_free_probe.3 b/man/io_uring_free_probe.3 index ba98a1b..0fc41f3 100644 --- a/man/io_uring_free_probe.3 +++ b/man/io_uring_free_probe.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_free_probe "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_free_probe - free probe instance +io_uring_free_probe \- free probe instance .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_get_probe.3 b/man/io_uring_get_probe.3 index 17841bf..d8a0e6d 100644 --- a/man/io_uring_get_probe.3 +++ b/man/io_uring_get_probe.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_get_probe "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_get_probe - get probe instance +io_uring_get_probe \- get probe instance .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_get_sqe.3 b/man/io_uring_get_sqe.3 index 48ffe01..3f6c82d 100644 --- a/man/io_uring_get_sqe.3 +++ b/man/io_uring_get_sqe.3 @@ -5,7 +5,7 @@ .\" .TH io_uring_get_sqe 3 "July 10, 2020" "liburing-0.7" "liburing Manual" .SH NAME -io_uring_get_sqe - get the next available submission queue entry from the +io_uring_get_sqe \- get the next available submission queue entry from the submission queue .SH SYNOPSIS .nf diff --git a/man/io_uring_opcode_supported.3 b/man/io_uring_opcode_supported.3 index 9b3db98..9f2dbcc 100644 --- a/man/io_uring_opcode_supported.3 +++ b/man/io_uring_opcode_supported.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_opcode_supported "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_opcode_supported - is op code supported? +io_uring_opcode_supported \- is op code supported? .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3 index ae108b3..56bff06 100644 --- a/man/io_uring_peek_cqe.3 +++ b/man/io_uring_peek_cqe.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_peek_cqe 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_peek_cqe - check if an io_uring completion event is available +io_uring_peek_cqe \- check if an io_uring completion event is available .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 9fd7ea5..30d7923 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_accept 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_accept - prepare an accept request -.fi +io_uring_prep_accept \- prepare an accept request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 31bfa41..ead0960 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_cancel 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_cancel - prepare a cancelation request -.fi +io_uring_prep_cancel \- prepare a cancelation request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index d171879..5922637 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_close 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_close - prepare a file descriptor close request -.fi +io_uring_prep_close \- prepare a file descriptor close request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 index 4bcbf0f..2a59ae0 100644 --- a/man/io_uring_prep_connect.3 +++ b/man/io_uring_prep_connect.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_connect 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_connect - prepare a connect request -.fi +io_uring_prep_connect \- prepare a connect request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_fadvise.3 b/man/io_uring_prep_fadvise.3 index a8c9d1d..834d98f 100644 --- a/man/io_uring_prep_fadvise.3 +++ b/man/io_uring_prep_fadvise.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_fadvise 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_fadvise - prepare a fadvise request -.fi +io_uring_prep_fadvise \- prepare a fadvise request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_fallocate.3 b/man/io_uring_prep_fallocate.3 index 168251a..8649840 100644 --- a/man/io_uring_prep_fallocate.3 +++ b/man/io_uring_prep_fallocate.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_fallocate 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_fallocate - prepare a fallocate request -.fi +io_uring_prep_fallocate \- prepare a fallocate request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index 95c6c4f..5f3ef29 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_files_update 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_files_update - prepare a registered file update request -.fi +io_uring_prep_files_update \- prepare a registered file update request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 index 42f5742..4de3301 100644 --- a/man/io_uring_prep_fsync.3 +++ b/man/io_uring_prep_fsync.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_fsync 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_fsync - prepare an fsync request -.fi +io_uring_prep_fsync \- prepare an fsync request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index 1dae9f3..ea96684 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_linkat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_linkat - prepare a linkat request -.fi +io_uring_prep_linkat \- prepare a linkat request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 index c7aac37..32a6689 100644 --- a/man/io_uring_prep_madvise.3 +++ b/man/io_uring_prep_madvise.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_madvise 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_madvise - prepare a madvise request -.fi +io_uring_prep_madvise \- prepare a madvise request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index 3278396..87f7f96 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_mkdirat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_mkdirat - prepare an mkdirat request -.fi +io_uring_prep_mkdirat \- prepare an mkdirat request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index 3f0f97d..f5496d5 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_msg_ring 3 "March 10, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_msg_ring - send a message to another ring - +io_uring_prep_msg_ring \- send a message to another ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index 5464945..a6cb648 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_openat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_openat - prepare an openat request -.fi +io_uring_prep_openat \- prepare an openat request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 07eadbc..e75310b 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_openat2 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_openat2 - prepare an openat2 request -.fi +io_uring_prep_openat2 \- prepare an openat2 request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index 2ba8d32..5aa0053 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_poll_add 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_poll_add - prepare a poll request -.fi +io_uring_prep_poll_add \- prepare a poll request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_poll_remove.3 b/man/io_uring_prep_poll_remove.3 index a04c0c2..e6b08d7 100644 --- a/man/io_uring_prep_poll_remove.3 +++ b/man/io_uring_prep_poll_remove.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_poll_remove 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_poll_remove - prepare a poll deletion request -.fi +io_uring_prep_poll_remove \- prepare a poll deletion request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index af9d542..3e7f229 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_poll_update 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_poll_update - update an existing poll request -.fi +io_uring_prep_poll_update \- update an existing poll request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3 index d099a35..281c3eb 100644 --- a/man/io_uring_prep_provide_buffers.3 +++ b/man/io_uring_prep_provide_buffers.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_provide_buffers 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_provide_buffers - prepare a provide buffers request -.fi +io_uring_prep_provide_buffers \- prepare a provide buffers request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index 5d2c916..2430b3e 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_read 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_prep_read - prepare I/O read request - +io_uring_prep_read \- prepare I/O read request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index 2156427..54aa291 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_read 3 "February 13, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_prep_read_fixed - prepare I/O read request with registered buffer - +io_uring_prep_read_fixed \- prepare I/O read request with registered buffer .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index e758de9..4d9bfc0 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_readv 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_prep_readv - prepare vector I/O read request -.fi +io_uring_prep_readv \- prepare vector I/O read request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 0279fa3..d90a777 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -4,9 +4,7 @@ .\" .TH io_uring_prep_readv2 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -.fi -io_uring_prep_readv2 - prepare vector I/O read request with flags - +io_uring_prep_readv2 \- prepare vector I/O read request with flags .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 index 071a300..da8a011 100644 --- a/man/io_uring_prep_recv.3 +++ b/man/io_uring_prep_recv.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_recv 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_recv - prepare a recv request -.fi +io_uring_prep_recv \- prepare a recv request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index a8cf001..56e8153 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_recvmsg 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_recvmsg - prepare a recvmsg request -.fi +io_uring_prep_recvmsg \- prepare a recvmsg request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_remove_buffers.3 b/man/io_uring_prep_remove_buffers.3 index ff78d70..ac52858 100644 --- a/man/io_uring_prep_remove_buffers.3 +++ b/man/io_uring_prep_remove_buffers.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_remove_buffers 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_remove_buffers - prepare a remove buffers request -.fi +io_uring_prep_remove_buffers \- prepare a remove buffers request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index 5eefe33..cc2103e 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_renameat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_renameat - prepare a renameat request -.fi +io_uring_prep_renameat \- prepare a renameat request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 index fdd6423..d50c9df 100644 --- a/man/io_uring_prep_send.3 +++ b/man/io_uring_prep_send.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_send 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_send - prepare a send request -.fi +io_uring_prep_send \- prepare a send request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index 8986399..2cc06c4 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_sendmsg 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_sendmsg - prepare a sendmsg request -.fi +io_uring_prep_sendmsg \- prepare a sendmsg request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index 96948eb..482ed67 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_shutdown 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_shutdown - prepare a shutdown request -.fi +io_uring_prep_shutdown \- prepare a shutdown request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_socket.3 b/man/io_uring_prep_socket.3 index 41d33ec..caaa16f 100644 --- a/man/io_uring_prep_socket.3 +++ b/man/io_uring_prep_socket.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_socket 3 "May 27, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_socket - prepare a socket creation request -.fi +io_uring_prep_socket \- prepare a socket creation request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3 index eb6f1fe..2ecd1e3 100644 --- a/man/io_uring_prep_splice.3 +++ b/man/io_uring_prep_splice.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_splice 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_splice - prepare an splice request -.fi +io_uring_prep_splice \- prepare an splice request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3 index 63cf8cd..0d02379 100644 --- a/man/io_uring_prep_statx.3 +++ b/man/io_uring_prep_statx.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_statx 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_statx - prepare a statx request -.fi +io_uring_prep_statx \- prepare a statx request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index be5169a..f0bb2d9 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_symlinkat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_symlinkat - prepare a symlinkat request -.fi +io_uring_prep_symlinkat \- prepare a symlinkat request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index 0eacc7e..de0d53f 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_sync_file_range 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_sync_file_range - prepare a sync_file_range request -.fi +io_uring_prep_sync_file_range \- prepare a sync_file_range request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3 index af775be..3ecb030 100644 --- a/man/io_uring_prep_tee.3 +++ b/man/io_uring_prep_tee.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_tee 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_tee - prepare a tee request -.fi +io_uring_prep_tee \- prepare a tee request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 index 2bfbfb3..186d93b 100644 --- a/man/io_uring_prep_timeout.3 +++ b/man/io_uring_prep_timeout.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_poll_timeout 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_timeoute - prepare a timeout request -.fi +io_uring_prep_timeoute \- prepare a timeout request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 index a52ba86..0070581 100644 --- a/man/io_uring_prep_timeout_update.3 +++ b/man/io_uring_prep_timeout_update.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_poll_timeout_update 3 "March 12, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_timeoute_update - prepare a request to update an existing timeout -.fi +io_uring_prep_timeoute_update \- prepare a request to update an existing timeout .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index 5f1c3b4..275f3a3 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_unlinkat 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_prep_unlinkat - prepare an unlinkat request -.fi +io_uring_prep_unlinkat \- prepare an unlinkat request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 3b44651..8294a40 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_write 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_prep_write - prepare I/O write request - +io_uring_prep_write \- prepare I/O write request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index 91d1107..79fed99 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_write 3 "February 13, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_prep_write_fixed - prepare I/O write request with registered buffer - +io_uring_prep_write_fixed \- prepare I/O write request with registered buffer .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 4ccfadc..143fd26 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_writev 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_prep_writev - prepare vector I/O write request - +io_uring_prep_writev \- prepare vector I/O write request .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index bab62a6..8b7f26c 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_prep_writev2 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_prep_writev2 - prepare vector I/O write request with flags - +io_uring_prep_writev2 \- prepare vector I/O write request with flags .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_queue_exit.3 b/man/io_uring_queue_exit.3 index 2be51c8..1c14d64 100644 --- a/man/io_uring_queue_exit.3 +++ b/man/io_uring_queue_exit.3 @@ -5,7 +5,7 @@ .\" .TH io_uring_queue_exit 3 "July 10, 2020" "liburing-0.7" "liburing Manual" .SH NAME -io_uring_queue_exit - tear down io_uring submission and completion queues +io_uring_queue_exit \- tear down io_uring submission and completion queues .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index f34d163..9752bab 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -5,7 +5,7 @@ .\" .TH io_uring_queue_init 3 "July 10, 2020" "liburing-0.7" "liburing Manual" .SH NAME -io_uring_queue_init - setup io_uring submission and completion queues +io_uring_queue_init \- setup io_uring submission and completion queues .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3 index 9abb59b..36d22e3 100644 --- a/man/io_uring_register_buf_ring.3 +++ b/man/io_uring_register_buf_ring.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_register_buf_ring 3 "May 18, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_register_buf_ring - register buffer ring for provided buffers -.fi +io_uring_register_buf_ring \- register buffer ring for provided buffers .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index 3243776..fa9a68f 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_register_buffers 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_register_buffers - register buffers for fixed buffer operations -.fi +io_uring_register_buffers \- register buffers for fixed buffer operations .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_register_eventfd.3 b/man/io_uring_register_eventfd.3 index ec2295c..ed75e0d 100644 --- a/man/io_uring_register_eventfd.3 +++ b/man/io_uring_register_eventfd.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_register_eventfd 3 "April 16, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_register_eventfd - register an eventfd with a ring - +io_uring_register_eventfd \- register an eventfd with a ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index e342506..297198f 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_register_files 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_register_files - register file descriptors -.fi +io_uring_register_files \- register file descriptors .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_register_iowq_aff.3 b/man/io_uring_register_iowq_aff.3 index cf5cd73..c7ce6a2 100644 --- a/man/io_uring_register_iowq_aff.3 +++ b/man/io_uring_register_iowq_aff.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_register_iowq_aff 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_register_iowq_aff - register async worker CPU affinities -.fi +io_uring_register_iowq_aff \- register async worker CPU affinities .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_register_iowq_max_workers.3 b/man/io_uring_register_iowq_max_workers.3 index 10687cb..cd82bd1 100644 --- a/man/io_uring_register_iowq_max_workers.3 +++ b/man/io_uring_register_iowq_max_workers.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_register_iowq_max_workers 3 "March 13, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_register_iowq_max_workers - modify the maximum allowed async workers -.fi +io_uring_register_iowq_max_workers \- modify the maximum allowed async workers .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3 index 9d86b0d..0f69ba5 100644 --- a/man/io_uring_register_ring_fd.3 +++ b/man/io_uring_register_ring_fd.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_register_ring_fd 3 "March 11, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_register_ring_fd - register a ring file descriptor - +io_uring_register_ring_fd \- register a ring file descriptor .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_sq_ready.3 b/man/io_uring_sq_ready.3 index 53f5be5..369a7aa 100644 --- a/man/io_uring_sq_ready.3 +++ b/man/io_uring_sq_ready.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_sq_ready "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_sq_ready - number of unconsumed or unsubmitted entries in the SQ ring +io_uring_sq_ready \- number of unconsumed or unsubmitted entries in the SQ ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_sq_space_left.3 b/man/io_uring_sq_space_left.3 index e167097..8d9c019 100644 --- a/man/io_uring_sq_space_left.3 +++ b/man/io_uring_sq_space_left.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_sq_space-left "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_sq_space_left - free space in the SQ ring +io_uring_sq_space_left \- free space in the SQ ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3 index a30bbf8..de4eb40 100644 --- a/man/io_uring_sqe_set_data.3 +++ b/man/io_uring_sqe_set_data.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_sqe_set_data 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_sqe_set_data - set user data for submission queue event +io_uring_sqe_set_data \- set user data for submission queue event .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 index 76964e5..6658946 100644 --- a/man/io_uring_sqe_set_flags.3 +++ b/man/io_uring_sqe_set_flags.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_sqe_set_flags "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_sqe_set_flags - set flags for submission queue entry +io_uring_sqe_set_flags \- set flags for submission queue entry .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_sqring_wait.3 b/man/io_uring_sqring_wait.3 index 7bdff65..a70c717 100644 --- a/man/io_uring_sqring_wait.3 +++ b/man/io_uring_sqring_wait.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_sqring_wait "January 25, 2022" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_sqring_wait - wait for free space in the SQ ring +io_uring_sqring_wait \- wait for free space in the SQ ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 index c26c20d..d38683e 100644 --- a/man/io_uring_submit.3 +++ b/man/io_uring_submit.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_submit 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_submit - submit requests to the submission queue -.fi +io_uring_submit \- submit requests to the submission queue .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_submit_and_wait.3 b/man/io_uring_submit_and_wait.3 index 320df9d..f96cd84 100644 --- a/man/io_uring_submit_and_wait.3 +++ b/man/io_uring_submit_and_wait.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_submit_and_wait 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_submit_and_wait - submit requests to the submission queue and wait for completion -.fi +io_uring_submit_and_wait \- submit requests to the submission queue and wait for completion .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 index 2aba4cf..8757628 100644 --- a/man/io_uring_submit_and_wait_timeout.3 +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -4,9 +4,8 @@ .\" .TH io_uring_submit_and_wait_timeout 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_submit_and_wait_timeout - submit requests to the submission queue and +io_uring_submit_and_wait_timeout \- submit requests to the submission queue and wait for the completion with timeout -.fi .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_unregister_buf_ring.3 b/man/io_uring_unregister_buf_ring.3 index 8743328..4b5aeff 100644 --- a/man/io_uring_unregister_buf_ring.3 +++ b/man/io_uring_unregister_buf_ring.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_unregister_buf_ring 3 "May 18, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_unregister_buf_ring - unregister a previously registered buffer ring -.fi +io_uring_unregister_buf_ring \- unregister a previously registered buffer ring .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_unregister_buffers.3 b/man/io_uring_unregister_buffers.3 index 26ff806..9c12692 100644 --- a/man/io_uring_unregister_buffers.3 +++ b/man/io_uring_unregister_buffers.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_unregister_buffers 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_unregister_buffers - unregister buffers for fixed buffer operations -.fi +io_uring_unregister_buffers \- unregister buffers for fixed buffer operations .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_unregister_files.3 b/man/io_uring_unregister_files.3 index a08bbd0..12e98c8 100644 --- a/man/io_uring_unregister_files.3 +++ b/man/io_uring_unregister_files.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_unregister_files 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_unregister_files - unregister file descriptors -.fi +io_uring_unregister_files \- unregister file descriptors .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_unregister_ring_fd.3 b/man/io_uring_unregister_ring_fd.3 index c958ec1..76a5c3b 100644 --- a/man/io_uring_unregister_ring_fd.3 +++ b/man/io_uring_unregister_ring_fd.3 @@ -4,8 +4,7 @@ .\" .TH io_uring_unregister_ring_fd 3 "March 11, 2022" "liburing-2.2" "liburing Manual" .SH NAME -io_uring_unregister_ring_fd - unregister a ring file descriptor - +io_uring_unregister_ring_fd \- unregister a ring file descriptor .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3 index 3bd10f7..b081727 100644 --- a/man/io_uring_wait_cqe.3 +++ b/man/io_uring_wait_cqe.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_wait_cqe 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_wait_cqe - wait for one io_uring completion event +io_uring_wait_cqe \- wait for one io_uring completion event .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3 index e4cf259..11caeb3 100644 --- a/man/io_uring_wait_cqe_nr.3 +++ b/man/io_uring_wait_cqe_nr.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_wait_cqe_nr 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_wait_cqe_nr - wait for one or more io_uring completion events +io_uring_wait_cqe_nr \- wait for one or more io_uring completion events .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 index 07bc9b4..ef56e76 100644 --- a/man/io_uring_wait_cqe_timeout.3 +++ b/man/io_uring_wait_cqe_timeout.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_wait_cqe_timeout 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_wait_cqe_timeout - wait for one io_uring completion event with timeout +io_uring_wait_cqe_timeout \- wait for one io_uring completion event with timeout .SH SYNOPSIS .nf .BR "#include " diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3 index fc200bb..31f9467 100644 --- a/man/io_uring_wait_cqes.3 +++ b/man/io_uring_wait_cqes.3 @@ -4,7 +4,7 @@ .\" .TH io_uring_wait_cqes 3 "November 15, 2021" "liburing-2.1" "liburing Manual" .SH NAME -io_uring_wait_cqes - wait for one or more io_uring completion events +io_uring_wait_cqes \- wait for one or more io_uring completion events .SH SYNOPSIS .nf .BR "#include " -- cgit v1.2.3 From 27697b4cd16346d5bef6bfc0b1228146ff9d3708 Mon Sep 17 00:00:00 2001 From: Otto Modinos Date: Tue, 31 May 2022 19:41:31 +0300 Subject: man: use PP betwen multiple function definitions Signed-off-by: Otto Modinos --- man/io_uring_prep_accept.3 | 6 +++--- man/io_uring_prep_cancel.3 | 2 +- man/io_uring_prep_close.3 | 4 ++-- man/io_uring_prep_openat.3 | 2 +- man/io_uring_prep_openat2.3 | 2 +- man/io_uring_prep_poll_add.3 | 2 +- man/io_uring_prep_socket.3 | 2 +- man/io_uring_prep_timeout_update.3 | 2 +- man/io_uring_queue_init.3 | 2 +- man/io_uring_register_buffers.3 | 2 +- man/io_uring_register_eventfd.3 | 2 ++ man/io_uring_register_files.3 | 2 +- man/io_uring_register_iowq_aff.3 | 2 +- 13 files changed, 17 insertions(+), 15 deletions(-) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 30d7923..3baeff4 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -15,20 +15,20 @@ io_uring_prep_accept \- prepare an accept request .BI " struct sockaddr *" addr "," .BI " socklen_t " addrlen "," .BI " int " flags ");" -.BI " +.PP .BI "void io_uring_prep_accept_direct(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," .BI " struct sockaddr *" addr "," .BI " socklen_t " addrlen "," .BI " int " flags "," .BI " unsigned int " file_index ");" -.BI " +.PP .BI "void io_uring_prep_multishot_accept(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," .BI " struct sockaddr *" addr "," .BI " socklen_t " addrlen "," .BI " int " flags ");" -.BI " +.PP .BI "void io_uring_prep_multishot_accept_direct(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," .BI " struct sockaddr *" addr "," diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index ead0960..3d2df64 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -12,7 +12,7 @@ io_uring_prep_cancel \- prepare a cancelation request .BI "void io_uring_prep_cancel(struct io_uring_sqe *" sqe "," .BI " __u64 " user_data "," .BI " int " flags ");" -.BI " +.PP .BI "void io_uring_prep_cancel_fd(struct io_uring_sqe *" sqe "," .BI " int " fd "," .BI " int " flags ");" diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index 5922637..ab2dcd4 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -11,10 +11,10 @@ io_uring_prep_close \- prepare a file descriptor close request .PP .BI "void io_uring_prep_close(struct io_uring_sqe *" sqe "," .BI " int " fd ");" -.BI " +.PP .BI "void io_uring_prep_close_direct(struct io_uring_sqe *" sqe "," .BI " unsigned " file_index ");" -.BI " +.PP .BI "void io_uring_prep_close_direct_unregister(struct io_uring_sqe *" sqe "," .BI " int " fd ", .BI " unsigned " file_index ");" diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index a6cb648..093ab0c 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -17,7 +17,7 @@ io_uring_prep_openat \- prepare an openat request .BI " const char *" path "," .BI " int " flags "," .BI " mode_t " mode ");" -.BI " +.PP .BI "void io_uring_prep_openat_direct(struct io_uring_sqe *" sqe "," .BI " int " dfd "," .BI " const char *" path "," diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index e75310b..ef39cb7 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -18,7 +18,7 @@ io_uring_prep_openat2 \- prepare an openat2 request .BI " const char *" path "," .BI " int " flags "," .BI " struct open_how *" how ");" -.BI " +.PP .BI "void io_uring_prep_openat2_direct(struct io_uring_sqe *" sqe "," .BI " int " dfd "," .BI " const char *" path "," diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index 5aa0053..51089ea 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -13,7 +13,7 @@ io_uring_prep_poll_add \- prepare a poll request .BI "void io_uring_prep_poll_add(struct io_uring_sqe *" sqe "," .BI " int " fd "," .BI " unsigned " poll_mask ");" -.BI " +.PP .BI "void io_uring_prep_poll_multishot(struct io_uring_sqe *" sqe "," .BI " int " fd "," .BI " unsigned " poll_mask ");" diff --git a/man/io_uring_prep_socket.3 b/man/io_uring_prep_socket.3 index caaa16f..e434b9a 100644 --- a/man/io_uring_prep_socket.3 +++ b/man/io_uring_prep_socket.3 @@ -15,7 +15,7 @@ io_uring_prep_socket \- prepare a socket creation request .BI " int " type "," .BI " int " protocol "," .BI " unsigned int " flags ");" -.BI " +.PP .BI "void io_uring_prep_socket_direct(struct io_uring_sqe *" sqe "," .BI " int " domain "," .BI " int " type "," diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 index 0070581..fb055f3 100644 --- a/man/io_uring_prep_timeout_update.3 +++ b/man/io_uring_prep_timeout_update.3 @@ -13,7 +13,7 @@ io_uring_prep_timeoute_update \- prepare a request to update an existing timeout .BI " struct __kernel_timespec *" ts "," .BI " __u64 " user_data "," .BI " unsigned " flags ");" -.BI " +.PP .BI "void io_uring_prep_timeout_remove(struct io_uring_sqe *" sqe "," .BI " __u64 " user_data "," .BI " unsigned " flags ");" diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index 9752bab..ed4f5ff 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -13,7 +13,7 @@ io_uring_queue_init \- setup io_uring submission and completion queues .BI "int io_uring_queue_init(unsigned " entries "," .BI " struct io_uring *" ring "," .BI " unsigned " flags ");" -.BI " +.PP .BI "int io_uring_queue_init_params(unsigned " entries "," .BI " struct io_uring *" ring "," .BI " struct io_uring_params *" params ");" diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index fa9a68f..07b1bfa 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -12,7 +12,7 @@ io_uring_register_buffers \- register buffers for fixed buffer operations .BI "int io_uring_register_buffers(struct io_uring *" ring ", .BI " const struct iovec *" iovecs ", .BI " unsigned " nr_iovecs ");" -.BI " +.PP .BI "int io_uring_register_buffers_sparse(struct io_uring *" ring ", .BI " unsigned " nr_iovecs ");" .PP diff --git a/man/io_uring_register_eventfd.3 b/man/io_uring_register_eventfd.3 index ed75e0d..030ec0f 100644 --- a/man/io_uring_register_eventfd.3 +++ b/man/io_uring_register_eventfd.3 @@ -11,8 +11,10 @@ io_uring_register_eventfd \- register an eventfd with a ring .PP .BI "int io_uring_register_eventfd(struct io_uring *" ring "," .BI " int " fd ");" +.PP .BI "int io_uring_register_eventfd_async(struct io_uring *" ring "," .BI " int " fd ");" +.PP .BI "int io_uring_unregister_eventfd(struct io_uring *" ring ");" .SH DESCRIPTION diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index 297198f..d3b91d5 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -12,7 +12,7 @@ io_uring_register_files \- register file descriptors .BI "int io_uring_register_files(struct io_uring *" ring "," .BI " const int *" files "," .BI " unsigned " nr_files ");" -.BI +.PP .BI "int io_uring_register_files_sparse(struct io_uring *" ring "," .BI " unsigned " nr_files ");" .PP diff --git a/man/io_uring_register_iowq_aff.3 b/man/io_uring_register_iowq_aff.3 index c7ce6a2..9c10883 100644 --- a/man/io_uring_register_iowq_aff.3 +++ b/man/io_uring_register_iowq_aff.3 @@ -13,7 +13,7 @@ io_uring_register_iowq_aff \- register async worker CPU affinities .BI "int io_uring_register_iowq_aff(struct io_uring *" ring "," .BI " size_t " cpusz "," .BI " const cpu_set_t *" mask "); -.BI " +.PP .BI "void io_uring_unregister_iowq_aff(struct io_uring *" ring ");" .PP .SH DESCRIPTION -- cgit v1.2.3 From 4f13cff751dffb0d5badb5fa4c7652e71195cb52 Mon Sep 17 00:00:00 2001 From: Otto Modinos Date: Tue, 31 May 2022 23:06:41 +0300 Subject: man: fix bold/italic punctuation Signed-off-by: Otto Modinos --- man/io_uring_buf_ring_add.3 | 2 +- man/io_uring_buf_ring_advance.3 | 2 +- man/io_uring_buf_ring_cq_advance.3 | 2 +- man/io_uring_cqe_get_data.3 | 2 +- man/io_uring_peek_cqe.3 | 2 +- man/io_uring_prep_accept.3 | 10 +++++----- man/io_uring_prep_cancel.3 | 4 ++-- man/io_uring_prep_close.3 | 8 ++++---- man/io_uring_prep_connect.3 | 4 ++-- man/io_uring_prep_fadvise.3 | 4 ++-- man/io_uring_prep_fallocate.3 | 2 +- man/io_uring_prep_files_update.3 | 4 ++-- man/io_uring_prep_fsync.3 | 2 +- man/io_uring_prep_linkat.3 | 4 ++-- man/io_uring_prep_madvise.3 | 4 ++-- man/io_uring_prep_mkdirat.3 | 4 ++-- man/io_uring_prep_msg_ring.3 | 4 ++-- man/io_uring_prep_openat.3 | 4 ++-- man/io_uring_prep_openat2.3 | 4 ++-- man/io_uring_prep_poll_add.3 | 2 +- man/io_uring_prep_poll_update.3 | 2 +- man/io_uring_prep_provide_buffers.3 | 6 +++--- man/io_uring_prep_read.3 | 6 +++--- man/io_uring_prep_read_fixed.3 | 10 +++++----- man/io_uring_prep_readv.3 | 6 +++--- man/io_uring_prep_readv2.3 | 6 +++--- man/io_uring_prep_recv.3 | 4 ++-- man/io_uring_prep_recvmsg.3 | 2 +- man/io_uring_prep_remove_buffers.3 | 2 +- man/io_uring_prep_renameat.3 | 4 ++-- man/io_uring_prep_send.3 | 4 ++-- man/io_uring_prep_sendmsg.3 | 2 +- man/io_uring_prep_shutdown.3 | 2 +- man/io_uring_prep_socket.3 | 8 ++++---- man/io_uring_prep_splice.3 | 6 +++--- man/io_uring_prep_statx.3 | 4 ++-- man/io_uring_prep_symlinkat.3 | 4 ++-- man/io_uring_prep_sync_file_range.3 | 2 +- man/io_uring_prep_tee.3 | 2 +- man/io_uring_prep_timeout.3 | 2 +- man/io_uring_prep_timeout_update.3 | 4 ++-- man/io_uring_prep_unlinkat.3 | 4 ++-- man/io_uring_prep_write.3 | 6 +++--- man/io_uring_prep_write_fixed.3 | 9 +++++---- man/io_uring_prep_writev.3 | 6 +++--- man/io_uring_prep_writev2.3 | 6 +++--- man/io_uring_queue_init.3 | 2 +- man/io_uring_register_buf_ring.3 | 6 +++--- man/io_uring_register_buffers.3 | 6 +++--- man/io_uring_register_eventfd.3 | 2 +- man/io_uring_register_files.3 | 2 +- man/io_uring_sqe_set_data.3 | 2 +- man/io_uring_submit.3 | 4 ++-- man/io_uring_submit_and_wait_timeout.3 | 4 ++-- man/io_uring_unregister_buf_ring.3 | 4 ++-- man/io_uring_unregister_buffers.3 | 2 +- man/io_uring_unregister_files.3 | 2 +- man/io_uring_wait_cqe.3 | 2 +- man/io_uring_wait_cqe_nr.3 | 2 +- man/io_uring_wait_cqes.3 | 2 +- 60 files changed, 118 insertions(+), 117 deletions(-) diff --git a/man/io_uring_buf_ring_add.3 b/man/io_uring_buf_ring_add.3 index 0b10665..d3de98b 100644 --- a/man/io_uring_buf_ring_add.3 +++ b/man/io_uring_buf_ring_add.3 @@ -20,7 +20,7 @@ io_uring_buf_ring_add \- add buffers to a shared buffer ring The .BR io_uring_buf_ring_add (3) adds a new buffer to the shared buffer ring -.I br. +.IR br . The buffer address is indicated by .I addr and is of diff --git a/man/io_uring_buf_ring_advance.3 b/man/io_uring_buf_ring_advance.3 index 41ede49..289aee9 100644 --- a/man/io_uring_buf_ring_advance.3 +++ b/man/io_uring_buf_ring_advance.3 @@ -19,7 +19,7 @@ The commits .I count previously added buffers to the shared buffer ring -.I br, +.IR br , making them visible to the kernel and hence consumable. This passes ownership of the buffer to the ring. diff --git a/man/io_uring_buf_ring_cq_advance.3 b/man/io_uring_buf_ring_cq_advance.3 index 6a5aa45..2496c5c 100644 --- a/man/io_uring_buf_ring_cq_advance.3 +++ b/man/io_uring_buf_ring_cq_advance.3 @@ -20,7 +20,7 @@ The commits .I count previously added buffers to the shared buffer ring -.I br, +.IR br , making them visible to the kernel and hence consumable. This passes ownership of the buffer to the ring. At the same time, it advances the CQ ring of .I ring diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index 1e0f537..b0dfda0 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -17,7 +17,7 @@ io_uring_cqe_get_data \- get user data for completion event The .BR io_uring_cqe_get_data (3) function returns the user_data with the completion queue entry -.I cqe. +.IR cqe . After the caller has received a completion queue entry (CQE) with .BR io_uring_wait_cqe (3), diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3 index 56bff06..d2fd840 100644 --- a/man/io_uring_peek_cqe.3 +++ b/man/io_uring_peek_cqe.3 @@ -32,6 +32,6 @@ On success returns .B 0 and the cqe_ptr parameter is filled in. On failure it returns -.B -EAGAIN. +.BR -EAGAIN . .SH SEE ALSO .BR io_uring_submit (3), io_uring_wait_cqes (3), io_uring_wait_cqe (3) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 3baeff4..fbd3c0c 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -48,7 +48,7 @@ to start accepting a connection request described by the socket address at and of structure length .I addrlen and using modifier flags in -.I flags. +.IR flags . For a direct descriptor accept request, the offset is specified by the .I file_index @@ -87,10 +87,10 @@ return. For a direct descriptor accept request, the .I file_index argument can be set to -.B IORING_FILE_INDEX_ALLOC, +.BR IORING_FILE_INDEX_ALLOC , In this case a free entry in io_uring file table will be used automatically and the file index will be returned as CQE -.I res. +.IR res . .B -ENFILE is otherwise returned if there is no free entries in the io_uring file table. @@ -109,7 +109,7 @@ For multishot with direct descriptors, must be used as the file descriptor. This tells io_uring to allocate a free direct descriptor from our table, rather than the application passing one in. Failure to do so will result in the accept request being terminated with -.B -EINVAL. +.BR -EINVAL . The allocated descriptor will be returned in the CQE .I res field, like a non-direct accept request. @@ -136,7 +136,7 @@ non-direct accept. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 3d2df64..5539680 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -24,7 +24,7 @@ The function prepares a cancelation request. The submission queue entry .I sqe is prepared to cancel an existing request identified by -.I user_data. +.IR user_data . For the .I flags argument, see below. @@ -42,7 +42,7 @@ The function prepares a cancelation request. The submission queue entry .I sqe is prepared to cancel an existing request that used the file descriptor -.I fd. +.IR fd . For the .I flags argument, see below. diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index ab2dcd4..74e6e98 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -26,12 +26,12 @@ The function prepares a close request. The submission queue entry .I sqe is setup to close the file descriptor indicated by -.I fd. +.IR fd . For a direct descriptor close request, the offset is specified by the .I file_index argument instead of the -.I fd. +.IR fd . This is identical to unregistering the direct descriptor, and is provided as a convenience. @@ -41,7 +41,7 @@ to unregister it, function is identical to closing a file descriptor indicated by .I fd and unregistering the direct descriptor specified by the -.I file_index. +.IR file_index . This function prepares an async .BR close (2) @@ -58,7 +58,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 index 2a59ae0..b0737a3 100644 --- a/man/io_uring_prep_connect.3 +++ b/man/io_uring_prep_connect.3 @@ -27,7 +27,7 @@ is setup to use the file descriptor to start connecting to the destination described by the socket address at .I addr and of structure length -.I addrlen. +.IR addrlen . This function prepares an async .BR connect (2) @@ -44,7 +44,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_fadvise.3 b/man/io_uring_prep_fadvise.3 index 834d98f..cf7dd92 100644 --- a/man/io_uring_prep_fadvise.3 +++ b/man/io_uring_prep_fadvise.3 @@ -29,7 +29,7 @@ to start an fadvise operation at and of .I len length in bytes, giving it the advise located in -.I advice. +.IR advice . This function prepares an async .BR posix_fadvise (2) @@ -46,7 +46,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_fallocate.3 b/man/io_uring_prep_fallocate.3 index 8649840..56528a1 100644 --- a/man/io_uring_prep_fallocate.3 +++ b/man/io_uring_prep_fallocate.3 @@ -47,7 +47,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index 5f3ef29..86b76d0 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -27,7 +27,7 @@ and of .I nr_fds in length to update that amount of previously registered files starting at offset -.I offset. +.IR offset . Once a previously registered file is updated with a new one, the existing entry is updated and then removed from the table. This operation is equivalent to @@ -62,7 +62,7 @@ One of the fields set in the SQE was invalid. .TP .B -EFAULT The kernel was unable to copy in the memory pointed to by -.I fds. +.IR fds . .TP .B -EBADF On of the descriptors located in diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 index 4de3301..0c880f3 100644 --- a/man/io_uring_prep_fsync.3 +++ b/man/io_uring_prep_fsync.3 @@ -57,7 +57,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index ea96684..c42752c 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -33,7 +33,7 @@ with the new directory file descriptor pointed to by and the new path pointed to by .I newpath and using the specified flags in -.I flags. +.IR flags . This function prepares an async .BR linkat (2) @@ -50,7 +50,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 index 32a6689..52c8e4a 100644 --- a/man/io_uring_prep_madvise.3 +++ b/man/io_uring_prep_madvise.3 @@ -29,7 +29,7 @@ to start an madvise operation at the virtual address of and of .I len length in bytes, giving it the advise located in -.I advice. +.IR advice . This function prepares an async .BR posix_madvise (2) @@ -46,7 +46,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index 87f7f96..054f6be 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -27,7 +27,7 @@ is setup to use the directory file descriptor pointed to by to start an mkdirat operation on the path identified by .I path with the mode given in -.I mode. +.IR mode . This function prepares an async .BR mkdirat (2) @@ -44,7 +44,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index f5496d5..ff550a0 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -33,9 +33,9 @@ and the of .I data with the request modifier flags set by -.I flags. +.IR flags . Currently there are no valid flag modifiers, this field must contain -.B 0. +.BR 0 . The targeted ring may be any ring that the user has access to, even the ring itself. This request can be used for simple message passing to another ring, diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index 093ab0c..0e969c9 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -38,7 +38,7 @@ to start opening a file described by and using the open flags in .I flags and using the file mode bits specified in -.I mode. +.IR mode . For a direct descriptor open request, the offset is specified by the .I file_index @@ -94,7 +94,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index ef39cb7..8965c68 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -39,7 +39,7 @@ to start opening a file described by and using the open flags in .I flags and using the instructions on how to open the file given in -.I how. +.IR how . For a direct descriptor open request, the offset is specified by the .I file_index @@ -94,7 +94,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index 51089ea..790d756 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -59,7 +59,7 @@ man page for details. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index 3e7f229..2b74bad 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -23,7 +23,7 @@ The function prepares a poll update request. The submission queue entry .I sqe is setup to update a poll request identified by -.I old_user_data, +.IR old_user_data , replacing it with the .I new_user_data information. The diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3 index 281c3eb..2f9a7eb 100644 --- a/man/io_uring_prep_provide_buffers.3 +++ b/man/io_uring_prep_provide_buffers.3 @@ -30,7 +30,7 @@ number of buffers starting at and identified by the buffer group ID of .I bgid and numbered sequentially starting at -.I bid. +.IR bid . This function sets up a request to provide buffers to the io_uring context that can be used by read or receive operations. This is done by filling in @@ -64,7 +64,7 @@ and sequentially ascending from that value. If buffers are provided and start with an initial .I bid of 0, then the buffer IDs will range from -.B 0..15. +.BR 0..15 . The application must be aware of this to make sense of the buffer ID passed back in the CQE. @@ -76,7 +76,7 @@ receive request. Attempting to use with a command that doesn't support it will result in a CQE .I res error of -.B -EINVAL. +.BR -EINVAL . Buffer selection will work with operations that take a .BR struct iovec as its data destination, but only if 1 iovec is provided. diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index 2430b3e..4453ffe 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -28,10 +28,10 @@ to start reading into the buffer .I buf at the specified -.I offset. +.IR offset . On files that support seeking, if the offset is set to -.B -1, +.BR -1 , the read operation commences at the file offset, and the file offset is incremented by the number of bytes read. See .BR read (2) @@ -56,7 +56,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index 54aa291..05382cc 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -30,14 +30,14 @@ to start reading into the buffer .I buf at the specified -.I offset, +.IR offset , and with the buffer matching the registered index of -.I buf_index. +.IR buf_index . This works just like -.B io_uring_prep_read(3) +.BR io_uring_prep_read (3) except it requires the use of buffers that have been registered with -.B io_uring_register_buffers(3). +.BR io_uring_register_buffers (3). The .I buf and @@ -61,7 +61,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index 4d9bfc0..85999ed 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -29,10 +29,10 @@ to start reading into the .I iovecs array at the specified -.I offset. +.IR offset . On files that support seeking, if the offset is set to -.B -1, +.BR -1 , the read operation commences at the file offset, and the file offset is incremented by the number of bytes read. See .BR read (2) @@ -57,7 +57,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index d90a777..3b89bcf 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -31,7 +31,7 @@ to start reading into the .I iovecs array at the specified -.I offset. +.IR offset . The behavior of the function can be controlled with the .I flags parameter. @@ -59,7 +59,7 @@ per-IO O_APPEND .P On files that support seeking, if the offset is set to -.B -1, +.BR -1 , the read operation commences at the file offset, and the file offset is incremented by the number of bytes read. See .BR read (2) @@ -84,7 +84,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 index da8a011..3194ff1 100644 --- a/man/io_uring_prep_recv.3 +++ b/man/io_uring_prep_recv.3 @@ -29,7 +29,7 @@ to start receiving the data into the buffer destination of size .I size and with modifier flags -.I flags. +.IR flags . This function prepares an async .BR recv (2) @@ -71,7 +71,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index 56e8153..30c59d2 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -72,7 +72,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_remove_buffers.3 b/man/io_uring_prep_remove_buffers.3 index ac52858..4c3e3a3 100644 --- a/man/io_uring_prep_remove_buffers.3 +++ b/man/io_uring_prep_remove_buffers.3 @@ -23,7 +23,7 @@ submission queue entry is setup to remove .I nr number of buffers from the buffer group ID indicated by -.I bgid. +.IR bgid . .SH RETURN VALUE None diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index cc2103e..cf268c4 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -33,7 +33,7 @@ with the new directory file descriptor pointed to by and the new path pointed to by .I newpath and using the specified flags in -.I flags. +.IR flags . This function prepares an async .BR renameat2 (2) @@ -54,7 +54,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 index d50c9df..f60be3a 100644 --- a/man/io_uring_prep_send.3 +++ b/man/io_uring_prep_send.3 @@ -28,7 +28,7 @@ to start sending the data from of size .I size and with modifier flags -.I flags. +.IR flags . This function prepares an async .BR send (2) @@ -45,7 +45,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index 2cc06c4..a82b956 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -47,7 +47,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index 482ed67..26b886e 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -41,7 +41,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_socket.3 b/man/io_uring_prep_socket.3 index e434b9a..959547f 100644 --- a/man/io_uring_prep_socket.3 +++ b/man/io_uring_prep_socket.3 @@ -34,7 +34,7 @@ is setup to use the communication domain defined by and use the communication type defined by .I type and the protocol set by -.I protocol. +.IR protocol . The .I flags argument are currently unused. @@ -67,10 +67,10 @@ existing file with For a direct descriptor socket request, the .I file_index argument can be set to -.B IORING_FILE_INDEX_ALLOC, +.BR IORING_FILE_INDEX_ALLOC , In this case a free entry in io_uring file table will be used automatically and the file index will be returned as CQE -.I res. +.IR res . .B -ENFILE is otherwise returned if there is no free entries in the io_uring file table. @@ -85,7 +85,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3 index 2ecd1e3..5cb6747 100644 --- a/man/io_uring_prep_splice.3 +++ b/man/io_uring_prep_splice.3 @@ -27,11 +27,11 @@ function prepares a splice request. The submission queue entry is setup to use as input the file descriptor .I fd_in at offset -.I off_in, +.IR off_in , splicing data to the file descriptor at .I fd_out and at offset -.I off_out. +.IR off_out . .I nbytes bytes of data should be spliced between the two descriptors. .I splice_flags @@ -67,7 +67,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3 index 0d02379..697a571 100644 --- a/man/io_uring_prep_statx.3 +++ b/man/io_uring_prep_statx.3 @@ -35,7 +35,7 @@ and using the flags given in for the fields specified by .I mask and into the buffer located at -.I statxbuf. +.IR statxbuf . This function prepares an async .BR statx (2) @@ -52,7 +52,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index f0bb2d9..cb20d8c 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -27,7 +27,7 @@ is setup to symlink the target path pointed to by to the new destination indicated by .I newdirfd and -.I linkpath. +.IR linkpath . This function prepares an async .BR symlinkat (2) @@ -44,7 +44,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index de0d53f..f2ad129 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -47,7 +47,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3 index 3ecb030..1357e52 100644 --- a/man/io_uring_prep_tee.3 +++ b/man/io_uring_prep_tee.3 @@ -60,7 +60,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 index 186d93b..714d900 100644 --- a/man/io_uring_prep_timeout.3 +++ b/man/io_uring_prep_timeout.3 @@ -74,7 +74,7 @@ where given, or the specified timeout seconds or nanoseconds where < 0. .TP .B -EFAULT io_uring was unable to access the data specified by -.I ts. +.IR ts . .TP .B -ECANCELED The timeout was canceled by a removal request. diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 index fb055f3..517c258 100644 --- a/man/io_uring_prep_timeout_update.3 +++ b/man/io_uring_prep_timeout_update.3 @@ -26,7 +26,7 @@ queue entry is setup to arm a timeout update or removal specified by .I user_data and with modifier flags given by -.I flags. +.IR flags . Additionally, the update request includes a .I ts structure, which contains new timeout information. @@ -81,7 +81,7 @@ where given, or the specified timeout seconds or nanoseconds where < 0. .TP .B -EFAULT io_uring was unable to access the data specified by -.I ts. +.IR ts . .SH NOTES As with any request that passes in data in a struct, that data must remain valid until the request has been successfully submitted. It need not remain diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index 275f3a3..80d54b5 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -27,7 +27,7 @@ is setup to use the directory file descriptor pointed to by to start an unlinkat operation on the path identified by .I path and using the flags given in -.I flags. +.IR flags . This function prepares an async .BR unlinkat (2) @@ -44,7 +44,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 8294a40..6370939 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -28,10 +28,10 @@ to start writing from the buffer .I buf at the specified -.I offset. +.IR offset . On files that support seeking, if the offset is set to -.B -1, +.BR -1 , the write operation commences at the file offset, and the file offset is incremented by the number of bytes written. See .BR write (2) @@ -56,7 +56,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index 79fed99..1864de9 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -32,12 +32,13 @@ from the buffer at the specified .I offset and with the buffer matching the registered index of -.I buf_index. +.IR buf_index . This works just like -.B io_uring_prep_write(3) +.BR io_uring_prep_write (3) except it requires the use of buffers that have been registered with -.B io_uring_register_buffers(3). The +.BR io_uring_register_buffers (3). +The .I buf and .I nbytes @@ -60,7 +61,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 143fd26..8e551ee 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -29,10 +29,10 @@ to start writing from the .I iovecs array at the specified -.I offset. +.IR offset . On files that support seeking, if the offset is set to -.B -1, +.BR -1 , the write operation commences at the file offset, and the file offset is incremented by the number of bytes written. See .BR write (2) @@ -57,7 +57,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index 8b7f26c..a035206 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -31,7 +31,7 @@ to start writing from the .I iovecs array at the specified -.I offset. +.IR offset . The behavior of the function can be controlled with the .I flags parameter. @@ -59,7 +59,7 @@ per-IO O_APPEND .P On files that support seeking, if the offset is set to -.B -1, +.BR -1 , the write operation commences at the file offset, and the file offset is incremented by the number of bytes written. See .BR write (2) @@ -84,7 +84,7 @@ details on possible values. Note that where synchronous system calls will return on failure and set .I errno to the actual error value, io_uring never uses -.I errno. +.IR errno . Instead it returns the negated .I errno directly in the CQE diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index ed4f5ff..27c3bb2 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -50,7 +50,7 @@ in .I struct io_uring_params will tell the kernel to allocate this many entries for the CQ ring, independent of the SQ ring size in given in -.I entries. +.IR entries . If the value isn't a power of 2, it will be rounded up to the nearest power of 2. diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3 index 36d22e3..f80aaf8 100644 --- a/man/io_uring_register_buf_ring.3 +++ b/man/io_uring_register_buf_ring.3 @@ -23,7 +23,7 @@ the request types that support it, provided buffers are given to the ring and one is selected by a request if it has .B IOSQE_BUFFER_SELECT set in the SQE -.I flags, +.IR flags , when the request is ready to receive data. This allows both clear ownership of the buffer lifetime, and a way to have more read/receive type of operations in flight than buffers available. @@ -53,7 +53,7 @@ The memory must be page aligned and hence allocated appropriately using eg or similar. The size of the ring is the product of .I ring_entries and the size of -.I struct io_uring_buf. +.IR "struct io_uring_buf" . .I ring_entries is the desired size of the ring, and must be a power-of-2 in size. .I bgid @@ -129,6 +129,6 @@ Available since 5.19. On success .BR io_uring_register_buf_ring (3) returns 0. On failure it returns -.B -errno. +.BR -errno . .SH SEE ALSO .BR io_uring_buf_ring_alloc (3), io_uring_buf_ring_add (3), io_uring_buf_ring_advance (3), io_uring_buf_ring_cq_advance (3) diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index 07b1bfa..92a2ed3 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -25,14 +25,14 @@ function registers number of buffers defined by the array .I iovecs belonging to the -.I ring. +.IR ring . The .BR io_uring_register_buffers_sparse (3) function registers .I nr_iovecs empty buffers belonging to the -.I ring. +.IR ring . These buffers must be updated before use, using eg .BR io_uring_register_buffers_update_tag (3). @@ -52,6 +52,6 @@ On success and .BR io_uring_register_buffers_sparse (3) return 0. On failure they return -.B -errno. +.BR -errno . .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_unregister_buffers (3), io_uring_register_buf_ring (3), io_uring_prep_read_fixed (3), io_uring_prep_write_fixed (3) diff --git a/man/io_uring_register_eventfd.3 b/man/io_uring_register_eventfd.3 index 030ec0f..e0c835e 100644 --- a/man/io_uring_register_eventfd.3 +++ b/man/io_uring_register_eventfd.3 @@ -23,7 +23,7 @@ io_uring_register_eventfd \- register an eventfd with a ring registers the eventfd file descriptor .I fd with the ring identified by -.I ring. +.IR ring . Whenever completions are posted to the CQ ring, an eventfd notification is generated with the registered eventfd descriptor. If diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index d3b91d5..74d94ec 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -44,6 +44,6 @@ On success and .BR io_uring_register_files_sparse (3) return 0. On failure they return -.B -errno. +.BR -errno . .SH SEE ALSO .BR io_uring_get_sqe (3), io_uring_unregister_files (3) diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3 index de4eb40..3f8a56d 100644 --- a/man/io_uring_sqe_set_data.3 +++ b/man/io_uring_sqe_set_data.3 @@ -20,7 +20,7 @@ The function stores a .I user_data pointer with the submission queue entry -.I sqe. +.IR sqe . After the caller has requested an submission queue entry (SQE) with io_uring_get_sqe(), he can associate a data pointer with the SQE. Once the completion arrives, the diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 index d38683e..6920184 100644 --- a/man/io_uring_submit.3 +++ b/man/io_uring_submit.3 @@ -16,7 +16,7 @@ io_uring_submit \- submit requests to the submission queue The .BR io_uring_submit (3) function submits the next events to the submission queue belonging to the -.I ring. +.IR ring . After the caller retrieves a submission queue entry (SQE) with .BR io_uring_get_sqe (3) @@ -26,7 +26,7 @@ and prepares the SQE, it can be submitted with io_uring_submit(). On success .BR io_uring_submit (3) returns the number of submitted submission queue entries. On failure it returns -.B -errno. +.BR -errno . .SH NOTES For any request that passes in data in a struct, that data must remain valid until the request has been successfully submitted. It need not remain diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 index 8757628..59879b7 100644 --- a/man/io_uring_submit_and_wait_timeout.3 +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -27,8 +27,8 @@ and waits for completion events or until the timeout .I ts expires. The completion events are stored in the -.I cqe_ptr array. -The +.I cqe_ptr +array. The .I sigmask specifies the set of signals to block. The prevailing signal mask is restored before returning. diff --git a/man/io_uring_unregister_buf_ring.3 b/man/io_uring_unregister_buf_ring.3 index 4b5aeff..a54f45e 100644 --- a/man/io_uring_unregister_buf_ring.3 +++ b/man/io_uring_unregister_buf_ring.3 @@ -18,12 +18,12 @@ io_uring_unregister_buf_ring \- unregister a previously registered buffer ring The .BR io_uring_unregister_buf_ring (3) function unregisters a previously registered shared buffer ring indicated by -.I bgid. +.IR bgid . .SH RETURN VALUE On success .BR io_uring_unregister_buf_ring (3) returns 0. On failure it returns -.B -errno. +.BR -errno . .SH SEE ALSO .BR io_uring_register_buf_ring (3), io_uring_buf_ring_free (3) diff --git a/man/io_uring_unregister_buffers.3 b/man/io_uring_unregister_buffers.3 index 9c12692..b67dde1 100644 --- a/man/io_uring_unregister_buffers.3 +++ b/man/io_uring_unregister_buffers.3 @@ -16,7 +16,7 @@ io_uring_unregister_buffers \- unregister buffers for fixed buffer operations The .BR io_uring_unregister_buffers (3) function unregisters the fixed buffers previously registered to the -.I ring. +.IR ring . .SH RETURN VALUE On success diff --git a/man/io_uring_unregister_files.3 b/man/io_uring_unregister_files.3 index 12e98c8..aef973e 100644 --- a/man/io_uring_unregister_files.3 +++ b/man/io_uring_unregister_files.3 @@ -16,7 +16,7 @@ io_uring_unregister_files \- unregister file descriptors The .BR io_uring_unregister_files (3) function unregisters the file descriptors previously registered to the -.I ring. +.IR ring . .SH RETURN VALUE On success diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3 index b081727..6f520a7 100644 --- a/man/io_uring_wait_cqe.3 +++ b/man/io_uring_wait_cqe.3 @@ -33,7 +33,7 @@ the application can retrieve the completion with On success .BR io_uring_wait_cqe (3) returns 0 and the cqe_ptr parm is filled in. On failure it returns -.B -errno. +.BR -errno . The return value indicates the result of waiting for a CQE, and it has no relation to the CQE result itself. .SH SEE ALSO diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3 index 11caeb3..30e02c9 100644 --- a/man/io_uring_wait_cqe_nr.3 +++ b/man/io_uring_wait_cqe_nr.3 @@ -36,7 +36,7 @@ the application can retrieve the completion with On success .BR io_uring_wait_cqe_nr (3) returns 0 and the cqe_ptr parm is filled in. On failure it returns -.B -errno. +.BR -errno . The return value indicates the result of waiting for a CQE, and it has no relation to the CQE result itself. .SH SEE ALSO diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3 index 31f9467..959f214 100644 --- a/man/io_uring_wait_cqes.3 +++ b/man/io_uring_wait_cqes.3 @@ -50,6 +50,6 @@ when waiting for a request. On success .BR io_uring_wait_cqes (3) returns 0 and the cqe_ptr parm is filled in. On failure it returns -.B -errno. +.BR -errno . .SH SEE ALSO .BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). -- cgit v1.2.3 From b97e28148cef7d2afb72e9fc109edf9e25d96fd5 Mon Sep 17 00:00:00 2001 From: Otto Modinos Date: Tue, 31 May 2022 23:17:34 +0300 Subject: man: put SEE ALSO suggestions on their own .BRs When they are all on the same .BR they look bunched up together, there is no space between the comma and the next letter. This was already done in `io_uring_queue_init`/`exit` Signed-off-by: Otto Modinos --- man/io_uring_buf_ring_add.3 | 4 +++- man/io_uring_buf_ring_advance.3 | 4 +++- man/io_uring_buf_ring_cq_advance.3 | 4 +++- man/io_uring_cq_advance.3 | 7 ++++++- man/io_uring_cq_ready.3 | 3 ++- man/io_uring_cqe_get_data.3 | 4 +++- man/io_uring_cqe_seen.3 | 7 ++++++- man/io_uring_peek_cqe.3 | 4 +++- man/io_uring_prep_accept.3 | 5 ++++- man/io_uring_prep_cancel.3 | 4 +++- man/io_uring_prep_close.3 | 4 +++- man/io_uring_prep_connect.3 | 4 +++- man/io_uring_prep_fadvise.3 | 5 ++++- man/io_uring_prep_fallocate.3 | 4 +++- man/io_uring_prep_files_update.3 | 4 +++- man/io_uring_prep_fsync.3 | 5 ++++- man/io_uring_prep_linkat.3 | 4 +++- man/io_uring_prep_madvise.3 | 5 ++++- man/io_uring_prep_mkdirat.3 | 4 +++- man/io_uring_prep_openat.3 | 5 ++++- man/io_uring_prep_openat2.3 | 5 ++++- man/io_uring_prep_poll_add.3 | 5 ++++- man/io_uring_prep_poll_remove.3 | 4 +++- man/io_uring_prep_poll_update.3 | 5 ++++- man/io_uring_prep_provide_buffers.3 | 5 ++++- man/io_uring_prep_read.3 | 5 ++++- man/io_uring_prep_read_fixed.3 | 3 ++- man/io_uring_prep_readv.3 | 5 ++++- man/io_uring_prep_readv2.3 | 5 ++++- man/io_uring_prep_recv.3 | 4 +++- man/io_uring_prep_recvmsg.3 | 4 +++- man/io_uring_prep_remove_buffers.3 | 5 ++++- man/io_uring_prep_renameat.3 | 5 ++++- man/io_uring_prep_send.3 | 4 +++- man/io_uring_prep_sendmsg.3 | 4 +++- man/io_uring_prep_shutdown.3 | 4 +++- man/io_uring_prep_socket.3 | 4 +++- man/io_uring_prep_splice.3 | 5 ++++- man/io_uring_prep_statx.3 | 4 +++- man/io_uring_prep_symlinkat.3 | 4 +++- man/io_uring_prep_sync_file_range.3 | 4 +++- man/io_uring_prep_tee.3 | 6 +++++- man/io_uring_prep_timeout.3 | 5 ++++- man/io_uring_prep_timeout_update.3 | 4 +++- man/io_uring_prep_unlinkat.3 | 4 +++- man/io_uring_prep_write.3 | 3 ++- man/io_uring_prep_write_fixed.3 | 3 ++- man/io_uring_prep_writev.3 | 5 ++++- man/io_uring_prep_writev2.3 | 5 ++++- man/io_uring_register_buf_ring.3 | 5 ++++- man/io_uring_register_buffers.3 | 6 +++++- man/io_uring_register_files.3 | 3 ++- man/io_uring_register_iowq_aff.3 | 3 ++- man/io_uring_register_iowq_max_workers.3 | 3 ++- man/io_uring_register_ring_fd.3 | 3 ++- man/io_uring_sqe_set_data.3 | 3 ++- man/io_uring_sqe_set_flags.3 | 3 ++- man/io_uring_sqring_wait.3 | 4 +++- man/io_uring_submit.3 | 4 +++- man/io_uring_submit_and_wait.3 | 4 +++- man/io_uring_submit_and_wait_timeout.3 | 5 ++++- man/io_uring_unregister_buf_ring.3 | 3 ++- man/io_uring_unregister_ring_fd.3 | 3 ++- man/io_uring_wait_cqe.3 | 3 ++- man/io_uring_wait_cqe_nr.3 | 3 ++- man/io_uring_wait_cqe_timeout.3 | 4 +++- man/io_uring_wait_cqes.3 | 4 +++- 67 files changed, 217 insertions(+), 67 deletions(-) diff --git a/man/io_uring_buf_ring_add.3 b/man/io_uring_buf_ring_add.3 index d3de98b..e130bf5 100644 --- a/man/io_uring_buf_ring_add.3 +++ b/man/io_uring_buf_ring_add.3 @@ -43,4 +43,6 @@ must be incremented by one for each buffer added. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_register_buf_ring (3), io_uring_buf_ring_advance (3), io_uring_buf_ring_cq_advance (3) +.BR io_uring_register_buf_ring (3), +.BR io_uring_buf_ring_advance (3), +.BR io_uring_buf_ring_cq_advance (3) diff --git a/man/io_uring_buf_ring_advance.3 b/man/io_uring_buf_ring_advance.3 index 289aee9..398fc5b 100644 --- a/man/io_uring_buf_ring_advance.3 +++ b/man/io_uring_buf_ring_advance.3 @@ -26,4 +26,6 @@ of the buffer to the ring. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_register_buf_ring (3), io_uring_buf_ring_add (3), io_uring_buf_ring_cq_advance (3) +.BR io_uring_register_buf_ring (3), +.BR io_uring_buf_ring_add (3), +.BR io_uring_buf_ring_cq_advance (3) diff --git a/man/io_uring_buf_ring_cq_advance.3 b/man/io_uring_buf_ring_cq_advance.3 index 2496c5c..869e9bb 100644 --- a/man/io_uring_buf_ring_cq_advance.3 +++ b/man/io_uring_buf_ring_cq_advance.3 @@ -36,4 +36,6 @@ barrier, doing both at once is more efficient. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_register_buf_ring (3), io_uring_buf_ring_add (3), io_uring_buf_ring_advance (3) +.BR io_uring_register_buf_ring (3), +.BR io_uring_buf_ring_add (3), +.BR io_uring_buf_ring_advance (3) diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 index f9d8550..5e02575 100644 --- a/man/io_uring_cq_advance.3 +++ b/man/io_uring_cq_advance.3 @@ -42,4 +42,9 @@ so will result in the same completion being returned on the next invocation. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_peek_cqe (3), io_uring_wait_cqes (3), io_uring_wait_cqe_timeout (3), io_uring_cqe_seen (3) +.BR io_uring_submit (3), +.BR io_uring_wait_cqe (3), +.BR io_uring_peek_cqe (3), +.BR io_uring_wait_cqes (3), +.BR io_uring_wait_cqe_timeout (3), +.BR io_uring_cqe_seen (3) diff --git a/man/io_uring_cq_ready.3 b/man/io_uring_cq_ready.3 index 1458159..9bee3dd 100644 --- a/man/io_uring_cq_ready.3 +++ b/man/io_uring_cq_ready.3 @@ -23,4 +23,5 @@ param. .SH RETURN VALUE Returns the number of unconsumed ready entries in the CQ ring. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe (3) +.BR io_uring_submit (3), +.BR io_uring_wait_cqe (3) diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index b0dfda0..86594c6 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -36,4 +36,6 @@ If the value has been set before submitting the request, it will be returned. Otherwise the functions returns NULL. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_sqe_set_data (3), io_uring_sqe_submit(3) +.BR io_uring_get_sqe (3), +.BR io_uring_sqe_set_data (3), +.BR io_uring_sqe_submit(3) diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3 index 8bc6ed4..77607b1 100644 --- a/man/io_uring_cqe_seen.3 +++ b/man/io_uring_cqe_seen.3 @@ -35,4 +35,9 @@ Completions must be marked as completed so their slot can get reused. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_peek_cqe (3), io_uring_wait_cqes (3), io_uring_wait_cqe_timeout (3), io_uring_cqe_seen (3) +.BR io_uring_submit (3), +.BR io_uring_wait_cqe (3), +.BR io_uring_peek_cqe (3), +.BR io_uring_wait_cqes (3), +.BR io_uring_wait_cqe_timeout (3), +.BR io_uring_cqe_seen (3) diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3 index d2fd840..c5d7bf3 100644 --- a/man/io_uring_peek_cqe.3 +++ b/man/io_uring_peek_cqe.3 @@ -34,4 +34,6 @@ returns and the cqe_ptr parameter is filled in. On failure it returns .BR -EAGAIN . .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqes (3), io_uring_wait_cqe (3) +.BR io_uring_submit (3), +.BR io_uring_wait_cqes (3), +.BR io_uring_wait_cqe (3) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index fbd3c0c..28b9fd5 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -153,4 +153,7 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), accept4 (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2), +.BR accept4 (2) diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 5539680..012e8f3 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -96,4 +96,6 @@ is no longer possible. This should normally mean that it will complete shortly, either successfully, or interrupted due to the cancelation. .SH SEE ALSO -.BR io_uring_prep_poll_remove (3), io_uring_get_sqe (3), io_uring_submit (3) +.BR io_uring_prep_poll_remove (3), +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3) diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index 74e6e98..8c93b9a 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -65,4 +65,6 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), close (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR close (2) diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 index b0737a3..9a8a253 100644 --- a/man/io_uring_prep_connect.3 +++ b/man/io_uring_prep_connect.3 @@ -61,4 +61,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), connect (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR connect (2) diff --git a/man/io_uring_prep_fadvise.3 b/man/io_uring_prep_fadvise.3 index cf7dd92..547c205 100644 --- a/man/io_uring_prep_fadvise.3 +++ b/man/io_uring_prep_fadvise.3 @@ -53,4 +53,7 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), posix_fadvise (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2), +.BR posix_fadvise (2) diff --git a/man/io_uring_prep_fallocate.3 b/man/io_uring_prep_fallocate.3 index 56528a1..2159080 100644 --- a/man/io_uring_prep_fallocate.3 +++ b/man/io_uring_prep_fallocate.3 @@ -54,4 +54,6 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), fallocate (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR fallocate (2) diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index 86b76d0..cdf3498 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -87,4 +87,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2) diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 index 0c880f3..c0179e5 100644 --- a/man/io_uring_prep_fsync.3 +++ b/man/io_uring_prep_fsync.3 @@ -64,4 +64,7 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), fsync (2), fdatasync (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR fsync (2), +.BR fdatasync (2) diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index c42752c..261665b 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -67,4 +67,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), linkat (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR linkat (2) diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 index 52c8e4a..c41d1cf 100644 --- a/man/io_uring_prep_madvise.3 +++ b/man/io_uring_prep_madvise.3 @@ -53,4 +53,7 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), posix_madvise (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2), +.BR posix_madvise (2) diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index 054f6be..37fb625 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -61,4 +61,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), mkdirat (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR mkdirat (2) diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index 0e969c9..818f7a2 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -111,4 +111,7 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), openat (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2), +.BR openat (2) diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 8965c68..889d536 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -111,4 +111,7 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), openat2 (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2), +.BR openat2 (2) diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index 790d756..149f997 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -66,4 +66,7 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), poll (2), epoll_ctl (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR poll (2), +.BR epoll_ctl (3) diff --git a/man/io_uring_prep_poll_remove.3 b/man/io_uring_prep_poll_remove.3 index e6b08d7..804af94 100644 --- a/man/io_uring_prep_poll_remove.3 +++ b/man/io_uring_prep_poll_remove.3 @@ -50,4 +50,6 @@ The execution state of the request has progressed far enough that cancelation is no longer possible. This should normally mean that it will complete shortly, either successfully, or interrupted due to the cancelation. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_cancel (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_prep_cancel (3) diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index 2b74bad..720ed00 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -83,4 +83,7 @@ was set and an error occurred re-arming the poll request with the new mask. The original poll request is terminated if this happens, and that termination CQE will contain the reason for the error re-arming. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_poll_add (3), io_uring_prep_poll_multishot (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_prep_poll_add (3), +.BR io_uring_prep_poll_multishot (3) diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3 index 2f9a7eb..59df801 100644 --- a/man/io_uring_prep_provide_buffers.3 +++ b/man/io_uring_prep_provide_buffers.3 @@ -125,4 +125,7 @@ and the length of buffers overflowed. .B -EBUSY Attempt to update a slot that is already used. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), io_uring_prep_remove_buffers (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2), +.BR io_uring_prep_remove_buffers (3) diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index 4453ffe..86270a7 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -63,4 +63,7 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_prep_readv (3), io_uring_prep_readv2 (3), io_uring_submit(3) +.BR io_uring_get_sqe (3), +.BR io_uring_prep_readv (3), +.BR io_uring_prep_readv2 (3), +.BR io_uring_submit(3) diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index 05382cc..5b6b362 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -68,4 +68,5 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_prep_read (3), io_uring_register_buffers (3) +.BR io_uring_prep_read (3), +.BR io_uring_register_buffers (3) diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index 85999ed..7ddae9a 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -79,4 +79,7 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_prep_read (3), io_uring_prep_readv2 (3), io_uring_submit (3) +.BR io_uring_get_sqe (3), +.BR io_uring_prep_read (3), +.BR io_uring_prep_readv2 (3), +.BR io_uring_submit (3) diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 3b89bcf..6d4d3a7 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -106,4 +106,7 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_prep_read (3), io_uring_prep_readv (3), io_uring_submit (3) +.BR io_uring_get_sqe (3), +.BR io_uring_prep_read (3), +.BR io_uring_prep_readv (3), +.BR io_uring_submit (3) diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 index 3194ff1..44aef5b 100644 --- a/man/io_uring_prep_recv.3 +++ b/man/io_uring_prep_recv.3 @@ -78,4 +78,6 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), recv (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR recv (2) diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index 30c59d2..ef11e8c 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -89,4 +89,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), recvmsg (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR recvmsg (2) diff --git a/man/io_uring_prep_remove_buffers.3 b/man/io_uring_prep_remove_buffers.3 index 4c3e3a3..7f75f07 100644 --- a/man/io_uring_prep_remove_buffers.3 +++ b/man/io_uring_prep_remove_buffers.3 @@ -46,4 +46,7 @@ No buffers exist at the specified .I bgid buffer group ID. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), io_uring_prep_provide_buffers (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2), +.BR io_uring_prep_provide_buffers (3) diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index cf268c4..95776b2 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -71,4 +71,7 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), renameat (2), renameat2 (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR renameat (2), +.BR renameat2 (2) diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 index f60be3a..58b5442 100644 --- a/man/io_uring_prep_send.3 +++ b/man/io_uring_prep_send.3 @@ -52,4 +52,6 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), send (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR send (2) diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index a82b956..08ae357 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -64,4 +64,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), sendmsg (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR sendmsg (2) diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index 26b886e..ba78581 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -48,4 +48,6 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), shutdown (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR shutdown (2) diff --git a/man/io_uring_prep_socket.3 b/man/io_uring_prep_socket.3 index 959547f..6bb5b8a 100644 --- a/man/io_uring_prep_socket.3 +++ b/man/io_uring_prep_socket.3 @@ -92,4 +92,6 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), socket (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR socket (2) diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3 index 5cb6747..aefe814 100644 --- a/man/io_uring_prep_splice.3 +++ b/man/io_uring_prep_splice.3 @@ -74,4 +74,7 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), splice (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2), +.BR splice (2) diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3 index 697a571..6ed2fe3 100644 --- a/man/io_uring_prep_statx.3 +++ b/man/io_uring_prep_statx.3 @@ -69,4 +69,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), statx (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR statx (2) diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index cb20d8c..e06e7fa 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -61,4 +61,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), symlinkat (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR symlinkat (2) diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index f2ad129..1e936b3 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -54,4 +54,6 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), sync_file_range (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR sync_file_range (2) diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3 index 1357e52..ee39fe5 100644 --- a/man/io_uring_prep_tee.3 +++ b/man/io_uring_prep_tee.3 @@ -67,4 +67,8 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_register (2), splice (2), tee (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_register (2), +.BR splice (2), +.BR tee (2) diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 index 714d900..2de0f9d 100644 --- a/man/io_uring_prep_timeout.3 +++ b/man/io_uring_prep_timeout.3 @@ -89,4 +89,7 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_timeout_remove (3), io_uring_prep_timeout_update (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_prep_timeout_remove (3), +.BR io_uring_prep_timeout_update (3) diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 index 517c258..3487d3a 100644 --- a/man/io_uring_prep_timeout_update.3 +++ b/man/io_uring_prep_timeout_update.3 @@ -93,4 +93,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_prep_timeout (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_prep_timeout (3) diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index 80d54b5..5f7ab8b 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -61,4 +61,6 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), unlinkat (2) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR unlinkat (2) diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 6370939..3776007 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -63,4 +63,5 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3) diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index 1864de9..7af2988 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -68,4 +68,5 @@ directly in the CQE .I res field. .SH SEE ALSO -.BR io_uring_prep_write (3), io_uring_register_buffers (3) +.BR io_uring_prep_write (3), +.BR io_uring_register_buffers (3) diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 8e551ee..0c31047 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -79,4 +79,7 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev2 (3), io_uring_submit (3) +.BR io_uring_get_sqe (3), +.BR io_uring_prep_write (3), +.BR io_uring_prep_writev2 (3), +.BR io_uring_submit (3) diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index a035206..941e385 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -106,4 +106,7 @@ behavior by inspecting the flag passed back from .BR io_uring_queue_init_params (3). .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_prep_write (3), io_uring_prep_writev (3), io_uring_submit (3) +.BR io_uring_get_sqe (3), +.BR io_uring_prep_write (3), +.BR io_uring_prep_writev (3), +.BR io_uring_submit (3) diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3 index f80aaf8..16d1a90 100644 --- a/man/io_uring_register_buf_ring.3 +++ b/man/io_uring_register_buf_ring.3 @@ -131,4 +131,7 @@ On success returns 0. On failure it returns .BR -errno . .SH SEE ALSO -.BR io_uring_buf_ring_alloc (3), io_uring_buf_ring_add (3), io_uring_buf_ring_advance (3), io_uring_buf_ring_cq_advance (3) +.BR io_uring_buf_ring_alloc (3), +.BR io_uring_buf_ring_add (3), +.BR io_uring_buf_ring_advance (3), +.BR io_uring_buf_ring_cq_advance (3) diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index 92a2ed3..9cc5cc7 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -54,4 +54,8 @@ and return 0. On failure they return .BR -errno . .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_unregister_buffers (3), io_uring_register_buf_ring (3), io_uring_prep_read_fixed (3), io_uring_prep_write_fixed (3) +.BR io_uring_get_sqe (3), +.BR io_uring_unregister_buffers (3), +.BR io_uring_register_buf_ring (3), +.BR io_uring_prep_read_fixed (3), +.BR io_uring_prep_write_fixed (3) diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index 74d94ec..13e1c8e 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -46,4 +46,5 @@ and return 0. On failure they return .BR -errno . .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_unregister_files (3) +.BR io_uring_get_sqe (3), +.BR io_uring_unregister_files (3) diff --git a/man/io_uring_register_iowq_aff.3 b/man/io_uring_register_iowq_aff.3 index 9c10883..3d5aecc 100644 --- a/man/io_uring_register_iowq_aff.3 +++ b/man/io_uring_register_iowq_aff.3 @@ -57,4 +57,5 @@ or .I mask was NULL/0, or any other value specified was invalid. .SH SEE ALSO -.BR io_uring_queue_init (3), io_uring_register (2) +.BR io_uring_queue_init (3), +.BR io_uring_register (2) diff --git a/man/io_uring_register_iowq_max_workers.3 b/man/io_uring_register_iowq_max_workers.3 index cd82bd1..1eb4bce 100644 --- a/man/io_uring_register_iowq_max_workers.3 +++ b/man/io_uring_register_iowq_max_workers.3 @@ -67,4 +67,5 @@ was .B NULL or the new values exceeded the maximum allowed value. .SH SEE ALSO -.BR io_uring_queue_init (3), io_uring_register (2) +.BR io_uring_queue_init (3), +.BR io_uring_register (2) diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3 index 0f69ba5..48a4645 100644 --- a/man/io_uring_register_ring_fd.3 +++ b/man/io_uring_register_ring_fd.3 @@ -45,4 +45,5 @@ or .B -errno on error. .SH SEE ALSO -.BR io_uring_unregister_ring_fd (3), io_uring_register_files (3) +.BR io_uring_unregister_ring_fd (3), +.BR io_uring_register_files (3) diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3 index 3f8a56d..40f35a0 100644 --- a/man/io_uring_sqe_set_data.3 +++ b/man/io_uring_sqe_set_data.3 @@ -29,4 +29,5 @@ function io_uring_cqe_get_data() can be called to identify the user request. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_cqe_get_data (3) +.BR io_uring_get_sqe (3), +.BR io_uring_cqe_get_data (3) diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 index 6658946..b0378ea 100644 --- a/man/io_uring_sqe_set_flags.3 +++ b/man/io_uring_sqe_set_flags.3 @@ -59,4 +59,5 @@ one completes. .SH RETURN VALUE None .SH SEE ALSO -.BR io_uring_submit (3), io_uring_register(3) +.BR io_uring_submit (3), +.BR io_uring_register(3) diff --git a/man/io_uring_sqring_wait.3 b/man/io_uring_sqring_wait.3 index a70c717..c2fed9e 100644 --- a/man/io_uring_sqring_wait.3 +++ b/man/io_uring_sqring_wait.3 @@ -28,4 +28,6 @@ This feature can only be used when SQPOLL is enabled. On success it returns the free space. If the kernel does not support the feature, -EINVAL is returned. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe (3), io_uring_wait_cqes (3) +.BR io_uring_submit (3), +.BR io_uring_wait_cqe (3), +.BR io_uring_wait_cqes (3) diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 index 6920184..fb49516 100644 --- a/man/io_uring_submit.3 +++ b/man/io_uring_submit.3 @@ -40,4 +40,6 @@ flag passed back from In general, the man pages for the individual prep helpers will have a note mentioning this fact as well, if required for the given command. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit_and_wait (3), io_uring_submit_and_wait_timeout (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit_and_wait (3), +.BR io_uring_submit_and_wait_timeout (3) diff --git a/man/io_uring_submit_and_wait.3 b/man/io_uring_submit_and_wait.3 index f96cd84..5a15729 100644 --- a/man/io_uring_submit_and_wait.3 +++ b/man/io_uring_submit_and_wait.3 @@ -30,4 +30,6 @@ On success .BR io_uring_submit_and_wait (3) returns the number of submitted submission queue entries. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_submit_and_wait_timeout (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_submit_and_wait_timeout (3) diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 index 59879b7..6587018 100644 --- a/man/io_uring_submit_and_wait_timeout.3 +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -42,4 +42,7 @@ On success .BR io_uring_submit_and_wait_timeout (3) returns the number of submitted submission queue entries. On failure it returns -errno. .SH SEE ALSO -.BR io_uring_get_sqe (3), io_uring_submit (3), io_uring_submit_and_wait (3), io_uring_wait_cqe (3) +.BR io_uring_get_sqe (3), +.BR io_uring_submit (3), +.BR io_uring_submit_and_wait (3), +.BR io_uring_wait_cqe (3) diff --git a/man/io_uring_unregister_buf_ring.3 b/man/io_uring_unregister_buf_ring.3 index a54f45e..6de60f9 100644 --- a/man/io_uring_unregister_buf_ring.3 +++ b/man/io_uring_unregister_buf_ring.3 @@ -26,4 +26,5 @@ On success returns 0. On failure it returns .BR -errno . .SH SEE ALSO -.BR io_uring_register_buf_ring (3), io_uring_buf_ring_free (3) +.BR io_uring_register_buf_ring (3), +.BR io_uring_buf_ring_free (3) diff --git a/man/io_uring_unregister_ring_fd.3 b/man/io_uring_unregister_ring_fd.3 index 76a5c3b..ce40d8c 100644 --- a/man/io_uring_unregister_ring_fd.3 +++ b/man/io_uring_unregister_ring_fd.3 @@ -29,4 +29,5 @@ or .B -errno on error. .SH SEE ALSO -.BR io_uring_register_ring_fd (3), io_uring_register_files (3) +.BR io_uring_register_ring_fd (3), +.BR io_uring_register_files (3) diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3 index 6f520a7..7b8f340 100644 --- a/man/io_uring_wait_cqe.3 +++ b/man/io_uring_wait_cqe.3 @@ -37,4 +37,5 @@ returns 0 and the cqe_ptr parm is filled in. On failure it returns The return value indicates the result of waiting for a CQE, and it has no relation to the CQE result itself. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqes(3) +.BR io_uring_submit (3), +.BR io_uring_wait_cqes(3) diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3 index 30e02c9..16a1b67 100644 --- a/man/io_uring_wait_cqe_nr.3 +++ b/man/io_uring_wait_cqe_nr.3 @@ -40,4 +40,5 @@ returns 0 and the cqe_ptr parm is filled in. On failure it returns The return value indicates the result of waiting for a CQE, and it has no relation to the CQE result itself. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqes (3) +.BR io_uring_submit (3), +.BR io_uring_wait_cqes (3) diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 index ef56e76..c092510 100644 --- a/man/io_uring_wait_cqe_timeout.3 +++ b/man/io_uring_wait_cqe_timeout.3 @@ -47,4 +47,6 @@ returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. The return value indicates the result of waiting for a CQE, and it has no relation to the CQE result itself. .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). +.BR io_uring_submit (3), +.BR io_uring_wait_cqe_timeout (3), +.BR io_uring_wait_cqe(3) diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3 index 959f214..24224aa 100644 --- a/man/io_uring_wait_cqes.3 +++ b/man/io_uring_wait_cqes.3 @@ -52,4 +52,6 @@ On success returns 0 and the cqe_ptr parm is filled in. On failure it returns .BR -errno . .SH SEE ALSO -.BR io_uring_submit (3), io_uring_wait_cqe_timeout (3), io_uring_wait_cqe(3). +.BR io_uring_submit (3), +.BR io_uring_wait_cqe_timeout (3), +.BR io_uring_wait_cqe(3) -- cgit v1.2.3 From 3eb50637418fbcae95cbba01be6a7356c3aa4747 Mon Sep 17 00:00:00 2001 From: Otto Modinos Date: Tue, 31 May 2022 23:27:57 +0300 Subject: man: no empty paragraphs before DESCRIPTION But do put an `.fi`. At least for `groff` this is not strictly needed as it is already done by the `.SH` but everybody else seems to do it so let's follow them. Signed-off-by: Otto Modinos --- man/io_uring_buf_ring_add.3 | 2 +- man/io_uring_buf_ring_advance.3 | 2 +- man/io_uring_buf_ring_cq_advance.3 | 2 +- man/io_uring_cq_advance.3 | 1 - man/io_uring_cq_ready.3 | 1 - man/io_uring_cqe_get_data.3 | 1 - man/io_uring_cqe_seen.3 | 1 - man/io_uring_free_probe.3 | 1 - man/io_uring_get_probe.3 | 1 - man/io_uring_get_sqe.3 | 1 - man/io_uring_opcode_supported.3 | 1 - man/io_uring_peek_cqe.3 | 1 - man/io_uring_prep_accept.3 | 2 +- man/io_uring_prep_cancel.3 | 2 +- man/io_uring_prep_close.3 | 2 +- man/io_uring_prep_connect.3 | 2 +- man/io_uring_prep_fadvise.3 | 2 +- man/io_uring_prep_fallocate.3 | 2 +- man/io_uring_prep_files_update.3 | 2 +- man/io_uring_prep_fsync.3 | 2 +- man/io_uring_prep_linkat.3 | 2 +- man/io_uring_prep_madvise.3 | 2 +- man/io_uring_prep_mkdirat.3 | 2 +- man/io_uring_prep_msg_ring.3 | 2 +- man/io_uring_prep_openat.3 | 2 +- man/io_uring_prep_openat2.3 | 2 +- man/io_uring_prep_poll_add.3 | 2 +- man/io_uring_prep_poll_remove.3 | 2 +- man/io_uring_prep_poll_update.3 | 2 +- man/io_uring_prep_provide_buffers.3 | 2 +- man/io_uring_prep_read.3 | 2 +- man/io_uring_prep_read_fixed.3 | 2 +- man/io_uring_prep_readv.3 | 2 +- man/io_uring_prep_readv2.3 | 1 - man/io_uring_prep_recv.3 | 2 +- man/io_uring_prep_recvmsg.3 | 2 +- man/io_uring_prep_remove_buffers.3 | 2 +- man/io_uring_prep_renameat.3 | 2 +- man/io_uring_prep_send.3 | 2 +- man/io_uring_prep_sendmsg.3 | 2 +- man/io_uring_prep_shutdown.3 | 2 +- man/io_uring_prep_socket.3 | 2 +- man/io_uring_prep_splice.3 | 2 +- man/io_uring_prep_statx.3 | 2 +- man/io_uring_prep_symlinkat.3 | 2 +- man/io_uring_prep_sync_file_range.3 | 2 +- man/io_uring_prep_tee.3 | 2 +- man/io_uring_prep_timeout.3 | 2 +- man/io_uring_prep_timeout_update.3 | 2 +- man/io_uring_prep_unlinkat.3 | 2 +- man/io_uring_prep_write.3 | 2 +- man/io_uring_prep_write_fixed.3 | 2 +- man/io_uring_prep_writev.3 | 2 +- man/io_uring_prep_writev2.3 | 1 - man/io_uring_queue_exit.3 | 1 - man/io_uring_queue_init.3 | 1 - man/io_uring_register_buf_ring.3 | 2 +- man/io_uring_register_buffers.3 | 2 +- man/io_uring_register_eventfd.3 | 2 +- man/io_uring_register_files.3 | 2 +- man/io_uring_register_iowq_aff.3 | 2 +- man/io_uring_register_iowq_max_workers.3 | 2 +- man/io_uring_register_ring_fd.3 | 2 +- man/io_uring_sq_ready.3 | 1 - man/io_uring_sq_space_left.3 | 1 - man/io_uring_sqe_set_data.3 | 1 - man/io_uring_sqe_set_flags.3 | 1 - man/io_uring_sqring_wait.3 | 1 - man/io_uring_submit.3 | 2 +- man/io_uring_submit_and_wait.3 | 2 +- man/io_uring_submit_and_wait_timeout.3 | 2 +- man/io_uring_unregister_buf_ring.3 | 2 +- man/io_uring_unregister_buffers.3 | 2 +- man/io_uring_unregister_files.3 | 2 +- man/io_uring_unregister_ring_fd.3 | 2 +- man/io_uring_wait_cqe.3 | 1 - man/io_uring_wait_cqe_nr.3 | 1 - man/io_uring_wait_cqe_timeout.3 | 2 +- man/io_uring_wait_cqes.3 | 1 - 79 files changed, 58 insertions(+), 79 deletions(-) diff --git a/man/io_uring_buf_ring_add.3 b/man/io_uring_buf_ring_add.3 index e130bf5..8b47d73 100644 --- a/man/io_uring_buf_ring_add.3 +++ b/man/io_uring_buf_ring_add.3 @@ -14,7 +14,7 @@ io_uring_buf_ring_add \- add buffers to a shared buffer ring .BI " unsigned int " len ", .BI " unsigned short " bid ", .BI " int " buf_offset ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_buf_ring_advance.3 b/man/io_uring_buf_ring_advance.3 index 398fc5b..11776c1 100644 --- a/man/io_uring_buf_ring_advance.3 +++ b/man/io_uring_buf_ring_advance.3 @@ -11,7 +11,7 @@ io_uring_buf_ring_advance \- advance index of provided buffer in buffer ring .PP .BI "int io_uring_buf_ring_advance(struct io_uring_buf_ring *" br ", .BI " int " count ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_buf_ring_cq_advance.3 b/man/io_uring_buf_ring_cq_advance.3 index 869e9bb..9fe8c3c 100644 --- a/man/io_uring_buf_ring_cq_advance.3 +++ b/man/io_uring_buf_ring_cq_advance.3 @@ -12,7 +12,7 @@ io_uring_buf_ring_cq_advance \- advance index of provided buffer and CQ ring .BI "int io_uring_buf_ring_cq_advance(struct io_uring *" ring ", .BI " struct io_uring_buf_ring *" br ", .BI " int " count ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 index 5e02575..a4f7ce0 100644 --- a/man/io_uring_cq_advance.3 +++ b/man/io_uring_cq_advance.3 @@ -12,7 +12,6 @@ io_uring_cq_advance \- mark one or more io_uring completion events as consumed .BI "void io_uring_cq_advance(struct io_uring *" ring "," .BI " unsigned " nr ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_cq_ready.3 b/man/io_uring_cq_ready.3 index 9bee3dd..b33ff1c 100644 --- a/man/io_uring_cq_ready.3 +++ b/man/io_uring_cq_ready.3 @@ -11,7 +11,6 @@ io_uring_cq_ready \- returns number of unconsumed ready entries in the CQ ring .PP .BI "unsigned io_uring_cq_ready(const struct io_uring *" ring ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index 86594c6..9e05c0b 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -11,7 +11,6 @@ io_uring_cqe_get_data \- get user data for completion event .PP .BI "void *io_uring_cqe_get_data(struct io_uring_cqe *" cqe ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3 index 77607b1..599a927 100644 --- a/man/io_uring_cqe_seen.3 +++ b/man/io_uring_cqe_seen.3 @@ -12,7 +12,6 @@ io_uring_cqe_seen \- mark io_uring completion event as consumed .BI "void io_uring_cqe_seen(struct io_uring *" ring "," .BI " struct io_uring_cqe *" cqe ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_free_probe.3 b/man/io_uring_free_probe.3 index 0fc41f3..4eb895d 100644 --- a/man/io_uring_free_probe.3 +++ b/man/io_uring_free_probe.3 @@ -11,7 +11,6 @@ io_uring_free_probe \- free probe instance .PP .BI "void io_uring_free_probe(struct io_uring_probe *" probe ");" .fi -.PP .SH DESCRIPTION .PP The function diff --git a/man/io_uring_get_probe.3 b/man/io_uring_get_probe.3 index d8a0e6d..3d761fe 100644 --- a/man/io_uring_get_probe.3 +++ b/man/io_uring_get_probe.3 @@ -11,7 +11,6 @@ io_uring_get_probe \- get probe instance .PP .BI "io_uring_probe *io_uring_get_probe(void);" .fi -.PP .SH DESCRIPTION .PP The function diff --git a/man/io_uring_get_sqe.3 b/man/io_uring_get_sqe.3 index 3f6c82d..e220236 100644 --- a/man/io_uring_get_sqe.3 +++ b/man/io_uring_get_sqe.3 @@ -13,7 +13,6 @@ submission queue .PP .BI "struct io_uring_sqe *io_uring_get_sqe(struct io_uring *" ring ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_opcode_supported.3 b/man/io_uring_opcode_supported.3 index 9f2dbcc..7f78700 100644 --- a/man/io_uring_opcode_supported.3 +++ b/man/io_uring_opcode_supported.3 @@ -12,7 +12,6 @@ io_uring_opcode_supported \- is op code supported? .BI "int io_uring_opcode_supported(struct io_uring_probe *" probe "," .BI " int " opcode ");" .fi -.PP .SH DESCRIPTION .PP The function diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3 index c5d7bf3..468716a 100644 --- a/man/io_uring_peek_cqe.3 +++ b/man/io_uring_peek_cqe.3 @@ -12,7 +12,6 @@ io_uring_peek_cqe \- check if an io_uring completion event is available .BI "int io_uring_peek_cqe(struct io_uring *" ring "," .BI " struct io_uring_cqe **" cqe_ptr ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index 28b9fd5..a2b3dee 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -34,7 +34,7 @@ io_uring_prep_accept \- prepare an accept request .BI " struct sockaddr *" addr "," .BI " socklen_t " addrlen "," .BI " int " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 012e8f3..24a4960 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -16,7 +16,7 @@ io_uring_prep_cancel \- prepare a cancelation request .BI "void io_uring_prep_cancel_fd(struct io_uring_sqe *" sqe "," .BI " int " fd "," .BI " int " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index 8c93b9a..fdab24f 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -18,7 +18,7 @@ io_uring_prep_close \- prepare a file descriptor close request .BI "void io_uring_prep_close_direct_unregister(struct io_uring_sqe *" sqe "," .BI " int " fd ", .BI " unsigned " file_index ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 index 9a8a253..29310cd 100644 --- a/man/io_uring_prep_connect.3 +++ b/man/io_uring_prep_connect.3 @@ -15,7 +15,7 @@ io_uring_prep_connect \- prepare a connect request .BI " int " sockfd "," .BI " const struct sockaddr *" addr "," .BI " socklen_t " addrlen ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_fadvise.3 b/man/io_uring_prep_fadvise.3 index 547c205..f512d3f 100644 --- a/man/io_uring_prep_fadvise.3 +++ b/man/io_uring_prep_fadvise.3 @@ -15,7 +15,7 @@ io_uring_prep_fadvise \- prepare a fadvise request .BI " __u64 " offset "," .BI " off_t " len "," .BI " int " advice ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_fallocate.3 b/man/io_uring_prep_fallocate.3 index 2159080..35e4b4d 100644 --- a/man/io_uring_prep_fallocate.3 +++ b/man/io_uring_prep_fallocate.3 @@ -15,7 +15,7 @@ io_uring_prep_fallocate \- prepare a fallocate request .BI " int " mode "," .BI " off_t " offset "," .BI " off_t " len ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index cdf3498..27ebd9d 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -13,7 +13,7 @@ io_uring_prep_files_update \- prepare a registered file update request .BI " int *" fds "," .BI " unsigned " nr_fds "," .BI " int " offset ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 index c0179e5..db2152b 100644 --- a/man/io_uring_prep_fsync.3 +++ b/man/io_uring_prep_fsync.3 @@ -12,7 +12,7 @@ io_uring_prep_fsync \- prepare an fsync request .BI "void io_uring_prep_fsync(struct io_uring_sqe *" sqe "," .BI " int " fd "," .BI " unsigned " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index 261665b..d26b9e6 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -17,7 +17,7 @@ io_uring_prep_linkat \- prepare a linkat request .BI " int " newdirfd "," .BI " const char *" newpath "," .BI " int " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 index c41d1cf..49d0127 100644 --- a/man/io_uring_prep_madvise.3 +++ b/man/io_uring_prep_madvise.3 @@ -15,7 +15,7 @@ io_uring_prep_madvise \- prepare a madvise request .BI " void *" addr "," .BI " off_t " len "," .BI " int " advice ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index 37fb625..6f5aa25 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -15,7 +15,7 @@ io_uring_prep_mkdirat \- prepare an mkdirat request .BI " int " dirfd "," .BI " const char *" path "," .BI " mode_t " mode ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index ff550a0..1527ccf 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -14,7 +14,7 @@ io_uring_prep_msg_ring \- send a message to another ring .BI " unsigned int " len "," .BI " __u64 " data "," .BI " unsigned int " flags ");" - +.fi .SH DESCRIPTION .PP .BR io_uring_prep_msg_ring (3) diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index 818f7a2..d7fde7b 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -24,7 +24,7 @@ io_uring_prep_openat \- prepare an openat request .BI " int " flags "," .BI " mode_t " mode "," .BI " unsigned " file_index ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 889d536..357d77f 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -25,7 +25,7 @@ io_uring_prep_openat2 \- prepare an openat2 request .BI " int " flags "," .BI " struct open_how *" how "," .BI " unsigned " file_index ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index 149f997..6f0265d 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -17,7 +17,7 @@ io_uring_prep_poll_add \- prepare a poll request .BI "void io_uring_prep_poll_multishot(struct io_uring_sqe *" sqe "," .BI " int " fd "," .BI " unsigned " poll_mask ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_poll_remove.3 b/man/io_uring_prep_poll_remove.3 index 804af94..d4d15f3 100644 --- a/man/io_uring_prep_poll_remove.3 +++ b/man/io_uring_prep_poll_remove.3 @@ -12,7 +12,7 @@ io_uring_prep_poll_remove \- prepare a poll deletion request .BI "void io_uring_prep_poll_remove(struct io_uring_sqe *" sqe "," .BI " __u64 " user_data ");" .BI " -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index 720ed00..a2fca4a 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -15,7 +15,7 @@ io_uring_prep_poll_update \- update an existing poll request .BI " __u64 " new_user_data "," .BI " unsigned " poll_mask "," .BI " unsigned " flags ");" - +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3 index 59df801..d9d89ed 100644 --- a/man/io_uring_prep_provide_buffers.3 +++ b/man/io_uring_prep_provide_buffers.3 @@ -15,7 +15,7 @@ io_uring_prep_provide_buffers \- prepare a provide buffers request .BI " int " nr "," .BI " int " bgid "," .BI " int " bid ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index 86270a7..e6816b1 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -14,7 +14,7 @@ io_uring_prep_read \- prepare I/O read request .BI " void *" buf "," .BI " unsigned " nbytes "," .BI " __u64 " offset ");" - +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index 5b6b362..1397739 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -15,7 +15,7 @@ io_uring_prep_read_fixed \- prepare I/O read request with registered buffer .BI " unsigned " nbytes "," .BI " __u64 " offset "," .BI " int " buf_index ");" - +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index 7ddae9a..dce12ce 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -15,7 +15,7 @@ io_uring_prep_readv \- prepare vector I/O read request .BI " const struct iovec *" iovecs "," .BI " unsigned " nr_vecs "," .BI " __u64 " offset ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 6d4d3a7..17b5299 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -17,7 +17,6 @@ io_uring_prep_readv2 \- prepare vector I/O read request with flags .BI " __u64 " offset "," .BI " int " flags ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 index 44aef5b..db97d02 100644 --- a/man/io_uring_prep_recv.3 +++ b/man/io_uring_prep_recv.3 @@ -14,7 +14,7 @@ io_uring_prep_recv \- prepare a recv request .BI " void *" buf "," .BI " size_t " len "," .BI " int " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index ef11e8c..91a00b2 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -15,7 +15,7 @@ io_uring_prep_recvmsg \- prepare a recvmsg request .BI " int " fd "," .BI " struct msghdr *" msg "," .BI " unsigned " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_remove_buffers.3 b/man/io_uring_prep_remove_buffers.3 index 7f75f07..7581ff1 100644 --- a/man/io_uring_prep_remove_buffers.3 +++ b/man/io_uring_prep_remove_buffers.3 @@ -12,7 +12,7 @@ io_uring_prep_remove_buffers \- prepare a remove buffers request .BI "void io_uring_prep_remove_buffers(struct io_uring_sqe *" sqe "," .BI " int " nr "," .BI " int " bgid ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index 95776b2..91fbce3 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -17,7 +17,7 @@ io_uring_prep_renameat \- prepare a renameat request .BI " int " newdirfd "," .BI " const char *" newpath "," .BI " int " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 index 58b5442..fe327b1 100644 --- a/man/io_uring_prep_send.3 +++ b/man/io_uring_prep_send.3 @@ -14,7 +14,7 @@ io_uring_prep_send \- prepare a send request .BI " const void *" buf "," .BI " size_t " len "," .BI " int " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index 08ae357..069b6fc 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -15,7 +15,7 @@ io_uring_prep_sendmsg \- prepare a sendmsg request .BI " int " fd "," .BI " const struct msghdr *" msg "," .BI " unsigned " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index ba78581..9faabfd 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -13,7 +13,7 @@ io_uring_prep_shutdown \- prepare a shutdown request .BI "void io_uring_prep_shutdown(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," .BI " int " how ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_socket.3 b/man/io_uring_prep_socket.3 index 6bb5b8a..18e28f6 100644 --- a/man/io_uring_prep_socket.3 +++ b/man/io_uring_prep_socket.3 @@ -22,7 +22,7 @@ io_uring_prep_socket \- prepare a socket creation request .BI " int " protocol "," .BI " unsigned int " file_index "," .BI " unsigned int " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3 index aefe814..d57b954 100644 --- a/man/io_uring_prep_splice.3 +++ b/man/io_uring_prep_splice.3 @@ -17,7 +17,7 @@ io_uring_prep_splice \- prepare an splice request .BI " int64_t " off_out "," .BI " unsigned int " nbytes "," .BI " unsigned int " splice_flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3 index 6ed2fe3..70fcdea 100644 --- a/man/io_uring_prep_statx.3 +++ b/man/io_uring_prep_statx.3 @@ -19,7 +19,7 @@ io_uring_prep_statx \- prepare a statx request .BI " int " flags "," .BI " unsigned " mask "," .BI " struct statx *" statxbuf ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index e06e7fa..7a17738 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -15,7 +15,7 @@ io_uring_prep_symlinkat \- prepare a symlinkat request .BI " const char *" target "," .BI " int " newdirfd "," .BI " const char *" linkpath ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index 1e936b3..ebad421 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -15,7 +15,7 @@ io_uring_prep_sync_file_range \- prepare a sync_file_range request .BI " unsigned " len "," .BI " __u64 " offset "," .BI " int " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3 index ee39fe5..83d5ed3 100644 --- a/man/io_uring_prep_tee.3 +++ b/man/io_uring_prep_tee.3 @@ -15,7 +15,7 @@ io_uring_prep_tee \- prepare a tee request .BI " int " fd_out "," .BI " unsigned int " nbytes "," .BI " unsigned int " splice_flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 index 2de0f9d..5b30b80 100644 --- a/man/io_uring_prep_timeout.3 +++ b/man/io_uring_prep_timeout.3 @@ -13,7 +13,7 @@ io_uring_prep_timeoute \- prepare a timeout request .BI " struct __kernel_timespec *" ts "," .BI " unsigned " count "," .BI " unsigned " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 index 3487d3a..d91cade 100644 --- a/man/io_uring_prep_timeout_update.3 +++ b/man/io_uring_prep_timeout_update.3 @@ -17,7 +17,7 @@ io_uring_prep_timeoute_update \- prepare a request to update an existing timeout .BI "void io_uring_prep_timeout_remove(struct io_uring_sqe *" sqe "," .BI " __u64 " user_data "," .BI " unsigned " flags ");" -.PP +.fi .SH DESCRIPTION .PP These functions modify or cancel an existing timeout request. The submission diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index 5f7ab8b..f4bb465 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -15,7 +15,7 @@ io_uring_prep_unlinkat \- prepare an unlinkat request .BI " int " dirfd "," .BI " const char *" path "," .BI " int " flags ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 3776007..91f6d33 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -14,7 +14,7 @@ io_uring_prep_write \- prepare I/O write request .BI " const void *" buf "," .BI " unsigned " nbytes "," .BI " __u64 " offset ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index 7af2988..9bf143a 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -15,7 +15,7 @@ io_uring_prep_write_fixed \- prepare I/O write request with registered buffer .BI " unsigned " nbytes "," .BI " __u64 " offset "," .BI " int " buf_index ");" - +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 0c31047..7120423 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -15,7 +15,7 @@ io_uring_prep_writev \- prepare vector I/O write request .BI " const struct iovec *" iovecs "," .BI " unsigned " nr_vecs "," .BI " __u64 " offset ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index 941e385..f874b0e 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -17,7 +17,6 @@ io_uring_prep_writev2 \- prepare vector I/O write request with flags .BI " __u64 " offset "," .BI " int " flags ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_queue_exit.3 b/man/io_uring_queue_exit.3 index 1c14d64..d0bc1fa 100644 --- a/man/io_uring_queue_exit.3 +++ b/man/io_uring_queue_exit.3 @@ -12,7 +12,6 @@ io_uring_queue_exit \- tear down io_uring submission and completion queues .PP .BI "void io_uring_queue_exit(struct io_uring *" ring ");" .fi -.PP .SH DESCRIPTION .PP .BR io_uring_queue_exit (3) diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index 27c3bb2..d0cedf9 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -18,7 +18,6 @@ io_uring_queue_init \- setup io_uring submission and completion queues .BI " struct io_uring *" ring "," .BI " struct io_uring_params *" params ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3 index 16d1a90..01d7f83 100644 --- a/man/io_uring_register_buf_ring.3 +++ b/man/io_uring_register_buf_ring.3 @@ -13,7 +13,7 @@ io_uring_register_buf_ring \- register buffer ring for provided buffers .BI " struct io_uring_buf_reg *" reg ", .BI " unsigned int " flags ");" .BI " -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index 9cc5cc7..1e3b0f0 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -15,7 +15,7 @@ io_uring_register_buffers \- register buffers for fixed buffer operations .PP .BI "int io_uring_register_buffers_sparse(struct io_uring *" ring ", .BI " unsigned " nr_iovecs ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_register_eventfd.3 b/man/io_uring_register_eventfd.3 index e0c835e..42a07aa 100644 --- a/man/io_uring_register_eventfd.3 +++ b/man/io_uring_register_eventfd.3 @@ -16,7 +16,7 @@ io_uring_register_eventfd \- register an eventfd with a ring .BI " int " fd ");" .PP .BI "int io_uring_unregister_eventfd(struct io_uring *" ring ");" - +.fi .SH DESCRIPTION .PP .BR io_uring_register_eventfd (3) diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index 13e1c8e..b5eab5f 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -15,7 +15,7 @@ io_uring_register_files \- register file descriptors .PP .BI "int io_uring_register_files_sparse(struct io_uring *" ring "," .BI " unsigned " nr_files ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_register_iowq_aff.3 b/man/io_uring_register_iowq_aff.3 index 3d5aecc..19d4ad7 100644 --- a/man/io_uring_register_iowq_aff.3 +++ b/man/io_uring_register_iowq_aff.3 @@ -15,7 +15,7 @@ io_uring_register_iowq_aff \- register async worker CPU affinities .BI " const cpu_set_t *" mask "); .PP .BI "void io_uring_unregister_iowq_aff(struct io_uring *" ring ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_register_iowq_max_workers.3 b/man/io_uring_register_iowq_max_workers.3 index 1eb4bce..5d90476 100644 --- a/man/io_uring_register_iowq_max_workers.3 +++ b/man/io_uring_register_iowq_max_workers.3 @@ -11,7 +11,7 @@ io_uring_register_iowq_max_workers \- modify the maximum allowed async workers .PP .BI "int io_uring_register_iowq_max_workers(struct io_uring *" ring "," .BI " unsigned int *" values ");" -.PP +.fi .SH DESCRIPTION .PP io_uring async workers are split into two types: diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3 index 48a4645..a2d4585 100644 --- a/man/io_uring_register_ring_fd.3 +++ b/man/io_uring_register_ring_fd.3 @@ -10,7 +10,7 @@ io_uring_register_ring_fd \- register a ring file descriptor .BR "#include " .PP .BI "int io_uring_register_ring_fd(struct io_uring *" ring ");" - +.fi .SH DESCRIPTION .PP .BR io_uring_register_ring_fd (3) diff --git a/man/io_uring_sq_ready.3 b/man/io_uring_sq_ready.3 index 369a7aa..d189340 100644 --- a/man/io_uring_sq_ready.3 +++ b/man/io_uring_sq_ready.3 @@ -11,7 +11,6 @@ io_uring_sq_ready \- number of unconsumed or unsubmitted entries in the SQ ring .PP .BI "unsigned io_uring_sq_ready(const struct io_uring *" ring ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_sq_space_left.3 b/man/io_uring_sq_space_left.3 index 8d9c019..14ca99e 100644 --- a/man/io_uring_sq_space_left.3 +++ b/man/io_uring_sq_space_left.3 @@ -11,7 +11,6 @@ io_uring_sq_space_left \- free space in the SQ ring .PP .BI "unsigned io_uring_sq_space_left(const struct io_uring *" ring ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3 index 40f35a0..04f629f 100644 --- a/man/io_uring_sqe_set_data.3 +++ b/man/io_uring_sqe_set_data.3 @@ -12,7 +12,6 @@ io_uring_sqe_set_data \- set user data for submission queue event .BI "void io_uring_sqe_set_data(struct io_uring_sqe *" sqe "," .BI " void *" user_data ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 index b0378ea..c8b0e37 100644 --- a/man/io_uring_sqe_set_flags.3 +++ b/man/io_uring_sqe_set_flags.3 @@ -12,7 +12,6 @@ io_uring_sqe_set_flags \- set flags for submission queue entry .BI "void io_uring_sqe_set_flags(struct io_uring_sqe *" sqe "," .BI " unsigned " flags ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_sqring_wait.3 b/man/io_uring_sqring_wait.3 index c2fed9e..dfec524 100644 --- a/man/io_uring_sqring_wait.3 +++ b/man/io_uring_sqring_wait.3 @@ -11,7 +11,6 @@ io_uring_sqring_wait \- wait for free space in the SQ ring .PP .BI "int io_uring_sqring_wait(struct io_uring *" ring ");" .fi -.PP .SH DESCRIPTION .PP The function diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 index fb49516..b077599 100644 --- a/man/io_uring_submit.3 +++ b/man/io_uring_submit.3 @@ -10,7 +10,7 @@ io_uring_submit \- submit requests to the submission queue .BR "#include " .PP .BI "int io_uring_submit(struct io_uring *" ring ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_submit_and_wait.3 b/man/io_uring_submit_and_wait.3 index 5a15729..730e271 100644 --- a/man/io_uring_submit_and_wait.3 +++ b/man/io_uring_submit_and_wait.3 @@ -11,7 +11,7 @@ io_uring_submit_and_wait \- submit requests to the submission queue and wait for .PP .BI "int io_uring_submit_and_wait(struct io_uring *" ring "," .BI " unsigned " wait_nr ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 index 6587018..bed242c 100644 --- a/man/io_uring_submit_and_wait_timeout.3 +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -15,7 +15,7 @@ wait for the completion with timeout .BI " unsigned " wait_nr "," .BI " struct __kernel_timespec *" ts "," .BI " sigset_t *" sigmask ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_unregister_buf_ring.3 b/man/io_uring_unregister_buf_ring.3 index 6de60f9..5daf133 100644 --- a/man/io_uring_unregister_buf_ring.3 +++ b/man/io_uring_unregister_buf_ring.3 @@ -12,7 +12,7 @@ io_uring_unregister_buf_ring \- unregister a previously registered buffer ring .BI "int io_uring_unregister_buf_ring(struct io_uring *" ring ", .BI " int " bgid ");" .BI " -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_unregister_buffers.3 b/man/io_uring_unregister_buffers.3 index b67dde1..01db86e 100644 --- a/man/io_uring_unregister_buffers.3 +++ b/man/io_uring_unregister_buffers.3 @@ -10,7 +10,7 @@ io_uring_unregister_buffers \- unregister buffers for fixed buffer operations .BR "#include " .PP .BI "int io_uring_unregister_buffers(struct io_uring *" ring ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_unregister_files.3 b/man/io_uring_unregister_files.3 index aef973e..f48e5f7 100644 --- a/man/io_uring_unregister_files.3 +++ b/man/io_uring_unregister_files.3 @@ -10,7 +10,7 @@ io_uring_unregister_files \- unregister file descriptors .BR "#include " .PP .BI "int io_uring_unregister_files(struct io_uring *" ring ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_unregister_ring_fd.3 b/man/io_uring_unregister_ring_fd.3 index ce40d8c..851a9db 100644 --- a/man/io_uring_unregister_ring_fd.3 +++ b/man/io_uring_unregister_ring_fd.3 @@ -10,7 +10,7 @@ io_uring_unregister_ring_fd \- unregister a ring file descriptor .BR "#include " .PP .BI "int io_uring_unregister_ring_fd(struct io_uring *" ring ");" - +.fi .SH DESCRIPTION .PP .BR io_uring_unregister_ring_fd (3) diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3 index 7b8f340..1bf77a6 100644 --- a/man/io_uring_wait_cqe.3 +++ b/man/io_uring_wait_cqe.3 @@ -12,7 +12,6 @@ io_uring_wait_cqe \- wait for one io_uring completion event .BI "int io_uring_wait_cqe(struct io_uring *" ring "," .BI " struct io_uring_cqe **" cqe_ptr ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3 index 16a1b67..e00771d 100644 --- a/man/io_uring_wait_cqe_nr.3 +++ b/man/io_uring_wait_cqe_nr.3 @@ -13,7 +13,6 @@ io_uring_wait_cqe_nr \- wait for one or more io_uring completion events .BI " struct io_uring_cqe **" cqe_ptr "," .BI " unsigned " wait_nr ");" .fi -.PP .SH DESCRIPTION .PP The diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 index c092510..9571397 100644 --- a/man/io_uring_wait_cqe_timeout.3 +++ b/man/io_uring_wait_cqe_timeout.3 @@ -12,7 +12,7 @@ io_uring_wait_cqe_timeout \- wait for one io_uring completion event with timeout .BI "int io_uring_wait_cqe_timeout(struct io_uring *" ring "," .BI " struct io_uring_cqe **" cqe_ptr "," .BI " struct __kernel_timespec *" ts ");" -.PP +.fi .SH DESCRIPTION .PP The diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3 index 24224aa..37baf1f 100644 --- a/man/io_uring_wait_cqes.3 +++ b/man/io_uring_wait_cqes.3 @@ -15,7 +15,6 @@ io_uring_wait_cqes \- wait for one or more io_uring completion events .BI " struct __kernel_timespec *" ts "," .BI " sigset_t *" sigmask "); .fi -.PP .SH DESCRIPTION .PP The -- cgit v1.2.3 From d6617d37bd8dda5c0603ff3918cf782dce7bb760 Mon Sep 17 00:00:00 2001 From: Otto Modinos Date: Wed, 1 Jun 2022 00:03:55 +0300 Subject: man: fix and simplify bold usage No need to use .BR with a single argument, that's what .B is for Signed-off-by: Otto Modinos --- man/io_uring_buf_ring_add.3 | 2 +- man/io_uring_buf_ring_advance.3 | 2 +- man/io_uring_buf_ring_cq_advance.3 | 2 +- man/io_uring_cq_advance.3 | 2 +- man/io_uring_cq_ready.3 | 2 +- man/io_uring_cqe_get_data.3 | 4 ++-- man/io_uring_cqe_seen.3 | 2 +- man/io_uring_free_probe.3 | 2 +- man/io_uring_get_probe.3 | 2 +- man/io_uring_get_sqe.3 | 7 ++++--- man/io_uring_opcode_supported.3 | 2 +- man/io_uring_peek_cqe.3 | 2 +- man/io_uring_prep_accept.3 | 4 ++-- man/io_uring_prep_cancel.3 | 4 ++-- man/io_uring_prep_close.3 | 2 +- man/io_uring_prep_connect.3 | 6 +++--- man/io_uring_prep_fadvise.3 | 4 ++-- man/io_uring_prep_fallocate.3 | 4 ++-- man/io_uring_prep_files_update.3 | 2 +- man/io_uring_prep_fsync.3 | 2 +- man/io_uring_prep_linkat.3 | 6 +++--- man/io_uring_prep_madvise.3 | 4 ++-- man/io_uring_prep_mkdirat.3 | 6 +++--- man/io_uring_prep_msg_ring.3 | 12 ++++++------ man/io_uring_prep_openat.3 | 8 ++++---- man/io_uring_prep_openat2.3 | 10 +++++----- man/io_uring_prep_poll_add.3 | 4 ++-- man/io_uring_prep_poll_remove.3 | 2 +- man/io_uring_prep_poll_update.3 | 4 ++-- man/io_uring_prep_provide_buffers.3 | 4 ++-- man/io_uring_prep_read.3 | 4 ++-- man/io_uring_prep_read_fixed.3 | 2 +- man/io_uring_prep_readv.3 | 4 ++-- man/io_uring_prep_readv2.3 | 4 ++-- man/io_uring_prep_recv.3 | 2 +- man/io_uring_prep_recvmsg.3 | 6 +++--- man/io_uring_prep_remove_buffers.3 | 2 +- man/io_uring_prep_renameat.3 | 6 +++--- man/io_uring_prep_send.3 | 2 +- man/io_uring_prep_sendmsg.3 | 6 +++--- man/io_uring_prep_shutdown.3 | 4 ++-- man/io_uring_prep_socket.3 | 4 ++-- man/io_uring_prep_splice.3 | 4 ++-- man/io_uring_prep_statx.3 | 10 +++++----- man/io_uring_prep_symlinkat.3 | 6 +++--- man/io_uring_prep_sync_file_range.3 | 4 ++-- man/io_uring_prep_tee.3 | 4 ++-- man/io_uring_prep_timeout.3 | 2 +- man/io_uring_prep_timeout_update.3 | 2 +- man/io_uring_prep_unlinkat.3 | 6 +++--- man/io_uring_prep_write.3 | 2 +- man/io_uring_prep_write_fixed.3 | 2 +- man/io_uring_prep_writev.3 | 4 ++-- man/io_uring_prep_writev2.3 | 4 ++-- man/io_uring_queue_exit.3 | 2 +- man/io_uring_queue_init.3 | 4 ++-- man/io_uring_register_buf_ring.3 | 2 +- man/io_uring_register_buffers.3 | 2 +- man/io_uring_register_eventfd.3 | 2 +- man/io_uring_register_files.3 | 4 ++-- man/io_uring_register_iowq_aff.3 | 6 +++--- man/io_uring_register_iowq_max_workers.3 | 4 ++-- man/io_uring_register_ring_fd.3 | 2 +- man/io_uring_sq_ready.3 | 2 +- man/io_uring_sq_space_left.3 | 2 +- man/io_uring_sqe_set_data.3 | 2 +- man/io_uring_sqe_set_flags.3 | 4 ++-- man/io_uring_sqring_wait.3 | 2 +- man/io_uring_submit.3 | 2 +- man/io_uring_submit_and_wait.3 | 2 +- man/io_uring_submit_and_wait_timeout.3 | 2 +- man/io_uring_unregister_buf_ring.3 | 2 +- man/io_uring_unregister_buffers.3 | 2 +- man/io_uring_unregister_files.3 | 2 +- man/io_uring_unregister_ring_fd.3 | 5 ++--- man/io_uring_wait_cqe.3 | 4 ++-- man/io_uring_wait_cqe_nr.3 | 2 +- man/io_uring_wait_cqe_timeout.3 | 4 ++-- man/io_uring_wait_cqes.3 | 4 ++-- 79 files changed, 143 insertions(+), 143 deletions(-) diff --git a/man/io_uring_buf_ring_add.3 b/man/io_uring_buf_ring_add.3 index 8b47d73..741cba6 100644 --- a/man/io_uring_buf_ring_add.3 +++ b/man/io_uring_buf_ring_add.3 @@ -7,7 +7,7 @@ io_uring_buf_ring_add \- add buffers to a shared buffer ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_buf_ring_add(struct io_uring_buf_ring *" br ", .BI " void *" addr ", diff --git a/man/io_uring_buf_ring_advance.3 b/man/io_uring_buf_ring_advance.3 index 11776c1..29a3578 100644 --- a/man/io_uring_buf_ring_advance.3 +++ b/man/io_uring_buf_ring_advance.3 @@ -7,7 +7,7 @@ io_uring_buf_ring_advance \- advance index of provided buffer in buffer ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_buf_ring_advance(struct io_uring_buf_ring *" br ", .BI " int " count ");" diff --git a/man/io_uring_buf_ring_cq_advance.3 b/man/io_uring_buf_ring_cq_advance.3 index 9fe8c3c..caf882f 100644 --- a/man/io_uring_buf_ring_cq_advance.3 +++ b/man/io_uring_buf_ring_cq_advance.3 @@ -7,7 +7,7 @@ io_uring_buf_ring_cq_advance \- advance index of provided buffer and CQ ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_buf_ring_cq_advance(struct io_uring *" ring ", .BI " struct io_uring_buf_ring *" br ", diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3 index a4f7ce0..fae2572 100644 --- a/man/io_uring_cq_advance.3 +++ b/man/io_uring_cq_advance.3 @@ -7,7 +7,7 @@ io_uring_cq_advance \- mark one or more io_uring completion events as consumed .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_cq_advance(struct io_uring *" ring "," .BI " unsigned " nr ");" diff --git a/man/io_uring_cq_ready.3 b/man/io_uring_cq_ready.3 index b33ff1c..e411a64 100644 --- a/man/io_uring_cq_ready.3 +++ b/man/io_uring_cq_ready.3 @@ -7,7 +7,7 @@ io_uring_cq_ready \- returns number of unconsumed ready entries in the CQ ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "unsigned io_uring_cq_ready(const struct io_uring *" ring ");" .fi diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index 9e05c0b..9112ee3 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -7,7 +7,7 @@ io_uring_cqe_get_data \- get user data for completion event .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void *io_uring_cqe_get_data(struct io_uring_cqe *" cqe ");" .fi @@ -37,4 +37,4 @@ the functions returns NULL. .SH SEE ALSO .BR io_uring_get_sqe (3), .BR io_uring_sqe_set_data (3), -.BR io_uring_sqe_submit(3) +.BR io_uring_sqe_submit (3) diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3 index 599a927..d2f2984 100644 --- a/man/io_uring_cqe_seen.3 +++ b/man/io_uring_cqe_seen.3 @@ -7,7 +7,7 @@ io_uring_cqe_seen \- mark io_uring completion event as consumed .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_cqe_seen(struct io_uring *" ring "," .BI " struct io_uring_cqe *" cqe ");" diff --git a/man/io_uring_free_probe.3 b/man/io_uring_free_probe.3 index 4eb895d..d2308fa 100644 --- a/man/io_uring_free_probe.3 +++ b/man/io_uring_free_probe.3 @@ -7,7 +7,7 @@ io_uring_free_probe \- free probe instance .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_free_probe(struct io_uring_probe *" probe ");" .fi diff --git a/man/io_uring_get_probe.3 b/man/io_uring_get_probe.3 index 3d761fe..94c1b21 100644 --- a/man/io_uring_get_probe.3 +++ b/man/io_uring_get_probe.3 @@ -7,7 +7,7 @@ io_uring_get_probe \- get probe instance .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "io_uring_probe *io_uring_get_probe(void);" .fi diff --git a/man/io_uring_get_sqe.3 b/man/io_uring_get_sqe.3 index e220236..58c8b96 100644 --- a/man/io_uring_get_sqe.3 +++ b/man/io_uring_get_sqe.3 @@ -9,7 +9,7 @@ io_uring_get_sqe \- get the next available submission queue entry from the submission queue .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "struct io_uring_sqe *io_uring_get_sqe(struct io_uring *" ring ");" .fi @@ -22,8 +22,9 @@ queue belonging to the .I ring param. -On success io_uring_get_sqe() returns a pointer to the submission queue entry. -On failure NULL is returned. +On success +.BR io_uring_get_sqe (3) +returns a pointer to the submission queue entry. On failure NULL is returned. If a submission queue entry is returned, it should be filled out via one of the prep functions such as diff --git a/man/io_uring_opcode_supported.3 b/man/io_uring_opcode_supported.3 index 7f78700..b20b504 100644 --- a/man/io_uring_opcode_supported.3 +++ b/man/io_uring_opcode_supported.3 @@ -7,7 +7,7 @@ io_uring_opcode_supported \- is op code supported? .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_opcode_supported(struct io_uring_probe *" probe "," .BI " int " opcode ");" diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3 index 468716a..a4ac2da 100644 --- a/man/io_uring_peek_cqe.3 +++ b/man/io_uring_peek_cqe.3 @@ -7,7 +7,7 @@ io_uring_peek_cqe \- check if an io_uring completion event is available .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_peek_cqe(struct io_uring *" ring "," .BI " struct io_uring_cqe **" cqe_ptr ");" diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index a2b3dee..c6b9609 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -7,8 +7,8 @@ io_uring_prep_accept \- prepare an accept request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_accept(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 24a4960..25a500a 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -7,7 +7,7 @@ io_uring_prep_cancel \- prepare a cancelation request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_cancel(struct io_uring_sqe *" sqe "," .BI " __u64 " user_data "," @@ -38,7 +38,7 @@ their field in the SQE. The -.BR io_uring_prep_cancel_fd() +.BR io_uring_prep_cancel_fd (3) function prepares a cancelation request. The submission queue entry .I sqe is prepared to cancel an existing request that used the file descriptor diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index fdab24f..832b3b1 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -7,7 +7,7 @@ io_uring_prep_close \- prepare a file descriptor close request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_close(struct io_uring_sqe *" sqe "," .BI " int " fd ");" diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3 index 29310cd..6a7c64a 100644 --- a/man/io_uring_prep_connect.3 +++ b/man/io_uring_prep_connect.3 @@ -7,9 +7,9 @@ io_uring_prep_connect \- prepare a connect request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_connect(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," diff --git a/man/io_uring_prep_fadvise.3 b/man/io_uring_prep_fadvise.3 index f512d3f..a53ab25 100644 --- a/man/io_uring_prep_fadvise.3 +++ b/man/io_uring_prep_fadvise.3 @@ -7,8 +7,8 @@ io_uring_prep_fadvise \- prepare a fadvise request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_fadvise(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_fallocate.3 b/man/io_uring_prep_fallocate.3 index 35e4b4d..86e1d39 100644 --- a/man/io_uring_prep_fallocate.3 +++ b/man/io_uring_prep_fallocate.3 @@ -7,8 +7,8 @@ io_uring_prep_fallocate \- prepare a fallocate request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_fallocate(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3 index 27ebd9d..bedb85e 100644 --- a/man/io_uring_prep_files_update.3 +++ b/man/io_uring_prep_files_update.3 @@ -7,7 +7,7 @@ io_uring_prep_files_update \- prepare a registered file update request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_files_update(struct io_uring_sqe *" sqe "," .BI " int *" fds "," diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3 index db2152b..a3259a0 100644 --- a/man/io_uring_prep_fsync.3 +++ b/man/io_uring_prep_fsync.3 @@ -7,7 +7,7 @@ io_uring_prep_fsync \- prepare an fsync request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_fsync(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index d26b9e6..04c3d78 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -7,9 +7,9 @@ io_uring_prep_linkat \- prepare a linkat request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_linkat(struct io_uring_sqe *" sqe "," .BI " int " olddirfd "," diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 index 49d0127..b261fa7 100644 --- a/man/io_uring_prep_madvise.3 +++ b/man/io_uring_prep_madvise.3 @@ -7,8 +7,8 @@ io_uring_prep_madvise \- prepare a madvise request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_madvise(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index 6f5aa25..6afda65 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -7,9 +7,9 @@ io_uring_prep_mkdirat \- prepare an mkdirat request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_mkdirat(struct io_uring_sqe *" sqe "," .BI " int " dirfd "," diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3 index 1527ccf..9cf3444 100644 --- a/man/io_uring_prep_msg_ring.3 +++ b/man/io_uring_prep_msg_ring.3 @@ -7,7 +7,7 @@ io_uring_prep_msg_ring \- send a message to another ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_msg_ring(struct io_uring_sqe *" sqe "," .BI " int " fd "," @@ -22,14 +22,14 @@ prepares a to send a CQE to an io_uring file descriptor. The submission queue entry .I sqe is setup to use the file descriptor -.I fd -, which must identify a io_uring context, to post a CQE on that ring where -the target CQE -.BR res +.IR fd , +which must identify a io_uring context, to post a CQE on that ring where the +target CQE +.B res field will contain the content of .I len and the -.BR user_data +.B user_data of .I data with the request modifier flags set by diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index d7fde7b..d8b19a4 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -7,10 +7,10 @@ io_uring_prep_openat \- prepare an openat request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_openat(struct io_uring_sqe *" sqe "," .BI " int " dfd "," diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 357d77f..5d3f445 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -7,11 +7,11 @@ io_uring_prep_openat2 \- prepare an openat2 request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_openat2(struct io_uring_sqe *" sqe "," .BI " int " dfd "," diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3 index 6f0265d..cb60878 100644 --- a/man/io_uring_prep_poll_add.3 +++ b/man/io_uring_prep_poll_add.3 @@ -7,8 +7,8 @@ io_uring_prep_poll_add \- prepare a poll request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_poll_add(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_poll_remove.3 b/man/io_uring_prep_poll_remove.3 index d4d15f3..b6f4b26 100644 --- a/man/io_uring_prep_poll_remove.3 +++ b/man/io_uring_prep_poll_remove.3 @@ -7,7 +7,7 @@ io_uring_prep_poll_remove \- prepare a poll deletion request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_poll_remove(struct io_uring_sqe *" sqe "," .BI " __u64 " user_data ");" diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3 index a2fca4a..11f6346 100644 --- a/man/io_uring_prep_poll_update.3 +++ b/man/io_uring_prep_poll_update.3 @@ -7,8 +7,8 @@ io_uring_prep_poll_update \- update an existing poll request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_poll_update(struct io_uring_sqe *" sqe "," .BI " __u64 " old_user_data "," diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3 index d9d89ed..f3dded9 100644 --- a/man/io_uring_prep_provide_buffers.3 +++ b/man/io_uring_prep_provide_buffers.3 @@ -7,7 +7,7 @@ io_uring_prep_provide_buffers \- prepare a provide buffers request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_provide_buffers(struct io_uring_sqe *" sqe "," .BI " void *" addr "," @@ -78,7 +78,7 @@ with a command that doesn't support it will result in a CQE error of .BR -EINVAL . Buffer selection will work with operations that take a -.BR struct iovec +.B struct iovec as its data destination, but only if 1 iovec is provided. . .SH RETURN VALUE diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3 index e6816b1..faec35f 100644 --- a/man/io_uring_prep_read.3 +++ b/man/io_uring_prep_read.3 @@ -7,7 +7,7 @@ io_uring_prep_read \- prepare I/O read request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_read(struct io_uring_sqe *" sqe "," .BI " int " fd "," @@ -66,4 +66,4 @@ field. .BR io_uring_get_sqe (3), .BR io_uring_prep_readv (3), .BR io_uring_prep_readv2 (3), -.BR io_uring_submit(3) +.BR io_uring_submit (3) diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3 index 1397739..d3726f2 100644 --- a/man/io_uring_prep_read_fixed.3 +++ b/man/io_uring_prep_read_fixed.3 @@ -7,7 +7,7 @@ io_uring_prep_read_fixed \- prepare I/O read request with registered buffer .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_read_fixed(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3 index dce12ce..ea7afd5 100644 --- a/man/io_uring_prep_readv.3 +++ b/man/io_uring_prep_readv.3 @@ -7,8 +7,8 @@ io_uring_prep_readv \- prepare vector I/O read request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_readv(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3 index 17b5299..171a699 100644 --- a/man/io_uring_prep_readv2.3 +++ b/man/io_uring_prep_readv2.3 @@ -7,8 +7,8 @@ io_uring_prep_readv2 \- prepare vector I/O read request with flags .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_readv2(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3 index db97d02..993e331 100644 --- a/man/io_uring_prep_recv.3 +++ b/man/io_uring_prep_recv.3 @@ -7,7 +7,7 @@ io_uring_prep_recv \- prepare a recv request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_recv(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3 index 91a00b2..8c49411 100644 --- a/man/io_uring_prep_recvmsg.3 +++ b/man/io_uring_prep_recvmsg.3 @@ -7,9 +7,9 @@ io_uring_prep_recvmsg \- prepare a recvmsg request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_recvmsg(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_remove_buffers.3 b/man/io_uring_prep_remove_buffers.3 index 7581ff1..cf4f226 100644 --- a/man/io_uring_prep_remove_buffers.3 +++ b/man/io_uring_prep_remove_buffers.3 @@ -7,7 +7,7 @@ io_uring_prep_remove_buffers \- prepare a remove buffers request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_remove_buffers(struct io_uring_sqe *" sqe "," .BI " int " nr "," diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index 91fbce3..96bbf88 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -7,9 +7,9 @@ io_uring_prep_renameat \- prepare a renameat request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_renameat(struct io_uring_sqe *" sqe "," .BI " int " olddirfd "," diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3 index fe327b1..10c86ba 100644 --- a/man/io_uring_prep_send.3 +++ b/man/io_uring_prep_send.3 @@ -7,7 +7,7 @@ io_uring_prep_send \- prepare a send request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_send(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3 index 069b6fc..bc81d91 100644 --- a/man/io_uring_prep_sendmsg.3 +++ b/man/io_uring_prep_sendmsg.3 @@ -7,9 +7,9 @@ io_uring_prep_sendmsg \- prepare a sendmsg request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_sendmsg(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3 index 9faabfd..9125e95 100644 --- a/man/io_uring_prep_shutdown.3 +++ b/man/io_uring_prep_shutdown.3 @@ -7,8 +7,8 @@ io_uring_prep_shutdown \- prepare a shutdown request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_shutdown(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," diff --git a/man/io_uring_prep_socket.3 b/man/io_uring_prep_socket.3 index 18e28f6..e576de9 100644 --- a/man/io_uring_prep_socket.3 +++ b/man/io_uring_prep_socket.3 @@ -7,8 +7,8 @@ io_uring_prep_socket \- prepare a socket creation request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_socket(struct io_uring_sqe *" sqe "," .BI " int " domain "," diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3 index d57b954..cb82ad0 100644 --- a/man/io_uring_prep_splice.3 +++ b/man/io_uring_prep_splice.3 @@ -7,8 +7,8 @@ io_uring_prep_splice \- prepare an splice request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_splice(struct io_uring_sqe *" sqe "," .BI " int " fd_in "," diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3 index 70fcdea..d9d983a 100644 --- a/man/io_uring_prep_statx.3 +++ b/man/io_uring_prep_statx.3 @@ -7,11 +7,11 @@ io_uring_prep_statx \- prepare a statx request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_statx(struct io_uring_sqe *" sqe "," .BI " int " dirfd "," diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index 7a17738..40a0271 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -7,9 +7,9 @@ io_uring_prep_symlinkat \- prepare a symlinkat request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_symlinkat(struct io_uring_sqe *" sqe "," .BI " const char *" target "," diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index ebad421..aa0a07f 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -7,8 +7,8 @@ io_uring_prep_sync_file_range \- prepare a sync_file_range request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_sync_file_range(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3 index 83d5ed3..44aaaf6 100644 --- a/man/io_uring_prep_tee.3 +++ b/man/io_uring_prep_tee.3 @@ -7,8 +7,8 @@ io_uring_prep_tee \- prepare a tee request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_tee(struct io_uring_sqe *" sqe "," .BI " int " fd_in "," diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3 index 5b30b80..bfb8791 100644 --- a/man/io_uring_prep_timeout.3 +++ b/man/io_uring_prep_timeout.3 @@ -7,7 +7,7 @@ io_uring_prep_timeoute \- prepare a timeout request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_timeout(struct io_uring_sqe *" sqe "," .BI " struct __kernel_timespec *" ts "," diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3 index d91cade..cb9ed12 100644 --- a/man/io_uring_prep_timeout_update.3 +++ b/man/io_uring_prep_timeout_update.3 @@ -7,7 +7,7 @@ io_uring_prep_timeoute_update \- prepare a request to update an existing timeout .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_timeout_update(struct io_uring_sqe *" sqe "," .BI " struct __kernel_timespec *" ts "," diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index f4bb465..dba8fbc 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -7,9 +7,9 @@ io_uring_prep_unlinkat \- prepare an unlinkat request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " -.BR "#include " +.B #include +.B #include +.B #include .PP .BI "void io_uring_prep_unlinkat(struct io_uring_sqe *" sqe "," .BI " int " dirfd "," diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3 index 91f6d33..791a5f1 100644 --- a/man/io_uring_prep_write.3 +++ b/man/io_uring_prep_write.3 @@ -7,7 +7,7 @@ io_uring_prep_write \- prepare I/O write request .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_write(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3 index 9bf143a..5dab4a6 100644 --- a/man/io_uring_prep_write_fixed.3 +++ b/man/io_uring_prep_write_fixed.3 @@ -7,7 +7,7 @@ io_uring_prep_write_fixed \- prepare I/O write request with registered buffer .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_prep_write_fixed(struct io_uring_sqe *" sqe "," .BI " int " fd ", diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3 index 7120423..9fb83d9 100644 --- a/man/io_uring_prep_writev.3 +++ b/man/io_uring_prep_writev.3 @@ -7,8 +7,8 @@ io_uring_prep_writev \- prepare vector I/O write request .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_writev(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3 index f874b0e..5093596 100644 --- a/man/io_uring_prep_writev2.3 +++ b/man/io_uring_prep_writev2.3 @@ -7,8 +7,8 @@ io_uring_prep_writev2 \- prepare vector I/O write request with flags .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "void io_uring_prep_writev2(struct io_uring_sqe *" sqe "," .BI " int " fd "," diff --git a/man/io_uring_queue_exit.3 b/man/io_uring_queue_exit.3 index d0bc1fa..00f8ae9 100644 --- a/man/io_uring_queue_exit.3 +++ b/man/io_uring_queue_exit.3 @@ -8,7 +8,7 @@ io_uring_queue_exit \- tear down io_uring submission and completion queues .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_queue_exit(struct io_uring *" ring ");" .fi diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index d0cedf9..4785b9e 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -8,7 +8,7 @@ io_uring_queue_init \- setup io_uring submission and completion queues .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_queue_init(unsigned " entries "," .BI " struct io_uring *" ring "," @@ -56,7 +56,7 @@ If the value isn't a power of 2, it will be rounded up to the nearest power of On success io_uring_queue_init() returns 0 and .I ring will point to the shared memory containing the io_uring queues. On failure -.BR -errno +.B -errno is returned. .I flags diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3 index 01d7f83..82a8efc 100644 --- a/man/io_uring_register_buf_ring.3 +++ b/man/io_uring_register_buf_ring.3 @@ -7,7 +7,7 @@ io_uring_register_buf_ring \- register buffer ring for provided buffers .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_register_buf_ring(struct io_uring *" ring ", .BI " struct io_uring_buf_reg *" reg ", diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3 index 1e3b0f0..656ac42 100644 --- a/man/io_uring_register_buffers.3 +++ b/man/io_uring_register_buffers.3 @@ -7,7 +7,7 @@ io_uring_register_buffers \- register buffers for fixed buffer operations .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_register_buffers(struct io_uring *" ring ", .BI " const struct iovec *" iovecs ", diff --git a/man/io_uring_register_eventfd.3 b/man/io_uring_register_eventfd.3 index 42a07aa..56f6f21 100644 --- a/man/io_uring_register_eventfd.3 +++ b/man/io_uring_register_eventfd.3 @@ -7,7 +7,7 @@ io_uring_register_eventfd \- register an eventfd with a ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_register_eventfd(struct io_uring *" ring "," .BI " int " fd ");" diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3 index b5eab5f..0a9ccc3 100644 --- a/man/io_uring_register_files.3 +++ b/man/io_uring_register_files.3 @@ -7,7 +7,7 @@ io_uring_register_files \- register file descriptors .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_register_files(struct io_uring *" ring "," .BI " const int *" files "," @@ -29,7 +29,7 @@ belonging to the for subsequent operations. The -.BR io_uring_register_files_sparse() +.BR io_uring_register_files_sparse (3) function registers an empty file table of .I nr_files number of file descriptors. The sparse variant is available in kernels 5.19 diff --git a/man/io_uring_register_iowq_aff.3 b/man/io_uring_register_iowq_aff.3 index 19d4ad7..e782914 100644 --- a/man/io_uring_register_iowq_aff.3 +++ b/man/io_uring_register_iowq_aff.3 @@ -7,8 +7,8 @@ io_uring_register_iowq_aff \- register async worker CPU affinities .SH SYNOPSIS .nf -.BR "#include " -.BR "#include " +.B #include +.B #include .PP .BI "int io_uring_register_iowq_aff(struct io_uring *" ring "," .BI " size_t " cpusz "," @@ -27,7 +27,7 @@ the system. If this function is called with set to the ring in question and .I mask set to a pointer to a -.BR cpu_set_t +.B cpu_set_t value and .I cpusz set to the size of the CPU set, then async workers will only be allowed to run diff --git a/man/io_uring_register_iowq_max_workers.3 b/man/io_uring_register_iowq_max_workers.3 index 5d90476..2557e21 100644 --- a/man/io_uring_register_iowq_max_workers.3 +++ b/man/io_uring_register_iowq_max_workers.3 @@ -7,7 +7,7 @@ io_uring_register_iowq_max_workers \- modify the maximum allowed async workers .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_register_iowq_max_workers(struct io_uring *" ring "," .BI " unsigned int *" values ");" @@ -35,7 +35,7 @@ limit, as indicated by the rlimit limit. This can be modified by calling -.BR io_uring_register_iowq_max_workers +.B io_uring_register_iowq_max_workers with .I ring set to the ring in question, and diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3 index a2d4585..d41883c 100644 --- a/man/io_uring_register_ring_fd.3 +++ b/man/io_uring_register_ring_fd.3 @@ -7,7 +7,7 @@ io_uring_register_ring_fd \- register a ring file descriptor .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_register_ring_fd(struct io_uring *" ring ");" .fi diff --git a/man/io_uring_sq_ready.3 b/man/io_uring_sq_ready.3 index d189340..adc07e0 100644 --- a/man/io_uring_sq_ready.3 +++ b/man/io_uring_sq_ready.3 @@ -7,7 +7,7 @@ io_uring_sq_ready \- number of unconsumed or unsubmitted entries in the SQ ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "unsigned io_uring_sq_ready(const struct io_uring *" ring ");" .fi diff --git a/man/io_uring_sq_space_left.3 b/man/io_uring_sq_space_left.3 index 14ca99e..d67eee2 100644 --- a/man/io_uring_sq_space_left.3 +++ b/man/io_uring_sq_space_left.3 @@ -7,7 +7,7 @@ io_uring_sq_space_left \- free space in the SQ ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "unsigned io_uring_sq_space_left(const struct io_uring *" ring ");" .fi diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3 index 04f629f..f7ac513 100644 --- a/man/io_uring_sqe_set_data.3 +++ b/man/io_uring_sqe_set_data.3 @@ -7,7 +7,7 @@ io_uring_sqe_set_data \- set user data for submission queue event .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_sqe_set_data(struct io_uring_sqe *" sqe "," .BI " void *" user_data ");" diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 index c8b0e37..23f5c8c 100644 --- a/man/io_uring_sqe_set_flags.3 +++ b/man/io_uring_sqe_set_flags.3 @@ -7,7 +7,7 @@ io_uring_sqe_set_flags \- set flags for submission queue entry .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "void io_uring_sqe_set_flags(struct io_uring_sqe *" sqe "," .BI " unsigned " flags ");" @@ -59,4 +59,4 @@ one completes. None .SH SEE ALSO .BR io_uring_submit (3), -.BR io_uring_register(3) +.BR io_uring_register (3) diff --git a/man/io_uring_sqring_wait.3 b/man/io_uring_sqring_wait.3 index dfec524..10296be 100644 --- a/man/io_uring_sqring_wait.3 +++ b/man/io_uring_sqring_wait.3 @@ -7,7 +7,7 @@ io_uring_sqring_wait \- wait for free space in the SQ ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_sqring_wait(struct io_uring *" ring ");" .fi diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 index b077599..2e09980 100644 --- a/man/io_uring_submit.3 +++ b/man/io_uring_submit.3 @@ -7,7 +7,7 @@ io_uring_submit \- submit requests to the submission queue .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_submit(struct io_uring *" ring ");" .fi diff --git a/man/io_uring_submit_and_wait.3 b/man/io_uring_submit_and_wait.3 index 730e271..62e5559 100644 --- a/man/io_uring_submit_and_wait.3 +++ b/man/io_uring_submit_and_wait.3 @@ -7,7 +7,7 @@ io_uring_submit_and_wait \- submit requests to the submission queue and wait for completion .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_submit_and_wait(struct io_uring *" ring "," .BI " unsigned " wait_nr ");" diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 index bed242c..cabc6fe 100644 --- a/man/io_uring_submit_and_wait_timeout.3 +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -8,7 +8,7 @@ io_uring_submit_and_wait_timeout \- submit requests to the submission queue and wait for the completion with timeout .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_submit_and_wait_timeout(struct io_uring *" ring "," .BI " struct io_uring_cqe **" cqe_ptr "," diff --git a/man/io_uring_unregister_buf_ring.3 b/man/io_uring_unregister_buf_ring.3 index 5daf133..ee87e86 100644 --- a/man/io_uring_unregister_buf_ring.3 +++ b/man/io_uring_unregister_buf_ring.3 @@ -7,7 +7,7 @@ io_uring_unregister_buf_ring \- unregister a previously registered buffer ring .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_unregister_buf_ring(struct io_uring *" ring ", .BI " int " bgid ");" diff --git a/man/io_uring_unregister_buffers.3 b/man/io_uring_unregister_buffers.3 index 01db86e..262a815 100644 --- a/man/io_uring_unregister_buffers.3 +++ b/man/io_uring_unregister_buffers.3 @@ -7,7 +7,7 @@ io_uring_unregister_buffers \- unregister buffers for fixed buffer operations .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_unregister_buffers(struct io_uring *" ring ");" .fi diff --git a/man/io_uring_unregister_files.3 b/man/io_uring_unregister_files.3 index f48e5f7..bddf4c1 100644 --- a/man/io_uring_unregister_files.3 +++ b/man/io_uring_unregister_files.3 @@ -7,7 +7,7 @@ io_uring_unregister_files \- unregister file descriptors .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_unregister_files(struct io_uring *" ring ");" .fi diff --git a/man/io_uring_unregister_ring_fd.3 b/man/io_uring_unregister_ring_fd.3 index 851a9db..d3deba2 100644 --- a/man/io_uring_unregister_ring_fd.3 +++ b/man/io_uring_unregister_ring_fd.3 @@ -7,7 +7,7 @@ io_uring_unregister_ring_fd \- unregister a ring file descriptor .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_unregister_ring_fd(struct io_uring *" ring ");" .fi @@ -24,8 +24,7 @@ For more information on ring descriptor registration, see .BR io_uring_register_ring_fd (3) .SH RETURN VALUE -Returns 1 on success, indicating that one file descriptor was unregistered, -or +Returns 1 on success, indicating that one file descriptor was unregistered, or .B -errno on error. .SH SEE ALSO diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3 index 1bf77a6..c115f6f 100644 --- a/man/io_uring_wait_cqe.3 +++ b/man/io_uring_wait_cqe.3 @@ -7,7 +7,7 @@ io_uring_wait_cqe \- wait for one io_uring completion event .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_wait_cqe(struct io_uring *" ring "," .BI " struct io_uring_cqe **" cqe_ptr ");" @@ -37,4 +37,4 @@ The return value indicates the result of waiting for a CQE, and it has no relation to the CQE result itself. .SH SEE ALSO .BR io_uring_submit (3), -.BR io_uring_wait_cqes(3) +.BR io_uring_wait_cqes (3) diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3 index e00771d..5a4a5d5 100644 --- a/man/io_uring_wait_cqe_nr.3 +++ b/man/io_uring_wait_cqe_nr.3 @@ -7,7 +7,7 @@ io_uring_wait_cqe_nr \- wait for one or more io_uring completion events .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_wait_cqe_nr(struct io_uring *" ring "," .BI " struct io_uring_cqe **" cqe_ptr "," diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 index 9571397..ce4cd09 100644 --- a/man/io_uring_wait_cqe_timeout.3 +++ b/man/io_uring_wait_cqe_timeout.3 @@ -7,7 +7,7 @@ io_uring_wait_cqe_timeout \- wait for one io_uring completion event with timeout .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_wait_cqe_timeout(struct io_uring *" ring "," .BI " struct io_uring_cqe **" cqe_ptr "," @@ -49,4 +49,4 @@ to the CQE result itself. .SH SEE ALSO .BR io_uring_submit (3), .BR io_uring_wait_cqe_timeout (3), -.BR io_uring_wait_cqe(3) +.BR io_uring_wait_cqe (3) diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3 index 37baf1f..b771ebe 100644 --- a/man/io_uring_wait_cqes.3 +++ b/man/io_uring_wait_cqes.3 @@ -7,7 +7,7 @@ io_uring_wait_cqes \- wait for one or more io_uring completion events .SH SYNOPSIS .nf -.BR "#include " +.B #include .PP .BI "int io_uring_wait_cqes(struct io_uring *" ring "," .BI " struct io_uring_cqe **" cqe_ptr "," @@ -53,4 +53,4 @@ returns 0 and the cqe_ptr parm is filled in. On failure it returns .SH SEE ALSO .BR io_uring_submit (3), .BR io_uring_wait_cqe_timeout (3), -.BR io_uring_wait_cqe(3) +.BR io_uring_wait_cqe (3) -- cgit v1.2.3 From 7b7a2014ec5fe1b492ca71f482001bb443575ec6 Mon Sep 17 00:00:00 2001 From: Usama Arif Date: Tue, 31 May 2022 22:21:43 +0100 Subject: io_uring: add prep functions for current working directory This is done for unlink, rename, mkdir, symlink and link. Signed-off-by: Usama Arif --- man/io_uring_prep_linkat.3 | 23 +++++++++++++++++++++-- man/io_uring_prep_mkdirat.3 | 26 ++++++++++++++++++++++---- man/io_uring_prep_renameat.3 | 23 +++++++++++++++++++++-- man/io_uring_prep_symlinkat.3 | 20 ++++++++++++++++++-- man/io_uring_prep_unlinkat.3 | 21 +++++++++++++++++++-- src/include/liburing.h | 31 +++++++++++++++++++++++++++++++ test/rename.c | 7 ++----- test/unlink.c | 2 +- 8 files changed, 135 insertions(+), 18 deletions(-) diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index 04c3d78..c10dd64 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -17,6 +17,11 @@ io_uring_prep_linkat \- prepare a linkat request .BI " int " newdirfd "," .BI " const char *" newpath "," .BI " int " flags ");" +.PP +.BI "void io_uring_prep_link(struct io_uring_sqe *" sqe "," +.BI " const char *" oldpath "," +.BI " const char *" newpath "," +.BI " int " flags ");" .fi .SH DESCRIPTION .PP @@ -34,11 +39,24 @@ and the new path pointed to by .I newpath and using the specified flags in .IR flags . - This function prepares an async .BR linkat (2) request. See that man page for details. +The +.BR io_uring_prep_link (3) +function prepares a link request. The submission queue entry +.I sqe +is setup to use the old path pointed to by +.I oldpath +and the new path pointed to by +.IR newpath , +both relative to the current working directory and using the specified flags in +.IR flags . +This function prepares an async +.BR link (2) +request. See that man page for details. + .SH RETURN VALUE None .SH ERRORS @@ -69,4 +87,5 @@ flag passed back from .SH SEE ALSO .BR io_uring_get_sqe (3), .BR io_uring_submit (3), -.BR linkat (2) +.BR linkat (2), +.BR link (2) diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index 6afda65..13ea2c0 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -15,24 +15,41 @@ io_uring_prep_mkdirat \- prepare an mkdirat request .BI " int " dirfd "," .BI " const char *" path "," .BI " mode_t " mode ");" +.PP +.BI "void io_uring_prep_mkdir(struct io_uring_sqe *" sqe "," +.BI " const char *" path "," +.BI " mode_t " mode ");" .fi .SH DESCRIPTION .PP The .BR io_uring_prep_mkdirat (3) -function prepares an mkdirat request. The submission queue entry +function prepares a mkdirat request. The submission queue entry .I sqe is setup to use the directory file descriptor pointed to by .I dirfd -to start an mkdirat operation on the path identified by +to start a mkdirat operation on the path identified by .I path with the mode given in .IR mode . - This function prepares an async .BR mkdirat (2) request. See that man page for details. +The +.BR io_uring_prep_mkdir (3) +function prepares a mkdir request. The submission queue entry +.I sqe +is setup to use the current working directory to start a mkdir +operation on the path identified by +.I path +with the mode given in +.IR mode . +This function prepares an async +.BR mkdir (2) +request. See that man page for details. + + .SH RETURN VALUE None .SH ERRORS @@ -63,4 +80,5 @@ flag passed back from .SH SEE ALSO .BR io_uring_get_sqe (3), .BR io_uring_submit (3), -.BR mkdirat (2) +.BR mkdirat (2), +.BR mkdir (2) diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index 96bbf88..25608ee 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -17,6 +17,11 @@ io_uring_prep_renameat \- prepare a renameat request .BI " int " newdirfd "," .BI " const char *" newpath "," .BI " int " flags ");" +.PP +.BI "void io_uring_prep_rename(struct io_uring_sqe *" sqe "," +.BI " const char *" oldpath "," +.BI " const char *" newpath "," +.BI " int " flags ");" .fi .SH DESCRIPTION .PP @@ -34,7 +39,6 @@ and the new path pointed to by .I newpath and using the specified flags in .IR flags . - This function prepares an async .BR renameat2 (2) request. If @@ -43,6 +47,20 @@ is zero, then this call is similar to the .BR renameat (2) system call. See those man page for details. +The +.BR io_uring_prep_rename (3) +function prepares a rename request. The submission queue entry +.I sqe +is setup to use the old path pointed to by +.I oldpath +with the new path pointed to by +.IR newpath , +both relative to the current working directory and using the specified flags in +.IR flags . +This function prepares an async +.BR rename (2) +request See that man page for details. + .SH RETURN VALUE None .SH ERRORS @@ -74,4 +92,5 @@ flag passed back from .BR io_uring_get_sqe (3), .BR io_uring_submit (3), .BR renameat (2), -.BR renameat2 (2) +.BR renameat2 (2), +.BR rename (2) diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index 40a0271..ae40b75 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -15,6 +15,10 @@ io_uring_prep_symlinkat \- prepare a symlinkat request .BI " const char *" target "," .BI " int " newdirfd "," .BI " const char *" linkpath ");" +.PP +.BI "void io_uring_prep_symlink(struct io_uring_sqe *" sqe "," +.BI " const char *" target "," +.BI " const char *" linkpath ");" .fi .SH DESCRIPTION .PP @@ -28,11 +32,22 @@ to the new destination indicated by .I newdirfd and .IR linkpath . - This function prepares an async .BR symlinkat (2) request. See that man page for details. +The +.BR io_uring_prep_symlink (3) +function prepares a symlink request. The submission queue entry +.I sqe +is setup to symlink the target path pointed to by +.I target +to the new destination indicated by +.I linkpath +relative to the the current working directory. This function prepares an async +.BR symlink (2) +request. See that man page for details. + .SH RETURN VALUE None .SH ERRORS @@ -63,4 +78,5 @@ flag passed back from .SH SEE ALSO .BR io_uring_get_sqe (3), .BR io_uring_submit (3), -.BR symlinkat (2) +.BR symlinkat (2), +.BR symlink (2) diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index dba8fbc..dfd98cb 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -15,6 +15,10 @@ io_uring_prep_unlinkat \- prepare an unlinkat request .BI " int " dirfd "," .BI " const char *" path "," .BI " int " flags ");" +.PP +.BI "void io_uring_prep_unlink(struct io_uring_sqe *" sqe "," +.BI " const char *" path "," +.BI " int " flags ");" .fi .SH DESCRIPTION .PP @@ -28,11 +32,23 @@ to start an unlinkat operation on the path identified by .I path and using the flags given in .IR flags . - This function prepares an async .BR unlinkat (2) request. See that man page for details. +The +.BR io_uring_prep_unlink (3) +function prepares an unlink request. The submission queue entry +.I sqe +is setup to start an unlinkat operation on the path identified by +.I path +relative to the current working directory and using the flags given in +.IR flags . +This function prepares an async +.BR unlink (2) +request. See that man page for details. + + .SH RETURN VALUE None .SH ERRORS @@ -63,4 +79,5 @@ flag passed back from .SH SEE ALSO .BR io_uring_get_sqe (3), .BR io_uring_submit (3), -.BR unlinkat (2) +.BR unlinkat (2), +.BR unlink (2) diff --git a/src/include/liburing.h b/src/include/liburing.h index 771e150..6eece30 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "liburing/compat.h" @@ -729,6 +730,12 @@ static inline void io_uring_prep_unlinkat(struct io_uring_sqe *sqe, int dfd, sqe->unlink_flags = (__u32) flags; } +static inline void io_uring_prep_unlink(struct io_uring_sqe *sqe, + const char *path, int flags) +{ + io_uring_prep_unlinkat(sqe, AT_FDCWD, path, flags); +} + static inline void io_uring_prep_renameat(struct io_uring_sqe *sqe, int olddfd, const char *oldpath, int newdfd, const char *newpath, int flags) @@ -739,6 +746,12 @@ static inline void io_uring_prep_renameat(struct io_uring_sqe *sqe, int olddfd, sqe->rename_flags = (__u32) flags; } +static inline void io_uring_prep_rename(struct io_uring_sqe *sqe, + const char *oldpath, const char *newpath) +{ + io_uring_prep_renameat(sqe, AT_FDCWD, oldpath, AT_FDCWD, newpath, 0); +} + static inline void io_uring_prep_sync_file_range(struct io_uring_sqe *sqe, int fd, unsigned len, __u64 offset, int flags) @@ -753,6 +766,12 @@ static inline void io_uring_prep_mkdirat(struct io_uring_sqe *sqe, int dfd, io_uring_prep_rw(IORING_OP_MKDIRAT, sqe, dfd, path, mode, 0); } +static inline void io_uring_prep_mkdir(struct io_uring_sqe *sqe, + const char *path, mode_t mode) +{ + io_uring_prep_mkdirat(sqe, AT_FDCWD, path, mode); +} + static inline void io_uring_prep_symlinkat(struct io_uring_sqe *sqe, const char *target, int newdirfd, const char *linkpath) @@ -761,6 +780,12 @@ static inline void io_uring_prep_symlinkat(struct io_uring_sqe *sqe, (uint64_t) (uintptr_t) linkpath); } +static inline void io_uring_prep_symlink(struct io_uring_sqe *sqe, + const char *target, const char *linkpath) +{ + io_uring_prep_symlinkat(sqe, target, AT_FDCWD, linkpath); +} + static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd, const char *oldpath, int newdfd, const char *newpath, int flags) @@ -770,6 +795,12 @@ static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd, sqe->hardlink_flags = (__u32) flags; } +static inline void io_uring_prep_link(struct io_uring_sqe *sqe, + const char *oldpath, const char *newpath, int flags) +{ + io_uring_prep_linkat(sqe, AT_FDCWD, oldpath, AT_FDCWD, newpath, flags); +} + static inline void io_uring_prep_msg_ring(struct io_uring_sqe *sqe, int fd, unsigned int len, __u64 data, unsigned int flags) diff --git a/test/rename.c b/test/rename.c index 7798d43..67d4e9c 100644 --- a/test/rename.c +++ b/test/rename.c @@ -26,11 +26,8 @@ static int test_rename(struct io_uring *ring, const char *old, const char *new) } memset(sqe, 0, sizeof(*sqe)); - sqe->opcode = IORING_OP_RENAMEAT; - sqe->fd = AT_FDCWD; - sqe->addr2 = (unsigned long) new; - sqe->addr = (unsigned long) old; - sqe->len = AT_FDCWD; + + io_uring_prep_rename(sqe, old, new); ret = io_uring_submit(ring); if (ret <= 0) { diff --git a/test/unlink.c b/test/unlink.c index e4c210b..8e7d2f4 100644 --- a/test/unlink.c +++ b/test/unlink.c @@ -24,7 +24,7 @@ static int test_unlink(struct io_uring *ring, const char *old) fprintf(stderr, "get sqe failed\n"); goto err; } - io_uring_prep_unlinkat(sqe, AT_FDCWD, old, 0); + io_uring_prep_unlink(sqe, old, 0); ret = io_uring_submit(ring); if (ret <= 0) { -- cgit v1.2.3 From 80b7fa86872c7e44baa62d6b9cd5ef13ae0d914b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 1 Jun 2022 05:50:09 -0600 Subject: Man page tweaks Signed-off-by: Jens Axboe --- man/io_uring_prep_link.3 | 1 + man/io_uring_prep_linkat.3 | 6 +++--- man/io_uring_prep_mkdir.3 | 1 + man/io_uring_prep_mkdirat.3 | 6 +++--- man/io_uring_prep_rename.3 | 1 + man/io_uring_prep_renameat.3 | 17 +++++++++-------- man/io_uring_prep_symlink.3 | 1 + man/io_uring_prep_unlink.3 | 1 + man/io_uring_prep_unlinkat.3 | 7 +++---- 9 files changed, 23 insertions(+), 18 deletions(-) create mode 120000 man/io_uring_prep_link.3 create mode 120000 man/io_uring_prep_mkdir.3 create mode 120000 man/io_uring_prep_rename.3 create mode 120000 man/io_uring_prep_symlink.3 create mode 120000 man/io_uring_prep_unlink.3 diff --git a/man/io_uring_prep_link.3 b/man/io_uring_prep_link.3 new file mode 120000 index 0000000..6d3059d --- /dev/null +++ b/man/io_uring_prep_link.3 @@ -0,0 +1 @@ +io_uring_prep_linkat.3 \ No newline at end of file diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index c10dd64..bd59afe 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -39,8 +39,11 @@ and the new path pointed to by .I newpath and using the specified flags in .IR flags . + This function prepares an async .BR linkat (2) +or +.BR link (2) request. See that man page for details. The @@ -53,9 +56,6 @@ and the new path pointed to by .IR newpath , both relative to the current working directory and using the specified flags in .IR flags . -This function prepares an async -.BR link (2) -request. See that man page for details. .SH RETURN VALUE None diff --git a/man/io_uring_prep_mkdir.3 b/man/io_uring_prep_mkdir.3 new file mode 120000 index 0000000..5f83143 --- /dev/null +++ b/man/io_uring_prep_mkdir.3 @@ -0,0 +1 @@ +man/io_uring_prep_mkdirat.3 \ No newline at end of file diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index 13ea2c0..5198ae7 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -32,9 +32,6 @@ to start a mkdirat operation on the path identified by .I path with the mode given in .IR mode . -This function prepares an async -.BR mkdirat (2) -request. See that man page for details. The .BR io_uring_prep_mkdir (3) @@ -45,8 +42,11 @@ operation on the path identified by .I path with the mode given in .IR mode . + This function prepares an async .BR mkdir (2) +or +.BR mkdirat (2) request. See that man page for details. diff --git a/man/io_uring_prep_rename.3 b/man/io_uring_prep_rename.3 new file mode 120000 index 0000000..82e3b3c --- /dev/null +++ b/man/io_uring_prep_rename.3 @@ -0,0 +1 @@ +man/io_uring_prep_renameat.3 \ No newline at end of file diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index 25608ee..dab0caf 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -39,13 +39,6 @@ and the new path pointed to by .I newpath and using the specified flags in .IR flags . -This function prepares an async -.BR renameat2 (2) -request. If -.I flags -is zero, then this call is similar to the -.BR renameat (2) -system call. See those man page for details. The .BR io_uring_prep_rename (3) @@ -57,9 +50,17 @@ with the new path pointed to by .IR newpath , both relative to the current working directory and using the specified flags in .IR flags . + This function prepares an async +.BR renameat2 (2) +or .BR rename (2) -request See that man page for details. +request. If +.I flags +is zero, then this call is similar to the +.BR renameat (2) +system call. See those man page for details. + .SH RETURN VALUE None diff --git a/man/io_uring_prep_symlink.3 b/man/io_uring_prep_symlink.3 new file mode 120000 index 0000000..243647f --- /dev/null +++ b/man/io_uring_prep_symlink.3 @@ -0,0 +1 @@ +man/io_uring_prep_symlinkat.3 \ No newline at end of file diff --git a/man/io_uring_prep_unlink.3 b/man/io_uring_prep_unlink.3 new file mode 120000 index 0000000..c2440a1 --- /dev/null +++ b/man/io_uring_prep_unlink.3 @@ -0,0 +1 @@ +man/io_uring_prep_unlinkat.3 \ No newline at end of file diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index dfd98cb..1efc211 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -32,9 +32,6 @@ to start an unlinkat operation on the path identified by .I path and using the flags given in .IR flags . -This function prepares an async -.BR unlinkat (2) -request. See that man page for details. The .BR io_uring_prep_unlink (3) @@ -44,11 +41,13 @@ is setup to start an unlinkat operation on the path identified by .I path relative to the current working directory and using the flags given in .IR flags . + This function prepares an async +.BR unlinkat (2) +or .BR unlink (2) request. See that man page for details. - .SH RETURN VALUE None .SH ERRORS -- cgit v1.2.3 From 23598884f2d45a6f02525ae5d95a780e2352f49c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 1 Jun 2022 05:55:54 -0600 Subject: Fixup bad symlinks Fixes: 80b7fa86872c ("Man page tweaks") Signed-off-by: Jens Axboe --- man/io_uring_prep_mkdir.3 | 2 +- man/io_uring_prep_rename.3 | 2 +- man/io_uring_prep_symlink.3 | 2 +- man/io_uring_prep_unlink.3 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/man/io_uring_prep_mkdir.3 b/man/io_uring_prep_mkdir.3 index 5f83143..b3412d1 120000 --- a/man/io_uring_prep_mkdir.3 +++ b/man/io_uring_prep_mkdir.3 @@ -1 +1 @@ -man/io_uring_prep_mkdirat.3 \ No newline at end of file +io_uring_prep_mkdirat.3 \ No newline at end of file diff --git a/man/io_uring_prep_rename.3 b/man/io_uring_prep_rename.3 index 82e3b3c..785b55e 120000 --- a/man/io_uring_prep_rename.3 +++ b/man/io_uring_prep_rename.3 @@ -1 +1 @@ -man/io_uring_prep_renameat.3 \ No newline at end of file +io_uring_prep_renameat.3 \ No newline at end of file diff --git a/man/io_uring_prep_symlink.3 b/man/io_uring_prep_symlink.3 index 243647f..ae6f41a 120000 --- a/man/io_uring_prep_symlink.3 +++ b/man/io_uring_prep_symlink.3 @@ -1 +1 @@ -man/io_uring_prep_symlinkat.3 \ No newline at end of file +io_uring_prep_symlinkat.3 \ No newline at end of file diff --git a/man/io_uring_prep_unlink.3 b/man/io_uring_prep_unlink.3 index c2440a1..80f86d2 120000 --- a/man/io_uring_prep_unlink.3 +++ b/man/io_uring_prep_unlink.3 @@ -1 +1 @@ -man/io_uring_prep_unlinkat.3 \ No newline at end of file +io_uring_prep_unlinkat.3 \ No newline at end of file -- cgit v1.2.3 From a12f209d0133b71648da3f0d7d71997b35f75359 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 1 Jun 2022 08:16:08 -0600 Subject: test/socket: fix argument order for socket prep Fixes: 971f3cf0f134 ("Fix type for io_uring_prep_socket_direct()") Signed-off-by: Jens Axboe --- test/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/socket.c b/test/socket.c index 131a3a6..6a3ea09 100644 --- a/test/socket.c +++ b/test/socket.c @@ -254,8 +254,8 @@ static int do_send(int socket_direct, int alloc) unsigned file_index = 0; if (alloc) file_index = IORING_FILE_INDEX_ALLOC - 1; - io_uring_prep_socket_direct(sqe, AF_INET, SOCK_DGRAM, 0, 0, - file_index); + io_uring_prep_socket_direct(sqe, AF_INET, SOCK_DGRAM, 0, + file_index, 0); } else { io_uring_prep_socket(sqe, AF_INET, SOCK_DGRAM, 0, 0); } -- cgit v1.2.3 From bc4fba1717c8efc38c67c36a7ef04c35e5f41efc Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 2 Jun 2022 08:10:21 +0700 Subject: .github: Use clang latest version By default, when we install clang from the default `Ubuntu apt` on the GitHub bot, we get clang-11, which is kinda old. clang-15 has better static analysis than the previous versions, for example, the fix in these commits were only found by clang-15: 7e3f7d6030fb6ce0872b876147d29fe230e7b2ba ("test/35fa71a030ca: Fix -Wunused-but-set-variable warning from clang-15") 045b8c5b183859fbc481ec7ab6b818442cc57ab0 ("test/submit-reuse: Fix -Wunused-but-set-variable warning from clang-15") Let's install the latest clang version to get better issue coverage. By default, the Ubuntu apt doesn't provide it. We have to pull from the LLVM repo. The detail is available at: https://apt.llvm.org Link: https://github.com/axboe/liburing/pull/567 Signed-off-by: Ammar Faizi --- .github/workflows/build.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 39f4314..37a2969 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -57,8 +57,15 @@ jobs: - name: Install Compilers run: | - sudo apt-get update -y; - sudo apt-get install -y ${{matrix.cc_pkg}} ${{matrix.cxx_pkg}}; + if [[ "${{matrix.cc_pkg}}" == "clang" ]]; then \ + wget https://apt.llvm.org/llvm.sh -O /tmp/llvm.sh; \ + sudo bash /tmp/llvm.sh 15; \ + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-15 400; \ + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 400; \ + else \ + sudo apt-get update -y; \ + sudo apt-get install -y ${{matrix.cc_pkg}} ${{matrix.cxx_pkg}}; \ + fi; - name: Display compiler versions run: | -- cgit v1.2.3 From c5aa73c7feea1081496c43b1b09bf36acfd4704f Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 2 Jun 2022 08:06:49 +0700 Subject: .github: Add powerpc64 build for GitHub bot Signed-off-by: Ammar Faizi --- .github/workflows/build.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37a2969..42b9812 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,13 @@ jobs: cc: arm-linux-gnueabi-gcc cxx: arm-linux-gnueabi-g++ + # powerpc64 + - arch: powerpc64 + cc_pkg: gcc-powerpc64-linux-gnu + cxx_pkg: g++-powerpc64-linux-gnu + cc: powerpc64-linux-gnu-gcc + cxx: powerpc64-linux-gnu-g++ + env: FLAGS: -g -O2 -Wall -Wextra -Werror -- cgit v1.2.3 From e6d3f8ac93d69d517da4f9354a33514742847d75 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 2 Jun 2022 08:06:49 +0700 Subject: .github: Add powerpc build for GitHub bot Signed-off-by: Ammar Faizi --- .github/workflows/build.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 42b9812..04e5532 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,6 +55,13 @@ jobs: cc: powerpc64-linux-gnu-gcc cxx: powerpc64-linux-gnu-g++ + # powerpc + - arch: powerpc + cc_pkg: gcc-powerpc-linux-gnu + cxx_pkg: g++-powerpc-linux-gnu + cc: powerpc-linux-gnu-gcc + cxx: powerpc-linux-gnu-g++ + env: FLAGS: -g -O2 -Wall -Wextra -Werror -- cgit v1.2.3 From edbeb68e68bf8078ff95584afbc2ff88d36de7d4 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 2 Jun 2022 08:06:50 +0700 Subject: .github: Add alpha build for GitHub bot Signed-off-by: Ammar Faizi --- .github/workflows/build.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04e5532..6de73b5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,6 +62,13 @@ jobs: cc: powerpc-linux-gnu-gcc cxx: powerpc-linux-gnu-g++ + # alpha + - arch: alpha + cc_pkg: gcc-alpha-linux-gnu + cxx_pkg: g++-alpha-linux-gnu + cc: alpha-linux-gnu-gcc + cxx: alpha-linux-gnu-g++ + env: FLAGS: -g -O2 -Wall -Wextra -Werror -- cgit v1.2.3 From bfaa1715c8785384e29cf0507f5a2f9111d6157b Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 2 Jun 2022 08:06:50 +0700 Subject: .github: Add mips64 build for GitHub bot Signed-off-by: Ammar Faizi --- .github/workflows/build.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6de73b5..dd7ba3c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -69,6 +69,13 @@ jobs: cc: alpha-linux-gnu-gcc cxx: alpha-linux-gnu-g++ + # mips64 + - arch: mips64 + cc_pkg: gcc-mips64-linux-gnuabi64 + cxx_pkg: g++-mips64-linux-gnuabi64 + cc: mips64-linux-gnuabi64-gcc + cxx: mips64-linux-gnuabi64-g++ + env: FLAGS: -g -O2 -Wall -Wextra -Werror -- cgit v1.2.3 From df9874a6ff66bd22edf99b558e78af0ddfa999ed Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Thu, 2 Jun 2022 08:06:50 +0700 Subject: .github: Add mips build for GitHub bot Signed-off-by: Ammar Faizi --- .github/workflows/build.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dd7ba3c..88192ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,6 +76,13 @@ jobs: cc: mips64-linux-gnuabi64-gcc cxx: mips64-linux-gnuabi64-g++ + # mips + - arch: mips + cc_pkg: gcc-mips-linux-gnu + cxx_pkg: g++-mips-linux-gnu + cc: mips-linux-gnu-gcc + cxx: mips-linux-gnu-g++ + env: FLAGS: -g -O2 -Wall -Wextra -Werror -- cgit v1.2.3 From febf522af0e83938d7c4a0d553b2631c7ba1178f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 4 Jun 2022 05:47:37 -0600 Subject: man: man page tweaks Consistent use of -errno, remove double empty lines, some formatting, and some clarifications in various spots. Also add the data64 variants of the sqe setting and cqe user_data getting helpers. Signed-off-by: Jens Axboe --- man/io_uring_cqe_get_data.3 | 21 +++++++++++++++++---- man/io_uring_cqe_get_data64.3 | 1 + man/io_uring_enter.2 | 16 ++++++++-------- man/io_uring_prep_accept.3 | 2 +- man/io_uring_prep_close.3 | 2 +- man/io_uring_prep_linkat.3 | 12 ++++++------ man/io_uring_prep_mkdirat.3 | 5 ++--- man/io_uring_prep_openat.3 | 2 +- man/io_uring_prep_openat2.3 | 2 +- man/io_uring_prep_renameat.3 | 5 ++--- man/io_uring_prep_socket.3 | 8 ++++---- man/io_uring_prep_symlinkat.3 | 9 ++++++--- man/io_uring_prep_sync_file_range.3 | 2 +- man/io_uring_prep_unlinkat.3 | 4 ++-- man/io_uring_queue_init.3 | 10 +++++++--- man/io_uring_register_eventfd.3 | 2 +- man/io_uring_register_ring_fd.3 | 2 +- man/io_uring_sq_ready.3 | 5 +++++ man/io_uring_sq_space_left.3 | 2 +- man/io_uring_sqe_set_data.3 | 22 +++++++++++++++++++--- man/io_uring_sqe_set_data64.3 | 1 + man/io_uring_sqe_set_flags.3 | 26 +++++++++++++++++++++++++- man/io_uring_sqring_wait.3 | 4 +++- man/io_uring_submit.3 | 3 ++- man/io_uring_submit_and_wait.3 | 9 ++++++--- man/io_uring_submit_and_wait_timeout.3 | 14 ++++++++++---- man/io_uring_unregister_buffers.3 | 3 ++- man/io_uring_unregister_files.3 | 3 ++- man/io_uring_unregister_ring_fd.3 | 2 +- man/io_uring_wait_cqe_timeout.3 | 7 ++++--- 30 files changed, 143 insertions(+), 63 deletions(-) create mode 120000 man/io_uring_cqe_get_data64.3 create mode 120000 man/io_uring_sqe_set_data64.3 diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3 index 9112ee3..4cbb32c 100644 --- a/man/io_uring_cqe_get_data.3 +++ b/man/io_uring_cqe_get_data.3 @@ -10,30 +10,43 @@ io_uring_cqe_get_data \- get user data for completion event .B #include .PP .BI "void *io_uring_cqe_get_data(struct io_uring_cqe *" cqe ");" +.BI " +.BI "__u64 io_uring_cqe_get_data64(struct io_uring_cqe *" cqe ");" .fi .SH DESCRIPTION .PP The .BR io_uring_cqe_get_data (3) function returns the user_data with the completion queue entry -.IR cqe . +.IR cqe +as a data pointer. + +The +.BR io_uring_cqe_get_data64 (3) +function returns the user_data with the completion queue entry +.IR cqe +as a 64-bit data value. After the caller has received a completion queue entry (CQE) with .BR io_uring_wait_cqe (3), the application can call .BR io_uring_cqe_get_data (3) +or +.BR io_uring_cqe_get_data64 (3) function to retrieve the .I user_data value. This requires that .I user_data has been set earlier with the function -.BR io_uring_sqe_set_data (3). +.BR io_uring_sqe_set_data (3) +or +.BR io_uring_sqe_set_data64 (3). .SH RETURN VALUE If the .I user_data -value has been set before submitting the request, it will be returned. Otherwise -the functions returns NULL. +value has been set before submitting the request, it will be returned. +Otherwise the functions returns NULL. .SH SEE ALSO .BR io_uring_get_sqe (3), .BR io_uring_sqe_set_data (3), diff --git a/man/io_uring_cqe_get_data64.3 b/man/io_uring_cqe_get_data64.3 new file mode 120000 index 0000000..51991c2 --- /dev/null +++ b/man/io_uring_cqe_get_data64.3 @@ -0,0 +1 @@ +io_uring_cqe_get_data.3 \ No newline at end of file diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2 index 22dbbd5..3c04541 100644 --- a/man/io_uring_enter.2 +++ b/man/io_uring_enter.2 @@ -441,7 +441,7 @@ clock source. The request will complete with if the timeout got completed through expiration of the timer, or .I 0 if the timeout got completed through requests completing on their own. If -the timeout was cancelled before it expired, the request will complete with +the timeout was canceled before it expired, the request will complete with .I -ECANCELED. Available since 5.4. @@ -476,7 +476,7 @@ operation. must contain the .I user_data field of the previously issued timeout operation. If the specified timeout -request is found and cancelled successfully, this request will terminate +request is found and canceled successfully, this request will terminate with a result value of .I 0 If the timeout request was found but expiration was already in progress, @@ -542,16 +542,16 @@ Attempt to cancel an already issued request. .I addr must contain the .I user_data -field of the request that should be cancelled. The cancellation request will +field of the request that should be canceled. The cancelation request will complete with one of the following results codes. If found, the .I res field of the cqe will contain 0. If not found, .I res -will contain -ENOENT. If found and attempted cancelled, the +will contain -ENOENT. If found and attempted canceled, the .I res field will contain -EALREADY. In this case, the request may or may not terminate. In general, requests that are interruptible (like socket IO) will -get cancelled, while disk IO requests cannot be cancelled if already started. +get canceled, while disk IO requests cannot be canceled if already started. Available since 5.5. .TP @@ -569,9 +569,9 @@ If used, the timeout specified in the command will cancel the linked command, unless the linked command completes before the timeout. The timeout will complete with .I -ETIME -if the timer expired and the linked request was attempted cancelled, or +if the timer expired and the linked request was attempted canceled, or .I -ECANCELED -if the timer got cancelled because of completion of the linked request. Like +if the timer got canceled because of completion of the linked request. Like .B IORING_OP_TIMEOUT the clock source used is .B CLOCK_MONOTONIC @@ -1138,7 +1138,7 @@ opcode specific and is the same as with breaking chains of One special case is when the request has a linked timeout, then the CQE generation for the linked timeout is decided solely by whether it has .B IOSQE_CQE_SKIP_SUCCESS -set, regardless whether it timed out or was cancelled. In other words, if a +set, regardless whether it timed out or was canceled. In other words, if a linked timeout has the flag set, it's guaranteed to not post a CQE. The semantics are chosen to accommodate several use cases. First, when all but diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index c6b9609..b859013 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -114,7 +114,7 @@ The allocated descriptor will be returned in the CQE .I res field, like a non-direct accept request. -This function prepares an async +These functions prepare an async .BR accept4 (2) request. See that man page for details. diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index 832b3b1..c4b0276 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -43,7 +43,7 @@ function is identical to closing a file descriptor indicated by and unregistering the direct descriptor specified by the .IR file_index . -This function prepares an async +These functions prepare an async .BR close (2) request. See that man page for details. diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3 index bd59afe..0949e3b 100644 --- a/man/io_uring_prep_linkat.3 +++ b/man/io_uring_prep_linkat.3 @@ -40,12 +40,6 @@ and the new path pointed to by and using the specified flags in .IR flags . -This function prepares an async -.BR linkat (2) -or -.BR link (2) -request. See that man page for details. - The .BR io_uring_prep_link (3) function prepares a link request. The submission queue entry @@ -57,6 +51,12 @@ and the new path pointed to by both relative to the current working directory and using the specified flags in .IR flags . +These functions prepare an async +.BR linkat (2) +or +.BR link (2) +request. See those man pages for details. + .SH RETURN VALUE None .SH ERRORS diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3 index 5198ae7..a98b4e3 100644 --- a/man/io_uring_prep_mkdirat.3 +++ b/man/io_uring_prep_mkdirat.3 @@ -43,12 +43,11 @@ operation on the path identified by with the mode given in .IR mode . -This function prepares an async +These functions prepare an async .BR mkdir (2) or .BR mkdirat (2) -request. See that man page for details. - +request. See those man pages for details. .SH RETURN VALUE None diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3 index d8b19a4..e8b4217 100644 --- a/man/io_uring_prep_openat.3 +++ b/man/io_uring_prep_openat.3 @@ -79,7 +79,7 @@ are available in the direct descriptor table, .B -ENFILE is returned instead. -This function prepares an async +These functions prepare an async .BR openat (2) request. See that man page for details. diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3 index 5d3f445..338cf7e 100644 --- a/man/io_uring_prep_openat2.3 +++ b/man/io_uring_prep_openat2.3 @@ -79,7 +79,7 @@ are available in the direct descriptor table, .B -ENFILE is returned instead. -This function prepares an async +These functions prepare an async .BR openat2 (2) request. See that man page for details. diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3 index dab0caf..1fc9e01 100644 --- a/man/io_uring_prep_renameat.3 +++ b/man/io_uring_prep_renameat.3 @@ -51,7 +51,7 @@ with the new path pointed to by both relative to the current working directory and using the specified flags in .IR flags . -This function prepares an async +These functions prepare an async .BR renameat2 (2) or .BR rename (2) @@ -59,8 +59,7 @@ request. If .I flags is zero, then this call is similar to the .BR renameat (2) -system call. See those man page for details. - +system call. See those man pages for details. .SH RETURN VALUE None diff --git a/man/io_uring_prep_socket.3 b/man/io_uring_prep_socket.3 index e576de9..473f225 100644 --- a/man/io_uring_prep_socket.3 +++ b/man/io_uring_prep_socket.3 @@ -50,10 +50,6 @@ argument should be set to the slot that should be used for this socket, or .B IORING_FILE_INDEX_ALLOC if io_uring should allocate a free one. -This function prepares an async -.BR socket (2) -request. See that man page for details. - If the direct variant is used, the application must first have registered a file table using .BR io_uring_register_files (3) @@ -74,6 +70,10 @@ be used automatically and the file index will be returned as CQE .B -ENFILE is otherwise returned if there is no free entries in the io_uring file table. +These functions prepare an async +.BR socket (2) +request. See that man page for details. + .SH RETURN VALUE None .SH ERRORS diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3 index ae40b75..0fa7056 100644 --- a/man/io_uring_prep_symlinkat.3 +++ b/man/io_uring_prep_symlinkat.3 @@ -32,9 +32,6 @@ to the new destination indicated by .I newdirfd and .IR linkpath . -This function prepares an async -.BR symlinkat (2) -request. See that man page for details. The .BR io_uring_prep_symlink (3) @@ -48,6 +45,12 @@ relative to the the current working directory. This function prepares an async .BR symlink (2) request. See that man page for details. +These functions prepare an async +.BR symlinkat (2) +or +.BR symlink (2) +request. See those man pages for details. + .SH RETURN VALUE None .SH ERRORS diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3 index aa0a07f..830e411 100644 --- a/man/io_uring_prep_sync_file_range.3 +++ b/man/io_uring_prep_sync_file_range.3 @@ -32,7 +32,7 @@ and with modifier flags in the .I flags argument. -This function prepares a +This function prepares an async .BR sync_file_range (2) request. See that man page for details on the arguments. diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3 index 1efc211..ba2633c 100644 --- a/man/io_uring_prep_unlinkat.3 +++ b/man/io_uring_prep_unlinkat.3 @@ -42,11 +42,11 @@ is setup to start an unlinkat operation on the path identified by relative to the current working directory and using the flags given in .IR flags . -This function prepares an async +These functions prepare an async .BR unlinkat (2) or .BR unlink (2) -request. See that man page for details. +request. See those man pages for details. .SH RETURN VALUE None diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3 index 4785b9e..086b70f 100644 --- a/man/io_uring_queue_init.3 +++ b/man/io_uring_queue_init.3 @@ -53,10 +53,12 @@ of the SQ ring size in given in If the value isn't a power of 2, it will be rounded up to the nearest power of 2. -On success io_uring_queue_init() returns 0 and +On success, +.BR io_uring_queue_init (3) +returns 0 and .I ring will point to the shared memory containing the io_uring queues. On failure -.B -errno +.BR -errno is returned. .I flags @@ -77,7 +79,9 @@ should be released via a corresponding call to .BR io_uring_queue_exit (3). .SH RETURN VALUE .BR io_uring_queue_init (3) -returns 0 on success and -errno on failure. +returns 0 on success and +.BR -errno +on failure. .SH SEE ALSO .BR io_uring_setup (2), .BR io_uring_register_ring_fd (3), diff --git a/man/io_uring_register_eventfd.3 b/man/io_uring_register_eventfd.3 index 56f6f21..5cbe72a 100644 --- a/man/io_uring_register_eventfd.3 +++ b/man/io_uring_register_eventfd.3 @@ -45,7 +45,7 @@ as a hint to check the CQ ring for completions. .SH RETURN VALUE Returns 0 on success, or or -.B -errno +.BR -errno on error. .SH SEE ALSO .BR eventfd (2) diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3 index d41883c..e70c551 100644 --- a/man/io_uring_register_ring_fd.3 +++ b/man/io_uring_register_ring_fd.3 @@ -42,7 +42,7 @@ ring fd. .SH RETURN VALUE Returns 1 on success, indicating that one file descriptor was registered, or -.B -errno +.BR -errno on error. .SH SEE ALSO .BR io_uring_unregister_ring_fd (3), diff --git a/man/io_uring_sq_ready.3 b/man/io_uring_sq_ready.3 index adc07e0..9927388 100644 --- a/man/io_uring_sq_ready.3 +++ b/man/io_uring_sq_ready.3 @@ -20,6 +20,11 @@ that exist in the SQ ring belonging to the .I ring param. +Usage of this function only applies if the ring has been setup with +.B IORING_SETUP_SQPOLL, +where request submissions, and hence consumption from the SQ ring, happens +through a polling thread. + .SH RETURN VALUE Returns the number of unconsumed or unsubmitted entries in the SQ ring. .SH SEE ALSO diff --git a/man/io_uring_sq_space_left.3 b/man/io_uring_sq_space_left.3 index d67eee2..b5b2e21 100644 --- a/man/io_uring_sq_space_left.3 +++ b/man/io_uring_sq_space_left.3 @@ -20,6 +20,6 @@ function retuns how much space is left in the SQ ring belonging to the param. .SH RETURN VALUE -Returns the free space in the SQ ring. +Returns the number of availables entries in the SQ ring. .SH SEE ALSO .BR io_uring_sq_ready (3) diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3 index f7ac513..274a892 100644 --- a/man/io_uring_sqe_set_data.3 +++ b/man/io_uring_sqe_set_data.3 @@ -11,6 +11,9 @@ io_uring_sqe_set_data \- set user data for submission queue event .PP .BI "void io_uring_sqe_set_data(struct io_uring_sqe *" sqe "," .BI " void *" user_data ");" +.BI " +.BI "void io_uring_sqe_set_data64(struct io_uring_sqe *" sqe "," +.BI " __u64 " data ");" .fi .SH DESCRIPTION .PP @@ -21,9 +24,22 @@ function stores a pointer with the submission queue entry .IR sqe . -After the caller has requested an submission queue entry (SQE) with io_uring_get_sqe(), -he can associate a data pointer with the SQE. Once the completion arrives, the -function io_uring_cqe_get_data() can be called to identify the user request. +The +.BR io_uring_sqe_set_data64 (3) +function stores a 64-bit +.I data +value with the submission queue entry +.IR sqe . + +After the caller has requested a submission queue entry (SQE) with +.BR io_uring_get_sqe (3) , +they can associate a data pointer or value with the SQE. Once the completion +arrives, the function +.BR io_uring_cqe_get_data (3) +or +.BR io_uring_cqe_get_data64 (3) +can be called to retrieve the data pointer or value associated with the +submitted request. .SH RETURN VALUE None diff --git a/man/io_uring_sqe_set_data64.3 b/man/io_uring_sqe_set_data64.3 new file mode 120000 index 0000000..8bbd692 --- /dev/null +++ b/man/io_uring_sqe_set_data64.3 @@ -0,0 +1 @@ +io_uring_sqe_set_data.3 \ No newline at end of file diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3 index 23f5c8c..75e836b 100644 --- a/man/io_uring_sqe_set_flags.3 +++ b/man/io_uring_sqe_set_flags.3 @@ -35,7 +35,9 @@ Normal operation for io_uring is to try and issue an sqe as non-blocking first, and if that fails, execute it in an async manner. To support more efficient overlapped operation of requests that the application knows/assumes will always (or most of the time) block, the application can ask for an sqe to be -issued async from the start. +issued async from the start. Note that this flag immediately causes the SQE +to be offloaded to an async helper thread with no initial non-blocking attempt. +This may be less efficient and should not be used sporadically. .TP .B IOSQE_IO_LINK When this flag is specified, the SQE forms a link with the next SQE in the @@ -50,13 +52,35 @@ executing in parallel, or chains and individual SQEs. Only members inside the chain are serialized. A chain of SQEs will be broken if any request in that chain ends in error. .TP +.B IOSQE_IO_HARDLINK +Like +.B IOSQE_IO_LINK , +except the links aren't severed if an error or unexpected result occurs. +.TP .B IOSQE_IO_DRAIN When this flag is specified, the SQE will not be started before previously submitted SQEs have completed, and new SQEs will not be started before this one completes. +.TP +.B IOSQE_CQE_SKIP_SUCCESS +Request that no CQE be generated for this request, if it completes successfully. +This can be useful in cases where the application doesn't need to know when +a specific request completed, if it completed succesfully. +.TP +.B IOSQE_BUFFER_SELECT +If set, and if the request types supports it, select an IO buffer from the +indicated buffer group. This can be used with requests that read or receive +data from a file or socket, where buffer selection is deferred until the kernel +is ready to transfer data, instead of when the IO is originally submitted. The +application must also set the +.I buf_group +field in the SQE, indicating which previously registered buffer group to select +a buffer from. .SH RETURN VALUE None .SH SEE ALSO .BR io_uring_submit (3), .BR io_uring_register (3) +.BR io_uring_register_buffers (3) +.BR io_uring_register_buf_ring (3) diff --git a/man/io_uring_sqring_wait.3 b/man/io_uring_sqring_wait.3 index 10296be..d70cf40 100644 --- a/man/io_uring_sqring_wait.3 +++ b/man/io_uring_sqring_wait.3 @@ -21,7 +21,9 @@ param, which happens when the kernel side thread has consumed one or more entries. If the SQ ring is currently non-full, no action is taken. -This feature can only be used when SQPOLL is enabled. +This feature can only be used when the ring has been setup with +.B IORING_SETUP_SQPOLL +and hence is using an offloaded approach to request submissions. .SH RETURN VALUE On success it returns the free space. If the kernel does not support the diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3 index 2e09980..f871b89 100644 --- a/man/io_uring_submit.3 +++ b/man/io_uring_submit.3 @@ -20,7 +20,8 @@ function submits the next events to the submission queue belonging to the After the caller retrieves a submission queue entry (SQE) with .BR io_uring_get_sqe (3) -and prepares the SQE, it can be submitted with io_uring_submit(). +and prepares the SQE using one of the provided helpers, it can be submitted with +.BR io_uring_submit (3) . .SH RETURN VALUE On success diff --git a/man/io_uring_submit_and_wait.3 b/man/io_uring_submit_and_wait.3 index 62e5559..1c9eb62 100644 --- a/man/io_uring_submit_and_wait.3 +++ b/man/io_uring_submit_and_wait.3 @@ -22,13 +22,16 @@ and waits for .I wait_nr completion events. -After the caller retrieves a submission queue entry (SQE) with io_uring_get_sqe(), -prepares the SQE, it can be submitted with io_uring_submit_and_wait(). +After the caller retrieves a submission queue entry (SQE) with +.BR io_uring_get_sqe (3) +and prepares the SQE, it can be submitted with +.BR io_uring_submit_and_wait (3) . .SH RETURN VALUE On success .BR io_uring_submit_and_wait (3) -returns the number of submitted submission queue entries. On failure it returns -errno. +returns the number of submitted submission queue entries. On failure it returns +.BR -errno . .SH SEE ALSO .BR io_uring_get_sqe (3), .BR io_uring_submit (3), diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3 index cabc6fe..80fe889 100644 --- a/man/io_uring_submit_and_wait_timeout.3 +++ b/man/io_uring_submit_and_wait_timeout.3 @@ -33,14 +33,20 @@ array. The specifies the set of signals to block. The prevailing signal mask is restored before returning. -After the caller retrieves a submission queue entry (SQE) with io_uring_get_sqe(), -prepares the SQE, it can be submitted with io_uring_submit_and_wait_timeout(). - +After the caller retrieves a submission queue entry (SQE) with +.BR io_uring_get_sqe (3) +and prepares the SQE, it can be submitted with +.BR io_uring_submit_and_wait_timeout (3) . .SH RETURN VALUE On success .BR io_uring_submit_and_wait_timeout (3) -returns the number of submitted submission queue entries. On failure it returns -errno. +returns the number of submitted submission queue entries. On failure it returns +.BR -errno . +The most common failure case is not receiving a completion within the specified +timeout, +.B -ETIME +is returned in this case. .SH SEE ALSO .BR io_uring_get_sqe (3), .BR io_uring_submit (3), diff --git a/man/io_uring_unregister_buffers.3 b/man/io_uring_unregister_buffers.3 index 262a815..f066679 100644 --- a/man/io_uring_unregister_buffers.3 +++ b/man/io_uring_unregister_buffers.3 @@ -21,6 +21,7 @@ function unregisters the fixed buffers previously registered to the .SH RETURN VALUE On success .BR io_uring_unregister_buffers (3) -returns 0. On failure it returns -errno. +returns 0. On failure it returns +.BR -errno . .SH SEE ALSO .BR io_uring_register_buffers (3) diff --git a/man/io_uring_unregister_files.3 b/man/io_uring_unregister_files.3 index bddf4c1..c468d08 100644 --- a/man/io_uring_unregister_files.3 +++ b/man/io_uring_unregister_files.3 @@ -21,6 +21,7 @@ function unregisters the file descriptors previously registered to the .SH RETURN VALUE On success .BR io_uring_unregister_files (3) -returns 0. On failure it returns -errno. +returns 0. On failure it returns +.BR -errno . .SH SEE ALSO .BR io_uring_register_files (3) diff --git a/man/io_uring_unregister_ring_fd.3 b/man/io_uring_unregister_ring_fd.3 index d3deba2..85aca14 100644 --- a/man/io_uring_unregister_ring_fd.3 +++ b/man/io_uring_unregister_ring_fd.3 @@ -25,7 +25,7 @@ For more information on ring descriptor registration, see .SH RETURN VALUE Returns 1 on success, indicating that one file descriptor was unregistered, or -.B -errno +.BR -errno on error. .SH SEE ALSO .BR io_uring_register_ring_fd (3), diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3 index ce4cd09..965fc32 100644 --- a/man/io_uring_wait_cqe_timeout.3 +++ b/man/io_uring_wait_cqe_timeout.3 @@ -43,9 +43,10 @@ when waiting for a request. .SH RETURN VALUE On success .BR io_uring_wait_cqes (3) -returns 0 and the cqe_ptr parm is filled in. On failure it returns -errno. The -return value indicates the result of waiting for a CQE, and it has no relation -to the CQE result itself. +returns 0 and the cqe_ptr parm is filled in. On failure it returns +.BR -errno . +The return value indicates the result of waiting for a CQE, and it has no +relation to the CQE result itself. .SH SEE ALSO .BR io_uring_submit (3), .BR io_uring_wait_cqe_timeout (3), -- cgit v1.2.3 From d4a41927e1184745f318fafef828d92060ba0d5b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 4 Jun 2022 06:02:53 -0600 Subject: README: clarify when RLIMIT_MEMLOCK is still used For newer kernels, the rings themselves are not accounted via RLIMIT_MEMLOCK, but registered buffers still are. Signed-off-by: Jens Axboe --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index afd14b0..80d2b3d 100644 --- a/README +++ b/README @@ -36,7 +36,7 @@ into detail on how to bump the limit on various systems is beyond the scope of this little blurb, but check /etc/security/limits.conf for user specific settings, or /etc/systemd/user.conf and /etc/systemd/system.conf for systemd setups. This affects 5.11 and earlier, new kernels are less dependent -on RLIMIT_MEMLOCK. +on RLIMIT_MEMLOCK as it is only used for registering buffers. Regressions tests -- cgit v1.2.3 From 9664daa178747f7095b8400125787cef08d6d21a Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 4 Jun 2022 06:04:42 -0600 Subject: Add cscope.out to .gitignore If make cscope is used, we don't want to have the output file shown as being not part of the repo. Signed-off-by: Jens Axboe --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 60fddd7..b5acffd 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ config-host.mak config.log liburing.pc + +cscope.out -- cgit v1.2.3 From a7fb522e3b03b6ecc53355305a587164dbec2df8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 4 Jun 2022 06:07:36 -0600 Subject: cHANGELOG: add a few more updates Signed-off-by: Jens Axboe --- CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8d28592..8ea19f3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,8 +22,8 @@ liburing-2.2 release - Add support for SQE128 and CQE32, which are doubly sized SQE and CQE rings. This is needed for some cases of the new IORING_OP_URING_CMD, notably for NVMe passthrough. -- ~5000 lines of man page additions, including adding 87 new man pages. +- ~5500 lines of man page additions, including adding ~90 new man pages. - Synced with the 5.19 kernel release, supporting all the features of 5.19 and earlier. -- 23 new regression test cases, and ~6000 lines of new tests in general. +- 24 new regression test cases, and ~7000 lines of new tests in general. - General optimizations and fixes. -- cgit v1.2.3 From 1f4041a064df14e1bdfd7b7a540b64ea7e85d1fb Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 6 Jun 2022 09:55:14 +0900 Subject: man/io_uring_prep_accept.3: fix parameter types `io_uring_prep_accept` and its variants accept `socklen_t *` not `socklen_t`. Signed-off-by: Seiichi Uchida --- man/io_uring_prep_accept.3 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3 index b859013..3800ccb 100644 --- a/man/io_uring_prep_accept.3 +++ b/man/io_uring_prep_accept.3 @@ -13,26 +13,26 @@ io_uring_prep_accept \- prepare an accept request .BI "void io_uring_prep_accept(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," .BI " struct sockaddr *" addr "," -.BI " socklen_t " addrlen "," +.BI " socklen_t *" addrlen "," .BI " int " flags ");" .PP .BI "void io_uring_prep_accept_direct(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," .BI " struct sockaddr *" addr "," -.BI " socklen_t " addrlen "," +.BI " socklen_t *" addrlen "," .BI " int " flags "," .BI " unsigned int " file_index ");" .PP .BI "void io_uring_prep_multishot_accept(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," .BI " struct sockaddr *" addr "," -.BI " socklen_t " addrlen "," +.BI " socklen_t *" addrlen "," .BI " int " flags ");" .PP .BI "void io_uring_prep_multishot_accept_direct(struct io_uring_sqe *" sqe "," .BI " int " sockfd "," .BI " struct sockaddr *" addr "," -.BI " socklen_t " addrlen "," +.BI " socklen_t *" addrlen "," .BI " int " flags ");" .fi .SH DESCRIPTION -- cgit v1.2.3 From b2399269447cef7e27362fcf2055486b0dd7410e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 6 Jun 2022 17:23:25 +0900 Subject: man/io_uring_prep_madvise.3: remove fd The man page for `io_uring_prep_madvise` contains wrong function signature and description. This commit fixes is by removing the unused parameter. Signed-off-by: Seiichi Uchida --- man/io_uring_prep_madvise.3 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 index b261fa7..700bfa4 100644 --- a/man/io_uring_prep_madvise.3 +++ b/man/io_uring_prep_madvise.3 @@ -11,7 +11,6 @@ io_uring_prep_madvise \- prepare a madvise request .B #include .PP .BI "void io_uring_prep_madvise(struct io_uring_sqe *" sqe "," -.BI " int " fd "," .BI " void *" addr "," .BI " off_t " len "," .BI " int " advice ");" @@ -22,9 +21,7 @@ The .BR io_uring_prep_madvise (3) function prepares an madvise request. The submission queue entry .I sqe -is setup to use the file descriptor pointed to by -.I fd -to start an madvise operation at the virtual address of +is setup to start an madvise operation at the virtual address of .I addr and of .I len -- cgit v1.2.3 From 853b88e5b16bdfac271958b5944077852a4956f3 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 6 Jun 2022 17:49:15 +0900 Subject: man/io_uring_prep_madvise.3: posix_madvise -> madvise `io_uring_prep_madvise` prepares an asynchronous madvise(2), not posix_madvise(3). Signed-off-by: Seiichi Uchida --- man/io_uring_prep_madvise.3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3 index 700bfa4..6c5f16b 100644 --- a/man/io_uring_prep_madvise.3 +++ b/man/io_uring_prep_madvise.3 @@ -29,7 +29,7 @@ length in bytes, giving it the advise located in .IR advice . This function prepares an async -.BR posix_madvise (2) +.BR madvise (2) request. See that man page for details. .SH RETURN VALUE @@ -53,4 +53,4 @@ field. .BR io_uring_get_sqe (3), .BR io_uring_submit (3), .BR io_uring_register (2), -.BR posix_madvise (2) +.BR madvise (2) -- cgit v1.2.3 From ed447b9aa0d84aaf5402021c68cba3d62c3d7a37 Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Mon, 13 Jun 2022 14:13:12 +0200 Subject: changelog: fix wrong man page reference During reading the recently added CHANGELOG I stumbled over IORING_SETUP_COOP_TASKRUN which is documented in man/io_uring_setup.2 rather than in man/io_uring_enter.3. Fixes: b7911762 ("Add CHANGELOG file") Signed-off-by: Florian Fischer --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 8ea19f3..01cb677 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,7 +11,7 @@ liburing-2.2 release - Add support for newer request cancelation features. - Add support for IORING_SETUP_COOP_TASKRUN, which can help reduce the overhead of io_uring in general. Most applications should set this flag, - see the io_uring_enter.3 man page for details. + see the io_uring_setup.2 man page for details. - Add support for registering a sparse buffer and file set. - Add support for a new buffer provide scheme, see io_uring_register_buf_ring.3 for details. -- cgit v1.2.3 From 7d25ba48783b8d6960dbd1c8e54f6862ee5a9afb Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Mon, 13 Jun 2022 06:12:50 -0700 Subject: remove non-existent manpage reference This function doesn't exist Signed-off-by: Dylan Yudaken Signed-off-by: Jens Axboe --- man/io_uring_register_buf_ring.3 | 1 - 1 file changed, 1 deletion(-) diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3 index 82a8efc..9e0b53d 100644 --- a/man/io_uring_register_buf_ring.3 +++ b/man/io_uring_register_buf_ring.3 @@ -131,7 +131,6 @@ On success returns 0. On failure it returns .BR -errno . .SH SEE ALSO -.BR io_uring_buf_ring_alloc (3), .BR io_uring_buf_ring_add (3), .BR io_uring_buf_ring_advance (3), .BR io_uring_buf_ring_cq_advance (3) -- cgit v1.2.3 From 2c9bc6ba8529c28da2b2afeffea88958ca315e5a Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Mon, 13 Jun 2022 06:12:51 -0700 Subject: add mask parameter to io_uring_buf_ring_add Without the mask parameter, it's not feasible to use this API without knowing where the tail is and performing some arithmetic Signed-off-by: Dylan Yudaken Signed-off-by: Jens Axboe --- man/io_uring_buf_ring_add.3 | 5 +++++ man/io_uring_buf_ring_mask.3 | 27 +++++++++++++++++++++++++++ src/include/liburing.h | 13 +++++++++++-- test/send_recvmsg.c | 3 ++- 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 man/io_uring_buf_ring_mask.3 diff --git a/man/io_uring_buf_ring_add.3 b/man/io_uring_buf_ring_add.3 index 741cba6..9d8283b 100644 --- a/man/io_uring_buf_ring_add.3 +++ b/man/io_uring_buf_ring_add.3 @@ -13,6 +13,7 @@ io_uring_buf_ring_add \- add buffers to a shared buffer ring .BI " void *" addr ", .BI " unsigned int " len ", .BI " unsigned short " bid ", +.BI " int " mask ", .BI " int " buf_offset ");" .fi .SH DESCRIPTION @@ -28,6 +29,9 @@ and is of bytes of length. .I bid is the buffer ID, which will be returned in the CQE. +.I mask +is the size mask of the ring, available from +.BR io_uring_buf_ring_mask (3) . .I buf_offset is the offset to insert at from the current tail. If just one buffer is provided before the ring tail is committed with @@ -44,5 +48,6 @@ must be incremented by one for each buffer added. None .SH SEE ALSO .BR io_uring_register_buf_ring (3), +.BR io_uring_buf_ring_mask (3), .BR io_uring_buf_ring_advance (3), .BR io_uring_buf_ring_cq_advance (3) diff --git a/man/io_uring_buf_ring_mask.3 b/man/io_uring_buf_ring_mask.3 new file mode 100644 index 0000000..9160663 --- /dev/null +++ b/man/io_uring_buf_ring_mask.3 @@ -0,0 +1,27 @@ +.\" Copyright (C) 2022 Dylan Yudaken +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_buf_ring_mask 3 "June 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_buf_ring_mask \- Calculate buffer ring mask size +.SH SYNOPSIS +.nf +.B #include +.PP +.BI "int io_uring_buf_ring_mask(__u32 " ring_entries ");" +.fi +.SH DESCRIPTION +.PP +.BR io_uring_buf_ring_mask (3) +calculates the appropriate size mask for a buffer ring. +.IR ring_entries +is the ring entries as specified in +.BR io_uring_register_buf_ring (3) . + +.SH RETURN VALUE +Size mask for the buffer ring. + +.SH SEE ALSO +.BR io_uring_register_buf_ring (3), +.BR io_uring_buf_ring_add (3) diff --git a/src/include/liburing.h b/src/include/liburing.h index 6eece30..9beef0b 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -1089,14 +1089,23 @@ static inline struct io_uring_sqe *_io_uring_get_sqe(struct io_uring *ring) return NULL; } +/* + * Return the appropriate mask for a buffer ring of size 'ring_entries' + */ +static inline int io_uring_buf_ring_mask(__u32 ring_entries) +{ + return ring_entries - 1; +} + /* * Assign 'buf' with the addr/len/buffer ID supplied */ static inline void io_uring_buf_ring_add(struct io_uring_buf_ring *br, void *addr, unsigned int len, - unsigned short bid, int buf_offset) + unsigned short bid, int mask, + int buf_offset) { - struct io_uring_buf *buf = &br->bufs[br->tail + buf_offset]; + struct io_uring_buf *buf = &br->bufs[(br->tail + buf_offset) & mask]; buf->addr = (unsigned long) (uintptr_t) addr; buf->len = len; diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index 44a01b0..6f18bae 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -199,7 +199,8 @@ static void *recv_fn(void *data) } br = ptr; - io_uring_buf_ring_add(br, buf, sizeof(buf), BUF_BID, 0); + io_uring_buf_ring_add(br, buf, sizeof(buf), BUF_BID, + io_uring_buf_ring_mask(1), 0); io_uring_buf_ring_advance(br, 1); } else { struct io_uring_sqe *sqe; -- cgit v1.2.3 From 9b02761ff329c80c90af874bbb1e97d8ca6f0575 Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Mon, 13 Jun 2022 06:12:52 -0700 Subject: add io_uring_buf_ring_init Kernel expects the tail to start at 0, so provide an API to init the ring appropriately. Signed-off-by: Dylan Yudaken Signed-off-by: Jens Axboe --- man/io_uring_buf_ring_init.3 | 30 ++++++++++++++++++++++++++++++ man/io_uring_register_buf_ring.3 | 5 ++++- src/include/liburing.h | 5 +++++ test/send_recvmsg.c | 1 + 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 man/io_uring_buf_ring_init.3 diff --git a/man/io_uring_buf_ring_init.3 b/man/io_uring_buf_ring_init.3 new file mode 100644 index 0000000..50cf69a --- /dev/null +++ b/man/io_uring_buf_ring_init.3 @@ -0,0 +1,30 @@ +.\" Copyright (C) 2022 Dylan Yudaken +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_buf_ring_init 3 "June 13, 2022" "liburing-2.2" "liburing Manual" +.SH NAME +io_uring_buf_ring_init \- Initialise a buffer ring +.SH SYNOPSIS +.nf +.B #include +.PP +.BI "void io_uring_buf_ring_init(struct io_uring_buf_ring *" br ");" +.fi +.SH DESCRIPTION +.PP +.BR io_uring_buf_ring_init (3) +initialises +.IR br +so that it is ready to be used. It may be called after +.BR io_uring_register_buf_ring (3) +but must be called before the buffer ring is used in any other way. + +.SH RETURN VALUE +None + +.SH SEE ALSO +.BR io_uring_register_buf_ring (3), +.BR io_uring_buf_ring_add (3) +.BR io_uring_buf_ring_advance (3), +.BR io_uring_buf_ring_cq_advance (3) diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3 index 9e0b53d..9e520bf 100644 --- a/man/io_uring_register_buf_ring.3 +++ b/man/io_uring_register_buf_ring.3 @@ -115,7 +115,9 @@ is the length of the buffer in bytes, and .I bid is the buffer ID that will be returned in the CQE once consumed. -Reserved fields must not be touched. Applications may use +Reserved fields must not be touched. Applications must use +.BR io_uring_buf_ring_init (3) +to initialise the buffer ring. Applications may use .BR io_uring_buf_ring_add (3) and .BR io_uring_buf_ring_advance (3) @@ -131,6 +133,7 @@ On success returns 0. On failure it returns .BR -errno . .SH SEE ALSO +.BR io_uring_buf_ring_init (3), .BR io_uring_buf_ring_add (3), .BR io_uring_buf_ring_advance (3), .BR io_uring_buf_ring_cq_advance (3) diff --git a/src/include/liburing.h b/src/include/liburing.h index 9beef0b..c31ece2 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -1097,6 +1097,11 @@ static inline int io_uring_buf_ring_mask(__u32 ring_entries) return ring_entries - 1; } +static inline void io_uring_buf_ring_init(struct io_uring_buf_ring *br) +{ + br->tail = 0; +} + /* * Assign 'buf' with the addr/len/buffer ID supplied */ diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index 6f18bae..cce6c45 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -199,6 +199,7 @@ static void *recv_fn(void *data) } br = ptr; + io_uring_buf_ring_init(br); io_uring_buf_ring_add(br, buf, sizeof(buf), BUF_BID, io_uring_buf_ring_mask(1), 0); io_uring_buf_ring_advance(br, 1); -- cgit v1.2.3 From 01e0120220e489f147fd4e91d1bde5393f14b4ff Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Mon, 13 Jun 2022 06:12:53 -0700 Subject: buf-ring: add tests that cycle through the provided buffer ring Add tests that make sure that the buffer ring logic works properly without actually using the data in each buffer. This exposes some bugs in 5.19-rc1 Signed-off-by: Dylan Yudaken Signed-off-by: Jens Axboe --- test/buf-ring.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/test/buf-ring.c b/test/buf-ring.c index 5fd1e53..2fcc360 100644 --- a/test/buf-ring.c +++ b/test/buf-ring.c @@ -206,9 +206,134 @@ static int test_reg_unreg(int bgid) return 0; } +static int test_one_nop(int bgid, struct io_uring *ring) +{ + int ret; + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "get sqe failed\n"); + return -1; + } + + io_uring_prep_nop(sqe); + sqe->flags |= IOSQE_BUFFER_SELECT; + sqe->buf_group = bgid; + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "sqe submit failed: %d\n", ret); + ret = -1; + goto out; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "wait completion %d\n", ret); + ret = -1; + goto out; + } + + if (cqe->res == -ENOBUFS) { + ret = cqe->res; + goto out; + } + + if (cqe->res != 0) { + fprintf(stderr, "nop result %d\n", ret); + ret = -1; + goto out; + } + + ret = cqe->flags >> 16; + +out: + io_uring_cqe_seen(ring, cqe); + return ret; +} + +static int test_running(int bgid, int entries, int loops) +{ + struct io_uring_buf_reg reg = { }; + struct io_uring ring; + void *ptr; + int ret; + int ring_size = (entries * sizeof(struct io_uring_buf) + 4095) & (~4095); + int ring_mask = io_uring_buf_ring_mask(entries); + + int loop, idx; + bool *buffers; + struct io_uring_buf_ring *br; + + ret = t_create_ring(1, &ring, 0); + if (ret == T_SETUP_SKIP) + return 0; + else if (ret != T_SETUP_OK) + return 1; + + if (posix_memalign(&ptr, 4096, ring_size)) + return 1; + + br = (struct io_uring_buf_ring *)ptr; + io_uring_buf_ring_init(br); + + buffers = malloc(sizeof(bool) * entries); + if (!buffers) + return 1; + + reg.ring_addr = (unsigned long) ptr; + reg.ring_entries = entries; + reg.bgid = bgid; + + ret = io_uring_register_buf_ring(&ring, ®, 0); + if (ret) { + /* by now should have checked if this is supported or not */ + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + for (loop = 0; loop < loops; loop++) { + memset(buffers, 0, sizeof(bool) * entries); + for (idx = 0; idx < entries; idx++) + io_uring_buf_ring_add(br, ptr, 1, idx, ring_mask, idx); + io_uring_buf_ring_advance(br, entries); + + for (idx = 0; idx < entries; idx++) { + ret = test_one_nop(bgid, &ring); + if (ret < 0) { + fprintf(stderr, "bad run %d/%d = %d\n", loop, idx, ret); + return ret; + } + if (buffers[ret]) { + fprintf(stderr, "reused buffer %d/%d = %d!\n", loop, idx, ret); + return 1; + } + buffers[ret] = true; + } + ret = test_one_nop(bgid, &ring); + if (ret != -ENOBUFS) { + fprintf(stderr, "expected enobufs run %d = %d\n", loop, ret); + return 1; + } + + } + + ret = io_uring_unregister_buf_ring(&ring, bgid); + if (ret) { + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + io_uring_queue_exit(&ring); + free(buffers); + return 0; +} + int main(int argc, char *argv[]) { int bgids[] = { 1, 127, -1 }; + int entries[] = {1, 32768, 4096, -1 }; int ret, i; if (argc > 1) @@ -242,5 +367,13 @@ int main(int argc, char *argv[]) } } + for (i = 0; !no_buf_ring && entries[i] != -1; i++) { + ret = test_running(2, entries[i], 3); + if (ret) { + fprintf(stderr, "test_running(%d) failed\n", entries[i]); + return 1; + } + } + return 0; } -- cgit v1.2.3 From d6f9e02f9c6a777010824341f14c994b11dfc8b1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 13 Jun 2022 08:07:03 -0600 Subject: test/buf-ring: ensure cqe isn't used uninitialized Fixes: 01e0120220e4 ("buf-ring: add tests that cycle through the provided buffer ring") Signed-off-by: Jens Axboe --- test/buf-ring.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/test/buf-ring.c b/test/buf-ring.c index 2fcc360..af1cac8 100644 --- a/test/buf-ring.c +++ b/test/buf-ring.c @@ -234,22 +234,19 @@ static int test_one_nop(int bgid, struct io_uring *ring) ret = -1; goto out; } + ret = cqe->res; + io_uring_cqe_seen(ring, cqe); - if (cqe->res == -ENOBUFS) { - ret = cqe->res; - goto out; - } + if (ret == -ENOBUFS) + return ret; - if (cqe->res != 0) { + if (ret != 0) { fprintf(stderr, "nop result %d\n", ret); - ret = -1; - goto out; + return -1; } ret = cqe->flags >> 16; - out: - io_uring_cqe_seen(ring, cqe); return ret; } -- cgit v1.2.3 From 5261fce55c79810e103bf1947e3efffe540f71db Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 15 Jun 2022 06:22:13 -0600 Subject: man/io_uring_setup.2: fix typo on when IORING_SETUP_TASKRUN_FLAG was added It's 5.19, not 5.10. Signed-off-by: Jens Axboe --- man/io_uring_setup.2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index 0b09667..c81da89 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -224,7 +224,7 @@ and enter the kernel to process them, and applications can do the same. This makes .B IORING_SETUP_TASKRUN_FLAG safe to use even when applications rely on a peek style operation on the CQ -ring to see if anything might be pending to reap. Available since 5.10. +ring to see if anything might be pending to reap. Available since 5.19. .TP .B IORING_SETUP_SQE128 If set, io_uring will use 128-byte SQEs rather than the normal 64-byte sized -- cgit v1.2.3 From a9e941d4986261332365292ffabf7f71383a9eef Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 15 Jun 2022 09:53:47 -0600 Subject: Remove IORING_CLOSE_FD_AND_FILE_SLOT We dropped this from 5.19, prune it from liburing as well for now. Signed-off-by: Jens Axboe --- man/io_uring_prep_close.3 | 11 ---- src/include/liburing.h | 9 --- src/include/liburing/io_uring.h | 6 -- test/Makefile | 1 - test/file-update-index-alloc.c | 139 ---------------------------------------- 5 files changed, 166 deletions(-) delete mode 100644 test/file-update-index-alloc.c diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3 index c4b0276..94780f2 100644 --- a/man/io_uring_prep_close.3 +++ b/man/io_uring_prep_close.3 @@ -15,9 +15,6 @@ io_uring_prep_close \- prepare a file descriptor close request .BI "void io_uring_prep_close_direct(struct io_uring_sqe *" sqe "," .BI " unsigned " file_index ");" .PP -.BI "void io_uring_prep_close_direct_unregister(struct io_uring_sqe *" sqe "," -.BI " int " fd ", -.BI " unsigned " file_index ");" .fi .SH DESCRIPTION .PP @@ -35,14 +32,6 @@ argument instead of the This is identical to unregistering the direct descriptor, and is provided as a convenience. -For a close request of a direct descriptor where the application also wants -to unregister it, -.BR io_uring_prep_close_direct_unregister (3) -function is identical to closing a file descriptor indicated by -.I fd -and unregistering the direct descriptor specified by the -.IR file_index . - These functions prepare an async .BR close (2) request. See that man page for details. diff --git a/src/include/liburing.h b/src/include/liburing.h index c31ece2..8cba613 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -615,15 +615,6 @@ static inline void io_uring_prep_close_direct(struct io_uring_sqe *sqe, __io_uring_set_target_fixed_file(sqe, file_index); } -static inline void -io_uring_prep_close_direct_unregister(struct io_uring_sqe *sqe, int fd, - unsigned file_index) -{ - io_uring_prep_close(sqe, fd); - __io_uring_set_target_fixed_file(sqe, file_index); - sqe->close_flags = IORING_CLOSE_FD_AND_FILE_SLOT; -} - static inline void io_uring_prep_read(struct io_uring_sqe *sqe, int fd, void *buf, unsigned nbytes, __u64 offset) { diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index 15d9fbd..2f391c9 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -50,7 +50,6 @@ struct io_uring_sqe { __u32 unlink_flags; __u32 hardlink_flags; __u32 xattr_flags; - __u32 close_flags; }; __u64 user_data; /* data to be passed back at completion time */ /* pack this to avoid bogus arm OABI complaints */ @@ -79,11 +78,6 @@ struct io_uring_sqe { */ #define IORING_FILE_INDEX_ALLOC (~0U) -/* - * close flags, store in sqe->close_flags. - */ -#define IORING_CLOSE_FD_AND_FILE_SLOT (1U << 0) - enum { IOSQE_FIXED_FILE_BIT, IOSQE_IO_DRAIN_BIT, diff --git a/test/Makefile b/test/Makefile index ab031e0..51c35a9 100644 --- a/test/Makefile +++ b/test/Makefile @@ -79,7 +79,6 @@ test_srcs := \ files-exit-hang-poll.c \ files-exit-hang-timeout.c \ file-update.c \ - file-update-index-alloc.c \ file-verify.c \ fixed-buf-iter.c \ fixed-link.c \ diff --git a/test/file-update-index-alloc.c b/test/file-update-index-alloc.c deleted file mode 100644 index ea5b420..0000000 --- a/test/file-update-index-alloc.c +++ /dev/null @@ -1,139 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Description: test IORING_OP_FILES_UPDATE can support io_uring - * allocates an available direct descriptor instead of having the - * application pass one. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "helpers.h" -#include "liburing.h" - -int main(int argc, char *argv[]) -{ - struct io_uring_cqe *cqe; - struct io_uring_sqe *sqe; - char wbuf[1] = { 0xef }, rbuf[1] = {0x0}; - struct io_uring ring; - int i, ret, pipe_fds[2], fds[2] = { -1, -1}; - - ret = io_uring_queue_init(8, &ring, 0); - if (ret) { - fprintf(stderr, "ring setup failed\n"); - return -1; - } - - ret = io_uring_register_files(&ring, fds, 2); - if (ret) { - fprintf(stderr, "%s: register ret=%d\n", __func__, ret); - return -1; - } - - if (pipe2(pipe_fds, O_NONBLOCK)) { - fprintf(stderr, "pipe() failed\n"); - return -1; - } - - /* - * Pass IORING_FILE_INDEX_ALLOC, so io_uring in kernel will allocate - * available direct descriptors. - */ - fds[0] = pipe_fds[0]; - fds[1] = pipe_fds[1]; - sqe = io_uring_get_sqe(&ring); - io_uring_prep_files_update(sqe, fds, 2, IORING_FILE_INDEX_ALLOC); - ret = io_uring_submit(&ring); - if (ret != 1) { - fprintf(stderr, "sqe submit failed: %d\n", ret); - return -1; - } - ret = io_uring_wait_cqe(&ring, &cqe); - if (ret < 0) { - fprintf(stderr, "wait files update completion failed: %d\n", ret); - return ret; - } - - if (cqe->res < 0) { - if (cqe->res == -EINVAL || cqe->res == -EOVERFLOW) { - fprintf(stdout, "files update(IORING_FILE_INDEX_ALLOC) not " - "supported, skipping\n"); - return 0; - } - fprintf(stderr, "files update(IORING_FILE_INDEX_ALLOC) failed: %d\n", cqe->res); - return ret; - } - ret = cqe->res; - if (ret != 2) { - fprintf(stderr, "should allocate 2 direct descriptors, but get:%d\n", ret); - return -1; - } - if (fds[0] != 0 || fds[1] != 1) { - fprintf(stderr, "allocate wrong direct descriptors:%d %d\n", - fds[0], fds[1]); - return -1; - } - io_uring_cqe_seen(&ring, cqe); - - sqe = io_uring_get_sqe(&ring); - io_uring_prep_write(sqe, fds[1], wbuf, sizeof(wbuf), 0); - sqe->flags |= IOSQE_FIXED_FILE; - ret = io_uring_submit(&ring); - if (ret != 1) { - fprintf(stderr, "sqe submit failed: %d\n", ret); - return -1; - } - ret = io_uring_wait_cqe(&ring, &cqe); - if (ret < 0 || cqe->res < 0) { - fprintf(stderr, "write failed %d\n", ret); - return ret; - } - io_uring_cqe_seen(&ring, cqe); - - sqe = io_uring_get_sqe(&ring); - io_uring_prep_read(sqe, fds[0], rbuf, sizeof(rbuf), 0); - sqe->flags |= IOSQE_FIXED_FILE; - ret = io_uring_submit(&ring); - if (ret != 1) { - fprintf(stderr, "sqe submit failed: %d\n", ret); - return -1; - } - ret = io_uring_wait_cqe(&ring, &cqe); - if (ret < 0 || cqe->res < 0) { - fprintf(stderr, "read failed %d\n", ret); - return ret; - } - if (rbuf[0] != (char)0xef) { - fprintf(stderr, "read wrong data %x\n", rbuf[0]); - return ret; - } - io_uring_cqe_seen(&ring, cqe); - - sqe = io_uring_get_sqe(&ring); - io_uring_prep_close_direct_unregister(sqe, pipe_fds[0], fds[0]); - sqe = io_uring_get_sqe(&ring); - io_uring_prep_close_direct_unregister(sqe, pipe_fds[1], fds[1]); - ret = io_uring_submit(&ring); - if (ret != 2) { - fprintf(stderr, "sqe submit failed: %d\n", ret); - return -1; - } - - for (i = 0; i < 2; i++) { - ret = io_uring_wait_cqe(&ring, &cqe); - if (ret < 0 || cqe->res < 0) { - fprintf(stderr, "wait close completion %d\n", ret); - return ret; - } - io_uring_cqe_seen(&ring, cqe); - } - - io_uring_queue_exit(&ring); - return 0; -} -- cgit v1.2.3 From ed55ffb31421684abe409dde38e4682eb207437a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 Jun 2022 00:34:31 +0800 Subject: man/io_uring_setup.2: fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 李通洲 --- man/io_uring_setup.2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2 index c81da89..75c69ff 100644 --- a/man/io_uring_setup.2 +++ b/man/io_uring_setup.2 @@ -171,7 +171,7 @@ then it will be clamped at .B IORING_MAX_CQ_ENTRIES . .TP .B IORING_SETUP_ATTACH_WQ -This flag should be set in conjunction with +This flag should be set in conjunction with .IR "struct io_uring_params.wq_fd" being set to an existing io_uring ring file descriptor. When set, the io_uring instance being created will share the asynchronous worker @@ -188,7 +188,7 @@ for details on how to enable the ring. Available since 5.10. .B IORING_SETUP_SUBMIT_ALL Normally io_uring stops submitting a batch of request, if one of these requests results in an error. This can cause submission of less than what is expected, -if a request ends in error while being submitted. If the ring is creted with +if a request ends in error while being submitted. If the ring is created with this flag, .BR io_uring_enter (2) will continue submitting requests even if it encounters an error submitting -- cgit v1.2.3 From 5e63866e719c47f13a0c43c90019fae912b328d8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 15 Jun 2022 14:58:58 -0600 Subject: Add io_uring_prep_cancel64() To keep things consistent between 2.1 and later versions of liburing, make io_uring_prep_cancel() take a void * pointer again instead of a __u64 type. Add io_uring_prep_cancel64() that takes a 64-bit type. Link: https://github.com/axboe/liburing/discussions/601 Signed-off-by: Jens Axboe --- man/io_uring_prep_cancel.3 | 11 ++++++++++- man/io_uring_prep_cancel64.3 | 1 + src/include/liburing.h | 10 ++++++++-- test/accept.c | 2 +- test/io-cancel.c | 6 +++--- 5 files changed, 23 insertions(+), 7 deletions(-) create mode 120000 man/io_uring_prep_cancel64.3 diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 25a500a..89c58c7 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -9,8 +9,12 @@ io_uring_prep_cancel \- prepare a cancelation request .nf .B #include .PP +.BI "void io_uring_prep_cancel64(struct io_uring_sqe *" sqe "," +.BI " __u64 " user_data "," +.BI " int " flags ");" +.PP .BI "void io_uring_prep_cancel(struct io_uring_sqe *" sqe "," -.BI " __u64 " user_data "," +.BI " void *" user_data "," .BI " int " flags ");" .PP .BI "void io_uring_prep_cancel_fd(struct io_uring_sqe *" sqe "," @@ -29,6 +33,11 @@ For the .I flags argument, see below. +.BR io_uring_prep_cancel64 (3) +is identical to +.BR io_uring_prep_cancel (3) , +except it takes a 64-bit integer rather than a pointer type. + The cancelation request will attempt to find the previously issued request identified by .I user_data diff --git a/man/io_uring_prep_cancel64.3 b/man/io_uring_prep_cancel64.3 new file mode 120000 index 0000000..347db09 --- /dev/null +++ b/man/io_uring_prep_cancel64.3 @@ -0,0 +1 @@ +io_uring_prep_cancel.3 \ No newline at end of file diff --git a/src/include/liburing.h b/src/include/liburing.h index 8cba613..1c1b03e 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -538,14 +538,20 @@ static inline void io_uring_prep_multishot_accept_direct(struct io_uring_sqe *sq __io_uring_set_target_fixed_file(sqe, IORING_FILE_INDEX_ALLOC - 1); } -static inline void io_uring_prep_cancel(struct io_uring_sqe *sqe, - __u64 user_data, int flags) +static inline void io_uring_prep_cancel64(struct io_uring_sqe *sqe, + __u64 user_data, int flags) { io_uring_prep_rw(IORING_OP_ASYNC_CANCEL, sqe, -1, NULL, 0, 0); sqe->addr = user_data; sqe->cancel_flags = (__u32) flags; } +static inline void io_uring_prep_cancel(struct io_uring_sqe *sqe, + void *user_data, int flags) +{ + io_uring_prep_cancel64(sqe, (__u64) (uintptr_t) user_data, flags); +} + static inline void io_uring_prep_cancel_fd(struct io_uring_sqe *sqe, int fd, unsigned int flags) { diff --git a/test/accept.c b/test/accept.c index 4e2f587..7bc6226 100644 --- a/test/accept.c +++ b/test/accept.c @@ -471,7 +471,7 @@ static int test_accept_cancel(unsigned usecs, unsigned int nr, bool multishot) for (i = 1; i <= nr; i++) { sqe = io_uring_get_sqe(&m_io_uring); - io_uring_prep_cancel(sqe, i, 0); + io_uring_prep_cancel64(sqe, i, 0); sqe->user_data = nr + i; ret = io_uring_submit(&m_io_uring); assert(ret == 1); diff --git a/test/io-cancel.c b/test/io-cancel.c index 89bb31a..d5e3ae9 100644 --- a/test/io-cancel.c +++ b/test/io-cancel.c @@ -128,7 +128,7 @@ static int start_cancel(struct io_uring *ring, int do_partial, int async_cancel) fprintf(stderr, "sqe get failed\n"); goto err; } - io_uring_prep_cancel(sqe, i + 1, 0); + io_uring_prep_cancel64(sqe, i + 1, 0); if (async_cancel) sqe->flags |= IOSQE_ASYNC; sqe->user_data = 0; @@ -246,7 +246,7 @@ static int test_dont_cancel_another_ring(void) fprintf(stderr, "%s: failed to get sqe\n", __FUNCTION__); return 1; } - io_uring_prep_cancel(sqe, 1, 0); + io_uring_prep_cancel64(sqe, 1, 0); sqe->user_data = 2; ret = io_uring_submit(&ring2); @@ -326,7 +326,7 @@ static int test_cancel_req_across_fork(void) fprintf(stderr, "%s: failed to get sqe\n", __FUNCTION__); return 1; } - io_uring_prep_cancel(sqe, 1, 0); + io_uring_prep_cancel64(sqe, 1, 0); sqe->user_data = 2; ret = io_uring_submit(&ring); -- cgit v1.2.3 From 649d7468ffc2903ca659e976c134e5602e4810bc Mon Sep 17 00:00:00 2001 From: Dylan Yudaken Date: Wed, 15 Jun 2022 04:37:33 -0700 Subject: convert buf-ring nop test to use read The NOP support for IOSQE_BUFFER_SELECT has been reverted, so use a supported function with read. This also allows verifying that the correct data has actually been read. Signed-off-by: Dylan Yudaken Link: https://lore.kernel.org/r/20220615113733.1424472-1-dylany@fb.com Signed-off-by: Jens Axboe --- test/buf-ring.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/test/buf-ring.c b/test/buf-ring.c index af1cac8..3d12ef6 100644 --- a/test/buf-ring.c +++ b/test/buf-ring.c @@ -206,7 +206,7 @@ static int test_reg_unreg(int bgid) return 0; } -static int test_one_nop(int bgid, struct io_uring *ring) +static int test_one_read(int fd, int bgid, struct io_uring *ring) { int ret; struct io_uring_cqe *cqe; @@ -218,21 +218,19 @@ static int test_one_nop(int bgid, struct io_uring *ring) return -1; } - io_uring_prep_nop(sqe); + io_uring_prep_read(sqe, fd, NULL, 1, 0); sqe->flags |= IOSQE_BUFFER_SELECT; sqe->buf_group = bgid; ret = io_uring_submit(ring); if (ret <= 0) { fprintf(stderr, "sqe submit failed: %d\n", ret); - ret = -1; - goto out; + return -1; } ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { fprintf(stderr, "wait completion %d\n", ret); - ret = -1; - goto out; + return -1; } ret = cqe->res; io_uring_cqe_seen(ring, cqe); @@ -240,14 +238,12 @@ static int test_one_nop(int bgid, struct io_uring *ring) if (ret == -ENOBUFS) return ret; - if (ret != 0) { - fprintf(stderr, "nop result %d\n", ret); + if (ret != 1) { + fprintf(stderr, "read result %d\n", ret); return -1; } - ret = cqe->flags >> 16; -out: - return ret; + return cqe->flags >> 16; } static int test_running(int bgid, int entries, int loops) @@ -255,6 +251,7 @@ static int test_running(int bgid, int entries, int loops) struct io_uring_buf_reg reg = { }; struct io_uring ring; void *ptr; + char buffer[8]; int ret; int ring_size = (entries * sizeof(struct io_uring_buf) + 4095) & (~4095); int ring_mask = io_uring_buf_ring_mask(entries); @@ -262,6 +259,7 @@ static int test_running(int bgid, int entries, int loops) int loop, idx; bool *buffers; struct io_uring_buf_ring *br; + int read_fd; ret = t_create_ring(1, &ring, 0); if (ret == T_SETUP_SKIP) @@ -279,6 +277,10 @@ static int test_running(int bgid, int entries, int loops) if (!buffers) return 1; + read_fd = open("/dev/zero", O_RDONLY); + if (read_fd < 0) + return 1; + reg.ring_addr = (unsigned long) ptr; reg.ring_entries = entries; reg.bgid = bgid; @@ -293,11 +295,12 @@ static int test_running(int bgid, int entries, int loops) for (loop = 0; loop < loops; loop++) { memset(buffers, 0, sizeof(bool) * entries); for (idx = 0; idx < entries; idx++) - io_uring_buf_ring_add(br, ptr, 1, idx, ring_mask, idx); + io_uring_buf_ring_add(br, buffer, sizeof(buffer), idx, ring_mask, idx); io_uring_buf_ring_advance(br, entries); for (idx = 0; idx < entries; idx++) { - ret = test_one_nop(bgid, &ring); + memset(buffer, 1, sizeof(buffer)); + ret = test_one_read(read_fd, bgid, &ring); if (ret < 0) { fprintf(stderr, "bad run %d/%d = %d\n", loop, idx, ret); return ret; @@ -306,9 +309,19 @@ static int test_running(int bgid, int entries, int loops) fprintf(stderr, "reused buffer %d/%d = %d!\n", loop, idx, ret); return 1; } + if (buffer[0] != 0) { + fprintf(stderr, "unexpected read %d %d/%d = %d!\n", + (int)buffer[0], loop, idx, ret); + return 1; + } + if (buffer[1] != 1) { + fprintf(stderr, "unexpected spilled read %d %d/%d = %d!\n", + (int)buffer[1], loop, idx, ret); + return 1; + } buffers[ret] = true; } - ret = test_one_nop(bgid, &ring); + ret = test_one_read(read_fd, bgid, &ring); if (ret != -ENOBUFS) { fprintf(stderr, "expected enobufs run %d = %d\n", loop, ret); return 1; @@ -322,6 +335,7 @@ static int test_running(int bgid, int entries, int loops) return 1; } + close(read_fd); io_uring_queue_exit(&ring); free(buffers); return 0; -- cgit v1.2.3 From e5d017ab9cd9605248db68168ae5451f830e646c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 15 Jun 2022 16:00:05 -0600 Subject: test/nop: kill cqe32 test code This was removed as it was just a debug feature, remove it from the test case as well. Signed-off-by: Jens Axboe --- test/nop.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/test/nop.c b/test/nop.c index ce223b3..01e41a6 100644 --- a/test/nop.c +++ b/test/nop.c @@ -20,7 +20,6 @@ static int test_single_nop(struct io_uring *ring) struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; int ret; - bool cqe32 = (ring->flags & IORING_SETUP_CQE32); sqe = io_uring_get_sqe(ring); if (!sqe) { @@ -29,10 +28,6 @@ static int test_single_nop(struct io_uring *ring) } io_uring_prep_nop(sqe); - if (cqe32) { - sqe->addr = 1234; - sqe->addr2 = 5678; - } sqe->user_data = ++seq; ret = io_uring_submit(ring); @@ -50,17 +45,6 @@ static int test_single_nop(struct io_uring *ring) fprintf(stderr, "Unexpected 0 user_data\n"); goto err; } - if (cqe32) { - if (cqe->big_cqe[0] != 1234) { - fprintf(stderr, "Unexpected extra1\n"); - goto err; - - } - if (cqe->big_cqe[1] != 5678) { - fprintf(stderr, "Unexpected extra2\n"); - goto err; - } - } io_uring_cqe_seen(ring, cqe); return 0; err: @@ -72,7 +56,6 @@ static int test_barrier_nop(struct io_uring *ring) struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; int ret, i; - bool cqe32 = (ring->flags & IORING_SETUP_CQE32); for (i = 0; i < 8; i++) { sqe = io_uring_get_sqe(ring); @@ -84,10 +67,6 @@ static int test_barrier_nop(struct io_uring *ring) io_uring_prep_nop(sqe); if (i == 4) sqe->flags = IOSQE_IO_DRAIN; - if (cqe32) { - sqe->addr = 1234; - sqe->addr2 = 5678; - } sqe->user_data = ++seq; } @@ -110,16 +89,6 @@ static int test_barrier_nop(struct io_uring *ring) fprintf(stderr, "Unexpected 0 user_data\n"); goto err; } - if (cqe32) { - if (cqe->big_cqe[0] != 1234) { - fprintf(stderr, "Unexpected extra1\n"); - goto err; - } - if (cqe->big_cqe[1] != 5678) { - fprintf(stderr, "Unexpected extra2\n"); - goto err; - } - } io_uring_cqe_seen(ring, cqe); } -- cgit v1.2.3 From 7bc5197125caac40240b881572139dfb3da55148 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 15 Jun 2022 20:17:49 -0600 Subject: test/ringbuf-read: add provided ring buffer read test case Signed-off-by: Jens Axboe --- test/Makefile | 1 + test/ringbuf-read.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 test/ringbuf-read.c diff --git a/test/Makefile b/test/Makefile index 51c35a9..09e73f9 100644 --- a/test/Makefile +++ b/test/Makefile @@ -126,6 +126,7 @@ test_srcs := \ recv-msgall-stream.c \ register-restrictions.c \ rename.c \ + ringbuf-read.c \ ring-leak2.c \ ring-leak.c \ rsrc_tags.c \ diff --git a/test/ringbuf-read.c b/test/ringbuf-read.c new file mode 100644 index 0000000..f2feba9 --- /dev/null +++ b/test/ringbuf-read.c @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: ring mapped provided buffers with reads + * + */ +#include +#include +#include +#include +#include +#include + +#include "liburing.h" +#include "helpers.h" + +#define BUF_SIZE 4096 +#define NR_BUFS 64 +#define FSIZE (BUF_SIZE * NR_BUFS) + +#define BR_MASK (NR_BUFS - 1) + +static int no_buf_ring; + +static int verify_buffer(char *buf, char val) +{ + int i; + + for (i = 0; i < BUF_SIZE; i++) { + if (buf[i] != val) { + fprintf(stderr, "got %d, wanted %d\n", buf[i], val); + return 1; + } + } + + return 0; +} + +static int test(const char *filename, int dio) +{ + struct io_uring_buf_reg reg = { }; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + struct io_uring_buf_ring *br; + int ret, fd, i; + char *buf; + void *ptr; + + ret = io_uring_queue_init(NR_BUFS, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + if (dio) + fd = open(filename, O_DIRECT | O_RDONLY); + else + fd = open(filename, O_RDONLY); + if (fd < 0) { + perror("open"); + return 1; + } + + posix_fadvise(fd, 0, FSIZE, POSIX_FADV_DONTNEED); + + if (posix_memalign((void **) &buf, 4096, FSIZE)) + return 1; + if (posix_memalign((void **) &br, 4096, 4096)) + return 1; + + reg.ring_addr = (unsigned long) br; + reg.ring_entries = NR_BUFS; + reg.bgid = 1; + + ret = io_uring_register_buf_ring(&ring, ®, 0); + if (ret) { + if (ret == -EINVAL) { + no_buf_ring = 1; + return 0; + } + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + ptr = buf; + for (i = 0; i < NR_BUFS; i++) { + io_uring_buf_ring_add(br, ptr, BUF_SIZE, i + 1, BR_MASK, i); + ptr += BUF_SIZE; + } + io_uring_buf_ring_advance(br, NR_BUFS); + + for (i = 0; i < NR_BUFS; i++) { + sqe = io_uring_get_sqe(&ring); + io_uring_prep_read(sqe, fd, NULL, BUF_SIZE, i * BUF_SIZE); + sqe->buf_group = 1; + sqe->flags |= IOSQE_BUFFER_SELECT; + } + + ret = io_uring_submit(&ring); + if (ret != NR_BUFS) { + fprintf(stderr, "submit: %d\n", ret); + return 1; + } + + for (i = 0; i < NR_BUFS; i++) { + int bid; + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait cqe failed %d\n", ret); + return 1; + } + if (cqe->res != BUF_SIZE) { + fprintf(stderr, "cqe res %d\n", cqe->res); + return 1; + } + if (!(cqe->flags & IORING_CQE_F_BUFFER)) { + fprintf(stderr, "no buffer selected\n"); + return 1; + } + bid = cqe->flags >> IORING_CQE_BUFFER_SHIFT; + io_uring_cqe_seen(&ring, cqe); + if (verify_buffer(buf + ((bid - 1) * BUF_SIZE), bid)) + return 1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + char buf[BUF_SIZE]; + char fname[80]; + int ret, fd, i, do_unlink; + + if (argc > 1) { + strcpy(fname, argv[1]); + do_unlink = 0; + } else { + sprintf(fname, ".ringbuf-read.%d", getpid()); + t_create_file(fname, FSIZE); + do_unlink = 1; + } + + fd = open(fname, O_WRONLY); + if (fd < 0) { + perror("open"); + goto err; + } + for (i = 0; i < NR_BUFS; i++) { + memset(buf, i + 1, BUF_SIZE); + ret = write(fd, buf, BUF_SIZE); + if (ret != BUF_SIZE) { + fprintf(stderr, "bad file prep write\n"); + goto err; + } + } + close(fd); + + ret = test(fname, 1); + if (ret) { + fprintf(stderr, "dio test failed\n"); + return ret; + } + if (no_buf_ring) + return 0; + + ret = test(fname, 0); + if (ret) { + fprintf(stderr, "buffered test failed\n"); + return ret; + } + + return 0; +err: + if (do_unlink) + unlink(fname); + return 1; +} -- cgit v1.2.3 From 05135505a4a90bbe2e882685a7edc7906ed5b491 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 16 Jun 2022 06:29:10 -0600 Subject: test/ringbuf-read: expand test case Add async to the mix as well, with the async test case being mixed in itself by only doing half of them async. Use ->user_data to tell which offset was used, so we don't have any implied ordering there. Signed-off-by: Jens Axboe --- test/ringbuf-read.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/test/ringbuf-read.c b/test/ringbuf-read.c index f2feba9..673f2de 100644 --- a/test/ringbuf-read.c +++ b/test/ringbuf-read.c @@ -35,7 +35,7 @@ static int verify_buffer(char *buf, char val) return 0; } -static int test(const char *filename, int dio) +static int test(const char *filename, int dio, int async) { struct io_uring_buf_reg reg = { }; struct io_uring_sqe *sqe; @@ -94,6 +94,9 @@ static int test(const char *filename, int dio) io_uring_prep_read(sqe, fd, NULL, BUF_SIZE, i * BUF_SIZE); sqe->buf_group = 1; sqe->flags |= IOSQE_BUFFER_SELECT; + if (async && !(i & 1)) + sqe->flags |= IOSQE_ASYNC; + sqe->user_data = i + 1; } ret = io_uring_submit(&ring); @@ -103,7 +106,7 @@ static int test(const char *filename, int dio) } for (i = 0; i < NR_BUFS; i++) { - int bid; + int bid, ud; ret = io_uring_wait_cqe(&ring, &cqe); if (ret) { @@ -119,8 +122,9 @@ static int test(const char *filename, int dio) return 1; } bid = cqe->flags >> IORING_CQE_BUFFER_SHIFT; + ud = cqe->user_data; io_uring_cqe_seen(&ring, cqe); - if (verify_buffer(buf + ((bid - 1) * BUF_SIZE), bid)) + if (verify_buffer(buf + ((bid - 1) * BUF_SIZE), ud)) return 1; } @@ -157,7 +161,7 @@ int main(int argc, char *argv[]) } close(fd); - ret = test(fname, 1); + ret = test(fname, 1, 0); if (ret) { fprintf(stderr, "dio test failed\n"); return ret; @@ -165,12 +169,24 @@ int main(int argc, char *argv[]) if (no_buf_ring) return 0; - ret = test(fname, 0); + ret = test(fname, 0, 0); if (ret) { fprintf(stderr, "buffered test failed\n"); return ret; } + ret = test(fname, 1, 1); + if (ret) { + fprintf(stderr, "dio async test failed\n"); + return ret; + } + + ret = test(fname, 0, 1); + if (ret) { + fprintf(stderr, "buffered async test failed\n"); + return ret; + } + return 0; err: if (do_unlink) -- cgit v1.2.3 From 203abdf5f0bf78a58d59f3f4a4e8561cb76b10f4 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 17 Jun 2022 09:42:41 +0100 Subject: Revert "test/nop: kill cqe32 test code" This reverts commit e5d017ab9cd9605248db68168ae5451f830e646c. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/a85bf82b68dca4f82fa8c275d5ed7e06cc065034.1655455225.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/nop.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/nop.c b/test/nop.c index 01e41a6..ce223b3 100644 --- a/test/nop.c +++ b/test/nop.c @@ -20,6 +20,7 @@ static int test_single_nop(struct io_uring *ring) struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; int ret; + bool cqe32 = (ring->flags & IORING_SETUP_CQE32); sqe = io_uring_get_sqe(ring); if (!sqe) { @@ -28,6 +29,10 @@ static int test_single_nop(struct io_uring *ring) } io_uring_prep_nop(sqe); + if (cqe32) { + sqe->addr = 1234; + sqe->addr2 = 5678; + } sqe->user_data = ++seq; ret = io_uring_submit(ring); @@ -45,6 +50,17 @@ static int test_single_nop(struct io_uring *ring) fprintf(stderr, "Unexpected 0 user_data\n"); goto err; } + if (cqe32) { + if (cqe->big_cqe[0] != 1234) { + fprintf(stderr, "Unexpected extra1\n"); + goto err; + + } + if (cqe->big_cqe[1] != 5678) { + fprintf(stderr, "Unexpected extra2\n"); + goto err; + } + } io_uring_cqe_seen(ring, cqe); return 0; err: @@ -56,6 +72,7 @@ static int test_barrier_nop(struct io_uring *ring) struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; int ret, i; + bool cqe32 = (ring->flags & IORING_SETUP_CQE32); for (i = 0; i < 8; i++) { sqe = io_uring_get_sqe(ring); @@ -67,6 +84,10 @@ static int test_barrier_nop(struct io_uring *ring) io_uring_prep_nop(sqe); if (i == 4) sqe->flags = IOSQE_IO_DRAIN; + if (cqe32) { + sqe->addr = 1234; + sqe->addr2 = 5678; + } sqe->user_data = ++seq; } @@ -89,6 +110,16 @@ static int test_barrier_nop(struct io_uring *ring) fprintf(stderr, "Unexpected 0 user_data\n"); goto err; } + if (cqe32) { + if (cqe->big_cqe[0] != 1234) { + fprintf(stderr, "Unexpected extra1\n"); + goto err; + } + if (cqe->big_cqe[1] != 5678) { + fprintf(stderr, "Unexpected extra2\n"); + goto err; + } + } io_uring_cqe_seen(ring, cqe); } -- cgit v1.2.3 From 540ca1c11016ed50940e3f6f555a986356578646 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 17 Jun 2022 09:42:42 +0100 Subject: tests: fix and improve nop tests We removed CQE32 for nops from the kernel, fix the tests and instead test that we return zeroes in the extra fields instead of garbage. Loop over the tests multiple times so it exhausts CQ and we also test CQ entries recycling and internal caching mechanism. Also excersie IOSQE_ASYNC. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/92f01041e5ef933a6018bd89dd54cc1fae57c6f6.1655455225.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- test/nop.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/test/nop.c b/test/nop.c index ce223b3..1aa88fc 100644 --- a/test/nop.c +++ b/test/nop.c @@ -15,7 +15,7 @@ static int seq; -static int test_single_nop(struct io_uring *ring) +static int test_single_nop(struct io_uring *ring, unsigned req_flags) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -29,11 +29,8 @@ static int test_single_nop(struct io_uring *ring) } io_uring_prep_nop(sqe); - if (cqe32) { - sqe->addr = 1234; - sqe->addr2 = 5678; - } sqe->user_data = ++seq; + sqe->flags |= req_flags; ret = io_uring_submit(ring); if (ret <= 0) { @@ -51,12 +48,12 @@ static int test_single_nop(struct io_uring *ring) goto err; } if (cqe32) { - if (cqe->big_cqe[0] != 1234) { + if (cqe->big_cqe[0] != 0) { fprintf(stderr, "Unexpected extra1\n"); goto err; } - if (cqe->big_cqe[1] != 5678) { + if (cqe->big_cqe[1] != 0) { fprintf(stderr, "Unexpected extra2\n"); goto err; } @@ -67,7 +64,7 @@ err: return 1; } -static int test_barrier_nop(struct io_uring *ring) +static int test_barrier_nop(struct io_uring *ring, unsigned req_flags) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -84,11 +81,8 @@ static int test_barrier_nop(struct io_uring *ring) io_uring_prep_nop(sqe); if (i == 4) sqe->flags = IOSQE_IO_DRAIN; - if (cqe32) { - sqe->addr = 1234; - sqe->addr2 = 5678; - } sqe->user_data = ++seq; + sqe->flags |= req_flags; } ret = io_uring_submit(ring); @@ -111,11 +105,11 @@ static int test_barrier_nop(struct io_uring *ring) goto err; } if (cqe32) { - if (cqe->big_cqe[0] != 1234) { + if (cqe->big_cqe[0] != 0) { fprintf(stderr, "Unexpected extra1\n"); goto err; } - if (cqe->big_cqe[1] != 5678) { + if (cqe->big_cqe[1] != 0) { fprintf(stderr, "Unexpected extra2\n"); goto err; } @@ -132,7 +126,7 @@ static int test_ring(unsigned flags) { struct io_uring ring; struct io_uring_params p = { }; - int ret; + int ret, i; p.flags = flags; ret = io_uring_queue_init_params(8, &ring, &p); @@ -143,18 +137,21 @@ static int test_ring(unsigned flags) return 1; } - ret = test_single_nop(&ring); - if (ret) { - fprintf(stderr, "test_single_nop failed\n"); - goto err; - } + for (i = 0; i < 1000; i++) { + unsigned req_flags = (i & 1) ? IOSQE_ASYNC : 0; - ret = test_barrier_nop(&ring); - if (ret) { - fprintf(stderr, "test_barrier_nop failed\n"); - goto err; - } + ret = test_single_nop(&ring, req_flags); + if (ret) { + fprintf(stderr, "test_single_nop failed\n"); + goto err; + } + ret = test_barrier_nop(&ring, req_flags); + if (ret) { + fprintf(stderr, "test_barrier_nop failed\n"); + goto err; + } + } err: io_uring_queue_exit(&ring); return ret; -- cgit v1.2.3 From c8909b9e1963f4651927f8f46d1d0420d28bcd58 Mon Sep 17 00:00:00 2001 From: Donald Hunter Date: Fri, 17 Jun 2022 22:36:01 +0800 Subject: Fix incorrect close in test for multishot accept This fixes a bug in accept_conn handling in the accept tests that caused it to incorrectly skip the multishot tests and also lose the warning message to a closed stdout. This can be seen in the strace output below. close(1) = 0 io_uring_setup(32, { ... ... write(1, "Fixed Multishot Accept not suppo"..., 47) = -1 EINVAL Unfortunately this exposes a a bug with gcc -O2 where multishot_mask logic gets optimized incorrectly and "Fixed Multishot Accept misses events" is wrongly reported. I am investigating this separately. Fixes: 66cf84527c34 ("test/accept.c: add test for multishot mode accept") Signed-off-by: Donald Hunter Link: https://lore.kernel.org/r/20220617143603.179277-2-hao.xu@linux.dev Signed-off-by: Jens Axboe --- test/accept.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/accept.c b/test/accept.c index 7bc6226..fb87a1d 100644 --- a/test/accept.c +++ b/test/accept.c @@ -103,7 +103,7 @@ static void queue_accept_conn(struct io_uring *ring, int fd, } } -static int accept_conn(struct io_uring *ring, int fixed_idx) +static int accept_conn(struct io_uring *ring, int fixed_idx, bool multishot) { struct io_uring_cqe *cqe; int ret; @@ -115,8 +115,10 @@ static int accept_conn(struct io_uring *ring, int fixed_idx) if (fixed_idx >= 0) { if (ret > 0) { - close(ret); - return -EINVAL; + if (!multishot) { + close(ret); + return -EINVAL; + } } else if (!ret) { ret = fixed_idx; } @@ -208,7 +210,7 @@ static int test_loop(struct io_uring *ring, queue_accept_conn(ring, recv_s0, args); for (i = 0; i < MAX_FDS; i++) { - s_fd[i] = accept_conn(ring, args.fixed ? 0 : -1); + s_fd[i] = accept_conn(ring, args.fixed ? 0 : -1, multishot); if (s_fd[i] == -EINVAL) { if (args.accept_should_error) goto out; -- cgit v1.2.3 From d0d9b70d4861bae77b86c05f6925e991cb6c32f1 Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Fri, 17 Jun 2022 22:36:02 +0800 Subject: test/accept: fix minus one error when calculating multishot_mask We don't need to minus one for the s_fd[i] since the returned cqe.res is already the fixed file table slot which is indexed from zero. Fixes: 66cf84527c34 ("test/accept.c: add test for multishot mode accept") Signed-off-by: Hao Xu Link: https://lore.kernel.org/r/20220617143603.179277-3-hao.xu@linux.dev Signed-off-by: Jens Axboe --- test/accept.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/accept.c b/test/accept.c index fb87a1d..368bc90 100644 --- a/test/accept.c +++ b/test/accept.c @@ -241,7 +241,7 @@ static int test_loop(struct io_uring *ring, i, s_fd[i]); goto err; } - multishot_mask |= (1 << (s_fd[i] - 1)); + multishot_mask |= (1U << s_fd[i]); } if (!multishot) break; -- cgit v1.2.3 From 6cc371d3fe076bcad549dbc0e1a95da8fc8085f2 Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Fri, 17 Jun 2022 22:36:03 +0800 Subject: test/accept: clean code of accept test This does three things: - change multishot_mask from uint to uint32_t - change multishot_mask != UINT_MAX check to ~multishot_mask != 0 The above two avoid compiler and arch influence. Make the logic more robost. - other cleaning to make code clearer. Signed-off-by: Hao Xu Link: https://lore.kernel.org/r/20220617143603.179277-4-hao.xu@linux.dev Signed-off-by: Jens Axboe --- test/accept.c | 66 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/test/accept.c b/test/accept.c index 368bc90..8078ccb 100644 --- a/test/accept.c +++ b/test/accept.c @@ -41,6 +41,21 @@ struct accept_test_args { int extra_loops; }; +static void close_fds(int fds[], int nr) +{ + int i; + + for (i = 0; i < nr; i++) + close(fds[i]); +} + +static void close_sock_fds(int s_fd[], int c_fd[], int nr, bool fixed) +{ + if (!fixed) + close_fds(s_fd, nr); + close_fds(c_fd, nr); +} + static void queue_send(struct io_uring *ring, int fd) { struct io_uring_sqe *sqe; @@ -198,19 +213,17 @@ static int test_loop(struct io_uring *ring, int i, ret, s_fd[MAX_FDS], c_fd[MAX_FDS], done = 0; bool fixed = args.fixed; bool multishot = args.multishot; - unsigned int multishot_mask = 0; + uint32_t multishot_mask = 0; + int nr_fds = multishot ? MAX_FDS : 1; - for (i = 0; i < MAX_FDS; i++) { + for (i = 0; i < nr_fds; i++) c_fd[i] = set_client_fd(addr); - if (!multishot) - break; - } if (!args.queue_accept_before_connect) queue_accept_conn(ring, recv_s0, args); - for (i = 0; i < MAX_FDS; i++) { - s_fd[i] = accept_conn(ring, args.fixed ? 0 : -1, multishot); + for (i = 0; i < nr_fds; i++) { + s_fd[i] = accept_conn(ring, fixed ? 0 : -1, multishot); if (s_fd[i] == -EINVAL) { if (args.accept_should_error) goto out; @@ -241,14 +254,17 @@ static int test_loop(struct io_uring *ring, i, s_fd[i]); goto err; } + /* + * for fixed multishot accept test, the file slots + * allocated are [0, 32), this means we finally end up + * with each bit of a u32 being 1. + */ multishot_mask |= (1U << s_fd[i]); } - if (!multishot) - break; } if (multishot) { - if (fixed && multishot_mask != UINT_MAX) { + if (fixed && (~multishot_mask != 0U)) { fprintf(stderr, "Fixed Multishot Accept misses events\n"); goto err; } @@ -256,7 +272,7 @@ static int test_loop(struct io_uring *ring, } queue_send(ring, c_fd[0]); - queue_recv(ring, s_fd[0], args.fixed); + queue_recv(ring, s_fd[0], fixed); ret = io_uring_submit_and_wait(ring, 2); assert(ret != -1); @@ -280,32 +296,10 @@ static int test_loop(struct io_uring *ring, } out: - if (!args.fixed) { - for (i = 0; i < MAX_FDS; i++) { - close(s_fd[i]); - if (!multishot) - break; - } - } - for (i = 0; i < MAX_FDS; i++) { - close(c_fd[i]); - if (!multishot) - break; - } + close_sock_fds(s_fd, c_fd, nr_fds, fixed); return 0; err: - if (!args.fixed) { - for (i = 0; i < MAX_FDS; i++) { - close(s_fd[i]); - if (!multishot) - break; - } - } - for (i = 0; i < MAX_FDS; i++) { - close(c_fd[i]); - if (!multishot) - break; - } + close_sock_fds(s_fd, c_fd, nr_fds, fixed); return 1; } @@ -627,7 +621,7 @@ static int test_accept_fixed(void) static int test_multishot_fixed_accept(void) { struct io_uring m_io_uring; - int ret, fd[100]; + int ret, fd[MAX_FDS]; struct accept_test_args args = { .fixed = true, .multishot = true -- cgit v1.2.3 From 57315cfe22fed1640ebc1fda1ff566ac75a70549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 Jun 2022 22:35:25 +0800 Subject: man/io_uring_prep_cancel.3: clearify the synchronous manner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 李通洲 --- man/io_uring_prep_cancel.3 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 89c58c7..3201445 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -104,6 +104,12 @@ The execution state of the request has progressed far enough that cancelation is no longer possible. This should normally mean that it will complete shortly, either successfully, or interrupted due to the cancelation. +.SH NOTES + +Although the cancelation request uses async request syntax, the kernel part isn't async at all. It is guaranteed that a CQE is always generated by the time the cancel request has been submitted. If the cancelation is succeed, the request targeted for cancelation will have been posted by the time submission returns. For +.B -EALREADY +it may take a bit of time to do so. + .SH SEE ALSO .BR io_uring_prep_poll_remove (3), .BR io_uring_get_sqe (3), -- cgit v1.2.3 From a2dece6ae57bdb521770f9b746089c865933b553 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 18 Jun 2022 08:52:11 -0600 Subject: man/io_uring_prep_cancel.3: clarify the NOTES section a bit more Signed-off-by: Jens Axboe --- man/io_uring_prep_cancel.3 | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3 index 3201445..3c9f2df 100644 --- a/man/io_uring_prep_cancel.3 +++ b/man/io_uring_prep_cancel.3 @@ -103,13 +103,15 @@ One of the fields set in the SQE was invalid. The execution state of the request has progressed far enough that cancelation is no longer possible. This should normally mean that it will complete shortly, either successfully, or interrupted due to the cancelation. - .SH NOTES - -Although the cancelation request uses async request syntax, the kernel part isn't async at all. It is guaranteed that a CQE is always generated by the time the cancel request has been submitted. If the cancelation is succeed, the request targeted for cancelation will have been posted by the time submission returns. For +Although the cancelation request uses async request syntax, the kernel side of +the cancelation is always run synchronously. It is guaranteed that a CQE is +always generated by the time the cancel request has been submitted. If the +cancelation is successful, the completion for the request targeted for +cancelation will have been posted by the time submission returns. For .B -EALREADY -it may take a bit of time to do so. - +it may take a bit of time to do so. For this case, the caller must wait for the +canceled request to post its completion event. .SH SEE ALSO .BR io_uring_prep_poll_remove (3), .BR io_uring_get_sqe (3), -- cgit v1.2.3 From 468991862c67a9eb62aa1a9ec15884353f84237b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 19 Jun 2022 12:05:56 -0600 Subject: test/Makefile: ensure statx is only added once Signed-off-by: Jens Axboe --- test/Makefile | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/Makefile b/test/Makefile index 09e73f9..e3204a7 100644 --- a/test/Makefile +++ b/test/Makefile @@ -171,21 +171,16 @@ test_srcs := \ skip-cqe.c \ # EOL - all_targets := include ../Makefile.quiet - ifdef CONFIG_HAVE_STATX test_srcs += statx.c -endif - -ifdef CONFIG_HAVE_GLIBC_STATX +else ifdef CONFIG_HAVE_GLIBC_STATX test_srcs += statx.c endif all_targets += statx.t - ifdef CONFIG_HAVE_CXX test_srcs += sq-full-cpp.cc endif -- cgit v1.2.3 From e5bc6a22d5653d2fcd5cdd5496f134084c994739 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 20 Jun 2022 06:58:44 -0600 Subject: test: cleanup some legacy tests These two tests are probably useless these days. But at least make them adhere to the current testing format, where we don't dump a bunch of useless info when they are run. Only dump for errors. Also make internal functions static, which then found a function that isn't even used... Signed-off-by: Jens Axboe --- test/io_uring_enter.c | 83 ++++++++++++----------------------------- test/io_uring_register.c | 97 ++++++++++++++---------------------------------- 2 files changed, 51 insertions(+), 129 deletions(-) diff --git a/test/io_uring_enter.c b/test/io_uring_enter.c index 4ea990c..ef00bf6 100644 --- a/test/io_uring_enter.c +++ b/test/io_uring_enter.c @@ -32,61 +32,39 @@ #define IORING_MAX_ENTRIES 4096 #define IORING_MAX_ENTRIES_FALLBACK 128 -int -expect_failed_submit(struct io_uring *ring, int error) -{ - int ret; - - ret = io_uring_submit(ring); - if (ret == 1) { - printf("expected failure, but io_uring_submit succeeded.\n"); - return 1; - } - - if (errno != error) { - printf("expected %d, got %d\n", error, errno); - return 1; - } - - return 0; -} - -int -expect_fail(int fd, unsigned int to_submit, unsigned int min_complete, - unsigned int flags, sigset_t *sig, int error) +static int expect_fail(int fd, unsigned int to_submit, + unsigned int min_complete, unsigned int flags, + sigset_t *sig, int error) { int ret; ret = __sys_io_uring_enter(fd, to_submit, min_complete, flags, sig); if (ret != -1) { - printf("expected %s, but call succeeded\n", strerror(error)); + fprintf(stderr, "expected %s, but call succeeded\n", strerror(error)); return 1; } if (errno != error) { - printf("expected %d, got %d\n", error, errno); + fprintf(stderr, "expected %d, got %d\n", error, errno); return 1; } return 0; } -int -try_io_uring_enter(int fd, unsigned int to_submit, unsigned int min_complete, - unsigned int flags, sigset_t *sig, int expect, int error) +static int try_io_uring_enter(int fd, unsigned int to_submit, + unsigned int min_complete, unsigned int flags, + sigset_t *sig, int expect, int error) { int ret; - printf("io_uring_enter(%d, %u, %u, %u, %p)\n", fd, to_submit, - min_complete, flags, sig); - if (expect == -1) return expect_fail(fd, to_submit, min_complete, flags, sig, error); ret = __sys_io_uring_enter(fd, to_submit, min_complete, flags, sig); if (ret != expect) { - printf("Expected %d, got %d\n", expect, errno); + fprintf(stderr, "Expected %d, got %d\n", expect, errno); return 1; } @@ -96,8 +74,7 @@ try_io_uring_enter(int fd, unsigned int to_submit, unsigned int min_complete, /* * prep a read I/O. index is treated like a block number. */ -int -setup_file(char *template, off_t len) +static int setup_file(char *template, off_t len) { int fd, ret; char buf[4096]; @@ -115,15 +92,15 @@ setup_file(char *template, off_t len) ret = read(fd, buf, 4096); if (ret != 4096) { - printf("read returned %d, expected 4096\n", ret); + fprintf(stderr, "read returned %d, expected 4096\n", ret); exit(1); } return fd; } -void -io_prep_read(struct io_uring_sqe *sqe, int fd, off_t offset, size_t len) +static void io_prep_read(struct io_uring_sqe *sqe, int fd, off_t offset, + size_t len) { struct iovec *iov; @@ -138,8 +115,7 @@ io_prep_read(struct io_uring_sqe *sqe, int fd, off_t offset, size_t len) io_uring_sqe_set_data(sqe, iov); // free on completion } -void -reap_events(struct io_uring *ring, unsigned nr) +static void reap_events(struct io_uring *ring, unsigned nr) { int ret; unsigned left = nr; @@ -147,17 +123,15 @@ reap_events(struct io_uring *ring, unsigned nr) struct iovec *iov; struct timeval start, now, elapsed; - printf("Reaping %u I/Os\n", nr); gettimeofday(&start, NULL); while (left) { ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { - printf("io_uring_wait_cqe returned %d\n", ret); - printf("expected success\n"); + fprintf(stderr, "io_uring_wait_cqe returned %d\n", ret); exit(1); } if (cqe->res != 4096) - printf("cqe->res: %d, expected 4096\n", cqe->res); + fprintf(stderr, "cqe->res: %d, expected 4096\n", cqe->res); iov = io_uring_cqe_get_data(cqe); free(iov->iov_base); free(iov); @@ -167,15 +141,14 @@ reap_events(struct io_uring *ring, unsigned nr) gettimeofday(&now, NULL); timersub(&now, &start, &elapsed); if (elapsed.tv_sec > 10) { - printf("Timed out waiting for I/Os to complete.\n"); - printf("%u expected, %u completed\n", nr, left); + fprintf(stderr, "Timed out waiting for I/Os to complete.\n"); + fprintf(stderr, "%u expected, %u completed\n", nr, left); break; } } } -void -submit_io(struct io_uring *ring, unsigned nr) +static void submit_io(struct io_uring *ring, unsigned nr) { int fd, ret; off_t file_len; @@ -183,7 +156,6 @@ submit_io(struct io_uring *ring, unsigned nr) static char template[32] = "/tmp/io_uring_enter-test.XXXXXX"; struct io_uring_sqe *sqe; - printf("Allocating %u sqes\n", nr); file_len = nr * 4096; fd = setup_file(template, file_len); for (i = 0; i < nr; i++) { @@ -194,18 +166,15 @@ submit_io(struct io_uring *ring, unsigned nr) } /* submit the I/Os */ - printf("Submitting %u I/Os\n", nr); ret = io_uring_submit(ring); unlink(template); if (ret < 0) { perror("io_uring_enter"); exit(1); } - printf("Done\n"); } -int -main(int argc, char **argv) +int main(int argc, char **argv) { int ret; unsigned int status = 0; @@ -242,7 +211,6 @@ main(int argc, char **argv) /* fill the sq ring */ sq_entries = *ring.sq.kring_entries; submit_io(&ring, sq_entries); - printf("Waiting for %u events\n", sq_entries); ret = __sys_io_uring_enter(ring.ring_fd, 0, sq_entries, IORING_ENTER_GETEVENTS, NULL); if (ret < 0) { @@ -256,7 +224,7 @@ main(int argc, char **argv) */ completed = *ring.cq.ktail - *ring.cq.khead; if (completed != sq_entries) { - printf("Submitted %u I/Os, but only got %u completions\n", + fprintf(stderr, "Submitted %u I/Os, but only got %u completions\n", sq_entries, completed); status = 1; } @@ -267,7 +235,6 @@ main(int argc, char **argv) * Add an invalid index to the submission queue. This should * result in the dropped counter increasing. */ - printf("Submitting invalid sqe index.\n"); index = *sq->kring_entries + 1; // invalid index dropped = *sq->kdropped; ktail = *sq->ktail; @@ -282,15 +249,13 @@ main(int argc, char **argv) ret = __sys_io_uring_enter(ring.ring_fd, 1, 0, 0, NULL); /* now check to see if our sqe was dropped */ if (*sq->kdropped == dropped) { - printf("dropped counter did not increase\n"); + fprintf(stderr, "dropped counter did not increase\n"); status = 1; } - if (!status) { - printf("PASS\n"); + if (!status) return 0; - } - printf("FAIL\n"); + fprintf(stderr, "FAIL\n"); return -1; } diff --git a/test/io_uring_register.c b/test/io_uring_register.c index eaed2dd..4fb6bde 100644 --- a/test/io_uring_register.c +++ b/test/io_uring_register.c @@ -42,19 +42,16 @@ static int memfd_create(const char *name, unsigned int flags) #endif -int -expect_fail(int fd, unsigned int opcode, void *arg, +static int expect_fail(int fd, unsigned int opcode, void *arg, unsigned int nr_args, int error) { int ret; - printf("io_uring_register(%d, %u, %p, %u)\n", - fd, opcode, arg, nr_args); ret = __sys_io_uring_register(fd, opcode, arg, nr_args); if (ret != -1) { int ret2 = 0; - printf("expected %s, but call succeeded\n", strerror(error)); + fprintf(stderr, "expected %s, but call succeeded\n", strerror(error)); if (opcode == IORING_REGISTER_BUFFERS) { ret2 = __sys_io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 0, 0); @@ -63,21 +60,20 @@ expect_fail(int fd, unsigned int opcode, void *arg, IORING_UNREGISTER_FILES, 0, 0); } if (ret2) { - printf("internal error: failed to unregister\n"); + fprintf(stderr, "internal error: failed to unregister\n"); exit(1); } return 1; } if (errno != error) { - printf("expected %d, got %d\n", error, errno); + fprintf(stderr, "expected %d, got %d\n", error, errno); return 1; } return 0; } -int -new_io_uring(int entries, struct io_uring_params *p) +static int new_io_uring(int entries, struct io_uring_params *p) { int fd; @@ -91,8 +87,7 @@ new_io_uring(int entries, struct io_uring_params *p) #define MAXFDS (UINT_MAX * sizeof(int)) -void * -map_filebacked(size_t size) +static void *map_filebacked(size_t size) { int fd, ret; void *addr; @@ -127,8 +122,7 @@ map_filebacked(size_t size) * NOTE: this is now limited by SCM_MAX_FD (253). Keep the code for now, * but probably should augment it to test 253 and 254, specifically. */ -int -test_max_fds(int uring_fd) +static int test_max_fds(int uring_fd) { int status = 1; int ret; @@ -148,14 +142,11 @@ test_max_fds(int uring_fd) fd_as = mmap(NULL, UINT_MAX * sizeof(int), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (fd_as == MAP_FAILED) { - if (errno == ENOMEM) { - printf("Not enough memory for this test, skipping\n"); + if (errno == ENOMEM) return 0; - } perror("mmap fd_as"); exit(1); } - printf("allocated %zu bytes of address space\n", UINT_MAX * sizeof(int)); fdtable_fd = mkstemp(template); if (fdtable_fd < 0) { @@ -193,7 +184,7 @@ test_max_fds(int uring_fd) fds = mmap(fds, 128*1024*1024, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fdtable_fd, 0); if (fds == MAP_FAILED) { - printf("mmap failed at offset %lu\n", + fprintf(stderr, "mmap failed at offset %lu\n", (unsigned long)((char *)fd_as - (char *)fds)); exit(1); } @@ -212,21 +203,15 @@ test_max_fds(int uring_fd) nr_fds /= 2; continue; } - printf("io_uring_register(%d, IORING_REGISTER_FILES, %p, %llu)" - "...succeeded\n", uring_fd, fd_as, nr_fds); status = 0; - printf("io_uring_register(%d, IORING_UNREGISTER_FILES, 0, 0)...", - uring_fd); ret = __sys_io_uring_register(uring_fd, IORING_UNREGISTER_FILES, 0, 0); if (ret < 0) { ret = errno; - printf("failed\n"); errno = ret; perror("io_uring_register UNREGISTER_FILES"); exit(1); } - printf("succeeded\n"); break; } @@ -234,15 +219,14 @@ test_max_fds(int uring_fd) close(fdtable_fd); ret = munmap(fd_as, UINT_MAX * sizeof(int)); if (ret != 0) { - printf("munmap(%zu) failed\n", UINT_MAX * sizeof(int)); + fprintf(stderr, "munmap(%zu) failed\n", UINT_MAX * sizeof(int)); exit(1); } return status; } -int -test_memlock_exceeded(int fd) +static int test_memlock_exceeded(int fd) { int ret; void *buf; @@ -260,7 +244,7 @@ test_memlock_exceeded(int fd) ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, &iov, 1); if (ret < 0) { if (errno == ENOMEM) { - printf("io_uring_register of %zu bytes failed " + fprintf(stderr, "io_uring_register of %zu bytes failed " "with ENOMEM (expected).\n", iov.iov_len); iov.iov_len /= 2; continue; @@ -269,16 +253,14 @@ test_memlock_exceeded(int fd) free(buf); return 0; } - printf("expected success or EFAULT, got %d\n", errno); + fprintf(stderr, "expected success or EFAULT, got %d\n", errno); free(buf); return 1; } - printf("successfully registered %zu bytes (%d).\n", - iov.iov_len, ret); ret = __sys_io_uring_register(fd, IORING_UNREGISTER_BUFFERS, NULL, 0); if (ret != 0) { - printf("error: unregister failed with %d\n", errno); + fprintf(stderr, "error: unregister failed with %d\n", errno); free(buf); return 1; } @@ -291,8 +273,7 @@ test_memlock_exceeded(int fd) return 0; } -int -test_iovec_nr(int fd) +static int test_iovec_nr(int fd) { int i, ret, status = 0; unsigned int nr = 1000000; @@ -315,13 +296,11 @@ test_iovec_nr(int fd) /* reduce to UIO_MAXIOV */ nr = UIO_MAXIOV; - printf("io_uring_register(%d, %u, %p, %u)\n", - fd, IORING_REGISTER_BUFFERS, iovs, nr); ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, iovs, nr); if (ret && (errno == ENOMEM || errno == EPERM) && geteuid()) { - printf("can't register large iovec for regular users, skip\n"); + fprintf(stderr, "can't register large iovec for regular users, skip\n"); } else if (ret != 0) { - printf("expected success, got %d\n", errno); + fprintf(stderr, "expected success, got %d\n", errno); status = 1; } else { __sys_io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 0, 0); @@ -334,8 +313,7 @@ test_iovec_nr(int fd) /* * io_uring limit is 1G. iov_len limit is ~OUL, I think */ -int -test_iovec_size(int fd) +static int test_iovec_size(int fd) { unsigned int status = 0; int ret; @@ -387,11 +365,10 @@ test_iovec_size(int fd) "RLIMIT_MEMLOCK resource limit by at " "least 2MB."); else { - printf("expected success, got %d\n", errno); + fprintf(stderr, "expected success, got %d\n", errno); status = 1; } } else { - printf("Success!\n"); ret = __sys_io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 0, 0); if (ret < 0) { @@ -409,7 +386,6 @@ test_iovec_size(int fd) status = 1; iov.iov_base = buf; iov.iov_len = 2*1024*1024; - printf("reserve file-backed buffers\n"); status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, EOPNOTSUPP); munmap(buf, 2*1024*1024); @@ -422,18 +398,7 @@ test_iovec_size(int fd) return status; } -void -dump_sqe(struct io_uring_sqe *sqe) -{ - printf("\topcode: %d\n", sqe->opcode); - printf("\tflags: 0x%.8x\n", sqe->flags); - printf("\tfd: %d\n", sqe->fd); - if (sqe->opcode == IORING_OP_POLL_ADD) - printf("\tpoll_events: 0x%.8x\n", sqe->poll_events); -} - -int -ioring_poll(struct io_uring *ring, int fd, int fixed) +static int ioring_poll(struct io_uring *ring, int fd, int fixed) { int ret; struct io_uring_sqe *sqe; @@ -447,22 +412,20 @@ ioring_poll(struct io_uring *ring, int fd, int fixed) sqe->fd = fd; sqe->poll_events = POLLIN|POLLOUT; - printf("io_uring_submit:\n"); - dump_sqe(sqe); ret = io_uring_submit(ring); if (ret != 1) { - printf("failed to submit poll sqe: %d.\n", errno); + fprintf(stderr, "failed to submit poll sqe: %d.\n", errno); return 1; } ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { - printf("io_uring_wait_cqe failed with %d\n", ret); + fprintf(stderr, "io_uring_wait_cqe failed with %d\n", ret); return 1; } ret = 0; if (cqe->res != POLLOUT) { - printf("io_uring_wait_cqe: expected 0x%.8x, got 0x%.8x\n", + fprintf(stderr, "io_uring_wait_cqe: expected 0x%.8x, got 0x%.8x\n", POLLOUT, cqe->res); ret = 1; } @@ -471,8 +434,7 @@ ioring_poll(struct io_uring *ring, int fd, int fixed) return ret; } -int -test_poll_ringfd(void) +static int test_poll_ringfd(void) { int status = 0; int ret; @@ -609,8 +571,7 @@ out: return 0; } -int -main(int argc, char **argv) +int main(int argc, char **argv) { int fd, ret; unsigned int status = 0; @@ -628,8 +589,6 @@ main(int argc, char **argv) return 1; } mlock_limit = rlim.rlim_cur; - printf("RELIMIT_MEMLOCK: %llu (%llu)\n", (unsigned long long) rlim.rlim_cur, - (unsigned long long) rlim.rlim_max); devnull = open("/dev/null", O_RDWR); if (devnull < 0) { perror("open /dev/null"); @@ -661,10 +620,8 @@ main(int argc, char **argv) /* uring poll on the uring fd */ status |= test_poll_ringfd(); - if (!status) - printf("PASS\n"); - else - printf("FAIL\n"); + if (status) + fprintf(stderr, "FAIL\n"); ret = test_shmem(); if (ret) { -- cgit v1.2.3 From b1735ffa9c5dc5ec18c8fbc121b7b0bc417cdc89 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 20 Jun 2022 08:00:06 -0600 Subject: test/io_uring_register: kill another expected printf() Signed-off-by: Jens Axboe --- test/io_uring_register.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/io_uring_register.c b/test/io_uring_register.c index 4fb6bde..e639f05 100644 --- a/test/io_uring_register.c +++ b/test/io_uring_register.c @@ -244,8 +244,6 @@ static int test_memlock_exceeded(int fd) ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, &iov, 1); if (ret < 0) { if (errno == ENOMEM) { - fprintf(stderr, "io_uring_register of %zu bytes failed " - "with ENOMEM (expected).\n", iov.iov_len); iov.iov_len /= 2; continue; } -- cgit v1.2.3 From dda4848a9911120a903bef6284fb88286f4464c9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 23 Jun 2022 09:45:45 -0600 Subject: test/io_uring_setup: quiet it down We expect tests to only complain on error, silence all the useless garbage this old test prints. Signed-off-by: Jens Axboe --- test/io_uring_setup.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/test/io_uring_setup.c b/test/io_uring_setup.c index 94b54fd..7752c97 100644 --- a/test/io_uring_setup.c +++ b/test/io_uring_setup.c @@ -101,13 +101,9 @@ try_io_uring_setup(unsigned entries, struct io_uring_params *p, int expect, int { int ret, err; - printf("io_uring_setup(%u, %p), flags: %s, feat: %s, resv: %s, sq_thread_cpu: %u\n", - entries, p, flags_string(p), features_string(p), dump_resv(p), - p ? p->sq_thread_cpu : 0); - ret = __sys_io_uring_setup(entries, p); if (ret != expect) { - printf("expected %d, got %d\n", expect, ret); + fprintf(stderr, "expected %d, got %d\n", expect, ret); /* if we got a valid uring, close it */ if (ret > 0) close(ret); @@ -119,7 +115,7 @@ try_io_uring_setup(unsigned entries, struct io_uring_params *p, int expect, int printf("Needs root, not flagging as an error\n"); return 0; } - printf("expected errno %d, got %d\n", error, err); + fprintf(stderr, "expected errno %d, got %d\n", error, err); return 1; } @@ -169,7 +165,7 @@ main(int argc, char **argv) memset(&p, 0, sizeof(p)); fd = __sys_io_uring_setup(1, &p); if (fd < 0) { - printf("io_uring_setup failed with %d, expected success\n", + fprintf(stderr, "io_uring_setup failed with %d, expected success\n", errno); status = 1; } else { @@ -177,16 +173,14 @@ main(int argc, char **argv) int ret; ret = read(fd, buf, 4096); if (ret >= 0) { - printf("read from io_uring fd succeeded. expected fail\n"); + fprintf(stderr, "read from io_uring fd succeeded. expected fail\n"); status = 1; } } - if (!status) { - printf("PASS\n"); + if (!status) return 0; - } - printf("FAIL\n"); + fprintf(stderr, "FAIL\n"); return -1; } -- cgit v1.2.3