diff mbox series

[RFC,net-next,7/9] net: delay the removal of the name nodes until run_todo

Message ID 20210928125500.167943-8-atenart@kernel.org (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series Userspace spinning on net-sysfs access | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Clearly marked for net-next
netdev/subject_prefix success Link
netdev/cc_maintainers warning 8 maintainers not CCed: weiwan@google.com ap420073@gmail.com arnd@arndb.de bjorn@kernel.org memxor@gmail.com daniel@iogearbox.net edumazet@google.com alobakin@pm.me
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 6 this patch: 6
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 36 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 6 this patch: 6
netdev/header_inline success Link

Commit Message

Antoine Tenart Sept. 28, 2021, 12:54 p.m. UTC
Keep the node name collision detection working until the last
registration stage, by delaying the removal of the name nodes in
run_todo. This allows to perform unregistration operations being
sensitive to name collisions, in run_todo. As run_todo has sections of
code running without the rtnl lock taken, this will allow to perform
some of those operations not under this lock (when possible).

While we move the removal of the name node until a late unregistration
stage, we still want to avoid returning a net device reference when it's
being unregistered (calling __dev_get_by_name for example). We keep this
logic by setting the node name dev reference to NULL. This follows the
logic of __dev_get_by_name. Altnames are in the same list, they are not
special here.

From now on we have to be strict on the use of __dev_get_by_name vs
netdev_name_node_lookup. One is designed to get the device, the other
one to lookup in the list of currently reserved names. Current users
should have been fixed by previous patches.

One side effect is there is now a window between unregistering the
netdevice and running the todo where names are still reserved and can't
be used for new device creation.

Signed-off-by: Antoine Tenart <atenart@kernel.org>
---
 net/core/dev.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/net/core/dev.c b/net/core/dev.c
index 02f9d505dbe2..a1eab120bb50 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10611,10 +10611,15 @@  void netdev_run_todo(void)
 		if (dev->needs_free_netdev)
 			free_netdev(dev);
 
-		/* Report a network device has been unregistered */
 		rtnl_lock();
+		unlist_netdevice_name(dev);
+		synchronize_net();
+		netdev_name_node_free(dev->name_node);
+
 		dev_net(dev)->dev_unreg_count--;
 		__rtnl_unlock();
+
+		/* Report a network device has been unregistered */
 		wake_up(&netdev_unregistering_wq);
 
 		/* Free network device */
@@ -11039,7 +11044,12 @@  void unregister_netdevice_many(struct list_head *head)
 	list_for_each_entry(dev, head, unreg_list) {
 		/* And unlink it from device chain. */
 		unlist_netdevice(dev);
-		unlist_netdevice_name(dev);
+
+		/* Unreference the net device from the node name. From this
+		 * point on the node name is only used for naming collision
+		 * detection.
+		 */
+		dev->name_node->dev = NULL;
 
 		dev->reg_state = NETREG_UNREGISTERING;
 	}
@@ -11072,7 +11082,6 @@  void unregister_netdevice_many(struct list_head *head)
 		dev_mc_flush(dev);
 
 		netdev_name_node_alt_flush(dev);
-		netdev_name_node_free(dev->name_node);
 
 		if (dev->netdev_ops->ndo_uninit)
 			dev->netdev_ops->ndo_uninit(dev);