diff options
author | Eric Dumazet <edumazet@google.com> | 2013-12-15 10:53:46 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-12-17 14:50:58 -0500 |
commit | e47eb5dfb296bf217e9ebee7b2f07486670b9c1b (patch) | |
tree | cad273de648996d679f3cbfba678b84ff14f40b7 /net | |
parent | 50dc875f2e6e2e04aed3b3033eb0ac99192d6d02 (diff) | |
download | linux-stable-e47eb5dfb296bf217e9ebee7b2f07486670b9c1b.tar.gz linux-stable-e47eb5dfb296bf217e9ebee7b2f07486670b9c1b.tar.bz2 linux-stable-e47eb5dfb296bf217e9ebee7b2f07486670b9c1b.zip |
udp: ipv4: do not use sk_dst_lock from softirq context
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/udp.c | 13 |
1 files changed, 4 insertions, 9 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 62c19fdd102d..f140048334ce 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -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); } /* |