aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2016-01-21 16:24:16 -0500
committerIngo Molnar <mingo@kernel.org>2016-02-29 03:41:50 -0500
commit6fe1f348b3dd1f700f9630562b7d38afd6949568 (patch)
tree2f160853005ebdb0d6468e0672241d03399c0ad8
parentfc77dbd34c5c99bce46d40a2491937c3bcbd10af (diff)
sched/cgroup: Fix cgroup entity load tracking tear-down
When a cgroup's CPU runqueue is destroyed, it should remove its remaining load accounting from its parent cgroup. The current site for doing so it unsuited because its far too late and unordered against other cgroup removal (->css_free() will be, but we're also in an RCU callback). Put it in the ->css_offline() callback, which is the start of cgroup destruction, right after the group has been made unavailable to userspace. The ->css_offline() callbacks are called in hierarchical order after the following v4.4 commit: aa226ff4a1ce ("cgroup: make sure a parent css isn't offlined before its children") Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Christian Borntraeger <borntraeger@de.ibm.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Li Zefan <lizefan@huawei.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Tejun Heo <tj@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20160121212416.GL6357@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/sched/core.c4
-rw-r--r--kernel/sched/fair.c37
-rw-r--r--kernel/sched/sched.h2
3 files changed, 23 insertions, 20 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 9503d590e5ef..ab814bf100e1 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7860,11 +7860,9 @@ void sched_destroy_group(struct task_group *tg)
7860void sched_offline_group(struct task_group *tg) 7860void sched_offline_group(struct task_group *tg)
7861{ 7861{
7862 unsigned long flags; 7862 unsigned long flags;
7863 int i;
7864 7863
7865 /* end participation in shares distribution */ 7864 /* end participation in shares distribution */
7866 for_each_possible_cpu(i) 7865 unregister_fair_sched_group(tg);
7867 unregister_fair_sched_group(tg, i);
7868 7866
7869 spin_lock_irqsave(&task_group_lock, flags); 7867 spin_lock_irqsave(&task_group_lock, flags);
7870 list_del_rcu(&tg->list); 7868 list_del_rcu(&tg->list);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 56b7d4b83947..cce330329624 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -8234,11 +8234,8 @@ void free_fair_sched_group(struct task_group *tg)
8234 for_each_possible_cpu(i) { 8234 for_each_possible_cpu(i) {
8235 if (tg->cfs_rq) 8235 if (tg->cfs_rq)
8236 kfree(tg->cfs_rq[i]); 8236 kfree(tg->cfs_rq[i]);
8237 if (tg->se) { 8237 if (tg->se)
8238 if (tg->se[i])
8239 remove_entity_load_avg(tg->se[i]);
8240 kfree(tg->se[i]); 8238 kfree(tg->se[i]);
8241 }
8242 } 8239 }
8243 8240
8244 kfree(tg->cfs_rq); 8241 kfree(tg->cfs_rq);
@@ -8286,21 +8283,29 @@ err:
8286 return 0; 8283 return 0;
8287} 8284}
8288 8285
8289void unregister_fair_sched_group(struct task_group *tg, int cpu) 8286void unregister_fair_sched_group(struct task_group *tg)
8290{ 8287{
8291 struct rq *rq = cpu_rq(cpu);
8292 unsigned long flags; 8288 unsigned long flags;
8289 struct rq *rq;
8290 int cpu;
8293 8291
8294 /* 8292 for_each_possible_cpu(cpu) {
8295 * Only empty task groups can be destroyed; so we can speculatively 8293 if (tg->se[cpu])
8296 * check on_list without danger of it being re-added. 8294 remove_entity_load_avg(tg->se[cpu]);
8297 */
8298 if (!tg->cfs_rq[cpu]->on_list)
8299 return;
8300 8295
8301 raw_spin_lock_irqsave(&rq->lock, flags); 8296 /*
8302 list_del_leaf_cfs_rq(tg->cfs_rq[cpu]); 8297 * Only empty task groups can be destroyed; so we can speculatively
8303 raw_spin_unlock_irqrestore(&rq->lock, flags); 8298 * check on_list without danger of it being re-added.
8299 */
8300 if (!tg->cfs_rq[cpu]->on_list)
8301 continue;
8302
8303 rq = cpu_rq(cpu);
8304
8305 raw_spin_lock_irqsave(&rq->lock, flags);
8306 list_del_leaf_cfs_rq(tg->cfs_rq[cpu]);
8307 raw_spin_unlock_irqrestore(&rq->lock, flags);
8308 }
8304} 8309}
8305 8310
8306void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq, 8311void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
@@ -8382,7 +8387,7 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
8382 return 1; 8387 return 1;
8383} 8388}
8384 8389
8385void unregister_fair_sched_group(struct task_group *tg, int cpu) { } 8390void unregister_fair_sched_group(struct task_group *tg) { }
8386 8391
8387#endif /* CONFIG_FAIR_GROUP_SCHED */ 8392#endif /* CONFIG_FAIR_GROUP_SCHED */
8388 8393
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 10f16374df7f..30ea2d871ba7 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -313,7 +313,7 @@ extern int tg_nop(struct task_group *tg, void *data);
313 313
314extern void free_fair_sched_group(struct task_group *tg); 314extern void free_fair_sched_group(struct task_group *tg);
315extern int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent); 315extern int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent);
316extern void unregister_fair_sched_group(struct task_group *tg, int cpu); 316extern void unregister_fair_sched_group(struct task_group *tg);
317extern void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq, 317extern void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
318 struct sched_entity *se, int cpu, 318 struct sched_entity *se, int cpu,
319 struct sched_entity *parent); 319 struct sched_entity *parent);