-
Notifications
You must be signed in to change notification settings - Fork 4.1k
libbpf-tools/klockstat: Support nested mutex_trylock #5461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -103,7 +103,9 @@ static const char *lock_ksym_names[] = { | |||||||||||||
| "mutex_lock_interruptible_nested", | ||||||||||||||
| "mutex_lock_killable", | ||||||||||||||
| "mutex_lock_killable_nested", | ||||||||||||||
| "_mutex_lock_killable", | ||||||||||||||
| "mutex_trylock", | ||||||||||||||
| "_mutex_trylock_nest_lock", | ||||||||||||||
| "down_read", | ||||||||||||||
| "down_read_nested", | ||||||||||||||
| "down_read_interruptible", | ||||||||||||||
|
|
@@ -775,8 +777,6 @@ static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va | |||||||||||||
|
|
||||||||||||||
| static void enable_fentry(struct klockstat_bpf *obj) | ||||||||||||||
| { | ||||||||||||||
| bool debug_lock; | ||||||||||||||
|
|
||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_mutex_lock, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_mutex_lock_exit, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_mutex_trylock, false); | ||||||||||||||
|
|
@@ -804,22 +804,6 @@ static void enable_fentry(struct klockstat_bpf *obj) | |||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_down_write_killable_exit, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_up_write, false); | ||||||||||||||
|
|
||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_mutex_lock_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_mutex_lock_exit_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_mutex_lock_interruptible_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_mutex_lock_interruptible_exit_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_mutex_lock_killable_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_mutex_lock_killable_exit_nested, false); | ||||||||||||||
|
|
||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_down_read_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_down_read_exit_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_down_read_killable_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_down_read_killable_exit_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_down_write_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_down_write_exit_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_down_write_killable_nested, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_down_write_killable_exit_nested, false); | ||||||||||||||
|
|
||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_rtnetlink_rcv_msg, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_rtnetlink_rcv_msg_exit, false); | ||||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_netlink_dump, false); | ||||||||||||||
|
|
@@ -828,8 +812,7 @@ static void enable_fentry(struct klockstat_bpf *obj) | |||||||||||||
| bpf_program__set_autoload(obj->progs.kprobe_sock_do_ioctl_exit, false); | ||||||||||||||
|
|
||||||||||||||
| /* CONFIG_DEBUG_LOCK_ALLOC is on */ | ||||||||||||||
| debug_lock = fentry_can_attach("mutex_lock_nested", NULL); | ||||||||||||||
| if (!debug_lock) | ||||||||||||||
| if (!fentry_can_attach("mutex_lock_nested", NULL)) | ||||||||||||||
| return; | ||||||||||||||
|
|
||||||||||||||
| bpf_program__set_attach_target(obj->progs.mutex_lock, 0, | ||||||||||||||
|
|
@@ -840,10 +823,6 @@ static void enable_fentry(struct klockstat_bpf *obj) | |||||||||||||
| "mutex_lock_interruptible_nested"); | ||||||||||||||
| bpf_program__set_attach_target(obj->progs.mutex_lock_interruptible_exit, 0, | ||||||||||||||
| "mutex_lock_interruptible_nested"); | ||||||||||||||
| bpf_program__set_attach_target(obj->progs.mutex_lock_killable, 0, | ||||||||||||||
| "mutex_lock_killable_nested"); | ||||||||||||||
| bpf_program__set_attach_target(obj->progs.mutex_lock_killable_exit, 0, | ||||||||||||||
| "mutex_lock_killable_nested"); | ||||||||||||||
|
|
||||||||||||||
| bpf_program__set_attach_target(obj->progs.down_read, 0, | ||||||||||||||
| "down_read_nested"); | ||||||||||||||
|
|
@@ -861,6 +840,24 @@ static void enable_fentry(struct klockstat_bpf *obj) | |||||||||||||
| "down_write_killable_nested"); | ||||||||||||||
| bpf_program__set_attach_target(obj->progs.down_write_killable_exit, 0, | ||||||||||||||
| "down_write_killable_nested"); | ||||||||||||||
|
|
||||||||||||||
| /* Since v6.16 mutex_lock_killable nested variant is implemented differently */ | ||||||||||||||
| if (fentry_can_attach("_mutex_lock_killable", NULL)) { | ||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. _mutex_lock_killable handling is inside DEBUG-only section.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see it in /proc/kallsyms on a non-debug kernel and both definitions of _mutex_lock_killable(), in mutex.c and rtmutex_api.c are inside a #ifdef CONFIG_DEBUG_LOCK_ALLOC section.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Thank you.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright. I'll update the pull request soon with your suggestion. |
||||||||||||||
| bpf_program__set_attach_target(obj->progs.mutex_lock_killable, 0, | ||||||||||||||
| "_mutex_lock_killable"); | ||||||||||||||
| bpf_program__set_attach_target(obj->progs.mutex_lock_killable_exit, 0, | ||||||||||||||
| "_mutex_lock_killable"); | ||||||||||||||
| } else { | ||||||||||||||
| bpf_program__set_attach_target(obj->progs.mutex_lock_killable, 0, | ||||||||||||||
| "mutex_lock_killable_nested"); | ||||||||||||||
| bpf_program__set_attach_target(obj->progs.mutex_lock_killable_exit, 0, | ||||||||||||||
| "mutex_lock_killable_nested"); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /* Since v6.16 mutex_trylock also have a nested variant */ | ||||||||||||||
|
||||||||||||||
| /* Since v6.16 mutex_trylock also have a nested variant */ | |
| /* Since v6.16 mutex_trylock also has a nested variant */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I can fix that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unlike other mutex functions, only the exit probe is retargeted here. A short comment explaining why — e.g., that mutex_trylock is non-blocking so no contention-entry tracking is needed — would help future readers understand the intent.
Copilot
AI
Apr 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation for this comment uses spaces rather than the tabs used throughout the file, which makes the block look misaligned in the new control flow. Please adjust to match the surrounding indentation style.
| /* CONFIG_DEBUG_LOCK_ALLOC is on */ | |
| /* CONFIG_DEBUG_LOCK_ALLOC is on */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not part of my patch, but I can implement that change if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that the logic is inverted to an early-return guard, this comment reads more naturally if placed after the guard rather than before it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this API call have the intended effect for BPF_PROG_TYPE_KPROBE programs on BTF-less kernels with CONFIG_DEBUG_LOCK_ALLOC enabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kprobe_mutex_lock_killable ?
Copilot
AI
Mar 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In enable_kprobes(), when _mutex_lock_killable exists you’re calling bpf_program__set_attach_target() on the fentry mutex_lock_killable programs, but those were set to autoload=false at the top of enable_kprobes(). This means kprobe_mutex_lock_killable(_exit) will still attach to the old symbol and miss nested killable locks on newer kernels. Please retarget the kprobe mutex_lock_killable entry/exit programs to _mutex_lock_killable instead.
| bpf_program__set_attach_target(obj->progs.mutex_lock_killable, 0, | |
| "_mutex_lock_killable"); | |
| bpf_program__set_attach_target(obj->progs.mutex_lock_killable_exit, 0, | |
| bpf_program__set_attach_target(obj->progs.kprobe_mutex_lock_killable, 0, | |
| "_mutex_lock_killable"); | |
| bpf_program__set_attach_target(obj->progs.kprobe_mutex_lock_killable_exit, 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obviously some sloppy copy and paste business on my part. My bad! Will fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking the time to refactor beyond the immediate fix. Given that this code paths depend on multiple conditions — fentry vs. kprobe, CONFIG_DEBUG_LOCK_ALLOC, and kernel ≥ v6.16 — could you share which combinations you were able to test?