* [PATCH v1] vxcan: Support per-netns device unregistration.
@ 2026-07-12 21:21 Kuniyuki Iwashima
2026-07-12 21:34 ` sashiko-bot
0 siblings, 1 reply; 4+ messages in thread
From: Kuniyuki Iwashima @ 2026-07-12 21:21 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol
Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, linux-can
Currently, vxcan_dellink() unregisters both local and peer devices
synchronously under RTNL.
Once RTNL is removed, it can be called concurrently from different
netns.
Let's use xchg() and unregister_netdevice_queue_net() to support
per-netns device unregistration.
This way, each device is queued for destruction only once by
the winner of the race.
Note that the extra netdev_hold() ensures that @peer obtained by
the first xchg() is not freed during the subsequent access to
netdev_priv(peer). The 2nd xchg() overwrites @dev to balance
the refcount.
Tested:
1. Create two vxcan pairs (vxcan1-2, vxcan3-4) between two netns
(ns1 & ns2).
# ip netns add ns1
# ip netns add ns2
# ip -n ns1 link add vxcan1 type vxcan peer vxcan2 netns ns2
# ip -n ns1 link add vxcan3 type vxcan peer vxcan4 netns ns2
2. Run bpftrace to check if the same process does NOT
unregister the paired vxcan devices
# bpftrace -e '#include <linux/netdevice.h>
kprobe:free_netdev {
$dev = (struct net_device *)arg0;
printf("PID: %d | DEV: %s%s\n", pid, $dev->name, kstack());
}'
3. Remove vxcan2 in ns2 and check bpftrace output
# ip -n ns2 link del vxcan2
PID: 1524 | DEV: vxcan2
free_netdev+5
netdev_run_todo+4798
rtnl_dellink+1507
rtnetlink_rcv_msg+1791
netlink_rcv_skb+504
...
PID: 453 | DEV: vxcan1
free_netdev+5
netdev_run_todo+4798
process_scheduled_works+2538
worker_thread+1906
kthread+806
ret_from_fork+805
ret_from_fork_asm+17
4. Remove ns2 (thus vxcan4) and check bpftrace output
# ip netns del ns2
PID: 12 | DEV: vxcan4
free_netdev+5
netdev_run_todo+4798
default_device_exit_batch+2271
ops_undo_list+993
cleanup_net+1122
process_scheduled_works+2538
worker_thread+1906
kthread+806
ret_from_fork+805
ret_from_fork_asm+17
...
PID: 462 | DEV: vxcan3
free_netdev+5
netdev_run_todo+4798
process_scheduled_works+2538
worker_thread+1906
kthread+806
ret_from_fork+805
ret_from_fork_asm+17
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
This mirros commit d7fda2c776b2 ("veth: Support per-netns device
unregistration.").
The patch is based on net-next.git because it seems both main/master
of linux-can.git and linux-can-next.git are not synced with net-next.
71ac90cca6d8 is needed to verify the test output.
---
drivers/net/can/vxcan.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index e882250180ef..b7efed1226d8 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -33,6 +33,7 @@ MODULE_ALIAS_RTNL_LINK(DRV_NAME);
struct vxcan_priv {
struct net_device __rcu *peer;
+ netdevice_tracker peer_tracker;
};
static netdev_tx_t vxcan_xmit(struct sk_buff *oskb, struct net_device *dev)
@@ -268,9 +269,11 @@ static int vxcan_newlink(struct net_device *dev,
/* cross link the device pair */
priv = netdev_priv(dev);
rcu_assign_pointer(priv->peer, peer);
+ netdev_hold(peer, &priv->peer_tracker, GFP_KERNEL);
priv = netdev_priv(peer);
rcu_assign_pointer(priv->peer, dev);
+ netdev_hold(dev, &priv->peer_tracker, GFP_KERNEL);
return 0;
@@ -281,24 +284,25 @@ static int vxcan_newlink(struct net_device *dev,
static void vxcan_dellink(struct net_device *dev, struct list_head *head)
{
+ netdevice_tracker *peer_tracker;
struct vxcan_priv *priv;
struct net_device *peer;
priv = netdev_priv(dev);
- peer = rtnl_dereference(priv->peer);
+ peer_tracker = &priv->peer_tracker;
+ peer = unrcu_pointer(xchg(&priv->peer, NULL));
+ if (!peer)
+ return;
- /* Note : dellink() is called from default_device_exit_batch(),
- * before a rcu_synchronize() point. The devices are guaranteed
- * not being freed before one RCU grace period.
- */
- RCU_INIT_POINTER(priv->peer, NULL);
unregister_netdevice_queue(dev, head);
- if (peer) {
- priv = netdev_priv(peer);
- RCU_INIT_POINTER(priv->peer, NULL);
- unregister_netdevice_queue(peer, head);
- }
+ priv = netdev_priv(peer);
+ dev = unrcu_pointer(xchg(&priv->peer, NULL));
+ if (dev)
+ unregister_netdevice_queue_net(dev_net(dev), peer, head);
+
+ netdev_put(peer, peer_tracker);
+ netdev_put(dev, &priv->peer_tracker);
}
static const struct nla_policy vxcan_policy[VXCAN_INFO_MAX + 1] = {
--
2.55.0.795.g602f6c329a-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v1] vxcan: Support per-netns device unregistration.
2026-07-12 21:21 [PATCH v1] vxcan: Support per-netns device unregistration Kuniyuki Iwashima
@ 2026-07-12 21:34 ` sashiko-bot
2026-07-13 7:56 ` Oliver Hartkopp
0 siblings, 1 reply; 4+ messages in thread
From: sashiko-bot @ 2026-07-12 21:34 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: Oliver Hartkopp, linux-can, Oleksij Rempel, Marc Kleine-Budde,
Vincent Mailhol
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The patch calls the undefined function `unregister_netdevice_queue_net()`, resulting in a compilation error.
--
--- Patch [1]: [PATCH v1] vxcan: Support per-netns device unregistration. ---
commit 882fcd31630d9ce6b0a57cc99738c2ad0579763f
Author: Kuniyuki Iwashima <kuniyu@google.com>
vxcan: Support per-netns device unregistration.
This commit updates vxcan_dellink() to unregister local and peer devices
safely across different namespaces by using xchg(). The change aims to
prevent double-queuing of device destruction when RTNL is removed.
> diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
> --- a/drivers/net/can/vxcan.c
> +++ b/drivers/net/can/vxcan.c
[ ... ]
> @@ -281,24 +284,25 @@ static int vxcan_newlink(struct net_device *dev,
>
> static void vxcan_dellink(struct net_device *dev, struct list_head *head)
> {
[ ... ]
> unregister_netdevice_queue(dev, head);
>
> - if (peer) {
> - priv = netdev_priv(peer);
> - RCU_INIT_POINTER(priv->peer, NULL);
> - unregister_netdevice_queue(peer, head);
> - }
> + priv = netdev_priv(peer);
> + dev = unrcu_pointer(xchg(&priv->peer, NULL));
> + if (dev)
> + unregister_netdevice_queue_net(dev_net(dev), peer, head);
[Severity: Low]
Is this missing a prerequisite patch? It appears that
unregister_netdevice_queue_net() is not defined anywhere in the kernel
tree, which leads to a compilation error when building vxcan.c.
> +
> + netdev_put(peer, peer_tracker);
> + netdev_put(dev, &priv->peer_tracker);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260712212113.181121-1-kuniyu@google.com?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v1] vxcan: Support per-netns device unregistration.
2026-07-12 21:34 ` sashiko-bot
@ 2026-07-13 7:56 ` Oliver Hartkopp
2026-07-14 9:30 ` Kuniyuki Iwashima
0 siblings, 1 reply; 4+ messages in thread
From: Oliver Hartkopp @ 2026-07-13 7:56 UTC (permalink / raw)
To: sashiko-reviews, Kuniyuki Iwashima
Cc: linux-can, Oleksij Rempel, Marc Kleine-Budde, Vincent Mailhol
On 12.07.26 23:34, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Low] The patch calls the undefined function `unregister_netdevice_queue_net()`, resulting in a compilation error.
> --
>
> --- Patch [1]: [PATCH v1] vxcan: Support per-netns device unregistration. ---
> commit 882fcd31630d9ce6b0a57cc99738c2ad0579763f
> Author: Kuniyuki Iwashima <kuniyu@google.com>
>
> vxcan: Support per-netns device unregistration.
>
> This commit updates vxcan_dellink() to unregister local and peer devices
> safely across different namespaces by using xchg(). The change aims to
> prevent double-queuing of device destruction when RTNL is removed.
>
>> diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
>> --- a/drivers/net/can/vxcan.c
>> +++ b/drivers/net/can/vxcan.c
>
> [ ... ]
>
>> @@ -281,24 +284,25 @@ static int vxcan_newlink(struct net_device *dev,
>>
>> static void vxcan_dellink(struct net_device *dev, struct list_head *head)
>> {
>
> [ ... ]
>
>> unregister_netdevice_queue(dev, head);
>>
>> - if (peer) {
>> - priv = netdev_priv(peer);
>> - RCU_INIT_POINTER(priv->peer, NULL);
>> - unregister_netdevice_queue(peer, head);
>> - }
>> + priv = netdev_priv(peer);
>> + dev = unrcu_pointer(xchg(&priv->peer, NULL));
>> + if (dev)
>> + unregister_netdevice_queue_net(dev_net(dev), peer, head);
>
> [Severity: Low]
> Is this missing a prerequisite patch? It appears that
> unregister_netdevice_queue_net() is not defined anywhere in the kernel
> tree, which leads to a compilation error when building vxcan.c.
The referenced veth.c patch was applied to net-next:
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=d7fda2c776b2a969b9d78c5ad00e30824df43add
where also unregister_netdevice_queue_net() exists.
So this is a net-next resp. can-next patch.
Regards,
Oliver
>
>> +
>> + netdev_put(peer, peer_tracker);
>> + netdev_put(dev, &priv->peer_tracker);
>> }
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v1] vxcan: Support per-netns device unregistration.
2026-07-13 7:56 ` Oliver Hartkopp
@ 2026-07-14 9:30 ` Kuniyuki Iwashima
0 siblings, 0 replies; 4+ messages in thread
From: Kuniyuki Iwashima @ 2026-07-14 9:30 UTC (permalink / raw)
To: Oliver Hartkopp
Cc: sashiko-reviews, linux-can, Oleksij Rempel, Marc Kleine-Budde,
Vincent Mailhol
On Mon, Jul 13, 2026 at 9:57 AM Oliver Hartkopp <socketcan@hartkopp.net> wrote:
> On 12.07.26 23:34, sashiko-bot@kernel.org wrote:
> > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> > - [Low] The patch calls the undefined function `unregister_netdevice_queue_net()`, resulting in a compilation error.
> > --
> >
> > --- Patch [1]: [PATCH v1] vxcan: Support per-netns device unregistration. ---
> > commit 882fcd31630d9ce6b0a57cc99738c2ad0579763f
> > Author: Kuniyuki Iwashima <kuniyu@google.com>
> >
> > vxcan: Support per-netns device unregistration.
> >
> > This commit updates vxcan_dellink() to unregister local and peer devices
> > safely across different namespaces by using xchg(). The change aims to
> > prevent double-queuing of device destruction when RTNL is removed.
> >
> >> diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
> >> --- a/drivers/net/can/vxcan.c
> >> +++ b/drivers/net/can/vxcan.c
> >
> > [ ... ]
> >
> >> @@ -281,24 +284,25 @@ static int vxcan_newlink(struct net_device *dev,
> >>
> >> static void vxcan_dellink(struct net_device *dev, struct list_head *head)
> >> {
> >
> > [ ... ]
> >
> >> unregister_netdevice_queue(dev, head);
> >>
> >> - if (peer) {
> >> - priv = netdev_priv(peer);
> >> - RCU_INIT_POINTER(priv->peer, NULL);
> >> - unregister_netdevice_queue(peer, head);
> >> - }
> >> + priv = netdev_priv(peer);
> >> + dev = unrcu_pointer(xchg(&priv->peer, NULL));
> >> + if (dev)
> >> + unregister_netdevice_queue_net(dev_net(dev), peer, head);
> >
> > [Severity: Low]
> > Is this missing a prerequisite patch? It appears that
> > unregister_netdevice_queue_net() is not defined anywhere in the kernel
> > tree, which leads to a compilation error when building vxcan.c.
>
> The referenced veth.c patch was applied to net-next:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=d7fda2c776b2a969b9d78c5ad00e30824df43add
>
> where also unregister_netdevice_queue_net() exists.
>
> So this is a net-next resp. can-next patch.
Yes, I meant this is for can-next, but I was not sure how frequently
the tree is synced against net-next and what's the best approach here.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-14 9:30 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-12 21:21 [PATCH v1] vxcan: Support per-netns device unregistration Kuniyuki Iwashima
2026-07-12 21:34 ` sashiko-bot
2026-07-13 7:56 ` Oliver Hartkopp
2026-07-14 9:30 ` Kuniyuki Iwashima
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.