[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220210025932.966618-1-eric.dumazet@gmail.com>
Date: Wed, 9 Feb 2022 18:59:32 -0800
From: Eric Dumazet <eric.dumazet@...il.com>
To: "David S . Miller" <davem@...emloft.net>,
Jakub Kicinski <kuba@...nel.org>
Cc: netdev <netdev@...r.kernel.org>,
Eric Dumazet <edumazet@...gle.com>,
Eric Dumazet <eric.dumazet@...il.com>
Subject: [PATCH net-next] net: make net->dev_unreg_count atomic
From: Eric Dumazet <edumazet@...gle.com>
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@...gle.com>
---
include/net/net_namespace.h | 2 +-
net/core/dev.c | 11 ++++-------
net/core/rtnetlink.c | 2 +-
3 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 374cc7b260fcdf15a8fc2c709d0b0fc6d99e8c5c..c4f5601f6e32aff401dfb462fb4949ec7d37833a 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -63,7 +63,7 @@ struct net {
*/
spinlock_t rules_mod_lock;
- unsigned int dev_unreg_count;
+ atomic_t dev_unreg_count;
unsigned int dev_base_seq; /* protected by rtnl_mutex */
int ifindex;
diff --git a/net/core/dev.c b/net/core/dev.c
index f5ef5160108131de8892555d2c73e4adaf98eeed..2c3b8744e00c01448e8882460760fdb3304f0476 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 710da8a36729d6a9293b610b029bd33aa38d6514..a6fad3df42a800792ed362e7f75de20880c53726 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;
}
--
2.35.0.263.gb82422642f-goog
Powered by blists - more mailing lists