aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2017-07-23 08:36:15 -0400
committerTejun Heo <tj@kernel.org>2017-07-25 13:28:56 -0400
commit0a94efb5acbb6980d7c9ab604372d93cd507e4d8 (patch)
treef3ac747f0130dd53b5a704e56f1ccede24d90f31 /kernel/workqueue.c
parent5c0338c68706be53b3dc472e4308961c36e4ece1 (diff)
workqueue: implicit ordered attribute should be overridable
5c0338c68706 ("workqueue: restore WQ_UNBOUND/max_active==1 to be ordered") automatically enabled ordered attribute for unbound workqueues w/ max_active == 1. Because ordered workqueues reject max_active and some attribute changes, this implicit ordered mode broke cases where the user creates an unbound workqueue w/ max_active == 1 and later explicitly changes the related attributes. This patch distinguishes explicit and implicit ordered setting and overrides from attribute changes if implict. Signed-off-by: Tejun Heo <tj@kernel.org> Fixes: 5c0338c68706 ("workqueue: restore WQ_UNBOUND/max_active==1 to be ordered")
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index abe4a4971c24..7146ea70a62d 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -3744,8 +3744,12 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq,
3744 return -EINVAL; 3744 return -EINVAL;
3745 3745
3746 /* creating multiple pwqs breaks ordering guarantee */ 3746 /* creating multiple pwqs breaks ordering guarantee */
3747 if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs))) 3747 if (!list_empty(&wq->pwqs)) {
3748 return -EINVAL; 3748 if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
3749 return -EINVAL;
3750
3751 wq->flags &= ~__WQ_ORDERED;
3752 }
3749 3753
3750 ctx = apply_wqattrs_prepare(wq, attrs); 3754 ctx = apply_wqattrs_prepare(wq, attrs);
3751 if (!ctx) 3755 if (!ctx)
@@ -4129,13 +4133,14 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
4129 struct pool_workqueue *pwq; 4133 struct pool_workqueue *pwq;
4130 4134
4131 /* disallow meddling with max_active for ordered workqueues */ 4135 /* disallow meddling with max_active for ordered workqueues */
4132 if (WARN_ON(wq->flags & __WQ_ORDERED)) 4136 if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
4133 return; 4137 return;
4134 4138
4135 max_active = wq_clamp_max_active(max_active, wq->flags, wq->name); 4139 max_active = wq_clamp_max_active(max_active, wq->flags, wq->name);
4136 4140
4137 mutex_lock(&wq->mutex); 4141 mutex_lock(&wq->mutex);
4138 4142
4143 wq->flags &= ~__WQ_ORDERED;
4139 wq->saved_max_active = max_active; 4144 wq->saved_max_active = max_active;
4140 4145
4141 for_each_pwq(pwq, wq) 4146 for_each_pwq(pwq, wq)
@@ -5263,7 +5268,7 @@ int workqueue_sysfs_register(struct workqueue_struct *wq)
5263 * attributes breaks ordering guarantee. Disallow exposing ordered 5268 * attributes breaks ordering guarantee. Disallow exposing ordered
5264 * workqueues. 5269 * workqueues.
5265 */ 5270 */
5266 if (WARN_ON(wq->flags & __WQ_ORDERED)) 5271 if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
5267 return -EINVAL; 5272 return -EINVAL;
5268 5273
5269 wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL); 5274 wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL);