|
@@ -60,6 +60,13 @@ static int last_ftrace_enabled;
|
|
|
/* Quick disabling of function tracer. */
|
|
|
int function_trace_stop;
|
|
|
|
|
|
+/* List for set_ftrace_pid's pids. */
|
|
|
+LIST_HEAD(ftrace_pids);
|
|
|
+struct ftrace_pid {
|
|
|
+ struct list_head list;
|
|
|
+ struct pid *pid;
|
|
|
+};
|
|
|
+
|
|
|
/*
|
|
|
* ftrace_disabled is set when an anomaly is discovered.
|
|
|
* ftrace_disabled is much stronger than ftrace_enabled.
|
|
@@ -78,6 +85,10 @@ ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
|
|
|
ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
|
|
|
ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
|
|
|
|
|
|
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
|
+static int ftrace_set_func(unsigned long *array, int *idx, char *buffer);
|
|
|
+#endif
|
|
|
+
|
|
|
static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
|
|
|
{
|
|
|
struct ftrace_ops *op = ftrace_list;
|
|
@@ -155,7 +166,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops)
|
|
|
else
|
|
|
func = ftrace_list_func;
|
|
|
|
|
|
- if (ftrace_pid_trace) {
|
|
|
+ if (!list_empty(&ftrace_pids)) {
|
|
|
set_ftrace_pid_function(func);
|
|
|
func = ftrace_pid_func;
|
|
|
}
|
|
@@ -203,7 +214,7 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
|
|
|
if (ftrace_list->next == &ftrace_list_end) {
|
|
|
ftrace_func_t func = ftrace_list->func;
|
|
|
|
|
|
- if (ftrace_pid_trace) {
|
|
|
+ if (!list_empty(&ftrace_pids)) {
|
|
|
set_ftrace_pid_function(func);
|
|
|
func = ftrace_pid_func;
|
|
|
}
|
|
@@ -231,7 +242,7 @@ static void ftrace_update_pid_func(void)
|
|
|
func = __ftrace_trace_function;
|
|
|
#endif
|
|
|
|
|
|
- if (ftrace_pid_trace) {
|
|
|
+ if (!list_empty(&ftrace_pids)) {
|
|
|
set_ftrace_pid_function(func);
|
|
|
func = ftrace_pid_func;
|
|
|
} else {
|
|
@@ -821,8 +832,6 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
|
|
|
}
|
|
|
#endif /* CONFIG_FUNCTION_PROFILER */
|
|
|
|
|
|
-/* set when tracing only a pid */
|
|
|
-struct pid *ftrace_pid_trace;
|
|
|
static struct pid * const ftrace_swapper_pid = &init_struct_pid;
|
|
|
|
|
|
#ifdef CONFIG_DYNAMIC_FTRACE
|
|
@@ -1261,12 +1270,34 @@ static int ftrace_update_code(struct module *mod)
|
|
|
ftrace_new_addrs = p->newlist;
|
|
|
p->flags = 0L;
|
|
|
|
|
|
- /* convert record (i.e, patch mcount-call with NOP) */
|
|
|
- if (ftrace_code_disable(mod, p)) {
|
|
|
- p->flags |= FTRACE_FL_CONVERTED;
|
|
|
- ftrace_update_cnt++;
|
|
|
- } else
|
|
|
+ /*
|
|
|
+ * Do the initial record convertion from mcount jump
|
|
|
+ * to the NOP instructions.
|
|
|
+ */
|
|
|
+ if (!ftrace_code_disable(mod, p)) {
|
|
|
ftrace_free_rec(p);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ p->flags |= FTRACE_FL_CONVERTED;
|
|
|
+ ftrace_update_cnt++;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the tracing is enabled, go ahead and enable the record.
|
|
|
+ *
|
|
|
+ * The reason not to enable the record immediatelly is the
|
|
|
+ * inherent check of ftrace_make_nop/ftrace_make_call for
|
|
|
+ * correct previous instructions. Making first the NOP
|
|
|
+ * conversion puts the module to the correct state, thus
|
|
|
+ * passing the ftrace_make_call check.
|
|
|
+ */
|
|
|
+ if (ftrace_start_up) {
|
|
|
+ int failed = __ftrace_replace_code(p, 1);
|
|
|
+ if (failed) {
|
|
|
+ ftrace_bug(failed, p->ip);
|
|
|
+ ftrace_free_rec(p);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
stop = ftrace_now(raw_smp_processor_id());
|
|
@@ -1656,60 +1687,6 @@ ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-enum {
|
|
|
- MATCH_FULL,
|
|
|
- MATCH_FRONT_ONLY,
|
|
|
- MATCH_MIDDLE_ONLY,
|
|
|
- MATCH_END_ONLY,
|
|
|
-};
|
|
|
-
|
|
|
-/*
|
|
|
- * (static function - no need for kernel doc)
|
|
|
- *
|
|
|
- * Pass in a buffer containing a glob and this function will
|
|
|
- * set search to point to the search part of the buffer and
|
|
|
- * return the type of search it is (see enum above).
|
|
|
- * This does modify buff.
|
|
|
- *
|
|
|
- * Returns enum type.
|
|
|
- * search returns the pointer to use for comparison.
|
|
|
- * not returns 1 if buff started with a '!'
|
|
|
- * 0 otherwise.
|
|
|
- */
|
|
|
-static int
|
|
|
-ftrace_setup_glob(char *buff, int len, char **search, int *not)
|
|
|
-{
|
|
|
- int type = MATCH_FULL;
|
|
|
- int i;
|
|
|
-
|
|
|
- if (buff[0] == '!') {
|
|
|
- *not = 1;
|
|
|
- buff++;
|
|
|
- len--;
|
|
|
- } else
|
|
|
- *not = 0;
|
|
|
-
|
|
|
- *search = buff;
|
|
|
-
|
|
|
- for (i = 0; i < len; i++) {
|
|
|
- if (buff[i] == '*') {
|
|
|
- if (!i) {
|
|
|
- *search = buff + 1;
|
|
|
- type = MATCH_END_ONLY;
|
|
|
- } else {
|
|
|
- if (type == MATCH_END_ONLY)
|
|
|
- type = MATCH_MIDDLE_ONLY;
|
|
|
- else
|
|
|
- type = MATCH_FRONT_ONLY;
|
|
|
- buff[i] = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return type;
|
|
|
-}
|
|
|
-
|
|
|
static int ftrace_match(char *str, char *regex, int len, int type)
|
|
|
{
|
|
|
int matched = 0;
|
|
@@ -1758,7 +1735,7 @@ static void ftrace_match_records(char *buff, int len, int enable)
|
|
|
int not;
|
|
|
|
|
|
flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
|
|
|
- type = ftrace_setup_glob(buff, len, &search, ¬);
|
|
|
+ type = filter_parse_regex(buff, len, &search, ¬);
|
|
|
|
|
|
search_len = strlen(search);
|
|
|
|
|
@@ -1826,7 +1803,7 @@ static void ftrace_match_module_records(char *buff, char *mod, int enable)
|
|
|
}
|
|
|
|
|
|
if (strlen(buff)) {
|
|
|
- type = ftrace_setup_glob(buff, strlen(buff), &search, ¬);
|
|
|
+ type = filter_parse_regex(buff, strlen(buff), &search, ¬);
|
|
|
search_len = strlen(search);
|
|
|
}
|
|
|
|
|
@@ -1991,7 +1968,7 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
|
|
|
int count = 0;
|
|
|
char *search;
|
|
|
|
|
|
- type = ftrace_setup_glob(glob, strlen(glob), &search, ¬);
|
|
|
+ type = filter_parse_regex(glob, strlen(glob), &search, ¬);
|
|
|
len = strlen(search);
|
|
|
|
|
|
/* we do not support '!' for function probes */
|
|
@@ -2068,7 +2045,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
|
|
|
else if (glob) {
|
|
|
int not;
|
|
|
|
|
|
- type = ftrace_setup_glob(glob, strlen(glob), &search, ¬);
|
|
|
+ type = filter_parse_regex(glob, strlen(glob), &search, ¬);
|
|
|
len = strlen(search);
|
|
|
|
|
|
/* we do not support '!' for function probes */
|
|
@@ -2312,6 +2289,32 @@ static int __init set_ftrace_filter(char *str)
|
|
|
}
|
|
|
__setup("ftrace_filter=", set_ftrace_filter);
|
|
|
|
|
|
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
|
+static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
|
|
|
+static int __init set_graph_function(char *str)
|
|
|
+{
|
|
|
+ strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+__setup("ftrace_graph_filter=", set_graph_function);
|
|
|
+
|
|
|
+static void __init set_ftrace_early_graph(char *buf)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ char *func;
|
|
|
+
|
|
|
+ while (buf) {
|
|
|
+ func = strsep(&buf, ",");
|
|
|
+ /* we allow only one expression at a time */
|
|
|
+ ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
|
|
|
+ func);
|
|
|
+ if (ret)
|
|
|
+ printk(KERN_DEBUG "ftrace: function %s not "
|
|
|
+ "traceable\n", func);
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
|
|
+
|
|
|
static void __init set_ftrace_early_filter(char *buf, int enable)
|
|
|
{
|
|
|
char *func;
|
|
@@ -2328,6 +2331,10 @@ static void __init set_ftrace_early_filters(void)
|
|
|
set_ftrace_early_filter(ftrace_filter_buf, 1);
|
|
|
if (ftrace_notrace_buf[0])
|
|
|
set_ftrace_early_filter(ftrace_notrace_buf, 0);
|
|
|
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
|
+ if (ftrace_graph_buf[0])
|
|
|
+ set_ftrace_early_graph(ftrace_graph_buf);
|
|
|
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -2513,7 +2520,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
|
|
|
return -ENODEV;
|
|
|
|
|
|
/* decode regex */
|
|
|
- type = ftrace_setup_glob(buffer, strlen(buffer), &search, ¬);
|
|
|
+ type = filter_parse_regex(buffer, strlen(buffer), &search, ¬);
|
|
|
if (not)
|
|
|
return -EINVAL;
|
|
|
|
|
@@ -2624,7 +2631,7 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int ftrace_convert_nops(struct module *mod,
|
|
|
+static int ftrace_process_locs(struct module *mod,
|
|
|
unsigned long *start,
|
|
|
unsigned long *end)
|
|
|
{
|
|
@@ -2684,7 +2691,7 @@ static void ftrace_init_module(struct module *mod,
|
|
|
{
|
|
|
if (ftrace_disabled || start == end)
|
|
|
return;
|
|
|
- ftrace_convert_nops(mod, start, end);
|
|
|
+ ftrace_process_locs(mod, start, end);
|
|
|
}
|
|
|
|
|
|
static int ftrace_module_notify(struct notifier_block *self,
|
|
@@ -2745,7 +2752,7 @@ void __init ftrace_init(void)
|
|
|
|
|
|
last_ftrace_enabled = ftrace_enabled = 1;
|
|
|
|
|
|
- ret = ftrace_convert_nops(NULL,
|
|
|
+ ret = ftrace_process_locs(NULL,
|
|
|
__start_mcount_loc,
|
|
|
__stop_mcount_loc);
|
|
|
|
|
@@ -2778,23 +2785,6 @@ static inline void ftrace_startup_enable(int command) { }
|
|
|
# define ftrace_shutdown_sysctl() do { } while (0)
|
|
|
#endif /* CONFIG_DYNAMIC_FTRACE */
|
|
|
|
|
|
-static ssize_t
|
|
|
-ftrace_pid_read(struct file *file, char __user *ubuf,
|
|
|
- size_t cnt, loff_t *ppos)
|
|
|
-{
|
|
|
- char buf[64];
|
|
|
- int r;
|
|
|
-
|
|
|
- if (ftrace_pid_trace == ftrace_swapper_pid)
|
|
|
- r = sprintf(buf, "swapper tasks\n");
|
|
|
- else if (ftrace_pid_trace)
|
|
|
- r = sprintf(buf, "%u\n", pid_vnr(ftrace_pid_trace));
|
|
|
- else
|
|
|
- r = sprintf(buf, "no pid\n");
|
|
|
-
|
|
|
- return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
|
|
|
-}
|
|
|
-
|
|
|
static void clear_ftrace_swapper(void)
|
|
|
{
|
|
|
struct task_struct *p;
|
|
@@ -2845,14 +2835,12 @@ static void set_ftrace_pid(struct pid *pid)
|
|
|
rcu_read_unlock();
|
|
|
}
|
|
|
|
|
|
-static void clear_ftrace_pid_task(struct pid **pid)
|
|
|
+static void clear_ftrace_pid_task(struct pid *pid)
|
|
|
{
|
|
|
- if (*pid == ftrace_swapper_pid)
|
|
|
+ if (pid == ftrace_swapper_pid)
|
|
|
clear_ftrace_swapper();
|
|
|
else
|
|
|
- clear_ftrace_pid(*pid);
|
|
|
-
|
|
|
- *pid = NULL;
|
|
|
+ clear_ftrace_pid(pid);
|
|
|
}
|
|
|
|
|
|
static void set_ftrace_pid_task(struct pid *pid)
|
|
@@ -2863,74 +2851,184 @@ static void set_ftrace_pid_task(struct pid *pid)
|
|
|
set_ftrace_pid(pid);
|
|
|
}
|
|
|
|
|
|
-static ssize_t
|
|
|
-ftrace_pid_write(struct file *filp, const char __user *ubuf,
|
|
|
- size_t cnt, loff_t *ppos)
|
|
|
+static int ftrace_pid_add(int p)
|
|
|
{
|
|
|
struct pid *pid;
|
|
|
- char buf[64];
|
|
|
- long val;
|
|
|
- int ret;
|
|
|
+ struct ftrace_pid *fpid;
|
|
|
+ int ret = -EINVAL;
|
|
|
|
|
|
- if (cnt >= sizeof(buf))
|
|
|
- return -EINVAL;
|
|
|
+ mutex_lock(&ftrace_lock);
|
|
|
|
|
|
- if (copy_from_user(&buf, ubuf, cnt))
|
|
|
- return -EFAULT;
|
|
|
+ if (!p)
|
|
|
+ pid = ftrace_swapper_pid;
|
|
|
+ else
|
|
|
+ pid = find_get_pid(p);
|
|
|
|
|
|
- buf[cnt] = 0;
|
|
|
+ if (!pid)
|
|
|
+ goto out;
|
|
|
|
|
|
- ret = strict_strtol(buf, 10, &val);
|
|
|
- if (ret < 0)
|
|
|
- return ret;
|
|
|
+ ret = 0;
|
|
|
|
|
|
- mutex_lock(&ftrace_lock);
|
|
|
- if (val < 0) {
|
|
|
- /* disable pid tracing */
|
|
|
- if (!ftrace_pid_trace)
|
|
|
- goto out;
|
|
|
+ list_for_each_entry(fpid, &ftrace_pids, list)
|
|
|
+ if (fpid->pid == pid)
|
|
|
+ goto out_put;
|
|
|
|
|
|
- clear_ftrace_pid_task(&ftrace_pid_trace);
|
|
|
+ ret = -ENOMEM;
|
|
|
|
|
|
- } else {
|
|
|
- /* swapper task is special */
|
|
|
- if (!val) {
|
|
|
- pid = ftrace_swapper_pid;
|
|
|
- if (pid == ftrace_pid_trace)
|
|
|
- goto out;
|
|
|
- } else {
|
|
|
- pid = find_get_pid(val);
|
|
|
+ fpid = kmalloc(sizeof(*fpid), GFP_KERNEL);
|
|
|
+ if (!fpid)
|
|
|
+ goto out_put;
|
|
|
|
|
|
- if (pid == ftrace_pid_trace) {
|
|
|
- put_pid(pid);
|
|
|
- goto out;
|
|
|
- }
|
|
|
- }
|
|
|
+ list_add(&fpid->list, &ftrace_pids);
|
|
|
+ fpid->pid = pid;
|
|
|
|
|
|
- if (ftrace_pid_trace)
|
|
|
- clear_ftrace_pid_task(&ftrace_pid_trace);
|
|
|
+ set_ftrace_pid_task(pid);
|
|
|
|
|
|
- if (!pid)
|
|
|
- goto out;
|
|
|
+ ftrace_update_pid_func();
|
|
|
+ ftrace_startup_enable(0);
|
|
|
+
|
|
|
+ mutex_unlock(&ftrace_lock);
|
|
|
+ return 0;
|
|
|
+
|
|
|
+out_put:
|
|
|
+ if (pid != ftrace_swapper_pid)
|
|
|
+ put_pid(pid);
|
|
|
|
|
|
- ftrace_pid_trace = pid;
|
|
|
+out:
|
|
|
+ mutex_unlock(&ftrace_lock);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void ftrace_pid_reset(void)
|
|
|
+{
|
|
|
+ struct ftrace_pid *fpid, *safe;
|
|
|
|
|
|
- set_ftrace_pid_task(ftrace_pid_trace);
|
|
|
+ mutex_lock(&ftrace_lock);
|
|
|
+ list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) {
|
|
|
+ struct pid *pid = fpid->pid;
|
|
|
+
|
|
|
+ clear_ftrace_pid_task(pid);
|
|
|
+
|
|
|
+ list_del(&fpid->list);
|
|
|
+ kfree(fpid);
|
|
|
}
|
|
|
|
|
|
- /* update the function call */
|
|
|
ftrace_update_pid_func();
|
|
|
ftrace_startup_enable(0);
|
|
|
|
|
|
- out:
|
|
|
mutex_unlock(&ftrace_lock);
|
|
|
+}
|
|
|
|
|
|
- return cnt;
|
|
|
+static void *fpid_start(struct seq_file *m, loff_t *pos)
|
|
|
+{
|
|
|
+ mutex_lock(&ftrace_lock);
|
|
|
+
|
|
|
+ if (list_empty(&ftrace_pids) && (!*pos))
|
|
|
+ return (void *) 1;
|
|
|
+
|
|
|
+ return seq_list_start(&ftrace_pids, *pos);
|
|
|
+}
|
|
|
+
|
|
|
+static void *fpid_next(struct seq_file *m, void *v, loff_t *pos)
|
|
|
+{
|
|
|
+ if (v == (void *)1)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return seq_list_next(v, &ftrace_pids, pos);
|
|
|
+}
|
|
|
+
|
|
|
+static void fpid_stop(struct seq_file *m, void *p)
|
|
|
+{
|
|
|
+ mutex_unlock(&ftrace_lock);
|
|
|
+}
|
|
|
+
|
|
|
+static int fpid_show(struct seq_file *m, void *v)
|
|
|
+{
|
|
|
+ const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list);
|
|
|
+
|
|
|
+ if (v == (void *)1) {
|
|
|
+ seq_printf(m, "no pid\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (fpid->pid == ftrace_swapper_pid)
|
|
|
+ seq_printf(m, "swapper tasks\n");
|
|
|
+ else
|
|
|
+ seq_printf(m, "%u\n", pid_vnr(fpid->pid));
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct seq_operations ftrace_pid_sops = {
|
|
|
+ .start = fpid_start,
|
|
|
+ .next = fpid_next,
|
|
|
+ .stop = fpid_stop,
|
|
|
+ .show = fpid_show,
|
|
|
+};
|
|
|
+
|
|
|
+static int
|
|
|
+ftrace_pid_open(struct inode *inode, struct file *file)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if ((file->f_mode & FMODE_WRITE) &&
|
|
|
+ (file->f_flags & O_TRUNC))
|
|
|
+ ftrace_pid_reset();
|
|
|
+
|
|
|
+ if (file->f_mode & FMODE_READ)
|
|
|
+ ret = seq_open(file, &ftrace_pid_sops);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t
|
|
|
+ftrace_pid_write(struct file *filp, const char __user *ubuf,
|
|
|
+ size_t cnt, loff_t *ppos)
|
|
|
+{
|
|
|
+ char buf[64], *tmp;
|
|
|
+ long val;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (cnt >= sizeof(buf))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (copy_from_user(&buf, ubuf, cnt))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ buf[cnt] = 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid"
|
|
|
+ * to clean the filter quietly.
|
|
|
+ */
|
|
|
+ tmp = strstrip(buf);
|
|
|
+ if (strlen(tmp) == 0)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ ret = strict_strtol(tmp, 10, &val);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ ret = ftrace_pid_add(val);
|
|
|
+
|
|
|
+ return ret ? ret : cnt;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+ftrace_pid_release(struct inode *inode, struct file *file)
|
|
|
+{
|
|
|
+ if (file->f_mode & FMODE_READ)
|
|
|
+ seq_release(inode, file);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static const struct file_operations ftrace_pid_fops = {
|
|
|
- .read = ftrace_pid_read,
|
|
|
- .write = ftrace_pid_write,
|
|
|
+ .open = ftrace_pid_open,
|
|
|
+ .write = ftrace_pid_write,
|
|
|
+ .read = seq_read,
|
|
|
+ .llseek = seq_lseek,
|
|
|
+ .release = ftrace_pid_release,
|
|
|
};
|
|
|
|
|
|
static __init int ftrace_init_debugfs(void)
|
|
@@ -3293,4 +3391,3 @@ void ftrace_graph_stop(void)
|
|
|
ftrace_stop();
|
|
|
}
|
|
|
#endif
|
|
|
-
|