Skip to content

Commit 450ee0c

Browse files
committed
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 <[email protected]>
1 parent 454000a commit 450ee0c

File tree

2 files changed

+66
-17
lines changed

2 files changed

+66
-17
lines changed

include/linux/cgroup.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838

3939
/* walk only threadgroup leaders */
4040
#define CSS_TASK_ITER_PROCS (1U << 0)
41+
/* walk all threaded css_sets in the domain */
42+
#define CSS_TASK_ITER_THREADED (1U << 1)
4143

4244
/* a css_task_iter should be treated as an opaque object */
4345
struct css_task_iter {
@@ -47,11 +49,15 @@ struct css_task_iter {
4749
struct list_head *cset_pos;
4850
struct list_head *cset_head;
4951

52+
struct list_head *tcset_pos;
53+
struct list_head *tcset_head;
54+
5055
struct list_head *task_pos;
5156
struct list_head *tasks_head;
5257
struct list_head *mg_tasks_head;
5358

5459
struct css_set *cur_cset;
60+
struct css_set *cur_dcset;
5561
struct task_struct *cur_task;
5662
struct list_head iters_node; /* css_set->task_iters */
5763
};

kernel/cgroup/cgroup.c

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3629,6 +3629,58 @@ bool css_has_online_children(struct cgroup_subsys_state *css)
36293629
return ret;
36303630
}
36313631

3632+
static 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+
36323684
/**
36333685
* css_task_iter_advance_css_set - advance a task itererator to the next css_set
36343686
* @it: the iterator to advance
@@ -3637,32 +3689,19 @@ bool css_has_online_children(struct cgroup_subsys_state *css)
36373689
*/
36383690
static void css_task_iter_advance_css_set(struct css_task_iter *it)
36393691
{
3640-
struct list_head *l = it->cset_pos;
3641-
struct cgrp_cset_link *link;
36423692
struct css_set *cset;
36433693

36443694
lockdep_assert_held(&css_set_lock);
36453695

36463696
/* Advance to the next non-empty css_set */
36473697
do {
3648-
l = l->next;
3649-
if (l == it->cset_head) {
3650-
it->cset_pos = NULL;
3698+
cset = css_task_iter_next_css_set(it);
3699+
if (!cset) {
36513700
it->task_pos = NULL;
36523701
return;
36533702
}
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-
}
36623703
} while (!css_set_populated(cset));
36633704

3664-
it->cset_pos = l;
3665-
36663705
if (!list_empty(&cset->tasks))
36673706
it->task_pos = cset->tasks.next;
36683707
else
@@ -3805,6 +3844,9 @@ void css_task_iter_end(struct css_task_iter *it)
38053844
spin_unlock_irq(&css_set_lock);
38063845
}
38073846

3847+
if (it->cur_dcset)
3848+
put_css_set(it->cur_dcset);
3849+
38083850
if (it->cur_task)
38093851
put_task_struct(it->cur_task);
38103852
}
@@ -3830,6 +3872,7 @@ static void *cgroup_procs_start(struct seq_file *s, loff_t *pos)
38303872
struct kernfs_open_file *of = s->private;
38313873
struct cgroup *cgrp = seq_css(s)->cgroup;
38323874
struct css_task_iter *it = of->priv;
3875+
unsigned iter_flags = CSS_TASK_ITER_PROCS | CSS_TASK_ITER_THREADED;
38333876

38343877
/*
38353878
* 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)
38433886
if (!it)
38443887
return ERR_PTR(-ENOMEM);
38453888
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);
38473890
} else if (!(*pos)++) {
38483891
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);
38503893
}
38513894

38523895
return cgroup_procs_next(s, NULL, NULL);

0 commit comments

Comments
 (0)