mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: Juri Lelli <juri.lelli@redhat.com>
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 20/29] cgroup/cpuset: Give back the bandwidth an attach did not move
Date: Fri, 13 Nov 2026 08:12:32 -0500	[thread overview]
Message-ID: <e21aaf40-b929-444c-b707-3200e21d7301@efficios.com> (raw)
In-Reply-To: <avWEta7b9X4K6hF7@jlelli-thinkpadt14gen4.remote.csb>

Hi Juri,

> Humm, this is identity-blind: it cannot tell a task that can_attach()
> counted (its bandwidth really is inside sum_migrate_dl_bw) from one that
> became a deadline task in the can_attach() -> attach() gap, for which
> nothing was reserved, can it?

It cannot, and your example happens. There was no test for it.

I wrote a reproducer for it, in a 4-CPU guest. P is a one-CPU partition
root, which admits 95%. A process starts in the root cgroup, in the
root domain of the three other CPUs. One write to cgroup.procs moves
the process and all its threads into P. The process has:
- a main thread, the thread group leader. It is SCHED_OTHER and asleep.
- two sleeping deadline threads of 30% each.
- 2048 other sleeping threads, to make the move long.

During the move, another process calls sched_setattr() on the leader
and makes it a deadline task of 40%. cpuset_attach() handles the
leader first.

Without the changes below, each sched_setattr() that landed between
cpuset_can_attach() and cpuset_attach() gave the same result:
- P counts 40%, for the leader.
- The root domain the process left still counts the 60% of the two
   threads.
- When the two threads run, their bandwidth follows them, with no
   admission test. P then counts 100%.

> Not sure if we can consider tracking the counted tasks per task? The
> taskset is pinned between can_attach() and attach(), so we could build a
> list of (task, bw) pairs at can_attach() and let the gate check
> membership?

Yes. The planned next version does that, with a field in the task
instead of a list. It needs no allocation in cpuset_can_attach(), and
no lookup. Three things change:

1. This patch. cpuset_can_attach() records, with each task it counts,
    that room was made for it. cpuset_attach_task() moves the bandwidth
    of a task only if the task has that record. In the test above, P
    then counts the 60% of the two threads. The leader's 40% stays in
    the root domain it was admitted in. The patch has your Suggested-by.

2. Patch 21 of v5. The record is then the CPU the room was reserved on.
    cpuset_attach_task() moves the bandwidth to that CPU, and does not
    compute the CPU again. cpuset_can_attach() picks that CPU from the
    one the task is on. This matters for a sleeping task that wakes up
    during the attach and runs on another CPU. Computed again, the CPU
    differs, and the task misses its reservation.

    A wakeup cannot wait for the attach, and cannot fail. It does not
    need to. Between cpuset_can_attach() and cpuset_attach(), the
    bandwidth of each counted task is held in two places, as it is
    today. The root domain it leaves still counts it, and the
    destination has room reserved for it. A task that wakes up in
    between still has its old mask, so it runs in the root domain it
    leaves, which counts it. cpuset_attach_task() then moves the
    bandwidth to the reserved CPU and releases it in the root domain the
    task left.

3. A new patch. With 1 and 2 alone, the leader is in P after the move,
    and its bandwidth is still counted in the root domain it left. The
    cause is that sched_setattr() lands between the two steps at all.
    __sched_setscheduler() takes cpuset_mutex for a change that involves
    SCHED_DEADLINE, but the attach drops that mutex between
    cpuset_can_attach() and cpuset_attach(). So such a sched_setattr()
    now waits for an attach in progress, and so does sched_setaffinity()
    of a deadline task.

With the three, the move and the sched_setattr() never both succeed in
the test:
- If the sched_setattr() comes first, the move counts the three tasks
   and is refused with EBUSY.
- If it comes after, the leader has its new CPU and has not run on it.
   The call is refused with EPERM, as for any sleeping task moved to
   another partition.

A thread can still die during an attach. This patch already gives back
its part of the reservation.

Your finding led to one more change. In the test above, the bandwidth
of the two threads reached P with no admission test. Patch 23 of v5
does that on purpose: it moves the bandwidth of a task to the root
domain the task runs in. With isolcpus="domain", a cpuset that is not a
partition root can hold CPUs of two root domains. A deadline task in it
could then change root domain with no cpuset attach at all, and patch 23
moved its bandwidth unchecked.

Three new patches keep a deadline task in the root domain that counts
its bandwidth:
- Where a CPU is picked for the task, a CPU of that root domain is
   tried first. This covers a CPU offline, a mask change, a wakeup and
   a rebuild.
- A CPU offline fails with EBUSY if it takes the last CPU the task has
   in that root domain.
- A write to cpuset.cpus fails with EBUSY if it leaves the task no CPU
   in that root domain. cpuset makes a partition root that would do the
   same invalid.

