tcp_memcontrol.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include <net/tcp.h>
  2. #include <net/tcp_memcontrol.h>
  3. #include <net/sock.h>
  4. #include <net/ip.h>
  5. #include <linux/nsproxy.h>
  6. #include <linux/memcontrol.h>
  7. #include <linux/module.h>
  8. static struct cftype tcp_files[4]; /* XXX: will be removed soon */
  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. static void memcg_tcp_enter_memory_pressure(struct sock *sk)
  14. {
  15. if (sk->sk_cgrp->memory_pressure)
  16. *sk->sk_cgrp->memory_pressure = 1;
  17. }
  18. EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure);
  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. struct net *net = current->nsproxy->net_ns;
  32. cg_proto = tcp_prot.proto_cgroup(memcg);
  33. if (!cg_proto)
  34. goto create_files;
  35. tcp = tcp_from_cgproto(cg_proto);
  36. tcp->tcp_prot_mem[0] = net->ipv4.sysctl_tcp_mem[0];
  37. tcp->tcp_prot_mem[1] = net->ipv4.sysctl_tcp_mem[1];
  38. tcp->tcp_prot_mem[2] = net->ipv4.sysctl_tcp_mem[2];
  39. tcp->tcp_memory_pressure = 0;
  40. parent_cg = tcp_prot.proto_cgroup(parent);
  41. if (parent_cg)
  42. res_parent = parent_cg->memory_allocated;
  43. res_counter_init(&tcp->tcp_memory_allocated, res_parent);
  44. percpu_counter_init(&tcp->tcp_sockets_allocated, 0);
  45. cg_proto->enter_memory_pressure = memcg_tcp_enter_memory_pressure;
  46. cg_proto->memory_pressure = &tcp->tcp_memory_pressure;
  47. cg_proto->sysctl_mem = tcp->tcp_prot_mem;
  48. cg_proto->memory_allocated = &tcp->tcp_memory_allocated;
  49. cg_proto->sockets_allocated = &tcp->tcp_sockets_allocated;
  50. cg_proto->memcg = memcg;
  51. create_files:
  52. return cgroup_add_files(cgrp, ss, tcp_files,
  53. ARRAY_SIZE(tcp_files));
  54. }
  55. EXPORT_SYMBOL(tcp_init_cgroup);
  56. void tcp_destroy_cgroup(struct cgroup *cgrp)
  57. {
  58. struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
  59. struct cg_proto *cg_proto;
  60. struct tcp_memcontrol *tcp;
  61. u64 val;
  62. cg_proto = tcp_prot.proto_cgroup(memcg);
  63. if (!cg_proto)
  64. return;
  65. tcp = tcp_from_cgproto(cg_proto);
  66. percpu_counter_destroy(&tcp->tcp_sockets_allocated);
  67. val = res_counter_read_u64(&tcp->tcp_memory_allocated, RES_LIMIT);
  68. if (val != RESOURCE_MAX)
  69. static_key_slow_dec(&memcg_socket_limit_enabled);
  70. }
  71. EXPORT_SYMBOL(tcp_destroy_cgroup);
  72. static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
  73. {
  74. struct net *net = current->nsproxy->net_ns;
  75. struct tcp_memcontrol *tcp;
  76. struct cg_proto *cg_proto;
  77. u64 old_lim;
  78. int i;
  79. int ret;
  80. cg_proto = tcp_prot.proto_cgroup(memcg);
  81. if (!cg_proto)
  82. return -EINVAL;
  83. if (val > RESOURCE_MAX)
  84. val = RESOURCE_MAX;
  85. tcp = tcp_from_cgproto(cg_proto);
  86. old_lim = res_counter_read_u64(&tcp->tcp_memory_allocated, RES_LIMIT);
  87. ret = res_counter_set_limit(&tcp->tcp_memory_allocated, val);
  88. if (ret)
  89. return ret;
  90. for (i = 0; i < 3; i++)
  91. tcp->tcp_prot_mem[i] = min_t(long, val >> PAGE_SHIFT,
  92. net->ipv4.sysctl_tcp_mem[i]);
  93. if (val == RESOURCE_MAX && old_lim != RESOURCE_MAX)
  94. static_key_slow_dec(&memcg_socket_limit_enabled);
  95. else if (old_lim == RESOURCE_MAX && val != RESOURCE_MAX)
  96. static_key_slow_inc(&memcg_socket_limit_enabled);
  97. return 0;
  98. }
  99. static int tcp_cgroup_write(struct cgroup *cont, struct cftype *cft,
  100. const char *buffer)
  101. {
  102. struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
  103. unsigned long long val;
  104. int ret = 0;
  105. switch (cft->private) {
  106. case RES_LIMIT:
  107. /* see memcontrol.c */
  108. ret = res_counter_memparse_write_strategy(buffer, &val);
  109. if (ret)
  110. break;
  111. ret = tcp_update_limit(memcg, val);
  112. break;
  113. default:
  114. ret = -EINVAL;
  115. break;
  116. }
  117. return ret;
  118. }
  119. static u64 tcp_read_stat(struct mem_cgroup *memcg, int type, u64 default_val)
  120. {
  121. struct tcp_memcontrol *tcp;
  122. struct cg_proto *cg_proto;
  123. cg_proto = tcp_prot.proto_cgroup(memcg);
  124. if (!cg_proto)
  125. return default_val;
  126. tcp = tcp_from_cgproto(cg_proto);
  127. return res_counter_read_u64(&tcp->tcp_memory_allocated, type);
  128. }
  129. static u64 tcp_read_usage(struct mem_cgroup *memcg)
  130. {
  131. struct tcp_memcontrol *tcp;
  132. struct cg_proto *cg_proto;
  133. cg_proto = tcp_prot.proto_cgroup(memcg);
  134. if (!cg_proto)
  135. return atomic_long_read(&tcp_memory_allocated) << PAGE_SHIFT;
  136. tcp = tcp_from_cgproto(cg_proto);
  137. return res_counter_read_u64(&tcp->tcp_memory_allocated, RES_USAGE);
  138. }
  139. static u64 tcp_cgroup_read(struct cgroup *cont, struct cftype *cft)
  140. {
  141. struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
  142. u64 val;
  143. switch (cft->private) {
  144. case RES_LIMIT:
  145. val = tcp_read_stat(memcg, RES_LIMIT, RESOURCE_MAX);
  146. break;
  147. case RES_USAGE:
  148. val = tcp_read_usage(memcg);
  149. break;
  150. case RES_FAILCNT:
  151. case RES_MAX_USAGE:
  152. val = tcp_read_stat(memcg, cft->private, 0);
  153. break;
  154. default:
  155. BUG();
  156. }
  157. return val;
  158. }
  159. static int tcp_cgroup_reset(struct cgroup *cont, unsigned int event)
  160. {
  161. struct mem_cgroup *memcg;
  162. struct tcp_memcontrol *tcp;
  163. struct cg_proto *cg_proto;
  164. memcg = mem_cgroup_from_cont(cont);
  165. cg_proto = tcp_prot.proto_cgroup(memcg);
  166. if (!cg_proto)
  167. return 0;
  168. tcp = tcp_from_cgproto(cg_proto);
  169. switch (event) {
  170. case RES_MAX_USAGE:
  171. res_counter_reset_max(&tcp->tcp_memory_allocated);
  172. break;
  173. case RES_FAILCNT:
  174. res_counter_reset_failcnt(&tcp->tcp_memory_allocated);
  175. break;
  176. }
  177. return 0;
  178. }
  179. unsigned long long tcp_max_memory(const struct mem_cgroup *memcg)
  180. {
  181. struct tcp_memcontrol *tcp;
  182. struct cg_proto *cg_proto;
  183. cg_proto = tcp_prot.proto_cgroup((struct mem_cgroup *)memcg);
  184. if (!cg_proto)
  185. return 0;
  186. tcp = tcp_from_cgproto(cg_proto);
  187. return res_counter_read_u64(&tcp->tcp_memory_allocated, RES_LIMIT);
  188. }
  189. void tcp_prot_mem(struct mem_cgroup *memcg, long val, int idx)
  190. {
  191. struct tcp_memcontrol *tcp;
  192. struct cg_proto *cg_proto;
  193. cg_proto = tcp_prot.proto_cgroup(memcg);
  194. if (!cg_proto)
  195. return;
  196. tcp = tcp_from_cgproto(cg_proto);
  197. tcp->tcp_prot_mem[idx] = val;
  198. }
  199. static struct cftype tcp_files[] = {
  200. {
  201. .name = "kmem.tcp.limit_in_bytes",
  202. .write_string = tcp_cgroup_write,
  203. .read_u64 = tcp_cgroup_read,
  204. .private = RES_LIMIT,
  205. },
  206. {
  207. .name = "kmem.tcp.usage_in_bytes",
  208. .read_u64 = tcp_cgroup_read,
  209. .private = RES_USAGE,
  210. },
  211. {
  212. .name = "kmem.tcp.failcnt",
  213. .private = RES_FAILCNT,
  214. .trigger = tcp_cgroup_reset,
  215. .read_u64 = tcp_cgroup_read,
  216. },
  217. {
  218. .name = "kmem.tcp.max_usage_in_bytes",
  219. .private = RES_MAX_USAGE,
  220. .trigger = tcp_cgroup_reset,
  221. .read_u64 = tcp_cgroup_read,
  222. },
  223. };