diff options
| author | Steven Rostedt <rostedt@goodmis.org> | 2026-09-02 09:55:01 -0400 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2026-09-02 11:08:21 -0400 |
| commit | 4617721c502b2ddaa4e324e86da4997edf738fa5 (patch) | |
| tree | 350aa83b47da0b574a814795392b20b0bed83cbc /tools/perf/util/tool.h | |
| download | linux-stable-4617721c502b2ddaa4e324e86da4997edf738fa5.tar.gz linux-stable-4617721c502b2ddaa4e324e86da4997edf738fa5.zip | |
ftrace: Synchronize the initialization of ftrace_opsgrafted
There's some internal state that ftrace_ops needs to have set, but since
it can be declared outside of the ftrace.c code, it calls
ftrace_ops_init() on the ops in every global function. The issue is that
if two tasks call it on the same ops at the same time it is possible to
have the initialization of one corrupt the initialization of the other
call.
Create a ops_mutex to use to synchronize every initialization of the
ftrace_ops. The mutex is taken within checking the ftrace_ops flag that
states it was initializied but the flag is checked again after the mutex
has been taken. Checking first outside the mutex allows it to shortcut
having to take the mutex. But then the check needs to be done again after
the mute is taken in case of races.
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260902095501.6b59af20@gandalf.local.home
Fixes: f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock")
Reported-by: sashiko-bot@kernel.org
Close: https://lore.kernel.org/all/20260829025528.49A831F000E9@smtp.kernel.org/
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'tools/perf/util/tool.h')
| -rw-r--r-- | tools/perf/util/tool.h | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h new file mode 100644 index 000000000..2a4f124ff --- /dev/null +++ b/tools/perf/util/tool.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PERF_TOOL_H +#define __PERF_TOOL_H + +#include <stdbool.h> + +#include <linux/types.h> + +struct perf_session; +union perf_event; +struct evlist; +struct perf_sample; +struct perf_tool; +struct machine; +struct ordered_events; + +typedef int (*event_sample)(const struct perf_tool *tool, union perf_event *event, + struct perf_sample *sample, + struct machine *machine); + +typedef int (*event_op)(const struct perf_tool *tool, union perf_event *event, + struct perf_sample *sample, struct machine *machine); + +typedef int (*event_attr_op)(const struct perf_tool *tool, + union perf_event *event, + struct evlist **pevlist); + +typedef int (*event_op2)(const struct perf_tool *tool, struct perf_session *session, + union perf_event *event); +typedef s64 (*event_op3)(const struct perf_tool *tool, struct perf_session *session, + union perf_event *event); +typedef int (*event_op4)(const struct perf_tool *tool, struct perf_session *session, + union perf_event *event, u64 data, const char *str); + +typedef int (*event_oe)(const struct perf_tool *tool, union perf_event *event, + struct ordered_events *oe); + +enum show_feature_header { + SHOW_FEAT_NO_HEADER = 0, + SHOW_FEAT_HEADER, + SHOW_FEAT_HEADER_FULL_INFO, +}; + +struct perf_tool { + event_sample sample, + read, + callchain_deferred; + event_op mmap, + mmap2, + comm, + namespaces, + cgroup, + fork, + exit, + lost, + lost_samples, + aux, + itrace_start, + aux_output_hw_id, + context_switch, + throttle, + unthrottle, + ksymbol, + bpf, + text_poke; + + event_attr_op attr; + event_attr_op event_update; + event_op2 tracing_data; + event_oe finished_round; + event_op2 build_id, + id_index, + auxtrace_info, + auxtrace_error, + time_conv, + thread_map, + cpu_map, + stat_config, + stat, + stat_round, + feature, + finished_init, + bpf_metadata, + schedstat_cpu, + schedstat_domain; + event_op4 compressed; + event_op3 auxtrace; + bool ordered_events; + bool ordering_requires_timestamps; + bool namespace_events; + bool cgroup_events; + bool no_warn; + bool dont_split_sample_group; + bool merge_deferred_callchains; + enum show_feature_header show_feat_hdr; +}; + +void perf_tool__init(struct perf_tool *tool, bool ordered_events); + +bool perf_tool__compressed_is_stub(const struct perf_tool *tool); + +int process_event_sample_stub(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine); + +struct delegate_tool { + /** @tool: The actual tool that calls the delegate. */ + struct perf_tool tool; + /** @delegate: The tool that is delegated to. */ + struct perf_tool *delegate; +}; + +void delegate_tool__init(struct delegate_tool *tool, struct perf_tool *delegate); + +#endif /* __PERF_TOOL_H */ |
