Reviewed-by: Cheng Jian <cj.chengjian(a)huawei.com>
在 2021/10/23 17:09, wjy 写道:
> From: Vincent Guittot <vincent.guittot(a)linaro.org>
>
> stable inclusion
> from stable-v5.10.44
> commit 32e22db8b25ea165bd9e446c7f92b089c8568eaf
> bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=379
> CVE: NA
>
> -------------------------------------------------
>
> commit 02da26ad5ed6ea8680e5d01f20661439611ed776 upstream.
>
> During the update of fair blocked load (__update_blocked_fair()), we
> update the contribution of the cfs in tg->load_avg if cfs_rq's pelt
> has decayed. Nevertheless, the pelt values of a cfs_rq could have
> been recently updated while propagating the change of a child. In this
> case, cfs_rq's pelt will not decayed because it has already been
> updated and we don't update tg->load_avg.
>
> __update_blocked_fair
> ...
> for_each_leaf_cfs_rq_safe: child cfs_rq
> update cfs_rq_load_avg() for child cfs_rq
> ...
> update_load_avg(cfs_rq_of(se), se, 0)
> ...
> update cfs_rq_load_avg() for parent cfs_rq
> -propagation of child's load makes parent cfs_rq->load_sum
> becoming null
> -UPDATE_TG is not set so it doesn't update parent
> cfs_rq->tg_load_avg_contrib
> ..
> for_each_leaf_cfs_rq_safe: parent cfs_rq
> update cfs_rq_load_avg() for parent cfs_rq
> - nothing to do because parent cfs_rq has already been updated
> recently so cfs_rq->tg_load_avg_contrib is not updated
> ...
> parent cfs_rq is decayed
> list_del_leaf_cfs_rq parent cfs_rq
> - but it still contibutes to tg->load_avg
>
> we must set UPDATE_TG flags when propagting pending load to the parent
>
> Fixes: 039ae8bcf7a5 ("sched/fair: Fix O(nr_cgroups) in the load balancing path")
> Reported-by: Odin Ugedal <odin(a)uged.al>
> Signed-off-by: Vincent Guittot <vincent.guittot(a)linaro.org>
> Signed-off-by: Peter Zijlstra (Intel) <peterz(a)infradead.org>
> Reviewed-by: Odin Ugedal <odin(a)uged.al>
> Link: https://lkml.kernel.org/r/20210527122916.27683-3-vincent.guittot@linaro.org
> Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
> Signed-off-by: wjy <464310675(a)qq.com>
> ---
> kernel/sched/fair.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index 1ad0e52487f6..43497d88a330 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -7961,7 +7961,7 @@ static bool __update_blocked_fair(struct rq *rq, bool *done)
> /* Propagate pending load changes to the parent, if any: */
> se = cfs_rq->tg->se[cpu];
> if (se && !skip_blocked_update(se))
> - update_load_avg(cfs_rq_of(se), se, 0);
> + update_load_avg(cfs_rq_of(se), se, UPDATE_TG);
>
> /*
> * There can be a lot of idle CPU cgroups. Don't let fully