Netdev List
 help / color / mirror / Atom feed
* [PATCH 2/8] batman-adv: Make gateway_get_selected type safe
From: Sven Eckelmann @ 2011-04-17 19:30 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r, Marek Lindner
In-Reply-To: <1303068618-27928-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

From: Linus Lüssing <linus.luessing-S0/GAf8tV78@public.gmane.org>

Make the return value explicit instead of (void *).

Signed-off-by: Linus Lüssing <linus.luessing-S0/GAf8tV78@public.gmane.org>
Signed-off-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
Signed-off-by: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
---
 net/batman-adv/gateway_client.c |    2 +-
 net/batman-adv/gateway_client.h |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 3cc4355..27b87ad 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -42,7 +42,7 @@ static void gw_node_free_ref(struct gw_node *gw_node)
 		call_rcu(&gw_node->rcu, gw_node_free_rcu);
 }
 
-void *gw_get_selected(struct bat_priv *bat_priv)
+struct orig_node *gw_get_selected(struct bat_priv *bat_priv)
 {
 	struct gw_node *curr_gateway_tmp;
 	struct orig_node *orig_node = NULL;
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h
index 2aa4391..97c31d1 100644
--- a/net/batman-adv/gateway_client.h
+++ b/net/batman-adv/gateway_client.h
@@ -24,7 +24,7 @@
 
 void gw_deselect(struct bat_priv *bat_priv);
 void gw_election(struct bat_priv *bat_priv);
-void *gw_get_selected(struct bat_priv *bat_priv);
+struct orig_node *gw_get_selected(struct bat_priv *bat_priv);
 void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node);
 void gw_node_update(struct bat_priv *bat_priv,
 		    struct orig_node *orig_node, uint8_t new_gwflags);
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 3/8] batman-adv: Simplify gw_check_election(), use gw_get_selected()
From: Sven Eckelmann @ 2011-04-17 19:30 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r, Marek Lindner
In-Reply-To: <1303068618-27928-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

From: Linus Lüssing <linus.luessing-S0/GAf8tV78@public.gmane.org>

gw_get_selected() can get us the desired orig_node directly, therefore
reusing that function in gw_check_election().

Signed-off-by: Linus Lüssing <linus.luessing-S0/GAf8tV78@public.gmane.org>
Signed-off-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
Signed-off-by: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
---
 net/batman-adv/gateway_client.c |   23 ++++++++++++-----------
 1 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 27b87ad..879ac15 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -23,6 +23,7 @@
 #include "gateway_client.h"
 #include "gateway_common.h"
 #include "hard-interface.h"
+#include "originator.h"
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/udp.h>
@@ -203,28 +204,25 @@ void gw_election(struct bat_priv *bat_priv)
 
 void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
 {
-	struct gw_node *curr_gateway_tmp;
+	struct orig_node *curr_gw_orig;
 	uint8_t gw_tq_avg, orig_tq_avg;
 
+	curr_gw_orig = gw_get_selected(bat_priv);
+	if (!curr_gw_orig)
+		goto deselect;
+
 	rcu_read_lock();
-	curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw);
-	if (!curr_gateway_tmp)
-		goto out_rcu;
-
-	if (!curr_gateway_tmp->orig_node)
-		goto deselect_rcu;
-
-	if (!curr_gateway_tmp->orig_node->router)
+	if (!curr_gw_orig->router)
 		goto deselect_rcu;
 
 	/* this node already is the gateway */
-	if (curr_gateway_tmp->orig_node == orig_node)
+	if (curr_gw_orig == orig_node)
 		goto out_rcu;
 
 	if (!orig_node->router)
 		goto out_rcu;
 
-	gw_tq_avg = curr_gateway_tmp->orig_node->router->tq_avg;
+	gw_tq_avg = curr_gw_orig->router->tq_avg;
 	rcu_read_unlock();
 
 	orig_tq_avg = orig_node->router->tq_avg;
@@ -255,6 +253,9 @@ deselect_rcu:
 deselect:
 	gw_deselect(bat_priv);
 out:
+	if (curr_gw_orig)
+		orig_node_free_ref(curr_gw_orig);
+
 	return;
 }
 
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 4/8] batman-adv: Make orig_node->router an rcu protected pointer
From: Sven Eckelmann @ 2011-04-17 19:30 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r, Marek Lindner
In-Reply-To: <1303068618-27928-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

From: Linus Lüssing <linus.luessing-S0/GAf8tV78@public.gmane.org>

The rcu protected macros rcu_dereference() and rcu_assign_pointer()
for the orig_node->router need to be used, as well as spin/rcu locking.
Otherwise we might end up using a router pointer pointing to already
freed memory.

Therefore this commit introduces the safe getter method
orig_node_get_router().

Signed-off-by: Linus Lüssing <linus.luessing-S0/GAf8tV78@public.gmane.org>
Signed-off-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
Signed-off-by: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
---
 net/batman-adv/gateway_client.c |   80 ++++++++++-------
 net/batman-adv/icmp_socket.c    |   18 +---
 net/batman-adv/originator.c     |   37 ++++++--
 net/batman-adv/originator.h     |    1 +
 net/batman-adv/routing.c        |  194 +++++++++++++++++++--------------------
 net/batman-adv/send.c           |   19 +++--
 net/batman-adv/types.h          |    4 +-
 net/batman-adv/vis.c            |   91 +++++++++---------
 8 files changed, 232 insertions(+), 212 deletions(-)

diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 879ac15..42a8a7b 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -98,6 +98,7 @@ void gw_election(struct bat_priv *bat_priv)
 {
 	struct hlist_node *node;
 	struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL;
+	struct neigh_node *router;
 	uint8_t max_tq = 0;
 	uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
 	int down, up;
@@ -133,10 +134,11 @@ void gw_election(struct bat_priv *bat_priv)
 	}
 
 	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
-		if (!gw_node->orig_node->router)
+		if (gw_node->deleted)
 			continue;
 
-		if (gw_node->deleted)
+		router = orig_node_get_router(gw_node->orig_node);
+		if (!router)
 			continue;
 
 		switch (atomic_read(&bat_priv->gw_sel_class)) {
@@ -144,15 +146,14 @@ void gw_election(struct bat_priv *bat_priv)
 			gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags,
 					     &down, &up);
 
-			tmp_gw_factor = (gw_node->orig_node->router->tq_avg *
-					 gw_node->orig_node->router->tq_avg *
+			tmp_gw_factor = (router->tq_avg * router->tq_avg *
 					 down * 100 * 100) /
 					 (TQ_LOCAL_WINDOW_SIZE *
 					 TQ_LOCAL_WINDOW_SIZE * 64);
 
 			if ((tmp_gw_factor > max_gw_factor) ||
 			    ((tmp_gw_factor == max_gw_factor) &&
-			     (gw_node->orig_node->router->tq_avg > max_tq)))
+			     (router->tq_avg > max_tq)))
 				curr_gw_tmp = gw_node;
 			break;
 
@@ -164,19 +165,25 @@ void gw_election(struct bat_priv *bat_priv)
 			  *     soon as a better gateway appears which has
 			  *     $routing_class more tq points)
 			  **/
-			if (gw_node->orig_node->router->tq_avg > max_tq)
+			if (router->tq_avg > max_tq)
 				curr_gw_tmp = gw_node;
 			break;
 		}
 
-		if (gw_node->orig_node->router->tq_avg > max_tq)
-			max_tq = gw_node->orig_node->router->tq_avg;
+		if (router->tq_avg > max_tq)
+			max_tq = router->tq_avg;
 
 		if (tmp_gw_factor > max_gw_factor)
 			max_gw_factor = tmp_gw_factor;
+
+		neigh_node_free_ref(router);
 	}
 
 	if (curr_gw != curr_gw_tmp) {
+		router = orig_node_get_router(curr_gw_tmp->orig_node);
+		if (!router)
+			goto out;
+
 		if ((curr_gw) && (!curr_gw_tmp))
 			bat_dbg(DBG_BATMAN, bat_priv,
 				"Removing selected gateway - "
@@ -187,45 +194,47 @@ void gw_election(struct bat_priv *bat_priv)
 				"(gw_flags: %i, tq: %i)\n",
 				curr_gw_tmp->orig_node->orig,
 				curr_gw_tmp->orig_node->gw_flags,
-				curr_gw_tmp->orig_node->router->tq_avg);
+				router->tq_avg);
 		else
 			bat_dbg(DBG_BATMAN, bat_priv,
 				"Changing route to gateway %pM "
 				"(gw_flags: %i, tq: %i)\n",
 				curr_gw_tmp->orig_node->orig,
 				curr_gw_tmp->orig_node->gw_flags,
-				curr_gw_tmp->orig_node->router->tq_avg);
+				router->tq_avg);
 
+		neigh_node_free_ref(router);
 		gw_select(bat_priv, curr_gw_tmp);
 	}
 
+out:
 	rcu_read_unlock();
 }
 
 void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
 {
 	struct orig_node *curr_gw_orig;
+	struct neigh_node *router_gw = NULL, *router_orig = NULL;
 	uint8_t gw_tq_avg, orig_tq_avg;
 
 	curr_gw_orig = gw_get_selected(bat_priv);
 	if (!curr_gw_orig)
 		goto deselect;
 
-	rcu_read_lock();
-	if (!curr_gw_orig->router)
-		goto deselect_rcu;
+	router_gw = orig_node_get_router(curr_gw_orig);
+	if (!router_gw)
+		goto deselect;
 
 	/* this node already is the gateway */
 	if (curr_gw_orig == orig_node)
-		goto out_rcu;
+		goto out;
 
-	if (!orig_node->router)
-		goto out_rcu;
+	router_orig = orig_node_get_router(orig_node);
+	if (!router_orig)
+		goto out;
 
-	gw_tq_avg = curr_gw_orig->router->tq_avg;
-	rcu_read_unlock();
-
-	orig_tq_avg = orig_node->router->tq_avg;
+	gw_tq_avg = router_gw->tq_avg;
+	orig_tq_avg = router_orig->tq_avg;
 
 	/* the TQ value has to be better */
 	if (orig_tq_avg < gw_tq_avg)
@@ -243,18 +252,16 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
 		"Restarting gateway selection: better gateway found (tq curr: "
 		"%i, tq new: %i)\n",
 		gw_tq_avg, orig_tq_avg);
-	goto deselect;
 
-out_rcu:
-	rcu_read_unlock();
-	goto out;
-deselect_rcu:
-	rcu_read_unlock();
 deselect:
 	gw_deselect(bat_priv);
 out:
 	if (curr_gw_orig)
 		orig_node_free_ref(curr_gw_orig);
+	if (router_gw)
+		neigh_node_free_ref(router_gw);
+	if (router_orig)
+		neigh_node_free_ref(router_orig);
 
 	return;
 }
@@ -362,23 +369,30 @@ void gw_node_purge(struct bat_priv *bat_priv)
 	spin_unlock_bh(&bat_priv->gw_list_lock);
 }
 