The bandwidth of a task then goes to another root domain only by a
cpuset attach, which asks for room.

With admission control off, nothing is refused, and patch 23 still
moves the bandwidth. So an administrator gets past a refusal by writing
-1 to sched_rt_runtime_us. The two refusals are new behaviour for
user-space. I would like your opinion on them, and on whether that knob
is enough or a dedicated one is wanted.

The planned next version adds cases to deadline_bw_test for the changes
to the attach. Each is about a move between cpusets:
- a policy change during the move, with and without room in P;
- an affinity change during the move;
- a wakeup during the move, with and without room to spare;
- a thread that dies during the move;
- a move that another controller refuses;
- a move of a frozen task.
Four more cases cover the two refusals and the choice of a CPU.

About your sched-deadline-tests: I went through the branch you pointed
to. Four reproducers had no equivalent in deadline_bw_test, so I added
cases for them:
- a task stopped by SIGSTOP that leaves the class;
- a sleeping task that leaves the class after its CPU went offline;
- admission control off, with a task pinned to a CPU that goes offline;
- a deadline waiter that boosts two SCHED_OTHER owners through a chain
   of two mutexes.

They pass with the series. On v7.4-rc1, the first fails, and the third
failed in 6 guests of 8. The patch that was 11 in v5 fixes the first.
The one that was 13 fixes the third.

Thanks,

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com

  reply	other threads:[~2026-11-13 13:12 UTC|newest]

