Skip to content

Commit 3bc1e71

Browse files
committed
workqueue: Don't implicitly make UNBOUND workqueues w/ @max_active==1 ordered
5c0338c ("workqueue: restore WQ_UNBOUND/max_active==1 to be ordered") automoatically promoted UNBOUND workqueues w/ @max_active==1 to ordered workqueues because UNBOUND workqueues w/ @max_active==1 used to be the way to create ordered workqueues and the new NUMA support broke it. These problems can be subtle and the fact that they can only trigger on NUMA machines made them even more difficult to debug. However, overloading the UNBOUND allocation interface this way creates other issues. It's difficult to tell whether a given workqueue actually needs to be ordered and users that legitimately want a min concurrency level wq unexpectedly gets an ordered one instead. With planned UNBOUND workqueue udpates to improve execution locality and more prevalence of chiplet designs which can benefit from such improvements, this isn't a state we wanna be in forever. There aren't that many UNBOUND w/ @max_active==1 users in the tree and the preceding patches audited all and converted them to alloc_ordered_workqueue() as appropriate. This patch removes the implicit promotion of UNBOUND w/ @max_active==1 workqueues to ordered ones. v2: v1 patch incorrectly dropped !list_empty(&wq->pwqs) condition in apply_workqueue_attrs_locked() which spuriously triggers WARNING and fails workqueue creation. Fix it. Signed-off-by: Tejun Heo <[email protected]> Reported-by: kernel test robot <[email protected]> Link: https://lore.kernel.org/oe-lkp/[email protected]
1 parent 8eb17dc commit 3bc1e71

File tree

3 files changed

+10
-30
lines changed

3 files changed

+10
-30
lines changed

Documentation/core-api/workqueue.rst

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,11 @@ may queue at the same time. Unless there is a specific need for
256256
throttling the number of active work items, specifying '0' is
257257
recommended.
258258

259-
Some users depend on the strict execution ordering of ST wq. The
260-
combination of ``@max_active`` of 1 and ``WQ_UNBOUND`` used to
261-
achieve this behavior. Work items on such wq were always queued to the
262-
unbound worker-pools and only one work item could be active at any given
263-
time thus achieving the same ordering property as ST wq.
264-
265-
In the current implementation the above configuration only guarantees
266-
ST behavior within a given NUMA node. Instead ``alloc_ordered_workqueue()`` should
267-
be used to achieve system-wide ST behavior.
259+
Some users depend on strict execution ordering where only one work item
260+
is in flight at any given time and the work items are processed in
261+
queueing order. While the combination of ``@max_active`` of 1 and
262+
``WQ_UNBOUND`` used to achieve this behavior, this is no longer the
263+
case. Use ``alloc_ordered_queue()`` instead.
268264

269265

270266
Example Execution Scenarios

include/linux/workqueue.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,6 @@ enum wq_flags {
392392
__WQ_DRAINING = 1 << 16, /* internal: workqueue is draining */
393393
__WQ_ORDERED = 1 << 17, /* internal: workqueue is ordered */
394394
__WQ_LEGACY = 1 << 18, /* internal: create*_workqueue() */
395-
__WQ_ORDERED_EXPLICIT = 1 << 19, /* internal: alloc_ordered_workqueue() */
396395

397396
/* BH wq only allows the following flags */
398397
__WQ_BH_ALLOWS = WQ_BH | WQ_HIGHPRI,
@@ -507,8 +506,7 @@ alloc_workqueue(const char *fmt, unsigned int flags, int max_active, ...);
507506
* Pointer to the allocated workqueue on success, %NULL on failure.
508507
*/
509508
#define alloc_ordered_workqueue(fmt, flags, args...) \
510-
alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | \
511-
__WQ_ORDERED_EXPLICIT | (flags), 1, ##args)
509+
alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | (flags), 1, ##args)
512510

513511
#define create_workqueue(name) \
514512
alloc_workqueue("%s", __WQ_LEGACY | WQ_MEM_RECLAIM, 1, (name))

kernel/workqueue.c

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5007,12 +5007,8 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq,
50075007
return -EINVAL;
50085008

50095009
/* creating multiple pwqs breaks ordering guarantee */
5010-
if (!list_empty(&wq->pwqs)) {
5011-
if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
5012-
return -EINVAL;
5013-
5014-
wq->flags &= ~__WQ_ORDERED;
5015-
}
5010+
if (!list_empty(&wq->pwqs) && WARN_ON(wq->flags & __WQ_ORDERED))
5011+
return -EINVAL;
50165012

50175013
ctx = apply_wqattrs_prepare(wq, attrs, wq_unbound_cpumask);
50185014
if (IS_ERR(ctx))
@@ -5333,15 +5329,6 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
53335329
return NULL;
53345330
}
53355331

5336-
/*
5337-
* Unbound && max_active == 1 used to imply ordered, which is no longer
5338-
* the case on many machines due to per-pod pools. While
5339-
* alloc_ordered_workqueue() is the right way to create an ordered
5340-
* workqueue, keep the previous behavior to avoid subtle breakages.
5341-
*/
5342-
if ((flags & WQ_UNBOUND) && max_active == 1)
5343-
flags |= __WQ_ORDERED;
5344-
53455332
/* see the comment above the definition of WQ_POWER_EFFICIENT */
53465333
if ((flags & WQ_POWER_EFFICIENT) && wq_power_efficient)
53475334
flags |= WQ_UNBOUND;
@@ -5564,14 +5551,13 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
55645551
if (WARN_ON(wq->flags & WQ_BH))
55655552
return;
55665553
/* disallow meddling with max_active for ordered workqueues */
5567-
if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
5554+
if (WARN_ON(wq->flags & __WQ_ORDERED))
55685555
return;
55695556

55705557
max_active = wq_clamp_max_active(max_active, wq->flags, wq->name);
55715558

55725559
mutex_lock(&wq->mutex);
55735560

5574-
wq->flags &= ~__WQ_ORDERED;
55755561
wq->saved_max_active = max_active;
55765562
if (wq->flags & WQ_UNBOUND)
55775563
wq->saved_min_active = min(wq->saved_min_active, max_active);
@@ -7028,7 +7014,7 @@ int workqueue_sysfs_register(struct workqueue_struct *wq)
70287014
* attributes breaks ordering guarantee. Disallow exposing ordered
70297015
* workqueues.
70307016
*/
7031-
if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
7017+
if (WARN_ON(wq->flags & __WQ_ORDERED))
70327018
return -EINVAL;
70337019

70347020
wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL);

0 commit comments

Comments
 (0)