diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-02-17 05:31:01 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-17 05:31:01 -0500 |
commit | f492d3f8385a98f828e8220d14492337dc29e07b (patch) | |
tree | 31f22c83f7e45388955aacb45c425d7cb6a4d78c /kernel/trace/trace_functions.c | |
parent | c4e2b432d5b57e2faaeea048079b31c243079647 (diff) | |
parent | e110e3d1eaa0f9628918be67ddd32e8ad65a2871 (diff) |
Merge branch 'tip/tracing/ftrace' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into tracing/ftrace
Diffstat (limited to 'kernel/trace/trace_functions.c')
-rw-r--r-- | kernel/trace/trace_functions.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c index 36bf9568ccd..f520aa419df 100644 --- a/kernel/trace/trace_functions.c +++ b/kernel/trace/trace_functions.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * Copyright (C) 2004-2006 Ingo Molnar | 9 | * Copyright (C) 2004-2006 Ingo Molnar |
10 | * Copyright (C) 2004 William Lee Irwin III | 10 | * Copyright (C) 2004 William Lee Irwin III |
11 | */ | 11 | */ |
12 | #include <linux/ring_buffer.h> | ||
12 | #include <linux/debugfs.h> | 13 | #include <linux/debugfs.h> |
13 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
14 | #include <linux/ftrace.h> | 15 | #include <linux/ftrace.h> |
@@ -231,9 +232,171 @@ static struct tracer function_trace __read_mostly = | |||
231 | #endif | 232 | #endif |
232 | }; | 233 | }; |
233 | 234 | ||
235 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
236 | static void | ||
237 | ftrace_traceon(unsigned long ip, unsigned long parent_ip, void **data) | ||
238 | { | ||
239 | long *count = (long *)data; | ||
240 | |||
241 | if (tracing_is_on()) | ||
242 | return; | ||
243 | |||
244 | if (!*count) | ||
245 | return; | ||
246 | |||
247 | if (*count != -1) | ||
248 | (*count)--; | ||
249 | |||
250 | tracing_on(); | ||
251 | } | ||
252 | |||
253 | static void | ||
254 | ftrace_traceoff(unsigned long ip, unsigned long parent_ip, void **data) | ||
255 | { | ||
256 | long *count = (long *)data; | ||
257 | |||
258 | if (!tracing_is_on()) | ||
259 | return; | ||
260 | |||
261 | if (!*count) | ||
262 | return; | ||
263 | |||
264 | if (*count != -1) | ||
265 | (*count)--; | ||
266 | |||
267 | tracing_off(); | ||
268 | } | ||
269 | |||
270 | static int | ||
271 | ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, | ||
272 | struct ftrace_hook_ops *ops, void *data); | ||
273 | |||
274 | static struct ftrace_hook_ops traceon_hook_ops = { | ||
275 | .func = ftrace_traceon, | ||
276 | .print = ftrace_trace_onoff_print, | ||
277 | }; | ||
278 | |||
279 | static struct ftrace_hook_ops traceoff_hook_ops = { | ||
280 | .func = ftrace_traceoff, | ||
281 | .print = ftrace_trace_onoff_print, | ||
282 | }; | ||
283 | |||
284 | static int | ||
285 | ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, | ||
286 | struct ftrace_hook_ops *ops, void *data) | ||
287 | { | ||
288 | char str[KSYM_SYMBOL_LEN]; | ||
289 | long count = (long)data; | ||
290 | |||
291 | kallsyms_lookup(ip, NULL, NULL, NULL, str); | ||
292 | seq_printf(m, "%s:", str); | ||
293 | |||
294 | if (ops == &traceon_hook_ops) | ||
295 | seq_printf(m, "traceon"); | ||
296 | else | ||
297 | seq_printf(m, "traceoff"); | ||
298 | |||
299 | if (count != -1) | ||
300 | seq_printf(m, ":count=%ld", count); | ||
301 | seq_putc(m, '\n'); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int | ||
307 | ftrace_trace_onoff_unreg(char *glob, char *cmd, char *param) | ||
308 | { | ||
309 | struct ftrace_hook_ops *ops; | ||
310 | |||
311 | /* we register both traceon and traceoff to this callback */ | ||
312 | if (strcmp(cmd, "traceon") == 0) | ||
313 | ops = &traceon_hook_ops; | ||
314 | else | ||
315 | ops = &traceoff_hook_ops; | ||
316 | |||
317 | unregister_ftrace_function_hook_func(glob, ops); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int | ||
323 | ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable) | ||
324 | { | ||
325 | struct ftrace_hook_ops *ops; | ||
326 | void *count = (void *)-1; | ||
327 | char *number; | ||
328 | int ret; | ||
329 | |||
330 | /* hash funcs only work with set_ftrace_filter */ | ||
331 | if (!enable) | ||
332 | return -EINVAL; | ||
333 | |||
334 | if (glob[0] == '!') | ||
335 | return ftrace_trace_onoff_unreg(glob+1, cmd, param); | ||
336 | |||
337 | /* we register both traceon and traceoff to this callback */ | ||
338 | if (strcmp(cmd, "traceon") == 0) | ||
339 | ops = &traceon_hook_ops; | ||
340 | else | ||
341 | ops = &traceoff_hook_ops; | ||
342 | |||
343 | if (!param) | ||
344 | goto out_reg; | ||
345 | |||
346 | number = strsep(¶m, ":"); | ||
347 | |||
348 | if (!strlen(number)) | ||
349 | goto out_reg; | ||
350 | |||
351 | /* | ||
352 | * We use the callback data field (which is a pointer) | ||
353 | * as our counter. | ||
354 | */ | ||
355 | ret = strict_strtoul(number, 0, (unsigned long *)&count); | ||
356 | if (ret) | ||
357 | return ret; | ||
358 | |||
359 | out_reg: | ||
360 | ret = register_ftrace_function_hook(glob, ops, count); | ||
361 | |||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static struct ftrace_func_command ftrace_traceon_cmd = { | ||
366 | .name = "traceon", | ||
367 | .func = ftrace_trace_onoff_callback, | ||
368 | }; | ||
369 | |||
370 | static struct ftrace_func_command ftrace_traceoff_cmd = { | ||
371 | .name = "traceoff", | ||
372 | .func = ftrace_trace_onoff_callback, | ||
373 | }; | ||
374 | |||
375 | static int __init init_func_cmd_traceon(void) | ||
376 | { | ||
377 | int ret; | ||
378 | |||
379 | ret = register_ftrace_command(&ftrace_traceoff_cmd); | ||
380 | if (ret) | ||
381 | return ret; | ||
382 | |||
383 | ret = register_ftrace_command(&ftrace_traceon_cmd); | ||
384 | if (ret) | ||
385 | unregister_ftrace_command(&ftrace_traceoff_cmd); | ||
386 | return ret; | ||
387 | } | ||
388 | #else | ||
389 | static inline int init_func_cmd_traceon(void) | ||
390 | { | ||
391 | return 0; | ||
392 | } | ||
393 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
394 | |||
234 | static __init int init_function_trace(void) | 395 | static __init int init_function_trace(void) |
235 | { | 396 | { |
397 | init_func_cmd_traceon(); | ||
236 | return register_tracer(&function_trace); | 398 | return register_tracer(&function_trace); |
237 | } | 399 | } |
238 | 400 | ||
239 | device_initcall(init_function_trace); | 401 | device_initcall(init_function_trace); |
402 | |||