aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace_functions.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index 36bf9568ccd9..5c95708b9dc3 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,143 @@ static struct tracer function_trace __read_mostly =
231#endif 232#endif
232}; 233};
233 234
235#ifdef CONFIG_DYNAMIC_FTRACE
236static void
237ftrace_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
253static void
254ftrace_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
270static struct ftrace_hook_ops traceon_hook_ops = {
271 .func = ftrace_traceon,
272};
273
274static struct ftrace_hook_ops traceoff_hook_ops = {
275 .func = ftrace_traceoff,
276};
277
278static int
279ftrace_trace_onoff_unreg(char *glob, char *cmd, char *param)
280{
281 struct ftrace_hook_ops *ops;
282
283 /* we register both traceon and traceoff to this callback */
284 if (strcmp(cmd, "traceon") == 0)
285 ops = &traceon_hook_ops;
286 else
287 ops = &traceoff_hook_ops;
288
289 unregister_ftrace_function_hook_func(glob, ops);
290
291 return 0;
292}
293
294static int
295ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable)
296{
297 struct ftrace_hook_ops *ops;
298 void *count = (void *)-1;
299 char *number;
300 int ret;
301
302 /* hash funcs only work with set_ftrace_filter */
303 if (!enable)
304 return -EINVAL;
305
306 if (glob[0] == '!')
307 return ftrace_trace_onoff_unreg(glob+1, cmd, param);
308
309 /* we register both traceon and traceoff to this callback */
310 if (strcmp(cmd, "traceon") == 0)
311 ops = &traceon_hook_ops;
312 else
313 ops = &traceoff_hook_ops;
314
315 if (!param)
316 goto out_reg;
317
318 number = strsep(&param, ":");
319
320 if (!strlen(number))
321 goto out_reg;
322
323 /*
324 * We use the callback data field (which is a pointer)
325 * as our counter.
326 */
327 ret = strict_strtoul(number, 0, (unsigned long *)&count);
328 if (ret)
329 return ret;
330
331 out_reg:
332 ret = register_ftrace_function_hook(glob, ops, count);
333
334 return ret;
335}
336
337static struct ftrace_func_command ftrace_traceon_cmd = {
338 .name = "traceon",
339 .func = ftrace_trace_onoff_callback,
340};
341
342static struct ftrace_func_command ftrace_traceoff_cmd = {
343 .name = "traceoff",
344 .func = ftrace_trace_onoff_callback,
345};
346
347static int __init init_func_cmd_traceon(void)
348{
349 int ret;
350
351 ret = register_ftrace_command(&ftrace_traceoff_cmd);
352 if (ret)
353 return ret;
354
355 ret = register_ftrace_command(&ftrace_traceon_cmd);
356 if (ret)
357 unregister_ftrace_command(&ftrace_traceoff_cmd);
358 return ret;
359}
360#else
361static inline int init_func_cmd_traceon(void)
362{
363 return 0;
364}
365#endif /* CONFIG_DYNAMIC_FTRACE */
366
234static __init int init_function_trace(void) 367static __init int init_function_trace(void)
235{ 368{
369 init_func_cmd_traceon();
236 return register_tracer(&function_trace); 370 return register_tracer(&function_trace);
237} 371}
238 372
239device_initcall(init_function_trace); 373device_initcall(init_function_trace);
374