Skip to content

Commit 65101ae

Browse files
Paolo Abenidavem330
authored andcommitted
net/sock: factor out dequeue/peek with offset code
And update __sk_queue_drop_skb() to work on the specified queue. This will help the udp protocol to use an additional private rx queue in a later patch. Signed-off-by: Paolo Abeni <[email protected]> Acked-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9dca599 commit 65101ae

File tree

3 files changed

+60
-41
lines changed

3 files changed

+60
-41
lines changed

include/linux/skbuff.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3056,6 +3056,13 @@ static inline void skb_frag_list_init(struct sk_buff *skb)
30563056

30573057
int __skb_wait_for_more_packets(struct sock *sk, int *err, long *timeo_p,
30583058
const struct sk_buff *skb);
3059+
struct sk_buff *__skb_try_recv_from_queue(struct sock *sk,
3060+
struct sk_buff_head *queue,
3061+
unsigned int flags,
3062+
void (*destructor)(struct sock *sk,
3063+
struct sk_buff *skb),
3064+
int *peeked, int *off, int *err,
3065+
struct sk_buff **last);
30593066
struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned flags,
30603067
void (*destructor)(struct sock *sk,
30613068
struct sk_buff *skb),

include/net/sock.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,8 +2035,8 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer,
20352035

20362036
void sk_stop_timer(struct sock *sk, struct timer_list *timer);
20372037

2038-
int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
2039-
unsigned int flags,
2038+
int __sk_queue_drop_skb(struct sock *sk, struct sk_buff_head *sk_queue,
2039+
struct sk_buff *skb, unsigned int flags,
20402040
void (*destructor)(struct sock *sk,
20412041
struct sk_buff *skb));
20422042
int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);

net/core/datagram.c

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,43 @@ static struct sk_buff *skb_set_peeked(struct sk_buff *skb)
161161
return skb;
162162
}
163163

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+
164201
/**
165202
* __skb_try_recv_datagram - Receive a datagram skbuff
166203
* @sk: socket
@@ -216,46 +253,20 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
216253

217254
*peeked = 0;
218255
do {
256+
int _off = *off;
257+
219258
/* Again only user level code calls this function, so nothing
220259
* interrupt level will suddenly eat the receive_queue.
221260
*
222261
* Look at current nfs client by the way...
223262
* However, this function was correct in any case. 8)
224263
*/
225-
int _off = *off;
226-
227-
*last = (struct sk_buff *)queue;
228264
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);
258267
spin_unlock_irqrestore(&queue->lock, cpu_flags);
268+
if (skb)
269+
return skb;
259270

260271
if (!sk_can_busy_loop(sk))
261272
break;
@@ -335,24 +346,24 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
335346
}
336347
EXPORT_SYMBOL(__skb_free_datagram_locked);
337348

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,
340351
void (*destructor)(struct sock *sk,
341352
struct sk_buff *skb))
342353
{
343354
int err = 0;
344355

345356
if (flags & MSG_PEEK) {
346357
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);
350361
atomic_dec(&skb->users);
351362
if (destructor)
352363
destructor(sk, skb);
353364
err = 0;
354365
}
355-
spin_unlock_bh(&sk->sk_receive_queue.lock);
366+
spin_unlock_bh(&sk_queue->lock);
356367
}
357368

358369
atomic_inc(&sk->sk_drops);
@@ -383,7 +394,8 @@ EXPORT_SYMBOL(__sk_queue_drop_skb);
383394

384395
int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
385396
{
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);
387399

388400
kfree_skb(skb);
389401
sk_mem_reclaim_partial(sk);

0 commit comments

Comments
 (0)