2 #include <net/tcp_memcontrol.h>
5 #include <linux/nsproxy.h>
6 #include <linux/memcontrol.h>
7 #include <linux/module.h>
9 static u64
tcp_cgroup_read(struct cgroup
*cont
, struct cftype
*cft
);
10 static int tcp_cgroup_write(struct cgroup
*cont
, struct cftype
*cft
,
12 static int tcp_cgroup_reset(struct cgroup
*cont
, unsigned int event
);
14 static struct cftype tcp_files
[] = {
16 .name
= "kmem.tcp.limit_in_bytes",
17 .write_string
= tcp_cgroup_write
,
18 .read_u64
= tcp_cgroup_read
,
22 .name
= "kmem.tcp.usage_in_bytes",
23 .read_u64
= tcp_cgroup_read
,
27 .name
= "kmem.tcp.failcnt",
28 .private = RES_FAILCNT
,
29 .trigger
= tcp_cgroup_reset
,
30 .read_u64
= tcp_cgroup_read
,
33 .name
= "kmem.tcp.max_usage_in_bytes",
34 .private = RES_MAX_USAGE
,
35 .trigger
= tcp_cgroup_reset
,
36 .read_u64
= tcp_cgroup_read
,
40 static inline struct tcp_memcontrol
*tcp_from_cgproto(struct cg_proto
*cg_proto
)
42 return container_of(cg_proto
, struct tcp_memcontrol
, cg_proto
);
45 static void memcg_tcp_enter_memory_pressure(struct sock
*sk
)
47 if (sk
->sk_cgrp
->memory_pressure
)
48 *sk
->sk_cgrp
->memory_pressure
= 1;
50 EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure
);
52 int tcp_init_cgroup(struct cgroup
*cgrp
, struct cgroup_subsys
*ss
)
55 * The root cgroup does not use res_counters, but rather,
56 * rely on the data already collected by the network
59 struct res_counter
*res_parent
= NULL
;
60 struct cg_proto
*cg_proto
, *parent_cg
;
61 struct tcp_memcontrol
*tcp
;
62 struct mem_cgroup
*memcg
= mem_cgroup_from_cont(cgrp
);
63 struct mem_cgroup
*parent
= parent_mem_cgroup(memcg
);
64 struct net
*net
= current
->nsproxy
->net_ns
;
66 cg_proto
= tcp_prot
.proto_cgroup(memcg
);
70 tcp
= tcp_from_cgproto(cg_proto
);
72 tcp
->tcp_prot_mem
[0] = net
->ipv4
.sysctl_tcp_mem
[0];
73 tcp
->tcp_prot_mem
[1] = net
->ipv4
.sysctl_tcp_mem
[1];
74 tcp
->tcp_prot_mem
[2] = net
->ipv4
.sysctl_tcp_mem
[2];
75 tcp
->tcp_memory_pressure
= 0;
77 parent_cg
= tcp_prot
.proto_cgroup(parent
);
79 res_parent
= parent_cg
->memory_allocated
;
81 res_counter_init(&tcp
->tcp_memory_allocated
, res_parent
);
82 percpu_counter_init(&tcp
->tcp_sockets_allocated
, 0);
84 cg_proto
->enter_memory_pressure
= memcg_tcp_enter_memory_pressure
;
85 cg_proto
->memory_pressure
= &tcp
->tcp_memory_pressure
;
86 cg_proto
->sysctl_mem
= tcp
->tcp_prot_mem
;
87 cg_proto
->memory_allocated
= &tcp
->tcp_memory_allocated
;
88 cg_proto
->sockets_allocated
= &tcp
->tcp_sockets_allocated
;
89 cg_proto
->memcg
= memcg
;
92 return cgroup_add_files(cgrp
, ss
, tcp_files
,
93 ARRAY_SIZE(tcp_files
));
95 EXPORT_SYMBOL(tcp_init_cgroup
);
97 void tcp_destroy_cgroup(struct cgroup
*cgrp
)
99 struct mem_cgroup
*memcg
= mem_cgroup_from_cont(cgrp
);
100 struct cg_proto
*cg_proto
;
101 struct tcp_memcontrol
*tcp
;
104 cg_proto
= tcp_prot
.proto_cgroup(memcg
);
108 tcp
= tcp_from_cgproto(cg_proto
);
109 percpu_counter_destroy(&tcp
->tcp_sockets_allocated
);
111 val
= res_counter_read_u64(&tcp
->tcp_memory_allocated
, RES_LIMIT
);
113 if (val
!= RESOURCE_MAX
)
114 static_key_slow_dec(&memcg_socket_limit_enabled
);
116 EXPORT_SYMBOL(tcp_destroy_cgroup
);
118 static int tcp_update_limit(struct mem_cgroup
*memcg
, u64 val
)
120 struct net
*net
= current
->nsproxy
->net_ns
;
121 struct tcp_memcontrol
*tcp
;
122 struct cg_proto
*cg_proto
;
127 cg_proto
= tcp_prot
.proto_cgroup(memcg
);
131 if (val
> RESOURCE_MAX
)
134 tcp
= tcp_from_cgproto(cg_proto
);
136 old_lim
= res_counter_read_u64(&tcp
->tcp_memory_allocated
, RES_LIMIT
);
137 ret
= res_counter_set_limit(&tcp
->tcp_memory_allocated
, val
);
141 for (i
= 0; i
< 3; i
++)
142 tcp
->tcp_prot_mem
[i
] = min_t(long, val
>> PAGE_SHIFT
,
143 net
->ipv4
.sysctl_tcp_mem
[i
]);
145 if (val
== RESOURCE_MAX
&& old_lim
!= RESOURCE_MAX
)
146 static_key_slow_dec(&memcg_socket_limit_enabled
);
147 else if (old_lim
== RESOURCE_MAX
&& val
!= RESOURCE_MAX
)
148 static_key_slow_inc(&memcg_socket_limit_enabled
);
153 static int tcp_cgroup_write(struct cgroup
*cont
, struct cftype
*cft
,
156 struct mem_cgroup
*memcg
= mem_cgroup_from_cont(cont
);
157 unsigned long long val
;
160 switch (cft
->private) {
162 /* see memcontrol.c */
163 ret
= res_counter_memparse_write_strategy(buffer
, &val
);
166 ret
= tcp_update_limit(memcg
, val
);
175 static u64
tcp_read_stat(struct mem_cgroup
*memcg
, int type
, u64 default_val
)
177 struct tcp_memcontrol
*tcp
;
178 struct cg_proto
*cg_proto
;
180 cg_proto
= tcp_prot
.proto_cgroup(memcg
);
184 tcp
= tcp_from_cgproto(cg_proto
);
185 return res_counter_read_u64(&tcp
->tcp_memory_allocated
, type
);
188 static u64
tcp_read_usage(struct mem_cgroup
*memcg
)
190 struct tcp_memcontrol
*tcp
;
191 struct cg_proto
*cg_proto
;
193 cg_proto
= tcp_prot
.proto_cgroup(memcg
);
195 return atomic_long_read(&tcp_memory_allocated
) << PAGE_SHIFT
;
197 tcp
= tcp_from_cgproto(cg_proto
);
198 return res_counter_read_u64(&tcp
->tcp_memory_allocated
, RES_USAGE
);
201 static u64
tcp_cgroup_read(struct cgroup
*cont
, struct cftype
*cft
)
203 struct mem_cgroup
*memcg
= mem_cgroup_from_cont(cont
);
206 switch (cft
->private) {
208 val
= tcp_read_stat(memcg
, RES_LIMIT
, RESOURCE_MAX
);
211 val
= tcp_read_usage(memcg
);
215 val
= tcp_read_stat(memcg
, cft
->private, 0);
223 static int tcp_cgroup_reset(struct cgroup
*cont
, unsigned int event
)
225 struct mem_cgroup
*memcg
;
226 struct tcp_memcontrol
*tcp
;
227 struct cg_proto
*cg_proto
;
229 memcg
= mem_cgroup_from_cont(cont
);
230 cg_proto
= tcp_prot
.proto_cgroup(memcg
);
233 tcp
= tcp_from_cgproto(cg_proto
);
237 res_counter_reset_max(&tcp
->tcp_memory_allocated
);
240 res_counter_reset_failcnt(&tcp
->tcp_memory_allocated
);
247 unsigned long long tcp_max_memory(const struct mem_cgroup
*memcg
)
249 struct tcp_memcontrol
*tcp
;
250 struct cg_proto
*cg_proto
;
252 cg_proto
= tcp_prot
.proto_cgroup((struct mem_cgroup
*)memcg
);
256 tcp
= tcp_from_cgproto(cg_proto
);
257 return res_counter_read_u64(&tcp
->tcp_memory_allocated
, RES_LIMIT
);
260 void tcp_prot_mem(struct mem_cgroup
*memcg
, long val
, int idx
)
262 struct tcp_memcontrol
*tcp
;
263 struct cg_proto
*cg_proto
;
265 cg_proto
= tcp_prot
.proto_cgroup(memcg
);
269 tcp
= tcp_from_cgproto(cg_proto
);
271 tcp
->tcp_prot_mem
[idx
] = val
;