diff options
-rw-r--r-- | include/linux/cgroup.h | 14 | ||||
-rw-r--r-- | kernel/cgroup.c | 33 | ||||
-rw-r--r-- | kernel/exit.c | 16 |
3 files changed, 7 insertions, 56 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 1164963c3a8..08b78c09b09 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -329,13 +329,7 @@ struct cgroup_subsys { | |||
329 | struct cgroup *cgrp); | 329 | struct cgroup *cgrp); |
330 | void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cgrp); | 330 | void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cgrp); |
331 | void (*bind)(struct cgroup_subsys *ss, struct cgroup *root); | 331 | void (*bind)(struct cgroup_subsys *ss, struct cgroup *root); |
332 | /* | 332 | |
333 | * This routine is called with the task_lock of mm->owner held | ||
334 | */ | ||
335 | void (*mm_owner_changed)(struct cgroup_subsys *ss, | ||
336 | struct cgroup *old, | ||
337 | struct cgroup *new, | ||
338 | struct task_struct *p); | ||
339 | int subsys_id; | 333 | int subsys_id; |
340 | int active; | 334 | int active; |
341 | int disabled; | 335 | int disabled; |
@@ -400,9 +394,6 @@ void cgroup_iter_end(struct cgroup *cgrp, struct cgroup_iter *it); | |||
400 | int cgroup_scan_tasks(struct cgroup_scanner *scan); | 394 | int cgroup_scan_tasks(struct cgroup_scanner *scan); |
401 | int cgroup_attach_task(struct cgroup *, struct task_struct *); | 395 | int cgroup_attach_task(struct cgroup *, struct task_struct *); |
402 | 396 | ||
403 | void cgroup_mm_owner_callbacks(struct task_struct *old, | ||
404 | struct task_struct *new); | ||
405 | |||
406 | #else /* !CONFIG_CGROUPS */ | 397 | #else /* !CONFIG_CGROUPS */ |
407 | 398 | ||
408 | static inline int cgroup_init_early(void) { return 0; } | 399 | static inline int cgroup_init_early(void) { return 0; } |
@@ -420,9 +411,6 @@ static inline int cgroupstats_build(struct cgroupstats *stats, | |||
420 | return -EINVAL; | 411 | return -EINVAL; |
421 | } | 412 | } |
422 | 413 | ||
423 | static inline void cgroup_mm_owner_callbacks(struct task_struct *old, | ||
424 | struct task_struct *new) {} | ||
425 | |||
426 | #endif /* !CONFIG_CGROUPS */ | 414 | #endif /* !CONFIG_CGROUPS */ |
427 | 415 | ||
428 | #endif /* _LINUX_CGROUP_H */ | 416 | #endif /* _LINUX_CGROUP_H */ |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 87bb0258fd2..f221446aa02 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -116,7 +116,6 @@ static int root_count; | |||
116 | * be called. | 116 | * be called. |
117 | */ | 117 | */ |
118 | static int need_forkexit_callback __read_mostly; | 118 | static int need_forkexit_callback __read_mostly; |
119 | static int need_mm_owner_callback __read_mostly; | ||
120 | 119 | ||
121 | /* convenient tests for these bits */ | 120 | /* convenient tests for these bits */ |
122 | inline int cgroup_is_removed(const struct cgroup *cgrp) | 121 | inline int cgroup_is_removed(const struct cgroup *cgrp) |
@@ -2539,7 +2538,6 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss) | |||
2539 | init_css_set.subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id]; | 2538 | init_css_set.subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id]; |
2540 | 2539 | ||
2541 | need_forkexit_callback |= ss->fork || ss->exit; | 2540 | need_forkexit_callback |= ss->fork || ss->exit; |
2542 | need_mm_owner_callback |= !!ss->mm_owner_changed; | ||
2543 | 2541 | ||
2544 | /* At system boot, before all subsystems have been | 2542 | /* At system boot, before all subsystems have been |
2545 | * registered, no tasks have been forked, so we don't | 2543 | * registered, no tasks have been forked, so we don't |
@@ -2789,37 +2787,6 @@ void cgroup_fork_callbacks(struct task_struct *child) | |||
2789 | } | 2787 | } |
2790 | } | 2788 | } |
2791 | 2789 | ||
2792 | #ifdef CONFIG_MM_OWNER | ||
2793 | /** | ||
2794 | * cgroup_mm_owner_callbacks - run callbacks when the mm->owner changes | ||
2795 | * @p: the new owner | ||
2796 | * | ||
2797 | * Called on every change to mm->owner. mm_init_owner() does not | ||
2798 | * invoke this routine, since it assigns the mm->owner the first time | ||
2799 | * and does not change it. | ||
2800 | * | ||
2801 | * The callbacks are invoked with mmap_sem held in read mode. | ||
2802 | */ | ||
2803 | void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new) | ||
2804 | { | ||
2805 | struct cgroup *oldcgrp, *newcgrp = NULL; | ||
2806 | |||
2807 | if (need_mm_owner_callback) { | ||
2808 | int i; | ||
2809 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | ||
2810 | struct cgroup_subsys *ss = subsys[i]; | ||
2811 | oldcgrp = task_cgroup(old, ss->subsys_id); | ||
2812 | if (new) | ||
2813 | newcgrp = task_cgroup(new, ss->subsys_id); | ||
2814 | if (oldcgrp == newcgrp) | ||
2815 | continue; | ||
2816 | if (ss->mm_owner_changed) | ||
2817 | ss->mm_owner_changed(ss, oldcgrp, newcgrp, new); | ||
2818 | } | ||
2819 | } | ||
2820 | } | ||
2821 | #endif /* CONFIG_MM_OWNER */ | ||
2822 | |||
2823 | /** | 2790 | /** |
2824 | * cgroup_post_fork - called on a new task after adding it to the task list | 2791 | * cgroup_post_fork - called on a new task after adding it to the task list |
2825 | * @child: the task in question | 2792 | * @child: the task in question |
diff --git a/kernel/exit.c b/kernel/exit.c index c9e5a1c14e0..f923724ab3c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -642,35 +642,31 @@ retry: | |||
642 | /* | 642 | /* |
643 | * We found no owner yet mm_users > 1: this implies that we are | 643 | * We found no owner yet mm_users > 1: this implies that we are |
644 | * most likely racing with swapoff (try_to_unuse()) or /proc or | 644 | * most likely racing with swapoff (try_to_unuse()) or /proc or |
645 | * ptrace or page migration (get_task_mm()). Mark owner as NULL, | 645 | * ptrace or page migration (get_task_mm()). Mark owner as NULL. |
646 | * so that subsystems can understand the callback and take action. | ||
647 | */ | 646 | */ |
648 | down_write(&mm->mmap_sem); | ||
649 | cgroup_mm_owner_callbacks(mm->owner, NULL); | ||
650 | mm->owner = NULL; | 647 | mm->owner = NULL; |
651 | up_write(&mm->mmap_sem); | ||
652 | return; | 648 | return; |
653 | 649 | ||
654 | assign_new_owner: | 650 | assign_new_owner: |
655 | BUG_ON(c == p); | 651 | BUG_ON(c == p); |
656 | get_task_struct(c); | 652 | get_task_struct(c); |
657 | read_unlock(&tasklist_lock); | ||
658 | down_write(&mm->mmap_sem); | ||
659 | /* | 653 | /* |
660 | * The task_lock protects c->mm from changing. | 654 | * The task_lock protects c->mm from changing. |
661 | * We always want mm->owner->mm == mm | 655 | * We always want mm->owner->mm == mm |
662 | */ | 656 | */ |
663 | task_lock(c); | 657 | task_lock(c); |
658 | /* | ||
659 | * Delay read_unlock() till we have the task_lock() | ||
660 | * to ensure that c does not slip away underneath us | ||
661 | */ | ||
662 | read_unlock(&tasklist_lock); | ||
664 | if (c->mm != mm) { | 663 | if (c->mm != mm) { |
665 | task_unlock(c); | 664 | task_unlock(c); |
666 | up_write(&mm->mmap_sem); | ||
667 | put_task_struct(c); | 665 | put_task_struct(c); |
668 | goto retry; | 666 | goto retry; |
669 | } | 667 | } |
670 | cgroup_mm_owner_callbacks(mm->owner, c); | ||
671 | mm->owner = c; | 668 | mm->owner = c; |
672 | task_unlock(c); | 669 | task_unlock(c); |
673 | up_write(&mm->mmap_sem); | ||
674 | put_task_struct(c); | 670 | put_task_struct(c); |
675 | } | 671 | } |
676 | #endif /* CONFIG_MM_OWNER */ | 672 | #endif /* CONFIG_MM_OWNER */ |