+/**
+ * fails if orig_node has no router
+ */
 static int _write_buffer_text(struct bat_priv *bat_priv,
 			      struct seq_file *seq, struct gw_node *gw_node)
 {
 	struct gw_node *curr_gw;
-	int down, up, ret;
+	struct neigh_node *router;
+	int down, up, ret = -1;
 
 	gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
 
+	router = orig_node_get_router(gw_node->orig_node);
+	if (!router)
+		goto out;
+
 	rcu_read_lock();
 	curr_gw = rcu_dereference(bat_priv->curr_gw);
 
 	ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n",
 		       (curr_gw == gw_node ? "=>" : "  "),
 		       gw_node->orig_node->orig,
-		       gw_node->orig_node->router->tq_avg,
-		       gw_node->orig_node->router->addr,
-		       gw_node->orig_node->router->if_incoming->net_dev->name,
+		       router->tq_avg, router->addr,
+		       router->if_incoming->net_dev->name,
 		       gw_node->orig_node->gw_flags,
 		       (down > 2048 ? down / 1024 : down),
 		       (down > 2048 ? "MBit" : "KBit"),
@@ -386,6 +400,8 @@ static int _write_buffer_text(struct bat_priv *bat_priv,
 		       (up > 2048 ? "MBit" : "KBit"));
 
 	rcu_read_unlock();
+	neigh_node_free_ref(router);
+out:
 	return ret;
 }
 
@@ -423,10 +439,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
 		if (gw_node->deleted)
 			continue;
 
-		if (!gw_node->orig_node->router)
+		/* fails if orig_node has no router */
+		if (_write_buffer_text(bat_priv, seq, gw_node) < 0)
 			continue;
 
-		_write_buffer_text(bat_priv, seq, gw_node);
 		gw_count++;
 	}
 	rcu_read_unlock();
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 34ce56c..49079c2 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -218,23 +218,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
 	if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
 		goto dst_unreach;
 
-	rcu_read_lock();
 	orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
-
 	if (!orig_node)
-		goto unlock;
-
-	neigh_node = orig_node->router;
+		goto dst_unreach;
 
+	neigh_node = orig_node_get_router(orig_node);
 	if (!neigh_node)
-		goto unlock;
-
-	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
-		neigh_node = NULL;
-		goto unlock;
-	}
-
-	rcu_read_unlock();
+		goto dst_unreach;
 
 	if (!neigh_node->if_incoming)
 		goto dst_unreach;
@@ -252,8 +242,6 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
 	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
 	goto out;
 
-unlock:
-	rcu_read_unlock();
 dst_unreach:
 	icmp_packet->msg_type = DESTINATION_UNREACHABLE;
 	bat_socket_add_packet(socket_client, icmp_packet, packet_len);
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 0b91330..b4cfe36 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -70,6 +70,21 @@ void neigh_node_free_ref(struct neigh_node *neigh_node)
 		call_rcu(&neigh_node->rcu, neigh_node_free_rcu);
 }
 
+/* increases the refcounter of a found router */
+struct neigh_node *orig_node_get_router(struct orig_node *orig_node)
+{
+	struct neigh_node *router;
+
+	rcu_read_lock();
+	router = rcu_dereference(orig_node->router);
+
+	if (router && !atomic_inc_not_zero(&router->refcount))
+		router = NULL;
+
+	rcu_read_unlock();
+	return router;
+}
+
 struct neigh_node *create_neighbor(struct orig_node *orig_node,
 				   struct orig_node *orig_neigh_node,
 				   uint8_t *neigh,
@@ -390,7 +405,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
 	struct hlist_node *node, *node_tmp;
 	struct hlist_head *head;
 	struct orig_node *orig_node;
-	struct neigh_node *neigh_node;
+	struct neigh_node *neigh_node, *neigh_node_tmp;
 	int batman_count = 0;
 	int last_seen_secs;
 	int last_seen_msecs;
@@ -421,37 +436,41 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
 
 		rcu_read_lock();
 		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
-			if (!orig_node->router)
+			neigh_node = orig_node_get_router(orig_node);
+			if (!neigh_node)
 				continue;
 
-			if (orig_node->router->tq_avg == 0)
-				continue;
+			if (neigh_node->tq_avg == 0)
+				goto next;
 
 			last_seen_secs = jiffies_to_msecs(jiffies -
 						orig_node->last_valid) / 1000;
 			last_seen_msecs = jiffies_to_msecs(jiffies -
 						orig_node->last_valid) % 1000;
 
-			neigh_node = orig_node->router;
 			seq_printf(seq, "%pM %4i.%03is   (%3i) %pM [%10s]:",
 				   orig_node->orig, last_seen_secs,
 				   last_seen_msecs, neigh_node->tq_avg,
 				   neigh_node->addr,
 				   neigh_node->if_incoming->net_dev->name);
 
-			hlist_for_each_entry_rcu(neigh_node, node_tmp,
+			hlist_for_each_entry_rcu(neigh_node_tmp, node_tmp,
 						 &orig_node->neigh_list, list) {
-				seq_printf(seq, " %pM (%3i)", neigh_node->addr,
-						neigh_node->tq_avg);
+				seq_printf(seq, " %pM (%3i)",
+					   neigh_node_tmp->addr,
+					   neigh_node_tmp->tq_avg);
 			}
 
 			seq_printf(seq, "\n");
 			batman_count++;
+
+next:
+			neigh_node_free_ref(neigh_node);
 		}
 		rcu_read_unlock();
 	}
 
-	if ((batman_count == 0))
+	if (batman_count == 0)
 		seq_printf(seq, "No batman nodes in range ...\n");
 
 	return 0;
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 5cc0110..e1d641f 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -34,6 +34,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
 				   uint8_t *neigh,
 				   struct hard_iface *if_incoming);
 void neigh_node_free_ref(struct neigh_node *neigh_node);
+struct neigh_node *orig_node_get_router(struct orig_node *orig_node);
 int orig_seq_print_text(struct seq_file *seq, void *offset);
 int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num);
 int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num);
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index f212abe..b7d43ca 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -87,18 +87,20 @@ static void update_route(struct bat_priv *bat_priv,
 			 struct neigh_node *neigh_node,
 			 unsigned char *hna_buff, int hna_buff_len)
 {
-	struct neigh_node *neigh_node_tmp;
+	struct neigh_node *curr_router;
+
+	curr_router = orig_node_get_router(orig_node);
 
 	/* route deleted */
-	if ((orig_node->router) && (!neigh_node)) {
+	if ((curr_router) && (!neigh_node)) {
 
 		bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n",
 			orig_node->orig);
 		hna_global_del_orig(bat_priv, orig_node,
 				    "originator timed out");
 
-		/* route added */
-	} else if ((!orig_node->router) && (neigh_node)) {
+	/* route added */
+	} else if ((!curr_router) && (neigh_node)) {
 
 		bat_dbg(DBG_ROUTES, bat_priv,
 			"Adding route towards: %pM (via %pM)\n",
@@ -106,21 +108,29 @@ static void update_route(struct bat_priv *bat_priv,
 		hna_global_add_orig(bat_priv, orig_node,
 				    hna_buff, hna_buff_len);
 
-		/* route changed */
+	/* route changed */
 	} else {
 		bat_dbg(DBG_ROUTES, bat_priv,
 			"Changing route towards: %pM "
 			"(now via %pM - was via %pM)\n",
 			orig_node->orig, neigh_node->addr,
-			orig_node->router->addr);
+			curr_router->addr);
 	}
 
+	if (curr_router)
+		neigh_node_free_ref(curr_router);
+
+	/* increase refcount of new best neighbor */
 	if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount))
 		neigh_node = NULL;
-	neigh_node_tmp = orig_node->router;
-	orig_node->router = neigh_node;
-	if (neigh_node_tmp)
-		neigh_node_free_ref(neigh_node_tmp);
+
+	spin_lock_bh(&orig_node->neigh_list_lock);
+	rcu_assign_pointer(orig_node->router, neigh_node);
+	spin_unlock_bh(&orig_node->neigh_list_lock);
+
+	/* decrease refcount of previous best neighbor */
+	if (curr_router)
+		neigh_node_free_ref(curr_router);
 }
 
 
@@ -128,16 +138,23 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
 		   struct neigh_node *neigh_node, unsigned char *hna_buff,
 		   int hna_buff_len)
 {
+	struct neigh_node *router = NULL;
 
 	if (!orig_node)
-		return;
+		goto out;
 
-	if (orig_node->router != neigh_node)
+	router = orig_node_get_router(orig_node);
+
+	if (router != neigh_node)
 		update_route(bat_priv, orig_node, neigh_node,
 			     hna_buff, hna_buff_len);
 	/* may be just HNA changed */
 	else
 		update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len);
