Blame view
kernel/trace/trace_events.c
36.9 KB
b77e38aa2 tracing: add even... |
1 2 3 4 5 |
/* * event tracer * * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> * |
981d081ec tracing: add form... |
6 7 8 |
* - Added format output of fields of the trace point. * This was based off of work by Tom Zanussi <tzanussi@gmail.com>. * |
b77e38aa2 tracing: add even... |
9 |
*/ |
e6187007d tracing/events: a... |
10 11 12 |
#include <linux/workqueue.h> #include <linux/spinlock.h> #include <linux/kthread.h> |
b77e38aa2 tracing: add even... |
13 14 15 16 |
#include <linux/debugfs.h> #include <linux/uaccess.h> #include <linux/module.h> #include <linux/ctype.h> |
5a0e3ad6a include cleanup: ... |
17 |
#include <linux/slab.h> |
e6187007d tracing/events: a... |
18 |
#include <linux/delay.h> |
b77e38aa2 tracing: add even... |
19 |
|
020e5f85c tracing/events: A... |
20 |
#include <asm/setup.h> |
91729ef96 tracing: add ftra... |
21 |
#include "trace_output.h" |
b77e38aa2 tracing: add even... |
22 |
|
4e5292ea1 tracing: use the ... |
23 |
#undef TRACE_SYSTEM |
b628b3e62 tracing: make the... |
24 |
#define TRACE_SYSTEM "TRACE_SYSTEM" |
20c8928ab tracing/events: f... |
25 |
DEFINE_MUTEX(event_mutex); |
11a241a33 tracing: add prot... |
26 |
|
042957801 tracing/events: S... |
27 28 29 30 31 |
DEFINE_MUTEX(event_storage_mutex); EXPORT_SYMBOL_GPL(event_storage_mutex); char event_storage[EVENT_STORAGE_SIZE]; EXPORT_SYMBOL_GPL(event_storage); |
a59fd6027 tracing/events: c... |
32 |
LIST_HEAD(ftrace_events); |
8728fe501 tracing: Don't al... |
33 |
LIST_HEAD(ftrace_common_fields); |
a59fd6027 tracing/events: c... |
34 |
|
2e33af029 tracing: Move fie... |
35 36 37 38 39 40 41 |
struct list_head * trace_get_fields(struct ftrace_event_call *event_call) { if (!event_call->class->get_fields) return &event_call->class->fields; return event_call->class->get_fields(event_call); } |
8728fe501 tracing: Don't al... |
42 43 44 |
static int __trace_define_field(struct list_head *head, const char *type, const char *name, int offset, int size, int is_signed, int filter_type) |
cf027f645 tracing: add run-... |
45 46 |
{ struct ftrace_event_field *field; |
fe9f57f25 tracing: add run-... |
47 |
field = kzalloc(sizeof(*field), GFP_KERNEL); |
cf027f645 tracing: add run-... |
48 49 |
if (!field) goto err; |
fe9f57f25 tracing: add run-... |
50 |
|
cf027f645 tracing: add run-... |
51 52 53 |
field->name = kstrdup(name, GFP_KERNEL); if (!field->name) goto err; |
fe9f57f25 tracing: add run-... |
54 |
|
cf027f645 tracing: add run-... |
55 56 57 |
field->type = kstrdup(type, GFP_KERNEL); if (!field->type) goto err; |
fe9f57f25 tracing: add run-... |
58 |
|
43b51ead3 tracing/filters: ... |
59 60 61 62 |
if (filter_type == FILTER_OTHER) field->filter_type = filter_assign_type(type); else field->filter_type = filter_type; |
cf027f645 tracing: add run-... |
63 64 |
field->offset = offset; field->size = size; |
a118e4d14 tracing/filters: ... |
65 |
field->is_signed = is_signed; |
aa38e9fc3 tracing/filters: ... |
66 |
|
2e33af029 tracing: Move fie... |
67 |
list_add(&field->link, head); |
cf027f645 tracing: add run-... |
68 69 |
return 0; |
fe9f57f25 tracing: add run-... |
70 |
|
cf027f645 tracing: add run-... |
71 |
err: |
7b60997f7 tracing: Simplify... |
72 |
if (field) |
cf027f645 tracing: add run-... |
73 |
kfree(field->name); |
cf027f645 tracing: add run-... |
74 |
kfree(field); |
fe9f57f25 tracing: add run-... |
75 |
|
cf027f645 tracing: add run-... |
76 77 |
return -ENOMEM; } |
8728fe501 tracing: Don't al... |
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
int trace_define_field(struct ftrace_event_call *call, const char *type, const char *name, int offset, int size, int is_signed, int filter_type) { struct list_head *head; if (WARN_ON(!call->class)) return 0; head = trace_get_fields(call); return __trace_define_field(head, type, name, offset, size, is_signed, filter_type); } |
17c873ec2 tracing/events: a... |
92 |
EXPORT_SYMBOL_GPL(trace_define_field); |
cf027f645 tracing: add run-... |
93 |
|
e647d6b31 tracing/events: A... |
94 |
#define __common_field(type, item) \ |
8728fe501 tracing: Don't al... |
95 96 97 98 99 |
ret = __trace_define_field(&ftrace_common_fields, #type, \ "common_" #item, \ offsetof(typeof(ent), item), \ sizeof(ent.item), \ is_signed_type(type), FILTER_OTHER); \ |
e647d6b31 tracing/events: A... |
100 101 |
if (ret) \ return ret; |
8728fe501 tracing: Don't al... |
102 |
static int trace_define_common_fields(void) |
e647d6b31 tracing/events: A... |
103 104 105 106 107 108 109 110 |
{ int ret; struct trace_entry ent; __common_field(unsigned short, type); __common_field(unsigned char, flags); __common_field(unsigned char, preempt_count); __common_field(int, pid); |
a3a4a5acd Regression: parti... |
111 |
__common_field(int, padding); |
e647d6b31 tracing/events: A... |
112 113 114 |
return ret; } |
bd1a5c849 tracing: Ftrace d... |
115 |
void trace_destroy_fields(struct ftrace_event_call *call) |
2df75e415 tracing/events: f... |
116 117 |
{ struct ftrace_event_field *field, *next; |
2e33af029 tracing: Move fie... |
118 |
struct list_head *head; |
2df75e415 tracing/events: f... |
119 |
|
2e33af029 tracing: Move fie... |
120 121 |
head = trace_get_fields(call); list_for_each_entry_safe(field, next, head, link) { |
2df75e415 tracing/events: f... |
122 123 124 125 126 127 |
list_del(&field->link); kfree(field->type); kfree(field->name); kfree(field); } } |
87d9b4e1c tracing: Extract ... |
128 129 130 |
int trace_event_raw_init(struct ftrace_event_call *call) { int id; |
80decc70a tracing: Move pri... |
131 |
id = register_ftrace_event(&call->event); |
87d9b4e1c tracing: Extract ... |
132 133 |
if (!id) return -ENODEV; |
87d9b4e1c tracing: Extract ... |
134 135 136 137 |
return 0; } EXPORT_SYMBOL_GPL(trace_event_raw_init); |
a1d0ce821 tracing: Use clas... |
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
int ftrace_event_reg(struct ftrace_event_call *call, enum trace_reg type) { switch (type) { case TRACE_REG_REGISTER: return tracepoint_probe_register(call->name, call->class->probe, call); case TRACE_REG_UNREGISTER: tracepoint_probe_unregister(call->name, call->class->probe, call); return 0; #ifdef CONFIG_PERF_EVENTS case TRACE_REG_PERF_REGISTER: return tracepoint_probe_register(call->name, call->class->perf_probe, call); case TRACE_REG_PERF_UNREGISTER: tracepoint_probe_unregister(call->name, call->class->perf_probe, call); return 0; #endif } return 0; } EXPORT_SYMBOL_GPL(ftrace_event_reg); |
e870e9a12 tracing: Allow to... |
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
void trace_event_enable_cmd_record(bool enable) { struct ftrace_event_call *call; mutex_lock(&event_mutex); list_for_each_entry(call, &ftrace_events, list) { if (!(call->flags & TRACE_EVENT_FL_ENABLED)) continue; if (enable) { tracing_start_cmdline_record(); call->flags |= TRACE_EVENT_FL_RECORDED_CMD; } else { tracing_stop_cmdline_record(); call->flags &= ~TRACE_EVENT_FL_RECORDED_CMD; } } mutex_unlock(&event_mutex); } |
3b8e42738 tracing: Move a p... |
185 |
static int ftrace_event_enable_disable(struct ftrace_event_call *call, |
fd9949898 tracing: add raw ... |
186 187 |
int enable) { |
3b8e42738 tracing: Move a p... |
188 |
int ret = 0; |
fd9949898 tracing: add raw ... |
189 190 |
switch (enable) { case 0: |
553552ce1 tracing: Combine ... |
191 192 |
if (call->flags & TRACE_EVENT_FL_ENABLED) { call->flags &= ~TRACE_EVENT_FL_ENABLED; |
e870e9a12 tracing: Allow to... |
193 194 195 196 |
if (call->flags & TRACE_EVENT_FL_RECORDED_CMD) { tracing_stop_cmdline_record(); call->flags &= ~TRACE_EVENT_FL_RECORDED_CMD; } |
a1d0ce821 tracing: Use clas... |
197 |
call->class->reg(call, TRACE_REG_UNREGISTER); |
fd9949898 tracing: add raw ... |
198 |
} |
fd9949898 tracing: add raw ... |
199 200 |
break; case 1: |
553552ce1 tracing: Combine ... |
201 |
if (!(call->flags & TRACE_EVENT_FL_ENABLED)) { |
e870e9a12 tracing: Allow to... |
202 203 204 205 |
if (trace_flags & TRACE_ITER_RECORD_CMD) { tracing_start_cmdline_record(); call->flags |= TRACE_EVENT_FL_RECORDED_CMD; } |
a1d0ce821 tracing: Use clas... |
206 |
ret = call->class->reg(call, TRACE_REG_REGISTER); |
3b8e42738 tracing: Move a p... |
207 208 209 210 211 212 213 |
if (ret) { tracing_stop_cmdline_record(); pr_info("event trace: Could not enable event " "%s ", call->name); break; } |
553552ce1 tracing: Combine ... |
214 |
call->flags |= TRACE_EVENT_FL_ENABLED; |
fd9949898 tracing: add raw ... |
215 |
} |
fd9949898 tracing: add raw ... |
216 217 |
break; } |
3b8e42738 tracing: Move a p... |
218 219 |
return ret; |
fd9949898 tracing: add raw ... |
220 |
} |
0e907c993 ftrace: clean up ... |
221 222 223 224 225 226 227 228 229 230 |
static void ftrace_clear_events(void) { struct ftrace_event_call *call; mutex_lock(&event_mutex); list_for_each_entry(call, &ftrace_events, list) { ftrace_event_enable_disable(call, 0); } mutex_unlock(&event_mutex); } |
e9dbfae53 tracing: Fix bug ... |
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
static void __put_system(struct event_subsystem *system) { struct event_filter *filter = system->filter; WARN_ON_ONCE(system->ref_count == 0); if (--system->ref_count) return; if (filter) { kfree(filter->filter_string); kfree(filter); } kfree(system->name); kfree(system); } static void __get_system(struct event_subsystem *system) { WARN_ON_ONCE(system->ref_count == 0); system->ref_count++; } static void put_system(struct event_subsystem *system) { mutex_lock(&event_mutex); __put_system(system); mutex_unlock(&event_mutex); } |
8f31bfe53 tracing/events: c... |
259 260 261 262 263 |
/* * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events. */ static int __ftrace_set_clr_event(const char *match, const char *sub, const char *event, int set) |
b77e38aa2 tracing: add even... |
264 |
{ |
a59fd6027 tracing/events: c... |
265 |
struct ftrace_event_call *call; |
29f93943d tracing: initiali... |
266 |
int ret = -EINVAL; |
8f31bfe53 tracing/events: c... |
267 268 269 |
mutex_lock(&event_mutex); list_for_each_entry(call, &ftrace_events, list) { |
a1d0ce821 tracing: Use clas... |
270 |
if (!call->name || !call->class || !call->class->reg) |
8f31bfe53 tracing/events: c... |
271 272 273 274 |
continue; if (match && strcmp(match, call->name) != 0 && |
8f0820183 tracing: Create c... |
275 |
strcmp(match, call->class->system) != 0) |
8f31bfe53 tracing/events: c... |
276 |
continue; |
8f0820183 tracing: Create c... |
277 |
if (sub && strcmp(sub, call->class->system) != 0) |
8f31bfe53 tracing/events: c... |
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
continue; if (event && strcmp(event, call->name) != 0) continue; ftrace_event_enable_disable(call, set); ret = 0; } mutex_unlock(&event_mutex); return ret; } static int ftrace_set_clr_event(char *buf, int set) { |
b628b3e62 tracing: make the... |
294 |
char *event = NULL, *sub = NULL, *match; |
b628b3e62 tracing: make the... |
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
/* * The buf format can be <subsystem>:<event-name> * *:<event-name> means any event by that name. * :<event-name> is the same. * * <subsystem>:* means all events in that subsystem * <subsystem>: means the same. * * <name> (no ':') means all events in a subsystem with * the name <name> or any event that matches <name> */ match = strsep(&buf, ":"); if (buf) { sub = match; event = buf; match = NULL; if (!strlen(sub) || strcmp(sub, "*") == 0) sub = NULL; if (!strlen(event) || strcmp(event, "*") == 0) event = NULL; } |
b77e38aa2 tracing: add even... |
319 |
|
8f31bfe53 tracing/events: c... |
320 |
return __ftrace_set_clr_event(match, sub, event, set); |
b77e38aa2 tracing: add even... |
321 |
} |
4671c7940 tracing: add trac... |
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
/** * trace_set_clr_event - enable or disable an event * @system: system name to match (NULL for any system) * @event: event name to match (NULL for all events, within system) * @set: 1 to enable, 0 to disable * * This is a way for other parts of the kernel to enable or disable * event recording. * * Returns 0 on success, -EINVAL if the parameters do not match any * registered events. */ int trace_set_clr_event(const char *system, const char *event, int set) { return __ftrace_set_clr_event(NULL, system, event, set); } |
56355b83e tracing: Export t... |
338 |
EXPORT_SYMBOL_GPL(trace_set_clr_event); |
4671c7940 tracing: add trac... |
339 |
|
b77e38aa2 tracing: add even... |
340 341 342 343 344 345 346 |
/* 128 should be much more than enough */ #define EVENT_BUF_SIZE 127 static ssize_t ftrace_event_write(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos) { |
489663644 tracing: trace pa... |
347 |
struct trace_parser parser; |
4ba7978e9 tracing: Check th... |
348 |
ssize_t read, ret; |
b77e38aa2 tracing: add even... |
349 |
|
4ba7978e9 tracing: Check th... |
350 |
if (!cnt) |
b77e38aa2 tracing: add even... |
351 |
return 0; |
1852fcce1 tracing: expand t... |
352 353 354 |
ret = tracing_update_buffers(); if (ret < 0) return ret; |
489663644 tracing: trace pa... |
355 |
if (trace_parser_get_init(&parser, EVENT_BUF_SIZE + 1)) |
b77e38aa2 tracing: add even... |
356 |
return -ENOMEM; |
489663644 tracing: trace pa... |
357 |
read = trace_get_user(&parser, ubuf, cnt, ppos); |
4ba7978e9 tracing: Check th... |
358 |
if (read >= 0 && trace_parser_loaded((&parser))) { |
489663644 tracing: trace pa... |
359 |
int set = 1; |
b77e38aa2 tracing: add even... |
360 |
|
489663644 tracing: trace pa... |
361 |
if (*parser.buffer == '!') |
b77e38aa2 tracing: add even... |
362 |
set = 0; |
b77e38aa2 tracing: add even... |
363 |
|
489663644 tracing: trace pa... |
364 365 366 |
parser.buffer[parser.idx] = 0; ret = ftrace_set_clr_event(parser.buffer + !set, set); |
b77e38aa2 tracing: add even... |
367 |
if (ret) |
489663644 tracing: trace pa... |
368 |
goto out_put; |
b77e38aa2 tracing: add even... |
369 |
} |
b77e38aa2 tracing: add even... |
370 371 |
ret = read; |
489663644 tracing: trace pa... |
372 373 |
out_put: trace_parser_put(&parser); |
b77e38aa2 tracing: add even... |
374 375 376 377 378 379 380 |
return ret; } static void * t_next(struct seq_file *m, void *v, loff_t *pos) { |
30bd39cd6 tracing/events: u... |
381 |
struct ftrace_event_call *call = v; |
b77e38aa2 tracing: add even... |
382 383 |
(*pos)++; |
30bd39cd6 tracing/events: u... |
384 |
list_for_each_entry_continue(call, &ftrace_events, list) { |
40e26815f tracing: do not a... |
385 386 387 388 |
/* * The ftrace subsystem is for showing formats only. * They can not be enabled or disabled via the event files. */ |
a1d0ce821 tracing: Use clas... |
389 |
if (call->class && call->class->reg) |
30bd39cd6 tracing/events: u... |
390 |
return call; |
40e26815f tracing: do not a... |
391 |
} |
b77e38aa2 tracing: add even... |
392 |
|
30bd39cd6 tracing/events: u... |
393 |
return NULL; |
b77e38aa2 tracing: add even... |
394 395 396 397 |
} static void *t_start(struct seq_file *m, loff_t *pos) { |
30bd39cd6 tracing/events: u... |
398 |
struct ftrace_event_call *call; |
e1c7e2a6e tracing/events: D... |
399 |
loff_t l; |
20c8928ab tracing/events: f... |
400 |
mutex_lock(&event_mutex); |
e1c7e2a6e tracing/events: D... |
401 |
|
30bd39cd6 tracing/events: u... |
402 |
call = list_entry(&ftrace_events, struct ftrace_event_call, list); |
e1c7e2a6e tracing/events: D... |
403 |
for (l = 0; l <= *pos; ) { |
30bd39cd6 tracing/events: u... |
404 |
call = t_next(m, call, &l); |
e1c7e2a6e tracing/events: D... |
405 406 407 408 |
if (!call) break; } return call; |
b77e38aa2 tracing: add even... |
409 410 411 412 413 |
} static void * s_next(struct seq_file *m, void *v, loff_t *pos) { |
30bd39cd6 tracing/events: u... |
414 |
struct ftrace_event_call *call = v; |
b77e38aa2 tracing: add even... |
415 416 |
(*pos)++; |
30bd39cd6 tracing/events: u... |
417 |
list_for_each_entry_continue(call, &ftrace_events, list) { |
553552ce1 tracing: Combine ... |
418 |
if (call->flags & TRACE_EVENT_FL_ENABLED) |
30bd39cd6 tracing/events: u... |
419 |
return call; |
b77e38aa2 tracing: add even... |
420 |
} |
30bd39cd6 tracing/events: u... |
421 |
return NULL; |
b77e38aa2 tracing: add even... |
422 423 424 425 |
} static void *s_start(struct seq_file *m, loff_t *pos) { |
30bd39cd6 tracing/events: u... |
426 |
struct ftrace_event_call *call; |
e1c7e2a6e tracing/events: D... |
427 |
loff_t l; |
20c8928ab tracing/events: f... |
428 |
mutex_lock(&event_mutex); |
e1c7e2a6e tracing/events: D... |
429 |
|
30bd39cd6 tracing/events: u... |
430 |
call = list_entry(&ftrace_events, struct ftrace_event_call, list); |
e1c7e2a6e tracing/events: D... |
431 |
for (l = 0; l <= *pos; ) { |
30bd39cd6 tracing/events: u... |
432 |
call = s_next(m, call, &l); |
e1c7e2a6e tracing/events: D... |
433 434 435 436 |
if (!call) break; } return call; |
b77e38aa2 tracing: add even... |
437 438 439 440 441 |
} static int t_show(struct seq_file *m, void *v) { struct ftrace_event_call *call = v; |
8f0820183 tracing: Create c... |
442 443 |
if (strcmp(call->class->system, TRACE_SYSTEM) != 0) seq_printf(m, "%s:", call->class->system); |
b77e38aa2 tracing: add even... |
444 445 446 447 448 449 450 451 |
seq_printf(m, "%s ", call->name); return 0; } static void t_stop(struct seq_file *m, void *p) { |
20c8928ab tracing/events: f... |
452 |
mutex_unlock(&event_mutex); |
b77e38aa2 tracing: add even... |
453 454 455 456 457 |
} static int ftrace_event_seq_open(struct inode *inode, struct file *file) { |
b77e38aa2 tracing: add even... |
458 459 460 |
const struct seq_operations *seq_ops; if ((file->f_mode & FMODE_WRITE) && |
8650ae32e tracing: only tru... |
461 |
(file->f_flags & O_TRUNC)) |
b77e38aa2 tracing: add even... |
462 463 464 |
ftrace_clear_events(); seq_ops = inode->i_private; |
20c8928ab tracing/events: f... |
465 |
return seq_open(file, seq_ops); |
b77e38aa2 tracing: add even... |
466 |
} |
1473e4417 tracing: make eve... |
467 468 469 470 471 472 |
static ssize_t event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { struct ftrace_event_call *call = filp->private_data; char *buf; |
553552ce1 tracing: Combine ... |
473 |
if (call->flags & TRACE_EVENT_FL_ENABLED) |
1473e4417 tracing: make eve... |
474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
buf = "1 "; else buf = "0 "; return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2); } static ssize_t event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { struct ftrace_event_call *call = filp->private_data; |
1473e4417 tracing: make eve... |
488 489 |
unsigned long val; int ret; |
22fe9b54d tracing: Convert ... |
490 491 |
ret = kstrtoul_from_user(ubuf, cnt, 10, &val); if (ret) |
1473e4417 tracing: make eve... |
492 |
return ret; |
1852fcce1 tracing: expand t... |
493 494 495 |
ret = tracing_update_buffers(); if (ret < 0) return ret; |
1473e4417 tracing: make eve... |
496 497 |
switch (val) { case 0: |
1473e4417 tracing: make eve... |
498 |
case 1: |
11a241a33 tracing: add prot... |
499 |
mutex_lock(&event_mutex); |
3b8e42738 tracing: Move a p... |
500 |
ret = ftrace_event_enable_disable(call, val); |
11a241a33 tracing: add prot... |
501 |
mutex_unlock(&event_mutex); |
1473e4417 tracing: make eve... |
502 503 504 505 506 507 508 |
break; default: return -EINVAL; } *ppos += cnt; |
3b8e42738 tracing: Move a p... |
509 |
return ret ? ret : cnt; |
1473e4417 tracing: make eve... |
510 |
} |
8ae79a138 tracing: add hier... |
511 512 513 514 |
static ssize_t system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { |
c142b15dc tracing/events: s... |
515 |
const char set_to_char[4] = { '?', '0', '1', 'X' }; |
40ee4dfff tracing: Have "en... |
516 |
struct event_subsystem *system = filp->private_data; |
8ae79a138 tracing: add hier... |
517 518 |
struct ftrace_event_call *call; char buf[2]; |
c142b15dc tracing/events: s... |
519 |
int set = 0; |
8ae79a138 tracing: add hier... |
520 |
int ret; |
8ae79a138 tracing: add hier... |
521 522 |
mutex_lock(&event_mutex); list_for_each_entry(call, &ftrace_events, list) { |
a1d0ce821 tracing: Use clas... |
523 |
if (!call->name || !call->class || !call->class->reg) |
8ae79a138 tracing: add hier... |
524 |
continue; |
40ee4dfff tracing: Have "en... |
525 |
if (system && strcmp(call->class->system, system->name) != 0) |
8ae79a138 tracing: add hier... |
526 527 528 529 530 531 532 |
continue; /* * We need to find out if all the events are set * or if all events or cleared, or if we have * a mixture. */ |
553552ce1 tracing: Combine ... |
533 |
set |= (1 << !!(call->flags & TRACE_EVENT_FL_ENABLED)); |
c142b15dc tracing/events: s... |
534 |
|
8ae79a138 tracing: add hier... |
535 536 537 |
/* * If we have a mixture, no need to look further. */ |
c142b15dc tracing/events: s... |
538 |
if (set == 3) |
8ae79a138 tracing: add hier... |
539 540 541 |
break; } mutex_unlock(&event_mutex); |
c142b15dc tracing/events: s... |
542 |
buf[0] = set_to_char[set]; |
8ae79a138 tracing: add hier... |
543 544 |
buf[1] = ' '; |
8ae79a138 tracing: add hier... |
545 546 547 548 549 550 551 552 553 554 |
ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, 2); return ret; } static ssize_t system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { |
40ee4dfff tracing: Have "en... |
555 556 |
struct event_subsystem *system = filp->private_data; const char *name = NULL; |
8ae79a138 tracing: add hier... |
557 |
unsigned long val; |
8ae79a138 tracing: add hier... |
558 |
ssize_t ret; |
22fe9b54d tracing: Convert ... |
559 560 |
ret = kstrtoul_from_user(ubuf, cnt, 10, &val); if (ret) |
8ae79a138 tracing: add hier... |
561 562 563 564 565 |
return ret; ret = tracing_update_buffers(); if (ret < 0) return ret; |
8f31bfe53 tracing/events: c... |
566 |
if (val != 0 && val != 1) |
8ae79a138 tracing: add hier... |
567 |
return -EINVAL; |
8ae79a138 tracing: add hier... |
568 |
|
40ee4dfff tracing: Have "en... |
569 570 571 572 573 574 575 576 |
/* * Opening of "enable" adds a ref count to system, * so the name is safe to use. */ if (system) name = system->name; ret = __ftrace_set_clr_event(NULL, name, NULL, val); |
8ae79a138 tracing: add hier... |
577 |
if (ret) |
8f31bfe53 tracing/events: c... |
578 |
goto out; |
8ae79a138 tracing: add hier... |
579 580 |
ret = cnt; |
8f31bfe53 tracing/events: c... |
581 |
out: |
8ae79a138 tracing: add hier... |
582 583 584 585 |
*ppos += cnt; return ret; } |
2a37a3df5 tracing/events: C... |
586 587 |
enum { FORMAT_HEADER = 1, |
86397dc3c tracing: Clean up... |
588 589 |
FORMAT_FIELD_SEPERATOR = 2, FORMAT_PRINTFMT = 3, |
2a37a3df5 tracing/events: C... |
590 591 592 |
}; static void *f_next(struct seq_file *m, void *v, loff_t *pos) |
981d081ec tracing: add form... |
593 |
{ |
2a37a3df5 tracing/events: C... |
594 |
struct ftrace_event_call *call = m->private; |
5a65e9562 tracing: Use defi... |
595 |
struct ftrace_event_field *field; |
86397dc3c tracing: Clean up... |
596 597 |
struct list_head *common_head = &ftrace_common_fields; struct list_head *head = trace_get_fields(call); |
981d081ec tracing: add form... |
598 |
|
2a37a3df5 tracing/events: C... |
599 |
(*pos)++; |
5a65e9562 tracing: Use defi... |
600 |
|
2a37a3df5 tracing/events: C... |
601 602 |
switch ((unsigned long)v) { case FORMAT_HEADER: |
86397dc3c tracing: Clean up... |
603 604 605 606 607 608 |
if (unlikely(list_empty(common_head))) return NULL; field = list_entry(common_head->prev, struct ftrace_event_field, link); return field; |
5a65e9562 tracing: Use defi... |
609 |
|
86397dc3c tracing: Clean up... |
610 |
case FORMAT_FIELD_SEPERATOR: |
2a37a3df5 tracing/events: C... |
611 612 |
if (unlikely(list_empty(head))) return NULL; |
5a65e9562 tracing: Use defi... |
613 |
|
2a37a3df5 tracing/events: C... |
614 615 |
field = list_entry(head->prev, struct ftrace_event_field, link); return field; |
5a65e9562 tracing: Use defi... |
616 |
|
2a37a3df5 tracing/events: C... |
617 618 619 |
case FORMAT_PRINTFMT: /* all done */ return NULL; |
5a65e9562 tracing: Use defi... |
620 |
} |
2a37a3df5 tracing/events: C... |
621 |
field = v; |
86397dc3c tracing: Clean up... |
622 623 624 |
if (field->link.prev == common_head) return (void *)FORMAT_FIELD_SEPERATOR; else if (field->link.prev == head) |
2a37a3df5 tracing/events: C... |
625 626 627 |
return (void *)FORMAT_PRINTFMT; field = list_entry(field->link.prev, struct ftrace_event_field, link); |
2a37a3df5 tracing/events: C... |
628 |
return field; |
8728fe501 tracing: Don't al... |
629 |
} |
5a65e9562 tracing: Use defi... |
630 |
|
2a37a3df5 tracing/events: C... |
631 |
static void *f_start(struct seq_file *m, loff_t *pos) |
8728fe501 tracing: Don't al... |
632 |
{ |
2a37a3df5 tracing/events: C... |
633 634 |
loff_t l = 0; void *p; |
5a65e9562 tracing: Use defi... |
635 |
|
2a37a3df5 tracing/events: C... |
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 |
/* Start by showing the header */ if (!*pos) return (void *)FORMAT_HEADER; p = (void *)FORMAT_HEADER; do { p = f_next(m, p, &l); } while (p && l < *pos); return p; } static int f_show(struct seq_file *m, void *v) { struct ftrace_event_call *call = m->private; struct ftrace_event_field *field; const char *array_descriptor; switch ((unsigned long)v) { case FORMAT_HEADER: seq_printf(m, "name: %s ", call->name); seq_printf(m, "ID: %d ", call->event.type); seq_printf(m, "format: "); |
8728fe501 tracing: Don't al... |
662 |
return 0; |
5a65e9562 tracing: Use defi... |
663 |
|
86397dc3c tracing: Clean up... |
664 665 666 667 |
case FORMAT_FIELD_SEPERATOR: seq_putc(m, ' '); return 0; |
2a37a3df5 tracing/events: C... |
668 669 670 671 672 673 |
case FORMAT_PRINTFMT: seq_printf(m, " print fmt: %s ", call->print_fmt); return 0; |
981d081ec tracing: add form... |
674 |
} |
8728fe501 tracing: Don't al... |
675 |
|
2a37a3df5 tracing/events: C... |
676 |
field = v; |
8728fe501 tracing: Don't al... |
677 |
|
2a37a3df5 tracing/events: C... |
678 679 680 681 682 683 684 685 |
/* * Smartly shows the array type(except dynamic array). * Normal: * field:TYPE VAR * If TYPE := TYPE[LEN], it is shown: * field:TYPE VAR[LEN] */ array_descriptor = strchr(field->type, '['); |
8728fe501 tracing: Don't al... |
686 |
|
2a37a3df5 tracing/events: C... |
687 688 |
if (!strncmp(field->type, "__data_loc", 10)) array_descriptor = NULL; |
8728fe501 tracing: Don't al... |
689 |
|
2a37a3df5 tracing/events: C... |
690 691 692 693 694 695 696 697 698 699 700 701 |
if (!array_descriptor) seq_printf(m, "\tfield:%s %s;\toffset:%u;\tsize:%u;\tsigned:%d; ", field->type, field->name, field->offset, field->size, !!field->is_signed); else seq_printf(m, "\tfield:%.*s %s%s;\toffset:%u;\tsize:%u;\tsigned:%d; ", (int)(array_descriptor - field->type), field->type, field->name, array_descriptor, field->offset, field->size, !!field->is_signed); |
8728fe501 tracing: Don't al... |
702 |
|
2a37a3df5 tracing/events: C... |
703 704 |
return 0; } |
5a65e9562 tracing: Use defi... |
705 |
|
2a37a3df5 tracing/events: C... |
706 707 708 |
static void f_stop(struct seq_file *m, void *p) { } |
981d081ec tracing: add form... |
709 |
|
2a37a3df5 tracing/events: C... |
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 |
static const struct seq_operations trace_format_seq_ops = { .start = f_start, .next = f_next, .stop = f_stop, .show = f_show, }; static int trace_format_open(struct inode *inode, struct file *file) { struct ftrace_event_call *call = inode->i_private; struct seq_file *m; int ret; ret = seq_open(file, &trace_format_seq_ops); if (ret < 0) return ret; m = file->private_data; m->private = call; return 0; |
981d081ec tracing: add form... |
731 |
} |
23725aeea ftrace: provide a... |
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 |
static ssize_t event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { struct ftrace_event_call *call = filp->private_data; struct trace_seq *s; int r; if (*ppos) return 0; s = kmalloc(sizeof(*s), GFP_KERNEL); if (!s) return -ENOMEM; trace_seq_init(s); |
32c0edaea tracing: Remove d... |
747 748 |
trace_seq_printf(s, "%d ", call->event.type); |
23725aeea ftrace: provide a... |
749 750 751 752 753 754 |
r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); kfree(s); return r; } |
7ce7e4249 tracing: add per-... |
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 |
static ssize_t event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { struct ftrace_event_call *call = filp->private_data; struct trace_seq *s; int r; if (*ppos) return 0; s = kmalloc(sizeof(*s), GFP_KERNEL); if (!s) return -ENOMEM; trace_seq_init(s); |
8b3725621 tracing/filters: ... |
771 |
print_event_filter(call, s); |
4bda2d517 tracing/filters: ... |
772 |
r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); |
7ce7e4249 tracing: add per-... |
773 774 775 776 777 778 779 780 781 782 783 |
kfree(s); return r; } static ssize_t event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { struct ftrace_event_call *call = filp->private_data; |
8b3725621 tracing/filters: ... |
784 |
char *buf; |
7ce7e4249 tracing: add per-... |
785 |
int err; |
8b3725621 tracing/filters: ... |
786 |
if (cnt >= PAGE_SIZE) |
7ce7e4249 tracing: add per-... |
787 |
return -EINVAL; |
8b3725621 tracing/filters: ... |
788 789 |
buf = (char *)__get_free_page(GFP_TEMPORARY); if (!buf) |
7ce7e4249 tracing: add per-... |
790 |
return -ENOMEM; |
8b3725621 tracing/filters: ... |
791 792 793 |
if (copy_from_user(buf, ubuf, cnt)) { free_page((unsigned long) buf); return -EFAULT; |
7ce7e4249 tracing: add per-... |
794 |
} |
8b3725621 tracing/filters: ... |
795 |
buf[cnt] = '\0'; |
7ce7e4249 tracing: add per-... |
796 |
|
8b3725621 tracing/filters: ... |
797 798 799 |
err = apply_event_filter(call, buf); free_page((unsigned long) buf); if (err < 0) |
44e9c8b7a tracing/filters: ... |
800 |
return err; |
0a19e53c1 tracing/filters: ... |
801 |
|
7ce7e4249 tracing: add per-... |
802 803 804 805 |
*ppos += cnt; return cnt; } |
e9dbfae53 tracing: Fix bug ... |
806 807 808 809 810 811 |
static LIST_HEAD(event_subsystems); static int subsystem_open(struct inode *inode, struct file *filp) { struct event_subsystem *system = NULL; int ret; |
40ee4dfff tracing: Have "en... |
812 813 |
if (!inode->i_private) goto skip_search; |
e9dbfae53 tracing: Fix bug ... |
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 |
/* Make sure the system still exists */ mutex_lock(&event_mutex); list_for_each_entry(system, &event_subsystems, list) { if (system == inode->i_private) { /* Don't open systems with no events */ if (!system->nr_events) { system = NULL; break; } __get_system(system); break; } } mutex_unlock(&event_mutex); if (system != inode->i_private) return -ENODEV; |
40ee4dfff tracing: Have "en... |
831 |
skip_search: |
e9dbfae53 tracing: Fix bug ... |
832 |
ret = tracing_open_generic(inode, filp); |
40ee4dfff tracing: Have "en... |
833 |
if (ret < 0 && system) |
e9dbfae53 tracing: Fix bug ... |
834 835 836 837 838 839 840 841 |
put_system(system); return ret; } static int subsystem_release(struct inode *inode, struct file *file) { struct event_subsystem *system = inode->i_private; |
40ee4dfff tracing: Have "en... |
842 843 |
if (system) put_system(system); |
e9dbfae53 tracing: Fix bug ... |
844 845 846 |
return 0; } |
cfb180f3e tracing: add per-... |
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 |
static ssize_t subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { struct event_subsystem *system = filp->private_data; struct trace_seq *s; int r; if (*ppos) return 0; s = kmalloc(sizeof(*s), GFP_KERNEL); if (!s) return -ENOMEM; trace_seq_init(s); |
8b3725621 tracing/filters: ... |
863 |
print_subsystem_event_filter(system, s); |
4bda2d517 tracing/filters: ... |
864 |
r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); |
cfb180f3e tracing: add per-... |
865 866 867 868 869 870 871 872 873 874 875 |
kfree(s); return r; } static ssize_t subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { struct event_subsystem *system = filp->private_data; |
8b3725621 tracing/filters: ... |
876 |
char *buf; |
cfb180f3e tracing: add per-... |
877 |
int err; |
8b3725621 tracing/filters: ... |
878 |
if (cnt >= PAGE_SIZE) |
cfb180f3e tracing: add per-... |
879 |
return -EINVAL; |
8b3725621 tracing/filters: ... |
880 881 |
buf = (char *)__get_free_page(GFP_TEMPORARY); if (!buf) |
cfb180f3e tracing: add per-... |
882 |
return -ENOMEM; |
8b3725621 tracing/filters: ... |
883 884 885 |
if (copy_from_user(buf, ubuf, cnt)) { free_page((unsigned long) buf); return -EFAULT; |
cfb180f3e tracing: add per-... |
886 |
} |
8b3725621 tracing/filters: ... |
887 |
buf[cnt] = '\0'; |
cfb180f3e tracing: add per-... |
888 |
|
8b3725621 tracing/filters: ... |
889 890 891 |
err = apply_subsystem_event_filter(system, buf); free_page((unsigned long) buf); if (err < 0) |
44e9c8b7a tracing/filters: ... |
892 |
return err; |
cfb180f3e tracing: add per-... |
893 894 895 896 897 |
*ppos += cnt; return cnt; } |
d1b182a8d tracing/events/ri... |
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 |
static ssize_t show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { int (*func)(struct trace_seq *s) = filp->private_data; struct trace_seq *s; int r; if (*ppos) return 0; s = kmalloc(sizeof(*s), GFP_KERNEL); if (!s) return -ENOMEM; trace_seq_init(s); func(s); r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); kfree(s); return r; } |
b77e38aa2 tracing: add even... |
921 922 923 924 925 926 927 928 929 930 931 932 933 |
static const struct seq_operations show_event_seq_ops = { .start = t_start, .next = t_next, .show = t_show, .stop = t_stop, }; static const struct seq_operations show_set_event_seq_ops = { .start = s_start, .next = s_next, .show = t_show, .stop = t_stop, }; |
2314c4ae1 tracing: add back... |
934 935 936 937 938 939 |
static const struct file_operations ftrace_avail_fops = { .open = ftrace_event_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; |
b77e38aa2 tracing: add even... |
940 941 942 943 944 945 946 |
static const struct file_operations ftrace_set_event_fops = { .open = ftrace_event_seq_open, .read = seq_read, .write = ftrace_event_write, .llseek = seq_lseek, .release = seq_release, }; |
1473e4417 tracing: make eve... |
947 948 949 950 |
static const struct file_operations ftrace_enable_fops = { .open = tracing_open_generic, .read = event_enable_read, .write = event_enable_write, |
6038f373a llseek: automatic... |
951 |
.llseek = default_llseek, |
1473e4417 tracing: make eve... |
952 |
}; |
981d081ec tracing: add form... |
953 |
static const struct file_operations ftrace_event_format_fops = { |
2a37a3df5 tracing/events: C... |
954 955 956 957 |
.open = trace_format_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, |
981d081ec tracing: add form... |
958 |
}; |
23725aeea ftrace: provide a... |
959 960 961 |
static const struct file_operations ftrace_event_id_fops = { .open = tracing_open_generic, .read = event_id_read, |
6038f373a llseek: automatic... |
962 |
.llseek = default_llseek, |
23725aeea ftrace: provide a... |
963 |
}; |
7ce7e4249 tracing: add per-... |
964 965 966 967 |
static const struct file_operations ftrace_event_filter_fops = { .open = tracing_open_generic, .read = event_filter_read, .write = event_filter_write, |
6038f373a llseek: automatic... |
968 |
.llseek = default_llseek, |
7ce7e4249 tracing: add per-... |
969 |
}; |
cfb180f3e tracing: add per-... |
970 |
static const struct file_operations ftrace_subsystem_filter_fops = { |
e9dbfae53 tracing: Fix bug ... |
971 |
.open = subsystem_open, |
cfb180f3e tracing: add per-... |
972 973 |
.read = subsystem_filter_read, .write = subsystem_filter_write, |
6038f373a llseek: automatic... |
974 |
.llseek = default_llseek, |
e9dbfae53 tracing: Fix bug ... |
975 |
.release = subsystem_release, |
cfb180f3e tracing: add per-... |
976 |
}; |
8ae79a138 tracing: add hier... |
977 |
static const struct file_operations ftrace_system_enable_fops = { |
40ee4dfff tracing: Have "en... |
978 |
.open = subsystem_open, |
8ae79a138 tracing: add hier... |
979 980 |
.read = system_enable_read, .write = system_enable_write, |
6038f373a llseek: automatic... |
981 |
.llseek = default_llseek, |
40ee4dfff tracing: Have "en... |
982 |
.release = subsystem_release, |
8ae79a138 tracing: add hier... |
983 |
}; |
d1b182a8d tracing/events/ri... |
984 985 986 |
static const struct file_operations ftrace_show_header_fops = { .open = tracing_open_generic, .read = show_header, |
6038f373a llseek: automatic... |
987 |
.llseek = default_llseek, |
d1b182a8d tracing/events/ri... |
988 |
}; |
1473e4417 tracing: make eve... |
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 |
static struct dentry *event_trace_events_dir(void) { static struct dentry *d_tracer; static struct dentry *d_events; if (d_events) return d_events; d_tracer = tracing_init_dentry(); if (!d_tracer) return NULL; d_events = debugfs_create_dir("events", d_tracer); if (!d_events) pr_warning("Could not create debugfs " "'events' directory "); return d_events; } |
6ecc2d1ca tracing: add subs... |
1009 1010 1011 1012 |
static struct dentry * event_subsystem_dir(const char *name, struct dentry *d_events) { struct event_subsystem *system; |
e1112b4d9 tracing/filters: ... |
1013 |
struct dentry *entry; |
6ecc2d1ca tracing: add subs... |
1014 1015 1016 |
/* First see if we did not already create this dir */ list_for_each_entry(system, &event_subsystems, list) { |
dc82ec98a tracing/filter: R... |
1017 1018 |
if (strcmp(system->name, name) == 0) { system->nr_events++; |
6ecc2d1ca tracing: add subs... |
1019 |
return system->entry; |
dc82ec98a tracing/filter: R... |
1020 |
} |
6ecc2d1ca tracing: add subs... |
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 |
} /* need to create new entry */ system = kmalloc(sizeof(*system), GFP_KERNEL); if (!system) { pr_warning("No memory to create event subsystem %s ", name); return d_events; } system->entry = debugfs_create_dir(name, d_events); if (!system->entry) { pr_warning("Could not create event subsystem %s ", name); kfree(system); return d_events; } |
dc82ec98a tracing/filter: R... |
1040 |
system->nr_events = 1; |
e9dbfae53 tracing: Fix bug ... |
1041 |
system->ref_count = 1; |
6d723736e tracing/events: a... |
1042 1043 1044 1045 1046 1047 |
system->name = kstrdup(name, GFP_KERNEL); if (!system->name) { debugfs_remove(system->entry); kfree(system); return d_events; } |
6ecc2d1ca tracing: add subs... |
1048 |
list_add(&system->list, &event_subsystems); |
30e673b23 tracing/filters: ... |
1049 |
system->filter = NULL; |
cfb180f3e tracing: add per-... |
1050 |
|
8b3725621 tracing/filters: ... |
1051 1052 1053 1054 1055 1056 1057 |
system->filter = kzalloc(sizeof(struct event_filter), GFP_KERNEL); if (!system->filter) { pr_warning("Could not allocate filter for subsystem " "'%s' ", name); return system->entry; } |
e1112b4d9 tracing/filters: ... |
1058 1059 |
entry = debugfs_create_file("filter", 0644, system->entry, system, &ftrace_subsystem_filter_fops); |
8b3725621 tracing/filters: ... |
1060 1061 1062 |
if (!entry) { kfree(system->filter); system->filter = NULL; |
e1112b4d9 tracing/filters: ... |
1063 1064 1065 |
pr_warning("Could not create debugfs " "'%s/filter' entry ", name); |
8b3725621 tracing/filters: ... |
1066 |
} |
e1112b4d9 tracing/filters: ... |
1067 |
|
40ee4dfff tracing: Have "en... |
1068 |
trace_create_file("enable", 0644, system->entry, system, |
f3f3f0092 tracing/event: Cl... |
1069 |
&ftrace_system_enable_fops); |
8ae79a138 tracing: add hier... |
1070 |
|
6ecc2d1ca tracing: add subs... |
1071 1072 |
return system->entry; } |
1473e4417 tracing: make eve... |
1073 |
static int |
701970b3a tracing/events: m... |
1074 1075 1076 1077 1078 |
event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, const struct file_operations *id, const struct file_operations *enable, const struct file_operations *filter, const struct file_operations *format) |
1473e4417 tracing: make eve... |
1079 |
{ |
2e33af029 tracing: Move fie... |
1080 |
struct list_head *head; |
fd9949898 tracing: add raw ... |
1081 |
int ret; |
1473e4417 tracing: make eve... |
1082 |
|
6ecc2d1ca tracing: add subs... |
1083 1084 1085 1086 |
/* * If the trace point header did not define TRACE_SYSTEM * then the system would be called "TRACE_SYSTEM". */ |
8f0820183 tracing: Create c... |
1087 1088 |
if (strcmp(call->class->system, TRACE_SYSTEM) != 0) d_events = event_subsystem_dir(call->class->system, d_events); |
6ecc2d1ca tracing: add subs... |
1089 |
|
1473e4417 tracing: make eve... |
1090 1091 1092 1093 1094 1095 1096 |
call->dir = debugfs_create_dir(call->name, d_events); if (!call->dir) { pr_warning("Could not create debugfs " "'%s' directory ", call->name); return -1; } |
a1d0ce821 tracing: Use clas... |
1097 |
if (call->class->reg) |
f3f3f0092 tracing/event: Cl... |
1098 1099 |
trace_create_file("enable", 0644, call->dir, call, enable); |
1473e4417 tracing: make eve... |
1100 |
|
2239291ae tracing: Remove p... |
1101 |
#ifdef CONFIG_PERF_EVENTS |
a1d0ce821 tracing: Use clas... |
1102 |
if (call->event.type && call->class->reg) |
f3f3f0092 tracing/event: Cl... |
1103 1104 |
trace_create_file("id", 0444, call->dir, call, id); |
2239291ae tracing: Remove p... |
1105 |
#endif |
23725aeea ftrace: provide a... |
1106 |
|
c9d932cf8 tracing: Remove t... |
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 |
/* * Other events may have the same class. Only update * the fields if they are not already defined. */ head = trace_get_fields(call); if (list_empty(head)) { ret = call->class->define_fields(call); if (ret < 0) { pr_warning("Could not initialize trace point" " events/%s ", call->name); return ret; |
cf027f645 tracing: add run-... |
1119 1120 |
} } |
c9d932cf8 tracing: Remove t... |
1121 1122 |
trace_create_file("filter", 0644, call->dir, call, filter); |
cf027f645 tracing: add run-... |
1123 |
|
f3f3f0092 tracing/event: Cl... |
1124 1125 |
trace_create_file("format", 0444, call->dir, call, format); |
6d723736e tracing/events: a... |
1126 1127 1128 |
return 0; } |
67ead0a6c tracing: Remove o... |
1129 1130 1131 1132 1133 1134 |
static int __trace_add_event_call(struct ftrace_event_call *call, struct module *mod, const struct file_operations *id, const struct file_operations *enable, const struct file_operations *filter, const struct file_operations *format) |
bd1a5c849 tracing: Ftrace d... |
1135 1136 1137 |
{ struct dentry *d_events; int ret; |
6d723736e tracing/events: a... |
1138 |
|
67ead0a6c tracing: Remove o... |
1139 |
/* The linker may leave blanks */ |
bd1a5c849 tracing: Ftrace d... |
1140 1141 |
if (!call->name) return -EINVAL; |
701970b3a tracing/events: m... |
1142 |
|
0405ab80a tracing: Move raw... |
1143 1144 |
if (call->class->raw_init) { ret = call->class->raw_init(call); |
bd1a5c849 tracing: Ftrace d... |
1145 1146 |
if (ret < 0) { if (ret != -ENOSYS) |
67ead0a6c tracing: Remove o... |
1147 1148 1149 |
pr_warning("Could not initialize trace events/%s ", call->name); |
bd1a5c849 tracing: Ftrace d... |
1150 1151 1152 |
return ret; } } |
701970b3a tracing/events: m... |
1153 |
|
bd1a5c849 tracing: Ftrace d... |
1154 1155 1156 |
d_events = event_trace_events_dir(); if (!d_events) return -ENOENT; |
67ead0a6c tracing: Remove o... |
1157 |
ret = event_create_dir(call, d_events, id, enable, filter, format); |
88f70d759 tracing/ftrace: F... |
1158 1159 |
if (!ret) list_add(&call->list, &ftrace_events); |
67ead0a6c tracing: Remove o... |
1160 |
call->mod = mod; |
88f70d759 tracing/ftrace: F... |
1161 |
|
588bebb74 ftrace: Fix trace... |
1162 |
return ret; |
bd1a5c849 tracing: Ftrace d... |
1163 1164 1165 1166 1167 1168 1169 |
} /* Add an additional event_call dynamically */ int trace_add_event_call(struct ftrace_event_call *call) { int ret; mutex_lock(&event_mutex); |
67ead0a6c tracing: Remove o... |
1170 1171 1172 1173 |
ret = __trace_add_event_call(call, NULL, &ftrace_event_id_fops, &ftrace_enable_fops, &ftrace_event_filter_fops, &ftrace_event_format_fops); |
bd1a5c849 tracing: Ftrace d... |
1174 1175 1176 |
mutex_unlock(&event_mutex); return ret; } |
701970b3a tracing/events: m... |
1177 |
|
a2ca5e03b tracing/events: O... |
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 |
static void remove_subsystem_dir(const char *name) { struct event_subsystem *system; if (strcmp(name, TRACE_SYSTEM) == 0) return; list_for_each_entry(system, &event_subsystems, list) { if (strcmp(system->name, name) == 0) { if (!--system->nr_events) { |
a2ca5e03b tracing/events: O... |
1188 1189 |
debugfs_remove_recursive(system->entry); list_del(&system->list); |
e9dbfae53 tracing: Fix bug ... |
1190 |
__put_system(system); |
a2ca5e03b tracing/events: O... |
1191 1192 1193 1194 1195 |
} break; } } } |
4fead8e46 ftrace: Fix trace... |
1196 1197 1198 |
/* * Must be called under locking both of event_mutex and trace_event_mutex. */ |
bd1a5c849 tracing: Ftrace d... |
1199 1200 1201 |
static void __trace_remove_event_call(struct ftrace_event_call *call) { ftrace_event_enable_disable(call, 0); |
80decc70a tracing: Move pri... |
1202 1203 |
if (call->event.funcs) __unregister_ftrace_event(&call->event); |
bd1a5c849 tracing: Ftrace d... |
1204 1205 1206 1207 |
debugfs_remove_recursive(call->dir); list_del(&call->list); trace_destroy_fields(call); destroy_preds(call); |
8f0820183 tracing: Create c... |
1208 |
remove_subsystem_dir(call->class->system); |
bd1a5c849 tracing: Ftrace d... |
1209 1210 1211 1212 1213 1214 |
} /* Remove an event_call */ void trace_remove_event_call(struct ftrace_event_call *call) { mutex_lock(&event_mutex); |
4fead8e46 ftrace: Fix trace... |
1215 |
down_write(&trace_event_mutex); |
bd1a5c849 tracing: Ftrace d... |
1216 |
__trace_remove_event_call(call); |
4fead8e46 ftrace: Fix trace... |
1217 |
up_write(&trace_event_mutex); |
bd1a5c849 tracing: Ftrace d... |
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 |
mutex_unlock(&event_mutex); } #define for_each_event(event, start, end) \ for (event = start; \ (unsigned long)event < (unsigned long)end; \ event++) #ifdef CONFIG_MODULES static LIST_HEAD(ftrace_module_file_list); /* * Modules must own their file_operations to keep up with * reference counting. */ struct ftrace_module_file_ops { struct list_head list; struct module *mod; struct file_operations id; struct file_operations enable; struct file_operations format; struct file_operations filter; }; |
701970b3a tracing/events: m... |
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 |
static struct ftrace_module_file_ops * trace_create_file_ops(struct module *mod) { struct ftrace_module_file_ops *file_ops; /* * This is a bit of a PITA. To allow for correct reference * counting, modules must "own" their file_operations. * To do this, we allocate the file operations that will be * used in the event directory. */ file_ops = kmalloc(sizeof(*file_ops), GFP_KERNEL); if (!file_ops) return NULL; file_ops->mod = mod; file_ops->id = ftrace_event_id_fops; file_ops->id.owner = mod; file_ops->enable = ftrace_enable_fops; file_ops->enable.owner = mod; file_ops->filter = ftrace_event_filter_fops; file_ops->filter.owner = mod; file_ops->format = ftrace_event_format_fops; file_ops->format.owner = mod; list_add(&file_ops->list, &ftrace_module_file_list); return file_ops; } |
6d723736e tracing/events: a... |
1276 1277 |
static void trace_module_add_events(struct module *mod) { |
701970b3a tracing/events: m... |
1278 |
struct ftrace_module_file_ops *file_ops = NULL; |
e4a9ea5ee tracing: Replace ... |
1279 |
struct ftrace_event_call **call, **start, **end; |
6d723736e tracing/events: a... |
1280 1281 1282 1283 1284 1285 |
start = mod->trace_events; end = mod->trace_events + mod->num_trace_events; if (start == end) return; |
67ead0a6c tracing: Remove o... |
1286 1287 |
file_ops = trace_create_file_ops(mod); if (!file_ops) |
6d723736e tracing/events: a... |
1288 1289 1290 |
return; for_each_event(call, start, end) { |
e4a9ea5ee tracing: Replace ... |
1291 |
__trace_add_event_call(*call, mod, |
88f70d759 tracing/ftrace: F... |
1292 1293 |
&file_ops->id, &file_ops->enable, &file_ops->filter, &file_ops->format); |
6d723736e tracing/events: a... |
1294 1295 1296 1297 1298 |
} } static void trace_module_remove_events(struct module *mod) { |
701970b3a tracing/events: m... |
1299 |
struct ftrace_module_file_ops *file_ops; |
6d723736e tracing/events: a... |
1300 |
struct ftrace_event_call *call, *p; |
9456f0fa6 tracing: reset ri... |
1301 |
bool found = false; |
6d723736e tracing/events: a... |
1302 |
|
110bf2b76 tracing: add prot... |
1303 |
down_write(&trace_event_mutex); |
6d723736e tracing/events: a... |
1304 1305 |
list_for_each_entry_safe(call, p, &ftrace_events, list) { if (call->mod == mod) { |
9456f0fa6 tracing: reset ri... |
1306 |
found = true; |
bd1a5c849 tracing: Ftrace d... |
1307 |
__trace_remove_event_call(call); |
6d723736e tracing/events: a... |
1308 1309 |
} } |
701970b3a tracing/events: m... |
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 |
/* Now free the file_operations */ list_for_each_entry(file_ops, &ftrace_module_file_list, list) { if (file_ops->mod == mod) break; } if (&file_ops->list != &ftrace_module_file_list) { list_del(&file_ops->list); kfree(file_ops); } |
9456f0fa6 tracing: reset ri... |
1320 1321 1322 1323 1324 1325 1326 |
/* * It is safest to reset the ring buffer if the module being unloaded * registered any events. */ if (found) tracing_reset_current_online_cpus(); |
110bf2b76 tracing: add prot... |
1327 |
up_write(&trace_event_mutex); |
6d723736e tracing/events: a... |
1328 |
} |
61f919a12 tracing/events: f... |
1329 1330 |
static int trace_module_notify(struct notifier_block *self, unsigned long val, void *data) |
6d723736e tracing/events: a... |
1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 |
{ struct module *mod = data; mutex_lock(&event_mutex); switch (val) { case MODULE_STATE_COMING: trace_module_add_events(mod); break; case MODULE_STATE_GOING: trace_module_remove_events(mod); break; } mutex_unlock(&event_mutex); |
fd9949898 tracing: add raw ... |
1344 |
|
1473e4417 tracing: make eve... |
1345 1346 |
return 0; } |
61f919a12 tracing/events: f... |
1347 1348 1349 1350 1351 1352 1353 |
#else static int trace_module_notify(struct notifier_block *self, unsigned long val, void *data) { return 0; } #endif /* CONFIG_MODULES */ |
1473e4417 tracing: make eve... |
1354 |
|
ec827c7ec tracing: add stat... |
1355 |
static struct notifier_block trace_module_nb = { |
6d723736e tracing/events: a... |
1356 1357 1358 |
.notifier_call = trace_module_notify, .priority = 0, }; |
e4a9ea5ee tracing: Replace ... |
1359 1360 |
extern struct ftrace_event_call *__start_ftrace_events[]; extern struct ftrace_event_call *__stop_ftrace_events[]; |
a59fd6027 tracing/events: c... |
1361 |
|
020e5f85c tracing/events: A... |
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 |
static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata; static __init int setup_trace_event(char *str) { strlcpy(bootup_event_buf, str, COMMAND_LINE_SIZE); ring_buffer_expanded = 1; tracing_selftest_disabled = 1; return 1; } __setup("trace_event=", setup_trace_event); |
b77e38aa2 tracing: add even... |
1373 1374 |
static __init int event_trace_init(void) { |
e4a9ea5ee tracing: Replace ... |
1375 |
struct ftrace_event_call **call; |
b77e38aa2 tracing: add even... |
1376 1377 |
struct dentry *d_tracer; struct dentry *entry; |
1473e4417 tracing: make eve... |
1378 |
struct dentry *d_events; |
6d723736e tracing/events: a... |
1379 |
int ret; |
020e5f85c tracing/events: A... |
1380 1381 |
char *buf = bootup_event_buf; char *token; |
b77e38aa2 tracing: add even... |
1382 1383 1384 1385 |
d_tracer = tracing_init_dentry(); if (!d_tracer) return 0; |
2314c4ae1 tracing: add back... |
1386 1387 1388 1389 1390 1391 1392 |
entry = debugfs_create_file("available_events", 0444, d_tracer, (void *)&show_event_seq_ops, &ftrace_avail_fops); if (!entry) pr_warning("Could not create debugfs " "'available_events' entry "); |
b77e38aa2 tracing: add even... |
1393 1394 1395 1396 1397 1398 1399 |
entry = debugfs_create_file("set_event", 0644, d_tracer, (void *)&show_set_event_seq_ops, &ftrace_set_event_fops); if (!entry) pr_warning("Could not create debugfs " "'set_event' entry "); |
1473e4417 tracing: make eve... |
1400 1401 1402 |
d_events = event_trace_events_dir(); if (!d_events) return 0; |
d1b182a8d tracing/events/ri... |
1403 1404 1405 1406 1407 1408 1409 1410 |
/* ring buffer internal formats */ trace_create_file("header_page", 0444, d_events, ring_buffer_print_page_header, &ftrace_show_header_fops); trace_create_file("header_event", 0444, d_events, ring_buffer_print_entry_header, &ftrace_show_header_fops); |
8ae79a138 tracing: add hier... |
1411 |
trace_create_file("enable", 0644, d_events, |
8f31bfe53 tracing/events: c... |
1412 |
NULL, &ftrace_system_enable_fops); |
8ae79a138 tracing: add hier... |
1413 |
|
8728fe501 tracing: Don't al... |
1414 1415 |
if (trace_define_common_fields()) pr_warning("tracing: Failed to allocate common fields"); |
6d723736e tracing/events: a... |
1416 |
for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { |
e4a9ea5ee tracing: Replace ... |
1417 |
__trace_add_event_call(*call, NULL, &ftrace_event_id_fops, |
88f70d759 tracing/ftrace: F... |
1418 1419 1420 |
&ftrace_enable_fops, &ftrace_event_filter_fops, &ftrace_event_format_fops); |
1473e4417 tracing: make eve... |
1421 |
} |
020e5f85c tracing/events: A... |
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 |
while (true) { token = strsep(&buf, ","); if (!token) break; if (!*token) continue; ret = ftrace_set_clr_event(token, 1); if (ret) pr_warning("Failed to enable trace event: %s ", token); } |
6d723736e tracing/events: a... |
1435 |
ret = register_module_notifier(&trace_module_nb); |
553793769 ftrace: fix check... |
1436 |
if (ret) |
6d723736e tracing/events: a... |
1437 1438 |
pr_warning("Failed to register trace events module notifier "); |
b77e38aa2 tracing: add even... |
1439 1440 1441 |
return 0; } fs_initcall(event_trace_init); |
e6187007d tracing/events: a... |
1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 |
#ifdef CONFIG_FTRACE_STARTUP_TEST static DEFINE_SPINLOCK(test_spinlock); static DEFINE_SPINLOCK(test_spinlock_irq); static DEFINE_MUTEX(test_mutex); static __init void test_work(struct work_struct *dummy) { spin_lock(&test_spinlock); spin_lock_irq(&test_spinlock_irq); udelay(1); spin_unlock_irq(&test_spinlock_irq); spin_unlock(&test_spinlock); mutex_lock(&test_mutex); msleep(1); mutex_unlock(&test_mutex); } static __init int event_test_thread(void *unused) { void *test_malloc; test_malloc = kmalloc(1234, GFP_KERNEL); if (!test_malloc) pr_info("failed to kmalloc "); schedule_on_each_cpu(test_work); kfree(test_malloc); set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) schedule(); return 0; } /* * Do various things that may trigger events. */ static __init void event_test_stuff(void) { struct task_struct *test_thread; test_thread = kthread_run(event_test_thread, NULL, "test-events"); msleep(1); kthread_stop(test_thread); } /* * For every trace event defined, we will test each trace point separately, * and then by groups, and finally all trace points. */ |
9ea21c1ec tracing/events: p... |
1498 |
static __init void event_trace_self_tests(void) |
e6187007d tracing/events: a... |
1499 1500 1501 |
{ struct ftrace_event_call *call; struct event_subsystem *system; |
e6187007d tracing/events: a... |
1502 1503 1504 1505 1506 1507 |
int ret; pr_info("Running tests on trace events: "); list_for_each_entry(call, &ftrace_events, list) { |
2239291ae tracing: Remove p... |
1508 1509 |
/* Only test those that have a probe */ if (!call->class || !call->class->probe) |
e6187007d tracing/events: a... |
1510 |
continue; |
1f5a6b454 tracing: make tes... |
1511 1512 1513 1514 1515 1516 1517 |
/* * Testing syscall events here is pretty useless, but * we still do it if configured. But this is time consuming. * What we really need is a user thread to perform the * syscalls as we test. */ #ifndef CONFIG_EVENT_TRACE_TEST_SYSCALLS |
8f0820183 tracing: Create c... |
1518 1519 |
if (call->class->system && strcmp(call->class->system, "syscalls") == 0) |
1f5a6b454 tracing: make tes... |
1520 1521 |
continue; #endif |
e6187007d tracing/events: a... |
1522 1523 1524 1525 1526 1527 |
pr_info("Testing event %s: ", call->name); /* * If an event is already enabled, someone is using * it and the self test should not be on. */ |
553552ce1 tracing: Combine ... |
1528 |
if (call->flags & TRACE_EVENT_FL_ENABLED) { |
e6187007d tracing/events: a... |
1529 1530 1531 1532 1533 |
pr_warning("Enabled event during self test! "); WARN_ON_ONCE(1); continue; } |
0e907c993 ftrace: clean up ... |
1534 |
ftrace_event_enable_disable(call, 1); |
e6187007d tracing/events: a... |
1535 |
event_test_stuff(); |
0e907c993 ftrace: clean up ... |
1536 |
ftrace_event_enable_disable(call, 0); |
e6187007d tracing/events: a... |
1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 |
pr_cont("OK "); } /* Now test at the sub system level */ pr_info("Running tests on trace event systems: "); list_for_each_entry(system, &event_subsystems, list) { /* the ftrace system is special, skip it */ if (strcmp(system->name, "ftrace") == 0) continue; pr_info("Testing event system %s: ", system->name); |
8f31bfe53 tracing/events: c... |
1554 |
ret = __ftrace_set_clr_event(NULL, system->name, NULL, 1); |
e6187007d tracing/events: a... |
1555 1556 1557 1558 1559 1560 1561 1562 |
if (WARN_ON_ONCE(ret)) { pr_warning("error enabling system %s ", system->name); continue; } event_test_stuff(); |
8f31bfe53 tracing/events: c... |
1563 |
ret = __ftrace_set_clr_event(NULL, system->name, NULL, 0); |
e6187007d tracing/events: a... |
1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 |
if (WARN_ON_ONCE(ret)) pr_warning("error disabling system %s ", system->name); pr_cont("OK "); } /* Test with all events enabled */ pr_info("Running tests on all trace events: "); pr_info("Testing all events: "); |
8f31bfe53 tracing/events: c... |
1578 |
ret = __ftrace_set_clr_event(NULL, NULL, NULL, 1); |
e6187007d tracing/events: a... |
1579 |
if (WARN_ON_ONCE(ret)) { |
e6187007d tracing/events: a... |
1580 1581 |
pr_warning("error enabling all events "); |
9ea21c1ec tracing/events: p... |
1582 |
return; |
e6187007d tracing/events: a... |
1583 1584 1585 1586 1587 |
} event_test_stuff(); /* reset sysname */ |
8f31bfe53 tracing/events: c... |
1588 |
ret = __ftrace_set_clr_event(NULL, NULL, NULL, 0); |
e6187007d tracing/events: a... |
1589 1590 1591 |
if (WARN_ON_ONCE(ret)) { pr_warning("error disabling all events "); |
9ea21c1ec tracing/events: p... |
1592 |
return; |
e6187007d tracing/events: a... |
1593 1594 1595 1596 |
} pr_cont("OK "); |
9ea21c1ec tracing/events: p... |
1597 1598 1599 |
} #ifdef CONFIG_FUNCTION_TRACER |
245b2e70e percpu: clean up ... |
1600 |
static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable); |
9ea21c1ec tracing/events: p... |
1601 1602 1603 1604 1605 |
static void function_test_events_call(unsigned long ip, unsigned long parent_ip) { struct ring_buffer_event *event; |
e77405ad8 tracing: pass aro... |
1606 |
struct ring_buffer *buffer; |
9ea21c1ec tracing/events: p... |
1607 1608 1609 |
struct ftrace_entry *entry; unsigned long flags; long disabled; |
9ea21c1ec tracing/events: p... |
1610 1611 1612 1613 |
int cpu; int pc; pc = preempt_count(); |
5168ae50a tracing: Remove f... |
1614 |
preempt_disable_notrace(); |
9ea21c1ec tracing/events: p... |
1615 |
cpu = raw_smp_processor_id(); |
245b2e70e percpu: clean up ... |
1616 |
disabled = atomic_inc_return(&per_cpu(ftrace_test_event_disable, cpu)); |
9ea21c1ec tracing/events: p... |
1617 1618 1619 1620 1621 |
if (disabled != 1) goto out; local_save_flags(flags); |
e77405ad8 tracing: pass aro... |
1622 1623 |
event = trace_current_buffer_lock_reserve(&buffer, TRACE_FN, sizeof(*entry), |
9ea21c1ec tracing/events: p... |
1624 1625 1626 1627 1628 1629 |
flags, pc); if (!event) goto out; entry = ring_buffer_event_data(event); entry->ip = ip; entry->parent_ip = parent_ip; |
e77405ad8 tracing: pass aro... |
1630 |
trace_nowake_buffer_unlock_commit(buffer, event, flags, pc); |
9ea21c1ec tracing/events: p... |
1631 1632 |
out: |
245b2e70e percpu: clean up ... |
1633 |
atomic_dec(&per_cpu(ftrace_test_event_disable, cpu)); |
5168ae50a tracing: Remove f... |
1634 |
preempt_enable_notrace(); |
9ea21c1ec tracing/events: p... |
1635 1636 1637 1638 1639 1640 1641 1642 1643 |
} static struct ftrace_ops trace_ops __initdata = { .func = function_test_events_call, }; static __init void event_trace_self_test_with_function(void) { |
17bb615ad tracing: Have eve... |
1644 1645 1646 1647 1648 1649 1650 |
int ret; ret = register_ftrace_function(&trace_ops); if (WARN_ON(ret < 0)) { pr_info("Failed to enable function tracer for event tests "); return; } |
9ea21c1ec tracing/events: p... |
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 |
pr_info("Running tests again, along with the function tracer "); event_trace_self_tests(); unregister_ftrace_function(&trace_ops); } #else static __init void event_trace_self_test_with_function(void) { } #endif static __init int event_trace_self_tests_init(void) { |
020e5f85c tracing/events: A... |
1664 1665 1666 1667 |
if (!tracing_selftest_disabled) { event_trace_self_tests(); event_trace_self_test_with_function(); } |
e6187007d tracing/events: a... |
1668 1669 1670 |
return 0; } |
28d20e2d6 tracing/events: c... |
1671 |
late_initcall(event_trace_self_tests_init); |
e6187007d tracing/events: a... |
1672 1673 |
#endif |