aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>2009-01-07 21:07:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-08 11:31:04 -0500
commitc1e862c1f5ad34771b6d0a528cf681e0dcad7c86 (patch)
treee3ac7ca8cfe5ac02b0df83a4aef5f37e59d7d61f /mm/memcontrol.c
parentc8dad2bb6307f5b00f804a686917105206a4d5c9 (diff)
memcg: new force_empty to free pages under group
By memcg-move-all-accounts-to-parent-at-rmdir.patch, there is no leak of memory usage and force_empty is removed. This patch adds "force_empty" again, in reasonable manner. memory.force_empty file works when #echo 0 (or some) > memory.force_empty and have following function. 1. only works when there are no task in this cgroup. 2. free all page under this cgroup as much as possible. 3. page which cannot be freed will be moved up to parent. 4. Then, memcg will be empty after above echo returns. This is much better behavior than old "force_empty" which just forget all accounts. This patch also check signal_pending() and above "echo" can be stopped by "Ctrl-C". [akpm@linux-foundation.org: cleanup] Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e00f25e6545f..decace3bb57e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1062,21 +1062,27 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *mem,
1062 * make mem_cgroup's charge to be 0 if there is no task. 1062 * make mem_cgroup's charge to be 0 if there is no task.
1063 * This enables deleting this mem_cgroup. 1063 * This enables deleting this mem_cgroup.
1064 */ 1064 */
1065static int mem_cgroup_force_empty(struct mem_cgroup *mem) 1065static int mem_cgroup_force_empty(struct mem_cgroup *mem, bool free_all)
1066{ 1066{
1067 int ret; 1067 int ret;
1068 int node, zid, shrink; 1068 int node, zid, shrink;
1069 int nr_retries = MEM_CGROUP_RECLAIM_RETRIES; 1069 int nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
1070 struct cgroup *cgrp = mem->css.cgroup;
1070 1071
1071 css_get(&mem->css); 1072 css_get(&mem->css);
1072 1073
1073 shrink = 0; 1074 shrink = 0;
1075 /* should free all ? */
1076 if (free_all)
1077 goto try_to_free;
1074move_account: 1078move_account:
1075 while (mem->res.usage > 0) { 1079 while (mem->res.usage > 0) {
1076 ret = -EBUSY; 1080 ret = -EBUSY;
1077 if (atomic_read(&mem->css.cgroup->count) > 0) 1081 if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children))
1082 goto out;
1083 ret = -EINTR;
1084 if (signal_pending(current))
1078 goto out; 1085 goto out;
1079
1080 /* This is for making all *used* pages to be on LRU. */ 1086 /* This is for making all *used* pages to be on LRU. */
1081 lru_add_drain_all(); 1087 lru_add_drain_all();
1082 ret = 0; 1088 ret = 0;
@@ -1106,19 +1112,29 @@ out:
1106 return ret; 1112 return ret;
1107 1113
1108try_to_free: 1114try_to_free:
1109 /* returns EBUSY if we come here twice. */ 1115 /* returns EBUSY if there is a task or if we come here twice. */
1110 if (shrink) { 1116 if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children) || shrink) {
1111 ret = -EBUSY; 1117 ret = -EBUSY;
1112 goto out; 1118 goto out;
1113 } 1119 }
1120 /* we call try-to-free pages for make this cgroup empty */
1121 lru_add_drain_all();
1114 /* try to free all pages in this cgroup */ 1122 /* try to free all pages in this cgroup */
1115 shrink = 1; 1123 shrink = 1;
1116 while (nr_retries && mem->res.usage > 0) { 1124 while (nr_retries && mem->res.usage > 0) {
1117 int progress; 1125 int progress;
1126
1127 if (signal_pending(current)) {
1128 ret = -EINTR;
1129 goto out;
1130 }
1118 progress = try_to_free_mem_cgroup_pages(mem, 1131 progress = try_to_free_mem_cgroup_pages(mem,
1119 GFP_HIGHUSER_MOVABLE); 1132 GFP_HIGHUSER_MOVABLE);
1120 if (!progress) 1133 if (!progress) {
1121 nr_retries--; 1134 nr_retries--;
1135 /* maybe some writeback is necessary */
1136 congestion_wait(WRITE, HZ/10);
1137 }
1122 1138
1123 } 1139 }
1124 /* try move_account...there may be some *locked* pages. */ 1140 /* try move_account...there may be some *locked* pages. */
@@ -1128,6 +1144,12 @@ try_to_free:
1128 goto out; 1144 goto out;
1129} 1145}
1130 1146
1147int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event)
1148{
1149 return mem_cgroup_force_empty(mem_cgroup_from_cont(cont), true);
1150}
1151
1152
1131static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) 1153static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
1132{ 1154{
1133 return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res, 1155 return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res,
@@ -1225,6 +1247,7 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
1225 return 0; 1247 return 0;
1226} 1248}
1227 1249
1250
1228static struct cftype mem_cgroup_files[] = { 1251static struct cftype mem_cgroup_files[] = {
1229 { 1252 {
1230 .name = "usage_in_bytes", 1253 .name = "usage_in_bytes",
@@ -1253,6 +1276,10 @@ static struct cftype mem_cgroup_files[] = {
1253 .name = "stat", 1276 .name = "stat",
1254 .read_map = mem_control_stat_show, 1277 .read_map = mem_control_stat_show,
1255 }, 1278 },
1279 {
1280 .name = "force_empty",
1281 .trigger = mem_cgroup_force_empty_write,
1282 },
1256}; 1283};
1257 1284
1258static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node) 1285static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node)
@@ -1350,7 +1377,7 @@ static void mem_cgroup_pre_destroy(struct cgroup_subsys *ss,
1350 struct cgroup *cont) 1377 struct cgroup *cont)
1351{ 1378{
1352 struct mem_cgroup *mem = mem_cgroup_from_cont(cont); 1379 struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
1353 mem_cgroup_force_empty(mem); 1380 mem_cgroup_force_empty(mem, false);
1354} 1381}
1355 1382
1356static void mem_cgroup_destroy(struct cgroup_subsys *ss, 1383static void mem_cgroup_destroy(struct cgroup_subsys *ss,