summaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorRoman Gushchin <guro@fb.com>2020-08-07 08:21:51 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2020-08-07 20:33:25 +0200
commit536d3bf261a2fc3b05b3e91e7eef7383443015cf (patch)
treec54f3f2c612eecbee68daf5d9d09f29e74abe0be /mm/memcontrol.c
parentmm: kmem: switch to static_branch_likely() in memcg_kmem_enabled() (diff)
downloadlinux-536d3bf261a2fc3b05b3e91e7eef7383443015cf.tar.xz
linux-536d3bf261a2fc3b05b3e91e7eef7383443015cf.zip
mm: memcontrol: avoid workload stalls when lowering memory.high
Memory.high limit is implemented in a way such that the kernel penalizes all threads which are allocating a memory over the limit. Forcing all threads into the synchronous reclaim and adding some artificial delays allows to slow down the memory consumption and potentially give some time for userspace oom handlers/resource control agents to react. It works nicely if the memory usage is hitting the limit from below, however it works sub-optimal if a user adjusts memory.high to a value way below the current memory usage. It basically forces all workload threads (doing any memory allocations) into the synchronous reclaim and sleep. This makes the workload completely unresponsive for a long period of time and can also lead to a system-wide contention on lru locks. It can happen even if the workload is not actually tight on memory and has, for example, a ton of cold pagecache. In the current implementation writing to memory.high causes an atomic update of page counter's high value followed by an attempt to reclaim enough memory to fit into the new limit. To fix the problem described above, all we need is to change the order of execution: try to push the memory usage under the limit first, and only then set the new high limit. Reported-by: Domas Mituzas <domas@fb.com> Signed-off-by: Roman Gushchin <guro@fb.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Shakeel Butt <shakeelb@google.com> Acked-by: Michal Hocko <mhocko@suse.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Tejun Heo <tj@kernel.org> Cc: Chris Down <chris@chrisdown.name> Link: http://lkml.kernel.org/r/20200709194718.189231-1-guro@fb.com Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a3e963366769..bb0d3ac80ade 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -6213,8 +6213,6 @@ static ssize_t memory_high_write(struct kernfs_open_file *of,
if (err)
return err;
- page_counter_set_high(&memcg->memory, high);
-
for (;;) {
unsigned long nr_pages = page_counter_read(&memcg->memory);
unsigned long reclaimed;
@@ -6238,6 +6236,8 @@ static ssize_t memory_high_write(struct kernfs_open_file *of,
break;
}
+ page_counter_set_high(&memcg->memory, high);
+
return nbytes;
}