+
+out:
+	if (router)
+		neigh_node_free_ref(router);
 }
 
 static int is_bidirectional_neigh(struct orig_node *orig_node,
@@ -288,8 +305,8 @@ static void bonding_candidate_add(struct orig_node *orig_node,
 				  struct neigh_node *neigh_node)
 {
 	struct hlist_node *node;
-	struct neigh_node *tmp_neigh_node;
-	uint8_t best_tq, interference_candidate = 0;
+	struct neigh_node *tmp_neigh_node, *router = NULL;
+	uint8_t interference_candidate = 0;
 
 	spin_lock_bh(&orig_node->neigh_list_lock);
 
@@ -298,13 +315,12 @@ static void bonding_candidate_add(struct orig_node *orig_node,
 			 neigh_node->orig_node->primary_addr))
 		goto candidate_del;
 
-	if (!orig_node->router)
+	router = orig_node_get_router(orig_node);
+	if (!router)
 		goto candidate_del;
 
-	best_tq = orig_node->router->tq_avg;
-
 	/* ... and is good enough to be considered */
-	if (neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD)
+	if (neigh_node->tq_avg < router->tq_avg - BONDING_TQ_THRESHOLD)
 		goto candidate_del;
 
 	/**
@@ -350,7 +366,9 @@ candidate_del:
 
 out:
 	spin_unlock_bh(&orig_node->neigh_list_lock);
-	return;
+
+	if (router)
+		neigh_node_free_ref(router);
 }
 
 /* copy primary address for bonding */
@@ -373,6 +391,7 @@ static void update_orig(struct bat_priv *bat_priv,
 			char is_duplicate)
 {
 	struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
+	struct neigh_node *router = NULL;
 	struct orig_node *orig_node_tmp;
 	struct hlist_node *node;
 	int tmp_hna_buff_len;
@@ -441,19 +460,18 @@ static void update_orig(struct bat_priv *bat_priv,
 
 	/* if this neighbor already is our next hop there is nothing
 	 * to change */
-	if (orig_node->router == neigh_node)
+	router = orig_node_get_router(orig_node);
+	if (router == neigh_node)
 		goto update_hna;
 
 	/* if this neighbor does not offer a better TQ we won't consider it */
-	if ((orig_node->router) &&
-	    (orig_node->router->tq_avg > neigh_node->tq_avg))
+	if (router && (router->tq_avg > neigh_node->tq_avg))
 		goto update_hna;
 
 	/* if the TQ is the same and the link not more symetric we
 	 * won't consider it either */
-	if ((orig_node->router) &&
-	     (neigh_node->tq_avg == orig_node->router->tq_avg)) {
-		orig_node_tmp = orig_node->router->orig_node;
+	if (router && (neigh_node->tq_avg == router->tq_avg)) {
+		orig_node_tmp = router->orig_node;
 		spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
 		bcast_own_sum_orig =
 			orig_node_tmp->bcast_own_sum[if_incoming->if_num];
@@ -474,7 +492,7 @@ static void update_orig(struct bat_priv *bat_priv,
 	goto update_gw;
 
 update_hna:
-	update_routes(bat_priv, orig_node, orig_node->router,
+	update_routes(bat_priv, orig_node, router,
 		      hna_buff, tmp_hna_buff_len);
 
 update_gw:
@@ -496,6 +514,8 @@ unlock:
 out:
 	if (neigh_node)
 		neigh_node_free_ref(neigh_node);
+	if (router)
+		neigh_node_free_ref(router);
 }
 
 /* checks whether the host restarted and is in the protection time.
@@ -603,6 +623,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 	struct hard_iface *hard_iface;
 	struct orig_node *orig_neigh_node, *orig_node;
+	struct neigh_node *router = NULL, *router_router = NULL;
+	struct neigh_node *orig_neigh_router = NULL;
 	char has_directlink_flag;
 	char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
 	char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
@@ -747,14 +769,15 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 		goto out;
 	}
 
+	router = orig_node_get_router(orig_node);
+	if (router)
+		router_router = orig_node_get_router(router->orig_node);
+
 	/* avoid temporary routing loops */
-	if ((orig_node->router) &&
-	    (orig_node->router->orig_node->router) &&
-	    (compare_eth(orig_node->router->addr,
-			 batman_packet->prev_sender)) &&
+	if (router && router_router &&
+	    (compare_eth(router->addr, batman_packet->prev_sender)) &&
 	    !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) &&
-	    (compare_eth(orig_node->router->addr,
-			 orig_node->router->orig_node->router->addr))) {
+	    (compare_eth(router->addr, router_router->addr))) {
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"Drop packet: ignoring all rebroadcast packets that "
 			"may make me loop (sender: %pM)\n", ethhdr->h_source);
@@ -769,9 +792,11 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 	if (!orig_neigh_node)
 		goto out;
 
+	orig_neigh_router = orig_node_get_router(orig_neigh_node);
+
 	/* drop packet if sender is not a direct neighbor and if we
 	 * don't route towards it */
-	if (!is_single_hop_neigh && (!orig_neigh_node->router)) {
+	if (!is_single_hop_neigh && (!orig_neigh_router)) {
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"Drop packet: OGM via unknown neighbor!\n");
 		goto out_neigh;
@@ -825,6 +850,13 @@ out_neigh:
 	if ((orig_neigh_node) && (!is_single_hop_neigh))
 		orig_node_free_ref(orig_neigh_node);
 out:
+	if (router)
+		neigh_node_free_ref(router);
+	if (router_router)
+		neigh_node_free_ref(router_router);
+	if (orig_neigh_router)
+		neigh_node_free_ref(orig_neigh_router);
+
 	orig_node_free_ref(orig_node);
 }
 
@@ -869,7 +901,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
 			       struct sk_buff *skb, size_t icmp_len)
 {
 	struct orig_node *orig_node = NULL;
-	struct neigh_node *neigh_node = NULL;
+	struct neigh_node *router = NULL;
 	struct icmp_packet_rr *icmp_packet;
 	int ret = NET_RX_DROP;
 
@@ -886,23 +918,13 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
 
 	/* answer echo request (ping) */
 	/* get routing information */
-	rcu_read_lock();
 	orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
-
 	if (!orig_node)
-		goto unlock;
+		goto out;
 
-	neigh_node = orig_node->router;
-
-	if (!neigh_node)
-		goto unlock;
-
-	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
-		neigh_node = NULL;
-		goto unlock;
-	}
-
-	rcu_read_unlock();
+	router = orig_node_get_router(orig_node);
+	if (!router)
+		goto out;
 
 	/* create a copy of the skb, if needed, to modify it. */
 	if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
@@ -916,15 +938,12 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
 	icmp_packet->msg_type = ECHO_REPLY;
 	icmp_packet->ttl = TTL;
 
-	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	send_skb_packet(skb, router->if_incoming, router->addr);
 	ret = NET_RX_SUCCESS;
-	goto out;
 
-unlock:
-	rcu_read_unlock();
 out:
-	if (neigh_node)
-		neigh_node_free_ref(neigh_node);
+	if (router)
+		neigh_node_free_ref(router);
 	if (orig_node)
 		orig_node_free_ref(orig_node);
 	return ret;
@@ -934,7 +953,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
 				  struct sk_buff *skb)
 {
 	struct orig_node *orig_node = NULL;
-	struct neigh_node *neigh_node = NULL;
+	struct neigh_node *router = NULL;
 	struct icmp_packet *icmp_packet;
 	int ret = NET_RX_DROP;
 
@@ -952,23 +971,13 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
 		goto out;
 
 	/* get routing information */
-	rcu_read_lock();
 	orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
-
 	if (!orig_node)
-		goto unlock;
+		goto out;
 
-	neigh_node = orig_node->router;
-
-	if (!neigh_node)
-		goto unlock;
-
-	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
-		neigh_node = NULL;
-		goto unlock;
-	}
-
-	rcu_read_unlock();
+	router = orig_node_get_router(orig_node);
+	if (!router)
+		goto out;
 
 	/* create a copy of the skb, if needed, to modify it. */
 	if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
@@ -982,15 +991,12 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
 	icmp_packet->msg_type = TTL_EXCEEDED;
 	icmp_packet->ttl = TTL;
 
-	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	send_skb_packet(skb, router->if_incoming, router->addr);
 	ret = NET_RX_SUCCESS;
-	goto out;
 
-unlock:
-	rcu_read_unlock();
 out:
-	if (neigh_node)
-		neigh_node_free_ref(neigh_node);
+	if (router)
+		neigh_node_free_ref(router);
 	if (orig_node)
 		orig_node_free_ref(orig_node);
 	return ret;
@@ -1003,7 +1009,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 	struct icmp_packet_rr *icmp_packet;
 	struct ethhdr *ethhdr;
 	struct orig_node *orig_node = NULL;
-	struct neigh_node *neigh_node = NULL;
+	struct neigh_node *router = NULL;
 	int hdr_size = sizeof(struct icmp_packet);
 	int ret = NET_RX_DROP;
 
@@ -1050,23 +1056,13 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 		return recv_icmp_ttl_exceeded(bat_priv, skb);
 
 	/* get routing information */
-	rcu_read_lock();
 	orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
-
 	if (!orig_node)
-		goto unlock;
+		goto out;
 
-	neigh_node = orig_node->router;
-
-	if (!neigh_node)
-		goto unlock;
-
-	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
-		neigh_node = NULL;
-		goto unlock;
-	}
-
-	rcu_read_unlock();
+	router = orig_node_get_router(orig_node);
+	if (!router)
+		goto out;
 
 	/* create a copy of the skb, if needed, to modify it. */
 	if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
@@ -1078,15 +1074,12 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 	icmp_packet->ttl--;
 
 	/* route it */
-	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	send_skb_packet(skb, router->if_incoming, router->addr);
 	ret = NET_RX_SUCCESS;
-	goto out;
 
-unlock:
-	rcu_read_unlock();
 out:
-	if (neigh_node)
-		neigh_node_free_ref(neigh_node);
+	if (router)
+		neigh_node_free_ref(router);
 	if (orig_node)
 		orig_node_free_ref(orig_node);
 	return ret;
@@ -1208,7 +1201,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
 	if (!orig_node)
 		return NULL;
 
-	if (!orig_node->router)
+	router = orig_node_get_router(orig_node);
+	if (!router)
 		return NULL;
 
 	/* without bonding, the first node should
@@ -1217,9 +1211,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
 
 	rcu_read_lock();
 	/* select default router to output */
-	router = orig_node->router;
-	router_orig = orig_node->router->orig_node;
-	if (!router_orig || !atomic_inc_not_zero(&router->refcount)) {
+	router_orig = router->orig_node;
+	if (!router_orig) {
 		rcu_read_unlock();
 		return NULL;
 	}
@@ -1251,7 +1244,6 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
 	if (atomic_read(&primary_orig_node->bond_candidates) < 2)
 		goto return_router;
 
-
 	/* all nodes between should choose a candidate which
 	 * is is not on the interface where the packet came
 	 * in. */
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index d49e54d..e78670c 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -308,6 +308,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
 			     struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
+	struct neigh_node *router;
 	unsigned char in_tq, in_ttl, tq_avg = 0;
 	unsigned long send_time;
 
@@ -316,6 +317,8 @@ void schedule_forward_packet(struct orig_node *orig_node,
 		return;
 	}
 
+	router = orig_node_get_router(orig_node);
+
 	in_tq = batman_packet->tq;
 	in_ttl = batman_packet->ttl;
 
@@ -324,20 +327,22 @@ void schedule_forward_packet(struct orig_node *orig_node,
 
 	/* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
 	 * of our best tq value */
-	if ((orig_node->router) && (orig_node->router->tq_avg != 0)) {
+	if (router && router->tq_avg != 0) {
 
 		/* rebroadcast ogm of best ranking neighbor as is */
-		if (!compare_eth(orig_node->router->addr, ethhdr->h_source)) {
-			batman_packet->tq = orig_node->router->tq_avg;
+		if (!compare_eth(router->addr, ethhdr->h_source)) {
+			batman_packet->tq = router->tq_avg;
 
-			if (orig_node->router->last_ttl)
-				batman_packet->ttl = orig_node->router->last_ttl
-							- 1;
+			if (router->last_ttl)
+				batman_packet->ttl = router->last_ttl - 1;
 		}
 
-		tq_avg = orig_node->router->tq_avg;
+		tq_avg = router->tq_avg;
 	}
 
+	if (router)
+		neigh_node_free_ref(router);
+
 	/* apply hop penalty */
 	batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv);
 
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 83445cf..1854cbb 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -67,7 +67,7 @@ struct hard_iface {
 struct orig_node {
 	uint8_t orig[ETH_ALEN];
 	uint8_t primary_addr[ETH_ALEN];
-	struct neigh_node *router;
+	struct neigh_node __rcu *router; /* rcu protected pointer */
 	unsigned long *bcast_own;
 	uint8_t *bcast_own_sum;
 	unsigned long last_valid;
@@ -83,7 +83,7 @@ struct orig_node {
 	uint32_t last_bcast_seqno;
 	struct hlist_head neigh_list;
 	struct list_head frag_list;
-	spinlock_t neigh_list_lock; /* protects neighbor list */
+	spinlock_t neigh_list_lock; /* protects neigh_list and router */
 	atomic_t refcount;
 	struct rcu_head rcu;
 	struct hlist_node hash_entry;
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index f90212f..d4cc4f5 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -558,6 +558,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
 				struct vis_info *info)
 {
 	struct hashtable_t *hash = bat_priv->orig_hash;
+	struct neigh_node *router;
 	struct hlist_node *node;
 	struct hlist_head *head;
 	struct orig_node *orig_node;
@@ -571,13 +572,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
 
 		rcu_read_lock();
 		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
-			if ((orig_node) && (orig_node->router) &&
-			    (orig_node->flags & VIS_SERVER) &&
-			    (orig_node->router->tq_avg > best_tq)) {
-				best_tq = orig_node->router->tq_avg;
+			router = orig_node_get_router(orig_node);
+			if (!router)
+				continue;
+
+			if ((orig_node->flags & VIS_SERVER) &&
+			    (router->tq_avg > best_tq)) {
+				best_tq = router->tq_avg;
 				memcpy(packet->target_orig, orig_node->orig,
 				       ETH_ALEN);
 			}
+			neigh_node_free_ref(router);
 		}
 		rcu_read_unlock();
 	}
@@ -605,7 +610,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 	struct hlist_node *node;
 	struct hlist_head *head;
 	struct orig_node *orig_node;
-	struct neigh_node *neigh_node;
+	struct neigh_node *router;
 	struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
 	struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data;
 	struct vis_info_entry *entry;
@@ -633,30 +638,32 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 
 		rcu_read_lock();
 		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
-			neigh_node = orig_node->router;
-
-			if (!neigh_node)
+			router = orig_node_get_router(orig_node);
+			if (!router)
 				continue;
 
-			if (!compare_eth(neigh_node->addr, orig_node->orig))
-				continue;
+			if (!compare_eth(router->addr, orig_node->orig))
+				goto next;
 
-			if (neigh_node->if_incoming->if_status != IF_ACTIVE)
-				continue;
+			if (router->if_incoming->if_status != IF_ACTIVE)
+				goto next;
 
-			if (neigh_node->tq_avg < 1)
-				continue;
+			if (router->tq_avg < 1)
+				goto next;
 
 			/* fill one entry into buffer. */
 			entry = (struct vis_info_entry *)
 				      skb_put(info->skb_packet, sizeof(*entry));
 			memcpy(entry->src,
-			       neigh_node->if_incoming->net_dev->dev_addr,
+			       router->if_incoming->net_dev->dev_addr,
 			       ETH_ALEN);
 			memcpy(entry->dest, orig_node->orig, ETH_ALEN);
-			entry->quality = neigh_node->tq_avg;
+			entry->quality = router->tq_avg;
 			packet->entries++;
 
+next:
+			neigh_node_free_ref(router);
+
 			if (vis_packet_full(info))
 				goto unlock;
 		}
@@ -725,6 +732,7 @@ static void purge_vis_packets(struct bat_priv *bat_priv)
 static void broadcast_vis_packet(struct bat_priv *bat_priv,
 				 struct vis_info *info)
 {
+	struct neigh_node *router;
 	struct hashtable_t *hash = bat_priv->orig_hash;
 	struct hlist_node *node;
 	struct hlist_head *head;
@@ -745,19 +753,26 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
 		rcu_read_lock();
 		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
 			/* if it's a vis server and reachable, send it. */
-			if ((!orig_node) || (!orig_node->router))
-				continue;
 			if (!(orig_node->flags & VIS_SERVER))
 				continue;
+
+			router = orig_node_get_router(orig_node);
+			if (!router)
+				continue;
+
 			/* don't send it if we already received the packet from
-			* this node. */
+			 * this node. */
 			if (recv_list_is_in(bat_priv, &info->recv_list,
-					    orig_node->orig))
+					    orig_node->orig)) {
+				neigh_node_free_ref(router);
 				continue;
+			}
 
 			memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
-			hard_iface = orig_node->router->if_incoming;
-			memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+			hard_iface = router->if_incoming;
+			memcpy(dstaddr, router->addr, ETH_ALEN);
+
+			neigh_node_free_ref(router);
 
 			skb = skb_clone(info->skb_packet, GFP_ATOMIC);
 			if (skb)
@@ -772,45 +787,29 @@ static void unicast_vis_packet(struct bat_priv *bat_priv,
 			       struct vis_info *info)
 {
 	struct orig_node *orig_node;
-	struct neigh_node *neigh_node = NULL;
+	struct neigh_node *router = NULL;
 	struct sk_buff *skb;
 	struct vis_packet *packet;
 
 	packet = (struct vis_packet *)info->skb_packet->data;
 
-	rcu_read_lock();
 	orig_node = orig_hash_find(bat_priv, packet->target_orig);
-
 	if (!orig_node)
-		goto unlock;
+		goto out;
 
-	neigh_node = orig_node->router;
-
-	if (!neigh_node)
-		goto unlock;
-
-	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
-		neigh_node = NULL;
-		goto unlock;
-	}
-
-	rcu_read_unlock();
+	router = orig_node_get_router(orig_node);
+	if (!router)
+		goto out;
 
 	skb = skb_clone(info->skb_packet, GFP_ATOMIC);
 	if (skb)
-		send_skb_packet(skb, neigh_node->if_incoming,
-				neigh_node->addr);
+		send_skb_packet(skb, router->if_incoming, router->addr);
 
-	goto out;
-
-unlock:
-	rcu_read_unlock();
 out:
-	if (neigh_node)
-		neigh_node_free_ref(neigh_node);
+	if (router)
+		neigh_node_free_ref(router);
 	if (orig_node)
 		orig_node_free_ref(orig_node);
-	return;
 }
 
 /* only send one vis packet. called from send_vis_packets() */
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 5/8] batman-adv: Protect global TQ window with a spinlock
From: Sven Eckelmann @ 2011-04-17 19:30 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r, Marek Lindner
In-Reply-To: <1303068618-27928-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

From: Linus Lüssing <linus.luessing-S0/GAf8tV78@public.gmane.org>

Signed-off-by: Linus Lüssing <linus.luessing-S0/GAf8tV78@public.gmane.org>
Signed-off-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
Signed-off-by: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
---
 net/batman-adv/originator.c |    1 +
 net/batman-adv/routing.c    |    4 ++++
 net/batman-adv/types.h      |    1 +
 3 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index b4cfe36..5b8fe32 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -102,6 +102,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
 
 	INIT_HLIST_NODE(&neigh_node->list);
 	INIT_LIST_HEAD(&neigh_node->bonding_list);
+	spin_lock_init(&neigh_node->tq_lock);
 
 	memcpy(neigh_node->addr, neigh, ETH_ALEN);
 	neigh_node->orig_node = orig_neigh_node;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index b7d43ca..f6c6422 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -415,10 +415,12 @@ static void update_orig(struct bat_priv *bat_priv,
 		if (is_duplicate)
 			continue;
 
+		spin_lock_bh(&tmp_neigh_node->tq_lock);
 		ring_buffer_set(tmp_neigh_node->tq_recv,
 				&tmp_neigh_node->tq_index, 0);
 		tmp_neigh_node->tq_avg =
 			ring_buffer_avg(tmp_neigh_node->tq_recv);
+		spin_unlock_bh(&tmp_neigh_node->tq_lock);
 	}
 
 	if (!neigh_node) {
@@ -443,10 +445,12 @@ static void update_orig(struct bat_priv *bat_priv,
 	orig_node->flags = batman_packet->flags;
 	neigh_node->last_valid = jiffies;
 
+	spin_lock_bh(&neigh_node->tq_lock);
 	ring_buffer_set(neigh_node->tq_recv,
 			&neigh_node->tq_index,
 			batman_packet->tq);
 	neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
+	spin_unlock_bh(&neigh_node->tq_lock);
 
 	if (!is_duplicate) {
 		orig_node->last_ttl = batman_packet->ttl;
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 1854cbb..091476d 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -125,6 +125,7 @@ struct neigh_node {
 	struct rcu_head rcu;
 	struct orig_node *orig_node;
 	struct hard_iface *if_incoming;
+	spinlock_t tq_lock;	/* protects: tq_recv, tq_index */
 };
 
 
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 6/8] batman-adv: concentrate all curr_gw related rcu operations in select/deselect functions
From: Sven Eckelmann @ 2011-04-17 19:30 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r, Marek Lindner
In-Reply-To: <1303068618-27928-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

From: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>

Signed-off-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
Signed-off-by: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
---
 net/batman-adv/gateway_client.c |  176 ++++++++++++++++++++++-----------------
 net/batman-adv/gateway_client.h |    2 +-
 net/batman-adv/unicast.c        |    2 +-
 3 files changed, 103 insertions(+), 77 deletions(-)

diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 42a8a7b..2acd7a6 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -43,61 +43,75 @@ static void gw_node_free_ref(struct gw_node *gw_node)
 		call_rcu(&gw_node->rcu, gw_node_free_rcu);
 }
 
-struct orig_node *gw_get_selected(struct bat_priv *bat_priv)
+static struct gw_node *gw_get_selected_gw_node(struct bat_priv *bat_priv)
 {
-	struct gw_node *curr_gateway_tmp;
+	struct gw_node *gw_node;
+
+	rcu_read_lock();
+	gw_node = rcu_dereference(bat_priv->curr_gw);
+	if (!gw_node)
+		goto out;
+
+	if (!atomic_inc_not_zero(&gw_node->refcount))
+		gw_node = NULL;
+
+out:
+	rcu_read_unlock();
+	return gw_node;
+}
+
+struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv)
+{
+	struct gw_node *gw_node;
 	struct orig_node *orig_node = NULL;
 
-	rcu_read_lock();
-	curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw);
-	if (!curr_gateway_tmp)
+	gw_node = gw_get_selected_gw_node(bat_priv);
+	if (!gw_node)
 		goto out;
 
-	orig_node = curr_gateway_tmp->orig_node;
+	rcu_read_lock();
+	orig_node = gw_node->orig_node;
 	if (!orig_node)
-		goto out;
+		goto unlock;
 
 	if (!atomic_inc_not_zero(&orig_node->refcount))
 		orig_node = NULL;
 
-out:
+unlock:
 	rcu_read_unlock();
-	return orig_node;
-}
-
-void gw_deselect(struct bat_priv *bat_priv)
-{
-	struct gw_node *gw_node;
-
-	spin_lock_bh(&bat_priv->gw_list_lock);
-	gw_node = rcu_dereference(bat_priv->curr_gw);
-	rcu_assign_pointer(bat_priv->curr_gw, NULL);
-	spin_unlock_bh(&bat_priv->gw_list_lock);
-
+out:
 	if (gw_node)
 		gw_node_free_ref(gw_node);
+	return orig_node;
 }
 
 static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node)
 {
 	struct gw_node *curr_gw_node;
 
+	spin_lock_bh(&bat_priv->gw_list_lock);
+
 	if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
 		new_gw_node = NULL;
 
-	spin_lock_bh(&bat_priv->gw_list_lock);
-	curr_gw_node = rcu_dereference(bat_priv->curr_gw);
+	curr_gw_node = bat_priv->curr_gw;
 	rcu_assign_pointer(bat_priv->curr_gw, new_gw_node);
-	spin_unlock_bh(&bat_priv->gw_list_lock);
 
 	if (curr_gw_node)
 		gw_node_free_ref(curr_gw_node);
+
+	spin_unlock_bh(&bat_priv->gw_list_lock);
+}
+
+void gw_deselect(struct bat_priv *bat_priv)
+{
+	gw_select(bat_priv, NULL);
 }
 
 void gw_election(struct bat_priv *bat_priv)
 {
 	struct hlist_node *node;
-	struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL;
+	struct gw_node *gw_node, *curr_gw = NULL, *curr_gw_tmp = NULL;
 	struct neigh_node *router;
 	uint8_t max_tq = 0;
 	uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
@@ -112,25 +126,17 @@ void gw_election(struct bat_priv *bat_priv)
 	if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
 		return;
 
-	rcu_read_lock();
-	curr_gw = rcu_dereference(bat_priv->curr_gw);
-	if (curr_gw) {
-		rcu_read_unlock();
-		return;
-	}
+	curr_gw = gw_get_selected_gw_node(bat_priv);
+	if (!curr_gw)
+		goto out;
 
+	rcu_read_lock();
 	if (hlist_empty(&bat_priv->gw_list)) {
-
-		if (curr_gw) {
-			rcu_read_unlock();
-			bat_dbg(DBG_BATMAN, bat_priv,
-				"Removing selected gateway - "
-				"no gateway in range\n");
-			gw_deselect(bat_priv);
-		} else
-			rcu_read_unlock();
-
-		return;
+		bat_dbg(DBG_BATMAN, bat_priv,
+			"Removing selected gateway - "
+			"no gateway in range\n");
+		gw_deselect(bat_priv);
+		goto unlock;
 	}
 
 	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
@@ -182,7 +188,7 @@ void gw_election(struct bat_priv *bat_priv)
 	if (curr_gw != curr_gw_tmp) {
 		router = orig_node_get_router(curr_gw_tmp->orig_node);
 		if (!router)
-			goto out;
+			goto unlock;
 
 		if ((curr_gw) && (!curr_gw_tmp))
 			bat_dbg(DBG_BATMAN, bat_priv,
@@ -207,8 +213,11 @@ void gw_election(struct bat_priv *bat_priv)
 		gw_select(bat_priv, curr_gw_tmp);
 	}
 
-out:
+unlock:
 	rcu_read_unlock();
+out:
+	if (curr_gw)
+		gw_node_free_ref(curr_gw);
 }
 
 void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
@@ -217,7 +226,7 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
 	struct neigh_node *router_gw = NULL, *router_orig = NULL;
 	uint8_t gw_tq_avg, orig_tq_avg;
 
-	curr_gw_orig = gw_get_selected(bat_priv);
+	curr_gw_orig = gw_get_selected_orig(bat_priv);
 	if (!curr_gw_orig)
 		goto deselect;
 
@@ -299,7 +308,11 @@ void gw_node_update(struct bat_priv *bat_priv,
 		    struct orig_node *orig_node, uint8_t new_gwflags)
 {
 	struct hlist_node *node;
-	struct gw_node *gw_node;
+	struct gw_node *gw_node, *curr_gw;
+
+	curr_gw = gw_get_selected_gw_node(bat_priv);
+	if (!curr_gw)
+		goto out;
 
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
@@ -320,22 +333,26 @@ void gw_node_update(struct bat_priv *bat_priv,
 				"Gateway %pM removed from gateway list\n",
 				orig_node->orig);
 
-			if (gw_node == rcu_dereference(bat_priv->curr_gw)) {
-				rcu_read_unlock();
-				gw_deselect(bat_priv);
-				return;
-			}
+			if (gw_node == curr_gw)
+				goto deselect;
 		}
 
-		rcu_read_unlock();
-		return;
+		goto unlock;
 	}
-	rcu_read_unlock();
 
 	if (new_gwflags == 0)
-		return;
+		goto unlock;
 
 	gw_node_add(bat_priv, orig_node, new_gwflags);
+	goto unlock;
+
+deselect:
+	gw_deselect(bat_priv);
+unlock:
+	rcu_read_unlock();
+out:
+	if (curr_gw)
+		gw_node_free_ref(curr_gw);
 }
 
 void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node)
