Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcp: Save lock_sock() for memcg in inet_csk_accept().

If memcg is enabled, accept() acquires lock_sock() twice for each new
TCP/MPTCP socket in inet_csk_accept() and __inet_accept().

Let's move memcg operations from inet_csk_accept() to __inet_accept().

Note that SCTP somehow allocates a new socket by sk_alloc() in
sk->sk_prot->accept() and clones fields manually, instead of using
sk_clone_lock().

mem_cgroup_sk_alloc() is called for SCTP before __inet_accept(),
so I added the protocol check in __inet_accept(), but this can be
removed once SCTP uses sk_clone_lock().

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Reviewed-by: Shakeel Butt <shakeel.butt@linux.dev>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Acked-by: Roman Gushchin <roman.gushchin@linux.dev>
Link: https://patch.msgid.link/20251014235604.3057003-2-kuniyu@google.com

authored by

Kuniyuki Iwashima and committed by
Martin KaFai Lau
4a997d49 55db64dd

+22 -25
+22
net/ipv4/af_inet.c
··· 755 755 756 756 void __inet_accept(struct socket *sock, struct socket *newsock, struct sock *newsk) 757 757 { 758 + /* TODO: use sk_clone_lock() in SCTP and remove protocol checks */ 759 + if (mem_cgroup_sockets_enabled && 760 + (!IS_ENABLED(CONFIG_IP_SCTP) || sk_is_tcp(newsk))) { 761 + gfp_t gfp = GFP_KERNEL | __GFP_NOFAIL; 762 + 763 + mem_cgroup_sk_alloc(newsk); 764 + 765 + if (mem_cgroup_from_sk(newsk)) { 766 + int amt; 767 + 768 + /* The socket has not been accepted yet, no need 769 + * to look at newsk->sk_wmem_queued. 770 + */ 771 + amt = sk_mem_pages(newsk->sk_forward_alloc + 772 + atomic_read(&newsk->sk_rmem_alloc)); 773 + if (amt) 774 + mem_cgroup_sk_charge(newsk, amt, gfp); 775 + } 776 + 777 + kmem_cache_charge(newsk, gfp); 778 + } 779 + 758 780 sock_rps_record_flow(newsk); 759 781 WARN_ON(!((1 << newsk->sk_state) & 760 782 (TCPF_ESTABLISHED | TCPF_SYN_RECV |
-25
net/ipv4/inet_connection_sock.c
··· 712 712 713 713 release_sock(sk); 714 714 715 - if (mem_cgroup_sockets_enabled) { 716 - gfp_t gfp = GFP_KERNEL | __GFP_NOFAIL; 717 - int amt = 0; 718 - 719 - /* atomically get the memory usage, set and charge the 720 - * newsk->sk_memcg. 721 - */ 722 - lock_sock(newsk); 723 - 724 - mem_cgroup_sk_alloc(newsk); 725 - if (mem_cgroup_from_sk(newsk)) { 726 - /* The socket has not been accepted yet, no need 727 - * to look at newsk->sk_wmem_queued. 728 - */ 729 - amt = sk_mem_pages(newsk->sk_forward_alloc + 730 - atomic_read(&newsk->sk_rmem_alloc)); 731 - } 732 - 733 - if (amt) 734 - mem_cgroup_sk_charge(newsk, amt, gfp); 735 - kmem_cache_charge(newsk, gfp); 736 - 737 - release_sock(newsk); 738 - } 739 - 740 715 if (req) 741 716 reqsk_put(req); 742 717