diff options
author | Tejun Heo <tj@kernel.org> | 2017-07-23 08:36:15 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2017-07-25 13:28:56 -0400 |
commit | 0a94efb5acbb6980d7c9ab604372d93cd507e4d8 (patch) | |
tree | f3ac747f0130dd53b5a704e56f1ccede24d90f31 /kernel/workqueue.c | |
parent | 5c0338c68706be53b3dc472e4308961c36e4ece1 (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.c | 13 |
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); |