freenode
Kernel & Low-Level

Writeback drain stalls Tasks-RCU, panics hosts on BPF detach

Cgroup writeback cleanup can run for minutes without a Tasks-RCU quiescent state on lazy-preempt kernels, blocking ftrace and BPF unlinks until the hung-task detector fires.

Josef Bacik has posted a fix for a writeback cleanup path that can stall Tasks-RCU for minutes on modern preemptible kernels, turning routine BPF or ftrace detach into a host panic.

When a dying cgroup writeback domain is drained, the worker repeatedly switches attached inodes and used to call plain cond_resched() between passes. On kernels with full or lazy preemption, that call is a no-op. After the scheduler restricted preemption models, those are the only options on architectures that support lazy preemption, including arm64 and x86, so the loop never reports a Tasks-RCU quiescent state.

Bacik hit the failure on a 6.18 arm64 host in lazy mode: one worker spent more than 11 minutes draining a cgroup with millions of inodes. A BPF trampoline unlink then blocked in synchronize_rcu_tasks() while holding the trampoline mutex. Forty-two tasks piled up behind it in D state; the hung-task detector fired at 614 seconds and panicked the machine. Any BPF or ftrace detach concurrent with a long drain inherits that latency.

The patch reports a Tasks-RCU quiescent state on every drain pass so waiters are not held for the full cleanup. Tejun Heo, Paul McKenney, and Jan Kara backed the change for stable. They also flagged a deeper problem: many long kernel loops still rely only on cond_resched(), which no longer advances Tasks-RCU on the preemption models most systems run. Bacik is preparing a broader fix but wants the targeted drain change in first while machines are still going down.