Skip to content

Commit 8f53470

Browse files
committed
cgroup: Add cgroup_subsys->css_rstat_flush()
This patch adds cgroup_subsys->css_rstat_flush(). If a subsystem has this callback, its csses are linked on cgrp->css_rstat_list and rstat will call the function whenever the associated cgroup is flushed. Flush is also performed when such csses are released so that residual counts aren't lost. Combined with the rstat API previous patches factored out, this allows controllers to plug into rstat to manage their statistics in a scalable way. Signed-off-by: Tejun Heo <[email protected]>
1 parent 0fa294f commit 8f53470

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

include/linux/cgroup-defs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ struct cgroup_subsys_state {
130130
struct list_head sibling;
131131
struct list_head children;
132132

133+
/* flush target list anchored at cgrp->rstat_css_list */
134+
struct list_head rstat_css_node;
135+
133136
/*
134137
* PI: Subsys-unique ID. 0 is unused and root is always 1. The
135138
* matching css can be looked up using css_from_id().
@@ -412,6 +415,7 @@ struct cgroup {
412415

413416
/* per-cpu recursive resource statistics */
414417
struct cgroup_rstat_cpu __percpu *rstat_cpu;
418+
struct list_head rstat_css_list;
415419

416420
/* cgroup basic resource statistics */
417421
struct cgroup_base_stat pending_bstat; /* pending from children */
@@ -577,6 +581,7 @@ struct cgroup_subsys {
577581
void (*css_released)(struct cgroup_subsys_state *css);
578582
void (*css_free)(struct cgroup_subsys_state *css);
579583
void (*css_reset)(struct cgroup_subsys_state *css);
584+
void (*css_rstat_flush)(struct cgroup_subsys_state *css, int cpu);
580585
int (*css_extra_stat_show)(struct seq_file *seq,
581586
struct cgroup_subsys_state *css);
582587

kernel/cgroup/cgroup.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,6 +1860,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
18601860
cgrp->dom_cgrp = cgrp;
18611861
cgrp->max_descendants = INT_MAX;
18621862
cgrp->max_depth = INT_MAX;
1863+
INIT_LIST_HEAD(&cgrp->rstat_css_list);
18631864
prev_cputime_init(&cgrp->prev_cputime);
18641865

18651866
for_each_subsys(ss, ssid)
@@ -4621,6 +4622,11 @@ static void css_release_work_fn(struct work_struct *work)
46214622

46224623
if (ss) {
46234624
/* css release path */
4625+
if (!list_empty(&css->rstat_css_node)) {
4626+
cgroup_rstat_flush(cgrp);
4627+
list_del_rcu(&css->rstat_css_node);
4628+
}
4629+
46244630
cgroup_idr_replace(&ss->css_idr, NULL, css->id);
46254631
if (ss->css_released)
46264632
ss->css_released(css);
@@ -4682,6 +4688,7 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
46824688
css->id = -1;
46834689
INIT_LIST_HEAD(&css->sibling);
46844690
INIT_LIST_HEAD(&css->children);
4691+
INIT_LIST_HEAD(&css->rstat_css_node);
46854692
css->serial_nr = css_serial_nr_next++;
46864693
atomic_set(&css->online_cnt, 0);
46874694

@@ -4690,6 +4697,9 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
46904697
css_get(css->parent);
46914698
}
46924699

4700+
if (cgroup_on_dfl(cgrp) && ss->css_rstat_flush)
4701+
list_add_rcu(&css->rstat_css_node, &cgrp->rstat_css_list);
4702+
46934703
BUG_ON(cgroup_css(cgrp, ss));
46944704
}
46954705

@@ -4791,6 +4801,7 @@ static struct cgroup_subsys_state *css_create(struct cgroup *cgrp,
47914801
err_list_del:
47924802
list_del_rcu(&css->sibling);
47934803
err_free_css:
4804+
list_del_rcu(&css->rstat_css_node);
47944805
INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
47954806
queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
47964807
return ERR_PTR(err);

kernel/cgroup/rstat.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,17 @@ static void cgroup_rstat_flush_locked(struct cgroup *cgrp, bool may_sleep)
145145
struct cgroup *pos = NULL;
146146

147147
raw_spin_lock(cpu_lock);
148-
while ((pos = cgroup_rstat_cpu_pop_updated(pos, cgrp, cpu)))
148+
while ((pos = cgroup_rstat_cpu_pop_updated(pos, cgrp, cpu))) {
149+
struct cgroup_subsys_state *css;
150+
149151
cgroup_base_stat_flush(pos, cpu);
152+
153+
rcu_read_lock();
154+
list_for_each_entry_rcu(css, &pos->rstat_css_list,
155+
rstat_css_node)
156+
css->ss->css_rstat_flush(css, cpu);
157+
rcu_read_unlock();
158+
}
150159
raw_spin_unlock(cpu_lock);
151160

152161
/* if @may_sleep, play nice and yield if necessary */

0 commit comments

Comments
 (0)