The following commit has been merged in the merge/master branch: commit d1059685e5abf1d63e7938292dd332d376f086e1 Merge: fbb98aa65dbba86c94808204060434393c2ad19e 08ba64d0b558be47b48c1ef275b671b518581d04 Author: Marek Lindner mareklindner@neomailbox.ch Date: Sun Mar 27 15:51:40 2016 +0800
Merge branch 'maint' into next
diff --combined net/batman-adv/routing.c index 4dd646a,7b260e1..b781bf7 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@@ -1,4 -1,4 +1,4 @@@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * @@@ -25,7 -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> @@@ -73,7 -72,7 +73,7 @@@ static void _batadv_update_route(struc
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();
@@@ -98,20 -97,29 +98,29 @@@ }
if (curr_router) - batadv_neigh_node_free_ref(curr_router); + batadv_neigh_node_put(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); + /* curr_router used earlier may not be the current orig_ifinfo->router + * anymore because it was dereferenced outside of the neigh_list_lock + * protected region. After the new best neighbor has replace the current + * best neighbor the reference counter needs to decrease. Consequently, + * the code needs to ensure the curr_router variable contains a pointer + * to the replaced best neighbor. + */ + curr_router = rcu_dereference_protected(orig_ifinfo->router, true); + rcu_assign_pointer(orig_ifinfo->router, neigh_node); spin_unlock_bh(&orig_node->neigh_list_lock); - batadv_orig_ifinfo_free_ref(orig_ifinfo); + batadv_orig_ifinfo_put(orig_ifinfo);
/* decrease refcount of previous best neighbor */ if (curr_router) - batadv_neigh_node_free_ref(curr_router); + batadv_neigh_node_put(curr_router); }
/** @@@ -138,7 -146,7 +147,7 @@@ void batadv_update_route(struct batadv_
out: if (router) - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router); }
/** @@@ -147,29 -155,23 +156,29 @@@ * @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"); } @@@ -269,9 -271,9 +278,9 @@@ static int batadv_recv_my_icmp_packet(s } out: if (primary_if) - batadv_hardif_free_ref(primary_if); + batadv_hardif_put(primary_if); if (orig_node) - batadv_orig_node_free_ref(orig_node); + batadv_orig_node_put(orig_node); return ret; }
@@@ -317,9 -319,9 +326,9 @@@ static int batadv_recv_icmp_ttl_exceede
out: if (primary_if) - batadv_hardif_free_ref(primary_if); + batadv_hardif_put(primary_if); if (orig_node) - batadv_orig_node_free_ref(orig_node); + batadv_orig_node_put(orig_node); return ret; }
@@@ -403,7 -405,7 +412,7 @@@ int batadv_recv_icmp_packet(struct sk_b
out: if (orig_node) - batadv_orig_node_free_ref(orig_node); + batadv_orig_node_put(orig_node); return ret; }
@@@ -498,14 -500,14 +507,14 @@@ batadv_find_router(struct batadv_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; } @@@ -524,8 -526,8 +533,8 @@@
/* 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; } @@@ -545,16 -547,16 +554,16 @@@ next: /* free references */ if (cand_router) { - batadv_neigh_node_free_ref(cand_router); + batadv_neigh_node_put(cand_router); cand_router = NULL; } - batadv_orig_ifinfo_free_ref(cand); + batadv_orig_ifinfo_put(cand); } rcu_read_unlock();
/* last_bonding_candidate is reset below, remove the old reference. */ if (orig_node->last_bonding_candidate) - batadv_orig_ifinfo_free_ref(orig_node->last_bonding_candidate); + batadv_orig_ifinfo_put(orig_node->last_bonding_candidate);
/* After finding candidates, handle the three cases: * 1) there is a next candidate, use that @@@ -562,17 -564,17 +571,17 @@@ * 3) there is no candidate at all, return the default router */ if (next_candidate) { - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router);
/* remove references to first candidate, we don't need it. */ if (first_candidate) { - batadv_neigh_node_free_ref(first_candidate_router); - batadv_orig_ifinfo_free_ref(first_candidate); + batadv_neigh_node_put(first_candidate_router); + batadv_orig_ifinfo_put(first_candidate); } router = next_candidate_router; orig_node->last_bonding_candidate = next_candidate; } else if (first_candidate) { - batadv_neigh_node_free_ref(router); + batadv_neigh_node_put(router);
/* refcounting has already been done in the loop above. */ router = first_candidate_router; @@@ -649,7 -651,7 +658,7 @@@ static int batadv_route_unicast_packet(
out: if (orig_node) - batadv_orig_node_free_ref(orig_node); + batadv_orig_node_put(orig_node); return ret; }
@@@ -702,9 -704,9 +711,9 @@@ batadv_reroute_unicast_packet(struct ba ret = true; out: if (primary_if) - batadv_hardif_free_ref(primary_if); + batadv_hardif_put(primary_if); if (orig_node) - batadv_orig_node_free_ref(orig_node); + batadv_orig_node_put(orig_node);
return ret; } @@@ -768,7 -770,7 +777,7 @@@ static int batadv_check_unicast_ttvn(st return 0;
curr_ttvn = (u8)atomic_read(&orig_node->last_ttvn); - batadv_orig_node_free_ref(orig_node); + batadv_orig_node_put(orig_node); }
/* check if the TTVN contained in the packet is fresher than what the @@@ -808,7 -810,7 +817,7 @@@
ether_addr_copy(unicast_packet->dest, primary_if->net_dev->dev_addr);
- batadv_hardif_free_ref(primary_if); + batadv_hardif_put(primary_if);
unicast_packet->ttvn = curr_ttvn;
@@@ -908,7 -910,7 +917,7 @@@ int batadv_recv_unicast_packet(struct s
rx_success: if (orig_node) - batadv_orig_node_free_ref(orig_node); + batadv_orig_node_put(orig_node);
return NET_RX_SUCCESS; } @@@ -1019,7 -1021,7 +1028,7 @@@ int batadv_recv_frag_packet(struct sk_b
out: if (orig_node_src) - batadv_orig_node_free_ref(orig_node_src); + batadv_orig_node_put(orig_node_src);
return ret; } @@@ -1080,8 -1082,7 +1089,8 @@@ int batadv_recv_bcast_packet(struct sk_
/* 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 @@@ -1124,6 -1125,6 +1133,6 @@@ spin_unlock spin_unlock_bh(&orig_node->bcast_seqno_lock); out: if (orig_node) - batadv_orig_node_free_ref(orig_node); + batadv_orig_node_put(orig_node); return ret; }