Skip to content

Conversation

@mykyta5
Copy link
Contributor

@mykyta5 mykyta5 commented Oct 30, 2025

No description provided.

@mykyta5 mykyta5 force-pushed the b4/timer_nolock branch 7 times, most recently from 1d87dcc to 348b530 Compare October 31, 2025 16:28
@mykyta5 mykyta5 force-pushed the b4/timer_nolock branch 2 times, most recently from 039158d to fac8ac6 Compare October 31, 2025 19:00
This series reworks implementation of BPF timer and workqueue APIs.
The goal is to make both timers and wq non-blocking, enabling their use
in NMI context.
Today this code relies on a bpf_spin_lock embedded in the map element to
serialize:
 * init of the async object,
 * setting/changing the callback and bpf_prog
 * starting/cancelling the timer/work
 * tearing down when the map element is deleted or the map’s user ref is
 dropped

Current approach works, but it does not allow using the API in the
contexts not allowing wait.

The series apply design similar to existing bpf_task_work
approach [1]: RCU and refcount to maintain lifetime guarantees and state
machine to handle data races.

This RFC doesn’t yet fully add NMI support for timers
and workqueue work, but it takes the first step by removing the spinlock
from struct bpf_async_cb.

---
1: https://lore.kernel.org/bpf/175864081800.1466288.3242104888617580131.git-patchwork-notify@kernel.org/

Signed-off-by: Mykyta Yatsenko <[email protected]>

--- b4-submit-tracking ---
{
  "series": {
    "revision": 1,
    "change-id": "20251028-timer_nolock-457f5b9daace",
    "prefixes": [
      "OFFLIST"
    ]
  }
}
Move logic for updating callback and prog owning it into a separate
function: bpf_async_update_callback(). This helps to localize data race
and will be reused in the next patches.

Signed-off-by: Mykyta Yatsenko <[email protected]>
Move the logic that swaps the bpf_prog in struct bpf_async_cb into a
dedicated helper to make follow-up patches simpler.

Signed-off-by: Mykyta Yatsenko <[email protected]>
Move the timer deletion logic into a dedicated bpf_timer_delete()
helper so it can be reused by later patches.

Signed-off-by: Mykyta Yatsenko <[email protected]>
To manage lifetime guarantees of the struct bpf_async_cb, when
no lock serializes mutations, introduce refcnt field into the struct.
Implement bpf_async_tryget() and bpf_async_put() to handle the refcnt.

Signed-off-by: Mykyta Yatsenko <[email protected]>
Remove lock from bpf_async_cb, refactor bpf_timer and bpf_wq kfuncs and
helpers to run without it.
bpf_async_cb lifetime is managed by the refcnt and RCU, so every
function that uses it has to apply RCU guard.
cancel_and_free() path detaches bpf_async_cb from the map value (struct
bpf_async_kern) and sets the state to the terminal BPF_ASYNC_FREED
atomically, concurrent readers may operate on detached bpf_async_cb
safely under RCU read lock.

Guarantee safe bpf_prog drop from the bpf_async_cb by handling
BPF_ASYNC_FREED state in bpf_async_update_callback().

Signed-off-by: Mykyta Yatsenko <[email protected]>
@kernel-patches-daemon-bpf kernel-patches-daemon-bpf bot force-pushed the bpf-next_base branch 6 times, most recently from de0745f to efe6edf Compare November 6, 2025 01:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant