Skip to content

Commit 1ab5c05

Browse files
aryabinintorvalds
authored andcommitted
mm/memcontrol.c: try harder to decrease [memory,memsw].limit_in_bytes
mem_cgroup_resize_[memsw]_limit() tries to free only 32 (SWAP_CLUSTER_MAX) pages on each iteration. This makes it practically impossible to decrease limit of memory cgroup. Tasks could easily allocate back 32 pages, so we can't reduce memory usage, and once retry_count reaches zero we return -EBUSY. Easy to reproduce the problem by running the following commands: mkdir /sys/fs/cgroup/memory/test echo $$ >> /sys/fs/cgroup/memory/test/tasks cat big_file > /dev/null & sleep 1 && echo $((100*1024*1024)) > /sys/fs/cgroup/memory/test/memory.limit_in_bytes -bash: echo: write error: Device or resource busy Instead of relying on retry_count, keep retrying the reclaim until the desired limit is reached or fail if the reclaim doesn't make any progress or a signal is pending. Link: http://lkml.kernel.org/r/20180119132544.19569-1-aryabinin@virtuozzo.com Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com> Acked-by: Michal Hocko <mhocko@suse.com> Reviewed-by: Andrew Morton <akpm@linux-foundation.org> Cc: Shakeel Butt <shakeelb@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Vladimir Davydov <vdavydov.dev@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 8ad6e40 commit 1ab5c05

File tree

1 file changed

+6
-36
lines changed

1 file changed

+6
-36
lines changed

mm/memcontrol.c

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,20 +1176,6 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
11761176
}
11771177
}
11781178

1179-
/*
1180-
* This function returns the number of memcg under hierarchy tree. Returns
1181-
* 1(self count) if no children.
1182-
*/
1183-
static int mem_cgroup_count_children(struct mem_cgroup *memcg)
1184-
{
1185-
int num = 0;
1186-
struct mem_cgroup *iter;
1187-
1188-
for_each_mem_cgroup_tree(iter, memcg)
1189-
num++;
1190-
return num;
1191-
}
1192-
11931179
/*
11941180
* Return the memory (and swap, if configured) limit for a memcg.
11951181
*/
@@ -2463,24 +2449,11 @@ static DEFINE_MUTEX(memcg_limit_mutex);
24632449
static int mem_cgroup_resize_limit(struct mem_cgroup *memcg,
24642450
unsigned long limit, bool memsw)
24652451
{
2466-
unsigned long curusage;
2467-
unsigned long oldusage;
24682452
bool enlarge = false;
2469-
int retry_count;
24702453
int ret;
24712454
bool limits_invariant;
24722455
struct page_counter *counter = memsw ? &memcg->memsw : &memcg->memory;
24732456

2474-
/*
2475-
* For keeping hierarchical_reclaim simple, how long we should retry
2476-
* is depends on callers. We set our retry-count to be function
2477-
* of # of children which we should visit in this loop.
2478-
*/
2479-
retry_count = MEM_CGROUP_RECLAIM_RETRIES *
2480-
mem_cgroup_count_children(memcg);
2481-
2482-
oldusage = page_counter_read(counter);
2483-
24842457
do {
24852458
if (signal_pending(current)) {
24862459
ret = -EINTR;
@@ -2507,15 +2480,12 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg,
25072480
if (!ret)
25082481
break;
25092482

2510-
try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL, !memsw);
2511-
2512-
curusage = page_counter_read(counter);
2513-
/* Usage is reduced ? */
2514-
if (curusage >= oldusage)
2515-
retry_count--;
2516-
else
2517-
oldusage = curusage;
2518-
} while (retry_count);
2483+
if (!try_to_free_mem_cgroup_pages(memcg, 1,
2484+
GFP_KERNEL, !memsw)) {
2485+
ret = -EBUSY;
2486+
break;
2487+
}
2488+
} while (true);
25192489

25202490
if (!ret && enlarge)
25212491
memcg_oom_recover(memcg);

0 commit comments

Comments
 (0)