From: marek Date: Fri, 27 Aug 2010 17:42:48 +0000 (+0000) Subject: batman-adv: adding stability patches X-Git-Url: http://207.154.207.93/?a=commitdiff_plain;h=2de2e5f023d630708438fa42765168c6b5417388;p=packages.git batman-adv: adding stability patches Signed-off-by: Marek Lindner git-svn-id: svn://svn.openwrt.org/openwrt/packages@22823 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- 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 index 000000000..444b78a79 --- /dev/null +++ b/net/batman-advanced/patches/0001-batman-adv-Don-t-increment-stats-of-foreign-device.patch @@ -0,0 +1,44 @@ +From 3a50ba56201d00b700111c29b05e4cf4b49236d3 Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +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 +--- + 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 index 000000000..3f617fdcb --- /dev/null +++ b/net/batman-advanced/patches/0002-batman-adv-unify-orig_hash_lock-spinlock-handling-to.patch @@ -0,0 +1,79 @@ +From 3680f6998508e0a2a22bad3837028d172bb197b1 Mon Sep 17 00:00:00 2001 +From: Marek Lindner +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 +Signed-off-by: Marek Lindner +Signed-off-by: Sven Eckelmann +--- + 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 index 000000000..72cd83781 --- /dev/null +++ b/net/batman-advanced/patches/0003-batman-adv-Create-batman_if-only-on-register-event.patch @@ -0,0 +1,45 @@ +From 3bb2899bd37b1bb127adaa6808f4b1fa716df0de Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +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 +Cc: stable +--- + 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 index 000000000..8bbdfd257 --- /dev/null +++ b/net/batman-advanced/patches/0004-batman-adv-Don-t-use-net_dev-after-dev_put.patch @@ -0,0 +1,80 @@ +From 91235b4ca86709f2974fc954c2ff81fd8e5ac926 Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +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 +Signed-off-by: Sven Eckelmann +Cc: stable +--- + 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 index 000000000..a26785e39 --- /dev/null +++ b/net/batman-advanced/patches/0005-batman-adv-Don-t-write-in-not-allocated-packet_buff.patch @@ -0,0 +1,52 @@ +From e3a0cc90940915dd14e4ca6bdab6d74bbc60f4a4 Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +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 +Reported-by: Kazuki Shimada +Signed-off-by: Sven Eckelmann +Cc: stable +--- + 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 +