diff options
| author | Vincent Guittot <vincent.guittot@linaro.org> | 2019-02-06 11:14:22 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2019-02-11 02:02:13 -0500 |
| commit | 039ae8bcf7a5f4476f4487e6bf816885fb3fb617 (patch) | |
| tree | b122a00631dcbe446366736f3f3e11519c46f5af | |
| parent | 31bc6aeaab1d1de8959b67edbed5c7a4b3cdbe7c (diff) | |
sched/fair: Fix O(nr_cgroups) in the load balancing path
This re-applies the commit reverted here:
commit c40f7d74c741 ("sched/fair: Fix infinite loop in update_blocked_averages() by reverting a9e7f6544b9c")
I.e. now that cfs_rq can be safely removed/added in the list, we can re-apply:
commit a9e7f6544b9c ("sched/fair: Fix O(nr_cgroups) in load balance path")
Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: sargun@sargun.me
Cc: tj@kernel.org
Cc: xiexiuqi@huawei.com
Cc: xiezhipeng1@huawei.com
Link: https://lkml.kernel.org/r/1549469662-13614-3-git-send-email-vincent.guittot@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
| -rw-r--r-- | kernel/sched/fair.c | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 027f8e1b5b66..17a961522d1e 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c | |||
| @@ -368,9 +368,10 @@ static inline void assert_list_leaf_cfs_rq(struct rq *rq) | |||
| 368 | SCHED_WARN_ON(rq->tmp_alone_branch != &rq->leaf_cfs_rq_list); | 368 | SCHED_WARN_ON(rq->tmp_alone_branch != &rq->leaf_cfs_rq_list); |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | /* Iterate through all cfs_rq's on a runqueue in bottom-up order */ | 371 | /* Iterate thr' all leaf cfs_rq's on a runqueue */ |
| 372 | #define for_each_leaf_cfs_rq(rq, cfs_rq) \ | 372 | #define for_each_leaf_cfs_rq_safe(rq, cfs_rq, pos) \ |
| 373 | list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list) | 373 | list_for_each_entry_safe(cfs_rq, pos, &rq->leaf_cfs_rq_list, \ |
| 374 | leaf_cfs_rq_list) | ||
| 374 | 375 | ||
| 375 | /* Do the two (enqueued) entities belong to the same group ? */ | 376 | /* Do the two (enqueued) entities belong to the same group ? */ |
| 376 | static inline struct cfs_rq * | 377 | static inline struct cfs_rq * |
| @@ -461,8 +462,8 @@ static inline void assert_list_leaf_cfs_rq(struct rq *rq) | |||
| 461 | { | 462 | { |
| 462 | } | 463 | } |
| 463 | 464 | ||
| 464 | #define for_each_leaf_cfs_rq(rq, cfs_rq) \ | 465 | #define for_each_leaf_cfs_rq_safe(rq, cfs_rq, pos) \ |
| 465 | for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL) | 466 | for (cfs_rq = &rq->cfs, pos = NULL; cfs_rq; cfs_rq = pos) |
| 466 | 467 | ||
| 467 | static inline struct sched_entity *parent_entity(struct sched_entity *se) | 468 | static inline struct sched_entity *parent_entity(struct sched_entity *se) |
| 468 | { | 469 | { |
| @@ -7702,10 +7703,27 @@ static inline bool others_have_blocked(struct rq *rq) | |||
| 7702 | 7703 | ||
| 7703 | #ifdef CONFIG_FAIR_GROUP_SCHED | 7704 | #ifdef CONFIG_FAIR_GROUP_SCHED |
| 7704 | 7705 | ||
| 7706 | static inline bool cfs_rq_is_decayed(struct cfs_rq *cfs_rq) | ||
| 7707 | { | ||
| 7708 | if (cfs_rq->load.weight) | ||
| 7709 | return false; | ||
| 7710 | |||
| 7711 | if (cfs_rq->avg.load_sum) | ||
| 7712 | return false; | ||
| 7713 | |||
| 7714 | if (cfs_rq->avg.util_sum) | ||
| 7715 | return false; | ||
| 7716 | |||
| 7717 | if (cfs_rq->avg.runnable_load_sum) | ||
| 7718 | return false; | ||
| 7719 | |||
| 7720 | return true; | ||
| 7721 | } | ||
| 7722 | |||
| 7705 | static void update_blocked_averages(int cpu) | 7723 | static void update_blocked_averages(int cpu) |
| 7706 | { | 7724 | { |
| 7707 | struct rq *rq = cpu_rq(cpu); | 7725 | struct rq *rq = cpu_rq(cpu); |
| 7708 | struct cfs_rq *cfs_rq; | 7726 | struct cfs_rq *cfs_rq, *pos; |
| 7709 | const struct sched_class *curr_class; | 7727 | const struct sched_class *curr_class; |
| 7710 | struct rq_flags rf; | 7728 | struct rq_flags rf; |
| 7711 | bool done = true; | 7729 | bool done = true; |
| @@ -7717,7 +7735,7 @@ static void update_blocked_averages(int cpu) | |||
| 7717 | * Iterates the task_group tree in a bottom up fashion, see | 7735 | * Iterates the task_group tree in a bottom up fashion, see |
| 7718 | * list_add_leaf_cfs_rq() for details. | 7736 | * list_add_leaf_cfs_rq() for details. |
| 7719 | */ | 7737 | */ |
| 7720 | for_each_leaf_cfs_rq(rq, cfs_rq) { | 7738 | for_each_leaf_cfs_rq_safe(rq, cfs_rq, pos) { |
| 7721 | struct sched_entity *se; | 7739 | struct sched_entity *se; |
| 7722 | 7740 | ||
| 7723 | if (update_cfs_rq_load_avg(cfs_rq_clock_pelt(cfs_rq), cfs_rq)) | 7741 | if (update_cfs_rq_load_avg(cfs_rq_clock_pelt(cfs_rq), cfs_rq)) |
| @@ -7728,6 +7746,13 @@ static void update_blocked_averages(int cpu) | |||
| 7728 | if (se && !skip_blocked_update(se)) | 7746 | if (se && !skip_blocked_update(se)) |
| 7729 | update_load_avg(cfs_rq_of(se), se, 0); | 7747 | update_load_avg(cfs_rq_of(se), se, 0); |
| 7730 | 7748 | ||
| 7749 | /* | ||
| 7750 | * There can be a lot of idle CPU cgroups. Don't let fully | ||
| 7751 | * decayed cfs_rqs linger on the list. | ||
| 7752 | */ | ||
| 7753 | if (cfs_rq_is_decayed(cfs_rq)) | ||
| 7754 | list_del_leaf_cfs_rq(cfs_rq); | ||
| 7755 | |||
| 7731 | /* Don't need periodic decay once load/util_avg are null */ | 7756 | /* Don't need periodic decay once load/util_avg are null */ |
| 7732 | if (cfs_rq_has_blocked(cfs_rq)) | 7757 | if (cfs_rq_has_blocked(cfs_rq)) |
| 7733 | done = false; | 7758 | done = false; |
| @@ -10609,10 +10634,10 @@ const struct sched_class fair_sched_class = { | |||
| 10609 | #ifdef CONFIG_SCHED_DEBUG | 10634 | #ifdef CONFIG_SCHED_DEBUG |
| 10610 | void print_cfs_stats(struct seq_file *m, int cpu) | 10635 | void print_cfs_stats(struct seq_file *m, int cpu) |
| 10611 | { | 10636 | { |
| 10612 | struct cfs_rq *cfs_rq; | 10637 | struct cfs_rq *cfs_rq, *pos; |
| 10613 | 10638 | ||
| 10614 | rcu_read_lock(); | 10639 | rcu_read_lock(); |
| 10615 | for_each_leaf_cfs_rq(cpu_rq(cpu), cfs_rq) | 10640 | for_each_leaf_cfs_rq_safe(cpu_rq(cpu), cfs_rq, pos) |
| 10616 | print_cfs_rq(m, cpu, cfs_rq); | 10641 | print_cfs_rq(m, cpu, cfs_rq); |
| 10617 | rcu_read_unlock(); | 10642 | rcu_read_unlock(); |
| 10618 | } | 10643 | } |
