Glauber Costa | d1a4c0b | 2011-12-11 21:47:04 +0000 | [diff] [blame] | 1 | #include <net/tcp.h> |
| 2 | #include <net/tcp_memcontrol.h> |
| 3 | #include <net/sock.h> |
Glauber Costa | 3dc43e3 | 2011-12-11 21:47:05 +0000 | [diff] [blame^] | 4 | #include <net/ip.h> |
| 5 | #include <linux/nsproxy.h> |
Glauber Costa | d1a4c0b | 2011-12-11 21:47:04 +0000 | [diff] [blame] | 6 | #include <linux/memcontrol.h> |
| 7 | #include <linux/module.h> |
| 8 | |
| 9 | static inline struct tcp_memcontrol *tcp_from_cgproto(struct cg_proto *cg_proto) |
| 10 | { |
| 11 | return container_of(cg_proto, struct tcp_memcontrol, cg_proto); |
| 12 | } |
| 13 | |
| 14 | static void memcg_tcp_enter_memory_pressure(struct sock *sk) |
| 15 | { |
| 16 | if (!sk->sk_cgrp->memory_pressure) |
| 17 | *sk->sk_cgrp->memory_pressure = 1; |
| 18 | } |
| 19 | EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure); |
| 20 | |
| 21 | int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss) |
| 22 | { |
| 23 | /* |
| 24 | * The root cgroup does not use res_counters, but rather, |
| 25 | * rely on the data already collected by the network |
| 26 | * subsystem |
| 27 | */ |
| 28 | struct res_counter *res_parent = NULL; |
| 29 | struct cg_proto *cg_proto, *parent_cg; |
| 30 | struct tcp_memcontrol *tcp; |
| 31 | struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); |
| 32 | struct mem_cgroup *parent = parent_mem_cgroup(memcg); |
Glauber Costa | 3dc43e3 | 2011-12-11 21:47:05 +0000 | [diff] [blame^] | 33 | struct net *net = current->nsproxy->net_ns; |
Glauber Costa | d1a4c0b | 2011-12-11 21:47:04 +0000 | [diff] [blame] | 34 | |
| 35 | cg_proto = tcp_prot.proto_cgroup(memcg); |
| 36 | if (!cg_proto) |
| 37 | return 0; |
| 38 | |
| 39 | tcp = tcp_from_cgproto(cg_proto); |
| 40 | |
Glauber Costa | 3dc43e3 | 2011-12-11 21:47:05 +0000 | [diff] [blame^] | 41 | tcp->tcp_prot_mem[0] = net->ipv4.sysctl_tcp_mem[0]; |
| 42 | tcp->tcp_prot_mem[1] = net->ipv4.sysctl_tcp_mem[1]; |
| 43 | tcp->tcp_prot_mem[2] = net->ipv4.sysctl_tcp_mem[2]; |
Glauber Costa | d1a4c0b | 2011-12-11 21:47:04 +0000 | [diff] [blame] | 44 | tcp->tcp_memory_pressure = 0; |
| 45 | |
| 46 | parent_cg = tcp_prot.proto_cgroup(parent); |
| 47 | if (parent_cg) |
| 48 | res_parent = parent_cg->memory_allocated; |
| 49 | |
| 50 | res_counter_init(&tcp->tcp_memory_allocated, res_parent); |
| 51 | percpu_counter_init(&tcp->tcp_sockets_allocated, 0); |
| 52 | |
| 53 | cg_proto->enter_memory_pressure = memcg_tcp_enter_memory_pressure; |
| 54 | cg_proto->memory_pressure = &tcp->tcp_memory_pressure; |
| 55 | cg_proto->sysctl_mem = tcp->tcp_prot_mem; |
| 56 | cg_proto->memory_allocated = &tcp->tcp_memory_allocated; |
| 57 | cg_proto->sockets_allocated = &tcp->tcp_sockets_allocated; |
| 58 | cg_proto->memcg = memcg; |
| 59 | |
| 60 | return 0; |
| 61 | } |
| 62 | EXPORT_SYMBOL(tcp_init_cgroup); |
| 63 | |
| 64 | void tcp_destroy_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss) |
| 65 | { |
| 66 | struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); |
| 67 | struct cg_proto *cg_proto; |
| 68 | struct tcp_memcontrol *tcp; |
| 69 | |
| 70 | cg_proto = tcp_prot.proto_cgroup(memcg); |
| 71 | if (!cg_proto) |
| 72 | return; |
| 73 | |
| 74 | tcp = tcp_from_cgproto(cg_proto); |
| 75 | percpu_counter_destroy(&tcp->tcp_sockets_allocated); |
| 76 | } |
| 77 | EXPORT_SYMBOL(tcp_destroy_cgroup); |