diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2009-06-17 19:27:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-18 16:03:48 -0400 |
commit | 22a668d7c3ef833e7d67e9cef587ecc78069d532 (patch) | |
tree | da9f2e7ea7224c347dfe33ea9d4dddd944c861ac | |
parent | 8a9478ca7f4bcb8945cec7f95d52dae2d5e50cbd (diff) |
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>
-rw-r--r-- | Documentation/cgroups/memory.txt | 17 | ||||
-rw-r--r-- | mm/memcontrol.c | 19 |
2 files changed, 30 insertions, 6 deletions
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 1a608877b14e..af48135bd9b8 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt | |||
@@ -152,14 +152,19 @@ When swap is accounted, following files are added. | |||
152 | 152 | ||
153 | usage of mem+swap is limited by memsw.limit_in_bytes. | 153 | usage of mem+swap is limited by memsw.limit_in_bytes. |
154 | 154 | ||
155 | Note: why 'mem+swap' rather than swap. | 155 | * why 'mem+swap' rather than swap. |
156 | The global LRU(kswapd) can swap out arbitrary pages. Swap-out means | 156 | The global LRU(kswapd) can swap out arbitrary pages. Swap-out means |
157 | to move account from memory to swap...there is no change in usage of | 157 | to move account from memory to swap...there is no change in usage of |
158 | mem+swap. | 158 | mem+swap. In other words, when we want to limit the usage of swap without |
159 | 159 | affecting global LRU, mem+swap limit is better than just limiting swap from | |
160 | In other words, when we want to limit the usage of swap without affecting | 160 | OS point of view. |
161 | global LRU, mem+swap limit is better than just limiting swap from OS point | 161 | |
162 | of view. | 162 | * What happens when a cgroup hits memory.memsw.limit_in_bytes |
163 | When a cgroup his memory.memsw.limit_in_bytes, it's useless to do swap-out | ||
164 | in this cgroup. Then, swap-out will not be done by cgroup routine and file | ||
165 | caches are dropped. But as mentioned above, global LRU can do swapout memory | ||
166 | from it for sanity of the system's memory management state. You can't forbid | ||
167 | it by cgroup. | ||
163 | 168 | ||
164 | 2.5 Reclaim | 169 | 2.5 Reclaim |
165 | 170 | ||
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index a83e0395444b..6ceb6f2dbac2 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -177,6 +177,9 @@ struct mem_cgroup { | |||
177 | 177 | ||
178 | unsigned int swappiness; | 178 | unsigned int swappiness; |
179 | 179 | ||
180 | /* set when res.limit == memsw.limit */ | ||
181 | bool memsw_is_minimum; | ||
182 | |||
180 | /* | 183 | /* |
181 | * statistics. This must be placed at the end of memcg. | 184 | * statistics. This must be placed at the end of memcg. |
182 | */ | 185 | */ |
@@ -847,6 +850,10 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, | |||
847 | int ret, total = 0; | 850 | int ret, total = 0; |
848 | int loop = 0; | 851 | int loop = 0; |
849 | 852 | ||
853 | /* If memsw_is_minimum==1, swap-out is of-no-use. */ | ||
854 | if (root_mem->memsw_is_minimum) | ||
855 | noswap = true; | ||
856 | |||
850 | while (loop < 2) { | 857 | while (loop < 2) { |
851 | victim = mem_cgroup_select_victim(root_mem); | 858 | victim = mem_cgroup_select_victim(root_mem); |
852 | if (victim == root_mem) | 859 | if (victim == root_mem) |
@@ -1752,6 +1759,12 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg, | |||
1752 | break; | 1759 | break; |
1753 | } | 1760 | } |
1754 | ret = res_counter_set_limit(&memcg->res, val); | 1761 | ret = res_counter_set_limit(&memcg->res, val); |
1762 | if (!ret) { | ||
1763 | if (memswlimit == val) | ||
1764 | memcg->memsw_is_minimum = true; | ||
1765 | else | ||
1766 | memcg->memsw_is_minimum = false; | ||
1767 | } | ||
1755 | mutex_unlock(&set_limit_mutex); | 1768 | mutex_unlock(&set_limit_mutex); |
1756 | 1769 | ||
1757 | if (!ret) | 1770 | if (!ret) |
@@ -1799,6 +1812,12 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, | |||
1799 | break; | 1812 | break; |
1800 | } | 1813 | } |
1801 | ret = res_counter_set_limit(&memcg->memsw, val); | 1814 | ret = res_counter_set_limit(&memcg->memsw, val); |
1815 | if (!ret) { | ||
1816 | if (memlimit == val) | ||
1817 | memcg->memsw_is_minimum = true; | ||
1818 | else | ||
1819 | memcg->memsw_is_minimum = false; | ||
1820 | } | ||
1802 | mutex_unlock(&set_limit_mutex); | 1821 | mutex_unlock(&set_limit_mutex); |
1803 | 1822 | ||
1804 | if (!ret) | 1823 | if (!ret) |