Skip to content

Commit f678331

Browse files
vingu-linaroIngo Molnar
authored andcommitted
sched/fair: Fix insertion in rq->leaf_cfs_rq_list
Sargun reported a crash: "I picked up c40f7d7 sched/fair: Fix infinite loop in update_blocked_averages() by reverting a9e7f65 and put it on top of 4.19.13. In addition to this, I uninlined list_add_leaf_cfs_rq for debugging. This revealed a new bug that we didn't get to because we kept getting crashes from the previous issue. When we are running with cgroups that are rapidly changing, with CFS bandwidth control, and in addition using the cpusets cgroup, we see this crash. Specifically, it seems to occur with cgroups that are throttled and we change the allowed cpuset." The algorithm used to order cfs_rq in rq->leaf_cfs_rq_list assumes that it will walk down to root the 1st time a cfs_rq is used and we will finish to add either a cfs_rq without parent or a cfs_rq with a parent that is already on the list. But this is not always true in presence of throttling. Because a cfs_rq can be throttled even if it has never been used but other CPUs of the cgroup have already used all the bandwdith, we are not sure to go down to the root and add all cfs_rq in the list. Ensure that all cfs_rq will be added in the list even if they are throttled. [ mingo: Fix !CGROUPS build. ] Reported-by: Sargun Dhillon <[email protected]> Signed-off-by: Vincent Guittot <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Mike Galbraith <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Fixes: 9c2791f ("Fix hierarchical order in rq->leaf_cfs_rq_list") Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 5d299ea commit f678331

File tree

1 file changed

+28
-5
lines changed

1 file changed

+28
-5
lines changed

kernel/sched/fair.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,13 @@ static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
275275
return grp->my_q;
276276
}
277277

278-
static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
278+
static inline bool list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
279279
{
280280
struct rq *rq = rq_of(cfs_rq);
281281
int cpu = cpu_of(rq);
282282

283283
if (cfs_rq->on_list)
284-
return;
284+
return rq->tmp_alone_branch == &rq->leaf_cfs_rq_list;
285285

286286
cfs_rq->on_list = 1;
287287

@@ -310,7 +310,7 @@ static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
310310
* list.
311311
*/
312312
rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
313-
return;
313+
return true;
314314
}
315315

316316
if (!cfs_rq->tg->parent) {
@@ -325,7 +325,7 @@ static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
325325
* tmp_alone_branch to the beginning of the list.
326326
*/
327327
rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
328-
return;
328+
return true;
329329
}
330330

331331
/*
@@ -340,6 +340,7 @@ static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
340340
* of the branch
341341
*/
342342
rq->tmp_alone_branch = &cfs_rq->leaf_cfs_rq_list;
343+
return false;
343344
}
344345

345346
static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq)
@@ -435,8 +436,9 @@ static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
435436
return NULL;
436437
}
437438

438-
static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
439+
static inline bool list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
439440
{
441+
return true;
440442
}
441443

442444
static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq)
@@ -4995,6 +4997,12 @@ static void __maybe_unused unthrottle_offline_cfs_rqs(struct rq *rq)
49954997
}
49964998

49974999
#else /* CONFIG_CFS_BANDWIDTH */
5000+
5001+
static inline bool cfs_bandwidth_used(void)
5002+
{
5003+
return false;
5004+
}
5005+
49985006
static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq)
49995007
{
50005008
return rq_clock_task(rq_of(cfs_rq));
@@ -5186,6 +5194,21 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
51865194

51875195
}
51885196

5197+
if (cfs_bandwidth_used()) {
5198+
/*
5199+
* When bandwidth control is enabled; the cfs_rq_throttled()
5200+
* breaks in the above iteration can result in incomplete
5201+
* leaf list maintenance, resulting in triggering the assertion
5202+
* below.
5203+
*/
5204+
for_each_sched_entity(se) {
5205+
cfs_rq = cfs_rq_of(se);
5206+
5207+
if (list_add_leaf_cfs_rq(cfs_rq))
5208+
break;
5209+
}
5210+
}
5211+
51895212
assert_list_leaf_cfs_rq(rq);
51905213

51915214
hrtick_update(rq);

0 commit comments

Comments
 (0)