Re: [PATCH v2 net-next 06/14] net: Add per-netns netdev unregistration infra.
From: Kuniyuki Iwashima <kuniyu@google.com>
Date: 2026-07-06 16:35:04
Replying to Sashiko review, On Thu, Jul 2, 2026 at 5:10 PM Kuniyuki Iwashima [off-list ref] wrote: [...]
Note that unregister_netdevice_move_net() does not need to call rtnl_net_queue_work() because __dev_change_net_namespace() is (supposed to be) called with rtnl_net_lock(). (Not all callers hold it yet, but the race does not happen until all callers are converted and RTNL is removed.)
[...]
+static void unregister_netdevice_move_net(struct net *net_old,
+ struct net *net,
+ struct net_device *dev)
+{
+ if (net_old > net) {
+ spin_lock(&net->dev_unreg_lock);
+ spin_lock_nested(&net_old->dev_unreg_lock, SINGLE_DEPTH_NESTING);
+ } else {
+ spin_lock(&net_old->dev_unreg_lock);
+ spin_lock_nested(&net->dev_unreg_lock, SINGLE_DEPTH_NESTING);
+ }
+
+ if (!list_empty(&dev->unreg_list_net)) {
+ list_del(&dev->unreg_list_net);
+ list_add_tail(&dev->unreg_list_net, &net->dev_unreg_head);
+ }
+
+ spin_unlock(&net_old->dev_unreg_lock);
+ spin_unlock(&net->dev_unreg_lock);
+}
+
+void unregister_netdevice_many_net(struct net *net)
+{
+ struct net_device *dev, *tmp;
+ LIST_HEAD(unreg_head_net);
+ LIST_HEAD(unreg_head);
+
+ spin_lock(&net->dev_unreg_lock);
+ list_splice_init(&net->dev_unreg_head, &unreg_head_net);
+ spin_unlock(&net->dev_unreg_lock);
+
+ list_for_each_entry_safe(dev, tmp, &unreg_head_net, unreg_list_net) {
+ list_del_init(&dev->unreg_list_net);
+ list_add_tail(&dev->unreg_list, &unreg_head);
+ }---8<--- Will this result in a stalled unregistration if a cross-netns device is deleted and concurrently moved to a new namespace? If a user triggers deletion, unregister_netdevice_queue_net() queues the device in dev_unreg_head and schedules the async workqueue. Because unregistration runs asynchronously, dev->reg_state remains NETREG_REGISTERED initially. If the pending device is concurrently moved to a new netns via dev_change_net_namespace(), unregister_netdevice_move_net() correctly transfers the device to the new netns's dev_unreg_head list. However, does this block miss a call to rtnl_net_queue_work(net) to schedule processing for the new netns? ---8<--- I didn't add rtnl_net_queue_work() intentionally as mentioned in the commit message. For now, such a race does not occur thanks to RTNL. Once RTNL is removed, all dev_change_net_namespace() callers must be called under per-netns RTNL, so even if the race occurred, the dev would be removed at __rtnl_net_unlock().