Re: [PATCH] Docs/admin-guide/cgroup-v2: document hierarchical cpu.max throttling behavior

Shaojie Sun <[email protected]> Mon, 27 Jul 2026 11:18:55 +0800
Newsgroups org.kernel.vger.cgroups,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Hi, Michal.

On Fri, 24 Jul 2026 13:21:46, Michal wrote:
>On Fri, Jul 24, 2026 at 06:25:00PM +0800, Shaojie Sun <[email protected]> wrote:
>> diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
>> index 14b8c571c0d1..3572d3e7f688 100644
>> --- a/Documentation/admin-guide/cgroup-v2.rst
>> +++ b/Documentation/admin-guide/cgroup-v2.rst
>
>> +	                                       and the resulting
>> +	throttling may reflect the combined effect of multiple levels
>> +	rather than any single level's limit alone (this differs from
>> +	other Limits-type controllers such as memory.max and io.max,
>> +	where the most restrictive limit along the hierarchy is
>> +	applied).
>
>I'm not sure from the description what the "combined effect" is.
>Can you give an example where the cpu.max differs from that Limits-type
>semantics?

Here is an example to illustrate the difference. Consider:
  Parent:  cpu.max = 50000 100000 (50%)
  Child:   cpu.max = 20000 100000 (20%)
With cpu.max, when the child's processes consume CPU, throttling can be 
triggered by either the child's own limit or the parent's limit 
independently — both levels participate in enforcement. This is visible
in cpu.stat : the throttled_usec counter can accumulate non-zero values
at both the child and parent level. Even when the child's quota is 
smaller than the parent's (20 < 50), the parent's limit still
participates; conversely, when a child's quota is larger than the
parent's, the child's own limit still participates.

Compare this with memory.max. If we had:
  Parent:  memory.max = 50M
  Child:   memory.max = 20M
The effective limit for the child is simply min(20M, 50M) = 20M — only the
most restrictive limit along the path applies. The child will never see an
OOM triggered by the parent's 50M limit before reaching its own 20M.

In short: cpu.max enforcement is per-level independent — every level with 
cpu.max configured can independently throttle the group, and cpu.stat 
counters at multiple levels can all accumulate throttled_usec for the same
workload. memory.max only enforces the tightest limit along the path.

Thanks,
Shaojie Sun