aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/skbuff.h3
-rw-r--r--net/core/datagram.c43
-rw-r--r--net/ipv4/udp.c7
-rw-r--r--net/ipv6/udp.c7
4 files changed, 40 insertions, 20 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 17b3f70fbbc3..c618fbf7d173 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -288,6 +288,7 @@ struct sk_buff {
288 __u8 pkt_type:3, 288 __u8 pkt_type:3,
289 fclone:2, 289 fclone:2,
290 ipvs_property:1, 290 ipvs_property:1,
291 peeked:1,
291 nf_trace:1; 292 nf_trace:1;
292 __be16 protocol; 293 __be16 protocol;
293 294
@@ -1538,6 +1539,8 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
1538 skb = skb->prev) 1539 skb = skb->prev)
1539 1540
1540 1541
1542extern struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
1543 int *peeked, int *err);
1541extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, 1544extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
1542 int noblock, int *err); 1545 int noblock, int *err);
1543extern unsigned int datagram_poll(struct file *file, struct socket *sock, 1546extern unsigned int datagram_poll(struct file *file, struct socket *sock,
diff --git a/net/core/datagram.c b/net/core/datagram.c
index fbd6c76436d0..2d733131d7ce 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -115,10 +115,10 @@ out_noerr:
115} 115}
116 116
117/** 117/**
118 * skb_recv_datagram - Receive a datagram skbuff 118 * __skb_recv_datagram - Receive a datagram skbuff
119 * @sk: socket 119 * @sk: socket
120 * @flags: MSG_ flags 120 * @flags: MSG_ flags
121 * @noblock: blocking operation? 121 * @peeked: returns non-zero if this packet has been seen before
122 * @err: error code returned 122 * @err: error code returned
123 * 123 *
124 * Get a datagram skbuff, understands the peeking, nonblocking wakeups 124 * Get a datagram skbuff, understands the peeking, nonblocking wakeups
@@ -143,8 +143,8 @@ out_noerr:
143 * quite explicitly by POSIX 1003.1g, don't change them without having 143 * quite explicitly by POSIX 1003.1g, don't change them without having
144 * the standard around please. 144 * the standard around please.
145 */ 145 */
146struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, 146struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
147 int noblock, int *err) 147 int *peeked, int *err)
148{ 148{
149 struct sk_buff *skb; 149 struct sk_buff *skb;
150 long timeo; 150 long timeo;
@@ -156,7 +156,7 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
156 if (error) 156 if (error)
157 goto no_packet; 157 goto no_packet;
158 158
159 timeo = sock_rcvtimeo(sk, noblock); 159 timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
160 160
161 do { 161 do {
162 /* Again only user level code calls this function, so nothing 162 /* Again only user level code calls this function, so nothing
@@ -165,18 +165,19 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
165 * Look at current nfs client by the way... 165 * Look at current nfs client by the way...
166 * However, this function was corrent in any case. 8) 166 * However, this function was corrent in any case. 8)
167 */ 167 */
168 if (flags & MSG_PEEK) { 168 unsigned long cpu_flags;
169 unsigned long cpu_flags; 169
170 170 spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
171 spin_lock_irqsave(&sk->sk_receive_queue.lock, 171 skb = skb_peek(&sk->sk_receive_queue);
172 cpu_flags); 172 if (skb) {
173 skb = skb_peek(&sk->sk_receive_queue); 173 *peeked = skb->peeked;
174 if (skb) 174 if (flags & MSG_PEEK) {
175 skb->peeked = 1;
175 atomic_inc(&skb->users); 176 atomic_inc(&skb->users);
176 spin_unlock_irqrestore(&sk->sk_receive_queue.lock, 177 } else
177 cpu_flags); 178 __skb_unlink(skb, &sk->sk_receive_queue);
178 } else 179 }
179 skb = skb_dequeue(&sk->sk_receive_queue); 180 spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
180 181
181 if (skb) 182 if (skb)
182 return skb; 183 return skb;
@@ -194,6 +195,16 @@ no_packet:
194 *err = error; 195 *err = error;
195 return NULL; 196 return NULL;
196} 197}
198EXPORT_SYMBOL(__skb_recv_datagram);
199
200struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
201 int noblock, int *err)
202{
203 int peeked;
204
205 return __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
206 &peeked, err);
207}
197 208
198void skb_free_datagram(struct sock *sk, struct sk_buff *skb) 209void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
199{ 210{
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 78cfcb4a1b3f..9ed6393c65d9 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -827,6 +827,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
827 struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; 827 struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
828 struct sk_buff *skb; 828 struct sk_buff *skb;
829 unsigned int ulen, copied; 829 unsigned int ulen, copied;
830 int peeked;
830 int err; 831 int err;
831 int is_udplite = IS_UDPLITE(sk); 832 int is_udplite = IS_UDPLITE(sk);
832 833
@@ -840,7 +841,8 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
840 return ip_recv_error(sk, msg, len); 841 return ip_recv_error(sk, msg, len);
841 842
842try_again: 843try_again:
843 skb = skb_recv_datagram(sk, flags, noblock, &err); 844 skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
845 &peeked, &err);
844 if (!skb) 846 if (!skb)
845 goto out; 847 goto out;
846 848
@@ -875,7 +877,8 @@ try_again:
875 if (err) 877 if (err)
876 goto out_free; 878 goto out_free;
877 879
878 UDP_INC_STATS_USER(UDP_MIB_INDATAGRAMS, is_udplite); 880 if (!peeked)
881 UDP_INC_STATS_USER(UDP_MIB_INDATAGRAMS, is_udplite);
879 882
880 sock_recv_timestamp(msg, sk, skb); 883 sock_recv_timestamp(msg, sk, skb);
881 884
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 36bdcd2e1b52..fa640765385e 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -123,6 +123,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
123 struct inet_sock *inet = inet_sk(sk); 123 struct inet_sock *inet = inet_sk(sk);
124 struct sk_buff *skb; 124 struct sk_buff *skb;
125 unsigned int ulen, copied; 125 unsigned int ulen, copied;
126 int peeked;
126 int err; 127 int err;
127 int is_udplite = IS_UDPLITE(sk); 128 int is_udplite = IS_UDPLITE(sk);
128 129
@@ -133,7 +134,8 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
133 return ipv6_recv_error(sk, msg, len); 134 return ipv6_recv_error(sk, msg, len);
134 135
135try_again: 136try_again:
136 skb = skb_recv_datagram(sk, flags, noblock, &err); 137 skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
138 &peeked, &err);
137 if (!skb) 139 if (!skb)
138 goto out; 140 goto out;
139 141
@@ -166,7 +168,8 @@ try_again:
166 if (err) 168 if (err)
167 goto out_free; 169 goto out_free;
168 170
169 UDP6_INC_STATS_USER(UDP_MIB_INDATAGRAMS, is_udplite); 171 if (!peeked)
172 UDP6_INC_STATS_USER(UDP_MIB_INDATAGRAMS, is_udplite);
170 173
171 sock_recv_timestamp(msg, sk, skb); 174 sock_recv_timestamp(msg, sk, skb);
172 175