Thread overview: 86+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-08 18:53 [PATCH v5 00/29] sched/deadline: bandwidth accounting fixes and selftests Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 01/29] sched: Fix cpuset_mutex double unlock in __sched_setscheduler() Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 02/29] sched: Refuse SCHED_FLAG_KEEP_PARAMS that would change the policy or the class Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 03/29] sched/deadline: Do not admit bandwidth for parameters that are kept Mathieu Desnoyers
2026-11-09 12:42   ` Juri Lelli
2026-11-09 13:16     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 04/29] sched: Let a task boosted by a deadline waiter change its policy Mathieu Desnoyers
2026-11-09 13:38   ` Juri Lelli
2026-11-08 18:53 ` [PATCH v5 05/29] sched/deadline: Do not divide by zero active CPUs of a root domain Mathieu Desnoyers
2026-11-09 14:30   ` Juri Lelli
2026-11-09 14:57     ` Mathieu Desnoyers
2026-11-09 15:09       ` Juri Lelli
2026-11-09 15:22         ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 06/29] sched: Take cpuset_mutex for a deadline policy change only with pi Mathieu Desnoyers
2026-11-09 15:06   ` Juri Lelli
2026-11-09 15:22     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 07/29] sched/deadline: Do not lose a throttled task switched out and back Mathieu Desnoyers
2026-11-09 16:05   ` Juri Lelli
2026-11-09 16:29     ` Mathieu Desnoyers
2026-11-09 18:55       ` Mathieu Desnoyers
2026-11-09 18:56       ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 08/29] sched/deadline: Take a deadline boost from the waiter's rt_mutex node Mathieu Desnoyers
2026-11-10 11:14   ` Juri Lelli
2026-11-10 13:48     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 09/29] sched/deadline: Reset the deadline and the runtime with the parameters Mathieu Desnoyers
2026-11-10 13:18   ` Juri Lelli
2026-11-10 13:41     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 10/29] sched/deadline: Reset the donor's runtime at a deboost in the class Mathieu Desnoyers
2026-11-08 19:17   ` sashiko-bot
2026-11-09  2:56     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 11/29] sched/deadline: Release the bandwidth of a task that leaves the class asleep Mathieu Desnoyers
2026-11-10 19:47   ` Juri Lelli
2026-11-10 20:26     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 12/29] sched/deadline: Reject SCHED_DEADLINE on exited tasks Mathieu Desnoyers
2026-11-11  6:55   ` Juri Lelli
2026-11-08 18:53 ` [PATCH v5 13/29] sched/deadline: Keep departing bandwidth across a root domain rebuild Mathieu Desnoyers
2026-11-11 12:59   ` Juri Lelli
2026-11-11 15:35     ` Mathieu Desnoyers
2026-11-11 16:19       ` Peter Zijlstra
2026-11-11 19:19         ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 14/29] sched/deadline: Fix this_bw when a task is changed during a remote wakeup Mathieu Desnoyers
2026-11-11 13:49   ` Juri Lelli
2026-11-08 18:53 ` [PATCH v5 15/29] sched/deadline: Rebuild the root domains' accounting from the task list Mathieu Desnoyers
2026-11-11 14:24   ` Juri Lelli
2026-11-13 13:31     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 16/29] sched/deadline: Record the root domain holding a task's bandwidth Mathieu Desnoyers
2026-11-11 15:54   ` Juri Lelli
2026-11-13 13:33     ` Mathieu Desnoyers
2026-11-13 15:06       ` Juri Lelli
2026-11-08 18:53 ` [PATCH v5 17/29] sched/deadline: Leave a dying task out of a rebuild of the accounting Mathieu Desnoyers
2026-11-12  6:40   ` Juri Lelli
2026-11-13 13:34     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 18/29] sched/deadline: Move a task's bandwidth only where room was made Mathieu Desnoyers
2026-11-08 19:30   ` sashiko-bot
2026-11-09  2:57     ` Mathieu Desnoyers
2026-11-12  7:03   ` Juri Lelli
2026-11-13 13:35     ` Mathieu Desnoyers
2026-11-13 15:04       ` Andrea Parri
2026-11-13 15:20         ` Mathieu Desnoyers
2026-11-13  4:37   ` Waiman Long
2026-11-13 13:51     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 19/29] cgroup/cpuset: Wait for an attach before rebuilding the sched domains Mathieu Desnoyers
2026-11-12  7:50   ` Juri Lelli
2026-11-08 18:53 ` [PATCH v5 20/29] cgroup/cpuset: Give back the bandwidth an attach did not move Mathieu Desnoyers
2026-11-12  9:19   ` Juri Lelli
2026-11-13 13:12     ` Mathieu Desnoyers [this message]
2026-11-08 18:53 ` [PATCH v5 21/29] cgroup/cpuset: Reserve the bandwidth in the root domain a task moves to Mathieu Desnoyers
2026-11-08 19:32   ` sashiko-bot
2026-11-09  2:57     ` Mathieu Desnoyers
2026-11-08 18:53 ` [PATCH v5 22/29] sched/deadline: Make a rebuild use the CPU recorded with a task's bandwidth Mathieu Desnoyers
2026-11-08 19:25   ` sashiko-bot
2026-11-09  2:58     ` Mathieu Desnoyers
2026-11-08 18:54 ` [PATCH v5 23/29] sched/deadline: Move a task's bandwidth when it must leave its CPU Mathieu Desnoyers
2026-11-08 19:41   ` sashiko-bot
2026-11-09  2:58     ` Mathieu Desnoyers
2026-11-08 18:54 ` [PATCH v5 24/29] sched/deadline: Cancel the replenishment timer with the parameters Mathieu Desnoyers
2026-11-12  9:37   ` Juri Lelli
2026-11-08 18:54 ` [PATCH v5 25/29] sched/deadline: Count the bandwidth a boosted task is given Mathieu Desnoyers
2026-11-12 10:29   ` Juri Lelli
2026-11-08 18:54 ` [PATCH v5 26/29] sched/debug: Show the deadline bandwidth of each runqueue Mathieu Desnoyers
2026-11-12 10:36   ` Juri Lelli
2026-11-13 13:36     ` Mathieu Desnoyers
2026-11-13 15:04       ` Juri Lelli
2026-11-08 18:54 ` [PATCH v5 27/29] selftests/sched: Add a test of SCHED_DEADLINE policy round trips Mathieu Desnoyers
2026-11-08 18:54 ` [PATCH v5 28/29] selftests/sched: Test SCHED_DEADLINE bandwidth across a root domain rebuild Mathieu Desnoyers
2026-11-08 18:54 ` [PATCH v5 29/29] selftests/sched: Add a test of SCHED_DEADLINE bandwidth accounting Mathieu Desnoyers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e21aaf40-b929-444c-b707-3200e21d7301@efficios.com \
    --to=mathieu.desnoyers@efficios.com \
    --cc=bigeasy@linutronix.de \
    --cc=boqun@kernel.org \
    --cc=bsegall@google.com \
    --cc=cgroups@vger.kernel.org \
    --cc=clrkwllms@kernel.org \
    --cc=dietmar.eggemann@arm.com \
    --cc=hannes@cmpxchg.org \
    --cc=juri.lelli@redhat.com \
    --cc=kayracizmeci@gmail.com \
    --cc=kprateek.nayak@amd.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-rt-devel@lists.linux.dev \
    --cc=longman@redhat.com \
    --cc=luca.abeni@santannapisa.it \
    --cc=m.szyprowski@samsung.com \
    --cc=mathieu.poirier@linaro.org \
    --cc=mgorman@suse.de \
    --cc=mingo@redhat.com \
    --cc=mkoutny@suse.com \
    --cc=parri.andrea@gmail.com \
    --cc=peterz@infradead.org \
    --cc=ridong.chen@linux.dev \
    --cc=rostedt@goodmis.org \
    --cc=shuah@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=tglx@kernel.org \
    --cc=tj@kernel.org \
    --cc=vincent.guittot@linaro.org \
    --cc=vschneid@redhat.com \
    --cc=weihengqiuu@gmail.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®