History

workqueue: Add rcu lock check at the end of work item execution

Currently the workqueue just checks the atomic and locking states after work execution ends. However, sometimes, a work item may not unlock rcu after acquiring rcu_read_lock(). And as a result, it would cause rcu stall, but the rcu stall warning can not dump the work func, because the work has finished. In order to quickly discover those works that do not call rcu_read_unlock() after rcu_read_lock(), add the rcu lock check. Use rcu_preempt_depth() to check the work's rcu status. Normally, this value is 0. If this value is bigger than 0, it means the work are still holding rcu lock. If so, print err info and the work func. tj: Reworded the description for clarity. Minor formatting tweak.

Xuewen Yan committed 2 years ago

Commit 1a65a6d1 parent 85f0ab41 file · +5 −4Browse files

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

Unified · Split

kernel/workqueue.c+5−4
@@ -2640,11 +2640,12 @@ __acquires(&pool->lock) · 2639 unmodified lines
2640 lock_map_release(&lockdep_map);2640 lock_map_release(&lockdep_map);
2641 lock_map_release(&pwq->wq->lockdep_map);2641 lock_map_release(&pwq->wq->lockdep_map);
2642 2642
2643 if (unlikely(in_atomic() || lockdep_depth(current) > 0)) {2643 if (unlikely(in_atomic() || lockdep_depth(current) > 0 ||
2644 pr_err("BUG: workqueue leaked lock or atomic: %s/0x%08x/%d\n"2644 rcu_preempt_depth() > 0)) {
2645 pr_err("BUG: workqueue leaked lock or atomic: %s/0x%08x/%d/%d\n"
2645 " last function: %ps\n",2646 " last function: %ps\n",
2646 current->comm, preempt_count(), task_pid_nr(current),2647 current->comm, preempt_count(), rcu_preempt_depth(),
2647 worker->current_func);2648 task_pid_nr(current), worker->current_func);
2648 debug_show_held_locks(current);2649 debug_show_held_locks(current);
2649 dump_stack();2650 dump_stack();
2650 }2651 }