diff options
Diffstat (limited to 'kernel/workqueue.c')
| -rw-r--r-- | kernel/workqueue.c | 25 | 
1 files changed, 17 insertions, 8 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 601d61150b65..bc2e09a8ea61 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3329,7 +3329,7 @@ EXPORT_SYMBOL_GPL(execute_in_process_context);   *   * Undo alloc_workqueue_attrs().   */ -static void free_workqueue_attrs(struct workqueue_attrs *attrs) +void free_workqueue_attrs(struct workqueue_attrs *attrs)  {  	if (attrs) {  		free_cpumask_var(attrs->cpumask); @@ -3345,7 +3345,7 @@ static void free_workqueue_attrs(struct workqueue_attrs *attrs)   *   * Return: The allocated new workqueue_attr on success. %NULL on failure.   */ -static struct workqueue_attrs *alloc_workqueue_attrs(void) +struct workqueue_attrs *alloc_workqueue_attrs(void)  {  	struct workqueue_attrs *attrs; @@ -4030,16 +4030,20 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq,   *   * Performs GFP_KERNEL allocations.   * + * Assumes caller has CPU hotplug read exclusion, i.e. get_online_cpus(). + *   * Return: 0 on success and -errno on failure.   */ -static int apply_workqueue_attrs(struct workqueue_struct *wq, +int apply_workqueue_attrs(struct workqueue_struct *wq,  			  const struct workqueue_attrs *attrs)  {  	int ret; -	apply_wqattrs_lock(); +	lockdep_assert_cpus_held(); + +	mutex_lock(&wq_pool_mutex);  	ret = apply_workqueue_attrs_locked(wq, attrs); -	apply_wqattrs_unlock(); +	mutex_unlock(&wq_pool_mutex);  	return ret;  } @@ -4152,16 +4156,21 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)  			mutex_unlock(&wq->mutex);  		}  		return 0; -	} else if (wq->flags & __WQ_ORDERED) { +	} + +	get_online_cpus(); +	if (wq->flags & __WQ_ORDERED) {  		ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);  		/* there should only be single pwq for ordering guarantee */  		WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||  			      wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),  		     "ordering guarantee broken for workqueue %s\n", wq->name); -		return ret;  	} else { -		return apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]); +		ret = apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);  	} +	put_online_cpus(); + +	return ret;  }  static int wq_clamp_max_active(int max_active, unsigned int flags,  |