diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2012-05-03 23:09:03 -0400 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2013-03-15 00:34:40 -0400 |
| commit | ae63b31e4d0e2ec09c569306ea46f664508ef717 (patch) | |
| tree | 0d40e8fddca53d1776254cd92fc73bc4413ee1f5 | |
| parent | 613f04a0f51e6e68ac6fe571ab79da3c0a5eb4da (diff) | |
tracing: Separate out trace events from global variables
The trace events for ftrace are all defined via global variables.
The arrays of events and event systems are linked to a global list.
This prevents multiple users of the event system (what to enable and
what not to).
By adding descriptors to represent the event/file relation, as well
as to which trace_array descriptor they are associated with, allows
for more than one set of events to be defined. Once the trace events
files have a link between the trace event and the trace_array they
are associated with, we can create multiple trace_arrays that can
record separate events in separate buffers.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
| -rw-r--r-- | include/linux/ftrace_event.h | 51 | ||||
| -rw-r--r-- | include/trace/ftrace.h | 3 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 8 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 39 | ||||
| -rw-r--r-- | kernel/trace/trace_events.c | 776 | ||||
| -rw-r--r-- | kernel/trace/trace_events_filter.c | 5 |
6 files changed, 622 insertions, 260 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 13a54d0bdfa8..c7191d482f98 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h | |||
| @@ -182,18 +182,20 @@ extern int ftrace_event_reg(struct ftrace_event_call *event, | |||
| 182 | enum trace_reg type, void *data); | 182 | enum trace_reg type, void *data); |
| 183 | 183 | ||
| 184 | enum { | 184 | enum { |
| 185 | TRACE_EVENT_FL_ENABLED_BIT, | ||
| 186 | TRACE_EVENT_FL_FILTERED_BIT, | 185 | TRACE_EVENT_FL_FILTERED_BIT, |
| 187 | TRACE_EVENT_FL_RECORDED_CMD_BIT, | ||
| 188 | TRACE_EVENT_FL_CAP_ANY_BIT, | 186 | TRACE_EVENT_FL_CAP_ANY_BIT, |
| 189 | TRACE_EVENT_FL_NO_SET_FILTER_BIT, | 187 | TRACE_EVENT_FL_NO_SET_FILTER_BIT, |
| 190 | TRACE_EVENT_FL_IGNORE_ENABLE_BIT, | 188 | TRACE_EVENT_FL_IGNORE_ENABLE_BIT, |
| 191 | }; | 189 | }; |
| 192 | 190 | ||
| 191 | /* | ||
| 192 | * Event flags: | ||
| 193 | * FILTERED - The event has a filter attached | ||
| 194 | * CAP_ANY - Any user can enable for perf | ||
| 195 | * NO_SET_FILTER - Set when filter has error and is to be ignored | ||
| 196 | */ | ||
| 193 | enum { | 197 | enum { |
| 194 | TRACE_EVENT_FL_ENABLED = (1 << TRACE_EVENT_FL_ENABLED_BIT), | ||
| 195 | TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT), | 198 | TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT), |
| 196 | TRACE_EVENT_FL_RECORDED_CMD = (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT), | ||
| 197 | TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT), | 199 | TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT), |
| 198 | TRACE_EVENT_FL_NO_SET_FILTER = (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT), | 200 | TRACE_EVENT_FL_NO_SET_FILTER = (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT), |
| 199 | TRACE_EVENT_FL_IGNORE_ENABLE = (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT), | 201 | TRACE_EVENT_FL_IGNORE_ENABLE = (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT), |
| @@ -203,12 +205,44 @@ struct ftrace_event_call { | |||
| 203 | struct list_head list; | 205 | struct list_head list; |
| 204 | struct ftrace_event_class *class; | 206 | struct ftrace_event_class *class; |
| 205 | char *name; | 207 | char *name; |
| 206 | struct dentry *dir; | ||
| 207 | struct trace_event event; | 208 | struct trace_event event; |
| 208 | const char *print_fmt; | 209 | const char *print_fmt; |
| 209 | struct event_filter *filter; | 210 | struct event_filter *filter; |
| 211 | struct list_head *files; | ||
| 210 | void *mod; | 212 | void *mod; |
| 211 | void *data; | 213 | void *data; |
| 214 | int flags; /* static flags of different events */ | ||
| 215 | |||
| 216 | #ifdef CONFIG_PERF_EVENTS | ||
| 217 | int perf_refcount; | ||
| 218 | struct hlist_head __percpu *perf_events; | ||
| 219 | #endif | ||
| 220 | }; | ||
| 221 | |||
| 222 | struct trace_array; | ||
| 223 | struct ftrace_subsystem_dir; | ||
| 224 | |||
| 225 | enum { | ||
| 226 | FTRACE_EVENT_FL_ENABLED_BIT, | ||
| 227 | FTRACE_EVENT_FL_RECORDED_CMD_BIT, | ||
| 228 | }; | ||
| 229 | |||
| 230 | /* | ||
| 231 | * Ftrace event file flags: | ||
| 232 | * ENABELD - The event is enabled | ||
| 233 | * RECORDED_CMD - The comms should be recorded at sched_switch | ||
| 234 | */ | ||
| 235 | enum { | ||
| 236 | FTRACE_EVENT_FL_ENABLED = (1 << FTRACE_EVENT_FL_ENABLED_BIT), | ||
| 237 | FTRACE_EVENT_FL_RECORDED_CMD = (1 << FTRACE_EVENT_FL_RECORDED_CMD_BIT), | ||
| 238 | }; | ||
| 239 | |||
| 240 | struct ftrace_event_file { | ||
| 241 | struct list_head list; | ||
| 242 | struct ftrace_event_call *event_call; | ||
| 243 | struct dentry *dir; | ||
| 244 | struct trace_array *tr; | ||
| 245 | struct ftrace_subsystem_dir *system; | ||
| 212 | 246 | ||
| 213 | /* | 247 | /* |
| 214 | * 32 bit flags: | 248 | * 32 bit flags: |
| @@ -223,17 +257,12 @@ struct ftrace_event_call { | |||
| 223 | * | 257 | * |
| 224 | * Note: Reads of flags do not hold the event_mutex since | 258 | * Note: Reads of flags do not hold the event_mutex since |
| 225 | * they occur in critical sections. But the way flags | 259 | * they occur in critical sections. But the way flags |
| 226 | * is currently used, these changes do no affect the code | 260 | * is currently used, these changes do not affect the code |
| 227 | * except that when a change is made, it may have a slight | 261 | * except that when a change is made, it may have a slight |
| 228 | * delay in propagating the changes to other CPUs due to | 262 | * delay in propagating the changes to other CPUs due to |
| 229 | * caching and such. | 263 | * caching and such. |
| 230 | */ | 264 | */ |
| 231 | unsigned int flags; | 265 | unsigned int flags; |
| 232 | |||
| 233 | #ifdef CONFIG_PERF_EVENTS | ||
| 234 | int perf_refcount; | ||
| 235 | struct hlist_head __percpu *perf_events; | ||
| 236 | #endif | ||
| 237 | }; | 266 | }; |
| 238 | 267 | ||
| 239 | #define __TRACE_EVENT_FLAGS(name, value) \ | 268 | #define __TRACE_EVENT_FLAGS(name, value) \ |
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 40dc5e8fe340..191d9661e277 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h | |||
| @@ -518,7 +518,8 @@ static inline notrace int ftrace_get_offsets_##call( \ | |||
| 518 | static notrace void \ | 518 | static notrace void \ |
| 519 | ftrace_raw_event_##call(void *__data, proto) \ | 519 | ftrace_raw_event_##call(void *__data, proto) \ |
| 520 | { \ | 520 | { \ |
| 521 | struct ftrace_event_call *event_call = __data; \ | 521 | struct ftrace_event_file *ftrace_file = __data; \ |
| 522 | struct ftrace_event_call *event_call = ftrace_file->event_call; \ | ||
| 522 | struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ | 523 | struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ |
| 523 | struct ring_buffer_event *event; \ | 524 | struct ring_buffer_event *event; \ |
| 524 | struct ftrace_raw_##call *entry; \ | 525 | struct ftrace_raw_##call *entry; \ |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 4f1dade56981..932931897b8d 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -189,6 +189,8 @@ unsigned long long ns2usecs(cycle_t nsec) | |||
| 189 | */ | 189 | */ |
| 190 | static struct trace_array global_trace; | 190 | static struct trace_array global_trace; |
| 191 | 191 | ||
| 192 | LIST_HEAD(ftrace_trace_arrays); | ||
| 193 | |||
| 192 | static DEFINE_PER_CPU(struct trace_array_cpu, global_trace_cpu); | 194 | static DEFINE_PER_CPU(struct trace_array_cpu, global_trace_cpu); |
| 193 | 195 | ||
| 194 | int filter_current_check_discard(struct ring_buffer *buffer, | 196 | int filter_current_check_discard(struct ring_buffer *buffer, |
| @@ -5359,6 +5361,12 @@ __init static int tracer_alloc_buffers(void) | |||
| 5359 | 5361 | ||
| 5360 | register_die_notifier(&trace_die_notifier); | 5362 | register_die_notifier(&trace_die_notifier); |
| 5361 | 5363 | ||
| 5364 | global_trace.flags = TRACE_ARRAY_FL_GLOBAL; | ||
| 5365 | |||
| 5366 | INIT_LIST_HEAD(&global_trace.systems); | ||
| 5367 | INIT_LIST_HEAD(&global_trace.events); | ||
| 5368 | list_add(&global_trace.list, &ftrace_trace_arrays); | ||
| 5369 | |||
| 5362 | while (trace_boot_options) { | 5370 | while (trace_boot_options) { |
| 5363 | char *option; | 5371 | char *option; |
| 5364 | 5372 | ||
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 2081971367ea..037f7eb03d69 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
| @@ -158,13 +158,39 @@ struct trace_array_cpu { | |||
| 158 | */ | 158 | */ |
| 159 | struct trace_array { | 159 | struct trace_array { |
| 160 | struct ring_buffer *buffer; | 160 | struct ring_buffer *buffer; |
| 161 | struct list_head list; | ||
| 161 | int cpu; | 162 | int cpu; |
| 162 | int buffer_disabled; | 163 | int buffer_disabled; |
| 164 | unsigned int flags; | ||
| 163 | cycle_t time_start; | 165 | cycle_t time_start; |
| 166 | struct dentry *dir; | ||
| 167 | struct dentry *event_dir; | ||
| 168 | struct list_head systems; | ||
| 169 | struct list_head events; | ||
| 164 | struct task_struct *waiter; | 170 | struct task_struct *waiter; |
| 165 | struct trace_array_cpu *data[NR_CPUS]; | 171 | struct trace_array_cpu *data[NR_CPUS]; |
| 166 | }; | 172 | }; |
| 167 | 173 | ||
| 174 | enum { | ||
| 175 | TRACE_ARRAY_FL_GLOBAL = (1 << 0) | ||
| 176 | }; | ||
| 177 | |||
| 178 | extern struct list_head ftrace_trace_arrays; | ||
| 179 | |||
| 180 | /* | ||
| 181 | * The global tracer (top) should be the first trace array added, | ||
| 182 | * but we check the fl | ||
