aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_memcontrol.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_memcontrol.c')
-rw-r--r--net/ipv4/tcp_memcontrol.c87
1 files changed, 44 insertions, 43 deletions
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
index 1d191357bf88..272327134a1b 100644
--- a/net/ipv4/tcp_memcontrol.c
+++ b/net/ipv4/tcp_memcontrol.c
@@ -9,13 +9,13 @@
9int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss) 9int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
10{ 10{
11 /* 11 /*
12 * The root cgroup does not use res_counters, but rather, 12 * The root cgroup does not use page_counters, but rather,
13 * rely on the data already collected by the network 13 * rely on the data already collected by the network
14 * subsystem 14 * subsystem
15 */ 15 */
16 struct res_counter *res_parent = NULL;
17 struct cg_proto *cg_proto, *parent_cg;
18 struct mem_cgroup *parent = parent_mem_cgroup(memcg); 16 struct mem_cgroup *parent = parent_mem_cgroup(memcg);
17 struct page_counter *counter_parent = NULL;
18 struct cg_proto *cg_proto, *parent_cg;
19 19
20 cg_proto = tcp_prot.proto_cgroup(memcg); 20 cg_proto = tcp_prot.proto_cgroup(memcg);
21 if (!cg_proto) 21 if (!cg_proto)
@@ -29,9 +29,9 @@ int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
29 29
30 parent_cg = tcp_prot.proto_cgroup(parent); 30 parent_cg = tcp_prot.proto_cgroup(parent);
31 if (parent_cg) 31 if (parent_cg)
32 res_parent = &parent_cg->memory_allocated; 32 counter_parent = &parent_cg->memory_allocated;
33 33
34 res_counter_init(&cg_proto->memory_allocated, res_parent); 34 page_counter_init(&cg_proto->memory_allocated, counter_parent);
35 percpu_counter_init(&cg_proto->sockets_allocated, 0, GFP_KERNEL); 35 percpu_counter_init(&cg_proto->sockets_allocated, 0, GFP_KERNEL);
36 36
37 return 0; 37 return 0;
@@ -50,7 +50,7 @@ void tcp_destroy_cgroup(struct mem_cgroup *memcg)
50} 50}
51EXPORT_SYMBOL(tcp_destroy_cgroup); 51EXPORT_SYMBOL(tcp_destroy_cgroup);
52 52
53static int tcp_update_limit(struct mem_cgroup *memcg, u64 val) 53static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
54{ 54{
55 struct cg_proto *cg_proto; 55 struct cg_proto *cg_proto;
56 int i; 56 int i;
@@ -60,20 +60,17 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
60 if (!cg_proto) 60 if (!cg_proto)
61 return -EINVAL; 61 return -EINVAL;
62 62
63 if (val > RES_COUNTER_MAX) 63 ret = page_counter_limit(&cg_proto->memory_allocated, nr_pages);
64 val = RES_COUNTER_MAX;
65
66 ret = res_counter_set_limit(&cg_proto->memory_allocated, val);
67 if (ret) 64 if (ret)
68 return ret; 65 return ret;
69 66
70 for (i = 0; i < 3; i++) 67 for (i = 0; i < 3; i++)
71 cg_proto->sysctl_mem[i] = min_t(long, val >> PAGE_SHIFT, 68 cg_proto->sysctl_mem[i] = min_t(long, nr_pages,
72 sysctl_tcp_mem[i]); 69 sysctl_tcp_mem[i]);
73 70
74 if (val == RES_COUNTER_MAX) 71 if (nr_pages == PAGE_COUNTER_MAX)
75 clear_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags); 72 clear_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags);
76 else if (val != RES_COUNTER_MAX) { 73 else {
77 /* 74 /*
78 * The active bit needs to be written after the static_key 75 * The active bit needs to be written after the static_key
79 * update. This is what guarantees that the socket activation 76 * update. This is what guarantees that the socket activation
@@ -102,11 +99,20 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
102 return 0; 99 return 0;
103} 100}
104 101
102enum {
103 RES_USAGE,
104 RES_LIMIT,
105 RES_MAX_USAGE,
106 RES_FAILCNT,
107};
108
109static DEFINE_MUTEX(tcp_limit_mutex);
110
105static ssize_t tcp_cgroup_write(struct kernfs_open_file *of, 111static ssize_t tcp_cgroup_write(struct kernfs_open_file *of,
106 char *buf, size_t nbytes, loff_t off) 112 char *buf, size_t nbytes, loff_t off)
107{ 113{
108 struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of)); 114 struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
109 unsigned long long val; 115 unsigned long nr_pages;
110 int ret = 0; 116 int ret = 0;
111 117
112 buf = strstrip(buf); 118 buf = strstrip(buf);
@@ -114,10 +120,12 @@ static ssize_t tcp_cgroup_write(struct kernfs_open_file *of,
114 switch (of_cft(of)->private) { 120 switch (of_cft(of)->private) {
115 case RES_LIMIT: 121 case RES_LIMIT:
116 /* see memcontrol.c */ 122 /* see memcontrol.c */
117 ret = res_counter_memparse_write_strategy(buf, &val); 123 ret = page_counter_memparse(buf, &nr_pages);
118 if (ret) 124 if (ret)
119 break; 125 break;
120 ret = tcp_update_limit(memcg, val); 126 mutex_lock(&tcp_limit_mutex);
127 ret = tcp_update_limit(memcg, nr_pages);
128 mutex_unlock(&tcp_limit_mutex);
121 break; 129 break;
122 default: 130 default:
123 ret = -EINVAL; 131 ret = -EINVAL;
@@ -126,43 +134,36 @@ static ssize_t tcp_cgroup_write(struct kernfs_open_file *of,
126 return ret ?: nbytes; 134 return ret ?: nbytes;
127} 135}
128 136
129static u64 tcp_read_stat(struct mem_cgroup *memcg, int type, u64 default_val)
130{
131 struct cg_proto *cg_proto;
132
133 cg_proto = tcp_prot.proto_cgroup(memcg);
134 if (!cg_proto)
135 return default_val;
136
137 return res_counter_read_u64(&cg_proto->memory_allocated, type);
138}
139
140static u64 tcp_read_usage(struct mem_cgroup *memcg)
141{
142 struct cg_proto *cg_proto;
143
144 cg_proto = tcp_prot.proto_cgroup(memcg);
145 if (!cg_proto)
146 return atomic_long_read(&tcp_memory_allocated) << PAGE_SHIFT;
147
148 return res_counter_read_u64(&cg_proto->memory_allocated, RES_USAGE);
149}
150
151static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft) 137static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft)
152{ 138{
153 struct mem_cgroup *memcg = mem_cgroup_from_css(css); 139 struct mem_cgroup *memcg = mem_cgroup_from_css(css);
140 struct cg_proto *cg_proto = tcp_prot.proto_cgroup(memcg);
154 u64 val; 141 u64 val;
155 142
156 switch (cft->private) { 143 switch (cft->private) {
157 case RES_LIMIT: 144 case RES_LIMIT:
158 val = tcp_read_stat(memcg, RES_LIMIT, RES_COUNTER_MAX); 145 if (!cg_proto)
146 return PAGE_COUNTER_MAX;
147 val = cg_proto->memory_allocated.limit;
148 val *= PAGE_SIZE;
159 break; 149 break;
160 case RES_USAGE: 150 case RES_USAGE:
161 val = tcp_read_usage(memcg); 151 if (!cg_proto)
152 val = atomic_long_read(&tcp_memory_allocated);
153 else
154 val = page_counter_read(&cg_proto->memory_allocated);
155 val *= PAGE_SIZE;
162 break; 156 break;
163 case RES_FAILCNT: 157 case RES_FAILCNT:
158 if (!cg_proto)
159 return 0;
160 val = cg_proto->memory_allocated.failcnt;
161 break;
164 case RES_MAX_USAGE: 162 case RES_MAX_USAGE:
165 val = tcp_read_stat(memcg, cft->private, 0); 163 if (!cg_proto)
164 return 0;
165 val = cg_proto->memory_allocated.watermark;
166 val *= PAGE_SIZE;
166 break; 167 break;
167 default: 168 default:
168 BUG(); 169 BUG();
@@ -183,10 +184,10 @@ static ssize_t tcp_cgroup_reset(struct kernfs_open_file *of,
183 184
184 switch (of_cft(of)->private) { 185 switch (of_cft(of)->private) {
185 case RES_MAX_USAGE: 186 case RES_MAX_USAGE:
186 res_counter_reset_max(&cg_proto->memory_allocated); 187 page_counter_reset_watermark(&cg_proto->memory_allocated);
187 break; 188 break;
188 case RES_FAILCNT: 189 case RES_FAILCNT:
189 res_counter_reset_failcnt(&cg_proto->memory_allocated); 190 cg_proto->memory_allocated.failcnt = 0;
190 break; 191 break;
191 } 192 }
192 193