@@ -345,9 +362,12 @@ void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node)
 
 void gw_node_purge(struct bat_priv *bat_priv)
 {
-	struct gw_node *gw_node;
+	struct gw_node *gw_node, *curr_gw;
 	struct hlist_node *node, *node_tmp;
 	unsigned long timeout = 2 * PURGE_TIMEOUT * HZ;
+	char do_deselect = 0;
+
+	curr_gw = gw_get_selected_gw_node(bat_priv);
 
 	spin_lock_bh(&bat_priv->gw_list_lock);
 
@@ -358,15 +378,21 @@ void gw_node_purge(struct bat_priv *bat_priv)
 		    atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)
 			continue;
 
-		if (rcu_dereference(bat_priv->curr_gw) == gw_node)
-			gw_deselect(bat_priv);
+		if (curr_gw == gw_node)
+			do_deselect = 1;
 
 		hlist_del_rcu(&gw_node->list);
 		gw_node_free_ref(gw_node);
 	}
 
-
 	spin_unlock_bh(&bat_priv->gw_list_lock);
+
+	/* gw_deselect() needs to acquire the gw_list_lock */
+	if (do_deselect)
+		gw_deselect(bat_priv);
+
+	if (curr_gw)
+		gw_node_free_ref(curr_gw);
 }
 
 /**
@@ -385,22 +411,22 @@ static int _write_buffer_text(struct bat_priv *bat_priv,
 	if (!router)
 		goto out;
 
-	rcu_read_lock();
-	curr_gw = rcu_dereference(bat_priv->curr_gw);
+	curr_gw = gw_get_selected_gw_node(bat_priv);
 
 	ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n",
-		       (curr_gw == gw_node ? "=>" : "  "),
-		       gw_node->orig_node->orig,
-		       router->tq_avg, router->addr,
-		       router->if_incoming->net_dev->name,
-		       gw_node->orig_node->gw_flags,
-		       (down > 2048 ? down / 1024 : down),
-		       (down > 2048 ? "MBit" : "KBit"),
-		       (up > 2048 ? up / 1024 : up),
-		       (up > 2048 ? "MBit" : "KBit"));
+			 (curr_gw == gw_node ? "=>" : "  "),
+			 gw_node->orig_node->orig,
+			 router->tq_avg, router->addr,
+			 router->if_incoming->net_dev->name,
+			 gw_node->orig_node->gw_flags,
+			 (down > 2048 ? down / 1024 : down),
+			 (down > 2048 ? "MBit" : "KBit"),
+			 (up > 2048 ? up / 1024 : up),
+			 (up > 2048 ? "MBit" : "KBit"));
 
-	rcu_read_unlock();
 	neigh_node_free_ref(router);
+	if (curr_gw)
+		gw_node_free_ref(curr_gw);
 out:
 	return ret;
 }
@@ -459,6 +485,7 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
 	struct iphdr *iphdr;
 	struct ipv6hdr *ipv6hdr;
 	struct udphdr *udphdr;
+	struct gw_node *curr_gw;
 	unsigned int header_len = 0;
 
 	if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF)
@@ -523,12 +550,11 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
 	if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)
 		return -1;
 
-	rcu_read_lock();
-	if (!rcu_dereference(bat_priv->curr_gw)) {
-		rcu_read_unlock();
+	curr_gw = gw_get_selected_gw_node(bat_priv);
+	if (!curr_gw)
 		return 0;
-	}
-	rcu_read_unlock();
 
+	if (curr_gw)
+		gw_node_free_ref(curr_gw);
 	return 1;
 }
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h
index 97c31d1..1ce8c60 100644
--- a/net/batman-adv/gateway_client.h
+++ b/net/batman-adv/gateway_client.h
@@ -24,7 +24,7 @@
 
 void gw_deselect(struct bat_priv *bat_priv);
 void gw_election(struct bat_priv *bat_priv);
-struct orig_node *gw_get_selected(struct bat_priv *bat_priv);
+struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv);
 void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node);
 void gw_node_update(struct bat_priv *bat_priv,
 		    struct orig_node *orig_node, uint8_t new_gwflags);
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 19f84bd..d46acc8 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -289,7 +289,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
 
 	/* get routing information */
 	if (is_multicast_ether_addr(ethhdr->h_dest)) {
-		orig_node = (struct orig_node *)gw_get_selected(bat_priv);
+		orig_node = (struct orig_node *)gw_get_selected_orig(bat_priv);
 		if (orig_node)
 			goto find_router;
 	}
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 7/8] batman-adv: protect softif_neigh by rcu
From: Sven Eckelmann @ 2011-04-17 19:30 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r, Marek Lindner,
	Simon Wunderlich
