From: David Wei <dw@davidwei.uk>
To: io-uring@vger.kernel.org, netdev@vger.kernel.org
Cc: Jens Axboe <axboe@kernel.dk>, Pavel Begunkov <asml.silence@gmail.com>
Subject: [PATCH v2 3/5] io_uring/zcrx: share an ifq between rings
Date: Sat, 25 Oct 2025 12:15:02 -0700 [thread overview]
Message-ID: <20251025191504.3024224-4-dw@davidwei.uk> (raw)
In-Reply-To: <20251025191504.3024224-1-dw@davidwei.uk>
Add a way to share an ifq from a src ring that is real i.e. bound to a
HW RX queue with other rings. This is done by passing a new flag
IORING_ZCRX_IFQ_REG_PROXY in the registration struct
io_uring_zcrx_ifq_reg, alongside the fd of the src ring and the ifq id
to be proxied.
It is not permitted to proxy another proxy ifq; it must be a real ifq.
The proxy ifq has most fields zero initialised. The exception is
ifq->if_rxq, which is set to the same value as the src ifq. This is
because if_rxq will be used by the cleanup code to denote an ifq that
has been cleaned up but not yet freed.
To prevent the src ring or ifq from being cleaned up or freed while the
proxy exists, take the appropriate refs on the src ring (ctx->refs) and
src ifq (ifq->refs). The subsequent patch that adds cleaning up proxy
ifqs will discuss lifetimes in more detail.
Signed-off-by: David Wei <dw@davidwei.uk>
---
include/uapi/linux/io_uring.h | 4 ++
io_uring/zcrx.c | 72 ++++++++++++++++++++++++++++++++++-
io_uring/zcrx.h | 1 +
3 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 263bed13473e..10f6347b1725 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -1055,6 +1055,10 @@ struct io_uring_zcrx_area_reg {
__u64 __resv2[2];
};
+enum io_uring_zcrx_ifq_reg_flags {
+ IORING_ZCRX_IFQ_REG_PROXY = 1,
+};
+
/*
* Argument for IORING_REGISTER_ZCRX_IFQ
*/
diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index 22d759307c16..6b9066333fcf 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -22,10 +22,10 @@
#include <uapi/linux/io_uring.h>
#include "io_uring.h"
-#include "kbuf.h"
#include "memmap.h"
#include "zcrx.h"
#include "rsrc.h"
+#include "register.h"
#define IO_ZCRX_AREA_SUPPORTED_FLAGS (IORING_ZCRX_AREA_DMABUF)
@@ -541,6 +541,74 @@ struct io_mapped_region *io_zcrx_get_region(struct io_ring_ctx *ctx,
return ifq ? &ifq->region : NULL;
}
+static int io_proxy_zcrx_ifq(struct io_ring_ctx *ctx,
+ struct io_uring_zcrx_ifq_reg __user *arg,
+ struct io_uring_zcrx_ifq_reg *reg)
+{
+ struct io_zcrx_ifq *ifq, *src_ifq;
+ struct io_ring_ctx *src_ctx;
+ struct file *file;
+ int src_fd, ret;
+ u32 src_id, id;
+
+ src_fd = reg->if_idx;
+ src_id = reg->if_rxq;
+
+ file = io_uring_register_get_file(src_fd, false);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ src_ctx = file->private_data;
+ if (src_ctx == ctx)
+ return -EBADFD;
+
+ mutex_unlock(&ctx->uring_lock);
+ io_lock_two_rings(ctx, src_ctx);
+
+ ret = -EINVAL;
+ src_ifq = xa_load(&src_ctx->zcrx_ctxs, src_id);
+ if (!src_ifq || src_ifq->proxy)
+ goto err_unlock;
+
+ percpu_ref_get(&src_ctx->refs);
+ refcount_inc(&src_ifq->refs);
+
+ ifq = kzalloc(sizeof(*ifq), GFP_KERNEL);
+ ifq->proxy = src_ifq;
+ ifq->ctx = ctx;
+ ifq->if_rxq = src_ifq->if_rxq;
+
+ scoped_guard(mutex, &ctx->mmap_lock) {
+ ret = xa_alloc(&ctx->zcrx_ctxs, &id, NULL, xa_limit_31b, GFP_KERNEL);
+ if (ret)
+ goto err_free;
+
+ ret = -ENOMEM;
+ if (xa_store(&ctx->zcrx_ctxs, id, ifq, GFP_KERNEL)) {
+ xa_erase(&ctx->zcrx_ctxs, id);
+ goto err_free;
+ }
+ }
+
+ reg->zcrx_id = id;
+ if (copy_to_user(arg, reg, sizeof(*reg))) {
+ ret = -EFAULT;
+ goto err;
+ }
+ mutex_unlock(&src_ctx->uring_lock);
+ fput(file);
+ return 0;
+err:
+ scoped_guard(mutex, &ctx->mmap_lock)
+ xa_erase(&ctx->zcrx_ctxs, id);
+err_free:
+ kfree(ifq);
+err_unlock:
+ mutex_unlock(&src_ctx->uring_lock);
+ fput(file);
+ return ret;
+}
+
int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
struct io_uring_zcrx_ifq_reg __user *arg)
{
@@ -566,6 +634,8 @@ int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
return -EINVAL;
if (copy_from_user(®, arg, sizeof(reg)))
return -EFAULT;
+ if (reg.flags & IORING_ZCRX_IFQ_REG_PROXY)
+ return io_proxy_zcrx_ifq(ctx, arg, ®);
if (copy_from_user(&rd, u64_to_user_ptr(reg.region_ptr), sizeof(rd)))
return -EFAULT;
if (!mem_is_zero(®.__resv, sizeof(reg.__resv)) ||
diff --git a/io_uring/zcrx.h b/io_uring/zcrx.h
index 566d519cbaf6..0df956cb9592 100644
--- a/io_uring/zcrx.h
+++ b/io_uring/zcrx.h
@@ -62,6 +62,7 @@ struct io_zcrx_ifq {
struct io_mapped_region region;
refcount_t refs;
+ struct io_zcrx_ifq *proxy;
};
#if defined(CONFIG_IO_URING_ZCRX)
--
2.47.3
next prev parent reply other threads:[~2025-10-25 19:15 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-25 19:14 [PATCH v2 0/5] io_uring zcrx ifq sharing David Wei
2025-10-25 19:15 ` [PATCH v2 1/5] io_uring/rsrc: rename and export io_lock_two_rings() David Wei
2025-10-25 19:15 ` [PATCH v2 2/5] io_uring/zcrx: add refcount to struct io_zcrx_ifq David Wei
2025-10-25 23:37 ` Jens Axboe
2025-10-26 4:10 ` David Wei
2025-10-25 19:15 ` David Wei [this message]
2025-10-25 23:41 ` [PATCH v2 3/5] io_uring/zcrx: share an ifq between rings Jens Axboe
2025-10-26 4:12 ` David Wei
2025-10-26 13:16 ` Jens Axboe
2025-10-26 13:43 ` Jens Axboe
2025-10-26 15:06 ` David Wei
2025-10-25 19:15 ` [PATCH v2 4/5] io_uring/zcrx: redirect io_recvzc on proxy ifq to src ifq David Wei
2025-10-25 19:15 ` [PATCH v2 5/5] io_uring/zcrx: free proxy ifqs David Wei
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251025191504.3024224-4-dw@davidwei.uk \
--to=dw@davidwei.uk \
--cc=asml.silence@gmail.com \
--cc=axboe@kernel.dk \
--cc=io-uring@vger.kernel.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).