diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-05-04 02:18:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-04 02:18:14 -0400 |
commit | 93bb64eac10aad3dae6178d7da94765f207d121f (patch) | |
tree | 5f0990ed1a0a9fa9483d828a16235085d5d84215 /net/core | |
parent | f5460618405eec8c3300947a499011528a115acd (diff) |
net: skb_free_datagram_locked() fix
Commit 4b0b72f7dd617b ( net: speedup udp receive path )
introduced a bug in skb_free_datagram_locked().
We should not skb_orphan() skb if we dont have the guarantee we are the
last skb user, this might happen with MSG_PEEK concurrent users.
To keep socket locked for the smallest period of time, we split
consume_skb() logic, inlined in skb_free_datagram_locked()
Reported-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/datagram.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/net/core/datagram.c b/net/core/datagram.c index 95b851f3d713..e0097531417a 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -229,13 +229,18 @@ EXPORT_SYMBOL(skb_free_datagram); | |||
229 | 229 | ||
230 | void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) | 230 | void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) |
231 | { | 231 | { |
232 | if (likely(atomic_read(&skb->users) == 1)) | ||
233 | smp_rmb(); | ||
234 | else if (likely(!atomic_dec_and_test(&skb->users))) | ||
235 | return; | ||
236 | |||
232 | lock_sock_bh(sk); | 237 | lock_sock_bh(sk); |
233 | skb_orphan(skb); | 238 | skb_orphan(skb); |
234 | sk_mem_reclaim_partial(sk); | 239 | sk_mem_reclaim_partial(sk); |
235 | unlock_sock_bh(sk); | 240 | unlock_sock_bh(sk); |
236 | 241 | ||
237 | /* skb is now orphaned, might be freed outside of locked section */ | 242 | /* skb is now orphaned, can be freed outside of locked section */ |
238 | consume_skb(skb); | 243 | __kfree_skb(skb); |
239 | } | 244 | } |
240 | EXPORT_SYMBOL(skb_free_datagram_locked); | 245 | EXPORT_SYMBOL(skb_free_datagram_locked); |
241 | 246 | ||