Skip to content

Commit 7224b31

Browse files
committed
Merge branch 'for-3.13-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
Pull workqueue fixes from Tejun Heo: "This contains one important fix. The NUMA support added a while back broke ordering guarantees on ordered workqueues. It was enforced by having single frontend interface with @max_active == 1 but the NUMA support puts multiple interfaces on unbound workqueues on NUMA machines thus breaking the ordered guarantee. This is fixed by disabling NUMA support on ordered workqueues. The above and a couple other patches were sitting in for-3.12-fixes but I forgot to push that out, so they ended up waiting a bit too long. My aplogies. Other fixes are minor" * 'for-3.13-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq: workqueue: fix pool ID allocation leakage and remove BUILD_BUG_ON() in init_workqueues workqueue: fix comment typo for __queue_work() workqueue: fix ordered workqueues in NUMA setups workqueue: swap set_cpus_allowed_ptr() and PF_NO_SETAFFINITY
2 parents de92a05 + 4e8b22b commit 7224b31

File tree

1 file changed

+37
-13
lines changed

1 file changed

+37
-13
lines changed

kernel/workqueue.c

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,9 @@ static DEFINE_HASHTABLE(unbound_pool_hash, UNBOUND_POOL_HASH_ORDER);
305305
/* I: attributes used when instantiating standard unbound pools on demand */
306306
static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS];
307307

308+
/* I: attributes used when instantiating ordered pools on demand */
309+
static struct workqueue_attrs *ordered_wq_attrs[NR_STD_WORKER_POOLS];
310+
308311
struct workqueue_struct *system_wq __read_mostly;
309312
EXPORT_SYMBOL(system_wq);
310313
struct workqueue_struct *system_highpri_wq __read_mostly;
@@ -518,14 +521,21 @@ static inline void debug_work_activate(struct work_struct *work) { }
518521
static inline void debug_work_deactivate(struct work_struct *work) { }
519522
#endif
520523

521-
/* allocate ID and assign it to @pool */
524+
/**
525+
* worker_pool_assign_id - allocate ID and assing it to @pool
526+
* @pool: the pool pointer of interest
527+
*
528+
* Returns 0 if ID in [0, WORK_OFFQ_POOL_NONE) is allocated and assigned
529+
* successfully, -errno on failure.
530+
*/
522531
static int worker_pool_assign_id(struct worker_pool *pool)
523532
{
524533
int ret;
525534

526535
lockdep_assert_held(&wq_pool_mutex);
527536

528-
ret = idr_alloc(&worker_pool_idr, pool, 0, 0, GFP_KERNEL);
537+
ret = idr_alloc(&worker_pool_idr, pool, 0, WORK_OFFQ_POOL_NONE,
538+
GFP_KERNEL);
529539
if (ret >= 0) {
530540
pool->id = ret;
531541
return 0;
@@ -1320,7 +1330,7 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
13201330

13211331
debug_work_activate(work);
13221332

1323-
/* if dying, only works from the same workqueue are allowed */
1333+
/* if draining, only works from the same workqueue are allowed */
13241334
if (unlikely(wq->flags & __WQ_DRAINING) &&
13251335
WARN_ON_ONCE(!is_chained_work(wq)))
13261336
return;
@@ -1736,16 +1746,17 @@ static struct worker *create_worker(struct worker_pool *pool)
17361746
if (IS_ERR(worker->task))
17371747
goto fail;
17381748

1749+
set_user_nice(worker->task, pool->attrs->nice);
1750+
1751+
/* prevent userland from meddling with cpumask of workqueue workers */
1752+
worker->task->flags |= PF_NO_SETAFFINITY;
1753+
17391754
/*
17401755
* set_cpus_allowed_ptr() will fail if the cpumask doesn't have any
17411756
* online CPUs. It'll be re-applied when any of the CPUs come up.
17421757
*/
1743-
set_user_nice(worker->task, pool->attrs->nice);
17441758
set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask);
17451759

1746-
/* prevent userland from meddling with cpumask of workqueue workers */
1747-
worker->task->flags |= PF_NO_SETAFFINITY;
1748-
17491760
/*
17501761
* The caller is responsible for ensuring %POOL_DISASSOCIATED
17511762
* remains stable across this function. See the comments above the
@@ -4106,7 +4117,7 @@ static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu,
41064117
static int alloc_and_link_pwqs(struct workqueue_struct *wq)
41074118
{
41084119
bool highpri = wq->flags & WQ_HIGHPRI;
4109-
int cpu;
4120+
int cpu, ret;
41104121

41114122
if (!(wq->flags & WQ_UNBOUND)) {
41124123
wq->cpu_pwqs = alloc_percpu(struct pool_workqueue);
@@ -4126,6 +4137,13 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
41264137
mutex_unlock(&wq->mutex);
41274138
}
41284139
return 0;
4140+
} else if (wq->flags & __WQ_ORDERED) {
4141+
ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);
4142+
/* there should only be single pwq for ordering guarantee */
4143+
WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||
4144+
wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),
4145+
"ordering guarantee broken for workqueue %s\n", wq->name);
4146+
return ret;
41294147
} else {
41304148
return apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
41314149
}
@@ -5009,10 +5027,6 @@ static int __init init_workqueues(void)
50095027
int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL };
50105028
int i, cpu;
50115029

5012-
/* make sure we have enough bits for OFFQ pool ID */
5013-
BUILD_BUG_ON((1LU << (BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT)) <
5014-
WORK_CPU_END * NR_STD_WORKER_POOLS);
5015-
50165030
WARN_ON(__alignof__(struct pool_workqueue) < __alignof__(long long));
50175031

50185032
pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC);
@@ -5051,13 +5065,23 @@ static int __init init_workqueues(void)
50515065
}
50525066
}
50535067

5054-
/* create default unbound wq attrs */
5068+
/* create default unbound and ordered wq attrs */
50555069
for (i = 0; i < NR_STD_WORKER_POOLS; i++) {
50565070
struct workqueue_attrs *attrs;
50575071

50585072
BUG_ON(!(attrs = alloc_workqueue_attrs(GFP_KERNEL)));
50595073
attrs->nice = std_nice[i];
50605074
unbound_std_wq_attrs[i] = attrs;
5075+
5076+
/*
5077+
* An ordered wq should have only one pwq as ordering is
5078+
* guaranteed by max_active which is enforced by pwqs.
5079+
* Turn off NUMA so that dfl_pwq is used for all nodes.
5080+
*/
5081+
BUG_ON(!(attrs = alloc_workqueue_attrs(GFP_KERNEL)));
5082+
attrs->nice = std_nice[i];
5083+
attrs->no_numa = true;
5084+
ordered_wq_attrs[i] = attrs;
50615085
}
50625086

50635087
system_wq = alloc_workqueue("events", 0, 0);

0 commit comments

Comments
 (0)