From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from canpmsgout05.his.huawei.com (canpmsgout05.his.huawei.com [113.46.200.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9860E339875 for ; Mon, 18 May 2026 14:05:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.220 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779113120; cv=none; b=AIqG5AXF+bTcTzpcCFoE/f4MHTtE+oPnzrqq14+sQHlo16cF93C8KTaok7jaPLp1ZEkVkL68No9MsOUqs551gWI6wW12szzjIPj3BsqQH5PunzJ25UNJV3TFsr/iWxzubKq1eNbKGBJZwIWNskpLmIpRvA1cabv1+1XFrw9Qeac= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779113120; c=relaxed/simple; bh=0NB/3yCpuSJaiQEIEtb+I8d05t09YW3/Qxa4vk9WfP8=; h=Message-ID:Date:MIME-Version:From:Subject:To:CC:References: In-Reply-To:Content-Type; b=G9fEejE65tSoGyrgoLa6P11Q2hgdgYKmEZ3AzB6/O706aTGWO1pzKD8gQKC2ZGNmz0A/1sCezA0wQwhyCiNk9VJsfr0DK4arQH02elSCRRw7+IvqlRbcgGDHothXDwA0NWYWLDhWC8qFGAm/4rVhEHuGxh/UYTPZ09qWREAc2Mk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=XppuUkN/; arc=none smtp.client-ip=113.46.200.220 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="XppuUkN/" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=mFjN4dsc/Ie6X2dRLDl3+QOF1OUITzchGr0LGcTr7qE=; b=XppuUkN/8wxLU2VbFp3XyFDQyXuJXdMJZ7Qfhd18i4OINp/ohmKpNR9JTCHkZ2Y/9xRkHauvT Usg5Oio4hb7tuotkgiSm89GVAxtxXgblFT3xHmFB/FsDOvINlhIERyM4r2uYK4LoMGMRvzHZLxC mmMxw7iMMW8TgGMn7mg4NIY= Received: from mail.maildlp.com (unknown [172.19.162.144]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4gJzsb3Wmwz12LHX; Mon, 18 May 2026 21:58:11 +0800 (CST) Received: from kwepemr500016.china.huawei.com (unknown [7.202.195.68]) by mail.maildlp.com (Postfix) with ESMTPS id AF16740538; Mon, 18 May 2026 22:05:13 +0800 (CST) Received: from [10.67.111.161] (10.67.111.161) by kwepemr500016.china.huawei.com (7.202.195.68) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Mon, 18 May 2026 22:05:13 +0800 Message-ID: Date: Mon, 18 May 2026 22:05:12 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird From: chenjinghuang Subject: Re: [PATCH] [QUESTION] sched/fair: Potential vruntime underflow and unconstrained vlag scaling in rescale_entity() To: K Prateek Nayak , Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot CC: Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , References: <20260514132515.4009200-1-chenjinghuang2@huawei.com> In-Reply-To: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To kwepemr500016.china.huawei.com (7.202.195.68) Hello Prateek, On 5/14/2026 11:19 PM, K Prateek Nayak wrote: > Hello Chen, > > On 5/14/2026 6:55 PM, Chen Jinghuang wrote: >> Hi all, >> >> While analyzing cgroup weight adjustment scenarios in EEVDF, I observed a >> potential vruntime underflow issue caused by unconstrained vlag scaling in >> rescale_entity(). I would like to consult the community on whether this >> behavior is expected or if it represents a bug in the current implementation. >> >> I notice this my trace in a multi-level cgroup environment: >> >> CPU 3 >> CURRENT: PID: 12485 TASK: ffff003027f49440 COMMAND: "cpu_sim" >> ROOT_TASK_GROUP: ffffd714095439c0 CFS_RQ: ffff002fbfa3d140 >> TASK_GROUP: ffff00211fdfe800 CFS_RQ: ffff00213f2c9800 >> TASK_GROUP: ffff20300f2e7000 CFS_RQ: ffff0021190ca000 >> TASK_GROUP: ffff203016880c00 CFS_RQ: ffff00211ece4c00 >> [120] PID: 12485 TASK: ffff003027f49440 COMMAND: "cpu_sim" [CURRENT] >> TASK_GROUP: ffff203016884000 CFS_RQ: ffff002156835c00 >> [120] PID: 12649 TASK: ffff003027f4e540 COMMAND: "cpu_sim" >> >> Trace Metrics (Before/After rescale_entity and update_load_set): >> >> Before: weight: 209715, avruntime: 7738112562, vlag: 3638691801, vruntime: 4099420761 >> After: weight: 614, avruntime: 7738112562, vlag: 1242814741118, vruntime: 4099420761, limit: 724001488558 >> (vruntime/avruntime stay unchanged; the scaling only touches vlag, deadline, and vprot) >> >> Weight drop (209715->614) during __sched_group_set_shares() causes se->vlag >> to explode in rescale_entity(), surged from 3638691801 to 1242814741118. >> >> When the entity's vruntime is subsequently updated via se->vruntime = >> avruntime - se->vlag, the massive vlag value leads to a underflow of >> se->vruntime. >> >> Furthermore, I noticed that while entity_lag() typically applies a limit (calculated >> as 724001488558 in this instance) to constrain se->vlag, rescale_entity() performs >> the scaling without any such boundary checks. This allows se->vlag to exceed the >> theoretical limits expected by the EEVDF algorithm. > > The vlag, to begin with, would be within theoretical limits right? > Rescaling it should also put it under theoretical limits if I'm not > wrong. > >> >> Questions: >> 1. Is this se->vruntime underflow during drastic weight reduction considered acceptable >> within the current EEVDF design? > > All the vruntime considerations use signed delta from the zero_vruntime > so based on my understanding, it should be fine. > >> 2. Should rescale_entity() apply a limit check (similar to entity_lag()) immediately >> after scaling the vlag to prevent it from escaping reasonable bounds? >> >> Something like this? >> >> Signed-off-by: Chen Jinghuang >> --- >> kernel/sched/fair.c | 9 +++++++++ >> 1 file changed, 9 insertions(+) >> >> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c >> index 3ebec186f982..351e2f7b4b28 100644 >> --- a/kernel/sched/fair.c >> +++ b/kernel/sched/fair.c >> @@ -4046,6 +4046,15 @@ rescale_entity(struct sched_entity *se, unsigned long weight, bool rel_vprot) >> */ >> se->vlag = div64_long(se->vlag * old_weight, weight); > > This vlag is already calculated using entity_lag() which is within the > theoretical limits and is being scaled proportionally. > >> >> + { >> + u64 max_slice = cfs_rq_max_slice(cfs_rq_of(se)) + TICK_NSEC; > > This should also consider if "se" has the largest slice since it is > outside of the cfs_rq at this point. > >> + s64 limit; >> + >> + limit = calc_delta_fair(max_slice, se); > > update_load_set() is done after rescale_entity(). The above should > actually scale the limits based on the new weight. > In the trace data I recorded above, the limit = 724001488558 was computed by calc_delta_fair after se was scaled by update_load_set(), like this + rescale_entity(se, weight, rel_vprot); + + update_load_set(&se->load, weight); + + dl_record(se, cfs_rq, 1, _RET_IP_); dl_record() can capture the values of vlag, vruntime, limit and other data at the time of recording. The scaled se->vlag after rescale_entity() is 1242814741118, which does not fall within the expected range defined by the corresponding limit calculated for that se. >> + >> + se->vlag = clamp(se->vlag, -limit, limit); > > If we use the updated weight, se->vlag should already be within > those limits. > Currently, the calculation of limit is misplaced. Move it after update_load_set() to ensure it is calculated right after the weights for se are updated. The correvted code is as follows: diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 351e2f7b4b28..eb273a9047f1 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4104,6 +4104,11 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, update_load_set(&se->load, weight); + u64 max_slice = cfs_rq_max_slice(cfs_rq) + TICK_NSEC; + s64 limit = calc_delta_fair(max_slice, se); + + se->vlag = clamp(se->vlag, -limit, limit); + do { u32 divider = get_pelt_divider(&se->avg); se->avg.load_avg = div_u64(se_weight(se) * se->avg.load_sum, divider); >> + } >> + >> /* >> * DEADLINE >> * -------- >