Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1276786 > unrolled thread
| Started by | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| First post | 2015-11-24 23:00 +0100 |
| Last post | 2015-11-30 17:20 +0100 |
| Articles | 20 on this page of 30 — 4 participants |
Back to article view | Back to linux.kernel
[PATCH 00/13] mm: memcontrol: account socket memory in unified hierarchy v4 Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
[PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
Re: [PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller David Miller <davem@davemloft.net> - 2015-11-25 17:40 +0100
Re: [PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller Vladimir Davydov <vdavydov@virtuozzo.com> - 2015-11-30 12:00 +0100
Re: [PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller Johannes Weiner <hannes@cmpxchg.org> - 2015-11-30 16:30 +0100
Re: [PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller Vladimir Davydov <vdavydov@virtuozzo.com> - 2015-11-30 18:10 +0100
[PATCH 01/13] mm: memcontrol: export root_mem_cgroup Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
[PATCH 04/13] net: tcp_memcontrol: protect all tcp_memcontrol calls by jump-label Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
[PATCH 02/13] net: tcp_memcontrol: properly detect ancestor socket pressure Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
[PATCH 06/13] net: tcp_memcontrol: simplify the per-memcg limit access Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
Re: [PATCH 06/13] net: tcp_memcontrol: simplify the per-memcg limit access David Miller <davem@davemloft.net> - 2015-11-25 17:30 +0100
[PATCH 07/13] net: tcp_memcontrol: sanitize tcp memory accounting callbacks Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
Re: [PATCH 07/13] net: tcp_memcontrol: sanitize tcp memory accounting callbacks David Miller <davem@davemloft.net> - 2015-11-25 17:30 +0100
[PATCH 03/13] net: tcp_memcontrol: remove bogus hierarchy pressure propagation Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
[PATCH 11/13] mm: memcontrol: move socket code for unified hierarchy accounting Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
Re: [PATCH 11/13] mm: memcontrol: move socket code for unified hierarchy accounting David Miller <davem@davemloft.net> - 2015-11-25 17:40 +0100
[PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
Re: [PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label David Miller <davem@davemloft.net> - 2015-11-25 17:30 +0100
Re: [PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label Jason Baron <jbaron@akamai.com> - 2015-11-30 22:10 +0100
Re: [PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label Johannes Weiner <hannes@cmpxchg.org> - 2015-11-30 23:00 +0100
Re: [PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label Jason Baron <jbaron@akamai.com> - 2015-11-30 23:30 +0100
Re: [PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label Johannes Weiner <hannes@cmpxchg.org> - 2015-11-30 23:50 +0100
[PATCH 08/13] net: tcp_memcontrol: simplify linkage between socket and page counter Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
Re: [PATCH 08/13] net: tcp_memcontrol: simplify linkage between socket and page counter David Miller <davem@davemloft.net> - 2015-11-25 17:30 +0100
[PATCH 05/13] net: tcp_memcontrol: remove dead per-memcg count of allocated sockets Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:00 +0100
[PATCH 13/13] mm: memcontrol: hook up vmpressure to socket pressure Johannes Weiner <hannes@cmpxchg.org> - 2015-11-24 23:10 +0100
Re: [PATCH 13/13] mm: memcontrol: hook up vmpressure to socket pressure David Miller <davem@davemloft.net> - 2015-11-25 17:40 +0100
Re: [PATCH 13/13] mm: memcontrol: hook up vmpressure to socket pressure Vladimir Davydov <vdavydov@virtuozzo.com> - 2015-11-30 12:40 +0100
Re: [PATCH 13/13] mm: memcontrol: hook up vmpressure to socket pressure Johannes Weiner <hannes@cmpxchg.org> - 2015-11-30 17:00 +0100
Re: [PATCH 13/13] mm: memcontrol: hook up vmpressure to socket pressure Vladimir Davydov <vdavydov@virtuozzo.com> - 2015-11-30 17:20 +0100
Page 1 of 2 [1] 2 Next page →
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 00/13] mm: memcontrol: account socket memory in unified hierarchy v4 |
| Message-ID | <qytMZ-5hB-3@gated-at.bofh.it> |
Hi, this is version 4 of the patches to add socket memory accounting to the unified hierarchy memory controller. Andrew, absent any new showstoppers, please consider merging this series for v4.5. Thanks! Changes since v3 include: - Restored the local vmpressure reporting while preserving the hierarchical pressure semantics of the user interface, such that networking is throttled also for global memory shortage, and not just when encountering configured cgroup limits. As per Vladimir, this will make fully provisioned systems perform more smoothly. - Make packet submission paths enter direct reclaim when memory is tight, and reserve the background balancing worklet for receiving packets in softirq context. - Dropped a buggy shrinker cleanup, spotted by Vladimir. - Fixed a missing return statement, spotted by Eric. - Documented cgroup.memory=nosocket, as per Michal. - Rebased onto latest mmots and added ack tags. Changes since v2 include: - Fixed an underflow bug in the mem+swap counter that came through the design of the per-cpu charge cache. To fix that, the unused mem+swap counter is now fully patched out on unified hierarchy. Double whammy. - Restored the counting jump label such that the networking callbacks get patched out again when the last memory-controlled cgroup goes away. The code was already there, so we might as well keep it. - Broke down the massive tcp_memcontrol rewrite patch into smaller logical pieces to (hopefully) make it easier to review and verify. Changes since v1 include: - No accounting overhead unless a dedicated cgroup is created and the memory controller instructed to track that group's memory footprint. Distribution kernels enable CONFIG_MEMCG, and users (incl. systemd) might create cgroups only for process control or resources other than memory. As noted by David and Michal, these setups shouldn't pay any overhead for this. - Continue to enter the socket pressure state when hitting the memory controller's hard limit. Vladimir noted that there is at least some value in telling other sockets in the cgroup to not increase their transmit windows when one of them is already dropping packets. - Drop the controversial vmpressure rework. Instead of changing the level where pressure is noted, keep noting pressure in its origin and then make the pressure check hierarchical. As noted by Michal and Vladimir, we shouldn't risk changing user-visible behavior. --- Socket buffer memory can make up a significant share of a workload's memory footprint that can be directly linked to userspace activity, and so it needs to be part of the memory controller to provide proper resource isolation/containment. Historically, socket buffers were accounted in a separate counter, without any pressure equalization between anonymous memory, page cache, and the socket buffers. When the socket buffer pool was exhausted, buffer allocations would fail hard and cause network performance to tank, regardless of whether there was still memory available to the group or not. Likewise, struggling anonymous or cache workingsets could not dip into an idle socket memory pool. Because of this, the feature was not usable for many real life applications. To not repeat this mistake, the new memory controller will account all types of memory pages it is tracking on behalf of a cgroup in a single pool. Upon pressure, the VM reclaims and shrinks and puts pressure on whatever memory consumer in that pool is within its reach. For socket memory, pressure feedback is provided through vmpressure events. When the VM has trouble freeing memory, the network code is instructed to stop growing the cgroup's transmit windows. This series begins with a rework of the existing tcp memory controller that simplifies and cleans up the code while allowing us to have only one set of networking hooks for both memory controller versions. The original behavior of the existing tcp controller should be preserved. It then adds socket accounting to the v2 memory controller, including the use of the per-cpu charge cache and async memory.high enforcement from socket memory charges. Lastly, vmpressure is hooked up to the socket code so that it stops growing transmit windows when the VM has trouble reclaiming memory. Documentation/kernel-parameters.txt | 4 + include/linux/memcontrol.h | 71 ++++---- include/linux/vmpressure.h | 5 +- include/net/sock.h | 149 ++--------------- include/net/tcp.h | 5 +- include/net/tcp_memcontrol.h | 1 - mm/backing-dev.c | 2 +- mm/memcontrol.c | 296 ++++++++++++++++++++++------------ mm/vmpressure.c | 78 ++++++--- mm/vmscan.c | 10 +- net/core/sock.c | 78 +++------ net/ipv4/tcp.c | 3 +- net/ipv4/tcp_ipv4.c | 9 +- net/ipv4/tcp_memcontrol.c | 82 ++++------ net/ipv4/tcp_output.c | 7 +- net/ipv6/tcp_ipv6.c | 3 - 16 files changed, 383 insertions(+), 420 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller |
| Message-ID | <qytN0-5hB-9@gated-at.bofh.it> |
| In reply to | #1276786 |
Socket memory can be a significant share of overall memory consumed by
common workloads. In order to provide reasonable resource isolation in
the unified hierarchy, this type of memory needs to be included in the
tracking/accounting of a cgroup under active memory resource control.
Overhead is only incurred when a non-root control group is created AND
the memory controller is instructed to track and account the memory
footprint of that group. cgroup.memory=nosocket can be specified on
the boot commandline to override any runtime configuration and
forcibly exclude socket memory from active memory resource control.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
Documentation/kernel-parameters.txt | 4 ++
include/linux/memcontrol.h | 11 +++-
mm/memcontrol.c | 122 +++++++++++++++++++++++++++++-------
3 files changed, 111 insertions(+), 26 deletions(-)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 742f69d..7868f1b 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -599,6 +599,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
cut the overhead, others just disable the usage. So
only cgroup_disable=memory is actually worthy}
+ cgroup.memory= [KNL] Pass options to the cgroup memory controller.
+ Format: <string>
+ nosocket -- Disable socket memory accounting.
+
checkreqprot [SELINUX] Set initial checkreqprot flag value.
Format: { "0" | "1" }
See security/selinux/Kconfig help text.
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index dad56ef..fae0aaf 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -170,6 +170,9 @@ struct mem_cgroup {
unsigned long low;
unsigned long high;
+ /* Range enforcement for interrupt charges */
+ struct work_struct high_work;
+
unsigned long soft_limit;
/* vmpressure notifications */
@@ -679,7 +682,7 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
#endif /* CONFIG_CGROUP_WRITEBACK */
-#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
+#ifdef CONFIG_INET
struct sock;
extern struct static_key memcg_sockets_enabled_key;
#define mem_cgroup_sockets_enabled static_key_false(&memcg_sockets_enabled_key)
@@ -689,11 +692,15 @@ bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages);
void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages);
static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg)
{
+#ifdef CONFIG_MEMCG_KMEM
return memcg->tcp_mem.memory_pressure;
+#else
+ return false;
+#endif
}
#else
#define mem_cgroup_sockets_enabled 0
-#endif /* CONFIG_INET && CONFIG_MEMCG_KMEM */
+#endif /* CONFIG_INET */
#ifdef CONFIG_MEMCG_KMEM
extern struct static_key memcg_kmem_enabled_key;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index ed030b5..59555b0 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -80,6 +80,9 @@ struct mem_cgroup *root_mem_cgroup __read_mostly;
#define MEM_CGROUP_RECLAIM_RETRIES 5
+/* Socket memory accounting disabled? */
+static bool cgroup_memory_nosocket;
+
/* Whether the swap controller is active */
#ifdef CONFIG_MEMCG_SWAP
int do_swap_account __read_mostly;
@@ -1923,6 +1926,26 @@ static int memcg_cpu_hotplug_callback(struct notifier_block *nb,
return NOTIFY_OK;
}
+static void reclaim_high(struct mem_cgroup *memcg,
+ unsigned int nr_pages,
+ gfp_t gfp_mask)
+{
+ do {
+ if (page_counter_read(&memcg->memory) <= memcg->high)
+ continue;
+ mem_cgroup_events(memcg, MEMCG_HIGH, 1);
+ try_to_free_mem_cgroup_pages(memcg, nr_pages, gfp_mask, true);
+ } while ((memcg = parent_mem_cgroup(memcg)));
+}
+
+static void high_work_func(struct work_struct *work)
+{
+ struct mem_cgroup *memcg;
+
+ memcg = container_of(work, struct mem_cgroup, high_work);
+ reclaim_high(memcg, CHARGE_BATCH, GFP_KERNEL);
+}
+
/*
* Scheduled by try_charge() to be executed from the userland return path
* and reclaims memory over the high limit.
@@ -1930,20 +1953,13 @@ static int memcg_cpu_hotplug_callback(struct notifier_block *nb,
void mem_cgroup_handle_over_high(void)
{
unsigned int nr_pages = current->memcg_nr_pages_over_high;
- struct mem_cgroup *memcg, *pos;
+ struct mem_cgroup *memcg;
if (likely(!nr_pages))
return;
- pos = memcg = get_mem_cgroup_from_mm(current->mm);
-
- do {
- if (page_counter_read(&pos->memory) <= pos->high)
- continue;
- mem_cgroup_events(pos, MEMCG_HIGH, 1);
- try_to_free_mem_cgroup_pages(pos, nr_pages, GFP_KERNEL, true);
- } while ((pos = parent_mem_cgroup(pos)));
-
+ memcg = get_mem_cgroup_from_mm(current->mm);
+ reclaim_high(memcg, nr_pages, GFP_KERNEL);
css_put(&memcg->css);
current->memcg_nr_pages_over_high = 0;
}
@@ -2078,6 +2094,11 @@ done_restock:
*/
do {
if (page_counter_read(&memcg->memory) > memcg->high) {
+ /* Don't bother a random interrupted task */
+ if (in_interrupt()) {
+ schedule_work(&memcg->high_work);
+ break;
+ }
current->memcg_nr_pages_over_high += batch;
set_notify_resume(current);
break;
@@ -4126,6 +4147,8 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
{
int node;
+ cancel_work_sync(&memcg->high_work);
+
mem_cgroup_remove_from_trees(memcg);
for_each_node(node)
@@ -4172,6 +4195,7 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
page_counter_init(&memcg->kmem, NULL);
}
+ INIT_WORK(&memcg->high_work, high_work_func);
memcg->last_scanned_node = MAX_NUMNODES;
INIT_LIST_HEAD(&memcg->oom_notify);
memcg->move_charge_at_immigrate = 0;
@@ -4243,6 +4267,11 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
if (ret)
return ret;
+#ifdef CONFIG_INET
+ if (cgroup_subsys_on_dfl(memory_cgrp_subsys) && !cgroup_memory_nosocket)
+ static_key_slow_inc(&memcg_sockets_enabled_key);
+#endif
+
/*
* Make sure the memcg is initialized: mem_cgroup_iter()
* orders reading memcg->initialized against its callers
@@ -4282,6 +4311,10 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css)
struct mem_cgroup *memcg = mem_cgroup_from_css(css);
memcg_destroy_kmem(memcg);
+#ifdef CONFIG_INET
+ if (cgroup_subsys_on_dfl(memory_cgrp_subsys) && !cgroup_memory_nosocket)
+ static_key_slow_dec(&memcg_sockets_enabled_key);
+#endif
__mem_cgroup_free(memcg);
}
@@ -5470,8 +5503,7 @@ void mem_cgroup_replace_page(struct page *oldpage, struct page *newpage)
commit_charge(newpage, memcg, true);
}
-/* Writing them here to avoid exposing memcg's inner layout */
-#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
+#ifdef CONFIG_INET
struct static_key memcg_sockets_enabled_key;
EXPORT_SYMBOL(memcg_sockets_enabled_key);
@@ -5496,10 +5528,15 @@ void sock_update_memcg(struct sock *sk)
rcu_read_lock();
memcg = mem_cgroup_from_task(current);
- if (memcg != root_mem_cgroup &&
- memcg->tcp_mem.active &&
- css_tryget_online(&memcg->css))
+ if (memcg == root_mem_cgroup)
+ goto out;
+#ifdef CONFIG_MEMCG_KMEM
+ if (!cgroup_subsys_on_dfl(memory_cgrp_subsys) && !memcg->tcp_mem.active)
+ goto out;
+#endif
+ if (css_tryget_online(&memcg->css))
sk->sk_memcg = memcg;
+out:
rcu_read_unlock();
}
EXPORT_SYMBOL(sock_update_memcg);
@@ -5520,15 +5557,30 @@ void sock_release_memcg(struct sock *sk)
*/
bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
{
- struct page_counter *counter;
+ gfp_t gfp_mask = GFP_KERNEL;
- if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
- nr_pages, &counter)) {
- memcg->tcp_mem.memory_pressure = 0;
- return true;
+#ifdef CONFIG_MEMCG_KMEM
+ if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) {
+ struct page_counter *counter;
+
+ if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
+ nr_pages, &counter)) {
+ memcg->tcp_mem.memory_pressure = 0;
+ return true;
+ }
+ page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
+ memcg->tcp_mem.memory_pressure = 1;
+ return false;
}
- page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
- memcg->tcp_mem.memory_pressure = 1;
+#endif
+ /* Don't block in the packet receive path */
+ if (in_softirq())
+ gfp_mask = GFP_NOWAIT;
+
+ if (try_charge(memcg, gfp_mask, nr_pages) == 0)
+ return true;
+
+ try_charge(memcg, gfp_mask|__GFP_NOFAIL, nr_pages);
return false;
}
@@ -5539,10 +5591,32 @@ bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
*/
void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
{
- page_counter_uncharge(&memcg->tcp_mem.memory_allocated, nr_pages);
+#ifdef CONFIG_MEMCG_KMEM
+ if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) {
+ page_counter_uncharge(&memcg->tcp_mem.memory_allocated,
+ nr_pages);
+ return;
+ }
+#endif
+ page_counter_uncharge(&memcg->memory, nr_pages);
+ css_put_many(&memcg->css, nr_pages);
}
-#endif
+#endif /* CONFIG_INET */
+
+static int __init cgroup_memory(char *s)
+{
+ char *token;
+
+ while ((token = strsep(&s, ",")) != NULL) {
+ if (!*token)
+ continue;
+ if (!strcmp(token, "nosocket"))
+ cgroup_memory_nosocket = true;
+ }
+ return 0;
+}
+__setup("cgroup.memory=", cgroup_memory);
/*
* subsys_initcall() for memory controller.
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2015-11-25 17:40 +0100 |
| Subject | Re: [PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller |
| Message-ID | <qyLgR-jU-17@gated-at.bofh.it> |
| In reply to | #1276787 |
From: Johannes Weiner <hannes@cmpxchg.org> Date: Tue, 24 Nov 2015 16:58:44 -0500 > Socket memory can be a significant share of overall memory consumed by > common workloads. In order to provide reasonable resource isolation in > the unified hierarchy, this type of memory needs to be included in the > tracking/accounting of a cgroup under active memory resource control. > > Overhead is only incurred when a non-root control group is created AND > the memory controller is instructed to track and account the memory > footprint of that group. cgroup.memory=nosocket can be specified on > the boot commandline to override any runtime configuration and > forcibly exclude socket memory from active memory resource control. > > Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: David S. Miller <davem@davemloft.net> -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Vladimir Davydov <vdavydov@virtuozzo.com> |
|---|---|
| Date | 2015-11-30 12:00 +0100 |
| Subject | Re: [PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller |
| Message-ID | <qAulA-2t9-9@gated-at.bofh.it> |
| In reply to | #1276787 |
On Tue, Nov 24, 2015 at 04:58:44PM -0500, Johannes Weiner wrote:
...
> @@ -5520,15 +5557,30 @@ void sock_release_memcg(struct sock *sk)
> */
> bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
> {
> - struct page_counter *counter;
> + gfp_t gfp_mask = GFP_KERNEL;
>
> - if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
> - nr_pages, &counter)) {
> - memcg->tcp_mem.memory_pressure = 0;
> - return true;
> +#ifdef CONFIG_MEMCG_KMEM
> + if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) {
> + struct page_counter *counter;
> +
> + if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
> + nr_pages, &counter)) {
> + memcg->tcp_mem.memory_pressure = 0;
> + return true;
> + }
> + page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
> + memcg->tcp_mem.memory_pressure = 1;
> + return false;
> }
> - page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
> - memcg->tcp_mem.memory_pressure = 1;
> +#endif
> + /* Don't block in the packet receive path */
> + if (in_softirq())
> + gfp_mask = GFP_NOWAIT;
> +
> + if (try_charge(memcg, gfp_mask, nr_pages) == 0)
> + return true;
> +
> + try_charge(memcg, gfp_mask|__GFP_NOFAIL, nr_pages);
We won't trigger high reclaim if we get here, because try_charge does
not check high threshold if failing or forcing charge. I think this
should be fixed regardless of this patch. The fix is attached below.
Also, I don't like calling try_charge twice: the second time will go
through all the try_charge steps for nothing. What about checking
page_counter value after calling try_charge instead:
try_charge(memcg, gfp_mask|__GFP_NOFAIL, nr_pages);
return page_counter_read(&memcg->memory) <= memcg->memory.limit;
or adding an out parameter to try_charge that would inform us if charge
was forced?
> return false;
> }
>
> @@ -5539,10 +5591,32 @@ bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
> */
> void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
> {
> - page_counter_uncharge(&memcg->tcp_mem.memory_allocated, nr_pages);
> +#ifdef CONFIG_MEMCG_KMEM
> + if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) {
> + page_counter_uncharge(&memcg->tcp_mem.memory_allocated,
> + nr_pages);
> + return;
> + }
> +#endif
> + page_counter_uncharge(&memcg->memory, nr_pages);
> + css_put_many(&memcg->css, nr_pages);
cancel_charge(memcg, nr_pages);
?
---
From: Vladimir Davydov <vdavydov@virtuozzo.com>
Subject: [PATCH] memcg: check high threshold if forcing allocation
try_charge() does not result in checking high threshold if it forces
charge. This is incorrect, because we could have failed to reclaim
memory due to the current context, so we do need to check high threshold
and try to compensate for the excess once we are in the safe context.
Signed-off-by: Vladimir Davydov <vdavydov@virtuozzo.com>
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 79a29d564bff..e922965b572b 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2112,13 +2112,14 @@ static int try_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
page_counter_charge(&memcg->memsw, nr_pages);
css_get_many(&memcg->css, nr_pages);
- return 0;
+ goto check_high;
done_restock:
css_get_many(&memcg->css, batch);
if (batch > nr_pages)
refill_stock(memcg, batch - nr_pages);
+check_high:
/*
* If the hierarchy is above the normal consumption range, schedule
* reclaim on returning to userland. We can perform reclaim here
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-30 16:30 +0100 |
| Subject | Re: [PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller |
| Message-ID | <qAyyS-5lO-13@gated-at.bofh.it> |
| In reply to | #1279768 |
On Mon, Nov 30, 2015 at 01:54:21PM +0300, Vladimir Davydov wrote:
> On Tue, Nov 24, 2015 at 04:58:44PM -0500, Johannes Weiner wrote:
> ...
> > @@ -5520,15 +5557,30 @@ void sock_release_memcg(struct sock *sk)
> > */
> > bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
> > {
> > - struct page_counter *counter;
> > + gfp_t gfp_mask = GFP_KERNEL;
> >
> > - if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
> > - nr_pages, &counter)) {
> > - memcg->tcp_mem.memory_pressure = 0;
> > - return true;
> > +#ifdef CONFIG_MEMCG_KMEM
> > + if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) {
> > + struct page_counter *counter;
> > +
> > + if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
> > + nr_pages, &counter)) {
> > + memcg->tcp_mem.memory_pressure = 0;
> > + return true;
> > + }
> > + page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
> > + memcg->tcp_mem.memory_pressure = 1;
> > + return false;
> > }
> > - page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
> > - memcg->tcp_mem.memory_pressure = 1;
> > +#endif
> > + /* Don't block in the packet receive path */
> > + if (in_softirq())
> > + gfp_mask = GFP_NOWAIT;
> > +
> > + if (try_charge(memcg, gfp_mask, nr_pages) == 0)
> > + return true;
> > +
> > + try_charge(memcg, gfp_mask|__GFP_NOFAIL, nr_pages);
>
> We won't trigger high reclaim if we get here, because try_charge does
> not check high threshold if failing or forcing charge. I think this
> should be fixed regardless of this patch. The fix is attached below.
We kind of assume that max is either set above high, or not at
all. That means when max is hit the high limit has already failed and
it's of limited use to schedule background reclaim.
> Also, I don't like calling try_charge twice: the second time will go
> through all the try_charge steps for nothing. What about checking
> page_counter value after calling try_charge instead:
>
> try_charge(memcg, gfp_mask|__GFP_NOFAIL, nr_pages);
> return page_counter_read(&memcg->memory) <= memcg->memory.limit;
>
> or adding an out parameter to try_charge that would inform us if charge
> was forced?
That's a complete cold path where we are going to drop the packet in
all but a few cases. It's not worth the trouble.
> > @@ -5539,10 +5591,32 @@ bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
> > */
> > void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
> > {
> > - page_counter_uncharge(&memcg->tcp_mem.memory_allocated, nr_pages);
> > +#ifdef CONFIG_MEMCG_KMEM
> > + if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) {
> > + page_counter_uncharge(&memcg->tcp_mem.memory_allocated,
> > + nr_pages);
> > + return;
> > + }
> > +#endif
> > + page_counter_uncharge(&memcg->memory, nr_pages);
> > + css_put_many(&memcg->css, nr_pages);
>
> cancel_charge(memcg, nr_pages);
It does the same, but it's a weird name for regular uncharging.
> From: Vladimir Davydov <vdavydov@virtuozzo.com>
> Subject: [PATCH] memcg: check high threshold if forcing allocation
>
> try_charge() does not result in checking high threshold if it forces
> charge. This is incorrect, because we could have failed to reclaim
> memory due to the current context, so we do need to check high threshold
> and try to compensate for the excess once we are in the safe context.
>
> Signed-off-by: Vladimir Davydov <vdavydov@virtuozzo.com>
>
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 79a29d564bff..e922965b572b 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2112,13 +2112,14 @@ static int try_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
> page_counter_charge(&memcg->memsw, nr_pages);
> css_get_many(&memcg->css, nr_pages);
>
> - return 0;
> + goto check_high;
>
> done_restock:
> css_get_many(&memcg->css, batch);
> if (batch > nr_pages)
> refill_stock(memcg, batch - nr_pages);
>
> +check_high:
> /*
> * If the hierarchy is above the normal consumption range, schedule
> * reclaim on returning to userland. We can perform reclaim here
One problem is that OOM victims force their charges so they can exit
quickly. It'd be contradictory to then task them with high reclaim.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Vladimir Davydov <vdavydov@virtuozzo.com> |
|---|---|
| Date | 2015-11-30 18:10 +0100 |
| Subject | Re: [PATCH 12/13] mm: memcontrol: account socket memory in unified hierarchy memory controller |
| Message-ID | <qAA7D-6si-17@gated-at.bofh.it> |
| In reply to | #1279998 |
On Mon, Nov 30, 2015 at 10:26:38AM -0500, Johannes Weiner wrote:
> On Mon, Nov 30, 2015 at 01:54:21PM +0300, Vladimir Davydov wrote:
> > On Tue, Nov 24, 2015 at 04:58:44PM -0500, Johannes Weiner wrote:
> > ...
> > > @@ -5520,15 +5557,30 @@ void sock_release_memcg(struct sock *sk)
> > > */
> > > bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
> > > {
> > > - struct page_counter *counter;
> > > + gfp_t gfp_mask = GFP_KERNEL;
> > >
> > > - if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
> > > - nr_pages, &counter)) {
> > > - memcg->tcp_mem.memory_pressure = 0;
> > > - return true;
> > > +#ifdef CONFIG_MEMCG_KMEM
> > > + if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) {
> > > + struct page_counter *counter;
> > > +
> > > + if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
> > > + nr_pages, &counter)) {
> > > + memcg->tcp_mem.memory_pressure = 0;
> > > + return true;
> > > + }
> > > + page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
> > > + memcg->tcp_mem.memory_pressure = 1;
> > > + return false;
> > > }
> > > - page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
> > > - memcg->tcp_mem.memory_pressure = 1;
> > > +#endif
> > > + /* Don't block in the packet receive path */
> > > + if (in_softirq())
> > > + gfp_mask = GFP_NOWAIT;
> > > +
> > > + if (try_charge(memcg, gfp_mask, nr_pages) == 0)
> > > + return true;
> > > +
> > > + try_charge(memcg, gfp_mask|__GFP_NOFAIL, nr_pages);
> >
> > We won't trigger high reclaim if we get here, because try_charge does
> > not check high threshold if failing or forcing charge. I think this
> > should be fixed regardless of this patch. The fix is attached below.
>
> We kind of assume that max is either set above high, or not at
> all. That means when max is hit the high limit has already failed and
> it's of limited use to schedule background reclaim.
Yeah, you're right. No point scheduling the work here - it must be
already running.
>
> > Also, I don't like calling try_charge twice: the second time will go
> > through all the try_charge steps for nothing. What about checking
> > page_counter value after calling try_charge instead:
> >
> > try_charge(memcg, gfp_mask|__GFP_NOFAIL, nr_pages);
> > return page_counter_read(&memcg->memory) <= memcg->memory.limit;
> >
> > or adding an out parameter to try_charge that would inform us if charge
> > was forced?
>
> That's a complete cold path where we are going to drop the packet in
> all but a few cases. It's not worth the trouble.
Right
>
> > > @@ -5539,10 +5591,32 @@ bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
> > > */
> > > void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
> > > {
> > > - page_counter_uncharge(&memcg->tcp_mem.memory_allocated, nr_pages);
> > > +#ifdef CONFIG_MEMCG_KMEM
> > > + if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) {
> > > + page_counter_uncharge(&memcg->tcp_mem.memory_allocated,
> > > + nr_pages);
> > > + return;
> > > + }
> > > +#endif
> > > + page_counter_uncharge(&memcg->memory, nr_pages);
> > > + css_put_many(&memcg->css, nr_pages);
> >
> > cancel_charge(memcg, nr_pages);
>
> It does the same, but it's a weird name for regular uncharging.
Right
>
> > From: Vladimir Davydov <vdavydov@virtuozzo.com>
> > Subject: [PATCH] memcg: check high threshold if forcing allocation
> >
> > try_charge() does not result in checking high threshold if it forces
> > charge. This is incorrect, because we could have failed to reclaim
> > memory due to the current context, so we do need to check high threshold
> > and try to compensate for the excess once we are in the safe context.
> >
> > Signed-off-by: Vladimir Davydov <vdavydov@virtuozzo.com>
> >
> > diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> > index 79a29d564bff..e922965b572b 100644
> > --- a/mm/memcontrol.c
> > +++ b/mm/memcontrol.c
> > @@ -2112,13 +2112,14 @@ static int try_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
> > page_counter_charge(&memcg->memsw, nr_pages);
> > css_get_many(&memcg->css, nr_pages);
> >
> > - return 0;
> > + goto check_high;
> >
> > done_restock:
> > css_get_many(&memcg->css, batch);
> > if (batch > nr_pages)
> > refill_stock(memcg, batch - nr_pages);
> >
> > +check_high:
> > /*
> > * If the hierarchy is above the normal consumption range, schedule
> > * reclaim on returning to userland. We can perform reclaim here
>
> One problem is that OOM victims force their charges so they can exit
> quickly. It'd be contradictory to then task them with high reclaim.
>
Yeah, scratch that patch. It isn't necessary anyway, because, as you
pointed out, we don't really need to schedule high reclaim when we fail
hard in mem_cgroup_charge_skmem.
No more questions left,
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
Thanks,
Vladimir
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 01/13] mm: memcontrol: export root_mem_cgroup |
| Message-ID | <qytN0-5hB-11@gated-at.bofh.it> |
| In reply to | #1276786 |
A later patch will need this symbol in files other than memcontrol.c,
so export it now and replace mem_cgroup_root_css at the same time.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Michal Hocko <mhocko@suse.com>
Acked-by: David S. Miller <davem@davemloft.net>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
---
include/linux/memcontrol.h | 3 ++-
mm/backing-dev.c | 2 +-
mm/memcontrol.c | 5 ++---
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 9d5472b..320b690 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -265,7 +265,8 @@ struct mem_cgroup {
struct mem_cgroup_per_node *nodeinfo[0];
/* WARNING: nodeinfo must be the last member here */
};
-extern struct cgroup_subsys_state *mem_cgroup_root_css;
+
+extern struct mem_cgroup *root_mem_cgroup;
/**
* mem_cgroup_events - count memory events against a cgroup
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 9160853..fdc6f4d 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -707,7 +707,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
ret = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
if (!ret) {
- bdi->wb.memcg_css = mem_cgroup_root_css;
+ bdi->wb.memcg_css = &root_mem_cgroup->css;
bdi->wb.blkcg_css = blkcg_root_css;
}
return ret;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 79a29d5..f6ea649 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -76,9 +76,9 @@
struct cgroup_subsys memory_cgrp_subsys __read_mostly;
EXPORT_SYMBOL(memory_cgrp_subsys);
+struct mem_cgroup *root_mem_cgroup __read_mostly;
+
#define MEM_CGROUP_RECLAIM_RETRIES 5
-static struct mem_cgroup *root_mem_cgroup __read_mostly;
-struct cgroup_subsys_state *mem_cgroup_root_css __read_mostly;
/* Whether the swap controller is active */
#ifdef CONFIG_MEMCG_SWAP
@@ -4217,7 +4217,6 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
/* root ? */
if (parent_css == NULL) {
root_mem_cgroup = memcg;
- mem_cgroup_root_css = &memcg->css;
page_counter_init(&memcg->memory, NULL);
memcg->high = PAGE_COUNTER_MAX;
memcg->soft_limit = PAGE_COUNTER_MAX;
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 04/13] net: tcp_memcontrol: protect all tcp_memcontrol calls by jump-label |
| Message-ID | <qytN1-5hB-15@gated-at.bofh.it> |
| In reply to | #1276786 |
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>
---
include/linux/memcontrol.h | 9 +-------
mm/memcontrol.c | 56 +++++++++++++++++++++-------------------------
net/core/sock.c | 9 ++------
net/ipv4/tcp.c | 3 ++-
net/ipv4/tcp_ipv4.c | 4 +++-
5 files changed, 33 insertions(+), 48 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 320b690..724b76a 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -697,17 +697,10 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
#endif /* CONFIG_CGROUP_WRITEBACK */
-struct sock;
#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
+struct sock;
void sock_update_memcg(struct sock *sk);
void sock_release_memcg(struct sock *sk);
-#else
-static inline void sock_update_memcg(struct sock *sk)
-{
-}
-static inline void sock_release_memcg(struct sock *sk)
-{
-}
#endif /* CONFIG_INET && CONFIG_MEMCG_KMEM */
#ifdef CONFIG_MEMCG_KMEM
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index f6ea649..0b78f82 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)
void sock_update_memcg(struct sock *sk)
{
- if (mem_cgroup_sockets_enabled) {
- struct mem_cgroup *memcg;
- struct cg_proto *cg_proto;
+ struct mem_cgroup *memcg;
+ struct cg_proto *cg_proto;
- BUG_ON(!sk->sk_prot->proto_cgroup);
+ BUG_ON(!sk->sk_prot->proto_cgroup);
- /* Socket cloning can throw us here with sk_cgrp already
- * filled. It won't however, necessarily happen from
- * process context. So the test for root memcg given
- * the current task's memcg won't help us in this case.
- *
- * Respecting the original socket's memcg is a better
- * decision in this case.
- */
- if (sk->sk_cgrp) {
- BUG_ON(mem_cgroup_is_root(sk->sk_cgrp->memcg));
- css_get(&sk->sk_cgrp->memcg->css);
- return;
- }
+ /* Socket cloning can throw us here with sk_cgrp already
+ * filled. It won't however, necessarily happen from
+ * process context. So the test for root memcg given
+ * the current task's memcg won't help us in this case.
+ *
+ * Respecting the original socket's memcg is a better
+ * decision in this case.
+ */
+ if (sk->sk_cgrp) {
+ BUG_ON(mem_cgroup_is_root(sk->sk_cgrp->memcg));
+ css_get(&sk->sk_cgrp->memcg->css);
+ return;
+ }
- rcu_read_lock();
- memcg = mem_cgroup_from_task(current);
- cg_proto = sk->sk_prot->proto_cgroup(memcg);
- if (cg_proto && cg_proto->active &&
- css_tryget_online(&memcg->css)) {
- sk->sk_cgrp = cg_proto;
- }
- rcu_read_unlock();
+ rcu_read_lock();
+ memcg = mem_cgroup_from_task(current);
+ cg_proto = sk->sk_prot->proto_cgroup(memcg);
+ if (cg_proto && cg_proto->active &&
+ css_tryget_online(&memcg->css)) {
+ sk->sk_cgrp = cg_proto;
}
+ rcu_read_unlock();
}
EXPORT_SYMBOL(sock_update_memcg);
void sock_release_memcg(struct sock *sk)
{
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
- struct mem_cgroup *memcg;
- WARN_ON(!sk->sk_cgrp->memcg);
- memcg = sk->sk_cgrp->memcg;
- css_put(&sk->sk_cgrp->memcg->css);
- }
+ WARN_ON(!sk->sk_cgrp->memcg);
+ css_put(&sk->sk_cgrp->memcg->css);
}
struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg)
diff --git a/net/core/sock.c b/net/core/sock.c
index 1e4dd54..04e54bc 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1488,12 +1488,6 @@ void sk_free(struct sock *sk)
}
EXPORT_SYMBOL(sk_free);
-static void sk_update_clone(const struct sock *sk, struct sock *newsk)
-{
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- sock_update_memcg(newsk);
-}
-
/**
* sk_clone_lock - clone a socket, and lock its clone
* @sk: the socket to clone
@@ -1589,7 +1583,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
sk_set_socket(newsk, NULL);
newsk->sk_wq = NULL;
- sk_update_clone(sk, newsk);
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ sock_update_memcg(newsk);
if (newsk->sk_prot->sockets_allocated)
sk_sockets_allocated_inc(newsk);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c172877..f166c28 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -422,7 +422,8 @@ void tcp_init_sock(struct sock *sk)
sk->sk_rcvbuf = sysctl_tcp_rmem[1];
local_bh_disable();
- sock_update_memcg(sk);
+ if (mem_cgroup_sockets_enabled)
+ sock_update_memcg(sk);
sk_sockets_allocated_inc(sk);
local_bh_enable();
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index db00343..4027e02 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1813,7 +1813,9 @@ void tcp_v4_destroy_sock(struct sock *sk)
tcp_saved_syn_free(tp);
sk_sockets_allocated_dec(sk);
- sock_release_memcg(sk);
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ sock_release_memcg(sk);
}
EXPORT_SYMBOL(tcp_v4_destroy_sock);
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 02/13] net: tcp_memcontrol: properly detect ancestor socket pressure |
| Message-ID | <qytN1-5hB-27@gated-at.bofh.it> |
| In reply to | #1276786 |
When charging socket memory, the code currently checks only the local
page counter for excess to determine whether the memcg is under socket
pressure. But even if the local counter is fine, one of the ancestors
could have breached its limit, which should also force this child to
enter socket pressure. This currently doesn't happen.
Fix this by using page_counter_try_charge() first. If that fails, it
means that either the local counter or one of the ancestors are in
excess of their limit, and the child should enter socket pressure.
Fixes: 3e32cb2e0a12 ("mm: memcontrol: lockless page counters")
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: David S. Miller <davem@davemloft.net>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
---
include/net/sock.h | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 7f89e4b..8133c71 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1190,11 +1190,13 @@ static inline void memcg_memory_allocated_add(struct cg_proto *prot,
unsigned long amt,
int *parent_status)
{
- page_counter_charge(&prot->memory_allocated, amt);
+ struct page_counter *counter;
+
+ if (page_counter_try_charge(&prot->memory_allocated, amt, &counter))
+ return;
- if (page_counter_read(&prot->memory_allocated) >
- prot->memory_allocated.limit)
- *parent_status = OVER_LIMIT;
+ page_counter_charge(&prot->memory_allocated, amt);
+ *parent_status = OVER_LIMIT;
}
static inline void memcg_memory_allocated_sub(struct cg_proto *prot,
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 06/13] net: tcp_memcontrol: simplify the per-memcg limit access |
| Message-ID | <qytN1-5hB-35@gated-at.bofh.it> |
| In reply to | #1276786 |
tcp_memcontrol replicates the global sysctl_mem limit array per
cgroup, but it only ever sets these entries to the value of the
memory_allocated page_counter limit. Use the latter directly.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
---
include/linux/memcontrol.h | 1 -
include/net/sock.h | 8 +++++---
net/ipv4/tcp_memcontrol.c | 8 --------
3 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index cc45407..1a658be 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -89,7 +89,6 @@ struct cg_proto {
struct page_counter memory_allocated; /* Current allocated memory. */
int memory_pressure;
bool active;
- long sysctl_mem[3];
/*
* memcg field is used to find which memcg we belong directly
* Each memcg struct can hold more than one cg_proto, so container_of
diff --git a/include/net/sock.h b/include/net/sock.h
index 7afbdab..0b333c2 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1159,10 +1159,12 @@ static inline void sk_enter_memory_pressure(struct sock *sk)
static inline long sk_prot_mem_limits(const struct sock *sk, int index)
{
- long *prot = sk->sk_prot->sysctl_mem;
+ long limit = sk->sk_prot->sysctl_mem[index];
+
if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- prot = sk->sk_cgrp->sysctl_mem;
- return prot[index];
+ limit = min_t(long, limit, sk->sk_cgrp->memory_allocated.limit);
+
+ return limit;
}
static inline void memcg_memory_allocated_add(struct cg_proto *prot,
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
index 6759e0d..ef4268d 100644
--- a/net/ipv4/tcp_memcontrol.c
+++ b/net/ipv4/tcp_memcontrol.c
@@ -21,9 +21,6 @@ int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
if (!cg_proto)
return 0;
- cg_proto->sysctl_mem[0] = sysctl_tcp_mem[0];
- cg_proto->sysctl_mem[1] = sysctl_tcp_mem[1];
- cg_proto->sysctl_mem[2] = sysctl_tcp_mem[2];
cg_proto->memory_pressure = 0;
cg_proto->memcg = memcg;
@@ -54,7 +51,6 @@ EXPORT_SYMBOL(tcp_destroy_cgroup);
static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
{
struct cg_proto *cg_proto;
- int i;
int ret;
cg_proto = tcp_prot.proto_cgroup(memcg);
@@ -65,10 +61,6 @@ static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
if (ret)
return ret;
- for (i = 0; i < 3; i++)
- cg_proto->sysctl_mem[i] = min_t(long, nr_pages,
- sysctl_tcp_mem[i]);
-
if (!cg_proto->active) {
/*
* The active flag needs to be written after the static_key
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2015-11-25 17:30 +0100 |
| Subject | Re: [PATCH 06/13] net: tcp_memcontrol: simplify the per-memcg limit access |
| Message-ID | <qyL7d-gt-43@gated-at.bofh.it> |
| In reply to | #1276796 |
From: Johannes Weiner <hannes@cmpxchg.org> Date: Tue, 24 Nov 2015 16:51:58 -0500 > tcp_memcontrol replicates the global sysctl_mem limit array per > cgroup, but it only ever sets these entries to the value of the > memory_allocated page_counter limit. Use the latter directly. > > Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> > Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com> Acked-by: David S. Miller <davem@davemloft.net> -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 07/13] net: tcp_memcontrol: sanitize tcp memory accounting callbacks |
| Message-ID | <qytN2-5hB-39@gated-at.bofh.it> |
| In reply to | #1276786 |
There won't be a tcp control soft limit, so integrating the memcg code
into the global skmem limiting scheme complicates things
unnecessarily. Replace this with simple and clear charge and uncharge
calls--hidden behind a jump label--to account skb memory.
Note that this is not purely aesthetic: as a result of shoehorning the
per-memcg code into the same memory accounting functions that handle
the global level, the old code would compare the per-memcg consumption
against the smaller of the per-memcg limit and the global limit. This
allowed the total consumption of multiple sockets to exceed the global
limit, as long as the individual sockets stayed within bounds. After
this change, the code will always compare the per-memcg consumption to
the per-memcg limit, and the global consumption to the global limit,
and thus close this loophole.
Without a soft limit, the per-memcg memory pressure state in sockets
is generally questionable. However, we did it until now, so we
continue to enter it when the hard limit is hit, and packets are
dropped, to let other sockets in the cgroup know that they shouldn't
grow their transmit windows, either. However, keep it simple in the
new callback model and leave memory pressure lazily when the next
packet is accepted (as opposed to doing it synchroneously when packets
are processed). When packets are dropped, network performance will
already be in the toilet, so that should be a reasonable trade-off.
As described above, consumption is now checked on the per-memcg level
and the global level separately. Likewise, memory pressure states are
maintained on both the per-memcg level and the global level, and a
socket is considered under pressure when either level asserts as much.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
---
include/linux/memcontrol.h | 12 ++++-----
include/net/sock.h | 64 ++++++----------------------------------------
include/net/tcp.h | 5 ++--
mm/memcontrol.c | 32 +++++++++++++++++++++++
net/core/sock.c | 26 +++++++++++--------
net/ipv4/tcp_output.c | 7 +++--
6 files changed, 70 insertions(+), 76 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 1a658be..4d80021 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -664,12 +664,6 @@ void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
}
#endif /* CONFIG_MEMCG */
-enum {
- UNDER_LIMIT,
- SOFT_LIMIT,
- OVER_LIMIT,
-};
-
#ifdef CONFIG_CGROUP_WRITEBACK
struct list_head *mem_cgroup_cgwb_list(struct mem_cgroup *memcg);
@@ -699,6 +693,12 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
struct sock;
void sock_update_memcg(struct sock *sk);
void sock_release_memcg(struct sock *sk);
+bool mem_cgroup_charge_skmem(struct cg_proto *proto, unsigned int nr_pages);
+void mem_cgroup_uncharge_skmem(struct cg_proto *proto, unsigned int nr_pages);
+static inline bool mem_cgroup_under_socket_pressure(struct cg_proto *proto)
+{
+ return proto->memory_pressure;
+}
#endif /* CONFIG_INET && CONFIG_MEMCG_KMEM */
#ifdef CONFIG_MEMCG_KMEM
diff --git a/include/net/sock.h b/include/net/sock.h
index 0b333c2..888aa3f 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1126,8 +1126,9 @@ static inline bool sk_under_memory_pressure(const struct sock *sk)
if (!sk->sk_prot->memory_pressure)
return false;
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- return !!sk->sk_cgrp->memory_pressure;
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp &&
+ mem_cgroup_under_socket_pressure(sk->sk_cgrp))
+ return true;
return !!*sk->sk_prot->memory_pressure;
}
@@ -1141,9 +1142,6 @@ static inline void sk_leave_memory_pressure(struct sock *sk)
if (*memory_pressure)
*memory_pressure = 0;
-
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- sk->sk_cgrp->memory_pressure = 0;
}
static inline void sk_enter_memory_pressure(struct sock *sk)
@@ -1151,76 +1149,30 @@ static inline void sk_enter_memory_pressure(struct sock *sk)
if (!sk->sk_prot->enter_memory_pressure)
return;
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- sk->sk_cgrp->memory_pressure = 1;
-
sk->sk_prot->enter_memory_pressure(sk);
}
static inline long sk_prot_mem_limits(const struct sock *sk, int index)
{
- long limit = sk->sk_prot->sysctl_mem[index];
-
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- limit = min_t(long, limit, sk->sk_cgrp->memory_allocated.limit);
-
- return limit;
-}
-
-static inline void memcg_memory_allocated_add(struct cg_proto *prot,
- unsigned long amt,
- int *parent_status)
-{
- struct page_counter *counter;
-
- if (page_counter_try_charge(&prot->memory_allocated, amt, &counter))
- return;
-
- page_counter_charge(&prot->memory_allocated, amt);
- *parent_status = OVER_LIMIT;
-}
-
-static inline void memcg_memory_allocated_sub(struct cg_proto *prot,
- unsigned long amt)
-{
- page_counter_uncharge(&prot->memory_allocated, amt);
+ return sk->sk_prot->sysctl_mem[index];
}
static inline long
sk_memory_allocated(const struct sock *sk)
{
- struct proto *prot = sk->sk_prot;
-
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- return page_counter_read(&sk->sk_cgrp->memory_allocated);
-
- return atomic_long_read(prot->memory_allocated);
+ return atomic_long_read(sk->sk_prot->memory_allocated);
}
static inline long
-sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status)
+sk_memory_allocated_add(struct sock *sk, int amt)
{
- struct proto *prot = sk->sk_prot;
-
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
- memcg_memory_allocated_add(sk->sk_cgrp, amt, parent_status);
- /* update the root cgroup regardless */
- atomic_long_add_return(amt, prot->memory_allocated);
- return page_counter_read(&sk->sk_cgrp->memory_allocated);
- }
-
- return atomic_long_add_return(amt, prot->memory_allocated);
+ return atomic_long_add_return(amt, sk->sk_prot->memory_allocated);
}
static inline void
sk_memory_allocated_sub(struct sock *sk, int amt)
{
- struct proto *prot = sk->sk_prot;
-
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- memcg_memory_allocated_sub(sk->sk_cgrp, amt);
-
- atomic_long_sub(amt, prot->memory_allocated);
+ atomic_long_sub(amt, sk->sk_prot->memory_allocated);
}
static inline void sk_sockets_allocated_dec(struct sock *sk)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index f80e74c..04517d6 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -292,8 +292,9 @@ extern int tcp_memory_pressure;
/* optimized version of sk_under_memory_pressure() for TCP sockets */
static inline bool tcp_under_memory_pressure(const struct sock *sk)
{
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- return !!sk->sk_cgrp->memory_pressure;
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp &&
+ mem_cgroup_under_socket_pressure(sk->sk_cgrp))
+ return true;
return tcp_memory_pressure;
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 0b78f82..4b586ea 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -338,6 +338,38 @@ struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg)
}
EXPORT_SYMBOL(tcp_proto_cgroup);
+/**
+ * mem_cgroup_charge_skmem - charge socket memory
+ * @proto: proto to charge
+ * @nr_pages: number of pages to charge
+ *
+ * Charges @nr_pages to @proto. Returns %true if the charge fit within
+ * @proto's configured limit, %false if the charge had to be forced.
+ */
+bool mem_cgroup_charge_skmem(struct cg_proto *proto, unsigned int nr_pages)
+{
+ struct page_counter *counter;
+
+ if (page_counter_try_charge(&proto->memory_allocated,
+ nr_pages, &counter)) {
+ proto->memory_pressure = 0;
+ return true;
+ }
+ page_counter_charge(&proto->memory_allocated, nr_pages);
+ proto->memory_pressure = 1;
+ return false;
+}
+
+/**
+ * mem_cgroup_uncharge_skmem - uncharge socket memory
+ * @proto - proto to uncharge
+ * @nr_pages - number of pages to uncharge
+ */
+void mem_cgroup_uncharge_skmem(struct cg_proto *proto, unsigned int nr_pages)
+{
+ page_counter_uncharge(&proto->memory_allocated, nr_pages);
+}
+
#endif
#ifdef CONFIG_MEMCG_KMEM
diff --git a/net/core/sock.c b/net/core/sock.c
index 04e54bc..5b1b96f 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2066,27 +2066,27 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind)
struct proto *prot = sk->sk_prot;
int amt = sk_mem_pages(size);
long allocated;
- int parent_status = UNDER_LIMIT;
sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
- allocated = sk_memory_allocated_add(sk, amt, &parent_status);
+ allocated = sk_memory_allocated_add(sk, amt);
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp &&
+ !mem_cgroup_charge_skmem(sk->sk_cgrp, amt))
+ goto suppress_allocation;
/* Under limit. */
- if (parent_status == UNDER_LIMIT &&
- allocated <= sk_prot_mem_limits(sk, 0)) {
+ if (allocated <= sk_prot_mem_limits(sk, 0)) {
sk_leave_memory_pressure(sk);
return 1;
}
- /* Under pressure. (we or our parents) */
- if ((parent_status > SOFT_LIMIT) ||
- allocated > sk_prot_mem_limits(sk, 1))
+ /* Under pressure. */
+ if (allocated > sk_prot_mem_limits(sk, 1))
sk_enter_memory_pressure(sk);
- /* Over hard limit (we or our parents) */
- if ((parent_status == OVER_LIMIT) ||
- (allocated > sk_prot_mem_limits(sk, 2)))
+ /* Over hard limit. */
+ if (allocated > sk_prot_mem_limits(sk, 2))
goto suppress_allocation;
/* guarantee minimum buffer size under pressure */
@@ -2135,6 +2135,9 @@ suppress_allocation:
sk_memory_allocated_sub(sk, amt);
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ mem_cgroup_uncharge_skmem(sk->sk_cgrp, amt);
+
return 0;
}
EXPORT_SYMBOL(__sk_mem_schedule);
@@ -2150,6 +2153,9 @@ void __sk_mem_reclaim(struct sock *sk, int amount)
sk_memory_allocated_sub(sk, amount);
sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ mem_cgroup_uncharge_skmem(sk->sk_cgrp, amount);
+
if (sk_under_memory_pressure(sk) &&
(sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)))
sk_leave_memory_pressure(sk);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index cb7ca56..7aa168a 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2813,13 +2813,16 @@ begin_fwd:
*/
void sk_forced_mem_schedule(struct sock *sk, int size)
{
- int amt, status;
+ int amt;
if (size <= sk->sk_forward_alloc)
return;
amt = sk_mem_pages(size);
sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
- sk_memory_allocated_add(sk, amt, &status);
+ sk_memory_allocated_add(sk, amt);
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ mem_cgroup_charge_skmem(sk->sk_cgrp, amt);
}
/* Send a FIN. The caller locks the socket for us.
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2015-11-25 17:30 +0100 |
| Subject | Re: [PATCH 07/13] net: tcp_memcontrol: sanitize tcp memory accounting callbacks |
| Message-ID | <qyL7d-gt-45@gated-at.bofh.it> |
| In reply to | #1276798 |
From: Johannes Weiner <hannes@cmpxchg.org> Date: Tue, 24 Nov 2015 16:51:59 -0500 > There won't be a tcp control soft limit, so integrating the memcg code > into the global skmem limiting scheme complicates things > unnecessarily. Replace this with simple and clear charge and uncharge > calls--hidden behind a jump label--to account skb memory. > > Note that this is not purely aesthetic: as a result of shoehorning the > per-memcg code into the same memory accounting functions that handle > the global level, the old code would compare the per-memcg consumption > against the smaller of the per-memcg limit and the global limit. This > allowed the total consumption of multiple sockets to exceed the global > limit, as long as the individual sockets stayed within bounds. After > this change, the code will always compare the per-memcg consumption to > the per-memcg limit, and the global consumption to the global limit, > and thus close this loophole. > > Without a soft limit, the per-memcg memory pressure state in sockets > is generally questionable. However, we did it until now, so we > continue to enter it when the hard limit is hit, and packets are > dropped, to let other sockets in the cgroup know that they shouldn't > grow their transmit windows, either. However, keep it simple in the > new callback model and leave memory pressure lazily when the next > packet is accepted (as opposed to doing it synchroneously when packets > are processed). When packets are dropped, network performance will > already be in the toilet, so that should be a reasonable trade-off. > > As described above, consumption is now checked on the per-memcg level > and the global level separately. Likewise, memory pressure states are > maintained on both the per-memcg level and the global level, and a > socket is considered under pressure when either level asserts as much. > > Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> > Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com> Acked-by: David S. Miller <davem@davemloft.net> -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 03/13] net: tcp_memcontrol: remove bogus hierarchy pressure propagation |
| Message-ID | <qytN2-5hB-45@gated-at.bofh.it> |
| In reply to | #1276786 |
When a cgroup currently breaches its socket memory limit, it enters
memory pressure mode for itself and its *ancestors*. This throttles
transmission in unrelated sibling and cousin subtrees that have
nothing to do with the breached limit.
On the contrary, breaching a limit should make that group and its
*children* enter memory pressure mode. But this happens already,
albeit lazily: if an ancestor limit is breached, siblings will enter
memory pressure on their own once the next packet arrives for them.
So no additional hierarchy code is needed. Remove the bogus stuff.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: David S. Miller <davem@davemloft.net>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
---
include/net/sock.h | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 8133c71..e27a8bb 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1152,14 +1152,8 @@ static inline void sk_leave_memory_pressure(struct sock *sk)
if (*memory_pressure)
*memory_pressure = 0;
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
- struct cg_proto *cg_proto = sk->sk_cgrp;
- struct proto *prot = sk->sk_prot;
-
- for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
- cg_proto->memory_pressure = 0;
- }
-
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ sk->sk_cgrp->memory_pressure = 0;
}
static inline void sk_enter_memory_pressure(struct sock *sk)
@@ -1167,13 +1161,8 @@ static inline void sk_enter_memory_pressure(struct sock *sk)
if (!sk->sk_prot->enter_memory_pressure)
return;
- if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
- struct cg_proto *cg_proto = sk->sk_cgrp;
- struct proto *prot = sk->sk_prot;
-
- for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
- cg_proto->memory_pressure = 1;
- }
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ sk->sk_cgrp->memory_pressure = 1;
sk->sk_prot->enter_memory_pressure(sk);
}
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 11/13] mm: memcontrol: move socket code for unified hierarchy accounting |
| Message-ID | <qytN2-5hB-47@gated-at.bofh.it> |
| In reply to | #1276786 |
The unified hierarchy memory controller will account socket
memory. Move the infrastructure functions accordingly.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
---
mm/memcontrol.c | 148 ++++++++++++++++++++++++++++----------------------------
1 file changed, 74 insertions(+), 74 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 6b8c0f7..ed030b5 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -294,80 +294,6 @@ static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
return mem_cgroup_from_css(css);
}
-/* Writing them here to avoid exposing memcg's inner layout */
-#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
-
-struct static_key memcg_sockets_enabled_key;
-EXPORT_SYMBOL(memcg_sockets_enabled_key);
-
-void sock_update_memcg(struct sock *sk)
-{
- struct mem_cgroup *memcg;
-
- /* Socket cloning can throw us here with sk_cgrp already
- * filled. It won't however, necessarily happen from
- * process context. So the test for root memcg given
- * the current task's memcg won't help us in this case.
- *
- * Respecting the original socket's memcg is a better
- * decision in this case.
- */
- if (sk->sk_memcg) {
- BUG_ON(mem_cgroup_is_root(sk->sk_memcg));
- css_get(&sk->sk_memcg->css);
- return;
- }
-
- rcu_read_lock();
- memcg = mem_cgroup_from_task(current);
- if (memcg != root_mem_cgroup &&
- memcg->tcp_mem.active &&
- css_tryget_online(&memcg->css))
- sk->sk_memcg = memcg;
- rcu_read_unlock();
-}
-EXPORT_SYMBOL(sock_update_memcg);
-
-void sock_release_memcg(struct sock *sk)
-{
- WARN_ON(!sk->sk_memcg);
- css_put(&sk->sk_memcg->css);
-}
-
-/**
- * mem_cgroup_charge_skmem - charge socket memory
- * @memcg: memcg to charge
- * @nr_pages: number of pages to charge
- *
- * Charges @nr_pages to @memcg. Returns %true if the charge fit within
- * @memcg's configured limit, %false if the charge had to be forced.
- */
-bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
-{
- struct page_counter *counter;
-
- if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
- nr_pages, &counter)) {
- memcg->tcp_mem.memory_pressure = 0;
- return true;
- }
- page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
- memcg->tcp_mem.memory_pressure = 1;
- return false;
-}
-
-/**
- * mem_cgroup_uncharge_skmem - uncharge socket memory
- * @memcg - memcg to uncharge
- * @nr_pages - number of pages to uncharge
- */
-void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
-{
- page_counter_uncharge(&memcg->tcp_mem.memory_allocated, nr_pages);
-}
-
-#endif
-
#ifdef CONFIG_MEMCG_KMEM
/*
* This will be the memcg's index in each cache's ->memcg_params.memcg_caches.
@@ -5544,6 +5470,80 @@ void mem_cgroup_replace_page(struct page *oldpage, struct page *newpage)
commit_charge(newpage, memcg, true);
}
+/* Writing them here to avoid exposing memcg's inner layout */
+#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
+
+struct static_key memcg_sockets_enabled_key;
+EXPORT_SYMBOL(memcg_sockets_enabled_key);
+
+void sock_update_memcg(struct sock *sk)
+{
+ struct mem_cgroup *memcg;
+
+ /* Socket cloning can throw us here with sk_cgrp already
+ * filled. It won't however, necessarily happen from
+ * process context. So the test for root memcg given
+ * the current task's memcg won't help us in this case.
+ *
+ * Respecting the original socket's memcg is a better
+ * decision in this case.
+ */
+ if (sk->sk_memcg) {
+ BUG_ON(mem_cgroup_is_root(sk->sk_memcg));
+ css_get(&sk->sk_memcg->css);
+ return;
+ }
+
+ rcu_read_lock();
+ memcg = mem_cgroup_from_task(current);
+ if (memcg != root_mem_cgroup &&
+ memcg->tcp_mem.active &&
+ css_tryget_online(&memcg->css))
+ sk->sk_memcg = memcg;
+ rcu_read_unlock();
+}
+EXPORT_SYMBOL(sock_update_memcg);
+
+void sock_release_memcg(struct sock *sk)
+{
+ WARN_ON(!sk->sk_memcg);
+ css_put(&sk->sk_memcg->css);
+}
+
+/**
+ * mem_cgroup_charge_skmem - charge socket memory
+ * @memcg: memcg to charge
+ * @nr_pages: number of pages to charge
+ *
+ * Charges @nr_pages to @memcg. Returns %true if the charge fit within
+ * @memcg's configured limit, %false if the charge had to be forced.
+ */
+bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
+{
+ struct page_counter *counter;
+
+ if (page_counter_try_charge(&memcg->tcp_mem.memory_allocated,
+ nr_pages, &counter)) {
+ memcg->tcp_mem.memory_pressure = 0;
+ return true;
+ }
+ page_counter_charge(&memcg->tcp_mem.memory_allocated, nr_pages);
+ memcg->tcp_mem.memory_pressure = 1;
+ return false;
+}
+
+/**
+ * mem_cgroup_uncharge_skmem - uncharge socket memory
+ * @memcg - memcg to uncharge
+ * @nr_pages - number of pages to uncharge
+ */
+void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
+{
+ page_counter_uncharge(&memcg->tcp_mem.memory_allocated, nr_pages);
+}
+
+#endif
+
/*
* subsys_initcall() for memory controller.
*
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2015-11-25 17:40 +0100 |
| Subject | Re: [PATCH 11/13] mm: memcontrol: move socket code for unified hierarchy accounting |
| Message-ID | <qyLgR-jU-11@gated-at.bofh.it> |
| In reply to | #1276801 |
From: Johannes Weiner <hannes@cmpxchg.org> Date: Tue, 24 Nov 2015 16:52:03 -0500 > The unified hierarchy memory controller will account socket > memory. Move the infrastructure functions accordingly. > > Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> > Acked-by: Michal Hocko <mhocko@suse.com> > Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com> Acked-by: David S. Miller <davem@davemloft.net> -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-24 23:00 +0100 |
| Subject | [PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label |
| Message-ID | <qytN2-5hB-49@gated-at.bofh.it> |
| In reply to | #1276786 |
The unified hierarchy memory controller is going to use this jump
label as well to control the networking callbacks. Move it to the
memory controller code and give it a more generic name.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
---
include/linux/memcontrol.h | 4 ++++
include/net/sock.h | 7 -------
mm/memcontrol.c | 3 +++
net/core/sock.c | 5 -----
net/ipv4/tcp_memcontrol.c | 4 ++--
5 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index d99fefe..dad56ef 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -681,6 +681,8 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
struct sock;
+extern struct static_key memcg_sockets_enabled_key;
+#define mem_cgroup_sockets_enabled static_key_false(&memcg_sockets_enabled_key)
void sock_update_memcg(struct sock *sk);
void sock_release_memcg(struct sock *sk);
bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages);
@@ -689,6 +691,8 @@ static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg)
{
return memcg->tcp_mem.memory_pressure;
}
+#else
+#define mem_cgroup_sockets_enabled 0
#endif /* CONFIG_INET && CONFIG_MEMCG_KMEM */
#ifdef CONFIG_MEMCG_KMEM
diff --git a/include/net/sock.h b/include/net/sock.h
index 1a94b85..fcc9442 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1065,13 +1065,6 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
#define sk_refcnt_debug_release(sk) do { } while (0)
#endif /* SOCK_REFCNT_DEBUG */
-#if defined(CONFIG_MEMCG_KMEM) && defined(CONFIG_NET)
-extern struct static_key memcg_socket_limit_enabled;
-#define mem_cgroup_sockets_enabled static_key_false(&memcg_socket_limit_enabled)
-#else
-#define mem_cgroup_sockets_enabled 0
-#endif
-
static inline bool sk_stream_memory_free(const struct sock *sk)
{
if (sk->sk_wmem_queued >= sk->sk_sndbuf)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 68d67fc..0602bee 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -291,6 +291,9 @@ static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
/* Writing them here to avoid exposing memcg's inner layout */
#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
+struct static_key memcg_sockets_enabled_key;
+EXPORT_SYMBOL(memcg_sockets_enabled_key);
+
void sock_update_memcg(struct sock *sk)
{
struct mem_cgroup *memcg;
diff --git a/net/core/sock.c b/net/core/sock.c
index 6486b0d..c5435b5 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -201,11 +201,6 @@ EXPORT_SYMBOL(sk_net_capable);
static struct lock_class_key af_family_keys[AF_MAX];
static struct lock_class_key af_family_slock_keys[AF_MAX];
-#if defined(CONFIG_MEMCG_KMEM)
-struct static_key memcg_socket_limit_enabled;
-EXPORT_SYMBOL(memcg_socket_limit_enabled);
-#endif
-
/*
* Make lock validator output more readable. (we pre-construct these
* strings build-time, so that runtime initialization of socket
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
index e507825..9a22e2d 100644
--- a/net/ipv4/tcp_memcontrol.c
+++ b/net/ipv4/tcp_memcontrol.c
@@ -34,7 +34,7 @@ void tcp_destroy_cgroup(struct mem_cgroup *memcg)
return;
if (memcg->tcp_mem.active)
- static_key_slow_dec(&memcg_socket_limit_enabled);
+ static_key_slow_dec(&memcg_sockets_enabled_key);
}
static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
@@ -65,7 +65,7 @@ static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
* because when this value change, the code to process it is not
* patched in yet.
*/
- static_key_slow_inc(&memcg_socket_limit_enabled);
+ static_key_slow_inc(&memcg_sockets_enabled_key);
memcg->tcp_mem.active = true;
}
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2015-11-25 17:30 +0100 |
| Subject | Re: [PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label |
| Message-ID | <qyL7b-gt-11@gated-at.bofh.it> |
| In reply to | #1276802 |
From: Johannes Weiner <hannes@cmpxchg.org> Date: Tue, 24 Nov 2015 16:52:01 -0500 > The unified hierarchy memory controller is going to use this jump > label as well to control the networking callbacks. Move it to the > memory controller code and give it a more generic name. > > Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> > Acked-by: Michal Hocko <mhocko@suse.com> > Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com> Acked-by: David S. Miller <davem@davemloft.net> -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Jason Baron <jbaron@akamai.com> |
|---|---|
| Date | 2015-11-30 22:10 +0100 |
| Subject | Re: [PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label |
| Message-ID | <qADRT-nK-9@gated-at.bofh.it> |
| In reply to | #1276802 |
Hi,
On 11/24/2015 04:52 PM, Johannes Weiner wrote:
> The unified hierarchy memory controller is going to use this jump
> label as well to control the networking callbacks. Move it to the
> memory controller code and give it a more generic name.
>
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> Acked-by: Michal Hocko <mhocko@suse.com>
> Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
> ---
> include/linux/memcontrol.h | 4 ++++
> include/net/sock.h | 7 -------
> mm/memcontrol.c | 3 +++
> net/core/sock.c | 5 -----
> net/ipv4/tcp_memcontrol.c | 4 ++--
> 5 files changed, 9 insertions(+), 14 deletions(-)
>
> diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
> index d99fefe..dad56ef 100644
> --- a/include/linux/memcontrol.h
> +++ b/include/linux/memcontrol.h
> @@ -681,6 +681,8 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
>
> #if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
> struct sock;
> +extern struct static_key memcg_sockets_enabled_key;
> +#define mem_cgroup_sockets_enabled static_key_false(&memcg_sockets_enabled_key)
We're trying to move to the updated API, so this should be:
static_branch_unlikely(&memcg_sockets_enabled_key)
see: include/linux/jump_label.h for details.
> void sock_update_memcg(struct sock *sk);
> void sock_release_memcg(struct sock *sk);
> bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages);
> @@ -689,6 +691,8 @@ static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg)
> {
> return memcg->tcp_mem.memory_pressure;
> }
> +#else
> +#define mem_cgroup_sockets_enabled 0
> #endif /* CONFIG_INET && CONFIG_MEMCG_KMEM */
>
> #ifdef CONFIG_MEMCG_KMEM
> diff --git a/include/net/sock.h b/include/net/sock.h
> index 1a94b85..fcc9442 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -1065,13 +1065,6 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
> #define sk_refcnt_debug_release(sk) do { } while (0)
> #endif /* SOCK_REFCNT_DEBUG */
>
> -#if defined(CONFIG_MEMCG_KMEM) && defined(CONFIG_NET)
> -extern struct static_key memcg_socket_limit_enabled;
> -#define mem_cgroup_sockets_enabled static_key_false(&memcg_socket_limit_enabled)
> -#else
> -#define mem_cgroup_sockets_enabled 0
> -#endif
> -
> static inline bool sk_stream_memory_free(const struct sock *sk)
> {
> if (sk->sk_wmem_queued >= sk->sk_sndbuf)
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 68d67fc..0602bee 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -291,6 +291,9 @@ static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
> /* Writing them here to avoid exposing memcg's inner layout */
> #if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
>
> +struct static_key memcg_sockets_enabled_key;
And this would be:
static DEFINE_STATIC_KEY_FALSE(memcg_sockets_enabled_key);
> void sock_update_memcg(struct sock *sk)
> {
> struct mem_cgroup *memcg;
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 6486b0d..c5435b5 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -201,11 +201,6 @@ EXPORT_SYMBOL(sk_net_capable);
> static struct lock_class_key af_family_keys[AF_MAX];
> static struct lock_class_key af_family_slock_keys[AF_MAX];
>
> -#if defined(CONFIG_MEMCG_KMEM)
> -struct static_key memcg_socket_limit_enabled;
> -EXPORT_SYMBOL(memcg_socket_limit_enabled);
> -#endif
> -
> /*
> * Make lock validator output more readable. (we pre-construct these
> * strings build-time, so that runtime initialization of socket
> diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
> index e507825..9a22e2d 100644
> --- a/net/ipv4/tcp_memcontrol.c
> +++ b/net/ipv4/tcp_memcontrol.c
> @@ -34,7 +34,7 @@ void tcp_destroy_cgroup(struct mem_cgroup *memcg)
> return;
>
> if (memcg->tcp_mem.active)
> - static_key_slow_dec(&memcg_socket_limit_enabled);
> + static_key_slow_dec(&memcg_sockets_enabled_key);
>
static_branch_dec(&memcg_sockets_enabled_key);
}
>
> static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
> @@ -65,7 +65,7 @@ static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
> * because when this value change, the code to process it is not
> * patched in yet.
> */
> - static_key_slow_inc(&memcg_socket_limit_enabled);
> + static_key_slow_inc(&memcg_sockets_enabled_key);
> memcg->tcp_mem.active = true;
> }
>
>
static_branch_inc(&memcg_sockets_enabled_key);
Thanks,
-Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2015-11-30 23:00 +0100 |
| Subject | Re: [PATCH 09/13] mm: memcontrol: generalize the socket accounting jump label |
| Message-ID | <qAEEi-FH-27@gated-at.bofh.it> |
| In reply to | #1280285 |
On Mon, Nov 30, 2015 at 04:08:18PM -0500, Jason Baron wrote:
> We're trying to move to the updated API, so this should be:
> static_branch_unlikely(&memcg_sockets_enabled_key)
>
> see: include/linux/jump_label.h for details.
Good point. There is another struct static_key in there as well. How
about the following on top of this series?
---
From b784aa0323628d43272e13a67ead2a2ce0e93ea6 Mon Sep 17 00:00:00 2001
From: Johannes Weiner <hannes@cmpxchg.org>
Date: Mon, 30 Nov 2015 16:41:38 -0500
Subject: [PATCH] mm: memcontrol: switch to the updated jump-label API
According to <linux/jump_label.h> the direct use of struct static_key
is deprecated. Update the socket and slab accounting code accordingly.
Reported-by: Jason Baron <jbaron@akamai.com>
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
include/linux/memcontrol.h | 8 ++++----
mm/memcontrol.c | 12 ++++++------
net/ipv4/tcp_memcontrol.c | 4 ++--
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index a8df46c..9a19590 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -704,8 +704,8 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
#ifdef CONFIG_INET
struct sock;
-extern struct static_key memcg_sockets_enabled_key;
-#define mem_cgroup_sockets_enabled static_key_false(&memcg_sockets_enabled_key)
+extern struct static_key_false memcg_sockets_enabled_key;
+#define mem_cgroup_sockets_enabled static_branch_unlikely(&memcg_sockets_enabled_key)
void sock_update_memcg(struct sock *sk);
void sock_release_memcg(struct sock *sk);
bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages);
@@ -727,7 +727,7 @@ static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg)
#endif /* CONFIG_INET */
#ifdef CONFIG_MEMCG_KMEM
-extern struct static_key memcg_kmem_enabled_key;
+extern struct static_key_false memcg_kmem_enabled_key;
extern int memcg_nr_cache_ids;
void memcg_get_cache_ids(void);
@@ -743,7 +743,7 @@ void memcg_put_cache_ids(void);
static inline bool memcg_kmem_enabled(void)
{
- return static_key_false(&memcg_kmem_enabled_key);
+ return static_branch_unlikely(&memcg_kmem_enabled_key);
}
static inline bool memcg_kmem_is_active(struct mem_cgroup *memcg)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a0da91f..5fe45d68 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -346,7 +346,7 @@ void memcg_put_cache_ids(void)
* conditional to this static branch, we'll have to allow modules that does
* kmem_cache_alloc and the such to see this symbol as well
*/
-struct static_key memcg_kmem_enabled_key;
+DEFINE_STATIC_KEY_FALSE(memcg_kmem_enabled_key);
EXPORT_SYMBOL(memcg_kmem_enabled_key);
#endif /* CONFIG_MEMCG_KMEM */
@@ -2883,7 +2883,7 @@ static int memcg_activate_kmem(struct mem_cgroup *memcg,
err = page_counter_limit(&memcg->kmem, nr_pages);
VM_BUG_ON(err);
- static_key_slow_inc(&memcg_kmem_enabled_key);
+ static_branch_inc(&memcg_kmem_enabled_key);
/*
* A memory cgroup is considered kmem-active as soon as it gets
* kmemcg_id. Setting the id after enabling static branching will
@@ -3622,7 +3622,7 @@ static void memcg_destroy_kmem(struct mem_cgroup *memcg)
{
if (memcg->kmem_acct_activated) {
memcg_destroy_kmem_caches(memcg);
- static_key_slow_dec(&memcg_kmem_enabled_key);
+ static_branch_dec(&memcg_kmem_enabled_key);
WARN_ON(page_counter_read(&memcg->kmem));
}
tcp_destroy_cgroup(memcg);
@@ -4258,7 +4258,7 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
#ifdef CONFIG_INET
if (cgroup_subsys_on_dfl(memory_cgrp_subsys) && !cgroup_memory_nosocket)
- static_key_slow_inc(&memcg_sockets_enabled_key);
+ static_branch_inc(&memcg_sockets_enabled_key);
#endif
/*
@@ -4302,7 +4302,7 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css)
memcg_destroy_kmem(memcg);
#ifdef CONFIG_INET
if (cgroup_subsys_on_dfl(memory_cgrp_subsys) && !cgroup_memory_nosocket)
- static_key_slow_dec(&memcg_sockets_enabled_key);
+ static_branch_dec(&memcg_sockets_enabled_key);
#endif
__mem_cgroup_free(memcg);
}
@@ -5494,7 +5494,7 @@ void mem_cgroup_replace_page(struct page *oldpage, struct page *newpage)
#ifdef CONFIG_INET
-struct static_key memcg_sockets_enabled_key;
+DEFINE_STATIC_KEY_FALSE(memcg_sockets_enabled_key);
EXPORT_SYMBOL(memcg_sockets_enabled_key);
void sock_update_memcg(struct sock *sk)
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
index 9a22e2d..18bc7f7 100644
--- a/net/ipv4/tcp_memcontrol.c
+++ b/net/ipv4/tcp_memcontrol.c
@@ -34,7 +34,7 @@ void tcp_destroy_cgroup(struct mem_cgroup *memcg)
return;
if (memcg->tcp_mem.active)
- static_key_slow_dec(&memcg_sockets_enabled_key);
+ static_branch_dec(&memcg_sockets_enabled_key);
}
static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
@@ -65,7 +65,7 @@ static int tcp_update_limit(struct mem_cgroup *memcg, unsigned long nr_pages)
* because when this value change, the code to process it is not
* patched in yet.
*/
- static_key_slow_inc(&memcg_sockets_enabled_key);
+ static_branch_inc(&memcg_sockets_enabled_key);
memcg->tcp_mem.active = true;
}
--
2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web