drivers/net/wireguard/allowedips.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
From: Fushuai Wang <wangfushuai@baidu.com>
Replace call_rcu() + kmem_cache_free() with kfree_rcu() to simplify
the code and reduce function size.
Signed-off-by: Fushuai Wang <wangfushuai@baidu.com>
---
drivers/net/wireguard/allowedips.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c
index 09f7fcd7da78..5ece9acad64d 100644
--- a/drivers/net/wireguard/allowedips.c
+++ b/drivers/net/wireguard/allowedips.c
@@ -48,11 +48,6 @@ static void push_rcu(struct allowedips_node **stack,
}
}
-static void node_free_rcu(struct rcu_head *rcu)
-{
- kmem_cache_free(node_cache, container_of(rcu, struct allowedips_node, rcu));
-}
-
static void root_free_rcu(struct rcu_head *rcu)
{
struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = {
@@ -271,13 +266,13 @@ static void remove_node(struct allowedips_node *node, struct mutex *lock)
if (free_parent)
child = rcu_dereference_protected(parent->bit[!(node->parent_bit_packed & 1)],
lockdep_is_held(lock));
- call_rcu(&node->rcu, node_free_rcu);
+ kfree_rcu(node, rcu);
if (!free_parent)
return;
if (child)
child->parent_bit_packed = parent->parent_bit_packed;
*(struct allowedips_node **)(parent->parent_bit_packed & ~3UL) = child;
- call_rcu(&parent->rcu, node_free_rcu);
+ kfree_rcu(parent, rcu);
}
static int remove(struct allowedips_node __rcu **trie, u8 bits, const u8 *key,
--
2.36.1
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least pausible.
For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
---
wireguard: allowedips: Use kfree_rcu() instead of call_rcu()
This commit replaces call_rcu() with a custom kmem_cache_free() callback
with kfree_rcu() to simplify the code. The change affects how nodes are
freed in the remove_node() function.
> diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c
> index 09f7fcd7da78..5ece9acad64d 100644
> --- a/drivers/net/wireguard/allowedips.c
> +++ b/drivers/net/wireguard/allowedips.c
> @@ -48,11 +48,6 @@ static void push_rcu(struct allowedips_node **stack,
> }
> }
>
> -static void node_free_rcu(struct rcu_head *rcu)
> -{
> - kmem_cache_free(node_cache, container_of(rcu, struct allowedips_node, rcu));
> -}
> -
[ ... ]
> @@ -271,13 +266,13 @@ static void remove_node(struct allowedips_node *node, struct mutex *lock)
> if (free_parent)
> child = rcu_dereference_protected(parent->bit[!(node->parent_bit_packed & 1)],
> lockdep_is_held(lock));
> - call_rcu(&node->rcu, node_free_rcu);
> + kfree_rcu(node, rcu);
Does wg_allowedips_slab_uninit() need to be updated to use
kvfree_rcu_barrier() instead of rcu_barrier()?
When CONFIG_KVFREE_RCU_BATCHED is enabled (the default), kfree_rcu()
uses a batched mechanism that queues work via queue_rcu_work(). The
rcu_barrier() call waits for RCU callbacks to complete, but these
callbacks only queue the actual free to a workqueue via rcu_work_rcufn().
The workqueue work that calls kvfree() may still be pending after
rcu_barrier() returns.
The existing cleanup path is:
wg_allowedips_slab_uninit() -> rcu_barrier() -> kmem_cache_destroy()
With kfree_rcu(), this sequence could destroy the slab cache while
kfree_rcu_work() still has pending frees queued. The proper barrier for
kfree_rcu() is kvfree_rcu_barrier() which also calls flush_rcu_work()
on all pending batches.
> if (!free_parent)
> return;
> if (child)
> child->parent_bit_packed = parent->parent_bit_packed;
> *(struct allowedips_node **)(parent->parent_bit_packed & ~3UL) = child;
> - call_rcu(&parent->rcu, node_free_rcu);
> + kfree_rcu(parent, rcu);
> }
--
pw-bot: cr
Hi Jakub,
Minor side note: I noticed a small typo in the AI review foreword. I
assume this is part of a template:
On Wed, Jan 14, 2026 at 07:32:37PM -0800, Jakub Kicinski wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least pausible.
^~~~~~~~
pausible -> plausible
Best,
Petr
On Thu, 15 Jan 2026 09:12:13 +0100 Petr Vaněk wrote: > Hi Jakub, > > Minor side note: I noticed a small typo in the AI review foreword. I > assume this is part of a template: > > On Wed, Jan 14, 2026 at 07:32:37PM -0800, Jakub Kicinski wrote: > > This is an AI-generated review of your patch. The human sending this > > email has considered the AI review valid, or at least pausible. > ^~~~~~~~ > pausible -> plausible Ah, thanks :)
>> @@ -271,13 +266,13 @@ static void remove_node(struct allowedips_node *node, struct mutex *lock)
>> if (free_parent)
>> child = rcu_dereference_protected(parent->bit[!(node->parent_bit_packed & 1)],
>> lockdep_is_held(lock));
>> - call_rcu(&node->rcu, node_free_rcu);
>> + kfree_rcu(node, rcu);
>
> Does wg_allowedips_slab_uninit() need to be updated to use
> kvfree_rcu_barrier() instead of rcu_barrier()?
>
> When CONFIG_KVFREE_RCU_BATCHED is enabled (the default), kfree_rcu()
> uses a batched mechanism that queues work via queue_rcu_work(). The
> rcu_barrier() call waits for RCU callbacks to complete, but these
> callbacks only queue the actual free to a workqueue via rcu_work_rcufn().
> The workqueue work that calls kvfree() may still be pending after
> rcu_barrier() returns.
>
> The existing cleanup path is:
> wg_allowedips_slab_uninit() -> rcu_barrier() -> kmem_cache_destroy()
>
> With kfree_rcu(), this sequence could destroy the slab cache while
> kfree_rcu_work() still has pending frees queued. The proper barrier for
> kfree_rcu() is kvfree_rcu_barrier() which also calls flush_rcu_work()
> on all pending batches.
We do not need to add an explict kvfree_rcu_barrier(), becasue the commit
6c6c47b063b5 ("mm, slab: call kvfree_rcu_barrier() from kmem_cache_destroy()")
already does it.
---
Regards,
WANG
On Thu, Jan 15, 2026 at 6:12 AM Fushuai Wang <fushuai.wang@linux.dev> wrote:
>
> >> @@ -271,13 +266,13 @@ static void remove_node(struct allowedips_node *node, struct mutex *lock)
> >> if (free_parent)
> >> child = rcu_dereference_protected(parent->bit[!(node->parent_bit_packed & 1)],
> >> lockdep_is_held(lock));
> >> - call_rcu(&node->rcu, node_free_rcu);
> >> + kfree_rcu(node, rcu);
> >
> > Does wg_allowedips_slab_uninit() need to be updated to use
> > kvfree_rcu_barrier() instead of rcu_barrier()?
> >
> > When CONFIG_KVFREE_RCU_BATCHED is enabled (the default), kfree_rcu()
> > uses a batched mechanism that queues work via queue_rcu_work(). The
> > rcu_barrier() call waits for RCU callbacks to complete, but these
> > callbacks only queue the actual free to a workqueue via rcu_work_rcufn().
> > The workqueue work that calls kvfree() may still be pending after
> > rcu_barrier() returns.
> >
> > The existing cleanup path is:
> > wg_allowedips_slab_uninit() -> rcu_barrier() -> kmem_cache_destroy()
> >
> > With kfree_rcu(), this sequence could destroy the slab cache while
> > kfree_rcu_work() still has pending frees queued. The proper barrier for
> > kfree_rcu() is kvfree_rcu_barrier() which also calls flush_rcu_work()
> > on all pending batches.
>
> We do not need to add an explict kvfree_rcu_barrier(), becasue the commit
> 6c6c47b063b5 ("mm, slab: call kvfree_rcu_barrier() from kmem_cache_destroy()")
> already does it.
It was doing it, but got replaced recently with a plain rcu_barrier()
commit 0f35040de59371ad542b915d7b91176c9910dadc
Author: Harry Yoo <harry.yoo@oracle.com>
Date: Mon Dec 8 00:41:47 2025 +0900
mm/slab: introduce kvfree_rcu_barrier_on_cache() for cache destruction
We would like explicit +2 from mm _and_ rcu experts on this wireguard patch.
Thank you.
Hi Eric,
On Thu, Jan 15, 2026 at 10:15 AM Eric Dumazet <edumazet@google.com> wrote:
> > > The existing cleanup path is:
> > > wg_allowedips_slab_uninit() -> rcu_barrier() -> kmem_cache_destroy()
> > >
> > > With kfree_rcu(), this sequence could destroy the slab cache while
> > > kfree_rcu_work() still has pending frees queued. The proper barrier for
> > > kfree_rcu() is kvfree_rcu_barrier() which also calls flush_rcu_work()
> > > on all pending batches.
> >
> > We do not need to add an explict kvfree_rcu_barrier(), becasue the commit
> > 6c6c47b063b5 ("mm, slab: call kvfree_rcu_barrier() from kmem_cache_destroy()")
> > already does it.
>
> It was doing it, but got replaced recently with a plain rcu_barrier()
>
> commit 0f35040de59371ad542b915d7b91176c9910dadc
> Author: Harry Yoo <harry.yoo@oracle.com>
> Date: Mon Dec 8 00:41:47 2025 +0900
>
> mm/slab: introduce kvfree_rcu_barrier_on_cache() for cache destruction
>
> We would like explicit +2 from mm _and_ rcu experts on this wireguard patch.
I'll take this through the wireguard tree.
But just a question on your comment, "It was doing it, but got
replaced recently with a plain rcu_barrier()". Are you suggesting I
need a kvfree_rcu_barrier() instead? The latest net-next has a
kvfree_rcu_barrier_on_cache() called from kmem_cache_destroy()
still... But are you suggesting I add this anyway?
diff --git a/drivers/net/wireguard/allowedips.c
b/drivers/net/wireguard/allowedips.c
index 5ece9acad64d..aee39a0303b0 100644
--- a/drivers/net/wireguard/allowedips.c
+++ b/drivers/net/wireguard/allowedips.c
@@ -417,7 +417,7 @@ int __init wg_allowedips_slab_init(void)
void wg_allowedips_slab_uninit(void)
{
- rcu_barrier();
+ kvfree_rcu_barrier();
kmem_cache_destroy(node_cache);
}
Let me know.
Thanks,
Jason
On Thu, Jan 15, 2026 at 3:33 PM Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>
> Hi Eric,
>
> On Thu, Jan 15, 2026 at 10:15 AM Eric Dumazet <edumazet@google.com> wrote:
> > > > The existing cleanup path is:
> > > > wg_allowedips_slab_uninit() -> rcu_barrier() -> kmem_cache_destroy()
> > > >
> > > > With kfree_rcu(), this sequence could destroy the slab cache while
> > > > kfree_rcu_work() still has pending frees queued. The proper barrier for
> > > > kfree_rcu() is kvfree_rcu_barrier() which also calls flush_rcu_work()
> > > > on all pending batches.
> > >
> > > We do not need to add an explict kvfree_rcu_barrier(), becasue the commit
> > > 6c6c47b063b5 ("mm, slab: call kvfree_rcu_barrier() from kmem_cache_destroy()")
> > > already does it.
> >
> > It was doing it, but got replaced recently with a plain rcu_barrier()
> >
> > commit 0f35040de59371ad542b915d7b91176c9910dadc
> > Author: Harry Yoo <harry.yoo@oracle.com>
> > Date: Mon Dec 8 00:41:47 2025 +0900
> >
> > mm/slab: introduce kvfree_rcu_barrier_on_cache() for cache destruction
> >
> > We would like explicit +2 from mm _and_ rcu experts on this wireguard patch.
>
> I'll take this through the wireguard tree.
>
> But just a question on your comment, "It was doing it, but got
> replaced recently with a plain rcu_barrier()". Are you suggesting I
> need a kvfree_rcu_barrier() instead? The latest net-next has a
> kvfree_rcu_barrier_on_cache() called from kmem_cache_destroy()
> still... But are you suggesting I add this anyway?
>
> diff --git a/drivers/net/wireguard/allowedips.c
> b/drivers/net/wireguard/allowedips.c
> index 5ece9acad64d..aee39a0303b0 100644
> --- a/drivers/net/wireguard/allowedips.c
> +++ b/drivers/net/wireguard/allowedips.c
> @@ -417,7 +417,7 @@ int __init wg_allowedips_slab_init(void)
>
> void wg_allowedips_slab_uninit(void)
> {
> - rcu_barrier();
> + kvfree_rcu_barrier();
It seems kmem_cache_destroy() should take care of needed barriers,
at least this is what is claimed. An rcu_barrier() or kvfree_rcu_barrier()
should not be needed in wg_allowedips_slab_uninit() ?
Probably boring/distracting, I do not expect anyone needing to unload
this module in a loop and expect this to be ultra fast ?
> kmem_cache_destroy(node_cache);
> }
>
> Let me know.
>
> Thanks,
> Jason
On Thu, Jan 15, 2026 at 03:40:17PM +0100, Eric Dumazet wrote:
> On Thu, Jan 15, 2026 at 3:33 PM Jason A. Donenfeld <Jason@zx2c4.com> wrote:
> >
> > Hi Eric,
> >
> > On Thu, Jan 15, 2026 at 10:15 AM Eric Dumazet <edumazet@google.com> wrote:
> > > > > The existing cleanup path is:
> > > > > wg_allowedips_slab_uninit() -> rcu_barrier() -> kmem_cache_destroy()
> > > > >
> > > > > With kfree_rcu(), this sequence could destroy the slab cache while
> > > > > kfree_rcu_work() still has pending frees queued. The proper barrier for
> > > > > kfree_rcu() is kvfree_rcu_barrier() which also calls flush_rcu_work()
> > > > > on all pending batches.
> > > >
> > > > We do not need to add an explict kvfree_rcu_barrier(), becasue the commit
> > > > 6c6c47b063b5 ("mm, slab: call kvfree_rcu_barrier() from kmem_cache_destroy()")
> > > > already does it.
> > >
> > > It was doing it, but got replaced recently with a plain rcu_barrier()
> > >
> > > commit 0f35040de59371ad542b915d7b91176c9910dadc
> > > Author: Harry Yoo <harry.yoo@oracle.com>
> > > Date: Mon Dec 8 00:41:47 2025 +0900
> > >
> > > mm/slab: introduce kvfree_rcu_barrier_on_cache() for cache destruction
> > >
> > > We would like explicit +2 from mm _and_ rcu experts on this wireguard patch.
> >
> > I'll take this through the wireguard tree.
> >
> > But just a question on your comment, "It was doing it, but got
> > replaced recently with a plain rcu_barrier()". Are you suggesting I
> > need a kvfree_rcu_barrier() instead? The latest net-next has a
> > kvfree_rcu_barrier_on_cache() called from kmem_cache_destroy()
> > still... But are you suggesting I add this anyway?
> >
> > diff --git a/drivers/net/wireguard/allowedips.c
> > b/drivers/net/wireguard/allowedips.c
> > index 5ece9acad64d..aee39a0303b0 100644
> > --- a/drivers/net/wireguard/allowedips.c
> > +++ b/drivers/net/wireguard/allowedips.c
> > @@ -417,7 +417,7 @@ int __init wg_allowedips_slab_init(void)
> >
> > void wg_allowedips_slab_uninit(void)
> > {
> > - rcu_barrier();
> > + kvfree_rcu_barrier();
>
> It seems kmem_cache_destroy() should take care of needed barriers,
> at least this is what is claimed. An rcu_barrier() or kvfree_rcu_barrier()
> should not be needed in wg_allowedips_slab_uninit() ?
>
> Probably boring/distracting, I do not expect anyone needing to unload
> this module in a loop and expect this to be ultra fast ?
Okay so I'll take this patch, and perhaps amend to it the _removal_ of
that rcu_barrier()?
Jason
On Mon, Jan 12, 2026 at 09:06:33PM +0800, Fushuai Wang wrote: > From: Fushuai Wang <wangfushuai@baidu.com> > > Replace call_rcu() + kmem_cache_free() with kfree_rcu() to simplify > the code and reduce function size. > > Signed-off-by: Fushuai Wang <wangfushuai@baidu.com> Thanks, I believe this address prior review and moreover I agree with the approach taken here. Reviewed-by: Simon Horman <horms@kernel.org> ...
© 2016 - 2026 Red Hat, Inc.