*  Copyright (C) 2004-2006 Ingo Molnar
  *  Copyright (C) 2004 William Lee Irwin III
  */
+#include <linux/ring_buffer.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/ftrace.h>
 #endif
 };
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+static void
+ftrace_traceon(unsigned long ip, unsigned long parent_ip, void **data)
+{
+       long *count = (long *)data;
+
+       if (tracing_is_on())
+               return;
+
+       if (!*count)
+               return;
+
+       if (*count != -1)
+               (*count)--;
+
+       tracing_on();
+}
+
+static void
+ftrace_traceoff(unsigned long ip, unsigned long parent_ip, void **data)
+{
+       long *count = (long *)data;
+
+       if (!tracing_is_on())
+               return;
+
+       if (!*count)
+               return;
+
+       if (*count != -1)
+               (*count)--;
+
+       tracing_off();
+}
+
+static struct ftrace_hook_ops traceon_hook_ops = {
+       .func                   = ftrace_traceon,
+};
+
+static struct ftrace_hook_ops traceoff_hook_ops = {
+       .func                   = ftrace_traceoff,
+};
+
+static int
+ftrace_trace_onoff_unreg(char *glob, char *cmd, char *param)
+{
+       struct ftrace_hook_ops *ops;
+
+       /* we register both traceon and traceoff to this callback */
+       if (strcmp(cmd, "traceon") == 0)
+               ops = &traceon_hook_ops;
+       else
+               ops = &traceoff_hook_ops;
+
+       unregister_ftrace_function_hook_func(glob, ops);
+
+       return 0;
+}
+
+static int
+ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable)
+{
+       struct ftrace_hook_ops *ops;
+       void *count = (void *)-1;
+       char *number;
+       int ret;
+
+       /* hash funcs only work with set_ftrace_filter */
+       if (!enable)
+               return -EINVAL;
+
+       if (glob[0] == '!')
+               return ftrace_trace_onoff_unreg(glob+1, cmd, param);
+
+       /* we register both traceon and traceoff to this callback */
+       if (strcmp(cmd, "traceon") == 0)
+               ops = &traceon_hook_ops;
+       else
+               ops = &traceoff_hook_ops;
+
+       if (!param)
+               goto out_reg;
+
+       number = strsep(¶m, ":");
+
+       if (!strlen(number))
+               goto out_reg;
+
+       /*
+        * We use the callback data field (which is a pointer)
+        * as our counter.
+        */
+       ret = strict_strtoul(number, 0, (unsigned long *)&count);
+       if (ret)
+               return ret;
+
+ out_reg:
+       ret = register_ftrace_function_hook(glob, ops, count);
+
+       return ret;
+}
+
+static struct ftrace_func_command ftrace_traceon_cmd = {
+       .name                   = "traceon",
+       .func                   = ftrace_trace_onoff_callback,
+};
+
+static struct ftrace_func_command ftrace_traceoff_cmd = {
+       .name                   = "traceoff",
+       .func                   = ftrace_trace_onoff_callback,
+};
+
+static int __init init_func_cmd_traceon(void)
+{
+       int ret;
+
+       ret = register_ftrace_command(&ftrace_traceoff_cmd);
+       if (ret)
+               return ret;
+
+       ret = register_ftrace_command(&ftrace_traceon_cmd);
+       if (ret)
+               unregister_ftrace_command(&ftrace_traceoff_cmd);
+       return ret;
+}
+#else
+static inline int init_func_cmd_traceon(void)
+{
+       return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 static __init int init_function_trace(void)
 {
+       init_func_cmd_traceon();
        return register_tracer(&function_trace);
 }
 
 device_initcall(init_function_trace);
+