aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2016-01-14 18:21:05 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-14 19:00:49 -0500
commit3d596f7b907b0281b997cf30c92994a71ad0a1a9 (patch)
treec039825abb7b78cc1cbe3d06e2a2fe481f81f3af
parent931f3f4beb031cd483c1c8ab159ef1f8bdbe8888 (diff)
net: tcp_memcontrol: protect all tcp_memcontrol calls by jump-label
Move the jump-label from sock_update_memcg() and sock_release_memcg() to the callsite, and so eliminate those function calls when socket accounting is not enabled. This also eliminates the need for dummy functions because the calls will be optimized away if the Kconfig options are not enabled. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: David S. Miller <davem@davemloft.net> Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/memcontrol.h9
-rw-r--r--mm/memcontrol.c56
-rw-r--r--net/core/sock.c9
-rw-r--r--net/ipv4/tcp.c3
-rw-r--r--net/ipv4/tcp_ipv4.c4
5 files changed, 32 insertions, 49 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index d0c724f53691..85c437b0cbc0 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -694,17 +694,8 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
694#endif /* CONFIG_CGROUP_WRITEBACK */ 694#endif /* CONFIG_CGROUP_WRITEBACK */
695 695
696struct sock; 696struct sock;
697#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
698void sock_update_memcg(struct sock *sk); 697void sock_update_memcg(struct sock *sk);
699void sock_release_memcg(struct sock *sk); 698void sock_release_memcg(struct sock *sk);
700#else
701static inline void sock_update_memcg(struct sock *sk)
702{
703}
704static inline void sock_release_memcg(struct sock *sk)
705{
706}
707#endif /* CONFIG_INET && CONFIG_MEMCG_KMEM */
708 699
709#ifdef CONFIG_MEMCG_KMEM 700#ifdef CONFIG_MEMCG_KMEM
710extern struct static_key memcg_kmem_enabled_key; 701extern struct static_key memcg_kmem_enabled_key;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 44ed2dee8f0c..d9344dad207e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -293,46 +293,40 @@ static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
293 293
294void sock_update_memcg(struct sock *sk) 294void sock_update_memcg(struct sock *sk)
295{ 295{
296 if (mem_cgroup_sockets_enabled) { 296 struct mem_cgroup *memcg;
297 struct mem_cgroup *memcg; 297 struct cg_proto *cg_proto;
298 struct cg_proto *cg_proto;
299 298
300 BUG_ON(!sk->sk_prot->proto_cgroup); 299 BUG_ON(!sk->sk_prot->proto_cgroup);
301 300
302 /* Socket cloning can throw us here with sk_cgrp already 301 /* Socket cloning can throw us here with sk_cgrp already
303 * filled. It won't however, necessarily happen from 302 * filled. It won't however, necessarily happen from
304 * process context. So the test for root memcg given 303 * process context. So the test for root memcg given
305 * the current task's memcg won't help us in this case. 304 * the current task's memcg won't help us in this case.
306 * 305 *
307 * Respecting the original socket's memcg is a better 306 * Respecting the original socket's memcg is a better
308 * decision in this case. 307 * decision in this case.
309 */ 308 */
310 if (sk->sk_cgrp) { 309 if (sk->sk_cgrp) {
311 BUG_ON(mem_cgroup_is_root(sk->sk_cgrp->memcg)); 310 BUG_ON(mem_cgroup_is_root(sk->sk_cgrp->memcg));
312 css_get(&sk->sk_cgrp->memcg->css); 311 css_get(&sk->sk_cgrp->memcg->css);
313 return; 312 return;
314 } 313 }
315 314
316 rcu_read_lock(); 315 rcu_read_lock();
317 memcg = mem_cgroup_from_task(current); 316 memcg = mem_cgroup_from_task(current);
318 cg_proto = sk->sk_prot->proto_cgroup(memcg); 317 cg_proto = sk->sk_prot->proto_cgroup(memcg);
319 if (cg_proto && cg_proto->active && 318 if (cg_proto && cg_proto->active &&
320 css_tryget_online(&memcg->css)) { 319 css_tryget_online(&memcg->css)) {
321 sk->sk_cgrp = cg_proto; 320 sk->sk_cgrp = cg_proto;
322 }
323 rcu_read_unlock();
324 } 321 }
322 rcu_read_unlock();
325} 323}
326EXPORT_SYMBOL(sock_update_memcg); 324EXPORT_SYMBOL(sock_update_memcg);
327 325
328void sock_release_memcg(struct sock *sk) 326void sock_release_memcg(struct sock *sk)
329{ 327{
330 if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { 328 WARN_ON(!sk->sk_cgrp->memcg);
331 struct mem_cgroup *memcg; 329 css_put(&sk->sk_cgrp->memcg->css);
332 WARN_ON(!sk->sk_cgrp->memcg);
333 memcg = sk->sk_cgrp->memcg;
334 css_put(&sk->sk_cgrp->memcg->css);
335 }
336} 330}
337 331
338struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg) 332struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg)
diff --git a/net/core/sock.c b/net/core/sock.c
index 51270238e269..6c5dab01105b 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1507,12 +1507,6 @@ void sk_free(struct sock *sk)
1507} 1507}
1508EXPORT_SYMBOL(sk_free); 1508EXPORT_SYMBOL(sk_free);
1509 1509
1510static void sk_update_clone(const struct sock *sk, struct sock *newsk)
1511{
1512 if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
1513 sock_update_memcg(newsk);
1514}
1515
1516/** 1510/**
1517 * sk_clone_lock - clone a socket, and lock its clone 1511 * sk_clone_lock - clone a socket, and lock its clone
1518 * @sk: the socket to clone 1512 * @sk: the socket to clone
@@ -1607,7 +1601,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
1607 sk_set_socket(newsk, NULL); 1601 sk_set_socket(newsk, NULL);
1608 newsk->sk_wq = NULL; 1602 newsk->sk_wq = NULL;
1609 1603
1610 sk_update_clone(sk, newsk); 1604 if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
1605 sock_update_memcg(newsk);
1611 1606
1612 if (newsk->sk_prot->sockets_allocated) 1607 if (newsk->sk_prot->sockets_allocated)
1613 sk_sockets_allocated_inc(newsk); 1608 sk_sockets_allocated_inc(newsk);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 7bb1b091efd1..fd17eec93525 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -422,7 +422,8 @@ void tcp_init_sock(struct sock *sk)
422 sk->sk_rcvbuf = sysctl_tcp_rmem[1]; 422 sk->sk_rcvbuf = sysctl_tcp_rmem[1];
423 423
424 local_bh_disable(); 424 local_bh_disable();
425 sock_update_memcg(sk); 425 if (mem_cgroup_sockets_enabled)
426 sock_update_memcg(sk);
426 sk_sockets_allocated_inc(sk); 427 sk_sockets_allocated_inc(sk);
427 local_bh_enable(); 428 local_bh_enable();
428} 429}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 65947c1f4733..eb39e02899e5 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1818,7 +1818,9 @@ void tcp_v4_destroy_sock(struct sock *sk)
1818 tcp_saved_syn_free(tp); 1818 tcp_saved_syn_free(tp);
1819 1819
1820 sk_sockets_allocated_dec(sk); 1820 sk_sockets_allocated_dec(sk);
1821 sock_release_memcg(sk); 1821
1822 if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
1823 sock_release_memcg(sk);
1822} 1824}
1823EXPORT_SYMBOL(tcp_v4_destroy_sock); 1825EXPORT_SYMBOL(tcp_v4_destroy_sock);
1824 1826