]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - net/ipv4/tcp_memcontrol.c
net: tcp_memcontrol: remove dead per-memcg count of allocated sockets
[karo-tx-linux.git] / net / ipv4 / tcp_memcontrol.c
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
9 int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
10 {
11         /*
12          * The root cgroup does not use page_counters, but rather,
13          * rely on the data already collected by the network
14          * subsystem
15          */
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
20         cg_proto = tcp_prot.proto_cgroup(memcg);
21         if (!cg_proto)
22                 return 0;
23
24         cg_proto->sysctl_mem[0] = sysctl_tcp_mem[0];
25         cg_proto->sysctl_mem[1] = sysctl_tcp_mem[1];
26         cg_proto->sysctl_mem[2] = sysctl_tcp_mem[2];
27         cg_proto->memory_pressure = 0;
28         cg_proto->memcg = memcg;
29
30         parent_cg = tcp_prot.proto_cgroup(parent);
31         if (parent_cg)
32                 counter_parent = &parent_cg->memory_allocated;
33
34         page_counter_init(&cg_proto->memory_allocated, counter_parent);
35
36         return 0;
37 }
38 EXPORT_SYMBOL(tcp_init_cgroup);
39
40 void tcp_destroy_cgroup(struct mem_cgroup *memcg)
41 {
42         struct cg_proto *cg_proto;
43
44         cg_proto = tcp_prot.proto_cgroup(memcg);
45         if (!cg_proto)
46                 return;
47
48         if (cg_proto->active)
49                 static_key_slow_dec(&memcg_socket_limit_enabled);
50
51 }
52 EXPORT_SYMBOL(tcp_destroy_cgroup);
53
54 static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
55 {
56         struct cg_proto *cg_proto;
57         int i;
58         int ret;
59
60         cg_proto = tcp_prot.proto_cgroup(memcg);
61         if (!cg_proto)
62                 return -EINVAL;
63
64         ret = page_counter_limit(&cg_proto->memory_allocated, nr_pages);
65         if (ret)
66                 return ret;
67
68         for (i = 0; i < 3; i++)
69                 cg_proto->sysctl_mem[i] = min_t(long, nr_pages,
70                                                 sysctl_tcp_mem[i]);
71
72         if (!cg_proto->active) {
73                 /*
74                  * The active flag needs to be written after the static_key
75                  * update. This is what guarantees that the socket activation
76                  * function is the last one to run. See sock_update_memcg() for
77                  * details, and note that we don't mark any socket as belonging
78                  * to this memcg until that flag is up.
79                  *
80                  * We need to do this, because static_keys will span multiple
81                  * sites, but we can't control their order. If we mark a socket
82                  * as accounted, but the accounting functions are not patched in
83                  * yet, we'll lose accounting.
84                  *
85                  * We never race with the readers in sock_update_memcg(),
86                  * because when this value change, the code to process it is not
87                  * patched in yet.
88                  */
89                 static_key_slow_inc(&memcg_socket_limit_enabled);
90                 cg_proto->active = true;
91         }
92
93         return 0;
94 }
95
96 enum {
97         RES_USAGE,
98         RES_LIMIT,
99         RES_MAX_USAGE,
100         RES_FAILCNT,
101 };
102
103 static DEFINE_MUTEX(tcp_limit_mutex);
104
105 static ssize_t tcp_cgroup_write(struct kernfs_open_file *of,
106                                 char *buf, size_t nbytes, loff_t off)
107 {
108         struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
109         unsigned long nr_pages;
110         int ret = 0;
111
112         buf = strstrip(buf);
113
114         switch (of_cft(of)->private) {
115         case RES_LIMIT:
116                 /* see memcontrol.c */
117                 ret = page_counter_memparse(buf, "-1", &nr_pages);
118                 if (ret)
119                         break;
120                 mutex_lock(&tcp_limit_mutex);
121                 ret = tcp_update_limit(memcg, nr_pages);
122                 mutex_unlock(&tcp_limit_mutex);
123                 break;
124         default:
125                 ret = -EINVAL;
126                 break;
127         }
128         return ret ?: nbytes;
129 }
130
131 static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft)
132 {
133         struct mem_cgroup *memcg = mem_cgroup_from_css(css);
134         struct cg_proto *cg_proto = tcp_prot.proto_cgroup(memcg);
135         u64 val;
136
137         switch (cft->private) {
138         case RES_LIMIT:
139                 if (!cg_proto)
140                         return PAGE_COUNTER_MAX;
141                 val = cg_proto->memory_allocated.limit;
142                 val *= PAGE_SIZE;
143                 break;
144         case RES_USAGE:
145                 if (!cg_proto)
146                         val = atomic_long_read(&tcp_memory_allocated);
147                 else
148                         val = page_counter_read(&cg_proto->memory_allocated);
149                 val *= PAGE_SIZE;
150                 break;
151         case RES_FAILCNT:
152                 if (!cg_proto)
153                         return 0;
154                 val = cg_proto->memory_allocated.failcnt;
155                 break;
156         case RES_MAX_USAGE:
157                 if (!cg_proto)
158                         return 0;
159                 val = cg_proto->memory_allocated.watermark;
160                 val *= PAGE_SIZE;
161                 break;
162         default:
163                 BUG();
164         }
165         return val;
166 }
167
168 static ssize_t tcp_cgroup_reset(struct kernfs_open_file *of,
169                                 char *buf, size_t nbytes, loff_t off)
170 {
171         struct mem_cgroup *memcg;
172         struct cg_proto *cg_proto;
173
174         memcg = mem_cgroup_from_css(of_css(of));
175         cg_proto = tcp_prot.proto_cgroup(memcg);
176         if (!cg_proto)
177                 return nbytes;
178
179         switch (of_cft(of)->private) {
180         case RES_MAX_USAGE:
181                 page_counter_reset_watermark(&cg_proto->memory_allocated);
182                 break;
183         case RES_FAILCNT:
184                 cg_proto->memory_allocated.failcnt = 0;
185                 break;
186         }
187
188         return nbytes;
189 }
190
191 static struct cftype tcp_files[] = {
192         {
193                 .name = "kmem.tcp.limit_in_bytes",
194                 .write = tcp_cgroup_write,
195                 .read_u64 = tcp_cgroup_read,
196                 .private = RES_LIMIT,
197         },
198         {
199                 .name = "kmem.tcp.usage_in_bytes",
200                 .read_u64 = tcp_cgroup_read,
201                 .private = RES_USAGE,
202         },
203         {
204                 .name = "kmem.tcp.failcnt",
205                 .private = RES_FAILCNT,
206                 .write = tcp_cgroup_reset,
207                 .read_u64 = tcp_cgroup_read,
208         },
209         {
210                 .name = "kmem.tcp.max_usage_in_bytes",
211                 .private = RES_MAX_USAGE,
212                 .write = tcp_cgroup_reset,
213                 .read_u64 = tcp_cgroup_read,
214         },
215         { }     /* terminate */
216 };
217
218 static int __init tcp_memcontrol_init(void)
219 {
220         WARN_ON(cgroup_add_legacy_cftypes(&memory_cgrp_subsys, tcp_files));
221         return 0;
222 }
223 __initcall(tcp_memcontrol_init);