• Tejun Heo's avatar
    workqueue: Implement disable/enable for (delayed) work items · 86898fa6
    Tejun Heo authored
    While (delayed) work items could be flushed and canceled, there was no way
    to prevent them from being queued in the future. While this didn't lead to
    functional deficiencies, it sometimes required a bit more effort from the
    workqueue users to e.g. sequence shutdown steps with more care.
    
    Workqueue is currently in the process of replacing tasklet which does
    support disabling and enabling. The feature is used relatively widely to,
    for example, temporarily suppress main path while a control plane operation
    (reset or config change) is in progress.
    
    To enable easy conversion of tasklet users and as it seems like an inherent
    useful feature, this patch implements disabling and enabling of work items.
    
    - A work item carries 16bit disable count in work->data while not queued.
      The access to the count is synchronized by the PENDING bit like all other
      parts of work->data.
    
    - If the count is non-zero, the work item cannot be queued. Any attempt to
      queue the work item fails and returns %false.
    
    - disable_work[_sync](), enable_work(), disable_delayed_work[_sync]() and
      enable_delayed_work() are added.
    
    v3: enable_work() was using local_irq_enable() instead of
        local_irq_restore() to undo IRQ-disable by work_grab_pending(). This is
        awkward now and will become incorrect as enable_work() will later be
        used from IRQ context too. (Lai)
    
    v2: Lai noticed that queue_work_node() wasn't checking the disable count.
        Fixed. queue_rcu_work() is updated to trigger warning if the inner work
        item is disabled.
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    Reviewed-by: default avatarLai Jiangshan <jiangshanlai@gmail.com>
    86898fa6
workqueue.c 225 KB