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

From: Tejun Heo

Date: Tue Sep 22 2026 - 17:54:52 EST


Hello, Breno.

On Tue, Sep 22, 2026 at 03:34:48AM -0700, Breno Leitao wrote:
> Right, I will create a function that maps/scale one to another. Maybe
> the following?

Unbound max_active is distributed among nodes, with min_active as the
floor on each node, so I think the conversion should account for both.
One possibility, using:

U = unbound max_active, the system-wide target
L = unbound min_active, the floor on each node
P = percpu_max_active, the limit on each CPU
N = online CPUs in the effective unbound mask, at least 1

Setting P:
U = min(P * N, WQ_MAX_ACTIVE)
L = P

Setting U:
L = min(L, U)
P = max(DIV_ROUND_UP(U, N), L)

Setting L:
L = clamp(L, 0, U)
P = max(DIV_ROUND_UP(U, N), L)

This would carry the minimum concurrency in both directions. Clipping L
when lowering U preserves the existing setter's behavior. The cap and
rounding make the conversion approximate. We could derive the other
domain on explicit configuration changes and leave scope changes and
hotplug to use the saved values, with hotplug continuing to redistribute
U through the existing mechanism.

> Sure, and probably call them from wq_adjust_max_active(), so,
> independent of the one that is being set (percpu or unbound), it will
> change the other as well according to the function above.

I think separate kernel entry points and sysfs knobs for the two domains
would be clearer. Each would have a fixed meaning regardless of the
current scope. The conversion could happen in those setters, with
wq_adjust_max_active() publishing the saved limits and handling freezing.

> Oh, interesting, so, we are going to have CM toggable even for
> WQ_PERCPU and also for WQ_UNBOUND+WQ_AFFN_PERCPU, is this right?

The attribute could be changed in any scope, with its value taking effect
only in PERCPU scope. Maybe give it a percpu_ prefix to make that clear?

> Once we have it, what will be the difference between
> WQ_UNBOUND+WQ_AFFN_PERCPU+CM from WQ_PERCPU? They look exactly the same
> from a user perspective, no?

WQ_PERCPU declares that per-CPU affinity is required for correctness, so
the workqueue cannot leave PERCPU scope. WQ_PREFER_PERCPU starts in that
scope but permits scope changes and follows the unbound cpumask when
selecting the queueing CPU.

> I understand that scope means 'enum wq_affn_scope affn_scope', so, you
> want a WQ_AFFN_BH, right?

Yes. Scope is largely selecting the backend, and BH fits there. It remains
selectable only at creation, with no switching into or out of it.

> - echo -5 > nice succeeds and stores -5, whatever scope the wq is in
> - For WQ_PERCPU it runs on the highpri pool (nice -20 in practice)
> - echo 0 > nice, will turn the WQ_PERCPU workqueue into the normal
> pool.

I'd map only -20 to the highpri pool in PERCPU scope and everything else
to normal. The requested nice value would stay stored and apply verbatim
when using an unbound backend.

> Is this the final state you are envisioning?

How about PERCPU and BH scopes, with PREFER as a modifier of PERCPU like
CM? CM controls concurrency management. PREFER allows affinity to be
relaxed. WQ_PREFER_PERCPU would set the initial scope and modifier. We'd
still need to preserve the correctness requirement declared by
WQ_PERCPU when changing attributes.

These are suggestions. If you find a better way during implementation,
please go with that.

Thanks.

--
tejun