Commit 22a668d7 authored by KAMEZAWA Hiroyuki's avatar KAMEZAWA Hiroyuki Committed by Linus Torvalds

memcg: fix behavior under memory.limit equals to memsw.limit

A user can set memcg.limit_in_bytes == memcg.memsw.limit_in_bytes when the
user just want to limit the total size of applications, in other words,
not very interested in memory usage itself.  In this case, swap-out will
be done only by global-LRU.

But, under current implementation, memory.limit_in_bytes is checked at
first and try_to_free_page() may do swap-out.  But, that swap-out is
useless for memsw.limit_in_bytes and the thread may hit limit again.

This patch tries to fix the current behavior at memory.limit ==
memsw.limit case.  And documentation is updated to explain the behavior of
this special case.
Signed-off-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Cc: Balbir Singh <balbir@in.ibm.com>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Dhaval Giani <dhaval@linux.vnet.ibm.com>
Cc: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8a9478ca
...@@ -152,14 +152,19 @@ When swap is accounted, following files are added. ...@@ -152,14 +152,19 @@ When swap is accounted, following files are added.
usage of mem+swap is limited by memsw.limit_in_bytes. usage of mem+swap is limited by memsw.limit_in_bytes.
Note: why 'mem+swap' rather than swap. * why 'mem+swap' rather than swap.
The global LRU(kswapd) can swap out arbitrary pages. Swap-out means The global LRU(kswapd) can swap out arbitrary pages. Swap-out means
to move account from memory to swap...there is no change in usage of to move account from memory to swap...there is no change in usage of
mem+swap. mem+swap. In other words, when we want to limit the usage of swap without
affecting global LRU, mem+swap limit is better than just limiting swap from
In other words, when we want to limit the usage of swap without affecting OS point of view.
global LRU, mem+swap limit is better than just limiting swap from OS point
of view. * What happens when a cgroup hits memory.memsw.limit_in_bytes
When a cgroup his memory.memsw.limit_in_bytes, it's useless to do swap-out
in this cgroup. Then, swap-out will not be done by cgroup routine and file
caches are dropped. But as mentioned above, global LRU can do swapout memory
from it for sanity of the system's memory management state. You can't forbid
it by cgroup.
2.5 Reclaim 2.5 Reclaim
......
...@@ -177,6 +177,9 @@ struct mem_cgroup { ...@@ -177,6 +177,9 @@ struct mem_cgroup {
unsigned int swappiness; unsigned int swappiness;
/* set when res.limit == memsw.limit */
bool memsw_is_minimum;
/* /*
* statistics. This must be placed at the end of memcg. * statistics. This must be placed at the end of memcg.
*/ */
...@@ -847,6 +850,10 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, ...@@ -847,6 +850,10 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
int ret, total = 0; int ret, total = 0;
int loop = 0; int loop = 0;
/* If memsw_is_minimum==1, swap-out is of-no-use. */
if (root_mem->memsw_is_minimum)
noswap = true;
while (loop < 2) { while (loop < 2) {
victim = mem_cgroup_select_victim(root_mem); victim = mem_cgroup_select_victim(root_mem);
if (victim == root_mem) if (victim == root_mem)
...@@ -1752,6 +1759,12 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg, ...@@ -1752,6 +1759,12 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg,
break; break;
} }
ret = res_counter_set_limit(&memcg->res, val); ret = res_counter_set_limit(&memcg->res, val);
if (!ret) {
if (memswlimit == val)
memcg->memsw_is_minimum = true;
else
memcg->memsw_is_minimum = false;
}
mutex_unlock(&set_limit_mutex); mutex_unlock(&set_limit_mutex);
if (!ret) if (!ret)
...@@ -1799,6 +1812,12 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, ...@@ -1799,6 +1812,12 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg,
break; break;
} }
ret = res_counter_set_limit(&memcg->memsw, val); ret = res_counter_set_limit(&memcg->memsw, val);
if (!ret) {
if (memlimit == val)
memcg->memsw_is_minimum = true;
else
memcg->memsw_is_minimum = false;
}
mutex_unlock(&set_limit_mutex); mutex_unlock(&set_limit_mutex);
if (!ret) if (!ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment