Commit 4aa64fad authored by Eric Dumazet's avatar Eric Dumazet Committed by Liu Jian
Browse files

tcp: avoid indirect calls to sock_rfree

mainline inclusion
from mainline-v5.17-rc1
commit 3df684c1
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I65HYE

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3df684c1a3d08a4f649689053a3d527b3b5fda9e



---------------------------

TCP uses sk_eat_skb() when skbs can be removed from receive queue.
However, the call to skb_orphan() from __kfree_skb() incurs
an indirect call so sock_rfee(), which is more expensive than
a direct call, especially for CONFIG_RETPOLINE=y.

Add tcp_eat_recv_skb() function to make the call before
__kfree_skb().

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
(cherry picked from commit 3df684c1)
Signed-off-by: default avatarLiu Jian <liujian56@huawei.com>
parent 9b85ce5f
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -1596,6 +1596,16 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied)
		tcp_send_ack(sk);
}

static void tcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb)
{
	if (likely(skb->destructor == sock_rfree)) {
		sock_rfree(skb);
		skb->destructor = NULL;
		skb->sk = NULL;
	}
	sk_eat_skb(sk, skb);
}

static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
{
	struct sk_buff *skb;
@@ -1615,7 +1625,7 @@ static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
		 * splitted a fat GRO packet, while we released socket lock
		 * in skb_splice_bits()
		 */
		sk_eat_skb(sk, skb);
		tcp_eat_recv_skb(sk, skb);
	}
	return NULL;
}
@@ -1683,11 +1693,11 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
				continue;
		}
		if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) {
			sk_eat_skb(sk, skb);
			tcp_eat_recv_skb(sk, skb);
			++seq;
			break;
		}
		sk_eat_skb(sk, skb);
		tcp_eat_recv_skb(sk, skb);
		if (!desc->count)
			break;
		WRITE_ONCE(tp->copied_seq, seq);
@@ -2317,14 +2327,14 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
		if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
			goto found_fin_ok;
		if (!(flags & MSG_PEEK))
			sk_eat_skb(sk, skb);
			tcp_eat_recv_skb(sk, skb);
		continue;

found_fin_ok:
		/* Process the FIN. */
		WRITE_ONCE(*seq, *seq + 1);
		if (!(flags & MSG_PEEK))
			sk_eat_skb(sk, skb);
			tcp_eat_recv_skb(sk, skb);
		break;
	} while (len > 0);