sched/fair: Avoid overflow in place_entity()
Changes
1 files changed · +12 −4
| File | Status | Add | Del | Content |
|---|---|---|---|---|
| kernel/sched/fair.c | modified | +12 | −4 | View file |
kernel/sched/fair.c
View filediff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 57360f5..0f23644 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6463,12 +6463,20 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
load = cfs_rq->sum_weight;
if (curr && curr->on_rq)
load += avg_vruntime_weight(cfs_rq, curr->h_load.weight);
-
- weight = avg_vruntime_weight(cfs_rq, se->h_load.weight);
- lag *= load + weight;
if (WARN_ON_ONCE(!load))
load = 1;
- lag = div64_long(lag, load);
+
+ weight = avg_vruntime_weight(cfs_rq, se->h_load.weight);
+
+ /*
+ * Rewrite, because the product (W + w_i)*vl'_i might
+ * overflow s64:
+ *
+ * vl_i = (W + w_i)*vl'_i / W
+ * = (W*vl'_i + w_i*vl'_i) / W
+ * = vl'_i + w_i*vl'_i/W
+ */
+ lag += div64_long(lag * weight, load);
/*
* A heavy entity (relative to the tree) will pull the