@@ -161,6 +161,43 @@ static struct sk_buff *skb_set_peeked(struct sk_buff *skb)
161
161
return skb ;
162
162
}
163
163
164
+ struct sk_buff * __skb_try_recv_from_queue (struct sock * sk ,
165
+ struct sk_buff_head * queue ,
166
+ unsigned int flags ,
167
+ void (* destructor )(struct sock * sk ,
168
+ struct sk_buff * skb ),
169
+ int * peeked , int * off , int * err ,
170
+ struct sk_buff * * last )
171
+ {
172
+ struct sk_buff * skb ;
173
+
174
+ * last = queue -> prev ;
175
+ skb_queue_walk (queue , skb ) {
176
+ if (flags & MSG_PEEK ) {
177
+ if (* off >= skb -> len && (skb -> len || * off ||
178
+ skb -> peeked )) {
179
+ * off -= skb -> len ;
180
+ continue ;
181
+ }
182
+ if (!skb -> len ) {
183
+ skb = skb_set_peeked (skb );
184
+ if (unlikely (IS_ERR (skb ))) {
185
+ * err = PTR_ERR (skb );
186
+ return skb ;
187
+ }
188
+ }
189
+ * peeked = 1 ;
190
+ atomic_inc (& skb -> users );
191
+ } else {
192
+ __skb_unlink (skb , queue );
193
+ if (destructor )
194
+ destructor (sk , skb );
195
+ }
196
+ return skb ;
197
+ }
198
+ return NULL ;
199
+ }
200
+
164
201
/**
165
202
* __skb_try_recv_datagram - Receive a datagram skbuff
166
203
* @sk: socket
@@ -216,46 +253,20 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
216
253
217
254
* peeked = 0 ;
218
255
do {
256
+ int _off = * off ;
257
+
219
258
/* Again only user level code calls this function, so nothing
220
259
* interrupt level will suddenly eat the receive_queue.
221
260
*
222
261
* Look at current nfs client by the way...
223
262
* However, this function was correct in any case. 8)
224
263
*/
225
- int _off = * off ;
226
-
227
- * last = (struct sk_buff * )queue ;
228
264
spin_lock_irqsave (& queue -> lock , cpu_flags );
229
- skb_queue_walk (queue , skb ) {
230
- * last = skb ;
231
- if (flags & MSG_PEEK ) {
232
- if (_off >= skb -> len && (skb -> len || _off ||
233
- skb -> peeked )) {
234
- _off -= skb -> len ;
235
- continue ;
236
- }
237
- if (!skb -> len ) {
238
- skb = skb_set_peeked (skb );
239
- if (IS_ERR (skb )) {
240
- error = PTR_ERR (skb );
241
- spin_unlock_irqrestore (& queue -> lock ,
242
- cpu_flags );
243
- goto no_packet ;
244
- }
245
- }
246
- * peeked = 1 ;
247
- atomic_inc (& skb -> users );
248
- } else {
249
- __skb_unlink (skb , queue );
250
- if (destructor )
251
- destructor (sk , skb );
252
- }
253
- spin_unlock_irqrestore (& queue -> lock , cpu_flags );
254
- * off = _off ;
255
- return skb ;
256
- }
257
-
265
+ skb = __skb_try_recv_from_queue (sk , queue , flags , destructor ,
266
+ peeked , & _off , err , last );
258
267
spin_unlock_irqrestore (& queue -> lock , cpu_flags );
268
+ if (skb )
269
+ return skb ;
259
270
260
271
if (!sk_can_busy_loop (sk ))
261
272
break ;
@@ -335,24 +346,24 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
335
346
}
336
347
EXPORT_SYMBOL (__skb_free_datagram_locked );
337
348
338
- int __sk_queue_drop_skb (struct sock * sk , struct sk_buff * skb ,
339
- unsigned int flags ,
349
+ int __sk_queue_drop_skb (struct sock * sk , struct sk_buff_head * sk_queue ,
350
+ struct sk_buff * skb , unsigned int flags ,
340
351
void (* destructor )(struct sock * sk ,
341
352
struct sk_buff * skb ))
342
353
{
343
354
int err = 0 ;
344
355
345
356
if (flags & MSG_PEEK ) {
346
357
err = - ENOENT ;
347
- spin_lock_bh (& sk -> sk_receive_queue . lock );
348
- if (skb == skb_peek (& sk -> sk_receive_queue )) {
349
- __skb_unlink (skb , & sk -> sk_receive_queue );
358
+ spin_lock_bh (& sk_queue -> lock );
359
+ if (skb == skb_peek (sk_queue )) {
360
+ __skb_unlink (skb , sk_queue );
350
361
atomic_dec (& skb -> users );
351
362
if (destructor )
352
363
destructor (sk , skb );
353
364
err = 0 ;
354
365
}
355
- spin_unlock_bh (& sk -> sk_receive_queue . lock );
366
+ spin_unlock_bh (& sk_queue -> lock );
356
367
}
357
368
358
369
atomic_inc (& sk -> sk_drops );
@@ -383,7 +394,8 @@ EXPORT_SYMBOL(__sk_queue_drop_skb);
383
394
384
395
int skb_kill_datagram (struct sock * sk , struct sk_buff * skb , unsigned int flags )
385
396
{
386
- int err = __sk_queue_drop_skb (sk , skb , flags , NULL );
397
+ int err = __sk_queue_drop_skb (sk , & sk -> sk_receive_queue , skb , flags ,
398
+ NULL );
387
399
388
400
kfree_skb (skb );
389
401
sk_mem_reclaim_partial (sk );
0 commit comments