@@ -2071,13 +2071,54 @@ static void __move_netdevice_notifier_net(struct net *src_net,
20712071 __register_netdevice_notifier_net (dst_net , nb , true);
20722072}
20732073
2074+ static void rtnl_net_dev_lock (struct net_device * dev )
2075+ {
2076+ bool again ;
2077+
2078+ do {
2079+ struct net * net ;
2080+
2081+ again = false;
2082+
2083+ /* netns might be being dismantled. */
2084+ rcu_read_lock ();
2085+ net = dev_net_rcu (dev );
2086+ net_passive_inc (net );
2087+ rcu_read_unlock ();
2088+
2089+ rtnl_net_lock (net );
2090+
2091+ #ifdef CONFIG_NET_NS
2092+ /* dev might have been moved to another netns. */
2093+ if (!net_eq (net , rcu_access_pointer (dev -> nd_net .net ))) {
2094+ rtnl_net_unlock (net );
2095+ net_passive_dec (net );
2096+ again = true;
2097+ }
2098+ #endif
2099+ } while (again );
2100+ }
2101+
2102+ static void rtnl_net_dev_unlock (struct net_device * dev )
2103+ {
2104+ struct net * net = dev_net (dev );
2105+
2106+ rtnl_net_unlock (net );
2107+ net_passive_dec (net );
2108+ }
2109+
20742110int register_netdevice_notifier_dev_net (struct net_device * dev ,
20752111 struct notifier_block * nb ,
20762112 struct netdev_net_notifier * nn )
20772113{
20782114 struct net * net = dev_net (dev );
20792115 int err ;
20802116
2117+ /* rtnl_net_lock() assumes dev is not yet published by
2118+ * register_netdevice().
2119+ */
2120+ DEBUG_NET_WARN_ON_ONCE (!list_empty (& dev -> dev_list ));
2121+
20812122 rtnl_net_lock (net );
20822123 err = __register_netdevice_notifier_net (net , nb , false);
20832124 if (!err ) {
@@ -2094,13 +2135,12 @@ int unregister_netdevice_notifier_dev_net(struct net_device *dev,
20942135 struct notifier_block * nb ,
20952136 struct netdev_net_notifier * nn )
20962137{
2097- struct net * net = dev_net (dev );
20982138 int err ;
20992139
2100- rtnl_net_lock ( net );
2140+ rtnl_net_dev_lock ( dev );
21012141 list_del (& nn -> list );
2102- err = __unregister_netdevice_notifier_net (net , nb );
2103- rtnl_net_unlock ( net );
2142+ err = __unregister_netdevice_notifier_net (dev_net ( dev ) , nb );
2143+ rtnl_net_dev_unlock ( dev );
21042144
21052145 return err ;
21062146}
@@ -11901,11 +11941,9 @@ EXPORT_SYMBOL(unregister_netdevice_many);
1190111941 */
1190211942void unregister_netdev (struct net_device * dev )
1190311943{
11904- struct net * net = dev_net (dev );
11905-
11906- rtnl_net_lock (net );
11944+ rtnl_net_dev_lock (dev );
1190711945 unregister_netdevice (dev );
11908- rtnl_net_unlock ( net );
11946+ rtnl_net_dev_unlock ( dev );
1190911947}
1191011948EXPORT_SYMBOL (unregister_netdev );
1191111949
0 commit comments