public inbox for io-uring@vger.kernel.org
 help / color / mirror / Atom feed
From: Pavel Begunkov <asml.silence@gmail.com>
To: netdev@vger.kernel.org
Cc: "David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>,
	Jamal Hadi Salim <jhs@mojatatu.com>,
	io-uring@vger.kernel.org, asml.silence@gmail.com
Subject: [RFC 09/10] io_uring/rsrc: add zcrx backed registered buffers
Date: Sat, 11 Jul 2026 11:48:38 +0100	[thread overview]
Message-ID: <cd188445aee6477a09e0908f090106517becc7c0.1783614400.git.asml.silence@gmail.com> (raw)
In-Reply-To: <cover.1783614400.git.asml.silence@gmail.com>

Allow the user to take an existing zcrx instance and wrap it into a
registered buffer that will later be used for tx path. We don't want
leaking zcrx instances to other rings, so mark the buffer uncloneable.
The buffer also doesn't ping zcrx but relies on that zcrx can't be
unregistered.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 include/uapi/linux/io_uring.h |  1 +
 io_uring/rsrc.c               | 91 ++++++++++++++++++++++++++++++++++-
 io_uring/rsrc.h               |  5 ++
 3 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 98b259901185..4e86ad3ee977 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -810,6 +810,7 @@ enum io_uring_rsrc_reg_flags {
 enum io_uring_regbuf_type {
 	IO_REGBUF_TYPE_EMPTY,
 	IO_REGBUF_TYPE_UADDR,
+	IO_REGBUF_TYPE_ZCRX,
 
 	__IO_REGBUF_TYPE_MAX,
 };
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 05877b4c0ee5..583e51748c62 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -19,6 +19,7 @@
 #include "rsrc.h"
 #include "memmap.h"
 #include "register.h"
+#include "zcrx.h"
 
 struct io_rsrc_update {
 	struct file			*file;
@@ -881,6 +882,53 @@ bool io_check_coalesce_buffer(struct page **page_array, int nr_pages,
 	return true;
 }
 
+static void io_release_zcrx(void *priv)
+{
+}
+
+static struct io_rsrc_node *io_register_zcrx_buffer(struct io_ring_ctx *ctx,
+						    struct io_uring_regbuf_desc *desc)
+{
+	struct io_mapped_ubuf *imu = NULL;
+	struct io_rsrc_node *node;
+	struct io_zcrx_ifq *zcrx;
+	u32 ifq_idx = desc->uaddr;
+
+
+	if (ifq_idx != desc->uaddr)
+		return ERR_PTR(-EINVAL);
+	node = io_rsrc_node_alloc(ctx, IORING_RSRC_BUFFER);
+	if (!node)
+		return ERR_PTR(-ENOMEM);
+	zcrx = xa_load(&ctx->zcrx_ctxs, ifq_idx);
+	if (!zcrx)
+		return ERR_PTR(-EINVAL);
+
+	WARN_ON_ONCE(!zcrx->area);
+
+	if (zcrx->area->mem.size != desc->size)
+		return ERR_PTR(-EINVAL);
+
+	imu = io_alloc_imu(ctx, 0);
+	if (!imu) {
+		io_cache_free(&ctx->node_cache, node);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	imu->nr_bvecs = 0;
+	/* store original address for later verification */
+	imu->ubuf = 0;
+	imu->len = desc->size;
+	imu->folio_shift = PAGE_SHIFT;
+	imu->release = io_release_zcrx;
+	imu->priv = zcrx;
+	imu->flags = IO_REGBUF_F_UNCLONEABLE | IO_REGBUF_F_ZCRX;
+	imu->dir = IO_IMU_SOURCE;
+	refcount_set(&imu->refs, 1);
+	node->buf = imu;
+	return node;
+}
+
 static struct io_rsrc_node *io_sqe_buffer_register(struct io_ring_ctx *ctx,
 						   struct io_uring_regbuf_desc *desc)
 {
@@ -898,6 +946,8 @@ static struct io_rsrc_node *io_sqe_buffer_register(struct io_ring_ctx *ctx,
 		return ERR_PTR(-EINVAL);
 	if (!mem_is_zero(&desc->__resv, sizeof(desc->__resv)))
 		return ERR_PTR(-EINVAL);
+	if (desc->type == IO_REGBUF_TYPE_ZCRX)
+		return io_register_zcrx_buffer(ctx, desc);
 
 	if (desc->type == IO_REGBUF_TYPE_EMPTY) {
 		if (uaddr || size)
@@ -1170,9 +1220,17 @@ static int io_import_kbuf(int ddir, struct iov_iter *iter,
 	return 0;
 }
 
+static int io_import_from_zcrx(int ddir, struct iov_iter *iter,
+				struct io_mapped_ubuf *imu,
+				u64 buf_addr, size_t len)
+{
+	iov_iter_ubuf(iter, ddir, (void *)(unsigned long)buf_addr, len);
+	return 0;
+}
+
 static int io_import_fixed(int ddir, struct iov_iter *iter,
 			   struct io_mapped_ubuf *imu,
-			   u64 buf_addr, size_t len)
+			   u64 buf_addr, size_t len, unsigned import_flags)
 {
 	const struct bio_vec *bvec;
 	size_t folio_mask;
@@ -1185,6 +1243,13 @@ static int io_import_fixed(int ddir, struct iov_iter *iter,
 		return ret;
 	if (!(imu->dir & (1 << ddir)))
 		return -EFAULT;
+
+	if (imu->flags & IO_REGBUF_F_ZCRX) {
+		if (unlikely(!(import_flags & IO_REGBUF_IMPORT_ALLOW_ZCRX)))
+			return -EINVAL;
+		return io_import_from_zcrx(ddir, iter, imu, buf_addr, len);
+	}
+
 	if (unlikely(!len)) {
 		iov_iter_bvec(iter, ddir, NULL, 0, 0);
 		return 0;
@@ -1254,7 +1319,7 @@ int __io_import_reg_buf(struct io_kiocb *req, struct iov_iter *iter,
 	node = io_find_buf_node(req, issue_flags);
 	if (!node)
 		return -EFAULT;
-	return io_import_fixed(ddir, iter, node->buf, buf_addr, len);
+	return io_import_fixed(ddir, iter, node->buf, buf_addr, len, import_flags);
 }
 
 static int io_buffer_acct_cloned_hpages(struct io_ring_ctx *ctx,
@@ -1656,6 +1721,22 @@ static int io_kern_bvec_size(struct iovec *iov, unsigned nr_iovs,
 	return 0;
 }
 
+static int import_reg_vec_zcrx(int ddir, struct iov_iter *iter, struct iovec *iov,
+				unsigned nr_iovs)
+{
+	size_t size;
+	unsigned i;
+
+	for (i = 0; i < nr_iovs; i++) {
+		if (check_add_overflow(size, (size_t)iov[i].iov_len, &size))
+			return -EOVERFLOW;
+	}
+	if (size > MAX_RW_COUNT)
+		return -EINVAL;
+	iov_iter_init(iter, ddir, iov, nr_iovs, size);
+	return 0;
+}
+
 int __io_import_reg_vec(int ddir, struct iov_iter *iter,
 			struct io_kiocb *req, struct iou_vec *vec,
 			unsigned nr_iovs, unsigned issue_flags, unsigned import_flags)
@@ -1676,6 +1757,12 @@ int __io_import_reg_vec(int ddir, struct iov_iter *iter,
 	iovec_off = vec->nr - nr_iovs;
 	iov = vec->iovec + iovec_off;
 
+	if (imu->flags & IO_REGBUF_F_ZCRX) {
+		if (unlikely(!(import_flags & IO_REGBUF_IMPORT_ALLOW_ZCRX)))
+			return -EINVAL;
+		return import_reg_vec_zcrx(ddir, iter, iov, nr_iovs);
+	}
+
 	if (imu->flags & IO_REGBUF_F_KBUF) {
 		int ret = io_kern_bvec_size(iov, nr_iovs, imu, &nr_segs);
 
diff --git a/io_uring/rsrc.h b/io_uring/rsrc.h
index f12abaf63270..a44f7dfcd470 100644
--- a/io_uring/rsrc.h
+++ b/io_uring/rsrc.h
@@ -31,6 +31,11 @@ enum {
 enum {
 	IO_REGBUF_F_KBUF		= 1 << 0,
 	IO_REGBUF_F_UNCLONEABLE		= 1 << 1,
+	IO_REGBUF_F_ZCRX		= 1 << 2,
+};
+
+enum {
+	IO_REGBUF_IMPORT_ALLOW_ZCRX	= 1 << 0,
 };
 
 struct io_mapped_ubuf {
-- 
2.54.0


  parent reply	other threads:[~2026-07-11 10:49 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-11 10:48 [RFC 00/10] io_uring: prototype for device memory tx Pavel Begunkov
2026-07-11 10:48 ` [RFC 01/10] net: pass ubuf to custom sg_from_iter callbacks Pavel Begunkov
2026-07-11 10:48 ` [RFC 02/10] net: reject zcrx skbs to not registered devices Pavel Begunkov
2026-07-11 10:48 ` [RFC 03/10] io_uring/zcrx: switch to pcpu refcounting Pavel Begunkov
2026-07-11 10:48 ` [RFC 04/10] io_uring/zcrx: prepare areas to be exported for tx Pavel Begunkov
2026-07-11 10:48 ` [RFC 05/10] io_uring/rsrc: introduce buf registration structure Pavel Begunkov
2026-07-11 10:48 ` [RFC 06/10] io_uring/rsrc: extend buffer update Pavel Begunkov
2026-07-11 10:48 ` [RFC 07/10] io_uring/rsrc: add uncloneable regbuf flag Pavel Begunkov
2026-07-11 10:48 ` [RFC 08/10] io_uring/rsrc: add regbuf import flags Pavel Begunkov
2026-07-11 10:48 ` Pavel Begunkov [this message]
2026-07-11 10:48 ` [RFC 10/10] io_uring/net: implement device memory send Pavel Begunkov

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=cd188445aee6477a09e0908f090106517becc7c0.1783614400.git.asml.silence@gmail.com \
    --to=asml.silence@gmail.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=io-uring@vger.kernel.org \
    --cc=jhs@mojatatu.com \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /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