aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-12-05 04:53:40 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:56:34 -0500
commita59322be07c964e916d15be3df473fb7ba20c41e (patch)
tree16d4caa41c1fd6c3fb907ce792202b157e6c9a1e /net/core
parent1781f7f5804e52ee2d35328b129602146a8d8254 (diff)
[UDP]: Only increment counter on first peek/recv
The previous move of the the UDP inDatagrams counter caused each peek of the same packet to be counted separately. This may be undesirable. This patch fixes this by adding a bit to sk_buff to record whether this packet has already been seen through skb_recv_datagram. We then only increment the counter when the packet is seen for the first time. The only dodgy part is the fact that skb_recv_datagram doesn't have a good way of returning this new bit of information. So I've added a new function __skb_recv_datagram that does return this and made skb_recv_datagram a wrapper around it. The plan is to eventually replace all uses of skb_recv_datagram with this new function at which time it can be renamed its proper name. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/datagram.c43
1 files changed, 27 insertions, 16 deletions
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{