aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cgroup.h6
-rw-r--r--kernel/cgroup/cgroup.c77
2 files changed, 66 insertions, 17 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index b7dd23040cd5..79faa6467f76 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -38,6 +38,8 @@
38 38
39/* walk only threadgroup leaders */ 39/* walk only threadgroup leaders */
40#define CSS_TASK_ITER_PROCS (1U << 0) 40#define CSS_TASK_ITER_PROCS (1U << 0)
41/* walk all threaded css_sets in the domain */
42#define CSS_TASK_ITER_THREADED (1U << 1)
41 43
42/* a css_task_iter should be treated as an opaque object */ 44/* a css_task_iter should be treated as an opaque object */
43struct css_task_iter { 45struct css_task_iter {
@@ -47,11 +49,15 @@ struct css_task_iter {
47 struct list_head *cset_pos; 49 struct list_head *cset_pos;
48 struct list_head *cset_head; 50 struct list_head *cset_head;
49 51
52 struct list_head *tcset_pos;
53 struct list_head *tcset_head;
54
50 struct list_head *task_pos; 55 struct list_head *task_pos;
51 struct list_head *tasks_head; 56 struct list_head *tasks_head;
52 struct list_head *mg_tasks_head; 57 struct list_head *mg_tasks_head;
53 58
54 struct css_set *cur_cset; 59 struct css_set *cur_cset;
60 struct css_set *cur_dcset;
55 struct task_struct *cur_task; 61 struct task_struct *cur_task;
56 struct list_head iters_node; /* css_set->task_iters */ 62 struct list_head iters_node; /* css_set->task_iters */
57}; 63};
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index c7e1c243b77d..a1d59af274a9 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -3629,6 +3629,58 @@ bool css_has_online_children(struct cgroup_subsys_state *css)
3629 return ret; 3629 return ret;
3630} 3630}
3631 3631
3632static struct css_set *css_task_iter_next_css_set(struct css_task_iter *it)
3633{
3634 struct list_head *l;
3635 struct cgrp_cset_link *link;
3636 struct css_set *cset;
3637
3638 lockdep_assert_held(&css_set_lock);
3639
3640 /* find the next threaded cset */
3641 if (it->tcset_pos) {
3642 l = it->tcset_pos->next;
3643
3644 if (l != it->tcset_head) {
3645 it->tcset_pos = l;
3646 return container_of(l, struct css_set,
3647 threaded_csets_node);
3648 }
3649
3650 it->tcset_pos = NULL;
3651 }
3652
3653 /* find the next cset */
3654 l = it->cset_pos;
3655 l = l->next;
3656 if (l == it->cset_head) {
3657 it->cset_pos = NULL;
3658 return NULL;
3659 }
3660
3661 if (it->ss) {
3662 cset = container_of(l, struct css_set, e_cset_node[it->ss->id]);
3663 } else {
3664 link = list_entry(l, struct cgrp_cset_link, cset_link);
3665 cset = link->cset;
3666 }
3667
3668 it->cset_pos = l;
3669
3670 /* initialize threaded css_set walking */
3671 if (it->flags & CSS_TASK_ITER_THREADED) {
3672 if (it->cur_dcset)
3673 put_css_set_locked(it->cur_dcset);
3674 it->cur_dcset = cset;
3675 get_css_set(cset);
3676
3677 it->tcset_head = &cset->threaded_csets;
3678 it->tcset_pos = &cset->threaded_csets;
3679 }
3680
3681 return cset;
3682}
3683
3632/** 3684/**
3633 * css_task_iter_advance_css_set - advance a task itererator to the next css_set 3685 * css_task_iter_advance_css_set - advance a task itererator to the next css_set
3634 * @it: the iterator to advance 3686 * @it: the iterator to advance
@@ -3637,32 +3689,19 @@ bool css_has_online_children(struct cgroup_subsys_state *css)
3637 */ 3689 */
3638static void css_task_iter_advance_css_set(struct css_task_iter *it) 3690static void css_task_iter_advance_css_set(struct css_task_iter *it)
3639{ 3691{
3640 struct list_head *l = it->cset_pos;
3641 struct cgrp_cset_link *link;
3642 struct css_set *cset; 3692 struct css_set *cset;
3643 3693
3644 lockdep_assert_held(&css_set_lock); 3694 lockdep_assert_held(&css_set_lock);
3645 3695
3646 /* Advance to the next non-empty css_set */ 3696 /* Advance to the next non-empty css_set */
3647 do { 3697 do {
3648 l = l->next; 3698 cset = css_task_iter_next_css_set(it);
3649 if (l == it->cset_head) { 3699 if (!cset) {
3650 it->cset_pos = NULL;
3651 it->task_pos = NULL; 3700 it->task_pos = NULL;
3652 return; 3701 return;
3653 } 3702 }
3654
3655 if (it->ss) {
3656 cset = container_of(l, struct css_set,
3657 e_cset_node[it->ss->id]);
3658 } else {
3659 link = list_entry(l, struct cgrp_cset_link, cset_link);
3660 cset = link->cset;
3661 }
3662 } while (!css_set_populated(cset)); 3703 } while (!css_set_populated(cset));
3663 3704
3664 it->cset_pos = l;
3665
3666 if (!list_empty(&cset->tasks)) 3705 if (!list_empty(&cset->tasks))
3667 it->task_pos = cset->tasks.next; 3706 it->task_pos = cset->tasks.next;
3668 else 3707 else
@@ -3805,6 +3844,9 @@ void css_task_iter_end(struct css_task_iter *it)
3805 spin_unlock_irq(&css_set_lock); 3844 spin_unlock_irq(&css_set_lock);
3806 } 3845 }
3807 3846
3847 if (it->cur_dcset)
3848 put_css_set(it->cur_dcset);
3849
3808 if (it->cur_task) 3850 if (it->cur_task)
3809 put_task_struct(it->cur_task); 3851 put_task_struct(it->cur_task);
3810} 3852}
@@ -3830,6 +3872,7 @@ static void *cgroup_procs_start(struct seq_file *s, loff_t *pos)
3830 struct kernfs_open_file *of = s->private; 3872 struct kernfs_open_file *of = s->private;
3831 struct cgroup *cgrp = seq_css(s)->cgroup; 3873 struct cgroup *cgrp = seq_css(s)->cgroup;
3832 struct css_task_iter *it = of->priv; 3874 struct css_task_iter *it = of->priv;
3875 unsigned iter_flags = CSS_TASK_ITER_PROCS | CSS_TASK_ITER_THREADED;
3833 3876
3834 /* 3877 /*
3835 * When a seq_file is seeked, it's always traversed sequentially 3878 * When a seq_file is seeked, it's always traversed sequentially
@@ -3843,10 +3886,10 @@ static void *cgroup_procs_start(struct seq_file *s, loff_t *pos)
3843 if (!it) 3886 if (!it)
3844 return ERR_PTR(-ENOMEM); 3887 return ERR_PTR(-ENOMEM);
3845 of->priv = it; 3888 of->priv = it;
3846 css_task_iter_start(&cgrp->self, CSS_TASK_ITER_PROCS, it); 3889 css_task_iter_start(&cgrp->self, iter_flags, it);
3847 } else if (!(*pos)++) { 3890 } else if (!(*pos)++) {
3848 css_task_iter_end(it); 3891 css_task_iter_end(it);
3849 css_task_iter_start(&cgrp->self, CSS_TASK_ITER_PROCS, it); 3892 css_task_iter_start(&cgrp->self, iter_flags, it);
3850 } 3893 }
3851 3894
3852 return cgroup_procs_next(s, NULL, NULL); 3895 return cgroup_procs_next(s, NULL, NULL);