batman-adv: adding stability patches

Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>



git-svn-id: svn://svn.openwrt.org/openwrt/packages@22823 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
marek 2010-08-27 17:42:48 +00:00
parent 14bf835bfb
commit 2de2e5f023
5 changed files with 300 additions and 0 deletions

View File

@ -0,0 +1,44 @@
From 3a50ba56201d00b700111c29b05e4cf4b49236d3 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven.eckelmann@gmx.de>
Date: Tue, 20 Jul 2010 23:05:04 +0200
Subject: [PATCH 01/10] batman-adv: Don't increment stats of foreign device
The receive hook for batman-adv ethernet frames tried to get the last
device which processed the skb before us. It only used that information
to update the rx_bytes and rx_packets stat of that foreign device which
already has updated it using its own receive functions.
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
---
compat.h | 8 --------
hard-interface.c | 8 --------
2 files changed, 0 insertions(+), 16 deletions(-)
diff --git a/hard-interface.c b/hard-interface.c
index 6a37c33..e3e1e9e 100644
--- a/hard-interface.c
+++ b/hard-interface.c
@@ -440,7 +440,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
{
struct batman_packet *batman_packet;
struct batman_if *batman_if;
- struct net_device_stats *stats;
int ret;
skb = skb_share_check(skb, GFP_ATOMIC);
@@ -469,12 +468,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
if (batman_if->if_status != IF_ACTIVE)
goto err_free;
- stats = (struct net_device_stats *)dev_get_stats(skb->dev);
- if (stats) {
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
- }
-
batman_packet = (struct batman_packet *)skb->data;
if (batman_packet->version != COMPAT_VERSION) {
--
1.7.1

View File

@ -0,0 +1,79 @@
From 3680f6998508e0a2a22bad3837028d172bb197b1 Mon Sep 17 00:00:00 2001
From: Marek Lindner <lindner_marek@yahoo.de>
Date: Sun, 8 Aug 2010 13:01:11 +0000
Subject: [PATCH 04/10] batman-adv: unify orig_hash_lock spinlock handling to avoid deadlocks
The orig_hash_lock spinlock always has to be locked with IRQs being
disabled to avoid deadlocks between code that is being executed in
IRQ context and code that is being executed in non-IRQ context.
Reported-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
---
originator.c | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/originator.c b/originator.c
index 9fa1ac3..068210a 100644
--- a/originator.c
+++ b/originator.c
@@ -392,11 +392,12 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
{
struct orig_node *orig_node;
+ unsigned long flags;
HASHIT(hashit);
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
* if_num */
- spin_lock(&orig_hash_lock);
+ spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
@@ -405,11 +406,11 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
goto err;
}
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
return 0;
err:
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
return -ENOMEM;
}
@@ -469,12 +470,13 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
{
struct batman_if *batman_if_tmp;
struct orig_node *orig_node;
+ unsigned long flags;
HASHIT(hashit);
int ret;
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
* if_num */
- spin_lock(&orig_hash_lock);
+ spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
@@ -501,10 +503,10 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
rcu_read_unlock();
batman_if->if_num = -1;
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
return 0;
err:
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
return -ENOMEM;
}
--
1.7.1

View File

@ -0,0 +1,45 @@
From 3bb2899bd37b1bb127adaa6808f4b1fa716df0de Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven.eckelmann@gmx.de>
Date: Fri, 20 Aug 2010 19:16:00 +0000
Subject: [PATCH 08/10] batman-adv: Create batman_if only on register event
We try to get all events for all net_devices to be able to add special
sysfs folders for the batman-adv configuration. This also includes such
events like NETDEV_POST_INIT which has no valid kobject according to
v2.6.32-rc3-13-g7ffbe3f. This would create an oops in that situation.
It is enough to create the batman_if only on NETDEV_REGISTER events
because we will also receive those events for devices which already
existed when we registered the notifier call.
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Cc: stable <stable@kernel.org>
---
hard-interface.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/hard-interface.c b/hard-interface.c
index e3e1e9e..1670ec8 100644
--- a/hard-interface.c
+++ b/hard-interface.c
@@ -395,15 +395,13 @@ static int hard_if_event(struct notifier_block *this,
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
- if (!batman_if)
- batman_if = hardif_add_interface(net_dev);
+ if (!batman_if && event == NETDEV_REGISTER)
+ batman_if = hardif_add_interface(net_dev);
if (!batman_if)
goto out;
switch (event) {
- case NETDEV_REGISTER:
- break;
case NETDEV_UP:
hardif_activate_interface(soft_device, bat_priv, batman_if);
break;
--
1.7.1

View File

@ -0,0 +1,80 @@
From 91235b4ca86709f2974fc954c2ff81fd8e5ac926 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven.eckelmann@gmx.de>
Date: Fri, 20 Aug 2010 19:16:11 +0000
Subject: [PATCH 09/10] batman-adv: Don't use net_dev after dev_put
dev_put allows a device to be freed when all its references are dropped.
After that we are not allowed to access that information anymore. Access
to the data structure of a net_device must be surrounded a dev_hold
and ended using dev_put.
batman-adv adds a device to its own management structure in
hardif_add_interface and will release it in hardif_remove_interface.
Thus it must hold a reference all the time between those functions to
prevent any access to the already released net_device structure.
Reported-by: Tim Glaremin <Tim.Glaremin@web.de>
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Cc: stable <stable@kernel.org>
---
hard-interface.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/hard-interface.c b/hard-interface.c
index 1670ec8..ce6819a 100644
--- a/hard-interface.c
+++ b/hard-interface.c
@@ -196,8 +196,6 @@ static void hardif_activate_interface(struct net_device *net_dev,
if (batman_if->if_status != IF_INACTIVE)
return;
- dev_hold(batman_if->net_dev);
-
update_mac_addresses(batman_if);
batman_if->if_status = IF_TO_BE_ACTIVATED;
@@ -224,8 +222,6 @@ static void hardif_deactivate_interface(struct net_device *net_dev,
(batman_if->if_status != IF_TO_BE_ACTIVATED))
return;
- dev_put(batman_if->net_dev);
-
batman_if->if_status = IF_INACTIVE;
bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev);
@@ -322,12 +318,14 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
if (ret != 1)
goto out;
+ dev_hold(net_dev);
+
batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
if (!batman_if) {
printk(KERN_ERR "batman-adv:"
"Can't add interface (%s): out of memory\n",
net_dev->name);
- goto out;
+ goto release_dev;
}
batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC);
@@ -348,6 +346,8 @@ free_dev:
kfree(batman_if->dev);
free_if:
kfree(batman_if);
+release_dev:
+ dev_put(net_dev);
out:
return NULL;
}
@@ -376,6 +376,7 @@ static void hardif_remove_interface(struct batman_if *batman_if)
batman_if->if_status = IF_TO_BE_REMOVED;
list_del_rcu(&batman_if->list);
sysfs_del_hardif(&batman_if->hardif_obj);
+ dev_put(batman_if->net_dev);
call_rcu(&batman_if->rcu, hardif_free_interface);
}
--
1.7.1

