Re: [PATCH RFC 0/3] workqueue: Take the pwq backend from the attrs

From: Tejun Heo

Date: Fri Sep 18 2026 - 22:13:46 EST


Hello, Breno.

On Fri, Sep 18, 2026 at 07:25:32AM -0700, Breno Leitao wrote:
> * Keep wq->max_active and wq->percpu_max_active both current. The two
> backends meter work differently, and a pwq must not end up metered
> against a limit nobody set. (this is the semi-conflictual with my previous
> commit 27db9dd7f84f3a ("workqueue: Give percpu workqueues their own
> max_active")

Both should stay current but I don't think they should be the same number.
max_active means different things in the two domains, per-CPU on one side and
across the whole workqueue on the other, so let's keep the two sets of values
separate and link them through scaling. On creation, the argument sets the
values for the domain the workqueue starts in and the other domain is derived
from it. Afterwards, each domain has its own interface, kernel and sysfs, and
adjusting one updates the other accordingly. That way a switch always lands
on a sensible limit without anyone having to think about it.

> * Create a ->concurrency_managed field in the wq attributes, used to
> decide whether to do concurrency management or not.
>
> * Move WQ_PERCPU onto an UNBOUND workqueue with WQ_AFFN_CPU affinity and
> the newly created ->concurrency_managed. WQ_PERCPU is then only the
> promise that the workqueue stays on that backend.

I'd rather not build percpu on top of CPU scope. Unbound with strict CPU
scope and percpu are different things. The pools, the metering and how the
unbound cpumask applies all differ, and both should keep existing. So, how
about making PERCPU its own scope? Whether concurrency management is then
expressed as a flag or an attribute doesn't matter much as long as it can be
turned on and off. WQ_PERCPU would mean that the workqueue can't leave the
PERCPU scope while CM can still be toggled.

BH can be a scope value too for consistency. It's only selectable on creation
and can't be switched into or out of, but having it in the same enum keeps
things uniform.

With scope carrying the backend, nice can apply verbatim on unbound and snap
to normal or highpri when the workqueue is on percpu, picked from the current
value. No need to restrict what can be written.

> Not done: the switching itself. concurrency_managed is fixed when the
> workqueue is created and is not exported through sysfs, so nothing takes a
> workqueue onto the backend or off it yet.

For PREFER_PERCPU type workqueues, which benefit from cmwq but don't depend
on it for correctness, there's no reason to block switching in either
direction. Having them follow the unbound cpumask when picking the queueing
CPU even while on percpu, the way the last patch keys that on WQ_PERCPU
rather than on the backend, makes sense for them.

Thanks.

--
tejun