aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Davydov <vdavydov@virtuozzo.com>2016-01-20 18:02:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-20 20:09:18 -0500
commitd55f90bfab40e3b5db323711d28186ff09461692 (patch)
treeea3a5bea8619a39564fe13d343b919543a17e19f
parent489c2a20a414351fe0813a727c34600c0f7292ae (diff)
net: drop tcp_memcontrol.c
tcp_memcontrol.c only contains legacy memory.tcp.kmem.* file definitions and mem_cgroup->tcp_mem init/destroy stuff. This doesn't belong to network subsys. Let's move it to memcontrol.c. This also allows us to reuse generic code for handling legacy memcg files. Signed-off-by: Vladimir Davydov <vdavydov@virtuozzo.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Cc: "David S. Miller" <davem@davemloft.net> Acked-by: Michal Hocko <mhocko@suse.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/net/tcp_memcontrol.h10
-rw-r--r--mm/memcontrol.c98
-rw-r--r--net/ipv4/Makefile1
-rw-r--r--net/ipv4/sysctl_net_ipv4.c1
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv4/tcp_memcontrol.c200
-rw-r--r--net/ipv6/tcp_ipv6.c1
7 files changed, 90 insertions, 222 deletions
diff --git a/include/net/tcp_memcontrol.h b/include/net/tcp_memcontrol.h
deleted file mode 100644
index 020c2dee65e8..000000000000
--- a/include/net/tcp_memcontrol.h
+++ /dev/null
@@ -1,10 +0,0 @@
1#ifndef _TCP_MEMCG_H
2#define _TCP_MEMCG_H
3
4struct cgroup_subsys;
5struct mem_cgroup;
6
7int tcp_init_cgroup(struct mem_cgroup *memcg);
8void tcp_destroy_cgroup(struct mem_cgroup *memcg);
9
10#endif /* _TCP_MEMCG_H */
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 92e8ab67b6df..15896708429b 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -66,7 +66,6 @@
66#include "internal.h" 66#include "internal.h"
67#include <net/sock.h> 67#include <net/sock.h>
68#include <net/ip.h> 68#include <net/ip.h>
69#include <net/tcp_memcontrol.h>
70#include "slab.h" 69#include "slab.h"
71 70
72#include <asm/uaccess.h> 71#include <asm/uaccess.h>
@@ -242,6 +241,7 @@ enum res_type {
242 _MEMSWAP, 241 _MEMSWAP,
243 _OOM_TYPE, 242 _OOM_TYPE,
244 _KMEM, 243 _KMEM,
244 _TCP,
245}; 245};
246 246
247#define MEMFILE_PRIVATE(x, val) ((x) << 16 | (val)) 247#define MEMFILE_PRIVATE(x, val) ((x) << 16 | (val))
@@ -2842,6 +2842,11 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
2842 case _KMEM: 2842 case _KMEM:
2843 counter = &memcg->kmem; 2843 counter = &memcg->kmem;
2844 break; 2844 break;
2845#if defined(CONFIG_MEMCG_LEGACY_KMEM) && defined(CONFIG_INET)
2846 case _TCP:
2847 counter = &memcg->tcp_mem.memory_allocated;
2848 break;
2849#endif
2845 default: 2850 default:
2846 BUG(); 2851 BUG();
2847 } 2852 }
@@ -3028,6 +3033,48 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg,
3028#endif /* CONFIG_MEMCG_LEGACY_KMEM */ 3033#endif /* CONFIG_MEMCG_LEGACY_KMEM */
3029 3034
3030 3035
3036#if defined(CONFIG_MEMCG_LEGACY_KMEM) && defined(CONFIG_INET)
3037static int memcg_update_tcp_limit(struct mem_cgroup *memcg, unsigned long limit)
3038{
3039 int ret;
3040
3041 mutex_lock(&memcg_limit_mutex);
3042
3043 ret = page_counter_limit(&memcg->tcp_mem.memory_allocated, limit);
3044 if (ret)
3045 goto out;
3046
3047 if (!memcg->tcp_mem.active) {
3048 /*
3049 * The active flag needs to be written after the static_key
3050 * update. This is what guarantees that the socket activation
3051 * function is the last one to run. See sock_update_memcg() for
3052 * details, and note that we don't mark any socket as belonging
3053 * to this memcg until that flag is up.
3054 *
3055 * We need to do this, because static_keys will span multiple
3056 * sites, but we can't control their order. If we mark a socket
3057 * as accounted, but the accounting functions are not patched in
3058 * yet, we'll lose accounting.
3059 *
3060 * We never race with the readers in sock_update_memcg(),
3061 * because when this value change, the code to process it is not
3062 * patched in yet.
3063 */
3064 static_branch_inc(&memcg_sockets_enabled_key);
3065 memcg->tcp_mem.active = true;
3066 }
3067out:
3068 mutex_unlock(&memcg_limit_mutex);
3069 return ret;
3070}
3071#else
3072static int memcg_update_tcp_limit(struct mem_cgroup *memcg, unsigned long limit)
3073{
3074 return -EINVAL;
3075}
3076#endif /* CONFIG_MEMCG_LEGACY_KMEM && CONFIG_INET */
3077
3031/* 3078/*
3032 * The user of this function is... 3079 * The user of this function is...
3033 * RES_LIMIT. 3080 * RES_LIMIT.
@@ -3060,6 +3107,9 @@ static ssize_t mem_cgroup_write(struct kernfs_open_file *of,
3060 case _KMEM: 3107 case _KMEM:
3061 ret = memcg_update_kmem_limit(memcg, nr_pages); 3108 ret = memcg_update_kmem_limit(memcg, nr_pages);
3062 break; 3109 break;
3110 case _TCP:
3111 ret = memcg_update_tcp_limit(memcg, nr_pages);
3112 break;
3063 } 3113 }
3064 break; 3114 break;
3065 case RES_SOFT_LIMIT: 3115 case RES_SOFT_LIMIT:
@@ -3086,6 +3136,11 @@ static ssize_t mem_cgroup_reset(struct kernfs_open_file *of, char *buf,
3086 case _KMEM: 3136 case _KMEM:
3087 counter = &memcg->kmem; 3137 counter = &memcg->kmem;
3088 break; 3138 break;
3139#if defined(CONFIG_MEMCG_LEGACY_KMEM) && defined(CONFIG_INET)
3140 case _TCP:
3141 counter = &memcg->tcp_mem.memory_allocated;
3142 break;
3143#endif
3089 default: 3144 default:
3090 BUG(); 3145 BUG();
3091 } 3146 }
@@ -4072,6 +4127,31 @@ static struct cftype mem_cgroup_legacy_files[] = {
4072 .seq_show = memcg_slab_show, 4127 .seq_show = memcg_slab_show,
4073 }, 4128 },
4074#endif 4129#endif
4130#ifdef CONFIG_INET
4131 {
4132 .name = "kmem.tcp.limit_in_bytes",
4133 .private = MEMFILE_PRIVATE(_TCP, RES_LIMIT),
4134 .write = mem_cgroup_write,
4135 .read_u64 = mem_cgroup_read_u64,
4136 },
4137 {
4138 .name = "kmem.tcp.usage_in_bytes",
4139 .private = MEMFILE_PRIVATE(_TCP, RES_USAGE),
4140 .read_u64 = mem_cgroup_read_u64,
4141 },
4142 {
4143 .name = "kmem.tcp.failcnt",
4144 .private = MEMFILE_PRIVATE(_TCP, RES_FAILCNT),
4145 .write = mem_cgroup_reset,
4146 .read_u64 = mem_cgroup_read_u64,
4147 },
4148 {
4149 .name = "kmem.tcp.max_usage_in_bytes",
4150 .private = MEMFILE_PRIVATE(_TCP, RES_MAX_USAGE),
4151 .write = mem_cgroup_reset,
4152 .read_u64 = mem_cgroup_read_u64,
4153 },
4154#endif
4075#endif 4155#endif
4076 { }, /* terminate */ 4156 { }, /* terminate */
4077}; 4157};
@@ -4241,6 +4321,10 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
4241 memcg->soft_limit = PAGE_COUNTER_MAX; 4321 memcg->soft_limit = PAGE_COUNTER_MAX;
4242 page_counter_init(&memcg->memsw, &parent->memsw); 4322 page_counter_init(&memcg->memsw, &parent->memsw);
4243 page_counter_init(&memcg->kmem, &parent->kmem); 4323 page_counter_init(&memcg->kmem, &parent->kmem);
4324#if defined(CONFIG_MEMCG_LEGACY_KMEM) && defined(CONFIG_INET)
4325 page_counter_init(&memcg->tcp_mem.memory_allocated,
4326 &parent->tcp_mem.memory_allocated);
4327#endif
4244 4328
4245 /* 4329 /*
4246 * No need to take a reference to the parent because cgroup 4330 * No need to take a reference to the parent because cgroup
@@ -4252,6 +4336,9 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
4252 memcg->soft_limit = PAGE_COUNTER_MAX; 4336 memcg->soft_limit = PAGE_COUNTER_MAX;
4253 page_counter_init(&memcg->memsw, NULL); 4337 page_counter_init(&memcg->memsw, NULL);
4254 page_counter_init(&memcg->kmem, NULL); 4338 page_counter_init(&memcg->kmem, NULL);
4339#if defined(CONFIG_MEMCG_LEGACY_KMEM) && defined(CONFIG_INET)
4340 page_counter_init(&memcg->tcp_mem.memory_allocated, NULL);
4341#endif
4255 /* 4342 /*
4256 * Deeper hierachy with use_hierarchy == false doesn't make 4343 * Deeper hierachy with use_hierarchy == false doesn't make
4257 * much sense so let cgroup subsystem know about this 4344 * much sense so let cgroup subsystem know about this
@@ -4267,12 +4354,6 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
4267 return ret; 4354 return ret;
4268 4355
4269#ifdef CONFIG_INET 4356#ifdef CONFIG_INET
4270#ifdef CONFIG_MEMCG_LEGACY_KMEM
4271 ret = tcp_init_cgroup(memcg);
4272 if (ret)
4273 return ret;
4274#endif
4275
4276 if (cgroup_subsys_on_dfl(memory_cgrp_subsys) && !cgroup_memory_nosocket) 4357 if (cgroup_subsys_on_dfl(memory_cgrp_subsys) && !cgroup_memory_nosocket)
4277 static_branch_inc(&memcg_sockets_enabled_key); 4358 static_branch_inc(&memcg_sockets_enabled_key);
4278#endif 4359#endif
@@ -4330,7 +4411,8 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css)
4330 memcg_free_kmem(memcg); 4411 memcg_free_kmem(memcg);
4331 4412
4332#if defined(CONFIG_MEMCG_LEGACY_KMEM) && defined(CONFIG_INET) 4413#if defined(CONFIG_MEMCG_LEGACY_KMEM) && defined(CONFIG_INET)
4333 tcp_destroy_cgroup(memcg); 4414 if (memcg->tcp_mem.active)
4415 static_branch_dec(&memcg_sockets_enabled_key);
4334#endif 4416#endif
4335 4417
4336 __mem_cgroup_free(memcg); 4418 __mem_cgroup_free(memcg);
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index bee5055832a1..62c049b647e9 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
56obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o 56obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
57obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o 57obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
58obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o 58obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
59obj-$(CONFIG_MEMCG_LEGACY_KMEM) += tcp_memcontrol.o
60obj-$(CONFIG_NETLABEL) += cipso_ipv4.o 59obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
61 60
62obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ 61obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 46ce410703b1..4d367b4139a3 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -24,7 +24,6 @@
24#include <net/cipso_ipv4.h> 24#include <net/cipso_ipv4.h>
25#include <net/inet_frag.h> 25#include <net/inet_frag.h>
26#include <net/ping.h> 26#include <net/ping.h>
27#include <net/tcp_memcontrol.h>
28 27
29static int zero; 28static int zero;
30static int one = 1; 29static int one = 1;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c7d1fb50f381..5ced3e4013e3 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -73,7 +73,6 @@
73#include <net/timewait_sock.h> 73#include <net/timewait_sock.h>
74#include <net/xfrm.h> 74#include <net/xfrm.h>
75#include <net/secure_seq.h> 75#include <net/secure_seq.h>
76#include <net/tcp_memcontrol.h>
77#include <net/busy_poll.h> 76#include <net/busy_poll.h>
78 77
79#include <linux/inet.h> 78#include <linux/inet.h>
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
deleted file mode 100644
index 133eb5eac49f..000000000000
--- a/net/ipv4/tcp_memcontrol.c
+++ /dev/null
@@ -1,200 +0,0 @@
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
9int tcp_init_cgroup(struct mem_cgroup *memcg)
10{
11 struct mem_cgroup *parent = parent_mem_cgroup(memcg);
12 struct page_counter *counter_parent = NULL;
13 /*
14 * The root cgroup does not use page_counters, but rather,
15 * rely on the data already collected by the network
16 * subsystem
17 */
18 if (memcg == root_mem_cgroup)
19 return 0;
20
21 memcg->tcp_mem.memory_pressure = 0;
22
23 if (parent)
24 counter_parent = &parent->tcp_mem.memory_allocated;
25
26 page_counter_init(&memcg->tcp_mem.memory_allocated, counter_parent);
27
28 return 0;
29}
30
31void tcp_destroy_cgroup(struct mem_cgroup *memcg)
32{
33 if (memcg == root_mem_cgroup)
34 return;
35
36 if (memcg->tcp_mem.active)
37 static_branch_dec(&memcg_sockets_enabled_key);
38}
39
40static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
41{
42 int ret;
43
44 if (memcg == root_mem_cgroup)
45 return -EINVAL;
46
47 ret = page_counter_limit(&memcg->tcp_mem.memory_allocated, nr_pages);
48 if (ret)
49 return ret;
50
51 if (!memcg->tcp_mem.active) {
52 /*
53 * The active flag needs to be written after the static_key
54 * update. This is what guarantees that the socket activation
55 * function is the last one to run. See sock_update_memcg() for
56 * details, and note that we don't mark any socket as belonging
57 * to this memcg until that flag is up.
58 *
59 * We need to do this, because static_keys will span multiple
60 * sites, but we can't control their order. If we mark a socket
61 * as accounted, but the accounting functions are not patched in
62 * yet, we'll lose accounting.
63 *
64 * We never race with the readers in sock_update_memcg(),
65 * because when this value change, the code to process it is not
66 * patched in yet.
67 */
68 static_branch_inc(&memcg_sockets_enabled_key);
69 memcg->tcp_mem.active = true;
70 }
71
72 return 0;
73}
74
75enum {
76 RES_USAGE,
77 RES_LIMIT,
78 RES_MAX_USAGE,
79 RES_FAILCNT,
80};
81
82static DEFINE_MUTEX(tcp_limit_mutex);
83
84static ssize_t tcp_cgroup_write(struct kernfs_open_file *of,
85 char *buf, size_t nbytes, loff_t off)
86{
87 struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
88 unsigned long nr_pages;
89 int ret = 0;
90
91 buf = strstrip(buf);
92
93 switch (of_cft(of)->private) {
94 case RES_LIMIT:
95 /* see memcontrol.c */
96 ret = page_counter_memparse(buf, "-1", &nr_pages);
97 if (ret)
98 break;
99 mutex_lock(&tcp_limit_mutex);
100 ret = tcp_update_limit(memcg, nr_pages);
101 mutex_unlock(&tcp_limit_mutex);
102 break;
103 default:
104 ret = -EINVAL;
105 break;
106 }
107 return ret ?: nbytes;
108}
109
110static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft)
111{
112 struct mem_cgroup *memcg = mem_cgroup_from_css(css);
113 u64 val;
114
115 switch (cft->private) {
116 case RES_LIMIT:
117 if (memcg == root_mem_cgroup)
118 val = PAGE_COUNTER_MAX;
119 else
120 val = memcg->tcp_mem.memory_allocated.limit;
121 val *= PAGE_SIZE;
122 break;
123 case RES_USAGE:
124 if (memcg == root_mem_cgroup)
125 val = atomic_long_read(&tcp_memory_allocated);
126 else
127 val = page_counter_read(&memcg->tcp_mem.memory_allocated);
128 val *= PAGE_SIZE;
129 break;
130 case RES_FAILCNT:
131 if (memcg == root_mem_cgroup)
132 return 0;
133 val = memcg->tcp_mem.memory_allocated.failcnt;
134 break;
135 case RES_MAX_USAGE:
136 if (memcg == root_mem_cgroup)
137 return 0;
138 val = memcg->tcp_mem.memory_allocated.watermark;
139 val *= PAGE_SIZE;
140 break;
141 default:
142 BUG();
143 }
144 return val;
145}
146
147static ssize_t tcp_cgroup_reset(struct kernfs_open_file *of,
148 char *buf, size_t nbytes, loff_t off)
149{
150 struct mem_cgroup *memcg;
151
152 memcg = mem_cgroup_from_css(of_css(of));
153 if (memcg == root_mem_cgroup)
154 return nbytes;
155
156 switch (of_cft(of)->private) {
157 case RES_MAX_USAGE:
158 page_counter_reset_watermark(&memcg->tcp_mem.memory_allocated);
159 break;
160 case RES_FAILCNT:
161 memcg->tcp_mem.memory_allocated.failcnt = 0;
162 break;
163 }
164
165 return nbytes;
166}
167
168static struct cftype tcp_files[] = {
169 {
170 .name = "kmem.tcp.limit_in_bytes",
171 .write = tcp_cgroup_write,
172 .read_u64 = tcp_cgroup_read,
173 .private = RES_LIMIT,
174 },
175 {
176 .name = "kmem.tcp.usage_in_bytes",
177 .read_u64 = tcp_cgroup_read,
178 .private = RES_USAGE,
179 },
180 {
181 .name = "kmem.tcp.failcnt",
182 .private = RES_FAILCNT,
183 .write = tcp_cgroup_reset,
184 .read_u64 = tcp_cgroup_read,
185 },
186 {
187 .name = "kmem.tcp.max_usage_in_bytes",
188 .private = RES_MAX_USAGE,
189 .write = tcp_cgroup_reset,
190 .read_u64 = tcp_cgroup_read,
191 },
192 { } /* terminate */
193};
194
195static int __init tcp_memcontrol_init(void)
196{
197 WARN_ON(cgroup_add_legacy_cftypes(&memory_cgrp_subsys, tcp_files));
198 return 0;
199}
200__initcall(tcp_memcontrol_init);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 4ad8edb46f7c..006396e31cb0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -61,7 +61,6 @@
61#include <net/timewait_sock.h> 61#include <net/timewait_sock.h>
62#include <net/inet_common.h> 62#include <net/inet_common.h>
63#include <net/secure_seq.h> 63#include <net/secure_seq.h>
64#include <net/tcp_memcontrol.h>
65#include <net/busy_poll.h> 64#include <net/busy_poll.h>
66 65
67#include <linux/proc_fs.h> 66#include <linux/proc_fs.h>