diff options
-rw-r--r-- | include/net/sock.h | 6 | ||||
-rw-r--r-- | mm/memcontrol.c | 19 | ||||
-rw-r--r-- | net/core/sock.c | 2 |
3 files changed, 22 insertions, 5 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index bb972d254dff..0ed65e3a0bea 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -1103,6 +1103,12 @@ sk_sockets_allocated_read_positive(struct sock *sk) | |||
1103 | return percpu_counter_sum_positive(prot->sockets_allocated); | 1103 | return percpu_counter_sum_positive(prot->sockets_allocated); |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | static inline void sk_update_clone(const struct sock *sk, struct sock *newsk) | ||
1107 | { | ||
1108 | if (mem_cgroup_sockets_enabled && sk->sk_cgrp) | ||
1109 | sock_update_memcg(newsk); | ||
1110 | } | ||
1111 | |||
1106 | static inline int | 1112 | static inline int |
1107 | proto_sockets_allocated_sum_positive(struct proto *prot) | 1113 | proto_sockets_allocated_sum_positive(struct proto *prot) |
1108 | { | 1114 | { |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 94da8ee9e2c2..9c72d5d5372a 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -381,16 +381,25 @@ static void mem_cgroup_put(struct mem_cgroup *memcg); | |||
381 | static bool mem_cgroup_is_root(struct mem_cgroup *memcg); | 381 | static bool mem_cgroup_is_root(struct mem_cgroup *memcg); |
382 | void sock_update_memcg(struct sock *sk) | 382 | void sock_update_memcg(struct sock *sk) |
383 | { | 383 | { |
384 | /* A socket spends its whole life in the same cgroup */ | ||
385 | if (sk->sk_cgrp) { | ||
386 | WARN_ON(1); | ||
387 | return; | ||
388 | } | ||
389 | if (static_branch(&memcg_socket_limit_enabled)) { | 384 | if (static_branch(&memcg_socket_limit_enabled)) { |
390 | struct mem_cgroup *memcg; | 385 | struct mem_cgroup *memcg; |
391 | 386 | ||
392 | BUG_ON(!sk->sk_prot->proto_cgroup); | 387 | BUG_ON(!sk->sk_prot->proto_cgroup); |
393 | 388 | ||
389 | /* Socket cloning can throw us here with sk_cgrp already | ||
390 | * filled. It won't however, necessarily happen from | ||
391 | * process context. So the test for root memcg given | ||
392 | * the current task's memcg won't help us in this case. | ||
393 | * | ||
394 | * Respecting the original socket's memcg is a better | ||
395 | * decision in this case. | ||
396 | */ | ||
397 | if (sk->sk_cgrp) { | ||
398 | BUG_ON(mem_cgroup_is_root(sk->sk_cgrp->memcg)); | ||
399 | mem_cgroup_get(sk->sk_cgrp->memcg); | ||
400 | return; | ||
401 | } | ||
402 | |||
394 | rcu_read_lock(); | 403 | rcu_read_lock(); |
395 | memcg = mem_cgroup_from_task(current); | 404 | memcg = mem_cgroup_from_task(current); |
396 | if (!mem_cgroup_is_root(memcg)) { | 405 | if (!mem_cgroup_is_root(memcg)) { |
diff --git a/net/core/sock.c b/net/core/sock.c index 002939cfc069..e80b64fbd663 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1362,6 +1362,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | |||
1362 | sk_set_socket(newsk, NULL); | 1362 | sk_set_socket(newsk, NULL); |
1363 | newsk->sk_wq = NULL; | 1363 | newsk->sk_wq = NULL; |
1364 | 1364 | ||
1365 | sk_update_clone(sk, newsk); | ||
1366 | |||
1365 | if (newsk->sk_prot->sockets_allocated) | 1367 | if (newsk->sk_prot->sockets_allocated) |
1366 | sk_sockets_allocated_inc(newsk); | 1368 | sk_sockets_allocated_inc(newsk); |
1367 | 1369 | ||