From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794401962; b=Rit0A5YIacRUhAs/b/2pocrxO6WLEr6eg9Bq+Sy5J1CLVjY7jG+KJXWuvnkvwNr1Co3F HeCFppeuuOx2zjg5czi8icFudo98JsCkLQBvWQuHDpmvYg4DgyeAnVo2/5clixevGnCIb 3edPdM687rjnRTSg6X/qSMhn8khrOqfhFv9hDFp9uAHJQPxispBL2aI+MF1UKB5jWiPfS G5onZvN279ZKsmUcD874ZNKeU/+s2YNeHrgKIYwqAXjVaC41vAIhoOD6N/pdqE6QselBu g4T8wKEvSR2Oj5aij+2NvkRZWRWlEDYLoL6zVNDU6dxWU0d17YfYWEP4Ou5toPcu6Ng== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794401962; h=DMARC-Filter:DKIM-Signature:Received:X-MC-Unique: X-Mimecast-MFC-AGG-ID:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Gm-Gg:X-Received: X-Received:Received:Date:From:To:Cc:Subject:Message-ID:References: MIME-Version:Content-Type:Content-Disposition: Content-Transfer-Encoding:In-Reply-To; bh=Sfjm76wcFaYplzSjvgbZRL4nEIoICacZtL8Z7ioFei4=; b=U8TvUG/wBhh9JbV0bOfMLA0wQqjC8ZXsLGDAsgTkChpZ2hP1PmgdIjWF2xG882KVNSCi 8FdXU2KylQ8oFXplvbHcDW4qYqoXx3Skg5e13RNw4E4SwwE0oyAs72xbJN9hgksmEKZjR 0Y8rDu5sPkLT+VZUECNfNtx4ooXSuZNCE3a05JoIY+wfqp4hWnxjY31UqmJw62PD03UTk Cnc1kLAzQFz6FfPm7HDuaHM2Ajb4uHJfhV5cholWW3jSdvFIWTIO7t2kGw5TcG+1DuRZi Uh0vcUGcp8iox3kA12KDGDAZigjiPZxBImcYKECN1di0/aAsL82/ePp9MfC6MCST5tA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Smiccc5X; dkim=pass header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=google header.b=egZJe0Wi; arc=none smtp.remote-ip=170.10.133.124 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7ECCA606A88E for ; Wed, 11 Nov 2026 12:59:21 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 7ECCA606A88E Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Smiccc5X; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=google header.b=egZJe0Wi DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1794401960; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Sfjm76wcFaYplzSjvgbZRL4nEIoICacZtL8Z7ioFei4=; b=Smiccc5XO49PMyUug1kF3pjsPszfftMnVBpgNlav+pQkype24Nk9GhCQZQfZ33DpJguM2D xlq52biitAoXbC+sEieXvnqjVAmE9jOfLRpq7tFCBErIySuHFQy6ZRe5Ojhux9HUPLhO6G CcKh0UEQCF6IU3sJbiqkImdrE57HOT0= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-468-oYnL5npAP4CPvbErbGspoQ-1; Wed, 11 Nov 2026 07:59:19 -0500 X-MC-Unique: oYnL5npAP4CPvbErbGspoQ-1 X-Mimecast-MFC-AGG-ID: oYnL5npAP4CPvbErbGspoQ_1794401958 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-48e0ef019a4so2718693f8f.3 for ; Wed, 11 Nov 2026 04:59:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1794401958; x=1795006758; darn=vger.kernel.org; h=in-reply-to:content-transfer-encoding:content-disposition :content-type:mime-version:references:message-id:subject:cc:to:from :date:from:to:cc:subject:date:message-id:reply-to:content-type; bh=Sfjm76wcFaYplzSjvgbZRL4nEIoICacZtL8Z7ioFei4=; b=egZJe0Wi2sgZjvTjgJJhuoiDyof/Zk202uF3RPLv7m98WY0lrJYAOScdPXsTc5/K6H iWOQD8Q8pfH+bo+CxmkCanycg34E778FPSycBkv9TT0zKvt9ZQos2kBtFwTiEay0ifT6 sSYwu/OX3X2UwHWh0WW6Yx1NOEsfd7LJni2XNK2svB60HCMrsPeai6p86u2aOxhQ15iZ uJ1mxwmz1LeTHMj1zCcCEmD3liecbAY3V3qZdZ6mJxbQCkb27aD7Zd21LnW/3QY3kvjE 3Eakp+wW7kTWdyz5OQLLcZi4t8I9nQnbeRV0QIejW3m79wGCkWLbU7k3Ux1HXOR9GZPL 9bPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794401958; x=1795006758; h=in-reply-to:content-transfer-encoding:content-disposition :content-type:mime-version:references:message-id:subject:cc:to:from :date:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=Sfjm76wcFaYplzSjvgbZRL4nEIoICacZtL8Z7ioFei4=; b=XRRKKZCwtrFnqwIWwopsnXxbP3kgd/9hC96pV8U25dz9o1SAoUfgu+c7OfBpPVjb9p nhvkcxBkM0M0576nVkydoW6M5S/y6e5ETmcWP244NoFJiRo1GyNm6tikKotSmDpSvsVn //RIUbirhg+aCCnZf0LzwZaiTTVA216ZUfsO+xH318SvDoklnsg57kVViSUNL64fkoJI rCcRZapniVTlLIVA2KPHqJtYhvF1cS4RiTSnEQQ+6qchJBiJgZ53B2GUZnbHkR8H7TEJ zuhSIi+LcqP0Rlvjh49UY3tBl0a0ZGRzBFEhu0L9qvKmLei/g7e0eaCxmBmiWI5JHp/D UNPQ== X-Forwarded-Encrypted: i=1; AL+hErEQs7D8PTnCmpHUrpc26NsatRqK9peUneZpIIoLJfBtqYY1A5G+blOgRidz2vly8zSyotT1szluhSrh/e8=@vger.kernel.org X-Gm-Message-State: APuU4Z/ctgy4Fz73adHl/qM6feTK5uXwrNEyxa3oLum1BK/sPjo+iwDP 4HYpDSwQSSsDIeuJ+6wzYM2pE4L0xbB8Q5cP3UKDUPZspcL0nl7gtR17pW9HWQHrAK3HJG+/kBq jUQ76Ms4WT+eG2kxKlcZiLP5AIHOah7J5QPW1XNtMJ7+so/J+7oR+06JRGLtIXSCn8Q== X-Gm-Gg: AYBFou3I50BTmG5vpx/Z/aAXSedPykr28460kN5IWWa+Cbg2R7MYMd06DOlGVBBVhtQ 1HAfkOmZzzk6OeSwVjNGMzwroB7+aAqBEMmsgrm46MxCeL+TkX5ykrW3h/+mRP2chVa3Y4UhhjT RBCI1HWIb1rcVV4+iCecHA+VQThRNcHUTBX0IDhhfk86lcqEzlLmEoz7rREwXJOu/tVJMVaUCgK LPYYqzNt+3PdDpmEwFo4CnoqCZGHAz1bISW0d+nXLE8bcbmxWgR4pxjuk39Fhvfqig5VuaHv68N 886di6X01LAEZb5JD0xc3qMKAFzN1N+FXY1p3t26jwxsG+PIbDtuYAOfLU2xEtjkhnttpYz4AdG w8+TUdBXItm9pRP4gPP6SW5bX92JWz8Q0aqCLqodsyy1/CvgfYL4FbhvdtRn48rFTBK5UtCV27P QFEc0= X-Received: by 2002:a05:6000:2502:b0:491:1e11:9ffe with SMTP id ffacd0b85a97d-499c48154f6mr4396748f8f.2.1794401957793; Wed, 11 Nov 2026 04:59:17 -0800 (PST) X-Received: by 2002:a05:6000:2502:b0:491:1e11:9ffe with SMTP id ffacd0b85a97d-499c48154f6mr4396705f8f.2.1794401957282; Wed, 11 Nov 2026 04:59:17 -0800 (PST) Received: from jlelli-thinkpadt14gen4.remote.csb ([151.29.158.90]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49842f2a1f9sm11424324f8f.15.2026.11.11.04.59.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Nov 2026 04:59:15 -0800 (PST) Date: Wed, 11 Nov 2026 13:59:12 +0100 From: Juri Lelli To: Mathieu Desnoyers Cc: peterz@infradead.org, mingo@redhat.com, vincent.guittot@linaro.org, linux-kernel@vger.kernel.org, tglx@kernel.org, will@kernel.org, boqun@kernel.org, dietmar.eggemann@arm.com, rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de, vschneid@redhat.com, kprateek.nayak@amd.com, luca.abeni@santannapisa.it, mathieu.poirier@linaro.org, longman@redhat.com, ridong.chen@linux.dev, tj@kernel.org, hannes@cmpxchg.org, mkoutny@suse.com, shuah@kernel.org, bigeasy@linutronix.de, clrkwllms@kernel.org, parri.andrea@gmail.com, m.szyprowski@samsung.com, kayracizmeci@gmail.com, weihengqiuu@gmail.com, cgroups@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rt-devel@lists.linux.dev, stable@vger.kernel.org Subject: Re: [PATCH v5 13/29] sched/deadline: Keep departing bandwidth across a root domain rebuild Message-ID: References: <20261108185406.1549770-1-mathieu.desnoyers@efficios.com> <20261108185406.1549770-14-mathieu.desnoyers@efficios.com> X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20261108185406.1549770-14-mathieu.desnoyers@efficios.com> Hello, On 08/11/26 13:53, Mathieu Desnoyers wrote: > A task that leaves SCHED_DEADLINE, or dies, keeps its bandwidth in > total_bw until its 0-lag time. This keeps admission control on the safe > side. Then inactive_task_timer() removes it from the root domain of the > task's CPU. Two things break this: > > - A rebuild of the accounting clears every root domain, then adds back > the deadline tasks of the cpusets. It misses a task out of the > class, or a dead one. Their bandwidth is dropped, and the timer > removes it again. > - A task out of the class can also move to another root domain. The > timer then takes total_bw from that one, which never had it. > > Either way, a root domain admits deadline tasks beyond its capacity > until the next rebuild. > > Fix this with dl_departed_list. A departing task goes on it with the > CPU it is on. A rebuild puts its bandwidth back in that CPU's root > domain. The timer removes it from there, and so does > sched_dl_overflow() for a task back in the class. > > A rebuild still drops the bandwidth of a task whose CPU is inactive, or > that dies during the rebuild. Each task records a count of the > rebuilds, dl_bw_gen, with its bandwidth. The timer removes nothing if a > rebuild came since. > > Make dl_cookie and dl_bw_visited() static: only deadline.c uses them. > > deadline_rebuild_test, added later in this series, fails every time on > v7.3 and v7.4-rc1 kernels. A one-CPU partition root admits two tasks of > 600ms every second there, where it has room for one. It passes with > this patch. > > Fixes: 387e31300b57 ("sched/deadline: Fix the update of the total -deadline utilization") > Fixes: f9a25f776d78 ("cpusets: Rebuild root domain deadline accounting information") > Cc: stable@vger.kernel.org > Signed-off-by: Mathieu Desnoyers > --- ... > +/* > + * A task that leaves SCHED_DEADLINE, or dies, before its 0-lag time keeps > + * its bandwidth in total_bw until that time. Then the inactive timer > + * removes it. Meanwhile the task may run anywhere, under another policy. > + * The timer holds a reference to it. > + * > + * A rebuild of the root domains' accounting (dl_clear_root_domains() and > + * dl_add_task_root_domain()) does not find such a task among the deadline > + * tasks of the cpusets. So dl_departed_list holds these tasks, from their > + * departure to their timer. The rebuild puts their bandwidth back in the > + * root domain of the CPU each one was on when it left. > + * > + * dl_bw_gen counts the rebuilds. Each task records its value when its > + * bandwidth is counted. If a rebuild dropped the bandwidth since, there > + * is nothing to remove. A rebuild drops it when the CPU recorded is no > + * longer active. It also drops the bandwidth of a task that dies while > + * the rebuild runs. The cpuset walk skips that task, and it was not dead > + * yet when the list was put back. It took me a bit of staring to (hopefully) understand better how dl_bw_gen works, maybe the following can help others? /* * dl_bw_gen numbers the rebuilds of the accounting: how many times the * root domains were wiped and reconstructed (dl_clear_root_domain * increments it). A task records the number of its last definite * state, counted or settled. That number dates the state: * * - Current: the bandwidth is counted, or a release settled it since * the rebuild began. A release subtracts; the walk of the cpusets * skips. * - One behind: the clear that just ran wiped it. The rebuild puts * it back. * - Older: an earlier rebuild dropped it. Leave it out; its release * removes nothing. * * Only equalities are compared, so the wrap of the counter is * harmless. */ > + * > + * dl_departed_lock protects the list and both counts. Take it with > + * interrupts disabled, under the task's rq lock or pi_lock or in the > + * rebuild, and before any dl_bw lock. > + */ > +static LIST_HEAD(dl_departed_list); > +static DEFINE_RAW_SPINLOCK(dl_departed_lock); > +static unsigned int dl_bw_gen; ... > +/* > + * Clear every root domain before a rebuild of their accounting, and count > + * the rebuild in dl_bw_gen. Put back the bandwidth of their servers. Put > + * back the bandwidth of the tasks on dl_departed_list, which no cpuset > + * holds as deadline tasks. Put each in the root domain of the CPU > + * recorded for it, or drop it if that CPU is not active. > + * dl_add_task_root_domain() then adds the deadline tasks of the cpusets. > + */ > +void dl_clear_root_domains(void) > { > - dl_clear_root_domain(cpu_rq(cpu)->rd); > + struct sched_dl_entity *dl_se; > + u64 cookie = ++dl_cookie; > + struct dl_bw *dl_b; > + int cpu; > + > + guard(raw_spinlock_irqsave)(&dl_departed_lock); > + dl_bw_gen++; > + for_each_possible_cpu(cpu) { > + if (!dl_bw_visited(cpu, cookie)) > + dl_clear_root_domain(cpu_rq(cpu)->rd); > + } > + list_for_each_entry(dl_se, &dl_departed_list, dl_departed_node) { > + cpu = dl_se->dl_departed_cpu; > + /* > + * Skip bandwidth that an earlier rebuild dropped. It is not > + * counted now, and its release removes nothing > + * (dl_task_release_bw()). > + */ > + if (dl_se->dl_bw_gen != dl_bw_gen - 1) > + continue; > + if (!cpu_active(cpu)) > + continue; Maybe additional info can again help (before the above)? /* * Drop the bandwidth of a task whose CPU is inactive. * That CPU no longer identifies the root domain that * counts it: a CPU going offline sits in the default root * domain by then, and the old one cannot be found back * from the recorded number. The release then removes * nothing, and no later rebuild restores it. */ > + dl_b = dl_bw_of(cpu); > + raw_spin_lock(&dl_b->lock); > + __dl_add(dl_b, dl_se->dl_bw, dl_bw_cpus(cpu)); > + raw_spin_unlock(&dl_b->lock); > + dl_se->dl_bw_gen = dl_bw_gen; > + } > } ... > static void switched_to_dl(struct rq *rq, struct task_struct *p) > { > cancel_inactive_timer(&p->dl); > + /* > + * A task on the departed list gets here when priority inheritance > + * boosts it back into the class before its 0-lag time. (A policy change > + * took it off the list in sched_dl_overflow().) The inactive timer no > + * longer removes its bandwidth: the task does when it leaves the class > + * again. So take it off the list. If the task moved to another root > + * domain meanwhile, it then takes the bandwidth from that root domain > + * instead. > + */ > + if (p->dl.dl_departed_cpu >= 0) > + dl_task_undepart(p); Can something like the following happen? And do we actually have a test for it? 1. T departs. A SCHED_DEADLINE task with bandwidth X leaves the class asleep, 0-lag still ahead. Per the design, X stays counted in rd(A)'s total_bw; T goes on dl_departed_list with dl_departed_cpu = A, and the inactive timer is armed as the designated releaser. So far so good — the record says "rd( A) owes X on T's behalf." 2. T migrates. T is now a fair task; it wakes and gets placed on a CPU in a different root domain, rd(B). task_cpu(T) = B. 3. T is PI-boosted back. A deadline waiter blocks on a mutex T holds -> rt_mutex_setprio -> class change -> switched_to_dl(): - cancel_inactive_timer() — the designated releaser is cancelled; - dl_task_undepart() — T is delisted and dl_departed_cpu is reset to −1. X is still sitting in rd(A)'s total_bw, but nothing anywhere remembers that. T runs in rd(B) on its donor's reservation. 4. The boost ends. T is deboosted out of the class -> switched_from_dl() -> task_non_contending() -> dl_task_release_bw(p, task_cpu(p)). T is not on the departed list, so the passed-in CPU is used: X is subtracted from rd(B). ... Apart from the above, the proposed approach looks alright. I now wonder, though, if an overall different scheme might make more sense. The half-baked solution we have today for rebuilding bandwidth information after domain changes is based on cpusets keeping track of DEADLINE tasks (with the indirect cpu <-> rd association complicating things further). With dl_departed_list, we now have one half of a per-domain membership structure; the accounted current tasks are the other half. Wouldn't it be better to move to a single list of accounted tasks (current and departed alike), keyed by their recorded home CPU, which turns the rebuild from a reconstruction into a re-partition? The dl_bw_gen machinery and the cpuset walk would both go away. I understand this would require some major restructuring of a number of patches in this set, so maybe we can think of doing it after this set lands (or the majority of the patches in here). Unless you are open to trying the idea (if it makes any sense) and see if it simplifies things? Thanks, Juri