diff options
Diffstat (limited to 'net/batman-adv/vis.c')
-rw-r--r-- | net/batman-adv/vis.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index 8092eadcbdee..9832d8f9ed44 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c | |||
@@ -764,21 +764,35 @@ static void unicast_vis_packet(struct bat_priv *bat_priv, | |||
764 | struct vis_info *info) | 764 | struct vis_info *info) |
765 | { | 765 | { |
766 | struct orig_node *orig_node; | 766 | struct orig_node *orig_node; |
767 | struct neigh_node *neigh_node = NULL; | ||
767 | struct sk_buff *skb; | 768 | struct sk_buff *skb; |
768 | struct vis_packet *packet; | 769 | struct vis_packet *packet; |
769 | struct batman_if *batman_if; | 770 | struct batman_if *batman_if; |
770 | uint8_t dstaddr[ETH_ALEN]; | 771 | uint8_t dstaddr[ETH_ALEN]; |
771 | 772 | ||
772 | spin_lock_bh(&bat_priv->orig_hash_lock); | ||
773 | packet = (struct vis_packet *)info->skb_packet->data; | 773 | packet = (struct vis_packet *)info->skb_packet->data; |
774 | |||
775 | spin_lock_bh(&bat_priv->orig_hash_lock); | ||
774 | rcu_read_lock(); | 776 | rcu_read_lock(); |
775 | orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, | 777 | orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, |
776 | compare_orig, choose_orig, | 778 | compare_orig, choose_orig, |
777 | packet->target_orig)); | 779 | packet->target_orig)); |
778 | rcu_read_unlock(); | ||
779 | 780 | ||
780 | if ((!orig_node) || (!orig_node->router)) | 781 | if (!orig_node) |
781 | goto out; | 782 | goto unlock; |
783 | |||
784 | kref_get(&orig_node->refcount); | ||
785 | neigh_node = orig_node->router; | ||
786 | |||
787 | if (!neigh_node) | ||
788 | goto unlock; | ||
789 | |||
790 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
791 | neigh_node = NULL; | ||
792 | goto unlock; | ||
793 | } | ||
794 | |||
795 | rcu_read_unlock(); | ||
782 | 796 | ||
783 | /* don't lock while sending the packets ... we therefore | 797 | /* don't lock while sending the packets ... we therefore |
784 | * copy the required data before sending */ | 798 | * copy the required data before sending */ |
@@ -790,10 +804,17 @@ static void unicast_vis_packet(struct bat_priv *bat_priv, | |||
790 | if (skb) | 804 | if (skb) |
791 | send_skb_packet(skb, batman_if, dstaddr); | 805 | send_skb_packet(skb, batman_if, dstaddr); |
792 | 806 | ||
793 | return; | 807 | goto out; |
794 | 808 | ||
795 | out: | 809 | unlock: |
810 | rcu_read_unlock(); | ||
796 | spin_unlock_bh(&bat_priv->orig_hash_lock); | 811 | spin_unlock_bh(&bat_priv->orig_hash_lock); |
812 | out: | ||
813 | if (neigh_node) | ||
814 | neigh_node_free_ref(neigh_node); | ||
815 | if (orig_node) | ||
816 | kref_put(&orig_node->refcount, orig_node_free_ref); | ||
817 | return; | ||
797 | } | 818 | } |
798 | 819 | ||
799 | /* only send one vis packet. called from send_vis_packets() */ | 820 | /* only send one vis packet. called from send_vis_packets() */ |