View File

@ -0,0 +1,52 @@
From e3a0cc90940915dd14e4ca6bdab6d74bbc60f4a4 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven.eckelmann@gmx.de>
Date: Fri, 20 Aug 2010 17:32:38 +0200
Subject: [PATCH 10/10] batman-adv: Don't write in not allocated packet_buff
Each net_device in a system will automatically managed as a possible
batman_if and holds different informations like a buffer with a prepared
originator messages. To reduce the memory usage, the packet_buff will
only be allocated when the interface is really added/enabled for
batman-adv.
The function to update the hw address information inside the packet_buff
just assumes that the packet_buff is always initialised and thus the
kernel will just oops when we try to change the hw address of a not
already fully enabled interface.
We must always check if the packet_buff is allocated before we try to
change information inside of it.
Reported-by: Tim Glaremin <Tim.Glaremin@web.de>
Reported-by: Kazuki Shimada <zukky@bb.banban.jp>
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Cc: stable <stable@kernel.org>
---
hard-interface.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/hard-interface.c b/hard-interface.c
index ce6819a..4ef6504 100644
--- a/hard-interface.c
+++ b/hard-interface.c
@@ -131,6 +131,9 @@ static bool hardif_is_iface_up(struct batman_if *batman_if)
static void update_mac_addresses(struct batman_if *batman_if)
{
+ if (!batman_if || !batman_if->packet_buff)
+ return;
+
addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
@@ -336,6 +339,7 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
batman_if->if_num = -1;
batman_if->net_dev = net_dev;
batman_if->if_status = IF_NOT_IN_USE;
+ batman_if->packet_buff = NULL;
INIT_LIST_HEAD(&batman_if->list);
check_known_mac_addr(batman_if->net_dev->dev_addr);
--
1.7.1