diff options
author | Balbir Singh <balbir@linux.vnet.ibm.com> | 2008-10-16 01:01:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-16 14:21:28 -0400 |
commit | 9363b9f23c9cc36cc8ef6c05fdf879ee4a96ae92 (patch) | |
tree | 482746b06d6fdd8be606de4dff584a3a40054c4c | |
parent | 1648993fb05c487947c1cec6307aca29d8002abe (diff) |
memrlimit: cgroup mm owner callback changes to add task info
This patch adds an additional field to the mm_owner callbacks. This field
is required to get to the mm that changed. Hold mmap_sem in write mode
before calling the mm_owner_changed callback
[hugh@veritas.com: fix mmap_sem deadlock]
Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Cc: Sudhir Kumar <skumar@linux.vnet.ibm.com>
Cc: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
Cc: Paul Menage <menage@google.com>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Pavel Emelianov <xemul@openvz.org>
Cc: Balbir Singh <balbir@linux.vnet.ibm.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/cgroup.h | 3 | ||||
-rw-r--r-- | kernel/cgroup.c | 4 | ||||
-rw-r--r-- | kernel/exit.c | 9 |
3 files changed, 9 insertions, 7 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index c98dd7cb7076..30934e4bfaab 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -326,7 +326,8 @@ struct cgroup_subsys { | |||
326 | */ | 326 | */ |
327 | void (*mm_owner_changed)(struct cgroup_subsys *ss, | 327 | void (*mm_owner_changed)(struct cgroup_subsys *ss, |
328 | struct cgroup *old, | 328 | struct cgroup *old, |
329 | struct cgroup *new); | 329 | struct cgroup *new, |
330 | struct task_struct *p); | ||
330 | int subsys_id; | 331 | int subsys_id; |
331 | int active; | 332 | int active; |
332 | int disabled; | 333 | int disabled; |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index a0123d75ec9a..8c6e1c17e6d3 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2735,6 +2735,8 @@ void cgroup_fork_callbacks(struct task_struct *child) | |||
2735 | * Called on every change to mm->owner. mm_init_owner() does not | 2735 | * Called on every change to mm->owner. mm_init_owner() does not |
2736 | * invoke this routine, since it assigns the mm->owner the first time | 2736 | * invoke this routine, since it assigns the mm->owner the first time |
2737 | * and does not change it. | 2737 | * and does not change it. |
2738 | * | ||
2739 | * The callbacks are invoked with mmap_sem held in read mode. | ||
2738 | */ | 2740 | */ |
2739 | void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new) | 2741 | void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new) |
2740 | { | 2742 | { |
@@ -2750,7 +2752,7 @@ void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new) | |||
2750 | if (oldcgrp == newcgrp) | 2752 | if (oldcgrp == newcgrp) |
2751 | continue; | 2753 | continue; |
2752 | if (ss->mm_owner_changed) | 2754 | if (ss->mm_owner_changed) |
2753 | ss->mm_owner_changed(ss, oldcgrp, newcgrp); | 2755 | ss->mm_owner_changed(ss, oldcgrp, newcgrp, new); |
2754 | } | 2756 | } |
2755 | } | 2757 | } |
2756 | } | 2758 | } |
diff --git a/kernel/exit.c b/kernel/exit.c index 85a83c831856..0ef4673e351b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -640,24 +640,23 @@ retry: | |||
640 | assign_new_owner: | 640 | assign_new_owner: |
641 | BUG_ON(c == p); | 641 | BUG_ON(c == p); |
642 | get_task_struct(c); | 642 | get_task_struct(c); |
643 | read_unlock(&tasklist_lock); | ||
644 | down_write(&mm->mmap_sem); | ||
643 | /* | 645 | /* |
644 | * The task_lock protects c->mm from changing. | 646 | * The task_lock protects c->mm from changing. |
645 | * We always want mm->owner->mm == mm | 647 | * We always want mm->owner->mm == mm |
646 | */ | 648 | */ |
647 | task_lock(c); | 649 | task_lock(c); |
648 | /* | ||
649 | * Delay read_unlock() till we have the task_lock() | ||
650 | * to ensure that c does not slip away underneath us | ||
651 | */ | ||
652 | read_unlock(&tasklist_lock); | ||
653 | if (c->mm != mm) { | 650 | if (c->mm != mm) { |
654 | task_unlock(c); | 651 | task_unlock(c); |
652 | up_write(&mm->mmap_sem); | ||
655 | put_task_struct(c); | 653 | put_task_struct(c); |
656 | goto retry; | 654 | goto retry; |
657 | } | 655 | } |
658 | cgroup_mm_owner_callbacks(mm->owner, c); | 656 | cgroup_mm_owner_callbacks(mm->owner, c); |
659 | mm->owner = c; | 657 | mm->owner = c; |
660 | task_unlock(c); | 658 | task_unlock(c); |
659 | up_write(&mm->mmap_sem); | ||
661 | put_task_struct(c); | 660 | put_task_struct(c); |
662 | } | 661 | } |
663 | #endif /* CONFIG_MM_OWNER */ | 662 | #endif /* CONFIG_MM_OWNER */ |