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: KAMEZAWA 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
8a9478ca7f
commit
22a668d7c3
@ -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
|
||||||
|
OS point of view.
|
||||||
|
|
||||||
In other words, when we want to limit the usage of swap without affecting
|
* What happens when a cgroup hits memory.memsw.limit_in_bytes
|
||||||
global LRU, mem+swap limit is better than just limiting swap from OS point
|
When a cgroup his memory.memsw.limit_in_bytes, it's useless to do swap-out
|
||||||
of view.
|
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 {
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user