udp: ipv4: do not use sk_dst_lock from softirq context
authorEric Dumazet <edumazet@google.com>
Sun, 15 Dec 2013 18:53:46 +0000 (10:53 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 17 Dec 2013 19:50:58 +0000 (14:50 -0500)
Using sk_dst_lock from softirq context is not supported right now.

Instead of adding BH protection everywhere,
udp_sk_rx_dst_set() can instead use xchg(), as suggested
by David.

Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Fixes: 975022310233 ("udp: ipv4: must add synchronization in udp_sk_rx_dst_set()")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/udp.c

index 62c19fdd102d9bb1f3d8757c6de1debd6533ed50..f140048334ce21f38d86ac4a2fdf770df5330d78 100644 (file)
@@ -1600,20 +1600,15 @@ static void flush_stack(struct sock **stack, unsigned int count,
 }
 
 /* For TCP sockets, sk_rx_dst is protected by socket lock
- * For UDP, we use sk_dst_lock to guard against concurrent changes.
+ * For UDP, we use xchg() to guard against concurrent changes.
  */
 static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
 {
        struct dst_entry *old;
 
-       spin_lock(&sk->sk_dst_lock);
-       old = sk->sk_rx_dst;
-       if (likely(old != dst)) {
-               dst_hold(dst);
-               sk->sk_rx_dst = dst;
-               dst_release(old);
-       }
-       spin_unlock(&sk->sk_dst_lock);
+       dst_hold(dst);
+       old = xchg(&sk->sk_rx_dst, dst);
+       dst_release(old);
 }
 
 /*