In-Reply-To: <1303068618-27928-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

From: Simon Wunderlich <siwu-MaAgPAbsBIVS8oHt8HbXEIQuADTiUCJX@public.gmane.org>

Add get/set wrapper functions for softif_neigh and
use rcu functions to manipulate the pointers.

Signed-off-by: Simon Wunderlich <siwu-MaAgPAbsBIVS8oHt8HbXEIQuADTiUCJX@public.gmane.org>
Signed-off-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
Signed-off-by: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
---
 net/batman-adv/soft-interface.c |  114 +++++++++++++++++++++++++++++---------
 net/batman-adv/types.h          |    2 +-
 2 files changed, 88 insertions(+), 28 deletions(-)

diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 824e1f6..a60fd48 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -90,10 +90,51 @@ static void softif_neigh_free_ref(struct softif_neigh *softif_neigh)
 		call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
 }
 
+static struct softif_neigh *softif_neigh_get_selected(struct bat_priv *bat_priv)
+{
+	struct softif_neigh *neigh;
+
+	rcu_read_lock();
+	neigh = rcu_dereference(bat_priv->softif_neigh);
+
+	if (neigh && !atomic_inc_not_zero(&neigh->refcount))
+		neigh = NULL;
+
+	rcu_read_unlock();
+	return neigh;
+}
+
+static void softif_neigh_select(struct bat_priv *bat_priv,
+				struct softif_neigh *new_neigh)
+{
+	struct softif_neigh *curr_neigh;
+
+	spin_lock_bh(&bat_priv->softif_neigh_lock);
+
+	if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount))
+		new_neigh = NULL;
+
+	curr_neigh = bat_priv->softif_neigh;
+	rcu_assign_pointer(bat_priv->softif_neigh, new_neigh);
+
+	if (curr_neigh)
+		softif_neigh_free_ref(curr_neigh);
+
+	spin_unlock_bh(&bat_priv->softif_neigh_lock);
+}
+
+static void softif_neigh_deselect(struct bat_priv *bat_priv)
+{
+	softif_neigh_select(bat_priv, NULL);
+}
+
 void softif_neigh_purge(struct bat_priv *bat_priv)
 {
-	struct softif_neigh *softif_neigh, *softif_neigh_tmp;
+	struct softif_neigh *softif_neigh, *curr_softif_neigh;
 	struct hlist_node *node, *node_tmp;
+	char do_deselect = 0;
+
+	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
 
 	spin_lock_bh(&bat_priv->softif_neigh_lock);
 
@@ -105,22 +146,26 @@ void softif_neigh_purge(struct bat_priv *bat_priv)
 		    (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE))
 			continue;
 
