Repository : ssh://git@open-mesh.org/batman-adv
On branch : master
>---------------------------------------------------------------
commit 5b95c427d18799a5cd069dcdce5fecda44e19614
Author: Sven Eckelmann <sven(a)narfation.org>
Date: Sun Jun 21 14:45:14 2015 +0200
batman-adv: Annotate deleting functions with external lock via lockdep
Functions which use (h)list_del* are requiring correct locking when they
operate on global lists. Most of the time the search in the list and the
delete are done in the same function. All other cases should have it
visible that they require a special lock to avoid race conditions.
Lockdep asserts can be used to check these problem during runtime when the
lockdep functionality is enabled.
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
>---------------------------------------------------------------
5b95c427d18799a5cd069dcdce5fecda44e19614
net/batman-adv/main.c | 11 ++++++++---
net/batman-adv/multicast.c | 13 +++++++++++--
net/batman-adv/network-coding.c | 4 ++++
net/batman-adv/translation-table.c | 2 ++
4 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index d277ba7..50fc07b 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -30,6 +30,7 @@
#include <linux/ipv6.h>
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/lockdep.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
@@ -737,13 +738,17 @@ static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
/**
* batadv_tvlv_container_remove - remove tvlv container from the tvlv container
* list
+ * @bat_priv: the bat priv with all the soft interface information
* @tvlv: the to be removed tvlv container
*
* Has to be called with the appropriate locks being acquired
* (tvlv.container_list_lock).
*/
-static void batadv_tvlv_container_remove(struct batadv_tvlv_container *tvlv)
+static void batadv_tvlv_container_remove(struct batadv_priv *bat_priv,
+ struct batadv_tvlv_container *tvlv)
{
+ lockdep_assert_held(&bat_priv->tvlv.handler_list_lock);
+
if (!tvlv)
return;
@@ -768,7 +773,7 @@ void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv,
spin_lock_bh(&bat_priv->tvlv.container_list_lock);
tvlv = batadv_tvlv_container_get(bat_priv, type, version);
- batadv_tvlv_container_remove(tvlv);
+ batadv_tvlv_container_remove(bat_priv, tvlv);
spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
}
@@ -807,7 +812,7 @@ void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
spin_lock_bh(&bat_priv->tvlv.container_list_lock);
tvlv_old = batadv_tvlv_container_get(bat_priv, type, version);
- batadv_tvlv_container_remove(tvlv_old);
+ batadv_tvlv_container_remove(bat_priv, tvlv_old);
hlist_add_head(&tvlv_new->list, &bat_priv->tvlv.container_list);
spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
}
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index 8fa9af2..63bf8e9 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -31,6 +31,7 @@
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/list.h>
+#include <linux/lockdep.h>
#include <linux/netdevice.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
@@ -103,15 +104,19 @@ static bool batadv_mcast_mla_is_duplicate(u8 *mcast_addr,
/**
* batadv_mcast_mla_list_free - free a list of multicast addresses
+ * @bat_priv: the bat priv with all the soft interface information
* @mcast_list: the list to free
*
* Removes and frees all items in the given mcast_list.
*/
-static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list)
+static void batadv_mcast_mla_list_free(struct batadv_priv *bat_priv,
+ struct hlist_head *mcast_list)
{
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;
+ lockdep_assert_held(&bat_priv->tt.commit_lock);
+
hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
hlist_del(&mcast_entry->list);
kfree(mcast_entry);
@@ -134,6 +139,8 @@ static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;
+ lockdep_assert_held(&bat_priv->tt.commit_lock);
+
hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list,
list) {
if (mcast_list &&
@@ -164,6 +171,8 @@ static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;
+ lockdep_assert_held(&bat_priv->tt.commit_lock);
+
if (!mcast_list)
return;
@@ -268,7 +277,7 @@ update:
batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
out:
- batadv_mcast_mla_list_free(&mcast_list);
+ batadv_mcast_mla_list_free(bat_priv, &mcast_list);
}
/**
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index bfd5fe9..b07c57b 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -586,6 +586,8 @@ static bool batadv_nc_sniffed_purge(struct batadv_priv *bat_priv,
unsigned long timeout = bat_priv->nc.max_buffer_time;
bool res = false;
+ lockdep_assert_held(&nc_path->packet_list_lock);
+
/* Packets are added to tail, so the remaining packets did not time
* out and we can stop processing the current queue
*/
@@ -622,6 +624,8 @@ static bool batadv_nc_fwd_flush(struct batadv_priv *bat_priv,
{
unsigned long timeout = bat_priv->nc.max_fwd_delay;
+ lockdep_assert_held(&nc_path->packet_list_lock);
+
/* Packets are added to tail, so the remaining packets did not time
* out and we can stop processing the current queue
*/
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 53e52e1..66a9bf2 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1669,6 +1669,8 @@ static void
_batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
struct batadv_tt_orig_list_entry *orig_entry)
{
+ lockdep_assert_held(&tt_global_entry->list_lock);
+
batadv_tt_global_size_dec(orig_entry->orig_node,
tt_global_entry->common.vid);
atomic_dec(&tt_global_entry->orig_list_count);
Repository : ssh://git@open-mesh.org/batman-adv
Branch 'master' now includes:
013aab3 batman-adv: Replace gw_reselect 64 bit div with shift
a8c7689 Merge branch 'maint' into next
e9eeb93 Merge branch 'next'
Repository : ssh://git@open-mesh.org/batman-adv
Branch 'next' now includes:
013aab3 batman-adv: Replace gw_reselect 64 bit div with shift
a8c7689 Merge branch 'maint' into next
Repository : ssh://git@open-mesh.org/batman-adv
On branch : maint
>---------------------------------------------------------------
commit 013aab341e246a565b1ba96557123a6b7b98e08d
Author: Sven Eckelmann <sven(a)narfation.org>
Date: Mon Jun 22 09:13:23 2015 +0200
batman-adv: Replace gw_reselect 64 bit div with shift
The 64-bit gw_factor is divided by BATADV_TQ_LOCAL_WINDOW_SIZE ** 2 * 64.
But the rest of the calculation has nothing to do with the tq window size
end therefore the calculation is just (tmp_gw_factor / (64 ** 3)).
The problem with 64 bit div is that it doesn't work on systems without
native 64 bit div support. It has to be emulated using do_div or div_u64.
The change in f63c54bba31d ("batman-adv: Avoid u32 overflow during gateway
select") only compiled on such systems because the compiler converted the
div to a (tmp_gw_factor >> 18). Making this explicit avoids having build
problems in the future when BATADV_TQ_LOCAL_WINDOW_SIZE is changed in such
a way that (BATADV_TQ_LOCAL_WINDOW_SIZE ** 2 * 64) is not a power of two.
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
>---------------------------------------------------------------
013aab341e246a565b1ba96557123a6b7b98e08d
gateway_client.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/gateway_client.c b/gateway_client.c
index d8e3ead..e395abe 100644
--- a/gateway_client.c
+++ b/gateway_client.c
@@ -134,14 +134,10 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
struct batadv_neigh_ifinfo *router_ifinfo;
struct batadv_gw_node *gw_node, *curr_gw = NULL;
uint64_t max_gw_factor = 0, tmp_gw_factor = 0;
- uint32_t gw_divisor;
uint8_t max_tq = 0;
uint8_t tq_avg;
struct batadv_orig_node *orig_node;
- gw_divisor = BATADV_TQ_LOCAL_WINDOW_SIZE * BATADV_TQ_LOCAL_WINDOW_SIZE;
- gw_divisor *= 64;
-
rcu_read_lock();
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
if (gw_node->deleted)
@@ -167,7 +163,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
tmp_gw_factor = tq_avg * tq_avg;
tmp_gw_factor *= gw_node->bandwidth_down;
tmp_gw_factor *= 100 * 100;
- tmp_gw_factor /= gw_divisor;
+ tmp_gw_factor >>= 18;
if ((tmp_gw_factor > max_gw_factor) ||
((tmp_gw_factor == max_gw_factor) &&