net: avoid quadratic behavior in netdev_wait_allrefs_any()
authorEric Dumazet <edumazet@google.com>
Fri, 18 Feb 2022 06:54:30 +0000 (22:54 -0800)
committerJakub Kicinski <kuba@kernel.org>
Fri, 18 Feb 2022 15:28:31 +0000 (07:28 -0800)
If the list of devices has N elements, netdev_wait_allrefs_any()
is called N times, and linkwatch_forget_dev() is called N*(N-1)/2 times.

Fix this by calling linkwatch_forget_dev() only once per device.

Fixes: faab39f63c1f ("net: allow out-of-order netdev unregistration")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20220218065430.2613262-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/core/dev.c

index 05fa867..acd8849 100644 (file)
@@ -9828,9 +9828,6 @@ static struct net_device *netdev_wait_allrefs_any(struct list_head *list)
        struct net_device *dev;
        int wait = 0;
 
-       list_for_each_entry(dev, list, todo_list)
-               linkwatch_forget_dev(dev);
-
        rebroadcast_time = warning_time = jiffies;
 
        list_for_each_entry(dev, list, todo_list)
@@ -9951,6 +9948,7 @@ void netdev_run_todo(void)
                }
 
                dev->reg_state = NETREG_UNREGISTERED;
+               linkwatch_forget_dev(dev);
        }
 
        while (!list_empty(&list)) {