-		hlist_del_rcu(&softif_neigh->list);
-
-		if (bat_priv->softif_neigh == softif_neigh) {
+		if (curr_softif_neigh == softif_neigh) {
 			bat_dbg(DBG_ROUTES, bat_priv,
 				 "Current mesh exit point '%pM' vanished "
 				 "(vid: %d).\n",
 				 softif_neigh->addr, softif_neigh->vid);
-			softif_neigh_tmp = bat_priv->softif_neigh;
-			bat_priv->softif_neigh = NULL;
-			softif_neigh_free_ref(softif_neigh_tmp);
+			do_deselect = 1;
 		}
 
+		hlist_del_rcu(&softif_neigh->list);
 		softif_neigh_free_ref(softif_neigh);
 	}
 
 	spin_unlock_bh(&bat_priv->softif_neigh_lock);
+
+	/* soft_neigh_deselect() needs to acquire the softif_neigh_lock */
+	if (do_deselect)
+		softif_neigh_deselect(bat_priv);
+
+	if (curr_softif_neigh)
+		softif_neigh_free_ref(curr_softif_neigh);
 }
 
 static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
@@ -171,6 +216,7 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
 	struct bat_priv *bat_priv = netdev_priv(net_dev);
 	struct softif_neigh *softif_neigh;
 	struct hlist_node *node;
+	struct softif_neigh *curr_softif_neigh;
 
 	if (!bat_priv->primary_if) {
 		return seq_printf(seq, "BATMAN mesh %s disabled - "
@@ -180,14 +226,17 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
 
 	seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
 
+	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(softif_neigh, node,
 				 &bat_priv->softif_neigh_list, list)
 		seq_printf(seq, "%s %pM (vid: %d)\n",
-				bat_priv->softif_neigh == softif_neigh
+				curr_softif_neigh == softif_neigh
 				? "=>" : "  ", softif_neigh->addr,
 				softif_neigh->vid);
 	rcu_read_unlock();
+	if (curr_softif_neigh)
+		softif_neigh_free_ref(curr_softif_neigh);
 
 	return 0;
 }
@@ -198,7 +247,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
 	struct bat_priv *bat_priv = netdev_priv(dev);
 	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
 	struct batman_packet *batman_packet;
-	struct softif_neigh *softif_neigh, *softif_neigh_tmp;
+	struct softif_neigh *softif_neigh;
+	struct softif_neigh *curr_softif_neigh = NULL;
 
 	if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
 		batman_packet = (struct batman_packet *)
@@ -223,7 +273,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
 	if (!softif_neigh)
 		goto err;
 
-	if (bat_priv->softif_neigh == softif_neigh)
+	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
+	if (curr_softif_neigh == softif_neigh)
 		goto out;
 
 	/* we got a neighbor but its mac is 'bigger' than ours  */
@@ -232,38 +283,39 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
 		goto out;
 
 	/* switch to new 'smallest neighbor' */
-	if ((bat_priv->softif_neigh) &&
-	    (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr,
+	if ((curr_softif_neigh) &&
+	    (memcmp(softif_neigh->addr, curr_softif_neigh->addr,
 							ETH_ALEN) < 0)) {
 		bat_dbg(DBG_ROUTES, bat_priv,
 			"Changing mesh exit point from %pM (vid: %d) "
 			"to %pM (vid: %d).\n",
-			 bat_priv->softif_neigh->addr,
-			 bat_priv->softif_neigh->vid,
+			 curr_softif_neigh->addr,
+			 curr_softif_neigh->vid,
 			 softif_neigh->addr, softif_neigh->vid);
-		softif_neigh_tmp = bat_priv->softif_neigh;
-		bat_priv->softif_neigh = softif_neigh;
-		softif_neigh_free_ref(softif_neigh_tmp);
-		/* we need to hold the additional reference */
-		goto err;
+
+		softif_neigh_select(bat_priv, softif_neigh);
+		goto out;
 	}
 
 	/* close own batX device and use softif_neigh as exit node */
-	if ((!bat_priv->softif_neigh) &&
+	if ((!curr_softif_neigh) &&
 	    (memcmp(softif_neigh->addr,
 		    bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) {
 		bat_dbg(DBG_ROUTES, bat_priv,
 			"Setting mesh exit point to %pM (vid: %d).\n",
 			softif_neigh->addr, softif_neigh->vid);
-		bat_priv->softif_neigh = softif_neigh;
-		/* we need to hold the additional reference */
-		goto err;
+
+		softif_neigh_select(bat_priv, softif_neigh);
+		goto out;
 	}
 
 out:
 	softif_neigh_free_ref(softif_neigh);
 err:
 	kfree_skb(skb);
+	if (curr_softif_neigh)
+		softif_neigh_free_ref(curr_softif_neigh);
+
 	return;
 }
 
@@ -321,6 +373,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
 	struct bcast_packet *bcast_packet;
 	struct vlan_ethhdr *vhdr;
+	struct softif_neigh *curr_softif_neigh = NULL;
 	int data_len = skb->len, ret;
 	short vid = -1;
 	bool do_bcast = false;
@@ -348,7 +401,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 	 * if we have a another chosen mesh exit node in range
 	 * it will transport the packets to the mesh
 	 */
-	if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid))
+	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
+	if ((curr_softif_neigh) && (curr_softif_neigh->vid == vid))
 		goto dropped;
 
 	/* TODO: check this for locks */
@@ -410,6 +464,8 @@ dropped:
 dropped_freed:
 	bat_priv->stats.tx_dropped++;
 end:
+	if (curr_softif_neigh)
+		softif_neigh_free_ref(curr_softif_neigh);
 	return NETDEV_TX_OK;
 }
 
@@ -421,6 +477,7 @@ void interface_rx(struct net_device *soft_iface,
 	struct unicast_packet *unicast_packet;
 	struct ethhdr *ethhdr;
 	struct vlan_ethhdr *vhdr;
+	struct softif_neigh *curr_softif_neigh = NULL;
 	short vid = -1;
 	int ret;
 
@@ -450,7 +507,8 @@ void interface_rx(struct net_device *soft_iface,
 	 * if we have a another chosen mesh exit node in range
 	 * it will transport the packets to the non-mesh network
 	 */
-	if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) {
+	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
+	if (curr_softif_neigh && (curr_softif_neigh->vid == vid)) {
 		skb_push(skb, hdr_size);
 		unicast_packet = (struct unicast_packet *)skb->data;
 
@@ -461,7 +519,7 @@ void interface_rx(struct net_device *soft_iface,
 		skb_reset_mac_header(skb);
 
 		memcpy(unicast_packet->dest,
-		       bat_priv->softif_neigh->addr, ETH_ALEN);
+		       curr_softif_neigh->addr, ETH_ALEN);
 		ret = route_unicast_packet(skb, recv_if);
 		if (ret == NET_RX_DROP)
 			goto dropped;
@@ -486,11 +544,13 @@ void interface_rx(struct net_device *soft_iface,
 	soft_iface->last_rx = jiffies;
 
 	netif_rx(skb);
-	return;
+	goto out;
 
 dropped:
 	kfree_skb(skb);
 out:
+	if (curr_softif_neigh)
+		softif_neigh_free_ref(curr_softif_neigh);
 	return;
 }
 
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 091476d..75123b1 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -147,7 +147,7 @@ struct bat_priv {
 	atomic_t batman_queue_left;
 	char num_ifaces;
 	struct hlist_head softif_neigh_list;
-	struct softif_neigh *softif_neigh;
+	struct softif_neigh __rcu *softif_neigh;
 	struct debug_log *debug_log;
 	struct hard_iface *primary_if;
 	struct kobject *mesh_obj;
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 8/8] batman-adv: Set the txqueuelen to zero when creating soft interface
From: Sven Eckelmann @ 2011-04-17 19:30 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r, Marek Lindner
In-Reply-To: <1303068618-27928-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

From: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>

Like other virtual interfaces, e.g. br0, we don't need a transmit
queue. Packets should only be queued on real interfaces which are
underneath. In practice this patch makes little difference since the
virtual interfaces can accept packets as fast as they come, but the
patch will avoid bufferbloat questions to the mailling lists in the
future.

Signed-off-by: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
Tested-by: Linus Lüssing <linus.luessing-S0/GAf8tV78@public.gmane.org>
Signed-off-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
Signed-off-by: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
---
 net/batman-adv/soft-interface.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index a60fd48..1f6f756 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -584,6 +584,7 @@ static void interface_setup(struct net_device *dev)
 	dev->hard_start_xmit = interface_tx;
 #endif
 	dev->destructor = free_netdev;
+	dev->tx_queue_len = 0;
 
 	/**
 	 * can't call min_mtu, because the needed variables
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 1/1] drivers/net/usb/usbnet.c: Use FIELD_SIZEOF macro in usbnet_init() function.
From: Thiago Farina @ 2011-04-17 22:46 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: David Brownell, Greg Kroah-Hartman, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Thiago Farina

Signed-off-by: Thiago Farina <tfransosi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/net/usb/usbnet.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 069c1cf..7bc9852 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1529,9 +1529,9 @@ EXPORT_SYMBOL_GPL(usbnet_resume);
 
 static int __init usbnet_init(void)
 {
-	/* compiler should optimize this out */
-	BUILD_BUG_ON (sizeof (((struct sk_buff *)0)->cb)
-			< sizeof (struct skb_data));
+	/* Compiler should optimize this out. */
+	BUILD_BUG_ON(
+		FIELD_SIZEOF(struct sk_buff, cb) < sizeof(struct skb_data));
 
 	random_ether_addr(node_id);
 	return 0;
-- 
1.7.5.rc2.4.g4d8b3

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 0/42] Kill -Wunused-but-set warnings
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


The weather is real nice, so I decided to lock myself inside and
fix compiler warnings.

I started using gcc-4.6.x on my primary sparc64 build test machine the
other week and it now enables -Wunused-but-set with -Wall and it does
catch a bunch of bogus stuff.

Most of the cases are where you'd expect them, ISDN and ATM.

This is the first pass I've made over the networking cases.

There's still a bunch more to do.

^ permalink raw reply

* [PATCH 1/42] atm: eni: Kill set-but-unused variables.
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


The variable eni_dev is initialized but never subsequently used in
these two functions.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/atm/eni.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index c495fae..3230ea0 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1469,10 +1469,7 @@ if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost);
 
 static void bug_int(struct atm_dev *dev,unsigned long reason)
 {
-	struct eni_dev *eni_dev;
-
 	DPRINTK(">bug_int\n");
-	eni_dev = ENI_DEV(dev);
 	if (reason & MID_DMA_ERR_ACK)
 		printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
 		    "error\n",dev->number);
@@ -1900,7 +1897,6 @@ static void eni_close(struct atm_vcc *vcc)
 
 static int eni_open(struct atm_vcc *vcc)
 {
-	struct eni_dev *eni_dev;
 	struct eni_vcc *eni_vcc;
 	int error;
 	short vpi = vcc->vpi;
@@ -1910,7 +1906,6 @@ static int eni_open(struct atm_vcc *vcc)
 	EVENT("eni_open\n",0,0);
 	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))
 		vcc->dev_data = NULL;
-	eni_dev = ENI_DEV(vcc->dev);
 	if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
 		set_bit(ATM_VF_ADDR,&vcc->flags);
 	if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5)
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 2/42] atm: he: Fix undefined sequence points.
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


