• T
    workqueue: fix cwq->nr_active underflow · 8a2e8e5d
    Tejun Heo 提交于
    cwq->nr_active is used to keep track of how many work items are active
    for the cpu workqueue, where 'active' is defined as either pending on
    global worklist or executing.  This is used to implement the
    max_active limit and workqueue freezing.  If a work item is queued
    after nr_active has already reached max_active, the work item doesn't
    increment nr_active and is put on the delayed queue and gets activated
    later as previous active work items retire.
    
    try_to_grab_pending() which is used in the cancellation path
    unconditionally decremented nr_active whether the work item being
    cancelled is currently active or delayed, so cancelling a delayed work
    item makes nr_active underflow.  This breaks max_active enforcement
    and triggers BUG_ON() in destroy_workqueue() later on.
    
    This patch fixes this bug by adding a flag WORK_STRUCT_DELAYED, which
    is set while a work item in on the delayed list and making
    try_to_grab_pending() decrement nr_active iff the work item is
    currently active.
    
    The addition of the flag enlarges cwq alignment to 256 bytes which is
    getting a bit too large.  It's scheduled to be reduced back to 128
    bytes by merging WORK_STRUCT_PENDING and WORK_STRUCT_CWQ in the next
    devel cycle.
    Signed-off-by: NTejun Heo <tj@kernel.org>
    Reported-by: NJohannes Berg <johannes@sipsolutions.net>
    8a2e8e5d
workqueue.h 12.1 KB