Re: [PATCHv3 bpf-next 02/24] bpf: Use mutex lock pool for bpf trampolines

2026-03-16 Thread Jiri Olsa
On Mon, Mar 16, 2026 at 08:35:14AM +, [email protected] wrote:
> > diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
> > index f02254a21585..9923703a1544 100644
> > --- a/kernel/bpf/trampoline.c
> > +++ b/kernel/bpf/trampoline.c
> 
> [ ... ]
> 
> > +/*
> > + * We keep 32 trampoline locks (5 bits) in the pool, because there
> > + * is 48 (MAX_LOCK_DEPTH) locks limit allowed to be simultaneously
> > + * held by task.
> > + */
> > +#define TRAMPOLINE_LOCKS_BITS 5
> > +#define TRAMPOLINE_LOCKS_TABLE_SIZE (1 << TRAMPOLINE_LOCKS_BITS)
> > +
> > +static struct {
> > +   struct mutex mutex;
> > +   struct lock_class_key key;
> > +} trampoline_locks[TRAMPOLINE_LOCKS_TABLE_SIZE];
> 
> During v1 review, Alexei asked to add a comment explaining both the
> pool size of 32 and why per-lock class keys are needed:
> 
> https://lore.kernel.org/bpf/caadnvql_jpe_7a55htn5cyyoxwchahik3+cdeoeurqzauf+...@mail.gmail.com/
> 
> The comment explains the 32 count (MAX_LOCK_DEPTH limit), but does
> it also need to mention why each lock has its own lock_class_key?
> Without that, it is not obvious that distinct keys are required to
> avoid lockdep "recursive locking" warnings when
> trampoline_lock_all() acquires all 32 pool mutexes simultaneously.

yep, will add

jirka

> 
> 
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
> 
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/23133791558




Re: [PATCHv3 bpf-next 02/24] bpf: Use mutex lock pool for bpf trampolines

2026-03-16 Thread bot+bpf-ci
> diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
> index f02254a21585..9923703a1544 100644
> --- a/kernel/bpf/trampoline.c
> +++ b/kernel/bpf/trampoline.c

[ ... ]

> +/*
> + * We keep 32 trampoline locks (5 bits) in the pool, because there
> + * is 48 (MAX_LOCK_DEPTH) locks limit allowed to be simultaneously
> + * held by task.
> + */
> +#define TRAMPOLINE_LOCKS_BITS 5
> +#define TRAMPOLINE_LOCKS_TABLE_SIZE (1 << TRAMPOLINE_LOCKS_BITS)
> +
> +static struct {
> + struct mutex mutex;
> + struct lock_class_key key;
> +} trampoline_locks[TRAMPOLINE_LOCKS_TABLE_SIZE];

During v1 review, Alexei asked to add a comment explaining both the
pool size of 32 and why per-lock class keys are needed:

https://lore.kernel.org/bpf/caadnvql_jpe_7a55htn5cyyoxwchahik3+cdeoeurqzauf+...@mail.gmail.com/

The comment explains the 32 count (MAX_LOCK_DEPTH limit), but does
it also need to mention why each lock has its own lock_class_key?
Without that, it is not obvious that distinct keys are required to
avoid lockdep "recursive locking" warnings when
trampoline_lock_all() acquires all 32 pool mutexes simultaneously.


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/23133791558

[PATCHv3 bpf-next 02/24] bpf: Use mutex lock pool for bpf trampolines

2026-03-16 Thread Jiri Olsa
Adding mutex lock pool that replaces bpf trampolines mutex.

For tracing_multi link coming in following changes we need to lock all
the involved trampolines during the attachment. This could mean thousands
of mutex locks, which is not convenient.

As suggested by Andrii we can replace bpf trampolines mutex with mutex
pool, where each trampoline is hash-ed to one of the locks from the pool.

It's better to lock all the pool mutexes (32 at the moment) than
thousands of them.

There is 48 (MAX_LOCK_DEPTH) lock limit allowed to be simultaneously
held by task, so we need to keep 32 mutexes (5 bits) in the pool, so
when we lock them all in following changes the lockdep won't scream.

Removing the mutex_is_locked in bpf_trampoline_put, because we removed
the mutex from bpf_trampoline.

