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.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJWu1z7AAoJENpFlCjNi1MRD5YP+weJeSek2q9A7Of9BXAGFhjn
 YaqPxj0jAEeYLD3MUPoAUD+gkfHwD1bBxgXTXbK5mYYvnkkbXpl/Rm1jr+YFCGYp
 q8v/ks3Ncm5EbGXv2GzuC6BEzSlHQfLOnK+5MjPMxw5c/iQlgG2Oa25SVbHPRehk
 mv2NS7n6jhm4TdDIcBMcmxz+kJjgJqEIakmKzOG4NLOFKJytVmcnU246eJ3hST1+
 jRzVdxyZ5yNrNvc46/LbmLvRs7y0R7WktkX9s3xB02z37Xarrx4GVX12j30yu4/P
 5nhoKXuiz3Ravr1ZvZiJ5eP9m+uFtMSG6PztEvbwwABLn/GTJnu8GZO5BpfcNl6x
 DZEG4JRqx4nWmeZ32WnQcGLs2fJzkYhakILkJuFA3627mXNtVHTCZurEjGi3LTIr
 FiURbn/LRVAtJ+0wmdVKj4pAL6AucR0EdGnPNFAOMS4LHwZDqkUI6UDCypLiGXUD
 YT/7GOKzUTd0l6nh1bici20mjrUeQXoZK1P4pkwXovq7S+S1D7H8EalGlzVDaDZy
 hwEVwkQupN9R6gkKOJ5J4Tbk+uF2+kS7BDgOUObYk0csGxa59eApT/lG3rsdHutn
 2fsC6JCZ/daLqy4YleK4s507eyKukTTnpfluWZRg/wEuMrxWAEcFn+fC6oIXoH4Y
 C4CTHpsaOncZhGC4Vmoc
 =Qo6q
 -----END PGP SIGNATURE-----

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: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2016-02-11 03:49:55 -05:00
commit 30c1de08dd
18 changed files with 407 additions and 195 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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
/**
* 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)
{
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)
{
if (atomic_dec_and_test(&gw_node->refcount)) {
batadv_orig_node_free_ref(gw_node->orig_node);
kfree_rcu(gw_node, rcu);
}
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;

View file

@ -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);

View file

@ -20,8 +20,8 @@
#include "main.h"
#include <linux/atomic.h>
#include <linux/compiler.h>
#include <linux/kref.h>
#include <linux/notifier.h>
#include <linux/rcupdate.h>
#include <linux/stddef.h>
@ -61,18 +61,16 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
void batadv_hardif_remove_interfaces(void);
int batadv_hardif_min_mtu(struct net_device *soft_iface);
void batadv_update_min_mtu(struct net_device *soft_iface);
void batadv_hardif_free_rcu(struct rcu_head *rcu);
void batadv_hardif_release(struct kref *ref);
/**
* batadv_hardif_free_ref - decrement the hard interface refcounter and
* possibly free it
* batadv_hardif_free_ref - decrement the hard interface refcounter and possibly
* release it
* @hard_iface: the hard interface to free
*/
static inline void
batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface)
static inline void batadv_hardif_free_ref(struct batadv_hard_iface *hard_iface)
{
if (atomic_dec_and_test(&hard_iface->refcount))
call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu);
kref_put(&hard_iface->refcount, batadv_hardif_release);
}
static inline struct batadv_hard_iface *
@ -85,7 +83,7 @@ batadv_primary_if_get_selected(struct batadv_priv *bat_priv)
if (!hard_iface)
goto out;
if (!atomic_inc_not_zero(&hard_iface->refcount))
if (!kref_get_unless_zero(&hard_iface->refcount))
hard_iface = NULL;
out:

View file

@ -29,6 +29,7 @@
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/module.h>
@ -624,15 +625,27 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr)
}
/**
* batadv_tvlv_handler_free_ref - decrement the tvlv handler refcounter and
* possibly free it
* batadv_tvlv_handler_release - release tvlv handler from lists and queue for
* free after rcu grace period
* @ref: kref pointer of the tvlv
*/
static void batadv_tvlv_handler_release(struct kref *ref)
{
struct batadv_tvlv_handler *tvlv_handler;
tvlv_handler = container_of(ref, struct batadv_tvlv_handler, refcount);
kfree_rcu(tvlv_handler, rcu);
}
/**
* batadv_tvlv_handler_free_ref - decrement the tvlv container refcounter and
* possibly release it
* @tvlv_handler: the tvlv handler to free
*/
static void
batadv_tvlv_handler_free_ref(struct batadv_tvlv_handler *tvlv_handler)
{
if (atomic_dec_and_test(&tvlv_handler->refcount))
kfree_rcu(tvlv_handler, rcu);
kref_put(&tvlv_handler->refcount, batadv_tvlv_handler_release);
}
/**
@ -658,7 +671,7 @@ static struct batadv_tvlv_handler
if (tvlv_handler_tmp->version != version)
continue;
if (!atomic_inc_not_zero(&tvlv_handler_tmp->refcount))
if (!kref_get_unless_zero(&tvlv_handler_tmp->refcount))
continue;
tvlv_handler = tvlv_handler_tmp;
@ -669,15 +682,26 @@ static struct batadv_tvlv_handler
return tvlv_handler;
}
/**
* batadv_tvlv_container_release - release tvlv from lists and free
* @ref: kref pointer of the tvlv
*/
static void batadv_tvlv_container_release(struct kref *ref)
{
struct batadv_tvlv_container *tvlv;
tvlv = container_of(ref, struct batadv_tvlv_container, refcount);
kfree(tvlv);
}
/**
* batadv_tvlv_container_free_ref - decrement the tvlv container refcounter and
* possibly free it
* possibly release it
* @tvlv: the tvlv container to free
*/
static void batadv_tvlv_container_free_ref(struct batadv_tvlv_container *tvlv)
{
if (atomic_dec_and_test(&tvlv->refcount))
kfree(tvlv);
kref_put(&tvlv->refcount, batadv_tvlv_container_release);
}
/**
@ -697,6 +721,8 @@ static struct batadv_tvlv_container
{
struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL;
lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) {
if (tvlv_tmp->tvlv_hdr.type != type)
continue;
@ -704,7 +730,7 @@ static struct batadv_tvlv_container
if (tvlv_tmp->tvlv_hdr.version != version)
continue;
if (!atomic_inc_not_zero(&tvlv_tmp->refcount))
if (!kref_get_unless_zero(&tvlv_tmp->refcount))
continue;
tvlv = tvlv_tmp;
@ -729,6 +755,8 @@ static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
struct batadv_tvlv_container *tvlv;
u16 tvlv_len = 0;
lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
tvlv_len += sizeof(struct batadv_tvlv_hdr);
tvlv_len += ntohs(tvlv->tvlv_hdr.len);
@ -810,7 +838,7 @@ void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len));
INIT_HLIST_NODE(&tvlv_new->list);
atomic_set(&tvlv_new->refcount, 1);
kref_init(&tvlv_new->refcount);
spin_lock_bh(&bat_priv->tvlv.container_list_lock);
tvlv_old = batadv_tvlv_container_get(bat_priv, type, version);
@ -1096,7 +1124,7 @@ void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
tvlv_handler->type = type;
tvlv_handler->version = version;
tvlv_handler->flags = flags;
atomic_set(&tvlv_handler->refcount, 1);
kref_init(&tvlv_handler->refcount);
INIT_HLIST_NODE(&tvlv_handler->list);
spin_lock_bh(&bat_priv->tvlv.handler_list_lock);

View file

@ -35,6 +35,9 @@
/* Time To Live of broadcast messages */
#define BATADV_TTL 50
/* maximum sequence number age of broadcast messages */
#define BATADV_BCAST_MAX_AGE 64
/* purge originators after time in seconds if no valid packet comes in
* -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE
*/

View file

