In unplug_oldest_pwq(), the first inactive work item on the pool_workqueue is activated correctly. However, if multiple inactive works exist on the same pool_workqueue, subsequent works fail to activate because wq_node_nr_active.pending_pwqs is empty — the list insertion is skipped when the pool_workqueue is plugged. Fix this by checking for additional inactive works in unplug_oldest_pwq() and updating wq_node_nr_active.pending_pwqs accordingly.
Showing the changes to kernel/workqueue.c (1 of 1 file). Show all
Unified · Split
| @@ -1849,8 +1849,20 @@ static void unplug_oldest_pwq(struct workqueue_struct *wq) · 1848 unmodified lines | ||
| 1849 | 1849 | raw_spin_lock_irq(&pwq->pool->lock); |
| 1850 | 1850 | if (pwq->plugged) { |
| 1851 | 1851 | pwq->plugged = false; |
| 1852 | − if (pwq_activate_first_inactive(pwq, true)) | |
| 1852 | + if (pwq_activate_first_inactive(pwq, true)) { | |
| 1853 | + /* | |
| 1854 | + * While plugged, queueing skips activation which | |
| 1855 | + * includes bumping the nr_active count and adding the | |
| 1856 | + * pwq to nna->pending_pwqs if the count can't be | |
| 1857 | + * obtained. We need to restore both for the pwq being | |
| 1858 | + * unplugged. The first call activates the first | |
| 1859 | + * inactive work item and the second, if there are more | |
| 1860 | + * inactive, puts the pwq on pending_pwqs. | |
| 1861 | + */ | |
| 1862 | + pwq_activate_first_inactive(pwq, false); | |
| 1863 | + | |
| 1853 | 1864 | kick_pool(pwq->pool); |
| 1865 | + } | |
| 1854 | 1866 | } |
| 1855 | 1867 | raw_spin_unlock_irq(&pwq->pool->lock); |
| 1856 | 1868 | } |