mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
net/udp: do not touch skb->peeked unless really needed
In UDP recvmsg() path we currently access 3 cache lines from an skb while holding receive queue lock, plus another one if packet is dequeued, since we need to change skb->next->prev 1st cache line (contains ->next/prev pointers, offsets 0x00 and 0x08) 2nd cache line (skb->len & skb->peeked, offsets 0x80 and 0x8e) 3rd cache line (skb->truesize/users, offsets 0xe0 and 0xe4) skb->peeked is only needed to make sure 0-length packets are properly handled while MSG_PEEK is operated. I had first the intent to remove skb->peeked but the "MSG_PEEK at non-zero offset" support added by Sam Kumar makes this not possible. This patch avoids one cache line miss during the locked section, when skb->len and skb->peeked do not have to be read. It also avoids the skb_set_peeked() cost for non empty UDP datagrams. Signed-off-by: Eric Dumazet <edumazet@google.com> Acked-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e466af66c7
commit
a297569fe0
@ -214,6 +214,7 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
|
||||
if (error)
|
||||
goto no_packet;
|
||||
|
||||
*peeked = 0;
|
||||
do {
|
||||
/* Again only user level code calls this function, so nothing
|
||||
* interrupt level will suddenly eat the receive_queue.
|
||||
@ -227,22 +228,22 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
|
||||
spin_lock_irqsave(&queue->lock, cpu_flags);
|
||||
skb_queue_walk(queue, skb) {
|
||||
*last = skb;
|
||||
*peeked = skb->peeked;
|
||||
if (flags & MSG_PEEK) {
|
||||
if (_off >= skb->len && (skb->len || _off ||
|
||||
skb->peeked)) {
|
||||
_off -= skb->len;
|
||||
continue;
|
||||
}
|
||||
|
||||
skb = skb_set_peeked(skb);
|
||||
error = PTR_ERR(skb);
|
||||
if (IS_ERR(skb)) {
|
||||
spin_unlock_irqrestore(&queue->lock,
|
||||
cpu_flags);
|
||||
goto no_packet;
|
||||
if (!skb->len) {
|
||||
skb = skb_set_peeked(skb);
|
||||
if (IS_ERR(skb)) {
|
||||
error = PTR_ERR(skb);
|
||||
spin_unlock_irqrestore(&queue->lock,
|
||||
cpu_flags);
|
||||
goto no_packet;
|
||||
}
|
||||
}
|
||||
|
||||
*peeked = 1;
|
||||
atomic_inc(&skb->users);
|
||||
} else {
|
||||
__skb_unlink(skb, queue);
|
||||
|
Loading…
Reference in New Issue
Block a user