An id field is added to io_uring_params, which always returns the ID of the io-wq backend that is associated with an io_uring context. If an 'id' is provided and IORING_SETUP_SHARED is set in the creation flags, then we attempt to attach to an existing io-wq instead of setting up a new one. This allows creation of "sibling" io_urings, where we prefer to keep the SQ/CQ private, but want to share the async backend to minimize the amount of overhead associated with having multiple rings that belong to the same backend. Signed-off-by: Jens Axboe <axboe@xxxxxxxxx> --- fs/io_uring.c | 9 +++++++-- include/uapi/linux/io_uring.h | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 25f29ef81698..857cdf3f5ff6 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -5796,13 +5796,18 @@ static int io_sq_offload_start(struct io_ring_ctx *ctx, /* Do QD, or 4 * CPUS, whatever is smallest */ concurrency = min(ctx->sq_entries, 4 * num_online_cpus()); - ctx->io_wq = io_wq_create(concurrency, &data); + + if (ctx->flags & IORING_SETUP_SHARED) + ctx->io_wq = io_wq_create_id(concurrency, &data, p->id); + else + ctx->io_wq = io_wq_create(concurrency, &data); if (IS_ERR(ctx->io_wq)) { ret = PTR_ERR(ctx->io_wq); ctx->io_wq = NULL; goto err; } + p->id = io_wq_id(ctx->io_wq); return 0; err: io_finish_async(ctx); @@ -6626,7 +6631,7 @@ static long io_uring_setup(u32 entries, struct io_uring_params __user *params) if (p.flags & ~(IORING_SETUP_IOPOLL | IORING_SETUP_SQPOLL | IORING_SETUP_SQ_AFF | IORING_SETUP_CQSIZE | - IORING_SETUP_CLAMP)) + IORING_SETUP_CLAMP | IORING_SETUP_SHARED)) return -EINVAL; ret = io_uring_create(entries, &p); diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h index cffa6fd33827..c74681d30e92 100644 --- a/include/uapi/linux/io_uring.h +++ b/include/uapi/linux/io_uring.h @@ -75,6 +75,7 @@ enum { #define IORING_SETUP_SQ_AFF (1U << 2) /* sq_thread_cpu is valid */ #define IORING_SETUP_CQSIZE (1U << 3) /* app defines CQ size */ #define IORING_SETUP_CLAMP (1U << 4) /* clamp SQ/CQ ring sizes */ +#define IORING_SETUP_SHARED (1U << 5) /* share workqueue */ enum { IORING_OP_NOP, @@ -184,7 +185,8 @@ struct io_uring_params { __u32 sq_thread_cpu; __u32 sq_thread_idle; __u32 features; - __u32 resv[4]; + __u32 id; + __u32 resv[3]; struct io_sqring_offsets sq_off; struct io_cqring_offsets cq_off; }; -- 2.25.0