summaryrefslogtreecommitdiffstats
path: root/kernel/cgroup
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2018-04-26 17:29:05 -0400
committerTejun Heo <tj@kernel.org>2018-04-26 17:29:05 -0400
commit8f53470bab04229e93ff9e4c20338cc08b42b344 (patch)
tree8ab616e9b6ee8b2affcbe88278961d5e8bdc7eb3 /kernel/cgroup
parent0fa294fb1985c06c4e3325e30e759d4ca580f59a (diff)
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 <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup')
-rw-r--r--kernel/cgroup/cgroup.c11
-rw-r--r--kernel/cgroup/rstat.c11
2 files changed, 21 insertions, 1 deletions
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 31af98996692..04b7e7fad31a 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1860,6 +1860,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
1860 cgrp->dom_cgrp = cgrp; 1860 cgrp->dom_cgrp = cgrp;
1861 cgrp->max_descendants = INT_MAX; 1861 cgrp->max_descendants = INT_MAX;
1862 cgrp->max_depth = INT_MAX; 1862 cgrp->max_depth = INT_MAX;
1863 INIT_LIST_HEAD(&cgrp->rstat_css_list);
1863 prev_cputime_init(&cgrp->prev_cputime); 1864 prev_cputime_init(&cgrp->prev_cputime);
1864 1865
1865 for_each_subsys(ss, ssid) 1866 for_each_subsys(ss, ssid)
@@ -4621,6 +4622,11 @@ static void css_release_work_fn(struct work_struct *work)
4621 4622
4622 if (ss) { 4623 if (ss) {
4623 /* css release path */ 4624 /* 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
4624 cgroup_idr_replace(&ss->css_idr, NULL, css->id); 4630 cgroup_idr_replace(&ss->css_idr, NULL, css->id);
4625 if (ss->css_released) 4631 if (ss->css_released)
4626 ss->css_released(css); 4632 ss->css_released(css);
@@ -4682,6 +4688,7 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
4682 css->id = -1; 4688 css->id = -1;
4683 INIT_LIST_HEAD(&css->sibling); 4689 INIT_LIST_HEAD(&css->sibling);
4684 INIT_LIST_HEAD(&css->children); 4690 INIT_LIST_HEAD(&css->children);
4691 INIT_LIST_HEAD(&css->rstat_css_node);
4685 css->serial_nr = css_serial_nr_next++; 4692 css->serial_nr = css_serial_nr_next++;
4686 atomic_set(&css->online_cnt, 0); 4693 atomic_set(&css->online_cnt, 0);
4687 4694
@@ -4690,6 +4697,9 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
4690 css_get(css->parent); 4697 css_get(css->parent);
4691 } 4698 }
4692 4699
4700 if (cgroup_on_dfl(cgrp) && ss->css_rstat_flush)
4701 list_add_rcu(&css->rstat_css_node, &cgrp->rstat_css_list);
4702
4693 BUG_ON(cgroup_css(cgrp, ss)); 4703 BUG_ON(cgroup_css(cgrp, ss));
4694} 4704}
4695 4705
@@ -4791,6 +4801,7 @@ static struct cgroup_subsys_state *css_create(struct cgroup *cgrp,
4791err_list_del: 4801err_list_del:
4792 list_del_rcu(&css->sibling); 4802 list_del_rcu(&css->sibling);
4793err_free_css: 4803err_free_css:
4804 list_del_rcu(&css->rstat_css_node);
4794 INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn); 4805 INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
4795 queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork); 4806 queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
4796 return ERR_PTR(err); 4807 return ERR_PTR(err);
diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c
index 3386fb251a9e..339366e257d4 100644
--- a/kernel/cgroup/rstat.c
+++ b/kernel/cgroup/rstat.c
@@ -145,8 +145,17 @@ static void cgroup_rstat_flush_locked(struct cgroup *cgrp, bool may_sleep)
145 struct cgroup *pos = NULL; 145 struct cgroup *pos = NULL;
146 146
147 raw_spin_lock(cpu_lock); 147 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
149 cgroup_base_stat_flush(pos, cpu); 151 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 }
150 raw_spin_unlock(cpu_lock); 159 raw_spin_unlock(cpu_lock);
151 160
152 /* if @may_sleep, play nice and yield if necessary */ 161 /* if @may_sleep, play nice and yield if necessary */