History

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.

Tejun Heo committed 9 years ago

Commit 0a94efb1 parent 5c0338c2 files · +12 −5Browse files

Showing the changes to kernel/workqueue.c (1 of 2 files). Show all

Unified · Split

kernel/workqueue.c+9−4
@@ -3744,8 +3744,12 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq, · 3743 unmodified lines
37443744 return -EINVAL;
37453745
37463746 /* creating multiple pwqs breaks ordering guarantee */
3747− if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs)))
3748− return -EINVAL;
3747+ if (!list_empty(&wq->pwqs)) {
3748+ if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
3749+ return -EINVAL;
3750+
3751+ wq->flags &= ~__WQ_ORDERED;
3752+ }
37493753
37503754 ctx = apply_wqattrs_prepare(wq, attrs);
37513755 if (!ctx)
@@ -4129,13 +4133,14 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active) · 377 unmodified lines
41294133 struct pool_workqueue *pwq;
41304134
41314135 /* 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))
41334137 return;
41344138
41354139 max_active = wq_clamp_max_active(max_active, wq->flags, wq->name);
41364140
41374141 mutex_lock(&wq->mutex);
41384142
4143+ wq->flags &= ~__WQ_ORDERED;
41394144 wq->saved_max_active = max_active;
41404145
41414146 for_each_pwq(pwq, wq)
@@ -5263,7 +5268,7 @@ int workqueue_sysfs_register(struct workqueue_struct *wq) · 1121 unmodified lines
52635268 * attributes breaks ordering guarantee. Disallow exposing ordered
52645269 * workqueues.
52655270 */
5266− if (WARN_ON(wq->flags & __WQ_ORDERED))
5271+ if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
52675272 return -EINVAL;
52685273
52695274 wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL);