diff options
author | Eric Dumazet <edumazet@google.com> | 2022-02-10 05:59:32 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-02-10 18:30:26 +0300 |
commit | ede6c39c4f9068cbeb4036448c45fff5393e0432 (patch) | |
tree | dbeb843af969bdd903410d4ea5351db041893058 /net/core | |
parent | ca2d5f1ff05955da9506055e88c4bbb71da190f1 (diff) | |
download | linux-ede6c39c4f9068cbeb4036448c45fff5393e0432.tar.xz |
net: make net->dev_unreg_count atomic
Having to acquire rtnl from netdev_run_todo() for every dismantled
device is not desirable when/if rtnl is under stress.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 11 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 2 |
2 files changed, 5 insertions, 8 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index f5ef51601081..2c3b8744e00c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9143,7 +9143,7 @@ DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq); static void net_set_todo(struct net_device *dev) { list_add_tail(&dev->todo_list, &net_todo_list); - dev_net(dev)->dev_unreg_count++; + atomic_inc(&dev_net(dev)->dev_unreg_count); } static netdev_features_t netdev_sync_upper_features(struct net_device *lower, @@ -9965,11 +9965,8 @@ void netdev_run_todo(void) if (dev->needs_free_netdev) free_netdev(dev); - /* Report a network device has been unregistered */ - rtnl_lock(); - dev_net(dev)->dev_unreg_count--; - __rtnl_unlock(); - wake_up(&netdev_unregistering_wq); + if (atomic_dec_and_test(&dev_net(dev)->dev_unreg_count)) + wake_up(&netdev_unregistering_wq); /* Free network device */ kobject_put(&dev->dev.kobj); @@ -10898,7 +10895,7 @@ static void __net_exit rtnl_lock_unregistering(struct list_head *net_list) unregistering = false; list_for_each_entry(net, net_list, exit_list) { - if (net->dev_unreg_count > 0) { + if (atomic_read(&net->dev_unreg_count) > 0) { unregistering = true; break; } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 710da8a36729..a6fad3df42a8 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -459,7 +459,7 @@ static void rtnl_lock_unregistering_all(void) * setup_net() and cleanup_net() are not possible. */ for_each_net(net) { - if (net->dev_unreg_count > 0) { + if (atomic_read(&net->dev_unreg_count) > 0) { unregistering = true; break; } |