aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/linux/cgroup-defs.h5
-rw-r--r--kernel/cgroup/cgroup.c11
-rw-r--r--kernel/cgroup/rstat.c11
3 files changed, 26 insertions, 1 deletions
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 60d62fe97dc3..c0e68f903011 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -130,6 +130,9 @@ struct cgroup_subsys_state {
130 struct list_head sibling; 130 struct list_head sibling;
131 struct list_head children; 131 struct list_head children;
132 132
133 /* flush target list anchored at cgrp->rstat_css_list */
134 struct list_head rstat_css_node;
135
133 /* 136 /*
134 * PI: Subsys-unique ID. 0 is unused and root is always 1. The 137 * PI: Subsys-unique ID. 0 is unused and root is always 1. The
135 * matching css can be looked up using css_from_id(). 138 * matching css can be looked up using css_from_id().
@@ -412,6 +415,7 @@ struct cgroup {
412 415
413 /* per-cpu recursive resource statistics */ 416 /* per-cpu recursive resource statistics */
414 struct cgroup_rstat_cpu __percpu *rstat_cpu; 417 struct cgroup_rstat_cpu __percpu *rstat_cpu;
418 struct list_head rstat_css_list;
415 419
416 /* cgroup basic resource statistics */ 420 /* cgroup basic resource statistics */
417 struct cgroup_base_stat pending_bstat; /* pending from children */ 421 struct cgroup_base_stat pending_bstat; /* pending from children */
@@ -577,6 +581,7 @@ struct cgroup_subsys {
577 void (*css_released)(struct cgroup_subsys_state *css); 581 void (*css_released)(struct cgroup_subsys_state *css);
578 void (*css_free)(struct cgroup_subsys_state *css); 582 void (*css_free)(struct cgroup_subsys_state *css);
579 void (*css_reset)(struct cgroup_subsys_state *css); 583 void (*css_reset)(struct cgroup_subsys_state *css);
584 void (*css_rstat_flush)(struct cgroup_subsys_state *css, int cpu);
580 int (*css_extra_stat_show)(struct seq_file *seq, 585 int (*css_extra_stat_show)(struct seq_file *seq,
581 struct cgroup_subsys_state *css); 586 struct cgroup_subsys_state *css);
582 587
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 */