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 03/10] io_uring/zcrx: switch to pcpu refcounting
Date: Sat, 11 Jul 2026 11:48:32 +0100 [thread overview]
Message-ID: <3a990539e205fab5bafb5185471e73b308647a2f.1783614400.git.asml.silence@gmail.com> (raw)
In-Reply-To: <cover.1783614400.git.asml.silence@gmail.com>
We'll need a faster way to pin a zcrx instance for get_netmem(). Switch
refcounting to percpu_ref.
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
io_uring/zcrx.c | 36 ++++++++++++++++++++++++++++++------
io_uring/zcrx.h | 4 +++-
2 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index ef82e064e796..f501fc75d7b6 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -32,6 +32,8 @@
#define IO_DMA_ATTR (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
+static void ifq_pcpu_release(struct percpu_ref *ref);
+
static inline struct io_zcrx_ifq *io_pp_to_ifq(struct page_pool *pp)
{
return pp->mp_priv;
@@ -535,16 +537,22 @@ static int io_zcrx_create_area(struct io_zcrx_ifq *ifq,
static struct io_zcrx_ifq *io_zcrx_ifq_alloc(struct io_ring_ctx *ctx)
{
struct io_zcrx_ifq *ifq;
+ int ret;
ifq = kzalloc_obj(*ifq);
if (!ifq)
return NULL;
+ ret = percpu_ref_init(&ifq->refs, ifq_pcpu_release, 0, GFP_KERNEL_ACCOUNT);
+ if (ret) {
+ kfree(ifq);
+ return NULL;
+ }
+ percpu_ref_get(&ifq->refs);
ifq->if_rxq = -1;
spin_lock_init(&ifq->ctx_lock);
spin_lock_init(&ifq->rq.lock);
mutex_init(&ifq->pp_lock);
- refcount_set(&ifq->refs, 1);
refcount_set(&ifq->user_refs, 1);
return ifq;
}
@@ -606,13 +614,28 @@ static void io_zcrx_ifq_free(struct io_zcrx_ifq *ifq)
io_free_rbuf_ring(ifq);
free_uid(ifq->user);
mutex_destroy(&ifq->pp_lock);
+ percpu_ref_exit(&ifq->refs);
kfree(ifq);
}
+static inline void zcrx_release_work(struct work_struct *work)
+{
+ struct io_zcrx_ifq *ifq = container_of(work, struct io_zcrx_ifq, release_work);
+
+ io_zcrx_ifq_free(ifq);
+}
+
+static void ifq_pcpu_release(struct percpu_ref *ref)
+{
+ struct io_zcrx_ifq *ifq = container_of(ref, struct io_zcrx_ifq, refs);
+
+ INIT_WORK(&ifq->release_work, zcrx_release_work);
+ queue_work(system_wq, &ifq->release_work);
+}
+
static void io_put_zcrx_ifq(struct io_zcrx_ifq *ifq)
{
- if (refcount_dec_and_test(&ifq->refs))
- io_zcrx_ifq_free(ifq);
+ percpu_ref_put(&ifq->refs);
}
static void io_zcrx_return_niov_freelist(struct net_iov *niov)
@@ -683,6 +706,7 @@ static void zcrx_unregister_user(struct io_zcrx_ifq *ifq, struct io_ring_ctx *ct
if (refcount_dec_and_test(&ifq->user_refs)) {
io_close_queue(ifq);
io_zcrx_scrub(ifq);
+ percpu_ref_kill(&ifq->refs);
}
}
@@ -727,7 +751,7 @@ static int zcrx_export(struct io_ring_ctx *ctx, struct io_zcrx_ifq *ifq,
if (!mem_is_zero(ce, sizeof(*ce)))
return -EINVAL;
- refcount_inc(&ifq->refs);
+ percpu_ref_get(&ifq->refs);
refcount_inc(&ifq->user_refs);
file = anon_inode_create_getfile("[zcrx]", &zcrx_box_fops,
@@ -784,7 +808,7 @@ static int import_zcrx(struct io_ring_ctx *ctx,
return -EBADF;
ifq = file->private_data;
- refcount_inc(&ifq->refs);
+ percpu_ref_get(&ifq->refs);
refcount_inc(&ifq->user_refs);
scoped_guard(mutex, &ctx->mmap_lock) {
@@ -1285,7 +1309,7 @@ static int io_pp_zc_init(struct page_pool *pp)
if (pp->p.dma_dir != DMA_FROM_DEVICE)
return -EOPNOTSUPP;
- refcount_inc(&ifq->refs);
+ percpu_ref_get(&ifq->refs);
return 0;
}
diff --git a/io_uring/zcrx.h b/io_uring/zcrx.h
index fa00900e479e..205b9b40c74d 100644
--- a/io_uring/zcrx.h
+++ b/io_uring/zcrx.h
@@ -7,6 +7,7 @@
#include <linux/socket.h>
#include <net/page_pool/types.h>
#include <net/net_trackers.h>
+#include <linux/percpu-refcount.h>
#define ZCRX_SUPPORTED_REG_FLAGS (ZCRX_REG_IMPORT | ZCRX_REG_NODEV)
#define ZCRX_FEATURES (ZCRX_FEATURE_RX_PAGE_SIZE |\
@@ -64,7 +65,7 @@ struct io_zcrx_ifq {
struct device *dev;
struct net_device *netdev;
netdevice_tracker netdev_tracker;
- refcount_t refs;
+ struct percpu_ref refs;
/* counts userspace facing users like io_uring */
refcount_t user_refs;
@@ -81,6 +82,7 @@ struct io_zcrx_ifq {
u32 fired_notifs;
u64 notif_data;
struct zcrx_notif_stats *notif_stats;
+ struct work_struct release_work;
};
#if defined(CONFIG_IO_URING_ZCRX)
--
2.54.0
next prev 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 ` Pavel Begunkov [this message]
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 ` [RFC 09/10] io_uring/rsrc: add zcrx backed registered buffers Pavel Begunkov
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=3a990539e205fab5bafb5185471e73b308647a2f.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