batman-adv: Remove unnecessary hardif_list_lock
authorSven Eckelmann <sven@narfation.org>
Tue, 3 May 2011 09:51:38 +0000 (11:51 +0200)
committerSven Eckelmann <sven@narfation.org>
Sun, 8 May 2011 14:10:41 +0000 (16:10 +0200)
hardif_list_lock is unneccessary because we already ensure that no
multiple admin operations can take place through rtnl_lock.
hardif_list_lock only adds additional overhead and complexity.

Critical functions now check whether they are called with rtnl_lock
using ASSERT_RTNL.

It indirectly fixes the problem that orig_hash_del_if() expects that
only one interface is deleted from hardif_list at a time, but
hardif_remove_interfaces() removes all at once and then calls
orig_hash_del_if().

Reported-by: Linus Lüssing <linus.luessing@web.de>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
net/batman-adv/bat_sysfs.c
net/batman-adv/hard-interface.c
net/batman-adv/main.c
net/batman-adv/soft-interface.c

index e449bf6353e01de692ea74186c902e80fae8605e..85ba20d98a66fb76a2f9258cbe1e46bfdb2054c9 100644 (file)
@@ -502,7 +502,9 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
                rtnl_unlock();
        }
 
+       rtnl_lock();
        ret = hardif_enable_interface(hard_iface, buff);
+       rtnl_unlock();
 
 out:
        hardif_free_ref(hard_iface);
index 3e888f133d75df54f0572d647027116cddce5817..7e2f7728f706df49fc925746f4fd5af0f6e3a4b6 100644 (file)
@@ -31,9 +31,6 @@
 
 #include <linux/if_arp.h>
 
-/* protect update critical side of hardif_list - but not the content */
-static DEFINE_SPINLOCK(hardif_list_lock);
-
 
 static int batman_skb_recv(struct sk_buff *skb,
                           struct net_device *dev,
@@ -136,7 +133,7 @@ static void primary_if_select(struct bat_priv *bat_priv,
        struct hard_iface *curr_hard_iface;
        struct batman_packet *batman_packet;
 
-       spin_lock_bh(&hardif_list_lock);
+       ASSERT_RTNL();
 
        if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
                new_hard_iface = NULL;
@@ -148,7 +145,7 @@ static void primary_if_select(struct bat_priv *bat_priv,
                hardif_free_ref(curr_hard_iface);
 
        if (!new_hard_iface)
-               goto out;
+               return;
 
        batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff);
        batman_packet->flags = PRIMARIES_FIRST_HOP;
@@ -161,9 +158,6 @@ static void primary_if_select(struct bat_priv *bat_priv,
         * our new primary interface
         */
        atomic_set(&bat_priv->hna_local_changed, 1);
-
-out:
-       spin_unlock_bh(&hardif_list_lock);
 }
 
 static bool hardif_is_iface_up(struct hard_iface *hard_iface)
@@ -456,6 +450,8 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev)
        struct hard_iface *hard_iface;
        int ret;
 
+       ASSERT_RTNL();
+
        ret = is_valid_iface(net_dev);
        if (ret != 1)
                goto out;
@@ -482,10 +478,7 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev)
        atomic_set(&hard_iface->refcount, 2);
 
        check_known_mac_addr(hard_iface->net_dev);
-
-       spin_lock(&hardif_list_lock);
        list_add_tail_rcu(&hard_iface->list, &hardif_list);
-       spin_unlock(&hardif_list_lock);
 
        return hard_iface;
 
@@ -499,6 +492,8 @@ out:
 
 static void hardif_remove_interface(struct hard_iface *hard_iface)
 {
+       ASSERT_RTNL();
+
        /* first deactivate interface */
        if (hard_iface->if_status != IF_NOT_IN_USE)
                hardif_disable_interface(hard_iface);
@@ -514,20 +509,11 @@ static void hardif_remove_interface(struct hard_iface *hard_iface)
 void hardif_remove_interfaces(void)
 {
        struct hard_iface *hard_iface, *hard_iface_tmp;
-       struct list_head if_queue;
-
-       INIT_LIST_HEAD(&if_queue);
 
-       spin_lock(&hardif_list_lock);
+       rtnl_lock();
        list_for_each_entry_safe(hard_iface, hard_iface_tmp,
                                 &hardif_list, list) {
                list_del_rcu(&hard_iface->list);
-               list_add_tail(&hard_iface->list, &if_queue);
-       }
-       spin_unlock(&hardif_list_lock);
-
-       rtnl_lock();
-       list_for_each_entry_safe(hard_iface, hard_iface_tmp, &if_queue, list) {
                hardif_remove_interface(hard_iface);
        }
        rtnl_unlock();
@@ -556,9 +542,7 @@ static int hard_if_event(struct notifier_block *this,
                hardif_deactivate_interface(hard_iface);
                break;
        case NETDEV_UNREGISTER:
-               spin_lock(&hardif_list_lock);
                list_del_rcu(&hard_iface->list);
-               spin_unlock(&hardif_list_lock);
 
                hardif_remove_interface(hard_iface);
                break;
index 705e8be07c8d968eac2b283917e9a9f2b5327b89..7edf8d719e15c8d4dfa345a6ffd35b361f6ab659 100644 (file)
@@ -33,6 +33,9 @@
 #include "vis.h"
 #include "hash.h"
 
+
+/* List manipulations on hardif_list have to be rtnl_lock()'ed,
+ * list traversals just rcu-locked */
 struct list_head hardif_list;
 
 unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
index 8cb13a03b0e1951bdac06269d520661b9a0b8a74..9301e21052e7adccad1f4e06a0341d6a887776c2 100644 (file)
@@ -819,7 +819,7 @@ struct net_device *softif_create(char *name)
                goto out;
        }
 
-       ret = register_netdev(soft_iface);
+       ret = register_netdevice(soft_iface);
        if (ret < 0) {
                pr_err("Unable to register the batman interface '%s': %i\n",
                       name, ret);