Suggested-by: Andrii Nakryiko 
Signed-off-by: Jiri Olsa 
---
 include/linux/bpf.h |  2 --
 kernel/bpf/trampoline.c | 76 -
 2 files changed, 52 insertions(+), 26 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 05b34a6355b0..1d900f49aff5 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1335,8 +1335,6 @@ struct bpf_trampoline {
/* hlist for trampoline_ip_table */
struct hlist_node hlist_ip;
struct ftrace_ops *fops;
-   /* serializes access to fields of this trampoline */
-   struct mutex mutex;
refcount_t refcnt;
u32 flags;
u64 key;
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index f02254a21585..9923703a1544 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -30,6 +30,34 @@ static struct hlist_head 
trampoline_ip_table[TRAMPOLINE_TABLE_SIZE];
 /* serializes access to trampoline tables */
 static DEFINE_MUTEX(trampoline_mutex);
 
+/*
+ * We keep 32 trampoline locks (5 bits) in the pool, because there
+ * is 48 (MAX_LOCK_DEPTH) locks limit allowed to be simultaneously
+ * held by task.
+ */
+#define TRAMPOLINE_LOCKS_BITS 5
+#define TRAMPOLINE_LOCKS_TABLE_SIZE (1 << TRAMPOLINE_LOCKS_BITS)
+
+static struct {
+   struct mutex mutex;
+   struct lock_class_key key;
+} trampoline_locks[TRAMPOLINE_LOCKS_TABLE_SIZE];
+
+static struct mutex *select_trampoline_lock(struct bpf_trampoline *tr)
+{
+   return &trampoline_locks[hash_64((u64)(uintptr_t) tr, 
TRAMPOLINE_LOCKS_BITS)].mutex;
+}
+
+static void trampoline_lock(struct bpf_trampoline *tr)
+{
+   mutex_lock(select_trampoline_lock(tr));
+}
+
+static void trampoline_unlock(struct bpf_trampoline *tr)
+{
+   mutex_unlock(select_trampoline_lock(tr));
+}
+
 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
 static int bpf_trampoline_update(struct bpf_trampoline *tr, bool 
lock_direct_mutex);
 
@@ -69,9 +97,9 @@ static int bpf_tramp_ftrace_ops_func(struct ftrace_ops *ops, 
unsigned long ip,
 
if (cmd == FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF) {
/* This is called inside register_ftrace_direct_multi(), so
-* tr->mutex is already locked.
+* trampoline's mutex is already locked.
 */
-   lockdep_assert_held_once(&tr->mutex);
+   lockdep_assert_held_once(select_trampoline_lock(tr));
 
/* Instead of updating the trampoline here, we propagate
 * -EAGAIN to register_ftrace_direct(). Then we can
@@ -91,7 +119,7 @@ static int bpf_tramp_ftrace_ops_func(struct ftrace_ops *ops, 
unsigned long ip,
}
 
/* The normal locking order is
-*tr->mutex => direct_mutex (ftrace.c) => ftrace_lock (ftrace.c)
+*select_trampoline_lock(tr) => direct_mutex (ftrace.c) => 
ftrace_lock (ftrace.c)
 *
 * The following two commands are called from
 *
@@ -99,12 +127,12 @@ static int bpf_tramp_ftrace_ops_func(struct ftrace_ops 
*ops, unsigned long ip,
 *   cleanup_direct_functions_after_ipmodify
 *
 * In both cases, direct_mutex is already locked. Use
-* mutex_trylock(&tr->mutex) to avoid deadlock in race condition
-* (something else is making changes to this same trampoline).
+* mutex_trylock(select_trampoline_lock(tr)) to avoid deadlock in race 
condition
+* (something else holds the same pool lock).
 */
-   if (!mutex_trylock(&tr->mutex)) {
-   /* sleep 1 ms to make sure whatever holding tr->mutex makes
-* some progress.
+   if (!mutex_trylock(select_trampoline_lock(tr))) {
+   /* sleep 1 ms to make sure whatever holding 
select_trampoline_lock(tr)
+* makes some progress.
 */
msleep(1);
return -EAGAIN;
@@ -129,7 +157,7 @@ static int bpf_tramp_ftrace_ops_func(struct ftrace_ops 
*ops, unsigned long ip,
break;
}
 
-   mutex_unlock(&tr->mutex);
+   trampoline_unlock(tr);
return ret;
 }
 #endif
@@ -359,7 +387,6 @@ static struct bpf_trampoline *bp