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.
Showing the changes to kernel/workqueue.c (1 of 2 files). Show all
Unified · Split
| @@ -3744,8 +3744,12 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq, · 3743 unmodified lines | ||
| 3744 | 3744 | return -EINVAL; |
| 3745 | 3745 | |
| 3746 | 3746 | /* 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 | + } | |
| 3749 | 3753 | |
| 3750 | 3754 | ctx = apply_wqattrs_prepare(wq, attrs); |
| 3751 | 3755 | if (!ctx) |
| @@ -4129,13 +4133,14 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active) · 377 unmodified lines | ||
| 4129 | 4133 | struct pool_workqueue *pwq; |
| 4130 | 4134 | |
| 4131 | 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 | 4137 | return; |
| 4134 | 4138 | |
| 4135 | 4139 | max_active = wq_clamp_max_active(max_active, wq->flags, wq->name); |
| 4136 | 4140 | |
| 4137 | 4141 | mutex_lock(&wq->mutex); |
| 4138 | 4142 | |
| 4143 | + wq->flags &= ~__WQ_ORDERED; | |
| 4139 | 4144 | wq->saved_max_active = max_active; |
| 4140 | 4145 | |
| 4141 | 4146 | for_each_pwq(pwq, wq) |
| @@ -5263,7 +5268,7 @@ int workqueue_sysfs_register(struct workqueue_struct *wq) · 1121 unmodified lines | ||
| 5263 | 5268 | * attributes breaks ordering guarantee. Disallow exposing ordered |
| 5264 | 5269 | * workqueues. |
| 5265 | 5270 | */ |
| 5266 | − if (WARN_ON(wq->flags & __WQ_ORDERED)) | |
| 5271 | + if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) | |
| 5267 | 5272 | return -EINVAL; |
| 5268 | 5273 | |
| 5269 | 5274 | wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL); |