Skip to content

Commit d752a49

Browse files
shakeelbdavem330
authored andcommitted
net: memcg: late association of sock to memcg
If a TCP socket is allocated in IRQ context or cloned from unassociated (i.e. not associated to a memcg) in IRQ context then it will remain unassociated for its whole life. Almost half of the TCPs created on the system are created in IRQ context, so, memory used by such sockets will not be accounted by the memcg. This issue is more widespread in cgroup v1 where network memory accounting is opt-in but it can happen in cgroup v2 if the source socket for the cloning was created in root memcg. To fix the issue, just do the association of the sockets at the accept() time in the process context and then force charge the memory buffer already used and reserved by the socket. Signed-off-by: Shakeel Butt <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e876ecc commit d752a49

File tree

3 files changed

+24
-15
lines changed

3 files changed

+24
-15
lines changed

mm/memcontrol.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6682,20 +6682,6 @@ void mem_cgroup_sk_alloc(struct sock *sk)
66826682
if (!mem_cgroup_sockets_enabled)
66836683
return;
66846684

6685-
/*
6686-
* Socket cloning can throw us here with sk_memcg already
6687-
* filled. It won't however, necessarily happen from
6688-
* process context. So the test for root memcg given
6689-
* the current task's memcg won't help us in this case.
6690-
*
6691-
* Respecting the original socket's memcg is a better
6692-
* decision in this case.
6693-
*/
6694-
if (sk->sk_memcg) {
6695-
css_get(&sk->sk_memcg->css);
6696-
return;
6697-
}
6698-
66996685
/* Do not associate the sock with unrelated interrupted task's memcg. */
67006686
if (in_interrupt())
67016687
return;

net/core/sock.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1830,7 +1830,10 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
18301830
atomic_set(&newsk->sk_zckey, 0);
18311831

18321832
sock_reset_flag(newsk, SOCK_DONE);
1833-
mem_cgroup_sk_alloc(newsk);
1833+
1834+
/* sk->sk_memcg will be populated at accept() time */
1835+
newsk->sk_memcg = NULL;
1836+
18341837
cgroup_sk_alloc(&newsk->sk_cgrp_data);
18351838

18361839
rcu_read_lock();

net/ipv4/inet_connection_sock.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,26 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern)
482482
}
483483
spin_unlock_bh(&queue->fastopenq.lock);
484484
}
485+
486+
if (mem_cgroup_sockets_enabled) {
487+
int amt;
488+
489+
/* atomically get the memory usage, set and charge the
490+
* sk->sk_memcg.
491+
*/
492+
lock_sock(newsk);
493+
494+
/* The sk has not been accepted yet, no need to look at
495+
* sk->sk_wmem_queued.
496+
*/
497+
amt = sk_mem_pages(newsk->sk_forward_alloc +
498+
atomic_read(&sk->sk_rmem_alloc));
499+
mem_cgroup_sk_alloc(newsk);
500+
if (newsk->sk_memcg && amt)
501+
mem_cgroup_charge_skmem(newsk->sk_memcg, amt);
502+
503+
release_sock(newsk);
504+
}
485505
out:
486506
release_sock(sk);
487507
if (req)

0 commit comments

Comments
 (0)