GCC complains in these queue index operations because we
perform operations of the form:

	x = some_operation(++x);

which is undefined.  Replace with:

	x = some_operation(x + 1);

which is well defined and provides the intended operation.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/atm/he.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 6cf59bf..9a51df4 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -1801,7 +1801,7 @@ return_host_buffers:
 next_rbrq_entry:
 		he_dev->rbrq_head = (struct he_rbrq *)
 				((unsigned long) he_dev->rbrq_base |
-					RBRQ_MASK(++he_dev->rbrq_head));
+					RBRQ_MASK(he_dev->rbrq_head + 1));
 
 	}
 	read_unlock(&vcc_sklist_lock);
@@ -1884,7 +1884,7 @@ next_tbrq_entry:
 			pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
 		he_dev->tbrq_head = (struct he_tbrq *)
 				((unsigned long) he_dev->tbrq_base |
-					TBRQ_MASK(++he_dev->tbrq_head));
+					TBRQ_MASK(he_dev->tbrq_head + 1));
 	}
 
 	if (updated) {
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 3/42] atm: idt77252: Fix set-but-unused variables.
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


Two cases here:

1) idt77252_rx_raw() really does not make any use of the
   extracted PTI field of the atm header.

2) idt77252_collect_stat() only uses the register values
   in code which has been compiled out by a "NOTDEF" cpp
   test for more than 10 years.  Just kill this NOTDEF
   code entirely, but keep the register reads in case
   they have side effects.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/atm/idt77252.c |   52 +++--------------------------------------------
 1 files changed, 4 insertions(+), 48 deletions(-)

diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 048f99f..1f8d724 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -1261,14 +1261,13 @@ idt77252_rx_raw(struct idt77252_dev *card)
 				    PCI_DMA_FROMDEVICE);
 
 	while (head != tail) {
-		unsigned int vpi, vci, pti;
+		unsigned int vpi, vci;
 		u32 header;
 
 		header = le32_to_cpu(*(u32 *) &queue->data[0]);
 
 		vpi = (header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT;
 		vci = (header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT;
-		pti = (header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;
 
 #ifdef CONFIG_ATM_IDT77252_DEBUG
 		if (debug & DBG_RAW_CELL) {
@@ -2709,53 +2708,10 @@ idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page)
 static void
 idt77252_collect_stat(struct idt77252_dev *card)
 {
-	u32 cdc, vpec, icc;
+	(void) readl(SAR_REG_CDC);
+	(void) readl(SAR_REG_VPEC);
+	(void) readl(SAR_REG_ICC);
 
-	cdc = readl(SAR_REG_CDC);
-	vpec = readl(SAR_REG_VPEC);
-	icc = readl(SAR_REG_ICC);
-
-#ifdef	NOTDEF
-	printk("%s:", card->name);
-
-	if (cdc & 0x7f0000) {
-		char *s = "";
-
-		printk(" [");
-		if (cdc & (1 << 22)) {
-			printk("%sRM ID", s);
-			s = " | ";
-		}
-		if (cdc & (1 << 21)) {
-			printk("%sCON TAB", s);
-			s = " | ";
-		}
-		if (cdc & (1 << 20)) {
-			printk("%sNO FB", s);
-			s = " | ";
-		}
-		if (cdc & (1 << 19)) {
-			printk("%sOAM CRC", s);
-			s = " | ";
-		}
-		if (cdc & (1 << 18)) {
-			printk("%sRM CRC", s);
-			s = " | ";
-		}
-		if (cdc & (1 << 17)) {
-			printk("%sRM FIFO", s);
-			s = " | ";
-		}
-		if (cdc & (1 << 16)) {
-			printk("%sRX FIFO", s);
-			s = " | ";
-		}
-		printk("]");
-	}
-
-	printk(" CDC %04x, VPEC %04x, ICC: %04x\n",
-	       cdc & 0xffff, vpec & 0xffff, icc & 0xffff);
-#endif
 }
 
 static irqreturn_t
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 4/42] atm: solos-pci: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


This is just a readback to entire completion of a register
write, keep the readback but kill the unused variable.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/atm/solos-pci.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index cd0ff66..5d1d076 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -527,7 +527,6 @@ static int flash_upgrade(struct solos_card *card, int chip)
 {
 	const struct firmware *fw;
 	const char *fw_name;
-	uint32_t data32 = 0;
 	int blocksize = 0;
 	int numblocks = 0;
 	int offset;
@@ -576,7 +575,7 @@ static int flash_upgrade(struct solos_card *card, int chip)
 	
 	dev_info(&card->dev->dev, "Changing FPGA to Update mode\n");
 	iowrite32(1, card->config_regs + FPGA_MODE);
-	data32 = ioread32(card->config_regs + FPGA_MODE); 
+	(void) ioread32(card->config_regs + FPGA_MODE); 
 
 	/* Set mode to Chip Erase */
 	if(chip == 0 || chip == 2)
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 5/42] pktgen: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


"iph" in pktgen_output_ipsec() is set but never actually
used.  Kill it off.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/core/pktgen.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index aeeece7..2fa6fee 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2514,7 +2514,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
 {
 	struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
 	int err = 0;
-	struct iphdr *iph;
 
 	if (!x)
 		return 0;
@@ -2524,7 +2523,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
 		return 0;
 
 	spin_lock(&x->lock);
-	iph = ip_hdr(skb);
 
 	err = x->outer_mode->output(x, skb);
 	if (err)
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 6/42] decnet: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


"next" in dn_rebuild_zone() is set but not actually used,
kill it off.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/decnet/dn_table.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 99d8d3a..d8ea583 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -124,11 +124,10 @@ static inline void dn_rebuild_zone(struct dn_zone *dz,
 				   int old_divisor)
 {
 	int i;
-	struct dn_fib_node *f, **fp, *next;
+	struct dn_fib_node *f, **fp;
 
 	for(i = 0; i < old_divisor; i++) {
 		for(f = old_ht[i]; f; f = f->fn_next) {
-			next = f->fn_next;
 			for(fp = dn_chain_p(f->fn_key, dz);
 				*fp && dn_key_leq((*fp)->fn_key, f->fn_key);
 				fp = &(*fp)->fn_next)
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 7/42] econet: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


#if 0'd out code for IP handling in aun_data_available() has
been commented out since the beginning, which makes the variable
"ip" set but not used.

Kill it off as well as the stub code.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/econet/af_econet.c |    8 --------
 1 files changed, 0 insertions(+), 8 deletions(-)

diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 116d3fd..a1d9f37 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -935,7 +935,6 @@ static void aun_data_available(struct sock *sk, int slen)
 	struct sk_buff *skb;
 	unsigned char *data;
 	struct aunhdr *ah;
-	struct iphdr *ip;
 	size_t len;
 
 	while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) {
@@ -949,7 +948,6 @@ static void aun_data_available(struct sock *sk, int slen)
 	data = skb_transport_header(skb) + sizeof(struct udphdr);
 	ah = (struct aunhdr *)data;
 	len = skb->len - sizeof(struct udphdr);
-	ip = ip_hdr(skb);
 
 	switch (ah->code)
 	{
@@ -962,12 +960,6 @@ static void aun_data_available(struct sock *sk, int slen)
 	case 4:
 		aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING);
 		break;
-#if 0
-		/* This isn't quite right yet. */
-	case 5:
-		aun_send_response(ip->saddr, ah->handle, 6, ah->cb);
-		break;
-#endif
 	default:
 		printk(KERN_DEBUG "unknown AUN packet (type %d)\n", data[0]);
 	}
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 8/42] ax25: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


The variable 's' is set but unused in ax25_protocol_release().
Just kill it off.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ax25/ax25_iface.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
index 5a0dda8..60b545e 100644
--- a/net/ax25/ax25_iface.c
+++ b/net/ax25/ax25_iface.c
@@ -58,7 +58,7 @@ EXPORT_SYMBOL_GPL(ax25_register_pid);
 
 void ax25_protocol_release(unsigned int pid)
 {
-	struct ax25_protocol *s, *protocol;
+	struct ax25_protocol *protocol;
 
 	write_lock_bh(&protocol_list_lock);
 	protocol = protocol_list;
@@ -72,7 +72,6 @@ void ax25_protocol_release(unsigned int pid)
 
 	while (protocol != NULL && protocol->next != NULL) {
 		if (protocol->next->pid == pid) {
-			s = protocol->next;
 			protocol->next = protocol->next->next;
 			goto out;
 		}
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 9/42] atm: lec: Fix set-but-unused variables.
From: David Miller @ 2011-04-18  0:32 UTC (permalink / raw)
  To: netdev


The variable 'eth' is set but unused in lec_handle_bridge().  Also,
the variable 'priv' is set but unused in lane_module_cleanup().

Just kill them off.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/atm/lec.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/net/atm/lec.c b/net/atm/lec.c
index 38754fd..25073b6 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -129,7 +129,6 @@ static struct net_device *dev_lec[MAX_LEC_ITF];
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
 static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
 {
-	struct ethhdr *eth;
 	char *buff;
 	struct lec_priv *priv;
 
@@ -138,7 +137,6 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
 	 * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit
 	 * as the Config BPDU has
 	 */
-	eth = (struct ethhdr *)skb->data;
 	buff = skb->data + skb->dev->hard_header_len;
 	if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
 		struct sock *sk;
@@ -1180,7 +1178,6 @@ static int __init lane_module_init(void)
 static void __exit lane_module_cleanup(void)
 {
 	int i;
-	struct lec_priv *priv;
 
 	remove_proc_entry("lec", atm_proc_root);
 
@@ -1188,7 +1185,6 @@ static void __exit lane_module_cleanup(void)
 
 	for (i = 0; i < MAX_LEC_ITF; i++) {
 		if (dev_lec[i] != NULL) {
-			priv = netdev_priv(dev_lec[i]);
 			unregister_netdev(dev_lec[i]);
 			free_netdev(dev_lec[i]);
 			dev_lec[i] = NULL;
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 10/42] bonding: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:33 UTC (permalink / raw)
  To: netdev


The variable 'vlan_dev' is set but unused in
bond_send_gratuitous_arp().  Just kill it off.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/bonding/bond_main.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index ca902ae..fdf9215 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2763,7 +2763,6 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
 {
 	struct slave *slave = bond->curr_active_slave;
 	struct vlan_entry *vlan;
-	struct net_device *vlan_dev;
 
 	pr_debug("bond_send_grat_arp: bond %s slave %s\n",
 		 bond->dev->name, slave ? slave->dev->name : "NULL");
@@ -2783,7 +2782,6 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
 		return;
 
 	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
-		vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
 		if (vlan->vlan_ip) {
 			bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip,
 				      vlan->vlan_ip, vlan->vlan_id);
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 11/42] atlx: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:33 UTC (permalink / raw)
  To: netdev


The variable 'tpc' is set but unused in atl1_intr_tx().
Just kill it off.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/atlx/atl1.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 98334a1..dffa691 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -2074,9 +2074,6 @@ static void atl1_intr_tx(struct atl1_adapter *adapter)
 	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
 
 	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
-		struct tx_packet_desc *tpd;
-
-		tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
 		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
 		if (buffer_info->dma) {
 			pci_unmap_page(adapter->pdev, buffer_info->dma,
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 12/42] atl1e: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:33 UTC (permalink / raw)
  To: netdev


The variable 'tx_ring' is set but unused in
atl1e_init_ring_resources().  Just kill it off.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/atl1e/atl1e_main.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 9900ca1..86a9122 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -691,10 +691,8 @@ static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size)
 
 static void atl1e_init_ring_resources(struct atl1e_adapter *adapter)
 {
-	struct atl1e_tx_ring *tx_ring = NULL;
 	struct atl1e_rx_ring *rx_ring = NULL;
 
-	tx_ring = &adapter->tx_ring;
 	rx_ring = &adapter->rx_ring;
 
 	rx_ring->real_page_size = adapter->rx_ring.page_size
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 13/42] atl1c: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:33 UTC (permalink / raw)
  To: netdev


The variable 'extra_size' is set but unused in
atl1c_configure_tx().  Just kill it off.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/atl1c/atl1c_main.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index 894d485..5c64a5d 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -1095,10 +1095,8 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter)
 	u32 max_pay_load;
 	u16 tx_offload_thresh;
 	u32 txq_ctrl_data;
-	u32 extra_size = 0;     /* Jumbo frame threshold in QWORD unit */
 	u32 max_pay_load_data;
 
-	extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
 	tx_offload_thresh = MAX_TX_OFFLOAD_THRESH;
 	AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH,
 		(tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK);
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 14/42] isdn: gigaset: Fix set-but-unused variable.
From: David Miller @ 2011-04-18  0:33 UTC (permalink / raw)
  To: netdev


The variable 'offset' is set but unused in
write_iso_tasklet().  Just kill it off.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/isdn/gigaset/bas-gigaset.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 8a3c5cf..3913f47 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -1157,7 +1157,6 @@ static void write_iso_tasklet(unsigned long data)
 	struct urb *urb;
 	int status;
 	struct usb_iso_packet_descriptor *ifd;
-	int offset;
 	unsigned long flags;
 	int i;
 	struct sk_buff *skb;
@@ -1225,7 +1224,6 @@ static void write_iso_tasklet(unsigned long data)
 			 *   successfully sent
 			 * - all following frames are not sent at all
 			 */
-			offset = done->limit;	/* default (no error) */
 			for (i = 0; i < BAS_NUMFRAMES; i++) {
 				ifd = &urb->iso_frame_desc[i];
 				if (ifd->status ||
@@ -1235,9 +1233,6 @@ static void write_iso_tasklet(unsigned long data)
 						 i, ifd->actual_length,
 						 ifd->length,
 						 get_usb_statmsg(ifd->status));
-					offset = (ifd->offset +
-						  ifd->actual_length)
-						 % BAS_OUTBUFSIZE;
 					break;
 				}
 			}
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 15/42] isdn: eicon: Fix set-but-unused variables.
From: David Miller @ 2011-04-18  0:33 UTC (permalink / raw)
  To: netdev


The variable 'best_id' is set but unused in
diva_mnt_add_xdi_adapter().  Just kill it off.

Similarly for the variable 'CIP' in connect_req(), 'Number' in
sig_ind(), 'Info' in dtmf_confirmation() mixer_command()
fax_connect_ack_command() fax_edata_ack_command()
rtp_connect_b3_res_command() and rtp_connect_b3_res_command(), and 'a'
in mixer_indication_coefs_set(),

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/isdn/hardware/eicon/debug.c   |    3 +--
 drivers/isdn/hardware/eicon/message.c |   23 ++---------------------
 2 files changed, 3 insertions(+), 23 deletions(-)

diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
index 3626401..7a9894c 100644
--- a/drivers/isdn/hardware/eicon/debug.c
+++ b/drivers/isdn/hardware/eicon/debug.c
@@ -861,7 +861,7 @@ static int diva_get_idi_adapter_info (IDI_CALL request, dword* serial, dword* lo
 void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
   diva_os_spin_lock_magic_t old_irql, old_irql1;
   dword sec, usec, logical, serial, org_mask;
-  int id, best_id = 0, free_id = -1;
+  int id, free_id = -1;
   char tmp[128];
   diva_dbg_entry_head_t* pmsg = NULL;
   int len;
@@ -906,7 +906,6 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
         and slot is still free - reuse it
         */
       free_id = id;
-      best_id = 1;
       break;
     }
   }
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
index 8c5c563..a339598 100644
--- a/drivers/isdn/hardware/eicon/message.c
+++ b/drivers/isdn/hardware/eicon/message.c
@@ -1198,7 +1198,6 @@ static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
   word ch;
   word i;
   word Info;
-  word CIP;
   byte LinkLayer;
   API_PARSE * ai;
   API_PARSE * bp;
@@ -1340,7 +1339,6 @@ static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
         add_s(plci,BC,&parms[6]);
         add_s(plci,LLC,&parms[7]);
         add_s(plci,HLC,&parms[8]);
-        CIP = GET_WORD(parms[0].info);
         if (a->Info_Mask[appl->Id-1] & 0x200)
         {
           /* early B3 connect (CIP mask bit 9) no release after a disc */
@@ -4830,7 +4828,6 @@ static void sig_ind(PLCI *plci)
   dword x_Id;
   dword Id;
   dword rId;
-  word Number = 0;
   word i;
   word cip;
   dword cip_mask;
@@ -5106,7 +5103,7 @@ static void sig_ind(PLCI *plci)
     }
   }
 
-  if(plci->appl) Number = plci->appl->Number++;
+  if(plci->appl) plci->appl->Number++;
 
   switch(plci->Sig.Ind) {
   /* Response to Get_Supported_Services request */
@@ -5894,7 +5891,6 @@ static void sig_ind(PLCI *plci)
     break;
 
   case TEL_CTRL:
-    Number = 0;
     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
       switch (ie[1]&0x91) {
@@ -10119,14 +10115,12 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI
 
 static void dtmf_confirmation (dword Id, PLCI   *plci)
 {
-  word Info;
   word i;
     byte result[4];
 
   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
     UnMapId (Id), (char   *)(FILE_), __LINE__));
 
-  Info = GOOD;
   result[0] = 2;
   PUT_WORD (&result[1], DTMF_SUCCESS);
   if (plci->dtmf_send_requests != 0)
@@ -11520,13 +11514,12 @@ static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
 static void mixer_command (dword Id, PLCI   *plci, byte Rc)
 {
   DIVA_CAPI_ADAPTER   *a;
-  word i, internal_command, Info;
+  word i, internal_command;
 
   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
     plci->li_cmd));
 
-  Info = GOOD;
   a = plci->adapter;
   internal_command = plci->internal_command;
   plci->internal_command = 0;
@@ -11550,7 +11543,6 @@ static void mixer_command (dword Id, PLCI   *plci, byte Rc)
         {
           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
             UnMapId (Id), (char   *)(FILE_), __LINE__));
