summaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c25
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);
3329 * 3329 *
3330 * Undo alloc_workqueue_attrs(). 3330 * Undo alloc_workqueue_attrs().
3331 */ 3331 */
3332static void free_workqueue_attrs(struct workqueue_attrs *attrs) 3332void free_workqueue_attrs(struct workqueue_attrs *attrs)
3333{ 3333{
3334 if (attrs) { 3334 if (attrs) {
3335 free_cpumask_var(attrs->cpumask); 3335 free_cpumask_var(attrs->cpumask);
@@ -3345,7 +3345,7 @@ static void free_workqueue_attrs(struct workqueue_attrs *attrs)
3345 * 3345 *
3346 * Return: The allocated new workqueue_attr on success. %NULL on failure. 3346 * Return: The allocated new workqueue_attr on success. %NULL on failure.
3347 */ 3347 */
3348static struct workqueue_attrs *alloc_workqueue_attrs(void) 3348struct workqueue_attrs *alloc_workqueue_attrs(void)
3349{ 3349{
3350 struct workqueue_attrs *attrs; 3350 struct workqueue_attrs *attrs;
3351 3351
@@ -4030,16 +4030,20 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq,
4030 * 4030 *
4031 * Performs GFP_KERNEL allocations. 4031 * Performs GFP_KERNEL allocations.
4032 * 4032 *
4033 * Assumes caller has CPU hotplug read exclusion, i.e. get_online_cpus().
4034 *
4033 * Return: 0 on success and -errno on failure. 4035 * Return: 0 on success and -errno on failure.
4034 */ 4036 */
4035static int apply_workqueue_attrs(struct workqueue_struct *wq, 4037int apply_workqueue_attrs(struct workqueue_struct *wq,
4036 const struct workqueue_attrs *attrs) 4038 const struct workqueue_attrs *attrs)
4037{ 4039{
4038 int ret; 4040 int ret;
4039 4041
4040 apply_wqattrs_lock(); 4042 lockdep_assert_cpus_held();
4043
4044 mutex_lock(&wq_pool_mutex);
4041 ret = apply_workqueue_attrs_locked(wq, attrs); 4045 ret = apply_workqueue_attrs_locked(wq, attrs);
4042 apply_wqattrs_unlock(); 4046 mutex_unlock(&wq_pool_mutex);
4043 4047
4044 return ret; 4048 return ret;
4045} 4049}
@@ -4152,16 +4156,21 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
4152 mutex_unlock(&wq->mutex); 4156 mutex_unlock(&wq->mutex);
4153 } 4157 }
4154 return 0; 4158 return 0;
4155 } else if (wq->flags & __WQ_ORDERED) { 4159 }
4160
4161 get_online_cpus();
4162 if (wq->flags & __WQ_ORDERED) {
4156 ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]); 4163 ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);
4157 /* there should only be single pwq for ordering guarantee */ 4164 /* there should only be single pwq for ordering guarantee */
4158 WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node || 4165 WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||
4159 wq->pwqs.prev != &wq->dfl_pwq->pwqs_node), 4166 wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),
4160 "ordering guarantee broken for workqueue %s\n", wq->name); 4167 "ordering guarantee broken for workqueue %s\n", wq->name);
4161 return ret;
4162 } else { 4168 } else {
4163 return apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]); 4169 ret = apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
4164 } 4170 }
4171 put_online_cpus();
4172
4173 return ret;
4165} 4174}
4166 4175
4167static int wq_clamp_max_active(int max_active, unsigned int flags, 4176static int wq_clamp_max_active(int max_active, unsigned int flags,