[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240213063245.3605305-5-edumazet@google.com>
Date: Tue, 13 Feb 2024 06:32:36 +0000
From: Eric Dumazet <edumazet@...gle.com>
To: "David S . Miller" <davem@...emloft.net>, Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>
Cc: netdev@...r.kernel.org, eric.dumazet@...il.com,
Eric Dumazet <edumazet@...gle.com>
Subject: [PATCH v4 net-next 04/13] net: convert dev->reg_state to u8
Prepares things so that dev->reg_state reads can be lockless,
by adding WRITE_ONCE() on write side.
READ_ONCE()/WRITE_ONCE() do not support bitfields.
Signed-off-by: Eric Dumazet <edumazet@...gle.com>
---
include/linux/netdevice.h | 23 ++++++++++++++---------
net/core/dev.c | 8 ++++----
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 07cefa32eafa93dd1a4602de892d0ee1cbf2e22b..24fd24b0f2341f662b28ade45ed12a5e6d02852a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1815,6 +1815,15 @@ enum netdev_stat_type {
NETDEV_PCPU_STAT_DSTATS, /* struct pcpu_dstats */
};
+enum netdev_reg_state {
+ NETREG_UNINITIALIZED = 0,
+ NETREG_REGISTERED, /* completed register_netdevice */
+ NETREG_UNREGISTERING, /* called unregister_netdevice */
+ NETREG_UNREGISTERED, /* completed unregister todo */
+ NETREG_RELEASED, /* called free_netdev */
+ NETREG_DUMMY, /* dummy device for NAPI poll */
+};
+
/**
* struct net_device - The DEVICE structure.
*
@@ -2372,13 +2381,7 @@ struct net_device {
struct list_head link_watch_list;
- enum { NETREG_UNINITIALIZED=0,
- NETREG_REGISTERED, /* completed register_netdevice */
- NETREG_UNREGISTERING, /* called unregister_netdevice */
- NETREG_UNREGISTERED, /* completed unregister todo */
- NETREG_RELEASED, /* called free_netdev */
- NETREG_DUMMY, /* dummy device for NAPI poll */
- } reg_state:8;
+ u8 reg_state;
bool dismantle;
@@ -5254,7 +5257,9 @@ static inline const char *netdev_name(const struct net_device *dev)
static inline const char *netdev_reg_state(const struct net_device *dev)
{
- switch (dev->reg_state) {
+ u8 reg_state = READ_ONCE(dev->reg_state);
+
+ switch (reg_state) {
case NETREG_UNINITIALIZED: return " (uninitialized)";
case NETREG_REGISTERED: return "";
case NETREG_UNREGISTERING: return " (unregistering)";
@@ -5263,7 +5268,7 @@ static inline const char *netdev_reg_state(const struct net_device *dev)
case NETREG_DUMMY: return " (dummy)";
}
- WARN_ONCE(1, "%s: unknown reg_state %d\n", dev->name, dev->reg_state);
+ WARN_ONCE(1, "%s: unknown reg_state %d\n", dev->name, reg_state);
return " (unknown)";
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 693e08f3304d1de18f859ff4a65947b4a5cb9e4a..c08e8830ff976e74455157d3a3b8819e8424f93c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10297,7 +10297,7 @@ int register_netdevice(struct net_device *dev)
ret = netdev_register_kobject(dev);
write_lock(&dev_base_lock);
- dev->reg_state = ret ? NETREG_UNREGISTERED : NETREG_REGISTERED;
+ WRITE_ONCE(dev->reg_state, ret ? NETREG_UNREGISTERED : NETREG_REGISTERED);
write_unlock(&dev_base_lock);
if (ret)
goto err_uninit_notify;
@@ -10588,7 +10588,7 @@ void netdev_run_todo(void)
}
write_lock(&dev_base_lock);
- dev->reg_state = NETREG_UNREGISTERED;
+ WRITE_ONCE(dev->reg_state, NETREG_UNREGISTERED);
write_unlock(&dev_base_lock);
linkwatch_sync_dev(dev);
}
@@ -11008,7 +11008,7 @@ void free_netdev(struct net_device *dev)
}
BUG_ON(dev->reg_state != NETREG_UNREGISTERED);
- dev->reg_state = NETREG_RELEASED;
+ WRITE_ONCE(dev->reg_state, NETREG_RELEASED);
/* will free via device release */
put_device(&dev->dev);
@@ -11098,7 +11098,7 @@ void unregister_netdevice_many_notify(struct list_head *head,
/* And unlink it from device chain. */
write_lock(&dev_base_lock);
unlist_netdevice(dev, false);
- dev->reg_state = NETREG_UNREGISTERING;
+ WRITE_ONCE(dev->reg_state, NETREG_UNREGISTERING);
write_unlock(&dev_base_lock);
}
flush_all_backlogs();
--
2.43.0.687.g38aa6559b0-goog
Powered by blists - more mailing lists