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(). This makes easier to add a BPF hook that covers sk_prot.memory_allocated users (TCP, MPTCP, SCTP) in a single place. Two notes: 1) SCTP somehow allocates a new socket by sk_alloc() in sk->sk_prot->accept() and clones fields manually, instead of using sk_clone_lock(). For SCTP, mem_cgroup_sk_alloc() has been called before __inet_accept(), so I added the protocol tests in __inet_accept(), but this can be removed once SCTP uses sk_clone_lock(). 2) The single if block is separated into two because we will add a new bpf hook between the blocks, where a bpf prog can add a flag in sk->sk_memcg. Signed-off-by: Kuniyuki Iwashima <kuniyu@xxxxxxxxxx> --- net/ipv4/af_inet.c | 22 ++++++++++++++++++++++ net/ipv4/inet_connection_sock.c | 25 ------------------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 76e38092cd8a..ae83ecda3983 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -753,6 +753,28 @@ EXPORT_SYMBOL(inet_stream_connect); void __inet_accept(struct socket *sock, struct socket *newsock, struct sock *newsk) { + gfp_t gfp = GFP_KERNEL | __GFP_NOFAIL; + + /* TODO: use sk_clone_lock() in SCTP and remove protocol checks */ + if (mem_cgroup_sockets_enabled && + (!IS_ENABLED(CONFIG_IP_SCTP) || + sk_is_tcp(newsk) || sk_is_mptcp(newsk))) { + mem_cgroup_sk_alloc(newsk); + kmem_cache_charge(newsk, gfp); + } + + if (mem_cgroup_sk_enabled(newsk)) { + int amt; + + /* The socket has not been accepted yet, no need + * to look at newsk->sk_wmem_queued. + */ + amt = sk_mem_pages(newsk->sk_forward_alloc + + atomic_read(&newsk->sk_rmem_alloc)); + if (amt) + mem_cgroup_sk_charge(newsk, amt, gfp); + } + sock_rps_record_flow(newsk); WARN_ON(!((1 << newsk->sk_state) & (TCPF_ESTABLISHED | TCPF_SYN_RECV | diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 0ef1eacd539d..ed10b959a906 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -708,31 +708,6 @@ struct sock *inet_csk_accept(struct sock *sk, struct proto_accept_arg *arg) release_sock(sk); - if (mem_cgroup_sockets_enabled) { - gfp_t gfp = GFP_KERNEL | __GFP_NOFAIL; - int amt = 0; - - /* atomically get the memory usage, set and charge the - * newsk->sk_memcg. - */ - lock_sock(newsk); - - mem_cgroup_sk_alloc(newsk); - if (mem_cgroup_from_sk(newsk)) { - /* The socket has not been accepted yet, no need - * to look at newsk->sk_wmem_queued. - */ - amt = sk_mem_pages(newsk->sk_forward_alloc + - atomic_read(&newsk->sk_rmem_alloc)); - } - - if (amt) - mem_cgroup_sk_charge(newsk, amt, gfp); - kmem_cache_charge(newsk, gfp); - - release_sock(newsk); - } - if (req) reqsk_put(req); -- 2.51.0.261.g7ce5a0a67e-goog