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 | 20 +++++++++++++++++--- include/uapi/linux/io_uring.h | 4 +++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 9f73586dcfb8..3dad12906db3 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -5673,7 +5673,7 @@ static int io_sq_offload_start(struct io_ring_ctx *ctx, { struct io_wq_data data; unsigned concurrency; - int ret; + int ret, id; init_waitqueue_head(&ctx->sqo_wait); mmgrab(current->mm); @@ -5724,13 +5724,23 @@ 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); + + id = 0; + if (ctx->flags & IORING_SETUP_ATTACH_WQ) { + id = p->id; + if (!id) { + ret = -EINVAL; + goto err; + } + } + ctx->io_wq = io_wq_create_id(concurrency, &data, id); 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); @@ -6554,7 +6564,11 @@ 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_ATTACH_WQ)) + return -EINVAL; + + /* id isn't valid without ATTACH_WQ being set */ + if (!(p.flags & IORING_SETUP_ATTACH_WQ) && p.id) 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 57d05cc5e271..f66e53c74a3d 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_ATTACH_WQ (1U << 5) /* attach to existing wq */ enum { IORING_OP_NOP, @@ -183,7 +184,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