@ -30,6 +30,7 @@
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/netdevice.h>
@ -447,7 +448,7 @@ batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv)
hlist_for_each_entry_rcu(tmp_orig_node,
&bat_priv->mcast.want_all_ipv4_list,
mcast_want_all_ipv4_node) {
if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
if (!kref_get_unless_zero(&tmp_orig_node->refcount))
continue;
orig_node = tmp_orig_node;
@ -474,7 +475,7 @@ batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv)
hlist_for_each_entry_rcu(tmp_orig_node,
&bat_priv->mcast.want_all_ipv6_list,
mcast_want_all_ipv6_node) {
if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
if (!kref_get_unless_zero(&tmp_orig_node->refcount))
continue;
orig_node = tmp_orig_node;
@ -525,7 +526,7 @@ batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv)
hlist_for_each_entry_rcu(tmp_orig_node,
&bat_priv->mcast.want_all_unsnoopables_list,
mcast_want_all_unsnoopables_node) {
if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
if (!kref_get_unless_zero(&tmp_orig_node->refcount))
continue;
orig_node = tmp_orig_node;

View file

@ -32,6 +32,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>
@ -209,34 +210,50 @@ void batadv_nc_init_orig(struct batadv_orig_node *orig_node)
/**
* batadv_nc_node_release - release nc_node from lists and queue for free after
* rcu grace period
* @nc_node: the nc node to free
* @ref: kref pointer of the nc_node
*/
static void batadv_nc_node_release(struct batadv_nc_node *nc_node)
static void batadv_nc_node_release(struct kref *ref)
{
struct batadv_nc_node *nc_node;
nc_node = container_of(ref, struct batadv_nc_node, refcount);
batadv_orig_node_free_ref(nc_node->orig_node);
kfree_rcu(nc_node, rcu);
}
/**
* batadv_nc_node_free_ref - decrement the nc node refcounter and possibly
* batadv_nc_node_free_ref - decrement the nc_node refcounter and possibly
* release it
* @nc_node: the nc node to free
* @nc_node: nc_node to be free'd
*/
static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node)
{
if (atomic_dec_and_test(&nc_node->refcount))
batadv_nc_node_release(nc_node);
kref_put(&nc_node->refcount, batadv_nc_node_release);
}
/**
* batadv_nc_path_free_ref - decrements the nc path refcounter and possibly
* frees it
* @nc_path: the nc node to free
* batadv_nc_path_release - release nc_path from lists and queue for free after
* rcu grace period
* @ref: kref pointer of the nc_path
*/
static void batadv_nc_path_release(struct kref *ref)
{
struct batadv_nc_path *nc_path;
nc_path = container_of(ref, struct batadv_nc_path, refcount);
kfree_rcu(nc_path, rcu);
}
/**
* batadv_nc_path_free_ref - decrement the nc_path refcounter and possibly
* release it
* @nc_path: nc_path to be free'd
*/
static void batadv_nc_path_free_ref(struct batadv_nc_path *nc_path)
{
if (atomic_dec_and_test(&nc_path->refcount))
kfree_rcu(nc_path, rcu);
kref_put(&nc_path->refcount, batadv_nc_path_release);
}
/**
@ -541,7 +558,7 @@ batadv_nc_hash_find(struct batadv_hashtable *hash,
if (!batadv_nc_hash_compare(&nc_path->hash_entry, data))
continue;
if (!atomic_inc_not_zero(&nc_path->refcount))
if (!kref_get_unless_zero(&nc_path->refcount))
continue;
nc_path_tmp = nc_path;
@ -797,7 +814,7 @@ static struct batadv_nc_node
if (!batadv_compare_eth(nc_node->addr, orig_node->orig))
continue;
if (!atomic_inc_not_zero(&nc_node->refcount))
if (!kref_get_unless_zero(&nc_node->refcount))
continue;
/* Found a match */
@ -841,14 +858,15 @@ static struct batadv_nc_node
if (!nc_node)
return NULL;
if (!atomic_inc_not_zero(&orig_neigh_node->refcount))
if (!kref_get_unless_zero(&orig_neigh_node->refcount))
goto free;
/* Initialize nc_node */
INIT_LIST_HEAD(&nc_node->list);
ether_addr_copy(nc_node->addr, orig_node->orig);
nc_node->orig_node = orig_neigh_node;
atomic_set(&nc_node->refcount, 2);
kref_init(&nc_node->refcount);
kref_get(&nc_node->refcount);
/* Select ingoing or outgoing coding node */
if (in_coding) {
@ -967,7 +985,8 @@ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv,
/* Initialize nc_path */
INIT_LIST_HEAD(&nc_path->packet_list);
spin_lock_init(&nc_path->packet_list_lock);
atomic_set(&nc_path->refcount, 2);
kref_init(&nc_path->refcount);
kref_get(&nc_path->refcount);
nc_path->last_valid = jiffies;
ether_addr_copy(nc_path->next_hop, dst);
ether_addr_copy(nc_path->prev_hop, src);

View file

@ -18,11 +18,13 @@
#include "originator.h"
#include "main.h"
#include <linux/atomic.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
#include <linux/fs.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>
@ -81,7 +83,7 @@ batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
if (tmp->vid != vid)
continue;
if (!atomic_inc_not_zero(&tmp->refcount))
if (!kref_get_unless_zero(&tmp->refcount))
continue;
vlan = tmp;
@ -122,7 +124,8 @@ batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
if (!vlan)
goto out;
atomic_set(&vlan->refcount, 2);
kref_init(&vlan->refcount);
kref_get(&vlan->refcount);
vlan->vid = vid;
hlist_add_head_rcu(&vlan->list, &orig_node->vlan_list);
@ -134,14 +137,27 @@ out:
}
/**
* batadv_orig_node_vlan_free_ref - decrement the refcounter and possibly free
* the originator-vlan object
* batadv_orig_node_vlan_release - release originator-vlan object from lists
* and queue for free after rcu grace period
* @ref: kref pointer of the originator-vlan object
*/
static void batadv_orig_node_vlan_release(struct kref *ref)
{
struct batadv_orig_node_vlan *orig_vlan;
orig_vlan = container_of(ref, struct batadv_orig_node_vlan, refcount);
kfree_rcu(orig_vlan, rcu);
}
/**
* batadv_orig_node_vlan_free_ref - decrement the refcounter and possibly
* release the originator-vlan object
* @orig_vlan: the originator-vlan object to release
*/
void batadv_orig_node_vlan_free_ref(struct batadv_orig_node_vlan *orig_vlan)
{
if (atomic_dec_and_test(&orig_vlan->refcount))
kfree_rcu(orig_vlan, rcu);
kref_put(&orig_vlan->refcount, batadv_orig_node_vlan_release);
}
int batadv_originator_init(struct batadv_priv *bat_priv)
@ -171,11 +187,14 @@ err:
/**
* batadv_neigh_ifinfo_release - release neigh_ifinfo from lists and queue for
* free after rcu grace period
* @neigh_ifinfo: the neigh_ifinfo object to release
* @ref: kref pointer of the neigh_ifinfo
*/
static void
batadv_neigh_ifinfo_release(struct batadv_neigh_ifinfo *neigh_ifinfo)
static void batadv_neigh_ifinfo_release(struct kref *ref)
{
struct batadv_neigh_ifinfo *neigh_ifinfo;
neigh_ifinfo = container_of(ref, struct batadv_neigh_ifinfo, refcount);
if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
batadv_hardif_free_ref(neigh_ifinfo->if_outgoing);
@ -189,18 +208,21 @@ batadv_neigh_ifinfo_release(struct batadv_neigh_ifinfo *neigh_ifinfo)
*/
void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo)
{
if (atomic_dec_and_test(&neigh_ifinfo->refcount))
batadv_neigh_ifinfo_release(neigh_ifinfo);
kref_put(&neigh_ifinfo->refcount, batadv_neigh_ifinfo_release);
}
/**
* batadv_hardif_neigh_release - release hardif neigh node from lists and
* queue for free after rcu grace period
* @hardif_neigh: hardif neigh neighbor to free
* @ref: kref pointer of the neigh_node
*/
static void
batadv_hardif_neigh_release(struct batadv_hardif_neigh_node *hardif_neigh)
static void batadv_hardif_neigh_release(struct kref *ref)
{
struct batadv_hardif_neigh_node *hardif_neigh;
hardif_neigh = container_of(ref, struct batadv_hardif_neigh_node,
refcount);
spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
hlist_del_init_rcu(&hardif_neigh->list);
spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
@ -216,22 +238,23 @@ batadv_hardif_neigh_release(struct batadv_hardif_neigh_node *hardif_neigh)
*/
void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh)
{
if (atomic_dec_and_test(&hardif_neigh->refcount))
batadv_hardif_neigh_release(hardif_neigh);
kref_put(&hardif_neigh->refcount, batadv_hardif_neigh_release);
}
/**
* batadv_neigh_node_release - release neigh_node from lists and queue for
* free after rcu grace period
* @neigh_node: neigh neighbor to free
* @ref: kref pointer of the neigh_node
*/
static void batadv_neigh_node_release(struct batadv_neigh_node *neigh_node)
static void batadv_neigh_node_release(struct kref *ref)
{
struct hlist_node *node_tmp;
struct batadv_neigh_node *neigh_node;
struct batadv_hardif_neigh_node *hardif_neigh;
struct batadv_neigh_ifinfo *neigh_ifinfo;
struct batadv_algo_ops *bao;
neigh_node = container_of(ref, struct batadv_neigh_node, refcount);
bao = neigh_node->orig_node->bat_priv->bat_algo_ops;
hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
@ -256,14 +279,13 @@ static void batadv_neigh_node_release(struct batadv_neigh_node *neigh_node)
}
/**
* batadv_neigh_node_free_ref - decrement the neighbors refcounter
* and possibly release it
* batadv_neigh_node_free_ref - decrement the neighbors refcounter and possibly
* release it
* @neigh_node: neigh neighbor to free
*/
void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node)
{
if (atomic_dec_and_test(&neigh_node->refcount))
batadv_neigh_node_release(neigh_node);
kref_put(&neigh_node->refcount, batadv_neigh_node_release);
}
/**
@ -292,7 +314,7 @@ batadv_orig_router_get(struct batadv_orig_node *orig_node,
break;
}
if (router && !atomic_inc_not_zero(&router->refcount))
if (router && !kref_get_unless_zero(&router->refcount))
router = NULL;
rcu_read_unlock();
@ -320,7 +342,7 @@ batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
if (tmp->if_outgoing != if_outgoing)
continue;
if (!atomic_inc_not_zero(&tmp->refcount))
if (!kref_get_unless_zero(&tmp->refcount))
continue;
orig_ifinfo = tmp;
@ -360,7 +382,7 @@ batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
goto out;
if (if_outgoing != BATADV_IF_DEFAULT &&
!atomic_inc_not_zero(&if_outgoing->refcount)) {
!kref_get_unless_zero(&if_outgoing->refcount)) {
kfree(orig_ifinfo);
orig_ifinfo = NULL;
goto out;
@ -371,7 +393,8 @@ batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
orig_ifinfo->batman_seqno_reset = reset_time;
orig_ifinfo->if_outgoing = if_outgoing;
INIT_HLIST_NODE(&orig_ifinfo->list);
atomic_set(&orig_ifinfo->refcount, 2);
kref_init(&orig_ifinfo->refcount);
kref_get(&orig_ifinfo->refcount);
hlist_add_head_rcu(&orig_ifinfo->list,
&orig_node->ifinfo_list);
out:
@ -401,7 +424,7 @@ batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
if (tmp_neigh_ifinfo->if_outgoing != if_outgoing)
continue;
if (!atomic_inc_not_zero(&tmp_neigh_ifinfo->refcount))
if (!kref_get_unless_zero(&tmp_neigh_ifinfo->refcount))
continue;
neigh_ifinfo = tmp_neigh_ifinfo;
@ -439,14 +462,15 @@ batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
if (!neigh_ifinfo)
goto out;
if (if_outgoing && !atomic_inc_not_zero(&if_outgoing->refcount)) {
if (if_outgoing && !kref_get_unless_zero(&if_outgoing->refcount)) {
kfree(neigh_ifinfo);
neigh_ifinfo = NULL;
goto out;
}
INIT_HLIST_NODE(&neigh_ifinfo->list);
atomic_set(&neigh_ifinfo->refcount, 2);
kref_init(&neigh_ifinfo->refcount);
kref_get(&neigh_ifinfo->refcount);
neigh_ifinfo->if_outgoing = if_outgoing;
hlist_add_head_rcu(&neigh_ifinfo->list, &neigh->ifinfo_list);
@ -483,7 +507,7 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
if (tmp_neigh_node->if_incoming != hard_iface)
continue;
if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
if (!kref_get_unless_zero(&tmp_neigh_node->refcount))
continue;
res = tmp_neigh_node;
@ -515,7 +539,7 @@ batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
if (hardif_neigh)
goto out;
if (!atomic_inc_not_zero(&hard_iface->refcount))
if (!kref_get_unless_zero(&hard_iface->refcount))
goto out;
hardif_neigh = kzalloc(sizeof(*hardif_neigh), GFP_ATOMIC);
@ -529,7 +553,7 @@ batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
hardif_neigh->if_incoming = hard_iface;
hardif_neigh->last_seen = jiffies;
atomic_set(&hardif_neigh->refcount, 1);
kref_init(&hardif_neigh->refcount);
if (bat_priv->bat_algo_ops->bat_hardif_neigh_init)
bat_priv->bat_algo_ops->bat_hardif_neigh_init(hardif_neigh);
@ -584,7 +608,7 @@ batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface,
if (!batadv_compare_eth(tmp_hardif_neigh->addr, neigh_addr))
continue;
if (!atomic_inc_not_zero(&tmp_hardif_neigh->refcount))
if (!kref_get_unless_zero(&tmp_hardif_neigh->refcount))
continue;
hardif_neigh = tmp_hardif_neigh;
@ -626,7 +650,7 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
if (!neigh_node)
goto out;
if (!atomic_inc_not_zero(&hard_iface->refcount)) {
if (!kref_get_unless_zero(&hard_iface->refcount)) {
kfree(neigh_node);
neigh_node = NULL;
goto out;
@ -641,14 +665,15 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
neigh_node->orig_node = orig_node;
/* extra reference for return */
atomic_set(&neigh_node->refcount, 2);
kref_init(&neigh_node->refcount);
kref_get(&neigh_node->refcount);
spin_lock_bh(&orig_node->neigh_list_lock);
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
spin_unlock_bh(&orig_node->neigh_list_lock);
/* increment unique neighbor refcount */
atomic_inc(&hardif_neigh->refcount);
kref_get(&hardif_neigh->refcount);
batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv,
"Creating new neighbor %pM for orig_node %pM on interface %s\n",
@ -697,12 +722,15 @@ int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset)
/**
* batadv_orig_ifinfo_release - release orig_ifinfo from lists and queue for
* free after rcu grace period
* @orig_ifinfo: the orig_ifinfo object to release
* @ref: kref pointer of the orig_ifinfo
*/
static void batadv_orig_ifinfo_release(struct batadv_orig_ifinfo *orig_ifinfo)
static void batadv_orig_ifinfo_release(struct kref *ref)
{
struct batadv_orig_ifinfo *orig_ifinfo;
struct batadv_neigh_node *router;
orig_ifinfo = container_of(ref, struct batadv_orig_ifinfo, refcount);
if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
batadv_hardif_free_ref(orig_ifinfo->if_outgoing);
@ -721,8 +749,7 @@ static void batadv_orig_ifinfo_release(struct batadv_orig_ifinfo *orig_ifinfo)
*/
void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo)
{
if (atomic_dec_and_test(&orig_ifinfo->refcount))
batadv_orig_ifinfo_release(orig_ifinfo);
kref_put(&orig_ifinfo->refcount, batadv_orig_ifinfo_release);
}
/**
@ -749,14 +776,17 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
/**
* batadv_orig_node_release - release orig_node from lists and queue for
* free after rcu grace period
* @orig_node: the orig node to free
* @ref: kref pointer of the orig_node
*/
static void batadv_orig_node_release(struct batadv_orig_node *orig_node)
static void batadv_orig_node_release(struct kref *ref)
{
struct hlist_node *node_tmp;
struct batadv_neigh_node *neigh_node;
struct batadv_orig_node *orig_node;
struct batadv_orig_ifinfo *orig_ifinfo;
orig_node = container_of(ref, struct batadv_orig_node, refcount);
spin_lock_bh(&orig_node->neigh_list_lock);
/* for all neighbors towards this originator ... */
@ -786,8 +816,7 @@ static void batadv_orig_node_release(struct batadv_orig_node *orig_node)
*/
void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node)
{
if (atomic_dec_and_test(&orig_node->refcount))
batadv_orig_node_release(orig_node);
kref_put(&orig_node->refcount, batadv_orig_node_release);
}
void batadv_originator_free(struct batadv_priv *bat_priv)
@ -859,7 +888,8 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
batadv_nc_init_orig(orig_node);
/* extra reference for return */
atomic_set(&orig_node->refcount, 2);
kref_init(&orig_node->refcount);
kref_get(&orig_node->refcount);
orig_node->bat_priv = bat_priv;
ether_addr_copy(orig_node->orig, addr);
@ -1074,7 +1104,7 @@ batadv_find_best_neighbor(struct batadv_priv *bat_priv,
best, if_outgoing) <= 0))
continue;
if (!atomic_inc_not_zero(&neigh->refcount))
if (!kref_get_unless_zero(&neigh->refcount))
continue;
if (best)

