aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2017-05-15 09:34:03 -0400
committerTejun Heo <tj@kernel.org>2017-07-21 11:14:51 -0400
commit450ee0c1feed657894e0b4bdd48f3974af9d394c (patch)
tree9922f55956a546566a61e2e7d395a3a251647375 /kernel
parent454000adaa2a7420df6e56a42f22726d05872a3f (diff)
cgroup: implement CSS_TASK_ITER_THREADED
cgroup v2 is in the process of growing thread granularity support. Once thread mode is enabled, the root cgroup of the subtree serves as the dom_cgrp to which the processes of the subtree conceptually belong and domain-level resource consumptions not tied to any specific task are charged. In the subtree, threads won't be subject to process granularity or no-internal-task constraint and can be distributed arbitrarily across the subtree. This patch implements a new task iterator flag CSS_TASK_ITER_THREADED, which, when used on a dom_cgrp, makes the iteration include the tasks on all the associated threaded css_sets. "cgroup.procs" read path is updated to use it so that reading the file on a proc_cgrp lists all processes. This will also be used by controller implementations which need to walk processes or tasks at the resource domain level. Task iteration is implemented nested in css_set iteration. If CSS_TASK_ITER_THREADED is specified, after walking tasks of each !threaded css_set, all the associated threaded css_sets are visited before moving onto the next !threaded css_set. v2: ->cur_pcset renamed to ->cur_dcset. Updated for the new enable-threaded-per-cgroup behavior. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup/cgroup.c77
1 files changed, 60 insertions, 17 deletions
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);