Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3caf519 authored by Sven Eckelmann's avatar Sven Eckelmann
Browse files

batman-adv: Remove unnecessary hardif_list_lock



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: default avatarLinus Lüssing <linus.luessing@web.de>
Signed-off-by: default avatarSven Eckelmann <sven@narfation.org>
parent 61906ae8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+7 −23
Original line number Diff line number Diff line
@@ -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 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev)

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;
+3 −0
Original line number Diff line number Diff line
@@ -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};
+1 −1
Original line number Diff line number Diff line
@@ -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);