decnet: Add missing neigh->ha locking to dn_neigh_output_packet()
authorDavid S. Miller <davem@davemloft.net>
Wed, 1 Feb 2012 21:34:25 +0000 (16:34 -0500)
committerDavid S. Miller <davem@davemloft.net>
Wed, 1 Feb 2012 21:34:25 +0000 (16:34 -0500)
Basically, mirror the logic in neigh_connected_output().

Signed-off-by: David S. Miller <davem@davemloft.net>
net/decnet/dn_neigh.c

index befe426491ba0c793ac176ed9d3994f5d73e9b31..ee7013f24fcabc2518b3dfa8234e8cade433daa8 100644 (file)
@@ -205,17 +205,23 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
        struct neighbour *neigh = dst_get_neighbour_noref(dst);
        struct net_device *dev = neigh->dev;
        char mac_addr[ETH_ALEN];
+       unsigned int seq;
+       int err;
 
        dn_dn2eth(mac_addr, rt->rt_local_src);
-       if (dev_hard_header(skb, dev, ntohs(skb->protocol), neigh->ha,
-                           mac_addr, skb->len) >= 0)
-               return dev_queue_xmit(skb);
-
-       if (net_ratelimit())
-               printk(KERN_DEBUG "dn_neigh_output_packet: oops, can't send packet\n");
-
-       kfree_skb(skb);
-       return -EINVAL;
+       do {
+               seq = read_seqbegin(&neigh->ha_lock);
+               err = dev_hard_header(skb, dev, ntohs(skb->protocol),
+                                     neigh->ha, mac_addr, skb->len);
+       } while (read_seqretry(&neigh->ha_lock, seq));
+
+       if (err >= 0)
+               err = dev_queue_xmit(skb);
+       else {
+               kfree_skb(skb);
+               err = -EINVAL;
+       }
+       return err;
 }
 
 static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)