diff options
author | Sven Eckelmann <sven@narfation.org> | 2011-05-03 05:51:38 -0400 |
---|---|---|
committer | Sven Eckelmann <sven@narfation.org> | 2011-05-08 10:10:41 -0400 |
commit | c3caf5196c47a5d1c325308d8eb7f6b020ba12df (patch) | |
tree | 6c94a6272919cb238dea5e0d4a3c06f27e7bb3f3 /net/batman-adv | |
parent | 61906ae86d8989e5bd3bc1f51b2fb8d32ffde2c5 (diff) |
batman-adv: Remove unnecessary hardif_list_lock
hardif_list_lock is unneccessary because we already ensure that no
multiple admin operations can take place through rtnl_lock.
hardif_list_lock only adds additional overhead and complexity.
Critical functions now check whether they are called with rtnl_lock
using ASSERT_RTNL.
It indirectly fixes the problem that orig_hash_del_if() expects that
only one interface is deleted from hardif_list at a time, but
hardif_remove_interfaces() removes all at once and then calls
orig_hash_del_if().
Reported-by: Linus Lüssing <linus.luessing@web.de>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/bat_sysfs.c | 2 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.c | 30 | ||||
-rw-r--r-- | net/batman-adv/main.c | 3 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 2 |
4 files changed, 13 insertions, 24 deletions
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index e449bf6353e0..85ba20d98a66 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c | |||
@@ -502,7 +502,9 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, | |||
502 | rtnl_unlock(); | 502 | rtnl_unlock(); |
503 | } | 503 | } |
504 | 504 | ||
505 | rtnl_lock(); | ||
505 | ret = hardif_enable_interface(hard_iface, buff); | 506 | ret = hardif_enable_interface(hard_iface, buff); |
507 | rtnl_unlock(); | ||
506 | 508 | ||
507 | out: | 509 | out: |
508 | hardif_free_ref(hard_iface); | 510 | hardif_free_ref(hard_iface); |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 3e888f133d75..7e2f7728f706 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -31,9 +31,6 @@ | |||
31 | 31 | ||
32 | #include <linux/if_arp.h> | 32 | #include <linux/if_arp.h> |
33 | 33 | ||
34 | /* protect update critical side of hardif_list - but not the content */ | ||
35 | static DEFINE_SPINLOCK(hardif_list_lock); | ||
36 | |||
37 | 34 | ||
38 | static int batman_skb_recv(struct sk_buff *skb, | 35 | static int batman_skb_recv(struct sk_buff *skb, |
39 | struct net_device *dev, | 36 | struct net_device *dev, |
@@ -136,7 +133,7 @@ static void primary_if_select(struct bat_priv *bat_priv, | |||
136 | struct hard_iface *curr_hard_iface; | 133 | struct hard_iface *curr_hard_iface; |
137 | struct batman_packet *batman_packet; | 134 | struct batman_packet *batman_packet; |
138 | 135 | ||
139 | spin_lock_bh(&hardif_list_lock); | 136 | ASSERT_RTNL(); |
140 | 137 | ||
141 | if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) | 138 | if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) |
142 | new_hard_iface = NULL; | 139 | new_hard_iface = NULL; |
@@ -148,7 +145,7 @@ static void primary_if_select(struct bat_priv *bat_priv, | |||
148 | hardif_free_ref(curr_hard_iface); | 145 | hardif_free_ref(curr_hard_iface); |
149 | 146 | ||
150 | if (!new_hard_iface) | 147 | if (!new_hard_iface) |
151 | goto out; | 148 | return; |
152 | 149 | ||
153 | batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); | 150 | batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); |
154 | batman_packet->flags = PRIMARIES_FIRST_HOP; | 151 | batman_packet->flags = PRIMARIES_FIRST_HOP; |
@@ -161,9 +158,6 @@ static void primary_if_select(struct bat_priv *bat_priv, | |||
161 | * our new primary interface | 158 | * our new primary interface |
162 | */ | 159 | */ |
163 | atomic_set(&bat_priv->hna_local_changed, 1); | 160 | atomic_set(&bat_priv->hna_local_changed, 1); |
164 | |||
165 | out: | ||
166 | spin_unlock_bh(&hardif_list_lock); | ||
167 | } | 161 | } |
168 | 162 | ||
169 | static bool hardif_is_iface_up(struct hard_iface *hard_iface) | 163 | static bool hardif_is_iface_up(struct hard_iface *hard_iface) |
@@ -456,6 +450,8 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) | |||
456 | struct hard_iface *hard_iface; | 450 | struct hard_iface *hard_iface; |
457 | int ret; | 451 | int ret; |
458 | 452 | ||
453 | ASSERT_RTNL(); | ||
454 | |||
459 | ret = is_valid_iface(net_dev); | 455 | ret = is_valid_iface(net_dev); |
460 | if (ret != 1) | 456 | if (ret != 1) |
461 | goto out; | 457 | goto out; |
@@ -482,10 +478,7 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) | |||
482 | atomic_set(&hard_iface->refcount, 2); | 478 | atomic_set(&hard_iface->refcount, 2); |
483 | 479 | ||
484 | check_known_mac_addr(hard_iface->net_dev); | 480 | check_known_mac_addr(hard_iface->net_dev); |
485 | |||
486 | spin_lock(&hardif_list_lock); | ||
487 | list_add_tail_rcu(&hard_iface->list, &hardif_list); | 481 | list_add_tail_rcu(&hard_iface->list, &hardif_list); |
488 | spin_unlock(&hardif_list_lock); | ||
489 | 482 | ||
490 | return hard_iface; | 483 | return hard_iface; |
491 | 484 | ||
@@ -499,6 +492,8 @@ out: | |||
499 | 492 | ||
500 | static void hardif_remove_interface(struct hard_iface *hard_iface) | 493 | static void hardif_remove_interface(struct hard_iface *hard_iface) |
501 | { | 494 | { |
495 | ASSERT_RTNL(); | ||
496 | |||
502 | /* first deactivate interface */ | 497 | /* first deactivate interface */ |
503 | if (hard_iface->if_status != IF_NOT_IN_USE) | 498 | if (hard_iface->if_status != IF_NOT_IN_USE) |
504 | hardif_disable_interface(hard_iface); | 499 | hardif_disable_interface(hard_iface); |
@@ -514,20 +509,11 @@ static void hardif_remove_interface(struct hard_iface *hard_iface) | |||
514 | void hardif_remove_interfaces(void) | 509 | void hardif_remove_interfaces(void) |
515 | { | 510 | { |
516 | struct hard_iface *hard_iface, *hard_iface_tmp; | 511 | struct hard_iface *hard_iface, *hard_iface_tmp; |
517 | struct list_head if_queue; | ||
518 | |||
519 | INIT_LIST_HEAD(&if_queue); | ||
520 | 512 | ||
521 | spin_lock(&hardif_list_lock); | 513 | rtnl_lock(); |
522 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, | 514 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, |
523 | &hardif_list, list) { | 515 | &hardif_list, list) { |
524 | list_del_rcu(&hard_iface->list); | 516 | list_del_rcu(&hard_iface->list); |
525 | list_add_tail(&hard_iface->list, &if_queue); | ||
526 | } | ||
527 | spin_unlock(&hardif_list_lock); | ||
528 | |||
529 | rtnl_lock(); | ||
530 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, &if_queue, list) { | ||
531 | hardif_remove_interface(hard_iface); | 517 | hardif_remove_interface(hard_iface); |
532 | } | 518 | } |
533 | rtnl_unlock(); | 519 | rtnl_unlock(); |
@@ -556,9 +542,7 @@ static int hard_if_event(struct notifier_block *this, | |||
556 | hardif_deactivate_interface(hard_iface); | 542 | hardif_deactivate_interface(hard_iface); |
557 | break; | 543 | break; |
558 | case NETDEV_UNREGISTER: | 544 | case NETDEV_UNREGISTER: |
559 | spin_lock(&hardif_list_lock); | ||
560 | list_del_rcu(&hard_iface->list); | 545 | list_del_rcu(&hard_iface->list); |
561 | spin_unlock(&hardif_list_lock); | ||
562 | 546 | ||
563 | hardif_remove_interface(hard_iface); | 547 | hardif_remove_interface(hard_iface); |
564 | break; | 548 | break; |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 705e8be07c8d..7edf8d719e15 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -33,6 +33,9 @@ | |||
33 | #include "vis.h" | 33 | #include "vis.h" |
34 | #include "hash.h" | 34 | #include "hash.h" |
35 | 35 | ||
36 | |||
37 | /* List manipulations on hardif_list have to be rtnl_lock()'ed, | ||
38 | * list traversals just rcu-locked */ | ||
36 | struct list_head hardif_list; | 39 | struct list_head hardif_list; |
37 | 40 | ||
38 | unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 41 | unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 8cb13a03b0e1..9301e21052e7 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -819,7 +819,7 @@ struct net_device *softif_create(char *name) | |||
819 | goto out; | 819 | goto out; |
820 | } | 820 | } |
821 | 821 | ||
822 | ret = register_netdev(soft_iface); | 822 | ret = register_netdevice(soft_iface); |
823 | if (ret < 0) { | 823 | if (ret < 0) { |
824 | pr_err("Unable to register the batman interface '%s': %i\n", | 824 | pr_err("Unable to register the batman interface '%s': %i\n", |
825 | name, ret); | 825 | name, ret); |