diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 3cc90bfe24ed..02c2c21ff635 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -1516,10 +1516,24 @@ out: * To avoid these issues, punt to workqueue context when we are in a * timer callback. */ - if (this_cpu_read(hrtimer_running)) + if (this_cpu_read(hrtimer_running)) { queue_work(system_unbound_wq, &t->cb.delete_work); - else + return; + } + + if (IS_ENABLED(CONFIG_PREEMPT_RT)) { + /* If the timer is running on other CPU, also use a kworker to + * wait for the completion of the timer instead of trying to + * acquire a sleepable lock in hrtimer_cancel() to wait for its + * completion. + */ + if (hrtimer_try_to_cancel(&t->timer) >= 0) + kfree_rcu(t, cb.rcu); + else + queue_work(system_unbound_wq, &t->cb.delete_work); + } else { bpf_timer_delete_work(&t->cb.delete_work); + } } BPF_CALL_2(bpf_kptr_xchg, void *, map_value, void *, ptr)