batman-adv: adding stability patches
authorMarek Lindner <lindner_marek@yahoo.de>
Fri, 27 Aug 2010 17:42:48 +0000 (17:42 +0000)
committerMarek Lindner <lindner_marek@yahoo.de>
Fri, 27 Aug 2010 17:42:48 +0000 (17:42 +0000)
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
SVN-Revision: 22823

net/batman-advanced/patches/0001-batman-adv-Don-t-increment-stats-of-foreign-device.patch [new file with mode: 0644]
net/batman-advanced/patches/0002-batman-adv-unify-orig_hash_lock-spinlock-handling-to.patch [new file with mode: 0644]
net/batman-advanced/patches/0003-batman-adv-Create-batman_if-only-on-register-event.patch [new file with mode: 0644]
net/batman-advanced/patches/0004-batman-adv-Don-t-use-net_dev-after-dev_put.patch [new file with mode: 0644]
net/batman-advanced/patches/0005-batman-adv-Don-t-write-in-not-allocated-packet_buff.patch [new file with mode: 0644]

diff --git a/net/batman-advanced/patches/0001-batman-adv-Don-t-increment-stats-of-foreign-device.patch b/net/batman-advanced/patches/0001-batman-adv-Don-t-increment-stats-of-foreign-device.patch
new file mode 100644 (file)
index 0000000..444b78a
--- /dev/null
@@ -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
+
diff --git a/net/batman-advanced/patches/0002-batman-adv-unify-orig_hash_lock-spinlock-handling-to.patch b/net/batman-advanced/patches/0002-batman-adv-unify-orig_hash_lock-spinlock-handling-to.patch
new file mode 100644 (file)
index 0000000..3f617fd
--- /dev/null
@@ -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
+
diff --git a/net/batman-advanced/patches/0003-batman-adv-Create-batman_if-only-on-register-event.patch b/net/batman-advanced/patches/0003-batman-adv-Create-batman_if-only-on-register-event.patch
new file mode 100644 (file)
index 0000000..72cd837
--- /dev/null
@@ -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
+
diff --git a/net/batman-advanced/patches/0004-batman-adv-Don-t-use-net_dev-after-dev_put.patch b/net/batman-advanced/patches/0004-batman-adv-Don-t-use-net_dev-after-dev_put.patch
new file mode 100644 (file)
index 0000000..8bbdfd2
--- /dev/null
@@ -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
+
diff --git a/net/batman-advanced/patches/0005-batman-adv-Don-t-write-in-not-allocated-packet_buff.patch b/net/batman-advanced/patches/0005-batman-adv-Don-t-write-in-not-allocated-packet_buff.patch
new file mode 100644 (file)
index 0000000..a26785e
--- /dev/null
@@ -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
+