From 59f0551e666a8b98dc86a862d8abdd20ed5be096 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 5 Dec 2007 01:51:58 -0800 Subject: [PATCH] --- yaml --- r: 78338 b: refs/heads/master c: 27ab2568649d5ba6c5a20212079b7c4f6da4ca0d h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/skbuff.h | 2 +- trunk/net/core/datagram.c | 9 ++++++++- trunk/net/ipv4/udp.c | 5 ++--- trunk/net/ipv6/udp.c | 4 ++-- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/[refs] b/[refs] index de75dc0228d9..6b2ff5412b0c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c8fecf2242a0ab7230210665986b8ef915e1ae9e +refs/heads/master: 27ab2568649d5ba6c5a20212079b7c4f6da4ca0d diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index d39f53ef66bb..17b3f70fbbc3 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -1549,7 +1549,7 @@ extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen, struct iovec *iov); extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); -extern void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, +extern int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); extern __wsum skb_checksum(const struct sk_buff *skb, int offset, int len, __wsum csum); diff --git a/trunk/net/core/datagram.c b/trunk/net/core/datagram.c index 029b93e246b4..fbd6c76436d0 100644 --- a/trunk/net/core/datagram.c +++ b/trunk/net/core/datagram.c @@ -217,20 +217,27 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb) * This function currently only disables BH when acquiring the * sk_receive_queue lock. Therefore it must not be used in a * context where that lock is acquired in an IRQ context. + * + * It returns 0 if the packet was removed by us. */ -void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) +int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) { + int err = 0; + if (flags & MSG_PEEK) { + err = -ENOENT; spin_lock_bh(&sk->sk_receive_queue.lock); if (skb == skb_peek(&sk->sk_receive_queue)) { __skb_unlink(skb, &sk->sk_receive_queue); atomic_dec(&skb->users); + err = 0; } spin_unlock_bh(&sk->sk_receive_queue.lock); } kfree_skb(skb); + return err; } EXPORT_SYMBOL(skb_kill_datagram); diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index d0283b7fcec5..f50de5d5218d 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -899,9 +899,8 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, return err; csum_copy_err: - UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); - - skb_kill_datagram(sk, skb, flags); + if (!skb_kill_datagram(sk, skb, flags)) + UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); if (noblock) return -EAGAIN; diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 77ab31b99232..87bccec9882a 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -207,8 +207,8 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, return err; csum_copy_err: - UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); - skb_kill_datagram(sk, skb, flags); + if (!skb_kill_datagram(sk, skb, flags)) + UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); if (flags & MSG_DONTWAIT) return -EAGAIN;