From 375492c1ba1e084f841c0af49ad73e388ff3c1dd Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 4 Dec 2024 14:47:40 -0500 Subject: [PATCH] io_uring_try_setup_flags: New function to probe kernel flag support This new function is useful for flags like IORING_SETUP_SINGLE_ISSUER that are useful on kernels that support them, but not necessary on older kernels. Signed-off-by: Tavian Barnes --- man/io_uring_try_setup_flags.3 | 47 ++++++++++++++++++++++++++++++++++ src/include/liburing.h | 2 ++ src/liburing.map | 1 + src/setup.c | 17 ++++++++++++ test/Makefile | 1 + test/try-setup-flags.c | 33 ++++++++++++++++++++++++ 6 files changed, 101 insertions(+) create mode 100644 man/io_uring_try_setup_flags.3 create mode 100644 test/try-setup-flags.c diff --git a/man/io_uring_try_setup_flags.3 b/man/io_uring_try_setup_flags.3 new file mode 100644 index 000000000..824285073 --- /dev/null +++ b/man/io_uring_try_setup_flags.3 @@ -0,0 +1,47 @@ +.\" Copyright (C) 2024 Tavian Barnes +.\" +.\" SPDX-License-Identifier: LGPL-2.0-or-later +.\" +.TH io_uring_try_setup_flags 3 "December 4, 2024" "liburing-2.9" "liburing Manual" +.SH NAME +io_uring_try_setup_flags \- check if the kernel supports some setup flags +.SH SYNOPSIS +.nf +.B #include +.PP +.BI "int io_uring_try_setup_flags(struct io_uring_params *" params "," +.BI " unsigned " flags ");" +.fi +.SH DESCRIPTION +.PP +The +.BR io_uring_try_setup_flags (3) +function checks whether the running kernel supports a combination of +.B IORING_SETUP_* +flags. On success, +.BR io_uring_try_setup_flags (3) +performs +.PP +.nf +.RS +.I params\->flags |= flags; +.RE +.fi +.PP +and returns 0. On failure, +.I params +remains unchanged and +.B \-errno +is returned. +.SH RETURN VALUE +.BR io_uring_try_setup_flags (3) +returns 0 on success and +.BR -errno +on failure. +.SH ERRORS +.TP +.B EINVAL +The flag combination is invalid. +.SH SEE ALSO +.BR io_uring_setup (2), +.BR io_uring_queue_init (3) diff --git a/src/include/liburing.h b/src/include/liburing.h index 627fc47cc..6182094d6 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -158,6 +158,8 @@ IOURINGINLINE int io_uring_opcode_supported(const struct io_uring_probe *p, return (p->ops[op].flags & IO_URING_OP_SUPPORTED) != 0; } +int io_uring_try_setup_flags(struct io_uring_params *p, unsigned flags); + int io_uring_queue_init_mem(unsigned entries, struct io_uring *ring, struct io_uring_params *p, void *buf, size_t buf_size); diff --git a/src/liburing.map b/src/liburing.map index 9f7b21171..f7d450661 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -110,4 +110,5 @@ LIBURING_2.9 { io_uring_submit_and_wait_reg; io_uring_clone_buffers_offset; io_uring_register_region; + io_uring_try_setup_flags; } LIBURING_2.8; diff --git a/src/setup.c b/src/setup.c index d4694f50c..76d7db097 100644 --- a/src/setup.c +++ b/src/setup.c @@ -496,6 +496,23 @@ __cold void io_uring_free_probe(struct io_uring_probe *probe) free(probe); } +int io_uring_try_setup_flags(struct io_uring_params *p, unsigned flags) +{ + struct io_uring ring; + unsigned saved = p->flags; + int r; + + p->flags |= flags; + r = io_uring_queue_init_params(2, &ring, p); + if (r == 0) { + io_uring_queue_exit(&ring); + } else { + p->flags = saved; + } + + return r; +} + static size_t npages(size_t size, long page_size) { size--; diff --git a/test/Makefile b/test/Makefile index 3fc4a4230..88ad9a993 100644 --- a/test/Makefile +++ b/test/Makefile @@ -228,6 +228,7 @@ test_srcs := \ timeout.c \ timeout-new.c \ truncate.c \ + try-setup-flags.c \ tty-write-dpoll.c \ unlink.c \ uring_cmd_ublk.c \ diff --git a/test/try-setup-flags.c b/test/try-setup-flags.c new file mode 100644 index 000000000..53deae06e --- /dev/null +++ b/test/try-setup-flags.c @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: test io_uring_try_setup_flags() + * + */ +#include + +#include "liburing.h" +#include "helpers.h" + +int main(int argc, char *argv[]) +{ + struct io_uring_params params = {0}; + int ret; + + if (argc > 1) + return T_EXIT_SKIP; + + ret = io_uring_try_setup_flags(¶ms, IORING_SETUP_CLAMP); + if (ret != 0) { + fprintf(stderr, "IORING_SETUP_CLAMP failed\n"); + return T_EXIT_FAIL; + } + + /* should fail without IORING_SETUP_SINGLE_ISSUER */ + ret = io_uring_try_setup_flags(¶ms, IORING_SETUP_DEFER_TASKRUN); + if (ret != -EINVAL) { + fprintf(stderr, "IORING_SETUP_DEFER_TASKRUN failed\n"); + return T_EXIT_FAIL; + } + + return T_EXIT_PASS; +}