diff options
author | Glauber Costa <glommer@parallels.com> | 2011-12-11 16:47:03 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-12 19:04:10 -0500 |
commit | e1aab161e0135aafcd439be20b4f35e4b0922d95 (patch) | |
tree | d0bcdf7a34a34020079238027b431ffc6dece307 /net | |
parent | 180d8cd942ce336b2c869d324855c40c5db478ad (diff) |
socket: initial cgroup code.
The goal of this work is to move the memory pressure tcp
controls to a cgroup, instead of just relying on global
conditions.
To avoid excessive overhead in the network fast paths,
the code that accounts allocated memory to a cgroup is
hidden inside a static_branch(). This branch is patched out
until the first non-root cgroup is created. So when nobody
is using cgroups, even if it is mounted, no significant performance
penalty should be seen.
This patch handles the generic part of the code, and has nothing
tcp-specific.
Signed-off-by: Glauber Costa <glommer@parallels.com>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujtsu.com>
CC: Kirill A. Shutemov <kirill@shutemov.name>
CC: David S. Miller <davem@davemloft.net>
CC: Eric W. Biederman <ebiederm@xmission.com>
CC: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/sock.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index a3d4205e7238..6a871b8fdd20 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -111,6 +111,7 @@ | |||
111 | #include <linux/init.h> | 111 | #include <linux/init.h> |
112 | #include <linux/highmem.h> | 112 | #include <linux/highmem.h> |
113 | #include <linux/user_namespace.h> | 113 | #include <linux/user_namespace.h> |
114 | #include <linux/jump_label.h> | ||
114 | 115 | ||
115 | #include <asm/uaccess.h> | 116 | #include <asm/uaccess.h> |
116 | #include <asm/system.h> | 117 | #include <asm/system.h> |
@@ -142,6 +143,9 @@ | |||
142 | static struct lock_class_key af_family_keys[AF_MAX]; | 143 | static struct lock_class_key af_family_keys[AF_MAX]; |
143 | static struct lock_class_key af_family_slock_keys[AF_MAX]; | 144 | static struct lock_class_key af_family_slock_keys[AF_MAX]; |
144 | 145 | ||
146 | struct jump_label_key memcg_socket_limit_enabled; | ||
147 | EXPORT_SYMBOL(memcg_socket_limit_enabled); | ||
148 | |||
145 | /* | 149 | /* |
146 | * Make lock validator output more readable. (we pre-construct these | 150 | * Make lock validator output more readable. (we pre-construct these |
147 | * strings build-time, so that runtime initialization of socket | 151 | * strings build-time, so that runtime initialization of socket |
@@ -1711,23 +1715,27 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind) | |||
1711 | struct proto *prot = sk->sk_prot; | 1715 | struct proto *prot = sk->sk_prot; |
1712 | int amt = sk_mem_pages(size); | 1716 | int amt = sk_mem_pages(size); |
1713 | long allocated; | 1717 | long allocated; |
1718 | int parent_status = UNDER_LIMIT; | ||
1714 | 1719 | ||
1715 | sk->sk_forward_alloc += amt * SK_MEM_QUANTUM; | 1720 | sk->sk_forward_alloc += amt * SK_MEM_QUANTUM; |
1716 | 1721 | ||
1717 | allocated = sk_memory_allocated_add(sk, amt); | 1722 | allocated = sk_memory_allocated_add(sk, amt, &parent_status); |
1718 | 1723 | ||
1719 | /* Under limit. */ | 1724 | /* Under limit. */ |
1720 | if (allocated <= sk_prot_mem_limits(sk, 0)) { | 1725 | if (parent_status == UNDER_LIMIT && |
1726 | allocated <= sk_prot_mem_limits(sk, 0)) { | ||
1721 | sk_leave_memory_pressure(sk); | 1727 | sk_leave_memory_pressure(sk); |
1722 | return 1; | 1728 | return 1; |
1723 | } | 1729 | } |
1724 | 1730 | ||
1725 | /* Under pressure. */ | 1731 | /* Under pressure. (we or our parents) */ |
1726 | if (allocated > sk_prot_mem_limits(sk, 1)) | 1732 | if ((parent_status > SOFT_LIMIT) || |
1733 | allocated > sk_prot_mem_limits(sk, 1)) | ||
1727 | sk_enter_memory_pressure(sk); | 1734 | sk_enter_memory_pressure(sk); |
1728 | 1735 | ||
1729 | /* Over hard limit. */ | 1736 | /* Over hard limit (we or our parents) */ |
1730 | if (allocated > sk_prot_mem_limits(sk, 2)) | 1737 | if ((parent_status == OVER_LIMIT) || |
1738 | (allocated > sk_prot_mem_limits(sk, 2))) | ||
1731 | goto suppress_allocation; | 1739 | goto suppress_allocation; |
1732 | 1740 | ||
1733 | /* guarantee minimum buffer size under pressure */ | 1741 | /* guarantee minimum buffer size under pressure */ |
@@ -1774,7 +1782,7 @@ suppress_allocation: | |||
1774 | /* Alas. Undo changes. */ | 1782 | /* Alas. Undo changes. */ |
1775 | sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM; | 1783 | sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM; |
1776 | 1784 | ||
1777 | sk_memory_allocated_sub(sk, amt); | 1785 | sk_memory_allocated_sub(sk, amt, parent_status); |
1778 | 1786 | ||
1779 | return 0; | 1787 | return 0; |
1780 | } | 1788 | } |
@@ -1787,7 +1795,7 @@ EXPORT_SYMBOL(__sk_mem_schedule); | |||
1787 | void __sk_mem_reclaim(struct sock *sk) | 1795 | void __sk_mem_reclaim(struct sock *sk) |
1788 | { | 1796 | { |
1789 | sk_memory_allocated_sub(sk, | 1797 | sk_memory_allocated_sub(sk, |
1790 | sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT); | 1798 | sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT, 0); |
1791 | sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1; | 1799 | sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1; |
1792 | 1800 | ||
1793 | if (sk_under_memory_pressure(sk) && | 1801 | if (sk_under_memory_pressure(sk) && |