summaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2022-02-17 22:54:30 -0800
committerJakub Kicinski <kuba@kernel.org>2022-02-18 07:28:31 -0800
commit86213f80da1b1d007721cc22e04b5f5d0da33127 (patch)
treee0aff65d6880e34f9aa01b9f977d814b2c3f30e1 /net/core
parent086d49058cd8471046ae9927524708820f5fd1c7 (diff)
net: avoid quadratic behavior in netdev_wait_allrefs_any()
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>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c4
1 files changed, 1 insertions, 3 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 05fa867f1878..acd884910e12 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -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)) {