aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cgroup.h14
-rw-r--r--kernel/cgroup.c33
-rw-r--r--kernel/exit.c16
3 files changed, 7 insertions, 56 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 1164963c3a85..08b78c09b09a 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);
400int cgroup_scan_tasks(struct cgroup_scanner *scan); 394int cgroup_scan_tasks(struct cgroup_scanner *scan);
401int cgroup_attach_task(struct cgroup *, struct task_struct *); 395int cgroup_attach_task(struct cgroup *, struct task_struct *);
402 396
403void cgroup_mm_owner_callbacks(struct task_struct *old,
404 struct task_struct *new);
405
406#else /* !CONFIG_CGROUPS */ 397#else /* !CONFIG_CGROUPS */
407 398
408static inline int cgroup_init_early(void) { return 0; } 399static 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
423static 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 87bb0258fd27..f221446aa02d 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 */
118static int need_forkexit_callback __read_mostly; 118static int need_forkexit_callback __read_mostly;
119static int need_mm_owner_callback __read_mostly;
120 119
121/* convenient tests for these bits */ 120/* convenient tests for these bits */
122inline int cgroup_is_removed(const struct cgroup *cgrp) 121inline 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 */
2803void 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 c9e5a1c14e08..f923724ab3c9 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
654assign_new_owner: 650assign_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 */