History

workqueue: Add pool_workqueue to pending_pwqs list when unplugging multiple inactive works

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.

Matthew Brost committed 7 months ago

Commit 703ccb61 parent e3989781 file · +13 −1Browse files

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

Unified · Split

kernel/workqueue.c+13−1
@@ -1849,8 +1849,20 @@ static void unplug_oldest_pwq(struct workqueue_struct *wq) · 1848 unmodified lines
1849 raw_spin_lock_irq(&pwq->pool->lock);1849 raw_spin_lock_irq(&pwq->pool->lock);
1850 if (pwq->plugged) {1850 if (pwq->plugged) {
1851 pwq->plugged = false;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 kick_pool(pwq->pool);1864 kick_pool(pwq->pool);
1865 }
1854 }1866 }
1855 raw_spin_unlock_irq(&pwq->pool->lock);1867 raw_spin_unlock_irq(&pwq->pool->lock);
1856}1868}