aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorDaisuke Nishimura <nishimura@mxp.nes.nec.co.jp>2010-03-10 18:22:13 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-12 18:52:36 -0500
commit7dc74be032bfcaa2f9d9e4296ff5bbddfa9e2f19 (patch)
tree8bd10dcca3cfb3f4f6a0e6222c7f2048995a7d5f /mm/memcontrol.c
parentb70cc5fdb445a6929a01e9c406593265b136c99d (diff)
memcg: add interface to move charge at task migration
In current memcg, charges associated with a task aren't moved to the new cgroup at task migration. Some users feel this behavior to be strange. These patches are for this feature, that is, for charging to the new cgroup and, of course, uncharging from the old cgroup at task migration. This patch adds "memory.move_charge_at_immigrate" file, which is a flag file to determine whether charges should be moved to the new cgroup at task migration or not and what type of charges should be moved. This patch also adds read and write handlers of the file. This patch also adds no-op handlers for this feature. These handlers will be implemented in later patches. And you cannot write any values other than 0 to move_charge_at_immigrate yet. Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Cc: Balbir Singh <balbir@linux.vnet.ibm.com> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Paul Menage <menage@google.com> Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> 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.c97
1 files changed, 93 insertions, 4 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index d813823ab08f..59ffaf511d77 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -226,11 +226,26 @@ struct mem_cgroup {
226 bool memsw_is_minimum; 226 bool memsw_is_minimum;
227 227
228 /* 228 /*
229 * Should we move charges of a task when a task is moved into this
230 * mem_cgroup ? And what type of charges should we move ?
231 */
232 unsigned long move_charge_at_immigrate;
233
234 /*
229 * statistics. This must be placed at the end of memcg. 235 * statistics. This must be placed at the end of memcg.
230 */ 236 */
231 struct mem_cgroup_stat stat; 237 struct mem_cgroup_stat stat;
232}; 238};
233 239
240/* Stuffs for move charges at task migration. */
241/*
242 * Types of charges to be moved. "move_charge_at_immitgrate" is treated as a
243 * left-shifted bitmap of these types.
244 */
245enum move_type {
246 NR_MOVE_TYPE,
247};
248
234/* 249/*
235 * Maximum loops in mem_cgroup_hierarchical_reclaim(), used for soft 250 * Maximum loops in mem_cgroup_hierarchical_reclaim(), used for soft
236 * limit reclaim to prevent infinite loops, if they ever occur. 251 * limit reclaim to prevent infinite loops, if they ever occur.
@@ -2865,6 +2880,31 @@ static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
2865 return 0; 2880 return 0;
2866} 2881}
2867 2882
2883static u64 mem_cgroup_move_charge_read(struct cgroup *cgrp,
2884 struct cftype *cft)
2885{
2886 return mem_cgroup_from_cont(cgrp)->move_charge_at_immigrate;
2887}
2888
2889static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
2890 struct cftype *cft, u64 val)
2891{
2892 struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
2893
2894 if (val >= (1 << NR_MOVE_TYPE))
2895 return -EINVAL;
2896 /*
2897 * We check this value several times in both in can_attach() and
2898 * attach(), so we need cgroup lock to prevent this value from being
2899 * inconsistent.
2900 */
2901 cgroup_lock();
2902 mem->move_charge_at_immigrate = val;
2903 cgroup_unlock();
2904
2905 return 0;
2906}
2907
2868 2908
2869/* For read statistics */ 2909/* For read statistics */
2870enum { 2910enum {
@@ -3098,6 +3138,11 @@ static struct cftype mem_cgroup_files[] = {
3098 .read_u64 = mem_cgroup_swappiness_read, 3138 .read_u64 = mem_cgroup_swappiness_read,
3099 .write_u64 = mem_cgroup_swappiness_write, 3139 .write_u64 = mem_cgroup_swappiness_write,
3100 }, 3140 },
3141 {
3142 .name = "move_charge_at_immigrate",
3143 .read_u64 = mem_cgroup_move_charge_read,
3144 .write_u64 = mem_cgroup_move_charge_write,
3145 },
3101}; 3146};
3102 3147
3103#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP 3148#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
@@ -3345,6 +3390,7 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
3345 if (parent) 3390 if (parent)
3346 mem->swappiness = get_swappiness(parent); 3391 mem->swappiness = get_swappiness(parent);
3347 atomic_set(&mem->refcnt, 1); 3392 atomic_set(&mem->refcnt, 1);
3393 mem->move_charge_at_immigrate = 0;
3348 return &mem->css; 3394 return &mem->css;
3349free_out: 3395free_out:
3350 __mem_cgroup_free(mem); 3396 __mem_cgroup_free(mem);
@@ -3381,16 +3427,57 @@ static int mem_cgroup_populate(struct cgroup_subsys *ss,
3381 return ret; 3427 return ret;
3382} 3428}
3383 3429
3430/* Handlers for move charge at task migration. */
3431static int mem_cgroup_can_move_charge(void)
3432{
3433 return 0;
3434}
3435
3436static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
3437 struct cgroup *cgroup,
3438 struct task_struct *p,
3439 bool threadgroup)
3440{
3441 int ret = 0;
3442 struct mem_cgroup *mem = mem_cgroup_from_cont(cgroup);
3443
3444 if (mem->move_charge_at_immigrate) {
3445 struct mm_struct *mm;
3446 struct mem_cgroup *from = mem_cgroup_from_task(p);
3447
3448 VM_BUG_ON(from == mem);
3449
3450 mm = get_task_mm(p);
3451 if (!mm)
3452 return 0;
3453
3454 /* We move charges only when we move a owner of the mm */
3455 if (mm->owner == p)
3456 ret = mem_cgroup_can_move_charge();
3457
3458 mmput(mm);
3459 }
3460 return ret;
3461}
3462
3463static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
3464 struct cgroup *cgroup,
3465 struct task_struct *p,
3466 bool threadgroup)
3467{
3468}
3469
3470static void mem_cgroup_move_charge(void)
3471{
3472}
3473
3384static void mem_cgroup_move_task(struct cgroup_subsys *ss, 3474static void mem_cgroup_move_task(struct cgroup_subsys *ss,
3385 struct cgroup *cont, 3475 struct cgroup *cont,
3386 struct cgroup *old_cont, 3476 struct cgroup *old_cont,
3387 struct task_struct *p, 3477 struct task_struct *p,
3388 bool threadgroup) 3478 bool threadgroup)
3389{ 3479{
3390 /* 3480 mem_cgroup_move_charge();
3391 * FIXME: It's better to move charges of this process from old
3392 * memcg to new memcg. But it's just on TODO-List now.
3393 */
3394} 3481}
3395 3482
3396struct cgroup_subsys mem_cgroup_subsys = { 3483struct cgroup_subsys mem_cgroup_subsys = {
@@ -3400,6 +3487,8 @@ struct cgroup_subsys mem_cgroup_subsys = {
3400 .pre_destroy = mem_cgroup_pre_destroy, 3487 .pre_destroy = mem_cgroup_pre_destroy,
3401 .destroy = mem_cgroup_destroy, 3488 .destroy = mem_cgroup_destroy,
3402 .populate = mem_cgroup_populate, 3489 .populate = mem_cgroup_populate,
3490 .can_attach = mem_cgroup_can_attach,
3491 .cancel_attach = mem_cgroup_cancel_attach,
3403 .attach = mem_cgroup_move_task, 3492 .attach = mem_cgroup_move_task,
3404 .early_init = 0, 3493 .early_init = 0,
3405 .use_id = 1, 3494 .use_id = 1,