-          Info = _FACILITY_NOT_SUPPORTED;
           break;
         }
         if (plci->internal_command)
@@ -11592,7 +11584,6 @@ static void mixer_command (dword Id, PLCI   *plci, byte Rc)
             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
           }
-          Info = _FACILITY_NOT_SUPPORTED;
           break;
         }
         if (plci->internal_command)
@@ -11610,7 +11601,6 @@ static void mixer_command (dword Id, PLCI   *plci, byte Rc)
         {
           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
             UnMapId (Id), (char   *)(FILE_), __LINE__));
-          Info = _FACILITY_NOT_SUPPORTED;
           break;
         }
         if (plci->internal_command)
@@ -12448,13 +12438,11 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI
 static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
 {
   dword d;
-  DIVA_CAPI_ADAPTER   *a;
     byte result[12];
 
   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
     UnMapId (Id), (char   *)(FILE_), __LINE__));
 
-  a = plci->adapter;
   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
   {
     do
@@ -14111,13 +14099,11 @@ static void select_b_command (dword Id, PLCI   *plci, byte Rc)
 
 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
 {
-  word Info;
   word internal_command;
 
   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
 
-  Info = GOOD;
   internal_command = plci->internal_command;
   plci->internal_command = 0;
   switch (internal_command)
@@ -14160,13 +14146,11 @@ static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
 
 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
 {
-  word Info;
   word internal_command;
 
   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
 
-  Info = GOOD;
   internal_command = plci->internal_command;
   plci->internal_command = 0;
   switch (internal_command)
@@ -14395,13 +14379,11 @@ static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
 
 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
 {
-  word Info;
   word internal_command;
 
   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
 
-  Info = GOOD;
   internal_command = plci->internal_command;
   plci->internal_command = 0;
   switch (internal_command)
@@ -14423,7 +14405,6 @@ static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
     {
       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
-      Info = _WRONG_STATE;
       break;
     }
     if (plci_nl_busy (plci))
-- 
1.7.4.3


^ permalink raw reply related

* [PATCH 16/42] isdn: hfcpci: Fix set-but-unused variables.
From: David Miller @ 2011-04-18  0:33 UTC (permalink / raw)
  To: netdev


The variable 'total' is set but unused in
hfcpci_empty_bfifo().  Just kill it off.

Similarly for the variable 'val' in ph_state_nt().

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/isdn/hardware/mISDN/hfcpci.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 4343aba..b01a7be 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -405,7 +405,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
     u_char *bdata, int count)
 {
 	u_char		*ptr, *ptr1, new_f2;
-	int		total, maxlen, new_z2;
+	int		maxlen, new_z2;
 	struct zt	*zp;
 
 	if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO))
@@ -431,7 +431,6 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
 			printk(KERN_WARNING "HFCPCI: receive out of memory\n");
 			return;
 		}
-		total = count;
 		count -= 3;
 		ptr = skb_put(bch->rx_skb, count);
 
@@ -968,7 +967,6 @@ static void
 ph_state_nt(struct dchannel *dch)
 {
 	struct hfc_pci	*hc = dch->hw;
-	u_char	val;
 
 	if (dch->debug)
 		printk(KERN_DEBUG "%s: NT newstate %x\n",
@@ -982,7 +980,7 @@ ph_state_nt(struct dchannel *dch)
 			hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
 			Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
 			/* Clear already pending ints */
-			val = Read_hfc(hc, HFCPCI_INT_S1);
+			(void) Read_hfc(hc, HFCPCI_INT_S1);
 			Write_hfc(hc, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
 			udelay(10);
 			Write_hfc(hc, HFCPCI_STATES, 4);
-- 
1.7.4.3


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox