net: introduce a helper to move notifier block to different namespace
authorJiri Pirko <jiri@nvidia.com>
Tue, 8 Nov 2022 13:22:06 +0000 (14:22 +0100)
committerJakub Kicinski <kuba@kernel.org>
Wed, 9 Nov 2022 21:45:59 +0000 (13:45 -0800)
Currently, net_dev() netdev notifier variant follows the netdev with
per-net notifier from namespace to namespace. This is implemented
by move_netdevice_notifiers_dev_net() helper.

For devlink it is needed to re-register per-net notifier during
devlink reload. Introduce a new helper called
move_netdevice_notifier_net() and share the unregister/register code
with existing move_netdevice_notifiers_dev_net() helper.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/linux/netdevice.h
net/core/dev.c

index 4be87b8..02a2318 100644 (file)
@@ -2826,6 +2826,8 @@ int unregister_netdevice_notifier(struct notifier_block *nb);
 int register_netdevice_notifier_net(struct net *net, struct notifier_block *nb);
 int unregister_netdevice_notifier_net(struct net *net,
                                      struct notifier_block *nb);
+void move_netdevice_notifier_net(struct net *src_net, struct net *dst_net,
+                                struct notifier_block *nb);
 int register_netdevice_notifier_dev_net(struct net_device *dev,
                                        struct notifier_block *nb,
                                        struct netdev_net_notifier *nn);
index 707de6b..117e830 100644 (file)
@@ -1861,6 +1861,22 @@ int unregister_netdevice_notifier_net(struct net *net,
 }
 EXPORT_SYMBOL(unregister_netdevice_notifier_net);
 
+static void __move_netdevice_notifier_net(struct net *src_net,
+                                         struct net *dst_net,
+                                         struct notifier_block *nb)
+{
+       __unregister_netdevice_notifier_net(src_net, nb);
+       __register_netdevice_notifier_net(dst_net, nb, true);
+}
+
+void move_netdevice_notifier_net(struct net *src_net, struct net *dst_net,
+                                struct notifier_block *nb)
+{
+       rtnl_lock();
+       __move_netdevice_notifier_net(src_net, dst_net, nb);
+       rtnl_unlock();
+}
+
 int register_netdevice_notifier_dev_net(struct net_device *dev,
                                        struct notifier_block *nb,
                                        struct netdev_net_notifier *nn)
@@ -1897,10 +1913,8 @@ static void move_netdevice_notifiers_dev_net(struct net_device *dev,
 {
        struct netdev_net_notifier *nn;
 
-       list_for_each_entry(nn, &dev->net_notifier_list, list) {
-               __unregister_netdevice_notifier_net(dev_net(dev), nn->nb);
-               __register_netdevice_notifier_net(net, nn->nb, true);
-       }
+       list_for_each_entry(nn, &dev->net_notifier_list, list)
+               __move_netdevice_notifier_net(dev_net(dev), net, nn->nb);
 }
 
 /**