diff options
Diffstat (limited to 'kernel/workqueue.c')
| -rw-r--r-- | kernel/workqueue.c | 30 | 
1 files changed, 26 insertions, 4 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index a86688fabc55..ca937b0c3a96 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3577,6 +3577,13 @@ static bool wq_calc_node_cpumask(const struct workqueue_attrs *attrs, int node,  	/* yeap, return possible CPUs in @node that @attrs wants */  	cpumask_and(cpumask, attrs->cpumask, wq_numa_possible_cpumask[node]); + +	if (cpumask_empty(cpumask)) { +		pr_warn_once("WARNING: workqueue cpumask: online intersect > " +				"possible intersect\n"); +		return false; +	} +  	return !cpumask_equal(cpumask, attrs->cpumask);  use_dfl: @@ -3744,8 +3751,12 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq,  		return -EINVAL;  	/* creating multiple pwqs breaks ordering guarantee */ -	if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs))) -		return -EINVAL; +	if (!list_empty(&wq->pwqs)) { +		if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) +			return -EINVAL; + +		wq->flags &= ~__WQ_ORDERED; +	}  	ctx = apply_wqattrs_prepare(wq, attrs);  	if (!ctx) @@ -3929,6 +3940,16 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,  	struct workqueue_struct *wq;  	struct pool_workqueue *pwq; +	/* +	 * Unbound && max_active == 1 used to imply ordered, which is no +	 * longer the case on NUMA machines due to per-node pools.  While +	 * alloc_ordered_workqueue() is the right way to create an ordered +	 * workqueue, keep the previous behavior to avoid subtle breakages +	 * on NUMA. +	 */ +	if ((flags & WQ_UNBOUND) && max_active == 1) +		flags |= __WQ_ORDERED; +  	/* see the comment above the definition of WQ_POWER_EFFICIENT */  	if ((flags & WQ_POWER_EFFICIENT) && wq_power_efficient)  		flags |= WQ_UNBOUND; @@ -4119,13 +4140,14 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)  	struct pool_workqueue *pwq;  	/* disallow meddling with max_active for ordered workqueues */ -	if (WARN_ON(wq->flags & __WQ_ORDERED)) +	if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))  		return;  	max_active = wq_clamp_max_active(max_active, wq->flags, wq->name);  	mutex_lock(&wq->mutex); +	wq->flags &= ~__WQ_ORDERED;  	wq->saved_max_active = max_active;  	for_each_pwq(pwq, wq) @@ -5253,7 +5275,7 @@ int workqueue_sysfs_register(struct workqueue_struct *wq)  	 * attributes breaks ordering guarantee.  Disallow exposing ordered  	 * workqueues.  	 */ -	if (WARN_ON(wq->flags & __WQ_ORDERED)) +	if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))  		return -EINVAL;  	wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL);  | 
