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