diff options
Diffstat (limited to 'net/ipv4/tcp_memcontrol.c')
-rw-r--r-- | net/ipv4/tcp_memcontrol.c | 90 |
1 files changed, 18 insertions, 72 deletions
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c index 559d4ae6ebf4..03e9154f7e68 100644 --- a/net/ipv4/tcp_memcontrol.c +++ b/net/ipv4/tcp_memcontrol.c | |||
@@ -6,15 +6,10 @@ | |||
6 | #include <linux/memcontrol.h> | 6 | #include <linux/memcontrol.h> |
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | 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) | 9 | static void memcg_tcp_enter_memory_pressure(struct sock *sk) |
15 | { | 10 | { |
16 | if (sk->sk_cgrp->memory_pressure) | 11 | if (sk->sk_cgrp->memory_pressure) |
17 | *sk->sk_cgrp->memory_pressure = 1; | 12 | sk->sk_cgrp->memory_pressure = 1; |
18 | } | 13 | } |
19 | EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure); | 14 | EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure); |
20 | 15 | ||
@@ -27,34 +22,24 @@ int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss) | |||
27 | */ | 22 | */ |
28 | struct res_counter *res_parent = NULL; | 23 | struct res_counter *res_parent = NULL; |
29 | struct cg_proto *cg_proto, *parent_cg; | 24 | struct cg_proto *cg_proto, *parent_cg; |
30 | struct tcp_memcontrol *tcp; | ||
31 | struct mem_cgroup *parent = parent_mem_cgroup(memcg); | 25 | struct mem_cgroup *parent = parent_mem_cgroup(memcg); |
32 | struct net *net = current->nsproxy->net_ns; | ||
33 | 26 | ||
34 | cg_proto = tcp_prot.proto_cgroup(memcg); | 27 | cg_proto = tcp_prot.proto_cgroup(memcg); |
35 | if (!cg_proto) | 28 | if (!cg_proto) |
36 | return 0; | 29 | return 0; |
37 | 30 | ||
38 | tcp = tcp_from_cgproto(cg_proto); | 31 | cg_proto->sysctl_mem[0] = sysctl_tcp_mem[0]; |
39 | 32 | cg_proto->sysctl_mem[1] = sysctl_tcp_mem[1]; | |
40 | tcp->tcp_prot_mem[0] = net->ipv4.sysctl_tcp_mem[0]; | 33 | cg_proto->sysctl_mem[2] = sysctl_tcp_mem[2]; |
41 | tcp->tcp_prot_mem[1] = net->ipv4.sysctl_tcp_mem[1]; | 34 | cg_proto->memory_pressure = 0; |
42 | tcp->tcp_prot_mem[2] = net->ipv4.sysctl_tcp_mem[2]; | 35 | cg_proto->memcg = memcg; |
43 | tcp->tcp_memory_pressure = 0; | ||
44 | 36 | ||
45 | parent_cg = tcp_prot.proto_cgroup(parent); | 37 | parent_cg = tcp_prot.proto_cgroup(parent); |
46 | if (parent_cg) | 38 | if (parent_cg) |
47 | res_parent = parent_cg->memory_allocated; | 39 | res_parent = &parent_cg->memory_allocated; |
48 | |||
49 | res_counter_init(&tcp->tcp_memory_allocated, res_parent); | ||
50 | percpu_counter_init(&tcp->tcp_sockets_allocated, 0); | ||
51 | 40 | ||
52 | cg_proto->enter_memory_pressure = memcg_tcp_enter_memory_pressure; | 41 | res_counter_init(&cg_proto->memory_allocated, res_parent); |
53 | cg_proto->memory_pressure = &tcp->tcp_memory_pressure; | 42 | percpu_counter_init(&cg_proto->sockets_allocated, 0); |
54 | cg_proto->sysctl_mem = tcp->tcp_prot_mem; | ||
55 | cg_proto->memory_allocated = &tcp->tcp_memory_allocated; | ||
56 | cg_proto->sockets_allocated = &tcp->tcp_sockets_allocated; | ||
57 | cg_proto->memcg = memcg; | ||
58 | 43 | ||
59 | return 0; | 44 | return 0; |
60 | } | 45 | } |
@@ -63,21 +48,17 @@ EXPORT_SYMBOL(tcp_init_cgroup); | |||
63 | void tcp_destroy_cgroup(struct mem_cgroup *memcg) | 48 | void tcp_destroy_cgroup(struct mem_cgroup *memcg) |
64 | { | 49 | { |
65 | struct cg_proto *cg_proto; | 50 | struct cg_proto *cg_proto; |
66 | struct tcp_memcontrol *tcp; | ||
67 | 51 | ||
68 | cg_proto = tcp_prot.proto_cgroup(memcg); | 52 | cg_proto = tcp_prot.proto_cgroup(memcg); |
69 | if (!cg_proto) | 53 | if (!cg_proto) |
70 | return; | 54 | return; |
71 | 55 | ||
72 | tcp = tcp_from_cgproto(cg_proto); | 56 | percpu_counter_destroy(&cg_proto->sockets_allocated); |
73 | percpu_counter_destroy(&tcp->tcp_sockets_allocated); | ||
74 | } | 57 | } |
75 | EXPORT_SYMBOL(tcp_destroy_cgroup); | 58 | EXPORT_SYMBOL(tcp_destroy_cgroup); |
76 | 59 | ||
77 | static int tcp_update_limit(struct mem_cgroup *memcg, u64 val) | 60 | static int tcp_update_limit(struct mem_cgroup *memcg, u64 val) |
78 | { | 61 | { |
79 | struct net *net = current->nsproxy->net_ns; | ||
80 | struct tcp_memcontrol *tcp; | ||
81 | struct cg_proto *cg_proto; | 62 | struct cg_proto *cg_proto; |
82 | u64 old_lim; | 63 | u64 old_lim; |
83 | int i; | 64 | int i; |
@@ -90,16 +71,14 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val) | |||
90 | if (val > RES_COUNTER_MAX) | 71 | if (val > RES_COUNTER_MAX) |
91 | val = RES_COUNTER_MAX; | 72 | val = RES_COUNTER_MAX; |
92 | 73 | ||
93 | tcp = tcp_from_cgproto(cg_proto); | 74 | old_lim = res_counter_read_u64(&cg_proto->memory_allocated, RES_LIMIT); |
94 | 75 | ret = res_counter_set_limit(&cg_proto->memory_allocated, val); | |
95 | old_lim = res_counter_read_u64(&tcp->tcp_memory_allocated, RES_LIMIT); | ||
96 | ret = res_counter_set_limit(&tcp->tcp_memory_allocated, val); | ||
97 | if (ret) | 76 | if (ret) |
98 | return ret; | 77 | return ret; |
99 | 78 | ||
100 | for (i = 0; i < 3; i++) | 79 | for (i = 0; i < 3; i++) |
101 | tcp->tcp_prot_mem[i] = min_t(long, val >> PAGE_SHIFT, | 80 | cg_proto->sysctl_mem[i] = min_t(long, val >> PAGE_SHIFT, |
102 | net->ipv4.sysctl_tcp_mem[i]); | 81 | sysctl_tcp_mem[i]); |
103 | 82 | ||
104 | if (val == RES_COUNTER_MAX) | 83 | if (val == RES_COUNTER_MAX) |
105 | clear_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags); | 84 | clear_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags); |
@@ -156,28 +135,24 @@ static int tcp_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft, | |||
156 | 135 | ||
157 | static u64 tcp_read_stat(struct mem_cgroup *memcg, int type, u64 default_val) | 136 | static u64 tcp_read_stat(struct mem_cgroup *memcg, int type, u64 default_val) |
158 | { | 137 | { |
159 | struct tcp_memcontrol *tcp; | ||
160 | struct cg_proto *cg_proto; | 138 | struct cg_proto *cg_proto; |
161 | 139 | ||
162 | cg_proto = tcp_prot.proto_cgroup(memcg); | 140 | cg_proto = tcp_prot.proto_cgroup(memcg); |
163 | if (!cg_proto) | 141 | if (!cg_proto) |
164 | return default_val; | 142 | return default_val; |
165 | 143 | ||
166 | tcp = tcp_from_cgproto(cg_proto); | 144 | return res_counter_read_u64(&cg_proto->memory_allocated, type); |
167 | return res_counter_read_u64(&tcp->tcp_memory_allocated, type); | ||
168 | } | 145 | } |
169 | 146 | ||
170 | static u64 tcp_read_usage(struct mem_cgroup *memcg) | 147 | static u64 tcp_read_usage(struct mem_cgroup *memcg) |
171 | { | 148 | { |
172 | struct tcp_memcontrol *tcp; | ||
173 | struct cg_proto *cg_proto; | 149 | struct cg_proto *cg_proto; |
174 | 150 | ||
175 | cg_proto = tcp_prot.proto_cgroup(memcg); | 151 | cg_proto = tcp_prot.proto_cgroup(memcg); |
176 | if (!cg_proto) | 152 | if (!cg_proto) |
177 | return atomic_long_read(&tcp_memory_allocated) << PAGE_SHIFT; | 153 | return atomic_long_read(&tcp_memory_allocated) << PAGE_SHIFT; |
178 | 154 | ||
179 | tcp = tcp_from_cgproto(cg_proto); | 155 | return res_counter_read_u64(&cg_proto->memory_allocated, RES_USAGE); |
180 | return res_counter_read_u64(&tcp->tcp_memory_allocated, RES_USAGE); | ||
181 | } | 156 | } |
182 | 157 | ||
183 | static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft) | 158 | static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft) |
@@ -205,54 +180,25 @@ static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft) | |||
205 | static int tcp_cgroup_reset(struct cgroup_subsys_state *css, unsigned int event) | 180 | static int tcp_cgroup_reset(struct cgroup_subsys_state *css, unsigned int event) |
206 | { | 181 | { |
207 | struct mem_cgroup *memcg; | 182 | struct mem_cgroup *memcg; |
208 | struct tcp_memcontrol *tcp; | ||
209 | struct cg_proto *cg_proto; | 183 | struct cg_proto *cg_proto; |
210 | 184 | ||
211 | memcg = mem_cgroup_from_css(css); | 185 | memcg = mem_cgroup_from_css(css); |
212 | cg_proto = tcp_prot.proto_cgroup(memcg); | 186 | cg_proto = tcp_prot.proto_cgroup(memcg); |
213 | if (!cg_proto) | 187 | if (!cg_proto) |
214 | return 0; | 188 | return 0; |
215 | tcp = tcp_from_cgproto(cg_proto); | ||
216 | 189 | ||
217 | switch (event) { | 190 | switch (event) { |
218 | case RES_MAX_USAGE: | 191 | case RES_MAX_USAGE: |
219 | res_counter_reset_max(&tcp->tcp_memory_allocated); | 192 | res_counter_reset_max(&cg_proto->memory_allocated); |
220 | break; | 193 | break; |
221 | case RES_FAILCNT: | 194 | case RES_FAILCNT: |
222 | res_counter_reset_failcnt(&tcp->tcp_memory_allocated); | 195 | res_counter_reset_failcnt(&cg_proto->memory_allocated); |
223 | break; | 196 | break; |
224 | } | 197 | } |
225 | 198 | ||
226 | return 0; | 199 | return 0; |
227 | } | 200 | } |
228 | 201 | ||
229 | unsigned long long tcp_max_memory(const struct mem_cgroup *memcg) | ||
230 | { | ||
231 | struct tcp_memcontrol *tcp; | ||
232 | struct cg_proto *cg_proto; | ||
233 | |||
234 | cg_proto = tcp_prot.proto_cgroup((struct mem_cgroup *)memcg); | ||
235 | if (!cg_proto) | ||
236 | return 0; | ||
237 | |||
238 | tcp = tcp_from_cgproto(cg_proto); | ||
239 | return res_counter_read_u64(&tcp->tcp_memory_allocated, RES_LIMIT); | ||
240 | } | ||
241 | |||
242 | void tcp_prot_mem(struct mem_cgroup *memcg, long val, int idx) | ||
243 | { | ||
244 | struct tcp_memcontrol *tcp; | ||
245 | struct cg_proto *cg_proto; | ||
246 | |||
247 | cg_proto = tcp_prot.proto_cgroup(memcg); | ||
248 | if (!cg_proto) | ||
249 | return; | ||
250 | |||
251 | tcp = tcp_from_cgproto(cg_proto); | ||
252 | |||
253 | tcp->tcp_prot_mem[idx] = val; | ||
254 | } | ||
255 | |||
256 | static struct cftype tcp_files[] = { | 202 | static struct cftype tcp_files[] = { |
257 | { | 203 | { |
258 | .name = "kmem.tcp.limit_in_bytes", | 204 | .name = "kmem.tcp.limit_in_bytes", |