View file

@ -20,10 +20,10 @@
#include "main.h"
#include <linux/atomic.h>
#include <linux/compiler.h>
#include <linux/if_ether.h>
#include <linux/jhash.h>
#include <linux/kref.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/stddef.h>
@ -115,7 +115,7 @@ batadv_orig_hash_find(struct batadv_priv *bat_priv, const void *data)
if (!batadv_compare_eth(orig_node, data))
continue;
if (!atomic_inc_not_zero(&orig_node->refcount))
if (!kref_get_unless_zero(&orig_node->refcount))
continue;
orig_node_tmp = orig_node;

View file

@ -25,6 +25,7 @@
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/jiffies.h>
#include <linux/kref.h>
#include <linux/netdevice.h>
#include <linux/printk.h>
#include <linux/rculist.h>
@ -72,7 +73,7 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
rcu_read_lock();
curr_router = rcu_dereference(orig_ifinfo->router);
if (curr_router && !atomic_inc_not_zero(&curr_router->refcount))
if (curr_router && !kref_get_unless_zero(&curr_router->refcount))
curr_router = NULL;
rcu_read_unlock();
@ -100,7 +101,7 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
batadv_neigh_node_free_ref(curr_router);
/* increase refcount of new best neighbor */
if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount))
if (neigh_node && !kref_get_unless_zero(&neigh_node->refcount))
neigh_node = NULL;
spin_lock_bh(&orig_node->neigh_list_lock);
@ -146,23 +147,29 @@ out:
* @bat_priv: the bat priv with all the soft interface information
* @seq_num_diff: difference between the current/received sequence number and
* the last sequence number
* @seq_old_max_diff: maximum age of sequence number not considered as restart
* @last_reset: jiffies timestamp of the last reset, will be updated when reset
* is detected
* @protection_started: is set to true if the protection window was started,
* doesn't change otherwise.
*
* Return:
* 0 if the packet is to be accepted.
* 1 if the packet is to be ignored.
*/
int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
unsigned long *last_reset)
s32 seq_old_max_diff, unsigned long *last_reset,
bool *protection_started)
{
if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE ||
if (seq_num_diff <= -seq_old_max_diff ||
seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) {
if (!batadv_has_timed_out(*last_reset,
BATADV_RESET_PROTECTION_MS))
return 1;
*last_reset = jiffies;
if (protection_started)
*protection_started = true;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"old packet received, start protection\n");
}
@ -491,14 +498,14 @@ batadv_find_router(struct batadv_priv *bat_priv,
hlist_for_each_entry_rcu(cand, &orig_node->ifinfo_list, list) {
/* acquire some structures and references ... */
if (!atomic_inc_not_zero(&cand->refcount))
if (!kref_get_unless_zero(&cand->refcount))
continue;
cand_router = rcu_dereference(cand->router);
if (!cand_router)
goto next;
if (!atomic_inc_not_zero(&cand_router->refcount)) {
if (!kref_get_unless_zero(&cand_router->refcount)) {
cand_router = NULL;
goto next;
}
@ -517,8 +524,8 @@ batadv_find_router(struct batadv_priv *bat_priv,
/* mark the first possible candidate */
if (!first_candidate) {
atomic_inc(&cand_router->refcount);
atomic_inc(&cand->refcount);
kref_get(&cand_router->refcount);
kref_get(&cand->refcount);
first_candidate = cand;
first_candidate_router = cand_router;
}
@ -1073,7 +1080,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
/* check whether the packet is old and the host just restarted. */
if (batadv_window_protected(bat_priv, seq_diff,
&orig_node->bcast_seqno_reset))
BATADV_BCAST_MAX_AGE,
&orig_node->bcast_seqno_reset, NULL))
goto spin_unlock;
/* mark broadcast in flood history, update window position

View file

@ -52,6 +52,7 @@ batadv_find_router(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
struct batadv_hard_iface *recv_if);
int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
unsigned long *last_reset);
s32 seq_old_max_diff, unsigned long *last_reset,
bool *protection_started);
#endif /* _NET_BATMAN_ADV_ROUTING_H_ */

View file

@ -30,6 +30,7 @@
#include <linux/if_vlan.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>
@ -477,9 +478,27 @@ out:
return;
}
/**
* batadv_softif_vlan_release - release vlan from lists and queue for free after
* rcu grace period
* @ref: kref pointer of the vlan object
*/
static void batadv_softif_vlan_release(struct kref *ref)
{
struct batadv_softif_vlan *vlan;
vlan = container_of(ref, struct batadv_softif_vlan, refcount);
spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
hlist_del_rcu(&vlan->list);
spin_unlock_bh(&vlan->bat_priv->softif_vlan_list_lock);
kfree_rcu(vlan, rcu);
}
/**
* batadv_softif_vlan_free_ref - decrease the vlan object refcounter and
* possibly free it
* possibly release it
* @vlan: the vlan object to release
*/
void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
@ -487,13 +506,7 @@ void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
if (!vlan)
return;
if (atomic_dec_and_test(&vlan->refcount)) {
spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
hlist_del_rcu(&vlan->list);
spin_unlock_bh(&vlan->bat_priv->softif_vlan_list_lock);
kfree_rcu(vlan, rcu);
}
kref_put(&vlan->refcount, batadv_softif_vlan_release);
}
/**
@ -514,7 +527,7 @@ struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv,
if (vlan_tmp->vid != vid)
continue;
if (!atomic_inc_not_zero(&vlan_tmp->refcount))
if (!kref_get_unless_zero(&vlan_tmp->refcount))
continue;
vlan = vlan_tmp;
@ -549,7 +562,7 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
vlan->bat_priv = bat_priv;
vlan->vid = vid;
atomic_set(&vlan->refcount, 1);
kref_init(&vlan->refcount);
atomic_set(&vlan->ap_isolation, 0);

View file

@ -25,6 +25,7 @@
#include <linux/fs.h>
#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/kref.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/printk.h>
@ -97,7 +98,7 @@ batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
if (vlan_tmp->kobj != obj)
continue;
if (!atomic_inc_not_zero(&vlan_tmp->refcount))
if (!kref_get_unless_zero(&vlan_tmp->refcount))
continue;
vlan = vlan_tmp;

View file

@ -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>
@ -141,7 +142,7 @@ batadv_tt_hash_find(struct batadv_hashtable *hash, const u8 *addr,
if (tt->vid != vid)
continue;
if (!atomic_inc_not_zero(&tt->refcount))
if (!kref_get_unless_zero(&tt->refcount))
continue;
tt_tmp = tt;
@ -202,25 +203,59 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
return tt_global_entry;
}
static void
batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry)
/**
* batadv_tt_local_entry_release - release tt_local_entry from lists and queue
* for free after rcu grace period
* @ref: kref pointer of the nc_node
*/
static void batadv_tt_local_entry_release(struct kref *ref)
{
if (atomic_dec_and_test(&tt_local_entry->common.refcount))
kfree_rcu(tt_local_entry, common.rcu);
struct batadv_tt_local_entry *tt_local_entry;
tt_local_entry = container_of(ref, struct batadv_tt_local_entry,
common.refcount);
kfree_rcu(tt_local_entry, common.rcu);
}
/**
* batadv_tt_global_entry_free_ref - decrement the refcounter for a
* tt_global_entry and possibly free it
* @tt_global_entry: the object to free
* batadv_tt_local_entry_free_ref - decrement the tt_local_entry refcounter and
* possibly release it
* @tt_local_entry: tt_local_entry to be free'd
*/
static void
batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry)
{
kref_put(&tt_local_entry->common.refcount,
batadv_tt_local_entry_release);
}
/**
* batadv_tt_global_entry_release - release tt_global_entry from lists and queue
* for free after rcu grace period
* @ref: kref pointer of the nc_node
*/
static void batadv_tt_global_entry_release(struct kref *ref)
{
struct batadv_tt_global_entry *tt_global_entry;
tt_global_entry = container_of(ref, struct batadv_tt_global_entry,
common.refcount);
batadv_tt_global_del_orig_list(tt_global_entry);
kfree_rcu(tt_global_entry, common.rcu);
}
/**
* batadv_tt_global_entry_free_ref - decrement the tt_global_entry refcounter
* and possibly release it
* @tt_global_entry: tt_global_entry to be free'd
*/
static void
batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry)
{
if (atomic_dec_and_test(&tt_global_entry->common.refcount)) {
batadv_tt_global_del_orig_list(tt_global_entry);
kfree_rcu(tt_global_entry, common.rcu);
}
kref_put(&tt_global_entry->common.refcount,
batadv_tt_global_entry_release);
}
/**
@ -346,22 +381,28 @@ static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node,
/**
* batadv_tt_orig_list_entry_release - release tt orig entry from lists and
* queue for free after rcu grace period
* @orig_entry: tt orig entry to be free'd
* @ref: kref pointer of the tt orig entry
*/
static void
batadv_tt_orig_list_entry_release(struct batadv_tt_orig_list_entry *orig_entry)
static void batadv_tt_orig_list_entry_release(struct kref *ref)
{
struct batadv_tt_orig_list_entry *orig_entry;
orig_entry = container_of(ref, struct batadv_tt_orig_list_entry,
refcount);
batadv_orig_node_free_ref(orig_entry->orig_node);
kfree_rcu(orig_entry, rcu);
}
/**
* batadv_tt_orig_list_entry_free_ref - decrement the tt orig entry refcounter
* and possibly release it
* @orig_entry: tt orig entry to be free'd
*/
static void
batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
{
if (!atomic_dec_and_test(&orig_entry->refcount))
return;
batadv_tt_orig_list_entry_release(orig_entry);
kref_put(&orig_entry->refcount, batadv_tt_orig_list_entry_release);
}
/**
@ -626,7 +667,8 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
tt_local->common.vid = vid;
if (batadv_is_wifi_netdev(in_dev))
tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
atomic_set(&tt_local->common.refcount, 2);
kref_init(&tt_local->common.refcount);
kref_get(&tt_local->common.refcount);
tt_local->last_seen = jiffies;
tt_local->common.added_at = tt_local->last_seen;
@ -1270,7 +1312,7 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
hlist_for_each_entry_rcu(tmp_orig_entry, head, list) {
if (tmp_orig_entry->orig_node != orig_node)
continue;
if (!atomic_inc_not_zero(&tmp_orig_entry->refcount))
if (!kref_get_unless_zero(&tmp_orig_entry->refcount))
continue;
orig_entry = tmp_orig_entry;
@ -1327,11 +1369,12 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
goto out;
INIT_HLIST_NODE(&orig_entry->list);
atomic_inc(&orig_node->refcount);
kref_get(&orig_node->refcount);
batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
orig_entry->orig_node = orig_node;
orig_entry->ttvn = ttvn;
atomic_set(&orig_entry->refcount, 2);
kref_init(&orig_entry->refcount);
kref_get(&orig_entry->refcount);
spin_lock_bh(&tt_global->list_lock);
hlist_add_head_rcu(&orig_entry->list,
@ -1407,7 +1450,8 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
*/
if (flags & BATADV_TT_CLIENT_ROAM)
tt_global_entry->roam_at = jiffies;
atomic_set(&common->refcount, 2);
kref_init(&common->refcount);
kref_get(&common->refcount);
common->added_at = jiffies;
INIT_HLIST_HEAD(&tt_global_entry->orig_list);
@ -2089,7 +2133,7 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
/* found anything? */
if (best_entry)
orig_node = best_entry->orig_node;
if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
if (orig_node && !kref_get_unless_zero(&orig_node->refcount))
orig_node = NULL;
rcu_read_unlock();

