diff options
author | Tejun Heo | 2017-07-23 07:36:15 -0500 |
---|---|---|
committer | Greg Kroah-Hartman | 2017-08-11 11:09:00 -0500 |
commit | 34a08ae493f1970d5ce80dd3812b8dba4e5cbe22 (patch) | |
tree | 02f5cecfb03f2d71e6df69022bd05a5e7edea845 /kernel | |
parent | 0c787041504edd1739a5f8bd04bdd36b8fcb093c (diff) | |
download | kernel-omap-34a08ae493f1970d5ce80dd3812b8dba4e5cbe22.tar.gz kernel-omap-34a08ae493f1970d5ce80dd3812b8dba4e5cbe22.tar.xz kernel-omap-34a08ae493f1970d5ce80dd3812b8dba4e5cbe22.zip |
workqueue: implicit ordered attribute should be overridable
commit 0a94efb5acbb6980d7c9ab604372d93cd507e4d8 upstream.
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")
Cc: Holger Hoffstätte <holger@applied-asynchrony.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-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 137332379ed4..23231237f2e2 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -3647,8 +3647,12 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq, | |||
3647 | return -EINVAL; | 3647 | return -EINVAL; |
3648 | 3648 | ||
3649 | /* creating multiple pwqs breaks ordering guarantee */ | 3649 | /* creating multiple pwqs breaks ordering guarantee */ |
3650 | if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs))) | 3650 | if (!list_empty(&wq->pwqs)) { |
3651 | return -EINVAL; | 3651 | if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) |
3652 | return -EINVAL; | ||
3653 | |||
3654 | wq->flags &= ~__WQ_ORDERED; | ||
3655 | } | ||
3652 | 3656 | ||
3653 | ctx = apply_wqattrs_prepare(wq, attrs); | 3657 | ctx = apply_wqattrs_prepare(wq, attrs); |
3654 | 3658 | ||
@@ -4032,13 +4036,14 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active) | |||
4032 | struct pool_workqueue *pwq; | 4036 | struct pool_workqueue *pwq; |
4033 | 4037 | ||
4034 | /* disallow meddling with max_active for ordered workqueues */ | 4038 | /* disallow meddling with max_active for ordered workqueues */ |
4035 | if (WARN_ON(wq->flags & __WQ_ORDERED)) | 4039 | if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) |
4036 | return; | 4040 | return; |
4037 | 4041 | ||
4038 | max_active = wq_clamp_max_active(max_active, wq->flags, wq->name); | 4042 | max_active = wq_clamp_max_active(max_active, wq->flags, wq->name); |
4039 | 4043 | ||
4040 | mutex_lock(&wq->mutex); | 4044 | mutex_lock(&wq->mutex); |
4041 | 4045 | ||
4046 | wq->flags &= ~__WQ_ORDERED; | ||
4042 | wq->saved_max_active = max_active; | 4047 | wq->saved_max_active = max_active; |
4043 | 4048 | ||
4044 | for_each_pwq(pwq, wq) | 4049 | for_each_pwq(pwq, wq) |
@@ -5164,7 +5169,7 @@ int workqueue_sysfs_register(struct workqueue_struct *wq) | |||
5164 | * attributes breaks ordering guarantee. Disallow exposing ordered | 5169 | * attributes breaks ordering guarantee. Disallow exposing ordered |
5165 | * workqueues. | 5170 | * workqueues. |
5166 | */ | 5171 | */ |
5167 | if (WARN_ON(wq->flags & __WQ_ORDERED)) | 5172 | if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) |
5168 | return -EINVAL; | 5173 | return -EINVAL; |
5169 | 5174 | ||
5170 | wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL); | 5175 | wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL); |