net: push loops and nb calls into helper functions
authorJiri Pirko <jiri@mellanox.com>
Mon, 30 Sep 2019 08:15:09 +0000 (10:15 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 2 Oct 2019 15:48:44 +0000 (11:48 -0400)
Push iterations over net namespaces and netdevices from
register_netdevice_notifier() and unregister_netdevice_notifier()
into helper functions. Along with that introduce continue_reverse macros
to make the code a bit nicer allowing to get rid of "last" marks.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
include/net/net_namespace.h
net/core/dev.c

index 48cc71a..7b183f7 100644 (file)
@@ -2574,6 +2574,9 @@ extern rwlock_t                           dev_base_lock;          /* Device list lock */
                list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list)
 #define for_each_netdev_continue(net, d)               \
                list_for_each_entry_continue(d, &(net)->dev_base_head, dev_list)
+#define for_each_netdev_continue_reverse(net, d)               \
+               list_for_each_entry_continue_reverse(d, &(net)->dev_base_head, \
+                                                    dev_list)
 #define for_each_netdev_continue_rcu(net, d)           \
        list_for_each_entry_continue_rcu(d, &(net)->dev_base_head, dev_list)
 #define for_each_netdev_in_bond_rcu(bond, slave)       \
index f8712bb..c5a98e0 100644 (file)
@@ -317,7 +317,8 @@ static inline struct net *read_pnet(const possible_net_t *pnet)
 /* Protected by net_rwsem */
 #define for_each_net(VAR)                              \
        list_for_each_entry(VAR, &net_namespace_list, list)
-
+#define for_each_net_continue_reverse(VAR)             \
+       list_for_each_entry_continue_reverse(VAR, &net_namespace_list, list)
 #define for_each_net_rcu(VAR)                          \
        list_for_each_entry_rcu(VAR, &net_namespace_list, list)
 
index 7a456c6..a8b70cb 100644 (file)
@@ -1725,6 +1725,62 @@ static int call_netdevice_notifier(struct notifier_block *nb, unsigned long val,
        return nb->notifier_call(nb, val, &info);
 }
 
+static int call_netdevice_register_notifiers(struct notifier_block *nb,
+                                            struct net_device *dev)
+{
+       int err;
+
+       err = call_netdevice_notifier(nb, NETDEV_REGISTER, dev);
+       err = notifier_to_errno(err);
+       if (err)
+               return err;
+
+       if (!(dev->flags & IFF_UP))
+               return 0;
+
+       call_netdevice_notifier(nb, NETDEV_UP, dev);
+       return 0;
+}
+
+static void call_netdevice_unregister_notifiers(struct notifier_block *nb,
+                                               struct net_device *dev)
+{
+       if (dev->flags & IFF_UP) {
+               call_netdevice_notifier(nb, NETDEV_GOING_DOWN,
+                                       dev);
+               call_netdevice_notifier(nb, NETDEV_DOWN, dev);
+       }
+       call_netdevice_notifier(nb, NETDEV_UNREGISTER, dev);
+}
+
+static int call_netdevice_register_net_notifiers(struct notifier_block *nb,
+                                                struct net *net)
+{
+       struct net_device *dev;
+       int err;
+
+       for_each_netdev(net, dev) {
+               err = call_netdevice_register_notifiers(nb, dev);
+               if (err)
+                       goto rollback;
+       }
+       return 0;
+
+rollback:
+       for_each_netdev_continue_reverse(net, dev)
+               call_netdevice_unregister_notifiers(nb, dev);
+       return err;
+}
+
+static void call_netdevice_unregister_net_notifiers(struct notifier_block *nb,
+                                                   struct net *net)
+{
+       struct net_device *dev;
+
+       for_each_netdev(net, dev)
+               call_netdevice_unregister_notifiers(nb, dev);
+}
+
 static int dev_boot_phase = 1;
 
 /**
@@ -1743,8 +1799,6 @@ static int dev_boot_phase = 1;
 
 int register_netdevice_notifier(struct notifier_block *nb)
 {
-       struct net_device *dev;
-       struct net_device *last;
        struct net *net;
        int err;
 
@@ -1757,17 +1811,9 @@ int register_netdevice_notifier(struct notifier_block *nb)
        if (dev_boot_phase)
                goto unlock;
        for_each_net(net) {
-               for_each_netdev(net, dev) {
-                       err = call_netdevice_notifier(nb, NETDEV_REGISTER, dev);
-                       err = notifier_to_errno(err);
-                       if (err)
-                               goto rollback;
-
-                       if (!(dev->flags & IFF_UP))
-                               continue;
-
-                       call_netdevice_notifier(nb, NETDEV_UP, dev);
-               }
+               err = call_netdevice_register_net_notifiers(nb, net);
+               if (err)
+                       goto rollback;
        }
 
 unlock:
@@ -1776,22 +1822,9 @@ unlock:
        return err;
 
 rollback:
-       last = dev;
-       for_each_net(net) {
-               for_each_netdev(net, dev) {
-                       if (dev == last)
-                               goto outroll;
-
-                       if (dev->flags & IFF_UP) {
-                               call_netdevice_notifier(nb, NETDEV_GOING_DOWN,
-                                                       dev);
-                               call_netdevice_notifier(nb, NETDEV_DOWN, dev);
-                       }
-                       call_netdevice_notifier(nb, NETDEV_UNREGISTER, dev);
-               }
-       }
+       for_each_net_continue_reverse(net)
+               call_netdevice_unregister_net_notifiers(nb, net);
 
-outroll:
        raw_notifier_chain_unregister(&netdev_chain, nb);
        goto unlock;
 }