aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_functions.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-02-14 19:04:24 -0500
committerSteven Rostedt <srostedt@redhat.com>2009-02-16 22:50:04 -0500
commit23b4ff3aa479c9e3bb23cb6b2d0a97878399784a (patch)
treeba446de609489d91303e6bdafd5168463100417a /kernel/trace/trace_functions.c
parent988ae9d6b2bc3ebdc1a488490250a6812f85e9d4 (diff)
ftrace: add traceon traceoff commands to enable/disable the buffers
This patch adds the new function selection commands traceon and traceoff. traceon sets the function to enable the ring buffers while traceoff disables the ring buffers. You can pass in the number of times you want the command to be executed when the function is hit. It will only execute if the state of the buffers are not already in that state. Example: # echo do_fork:traceon:4 Will enable the ring buffers if they are disabled every time it hits do_fork, up to 4 times. # echo sys_close:traceoff This will disable the ring buffers every time (unlimited) when sys_close is called. Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel/trace/trace_functions.c')
-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