When we want to debug the workqueue stall, we can immediately make a panic to get the information we want. In some systems, it may be necessary to quickly reboot the system to escape from a workqueue lockup situation. In this case, we can control the number of stall detections to generate panic. workqueue.panic_on_stall sets the number times of the stall to trigger panic. 0 disables the panic on stall.
Showing the changes to kernel/workqueue.c (1 of 1 file). Show all
Unified · Split
| @@ -7398,6 +7398,9 @@ static struct timer_list wq_watchdog_timer; · 7397 unmodified lines | |||
| 7398 | static unsigned long wq_watchdog_touched = INITIAL_JIFFIES; | 7398 | static unsigned long wq_watchdog_touched = INITIAL_JIFFIES; |
| 7399 | static DEFINE_PER_CPU(unsigned long, wq_watchdog_touched_cpu) = INITIAL_JIFFIES; | 7399 | static DEFINE_PER_CPU(unsigned long, wq_watchdog_touched_cpu) = INITIAL_JIFFIES; |
| 7400 | 7400 | ||
| 7401 | static unsigned int wq_panic_on_stall; | ||
| 7402 | module_param_named(panic_on_stall, wq_panic_on_stall, uint, 0644); | ||
| 7403 | |||
| 7401 | /* | 7404 | /* |
| 7402 | * Show workers that might prevent the processing of pending work items. | 7405 | * Show workers that might prevent the processing of pending work items. |
| 7403 | * The only candidates are CPU-bound workers in the running state. | 7406 | * The only candidates are CPU-bound workers in the running state. |
| @@ -7449,6 +7452,16 @@ static void show_cpu_pools_hogs(void) · 45 unmodified lines | |||
| 7449 | rcu_read_unlock(); | 7452 | rcu_read_unlock(); |
| 7450 | } | 7453 | } |
| 7451 | 7454 | ||
| 7455 | static void panic_on_wq_watchdog(void) | ||
| 7456 | { | ||
| 7457 | static unsigned int wq_stall; | ||
| 7458 | |||
| 7459 | if (wq_panic_on_stall) { | ||
| 7460 | wq_stall++; | ||
| 7461 | BUG_ON(wq_stall >= wq_panic_on_stall); | ||
| 7462 | } | ||
| 7463 | } | ||
| 7464 | |||
| 7452 | static void wq_watchdog_reset_touched(void) | 7465 | static void wq_watchdog_reset_touched(void) |
| 7453 | { | 7466 | { |
| 7454 | int cpu; | 7467 | int cpu; |
| @@ -7521,6 +7534,9 @@ static void wq_watchdog_timer_fn(struct timer_list *unused) · 66 unmodified lines | |||
| 7521 | if (cpu_pool_stall) | 7534 | if (cpu_pool_stall) |
| 7522 | show_cpu_pools_hogs(); | 7535 | show_cpu_pools_hogs(); |
| 7523 | 7536 | ||
| 7537 | if (lockup_detected) | ||
| 7538 | panic_on_wq_watchdog(); | ||
| 7539 | |||
| 7524 | wq_watchdog_reset_touched(); | 7540 | wq_watchdog_reset_touched(); |
| 7525 | mod_timer(&wq_watchdog_timer, jiffies + thresh); | 7541 | mod_timer(&wq_watchdog_timer, jiffies + thresh); |
| 7526 | } | 7542 | } |