From c512727cc4f109e533f0ee2c2046b6e61db2a348 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 28 Apr 2010 14:35:48 -0700 Subject: [PATCH] --- yaml --- r: 194612 b: refs/heads/master c: 4b0b72f7dd617b13abd1b04c947e15873e011a24 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/net/sock.h | 10 ++++++++++ trunk/net/core/datagram.c | 10 +++++++--- trunk/net/ipv4/udp.c | 12 ++++++------ trunk/net/ipv6/udp.c | 4 ++-- 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/[refs] b/[refs] index d540e9b25474..bacd337ee8b5 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cfc1fbb079b265bf69d4ceba590a2e2c1a1cde33 +refs/heads/master: 4b0b72f7dd617b13abd1b04c947e15873e011a24 diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index cf12b1e61fa6..d361c7769fe0 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -1021,6 +1021,16 @@ extern void release_sock(struct sock *sk); SINGLE_DEPTH_NESTING) #define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock)) +static inline void lock_sock_bh(struct sock *sk) +{ + spin_lock_bh(&sk->sk_lock.slock); +} + +static inline void unlock_sock_bh(struct sock *sk) +{ + spin_unlock_bh(&sk->sk_lock.slock); +} + extern struct sock *sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot); diff --git a/trunk/net/core/datagram.c b/trunk/net/core/datagram.c index 5574a5ddf908..95b851f3d713 100644 --- a/trunk/net/core/datagram.c +++ b/trunk/net/core/datagram.c @@ -229,9 +229,13 @@ EXPORT_SYMBOL(skb_free_datagram); void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) { - lock_sock(sk); - skb_free_datagram(sk, skb); - release_sock(sk); + lock_sock_bh(sk); + skb_orphan(skb); + sk_mem_reclaim_partial(sk); + unlock_sock_bh(sk); + + /* skb is now orphaned, might be freed outside of locked section */ + consume_skb(skb); } EXPORT_SYMBOL(skb_free_datagram_locked); diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index 63eb56b2d873..1f86965ba7d7 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -1062,10 +1062,10 @@ static unsigned int first_packet_length(struct sock *sk) spin_unlock_bh(&rcvq->lock); if (!skb_queue_empty(&list_kill)) { - lock_sock(sk); + lock_sock_bh(sk); __skb_queue_purge(&list_kill); sk_mem_reclaim_partial(sk); - release_sock(sk); + unlock_sock_bh(sk); } return res; } @@ -1196,10 +1196,10 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, return err; csum_copy_err: - lock_sock(sk); + lock_sock_bh(sk); if (!skb_kill_datagram(sk, skb, flags)) UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); - release_sock(sk); + unlock_sock_bh(sk); if (noblock) return -EAGAIN; @@ -1624,9 +1624,9 @@ int udp_rcv(struct sk_buff *skb) void udp_destroy_sock(struct sock *sk) { - lock_sock(sk); + lock_sock_bh(sk); udp_flush_pending_frames(sk); - release_sock(sk); + unlock_sock_bh(sk); } /* diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 3ead20ad9d07..91c60f0090a4 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -424,7 +424,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, return err; csum_copy_err: - lock_sock(sk); + lock_sock_bh(sk); if (!skb_kill_datagram(sk, skb, flags)) { if (is_udp4) UDP_INC_STATS_USER(sock_net(sk), @@ -433,7 +433,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, UDP6_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); } - release_sock(sk); + unlock_sock_bh(sk); if (flags & MSG_DONTWAIT) return -EAGAIN;