View file

@ -25,6 +25,7 @@
#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/if_ether.h>
#include <linux/kref.h>
#include <linux/netdevice.h>
#include <linux/sched.h> /* for linux/wait.h */
#include <linux/spinlock.h>
@ -110,7 +111,7 @@ struct batadv_hard_iface {
struct net_device *net_dev;
u8 num_bcasts;
struct kobject *hardif_obj;
atomic_t refcount;
struct kref refcount;
struct packet_type batman_adv_ptype;
struct net_device *soft_iface;
struct rcu_head rcu;
@ -140,7 +141,7 @@ struct batadv_orig_ifinfo {
u32 last_real_seqno;
u8 last_ttl;
unsigned long batman_seqno_reset;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -196,7 +197,7 @@ struct batadv_orig_node_vlan {
unsigned short vid;
struct batadv_vlan_tt tt;
struct hlist_node list;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -298,7 +299,7 @@ struct batadv_orig_node {
struct batadv_priv *bat_priv;
/* bcast_seqno_lock protects: bcast_bits & last_bcast_seqno */
spinlock_t bcast_seqno_lock;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
#ifdef CONFIG_BATMAN_ADV_NC
struct list_head in_coding_list;
@ -341,7 +342,7 @@ struct batadv_gw_node {
struct batadv_orig_node *orig_node;
u32 bandwidth_down;
u32 bandwidth_up;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -359,7 +360,7 @@ struct batadv_hardif_neigh_node {
u8 addr[ETH_ALEN];
struct batadv_hard_iface *if_incoming;
unsigned long last_seen;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -383,7 +384,7 @@ struct batadv_neigh_node {
spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */
struct batadv_hard_iface *if_incoming;
unsigned long last_seen;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -419,7 +420,7 @@ struct batadv_neigh_ifinfo {
struct batadv_hard_iface *if_outgoing;
struct batadv_neigh_ifinfo_bat_iv bat_iv;
u8 last_ttl;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -745,7 +746,7 @@ struct batadv_softif_vlan {
atomic_t ap_isolation; /* boolean */
struct batadv_vlan_tt tt;
struct hlist_node list;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -929,7 +930,7 @@ struct batadv_bla_backbone_gw {
atomic_t request_sent;
u16 crc;
spinlock_t crc_lock; /* protects crc */
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -950,7 +951,7 @@ struct batadv_bla_claim {
unsigned long lasttime;
struct hlist_node hash_entry;
struct rcu_head rcu;
atomic_t refcount;
struct kref refcount;
};
#endif
@ -971,7 +972,7 @@ struct batadv_tt_common_entry {
struct hlist_node hash_entry;
u16 flags;
unsigned long added_at;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -1013,7 +1014,7 @@ struct batadv_tt_orig_list_entry {
struct batadv_orig_node *orig_node;
u8 ttvn;
struct hlist_node list;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -1066,7 +1067,7 @@ struct batadv_tt_roam_node {
struct batadv_nc_node {
struct list_head list;
u8 addr[ETH_ALEN];
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
struct batadv_orig_node *orig_node;
unsigned long last_seen;
@ -1086,7 +1087,7 @@ struct batadv_nc_node {
struct batadv_nc_path {
struct hlist_node hash_entry;
struct rcu_head rcu;
atomic_t refcount;
struct kref refcount;
struct list_head packet_list;
spinlock_t packet_list_lock; /* Protects packet_list */
u8 next_hop[ETH_ALEN];
@ -1229,7 +1230,7 @@ struct batadv_dat_entry {
unsigned short vid;
unsigned long last_update;
struct hlist_node hash_entry;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};
@ -1265,7 +1266,7 @@ struct batadv_dat_candidate {
struct batadv_tvlv_container {
struct hlist_node list;
struct batadv_tvlv_hdr tvlv_hdr;
atomic_t refcount;
struct kref refcount;
};
/**
@ -1292,7 +1293,7 @@ struct batadv_tvlv_handler {
u8 type;
u8 version;
u8 flags;
atomic_t refcount;
struct kref refcount;
struct rcu_head rcu;
};