aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/vis.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/vis.c')
-rw-r--r--net/batman-adv/vis.c33
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
795out: 809unlock:
810 rcu_read_unlock();
796 spin_unlock_bh(&bat_priv->orig_hash_lock); 811 spin_unlock_bh(&bat_priv->orig_hash_lock);
812out:
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() */