aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorTejun Heo2017-07-23 07:36:15 -0500
committerGreg Kroah-Hartman2017-08-11 11:09:00 -0500
commit34a08ae493f1970d5ce80dd3812b8dba4e5cbe22 (patch)
tree02f5cecfb03f2d71e6df69022bd05a5e7edea845 /kernel
parent0c787041504edd1739a5f8bd04bdd36b8fcb093c (diff)
downloadkernel-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.c13
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);