Commit cb7be3b2 authored by Steven Rostedt's avatar Steven Rostedt Committed by Ingo Molnar

ftrace: remove daemon

The ftrace daemon is complex and error prone.  This patch strips it out
of the code.
Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 07c4cc1c
...@@ -165,25 +165,8 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) ...@@ -165,25 +165,8 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
} }
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
#ifndef CONFIG_FTRACE_MCOUNT_RECORD #ifndef CONFIG_FTRACE_MCOUNT_RECORD
/* # error Dynamic ftrace depends on MCOUNT_RECORD
* The hash lock is only needed when the recording of the mcount
* callers are dynamic. That is, by the caller themselves and
* not recorded via the compilation.
*/
static DEFINE_SPINLOCK(ftrace_hash_lock);
#define ftrace_hash_lock(flags) spin_lock_irqsave(&ftrace_hash_lock, flags)
#define ftrace_hash_unlock(flags) \
spin_unlock_irqrestore(&ftrace_hash_lock, flags)
static void ftrace_release_hash(unsigned long start, unsigned long end);
#else
/* This is protected via the ftrace_lock with MCOUNT_RECORD. */
#define ftrace_hash_lock(flags) do { (void)(flags); } while (0)
#define ftrace_hash_unlock(flags) do { } while(0)
static inline void ftrace_release_hash(unsigned long start, unsigned long end)
{
}
#endif #endif
/* /*
...@@ -194,8 +177,6 @@ static inline void ftrace_release_hash(unsigned long start, unsigned long end) ...@@ -194,8 +177,6 @@ static inline void ftrace_release_hash(unsigned long start, unsigned long end)
*/ */
static unsigned long mcount_addr = MCOUNT_ADDR; static unsigned long mcount_addr = MCOUNT_ADDR;
static struct task_struct *ftraced_task;
enum { enum {
FTRACE_ENABLE_CALLS = (1 << 0), FTRACE_ENABLE_CALLS = (1 << 0),
FTRACE_DISABLE_CALLS = (1 << 1), FTRACE_DISABLE_CALLS = (1 << 1),
...@@ -212,7 +193,6 @@ static struct hlist_head ftrace_hash[FTRACE_HASHSIZE]; ...@@ -212,7 +193,6 @@ static struct hlist_head ftrace_hash[FTRACE_HASHSIZE];
static DEFINE_PER_CPU(int, ftrace_shutdown_disable_cpu); static DEFINE_PER_CPU(int, ftrace_shutdown_disable_cpu);
static DEFINE_MUTEX(ftraced_lock);
static DEFINE_MUTEX(ftrace_regex_lock); static DEFINE_MUTEX(ftrace_regex_lock);
struct ftrace_page { struct ftrace_page {
...@@ -230,10 +210,6 @@ struct ftrace_page { ...@@ -230,10 +210,6 @@ struct ftrace_page {
static struct ftrace_page *ftrace_pages_start; static struct ftrace_page *ftrace_pages_start;
static struct ftrace_page *ftrace_pages; static struct ftrace_page *ftrace_pages;
static int ftraced_trigger;
static int ftraced_suspend;
static int ftraced_stop;
static int ftrace_record_suspend; static int ftrace_record_suspend;
static struct dyn_ftrace *ftrace_free_records; static struct dyn_ftrace *ftrace_free_records;
...@@ -398,7 +374,6 @@ static void ...@@ -398,7 +374,6 @@ static void
ftrace_record_ip(unsigned long ip) ftrace_record_ip(unsigned long ip)
{ {
struct dyn_ftrace *node; struct dyn_ftrace *node;
unsigned long flags;
unsigned long key; unsigned long key;
int resched; int resched;
int cpu; int cpu;
...@@ -430,24 +405,18 @@ ftrace_record_ip(unsigned long ip) ...@@ -430,24 +405,18 @@ ftrace_record_ip(unsigned long ip)
if (ftrace_ip_in_hash(ip, key)) if (ftrace_ip_in_hash(ip, key))
goto out; goto out;
ftrace_hash_lock(flags);
/* This ip may have hit the hash before the lock */ /* This ip may have hit the hash before the lock */
if (ftrace_ip_in_hash(ip, key)) if (ftrace_ip_in_hash(ip, key))
goto out_unlock; goto out;
node = ftrace_alloc_dyn_node(ip); node = ftrace_alloc_dyn_node(ip);
if (!node) if (!node)
goto out_unlock; goto out;
node->ip = ip; node->ip = ip;
ftrace_add_hash(node, key); ftrace_add_hash(node, key);
ftraced_trigger = 1;
out_unlock:
ftrace_hash_unlock(flags);
out: out:
per_cpu(ftrace_shutdown_disable_cpu, cpu)--; per_cpu(ftrace_shutdown_disable_cpu, cpu)--;
...@@ -647,7 +616,7 @@ ftrace_code_disable(struct dyn_ftrace *rec) ...@@ -647,7 +616,7 @@ ftrace_code_disable(struct dyn_ftrace *rec)
return 1; return 1;
} }
static int __ftrace_update_code(void *ignore); static int ftrace_update_code(void *ignore);
static int __ftrace_modify_code(void *data) static int __ftrace_modify_code(void *data)
{ {
...@@ -659,7 +628,7 @@ static int __ftrace_modify_code(void *data) ...@@ -659,7 +628,7 @@ static int __ftrace_modify_code(void *data)
* Update any recorded ips now that we have the * Update any recorded ips now that we have the
* machine stopped * machine stopped
*/ */
__ftrace_update_code(NULL); ftrace_update_code(NULL);
ftrace_replace_code(1); ftrace_replace_code(1);
tracing_on = 1; tracing_on = 1;
} else if (*command & FTRACE_DISABLE_CALLS) { } else if (*command & FTRACE_DISABLE_CALLS) {
...@@ -686,26 +655,9 @@ static void ftrace_run_update_code(int command) ...@@ -686,26 +655,9 @@ static void ftrace_run_update_code(int command)
stop_machine(__ftrace_modify_code, &command, NULL); stop_machine(__ftrace_modify_code, &command, NULL);
} }
void ftrace_disable_daemon(void)
{
/* Stop the daemon from calling kstop_machine */
mutex_lock(&ftraced_lock);
ftraced_stop = 1;
mutex_unlock(&ftraced_lock);
ftrace_force_update();
}
void ftrace_enable_daemon(void)
{
mutex_lock(&ftraced_lock);
ftraced_stop = 0;
mutex_unlock(&ftraced_lock);
ftrace_force_update();
}
static ftrace_func_t saved_ftrace_func; static ftrace_func_t saved_ftrace_func;
static int ftrace_start;
static DEFINE_MUTEX(ftrace_start_lock);
static void ftrace_startup(void) static void ftrace_startup(void)
{ {
...@@ -714,9 +666,9 @@ static void ftrace_startup(void) ...@@ -714,9 +666,9 @@ static void ftrace_startup(void)
if (unlikely(ftrace_disabled)) if (unlikely(ftrace_disabled))
return; return;
mutex_lock(&ftraced_lock); mutex_lock(&ftrace_start_lock);
ftraced_suspend++; ftrace_start++;
if (ftraced_suspend == 1) if (ftrace_start == 1)
command |= FTRACE_ENABLE_CALLS; command |= FTRACE_ENABLE_CALLS;
if (saved_ftrace_func != ftrace_trace_function) { if (saved_ftrace_func != ftrace_trace_function) {
...@@ -729,7 +681,7 @@ static void ftrace_startup(void) ...@@ -729,7 +681,7 @@ static void ftrace_startup(void)
ftrace_run_update_code(command); ftrace_run_update_code(command);
out: out:
mutex_unlock(&ftraced_lock); mutex_unlock(&ftrace_start_lock);
} }
static void ftrace_shutdown(void) static void ftrace_shutdown(void)
...@@ -739,9 +691,9 @@ static void ftrace_shutdown(void) ...@@ -739,9 +691,9 @@ static void ftrace_shutdown(void)
if (unlikely(ftrace_disabled)) if (unlikely(ftrace_disabled))
return; return;
mutex_lock(&ftraced_lock); mutex_lock(&ftrace_start_lock);
ftraced_suspend--; ftrace_start--;
if (!ftraced_suspend) if (!ftrace_start)
command |= FTRACE_DISABLE_CALLS; command |= FTRACE_DISABLE_CALLS;
if (saved_ftrace_func != ftrace_trace_function) { if (saved_ftrace_func != ftrace_trace_function) {
...@@ -754,7 +706,7 @@ static void ftrace_shutdown(void) ...@@ -754,7 +706,7 @@ static void ftrace_shutdown(void)
ftrace_run_update_code(command); ftrace_run_update_code(command);
out: out:
mutex_unlock(&ftraced_lock); mutex_unlock(&ftrace_start_lock);
} }
static void ftrace_startup_sysctl(void) static void ftrace_startup_sysctl(void)
...@@ -764,15 +716,15 @@ static void ftrace_startup_sysctl(void) ...@@ -764,15 +716,15 @@ static void ftrace_startup_sysctl(void)
if (unlikely(ftrace_disabled)) if (unlikely(ftrace_disabled))
return; return;
mutex_lock(&ftraced_lock); mutex_lock(&ftrace_start_lock);
/* Force update next time */ /* Force update next time */
saved_ftrace_func = NULL; saved_ftrace_func = NULL;
/* ftraced_suspend is true if we want ftrace running */ /* ftrace_start is true if we want ftrace running */
if (ftraced_suspend) if (ftrace_start)
command |= FTRACE_ENABLE_CALLS; command |= FTRACE_ENABLE_CALLS;
ftrace_run_update_code(command); ftrace_run_update_code(command);
mutex_unlock(&ftraced_lock); mutex_unlock(&ftrace_start_lock);
} }
static void ftrace_shutdown_sysctl(void) static void ftrace_shutdown_sysctl(void)
...@@ -782,20 +734,20 @@ static void ftrace_shutdown_sysctl(void) ...@@ -782,20 +734,20 @@ static void ftrace_shutdown_sysctl(void)
if (unlikely(ftrace_disabled)) if (unlikely(ftrace_disabled))
return; return;
mutex_lock(&ftraced_lock); mutex_lock(&ftrace_start_lock);
/* ftraced_suspend is true if ftrace is running */ /* ftrace_start is true if ftrace is running */
if (ftraced_suspend) if (ftrace_start)
command |= FTRACE_DISABLE_CALLS; command |= FTRACE_DISABLE_CALLS;
ftrace_run_update_code(command); ftrace_run_update_code(command);
mutex_unlock(&ftraced_lock); mutex_unlock(&ftrace_start_lock);
} }
static cycle_t ftrace_update_time; static cycle_t ftrace_update_time;
static unsigned long ftrace_update_cnt; static unsigned long ftrace_update_cnt;
unsigned long ftrace_update_tot_cnt; unsigned long ftrace_update_tot_cnt;
static int __ftrace_update_code(void *ignore) static int ftrace_update_code(void *ignore)
{ {
int i, save_ftrace_enabled; int i, save_ftrace_enabled;
cycle_t start, stop; cycle_t start, stop;
...@@ -869,7 +821,6 @@ static int __ftrace_update_code(void *ignore) ...@@ -869,7 +821,6 @@ static int __ftrace_update_code(void *ignore)
stop = ftrace_now(raw_smp_processor_id()); stop = ftrace_now(raw_smp_processor_id());
ftrace_update_time = stop - start; ftrace_update_time = stop - start;
ftrace_update_tot_cnt += ftrace_update_cnt; ftrace_update_tot_cnt += ftrace_update_cnt;
ftraced_trigger = 0;
ftrace_enabled = save_ftrace_enabled; ftrace_enabled = save_ftrace_enabled;
ftrace_record_suspend--; ftrace_record_suspend--;
...@@ -877,17 +828,6 @@ static int __ftrace_update_code(void *ignore) ...@@ -877,17 +828,6 @@ static int __ftrace_update_code(void *ignore)
return 0; return 0;
} }
static int ftrace_update_code(void)
{
if (unlikely(ftrace_disabled) ||
!ftrace_enabled || !ftraced_trigger)
return 0;
stop_machine(__ftrace_update_code, NULL, NULL);
return 1;
}
static int __init ftrace_dyn_table_alloc(unsigned long num_to_init) static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
{ {
struct ftrace_page *pg; struct ftrace_page *pg;
...@@ -1425,10 +1365,10 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable) ...@@ -1425,10 +1365,10 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable)
} }
mutex_lock(&ftrace_sysctl_lock); mutex_lock(&ftrace_sysctl_lock);
mutex_lock(&ftraced_lock); mutex_lock(&ftrace_start_lock);
if (iter->filtered && ftraced_suspend && ftrace_enabled) if (iter->filtered && ftrace_start && ftrace_enabled)
ftrace_run_update_code(FTRACE_ENABLE_CALLS); ftrace_run_update_code(FTRACE_ENABLE_CALLS);
mutex_unlock(&ftraced_lock); mutex_unlock(&ftrace_start_lock);
mutex_unlock(&ftrace_sysctl_lock); mutex_unlock(&ftrace_sysctl_lock);
kfree(iter); kfree(iter);
...@@ -1448,55 +1388,6 @@ ftrace_notrace_release(struct inode *inode, struct file *file) ...@@ -1448,55 +1388,6 @@ ftrace_notrace_release(struct inode *inode, struct file *file)
return ftrace_regex_release(inode, file, 0); return ftrace_regex_release(inode, file, 0);
} }
static ssize_t
ftraced_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
/* don't worry about races */
char *buf = ftraced_stop ? "disabled\n" : "enabled\n";
int r = strlen(buf);
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
}
static ssize_t
ftraced_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
char buf[64];
long val;
int ret;
if (cnt >= sizeof(buf))
return -EINVAL;
if (copy_from_user(&buf, ubuf, cnt))
return -EFAULT;
if (strncmp(buf, "enable", 6) == 0)
val = 1;
else if (strncmp(buf, "disable", 7) == 0)
val = 0;
else {
buf[cnt] = 0;
ret = strict_strtoul(buf, 10, &val);
if (ret < 0)
return ret;
val = !!val;
}
if (val)
ftrace_enable_daemon();
else
ftrace_disable_daemon();
filp->f_pos += cnt;
return cnt;
}
static struct file_operations ftrace_avail_fops = { static struct file_operations ftrace_avail_fops = {
.open = ftrace_avail_open, .open = ftrace_avail_open,
.read = seq_read, .read = seq_read,
...@@ -1527,38 +1418,6 @@ static struct file_operations ftrace_notrace_fops = { ...@@ -1527,38 +1418,6 @@ static struct file_operations ftrace_notrace_fops = {
.release = ftrace_notrace_release, .release = ftrace_notrace_release,
}; };
static struct file_operations ftraced_fops = {
.open = tracing_open_generic,
.read = ftraced_read,
.write = ftraced_write,
};
/**
* ftrace_force_update - force an update to all recording ftrace functions
*/
int ftrace_force_update(void)
{
int ret = 0;
if (unlikely(ftrace_disabled))
return -ENODEV;
mutex_lock(&ftrace_sysctl_lock);
mutex_lock(&ftraced_lock);
/*
* If ftraced_trigger is not set, then there is nothing
* to update.
*/
if (ftraced_trigger && !ftrace_update_code())
ret = -EBUSY;
mutex_unlock(&ftraced_lock);
mutex_unlock(&ftrace_sysctl_lock);
return ret;
}
static __init int ftrace_init_debugfs(void) static __init int ftrace_init_debugfs(void)
{ {
struct dentry *d_tracer; struct dentry *d_tracer;
...@@ -1589,17 +1448,11 @@ static __init int ftrace_init_debugfs(void) ...@@ -1589,17 +1448,11 @@ static __init int ftrace_init_debugfs(void)
pr_warning("Could not create debugfs " pr_warning("Could not create debugfs "
"'set_ftrace_notrace' entry\n"); "'set_ftrace_notrace' entry\n");
entry = debugfs_create_file("ftraced_enabled", 0644, d_tracer,
NULL, &ftraced_fops);
if (!entry)
pr_warning("Could not create debugfs "
"'ftraced_enabled' entry\n");
return 0; return 0;
} }
fs_initcall(ftrace_init_debugfs); fs_initcall(ftrace_init_debugfs);
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
static int ftrace_convert_nops(unsigned long *start, static int ftrace_convert_nops(unsigned long *start,
unsigned long *end) unsigned long *end)
{ {
...@@ -1619,7 +1472,7 @@ static int ftrace_convert_nops(unsigned long *start, ...@@ -1619,7 +1472,7 @@ static int ftrace_convert_nops(unsigned long *start,
/* p is ignored */ /* p is ignored */
local_irq_save(flags); local_irq_save(flags);
__ftrace_update_code(p); ftrace_update_code(p);
local_irq_restore(flags); local_irq_restore(flags);
return 0; return 0;
...@@ -1666,122 +1519,6 @@ void __init ftrace_init(void) ...@@ -1666,122 +1519,6 @@ void __init ftrace_init(void)
failed: failed:
ftrace_disabled = 1; ftrace_disabled = 1;
} }
#else /* CONFIG_FTRACE_MCOUNT_RECORD */
static void ftrace_release_hash(unsigned long start, unsigned long end)
{
struct dyn_ftrace *rec;
struct hlist_node *t, *n;
struct hlist_head *head, temp_list;
unsigned long flags;
int i, cpu;
preempt_disable_notrace();
/* disable incase we call something that calls mcount */
cpu = raw_smp_processor_id();
per_cpu(ftrace_shutdown_disable_cpu, cpu)++;
ftrace_hash_lock(flags);
for (i = 0; i < FTRACE_HASHSIZE; i++) {
INIT_HLIST_HEAD(&temp_list);
head = &ftrace_hash[i];
/* all CPUS are stopped, we are safe to modify code */
hlist_for_each_entry_safe(rec, t, n, head, node) {
if (rec->flags & FTRACE_FL_FREE)
continue;
if ((rec->ip >= start) && (rec->ip < end))
ftrace_free_rec(rec);
}
}
ftrace_hash_unlock(flags);
per_cpu(ftrace_shutdown_disable_cpu, cpu)--;
preempt_enable_notrace();
}
static int ftraced(void *ignore)
{
unsigned long usecs;
while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE);
/* check once a second */
schedule_timeout(HZ);
if (unlikely(ftrace_disabled))
continue;
mutex_lock(&ftrace_sysctl_lock);
mutex_lock(&ftraced_lock);
if (!ftraced_suspend && !ftraced_stop &&
ftrace_update_code()) {
usecs = nsecs_to_usecs(ftrace_update_time);
if (ftrace_update_tot_cnt > 100000) {
ftrace_update_tot_cnt = 0;
pr_info("hm, dftrace overflow: %lu change%s"
" (%lu total) in %lu usec%s\n",
ftrace_update_cnt,
ftrace_update_cnt != 1 ? "s" : "",
ftrace_update_tot_cnt,
usecs, usecs != 1 ? "s" : "");
FTRACE_WARN_ON_ONCE(1);
}
}
mutex_unlock(&ftraced_lock);
mutex_unlock(&ftrace_sysctl_lock);
ftrace_shutdown_replenish();
}
__set_current_state(TASK_RUNNING);
return 0;
}
static int __init ftrace_dynamic_init(void)
{
struct task_struct *p;
unsigned long addr;
int ret;
addr = (unsigned long)ftrace_record_ip;
stop_machine(ftrace_dyn_arch_init, &addr, NULL);
/* ftrace_dyn_arch_init places the return code in addr */
if (addr) {
ret = (int)addr;
goto failed;
}
ret = ftrace_dyn_table_alloc(NR_TO_INIT);
if (ret)
goto failed;
p = kthread_run(ftraced, NULL, "ftraced");
if (IS_ERR(p)) {
ret = -1;
goto failed;
}
last_ftrace_enabled = ftrace_enabled = 1;
ftraced_task = p;
return 0;
failed:
ftrace_disabled = 1;
return ret;
}
core_initcall(ftrace_dynamic_init);
#endif /* CONFIG_FTRACE_MCOUNT_RECORD */
#else #else
# define ftrace_startup() do { } while (0) # define ftrace_startup() do { } while (0)
...@@ -1801,9 +1538,6 @@ void ftrace_kill(void) ...@@ -1801,9 +1538,6 @@ void ftrace_kill(void)
{ {
ftrace_disabled = 1; ftrace_disabled = 1;
ftrace_enabled = 0; ftrace_enabled = 0;
#ifdef CONFIG_DYNAMIC_FTRACE
ftraced_suspend = -1;
#endif
clear_ftrace_function(); clear_ftrace_function();
} }
......
...@@ -99,13 +99,6 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace, ...@@ -99,13 +99,6 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
/* passed in by parameter to fool gcc from optimizing */ /* passed in by parameter to fool gcc from optimizing */
func(); func();
/* update the records */
ret = ftrace_force_update();
if (ret) {
printk(KERN_CONT ".. ftraced failed .. ");
return ret;
}
/* /*
* Some archs *cough*PowerPC*cough* add charachters to the * Some archs *cough*PowerPC*cough* add charachters to the
* start of the function names. We simply put a '*' to * start of the function names. We simply put a '*' to
...@@ -183,13 +176,6 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr) ...@@ -183,13 +176,6 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
/* make sure msleep has been recorded */ /* make sure msleep has been recorded */
msleep(1); msleep(1);
/* force the recorded functions to be traced */
ret = ftrace_force_update();
if (ret) {
printk(KERN_CONT ".. ftraced failed .. ");
return ret;
}
/* start the tracing */ /* start the tracing */
ftrace_enabled = 1; ftrace_enabled = 1;
tracer_enabled = 1; tracer_enabled = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment