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

Commit 30c1de08 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge



Antonio Quartulli says:

====================
Here you have a batch of patches by Sven Eckelmann that
drops our private reference counting implementation and
substitutes it with the kref objects/functions.

Then you have a patch, by Simon Wunderlich, that
makes the broadcast protection window code more generic so
that it can be re-used in the future by other components
with different requirements.

Lastly, Sven is also introducing two lockdep asserts in
functions operating on our TVLV container list, to make
sure that the proper lock is always acquired by the users.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents dba6cf55 92dcdf09
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/list.h>
#include <linux/kref.h>
#include <linux/netdevice.h>
#include <linux/pkt_sched.h>
#include <linux/printk.h>
@@ -643,10 +644,10 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
	unsigned char *skb_buff;
	unsigned int skb_size;

	if (!atomic_inc_not_zero(&if_incoming->refcount))
	if (!kref_get_unless_zero(&if_incoming->refcount))
		return;

	if (!atomic_inc_not_zero(&if_outgoing->refcount))
	if (!kref_get_unless_zero(&if_outgoing->refcount))
		goto out_free_incoming;

	/* own packet should always be scheduled */
@@ -1002,7 +1003,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
		neigh_addr = tmp_neigh_node->addr;
		if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
		    tmp_neigh_node->if_incoming == if_incoming &&
		    atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
		    kref_get_unless_zero(&tmp_neigh_node->refcount)) {
			if (WARN(neigh_node, "too many matching neigh_nodes"))
				batadv_neigh_node_free_ref(neigh_node);
			neigh_node = tmp_neigh_node;
@@ -1161,7 +1162,7 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
		if (tmp_neigh_node->if_incoming != if_incoming)
			continue;

		if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
		if (!kref_get_unless_zero(&tmp_neigh_node->refcount))
			continue;

		neigh_node = tmp_neigh_node;
@@ -1315,7 +1316,8 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
	/* signalize caller that the packet is to be dropped. */
	if (!hlist_empty(&orig_node->neigh_list) &&
	    batadv_window_protected(bat_priv, seq_diff,
				    &orig_ifinfo->batman_seqno_reset)) {
				    BATADV_TQ_LOCAL_WINDOW_SIZE,
				    &orig_ifinfo->batman_seqno_reset, NULL)) {
		ret = BATADV_PROTECTED;
		goto out;
	}
+32 −11
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/jhash.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/netdevice.h>
@@ -143,14 +144,29 @@ static int batadv_compare_claim(const struct hlist_node *node,
}

/**
 * batadv_compare_backbone_gw - free backbone gw
 * batadv_backbone_gw_release - release backbone gw from lists and queue for
 *  free after rcu grace period
 * @ref: kref pointer of the backbone gw
 */
static void batadv_backbone_gw_release(struct kref *ref)
{
	struct batadv_bla_backbone_gw *backbone_gw;

	backbone_gw = container_of(ref, struct batadv_bla_backbone_gw,
				   refcount);

	kfree_rcu(backbone_gw, rcu);
}

/**
 * batadv_backbone_gw_free_ref - decrement the backbone gw refcounter and
 *  possibly release it
 * @backbone_gw: backbone gateway to be free'd
 */
static void
batadv_backbone_gw_free_ref(struct batadv_bla_backbone_gw *backbone_gw)
{
	if (atomic_dec_and_test(&backbone_gw->refcount))
		kfree_rcu(backbone_gw, rcu);
	kref_put(&backbone_gw->refcount, batadv_backbone_gw_release);
}

/**
@@ -158,8 +174,12 @@ batadv_backbone_gw_free_ref(struct batadv_bla_backbone_gw *backbone_gw)
 *  grace period
 * @ref: kref pointer of the claim
 */
static void batadv_claim_release(struct batadv_bla_claim *claim)
static void batadv_claim_release(struct kref *ref)
{
	struct batadv_bla_claim *claim;

	claim = container_of(ref, struct batadv_bla_claim, refcount);

	batadv_backbone_gw_free_ref(claim->backbone_gw);
	kfree_rcu(claim, rcu);
}
@@ -171,8 +191,7 @@ static void batadv_claim_release(struct batadv_bla_claim *claim)
 */
static void batadv_claim_free_ref(struct batadv_bla_claim *claim)
{
	if (atomic_dec_and_test(&claim->refcount))
		batadv_claim_release(claim);
	kref_put(&claim->refcount, batadv_claim_release);
}

/**
@@ -203,7 +222,7 @@ static struct batadv_bla_claim
		if (!batadv_compare_claim(&claim->hash_entry, data))
			continue;

		if (!atomic_inc_not_zero(&claim->refcount))
		if (!kref_get_unless_zero(&claim->refcount))
			continue;

		claim_tmp = claim;
@@ -247,7 +266,7 @@ batadv_backbone_hash_find(struct batadv_priv *bat_priv, u8 *addr,
						&search_entry))
			continue;

		if (!atomic_inc_not_zero(&backbone_gw->refcount))
		if (!kref_get_unless_zero(&backbone_gw->refcount))
			continue;

		backbone_gw_tmp = backbone_gw;
@@ -448,7 +467,8 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig,
	ether_addr_copy(entry->orig, orig);

	/* one for the hash, one for returning */
	atomic_set(&entry->refcount, 2);
	kref_init(&entry->refcount);
	kref_get(&entry->refcount);

	hash_added = batadv_hash_add(bat_priv->bla.backbone_hash,
				     batadv_compare_backbone_gw,
@@ -634,7 +654,8 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
		claim->lasttime = jiffies;
		claim->backbone_gw = backbone_gw;

		atomic_set(&claim->refcount, 2);
		kref_init(&claim->refcount);
		kref_get(&claim->refcount);
		batadv_dbg(BATADV_DBG_BLA, bat_priv,
			   "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n",
			   mac, BATADV_PRINT_VID(vid));
@@ -664,7 +685,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
		batadv_backbone_gw_free_ref(claim->backbone_gw);
	}
	/* set (new) backbone gw */
	atomic_inc(&backbone_gw->refcount);
	kref_get(&backbone_gw->refcount);
	claim->backbone_gw = backbone_gw;

	spin_lock_bh(&backbone_gw->crc_lock);
+22 −7
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <linux/in.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
@@ -61,15 +62,28 @@ static void batadv_dat_start_timer(struct batadv_priv *bat_priv)
			   msecs_to_jiffies(10000));
}

/**
 * batadv_dat_entry_release - release dat_entry from lists and queue for free
 *  after rcu grace period
 * @ref: kref pointer of the dat_entry
 */
static void batadv_dat_entry_release(struct kref *ref)
{
	struct batadv_dat_entry *dat_entry;

	dat_entry = container_of(ref, struct batadv_dat_entry, refcount);

	kfree_rcu(dat_entry, rcu);
}

/**
 * batadv_dat_entry_free_ref - decrement the dat_entry refcounter and possibly
 * free it
 * @dat_entry: the entry to free
 *  release it
 * @dat_entry: dat_entry to be free'd
 */
static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry)
{
	if (atomic_dec_and_test(&dat_entry->refcount))
		kfree_rcu(dat_entry, rcu);
	kref_put(&dat_entry->refcount, batadv_dat_entry_release);
}

/**
@@ -281,7 +295,7 @@ batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip,
		if (dat_entry->ip != ip)
			continue;

		if (!atomic_inc_not_zero(&dat_entry->refcount))
		if (!kref_get_unless_zero(&dat_entry->refcount))
			continue;

		dat_entry_tmp = dat_entry;
@@ -326,7 +340,8 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
	dat_entry->vid = vid;
	ether_addr_copy(dat_entry->mac_addr, mac_addr);
	dat_entry->last_update = jiffies;
	atomic_set(&dat_entry->refcount, 2);
	kref_init(&dat_entry->refcount);
	kref_get(&dat_entry->refcount);

	hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
				     batadv_hash_dat, dat_entry,
@@ -527,7 +542,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
							  max_orig_node))
				continue;

			if (!atomic_inc_not_zero(&orig_node->refcount))
			if (!kref_get_unless_zero(&orig_node->refcount))
				continue;

			max = tmp_max;
+31 −13
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/rculist.h>
@@ -59,12 +60,29 @@
 */
#define BATADV_DHCP_CHADDR_OFFSET	28

static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node)
/**
 * batadv_gw_node_release - release gw_node from lists and queue for free after
 *  rcu grace period
 * @ref: kref pointer of the gw_node
 */
static void batadv_gw_node_release(struct kref *ref)
{
	if (atomic_dec_and_test(&gw_node->refcount)) {
	struct batadv_gw_node *gw_node;

	gw_node = container_of(ref, struct batadv_gw_node, refcount);

	batadv_orig_node_free_ref(gw_node->orig_node);
	kfree_rcu(gw_node, rcu);
}

/**
 * batadv_gw_node_free_ref - decrement the gw_node refcounter and possibly
 *  release it
 * @gw_node: gateway node to free
 */
static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node)
{
	kref_put(&gw_node->refcount, batadv_gw_node_release);
}

static struct batadv_gw_node *
@@ -77,7 +95,7 @@ batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv)
	if (!gw_node)
		goto out;

	if (!atomic_inc_not_zero(&gw_node->refcount))
	if (!kref_get_unless_zero(&gw_node->refcount))
		gw_node = NULL;

out:
@@ -100,7 +118,7 @@ batadv_gw_get_selected_orig(struct batadv_priv *bat_priv)
	if (!orig_node)
		goto unlock;

	if (!atomic_inc_not_zero(&orig_node->refcount))
	if (!kref_get_unless_zero(&orig_node->refcount))
		orig_node = NULL;

unlock:
@@ -118,7 +136,7 @@ static void batadv_gw_select(struct batadv_priv *bat_priv,

	spin_lock_bh(&bat_priv->gw.list_lock);

	if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
	if (new_gw_node && !kref_get_unless_zero(&new_gw_node->refcount))
		new_gw_node = NULL;

	curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1);
@@ -170,7 +188,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
		if (!router_ifinfo)
			goto next;

		if (!atomic_inc_not_zero(&gw_node->refcount))
		if (!kref_get_unless_zero(&gw_node->refcount))
			goto next;

		tq_avg = router_ifinfo->bat_iv.tq_avg;
@@ -188,7 +206,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
				if (curr_gw)
					batadv_gw_node_free_ref(curr_gw);
				curr_gw = gw_node;
				atomic_inc(&curr_gw->refcount);
				kref_get(&curr_gw->refcount);
			}
			break;

@@ -203,7 +221,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
				if (curr_gw)
					batadv_gw_node_free_ref(curr_gw);
				curr_gw = gw_node;
				atomic_inc(&curr_gw->refcount);
				kref_get(&curr_gw->refcount);
			}
			break;
		}
@@ -423,7 +441,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
	if (gateway->bandwidth_down == 0)
		return;

	if (!atomic_inc_not_zero(&orig_node->refcount))
	if (!kref_get_unless_zero(&orig_node->refcount))
		return;

	gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
@@ -436,7 +454,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
	gw_node->orig_node = orig_node;
	gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
	gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
	atomic_set(&gw_node->refcount, 1);
	kref_init(&gw_node->refcount);

	spin_lock_bh(&bat_priv->gw.list_lock);
	hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list);
@@ -469,7 +487,7 @@ batadv_gw_node_get(struct batadv_priv *bat_priv,
		if (gw_node_tmp->orig_node != orig_node)
			continue;

		if (!atomic_inc_not_zero(&gw_node_tmp->refcount))
		if (!kref_get_unless_zero(&gw_node_tmp->refcount))
			continue;

		gw_node = gw_node_tmp;
+17 −8
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include "hard-interface.h"
#include "main.h"

#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/errno.h>
@@ -26,6 +27,7 @@
#include <linux/if_ether.h>
#include <linux/if.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/printk.h>
@@ -47,13 +49,19 @@
#include "sysfs.h"
#include "translation-table.h"

void batadv_hardif_free_rcu(struct rcu_head *rcu)
/**
 * batadv_hardif_release - release hard interface from lists and queue for
 *  free after rcu grace period
 * @ref: kref pointer of the hard interface
 */
void batadv_hardif_release(struct kref *ref)
{
	struct batadv_hard_iface *hard_iface;

	hard_iface = container_of(rcu, struct batadv_hard_iface, rcu);
	hard_iface = container_of(ref, struct batadv_hard_iface, refcount);
	dev_put(hard_iface->net_dev);
	kfree(hard_iface);

	kfree_rcu(hard_iface, rcu);
}

struct batadv_hard_iface *
@@ -64,7 +72,7 @@ batadv_hardif_get_by_netdev(const struct net_device *net_dev)
	rcu_read_lock();
	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
		if (hard_iface->net_dev == net_dev &&
		    atomic_inc_not_zero(&hard_iface->refcount))
		    kref_get_unless_zero(&hard_iface->refcount))
			goto out;
	}

@@ -169,7 +177,7 @@ batadv_hardif_get_active(const struct net_device *soft_iface)
			continue;

		if (hard_iface->if_status == BATADV_IF_ACTIVE &&
		    atomic_inc_not_zero(&hard_iface->refcount))
		    kref_get_unless_zero(&hard_iface->refcount))
			goto out;
	}

@@ -203,7 +211,7 @@ static void batadv_primary_if_select(struct batadv_priv *bat_priv,

	ASSERT_RTNL();

	if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
	if (new_hard_iface && !kref_get_unless_zero(&new_hard_iface->refcount))
		new_hard_iface = NULL;

	curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1);
@@ -431,7 +439,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
		goto out;

	if (!atomic_inc_not_zero(&hard_iface->refcount))
	if (!kref_get_unless_zero(&hard_iface->refcount))
		goto out;

	soft_iface = dev_get_by_name(&init_net, iface_name);
@@ -652,7 +660,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
		hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;

	/* extra reference for return */
	atomic_set(&hard_iface->refcount, 2);
	kref_init(&hard_iface->refcount);
	kref_get(&hard_iface->refcount);

	batadv_check_known_mac_addr(hard_iface->net_dev);
	list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
Loading