Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 100462
b: refs/heads/master
c: 4eebcc8
h: refs/heads/master
v: v3
  • Loading branch information
Steven Rostedt authored and Thomas Gleixner committed May 23, 2008
1 parent 8edf250 commit 6baff18
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 37ad508419f0fdfda7b378756eb1f35cfd26d96d
refs/heads/master: 4eebcc81a33fbc45e28542b50197ed7b3c486d90
3 changes: 3 additions & 0 deletions trunk/include/linux/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ struct dyn_ftrace {
int ftrace_force_update(void);
void ftrace_set_filter(unsigned char *buf, int len, int reset);

/* totally disable ftrace - can not re-enable after this */
void ftrace_kill(void);

/* defined in arch */
extern int ftrace_ip_converted(unsigned long ip);
extern unsigned char *ftrace_nop_replace(void);
Expand Down
112 changes: 103 additions & 9 deletions trunk/kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,16 @@

#include "trace.h"

int ftrace_enabled;
/* ftrace_enabled is a method to turn ftrace on or off */
int ftrace_enabled __read_mostly;
static int last_ftrace_enabled;

/*
* ftrace_disabled is set when an anomaly is discovered.
* ftrace_disabled is much stronger than ftrace_enabled.
*/
static int ftrace_disabled __read_mostly;

static DEFINE_SPINLOCK(ftrace_lock);
static DEFINE_MUTEX(ftrace_sysctl_lock);

Expand Down Expand Up @@ -230,10 +237,11 @@ static notrace struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
if (ftrace_free_records) {
rec = ftrace_free_records;

/* todo, disable tracing altogether on this warning */
if (unlikely(!(rec->flags & FTRACE_FL_FREE))) {
WARN_ON_ONCE(1);
ftrace_free_records = NULL;
ftrace_disabled = 1;
ftrace_enabled = 0;
return NULL;
}

Expand All @@ -260,7 +268,7 @@ ftrace_record_ip(unsigned long ip)
int resched;
int atomic;

if (!ftrace_enabled)
if (!ftrace_enabled || ftrace_disabled)
return;

resched = need_resched();
Expand Down Expand Up @@ -485,6 +493,9 @@ static void notrace ftrace_startup(void)
{
int command = 0;

if (unlikely(ftrace_disabled))
return;

mutex_lock(&ftraced_lock);
ftraced_suspend++;
if (ftraced_suspend == 1)
Expand All @@ -507,6 +518,9 @@ static void notrace ftrace_shutdown(void)
{
int command = 0;

if (unlikely(ftrace_disabled))
return;

mutex_lock(&ftraced_lock);
ftraced_suspend--;
if (!ftraced_suspend)
Expand All @@ -529,6 +543,9 @@ static void notrace ftrace_startup_sysctl(void)
{
int command = FTRACE_ENABLE_MCOUNT;

if (unlikely(ftrace_disabled))
return;

mutex_lock(&ftraced_lock);
/* Force update next time */
saved_ftrace_func = NULL;
Expand All @@ -544,6 +561,9 @@ static void notrace ftrace_shutdown_sysctl(void)
{
int command = FTRACE_DISABLE_MCOUNT;

if (unlikely(ftrace_disabled))
return;

mutex_lock(&ftraced_lock);
/* ftraced_suspend is true if ftrace is running */
if (ftraced_suspend)
Expand Down Expand Up @@ -600,6 +620,9 @@ static int notrace __ftrace_update_code(void *ignore)

static void notrace ftrace_update_code(void)
{
if (unlikely(ftrace_disabled))
return;

stop_machine_run(__ftrace_update_code, NULL, NR_CPUS);
}

Expand All @@ -614,6 +637,9 @@ static int notrace ftraced(void *ignore)
/* check once a second */
schedule_timeout(HZ);

if (unlikely(ftrace_disabled))
continue;

mutex_lock(&ftrace_sysctl_lock);
mutex_lock(&ftraced_lock);
if (ftrace_enabled && ftraced_trigger && !ftraced_suspend) {
Expand All @@ -628,6 +654,7 @@ static int notrace ftraced(void *ignore)
ftrace_update_cnt != 1 ? "s" : "",
ftrace_update_tot_cnt,
usecs, usecs != 1 ? "s" : "");
ftrace_disabled = 1;
WARN_ON_ONCE(1);
}
ftraced_trigger = 0;
Expand Down Expand Up @@ -785,6 +812,9 @@ ftrace_avail_open(struct inode *inode, struct file *file)
struct ftrace_iterator *iter;
int ret;

if (unlikely(ftrace_disabled))
return -ENODEV;

iter = kzalloc(sizeof(*iter), GFP_KERNEL);
if (!iter)
return -ENOMEM;
Expand Down Expand Up @@ -843,6 +873,9 @@ ftrace_filter_open(struct inode *inode, struct file *file)
struct ftrace_iterator *iter;
int ret = 0;

if (unlikely(ftrace_disabled))
return -ENODEV;

iter = kzalloc(sizeof(*iter), GFP_KERNEL);
if (!iter)
return -ENOMEM;
Expand Down Expand Up @@ -1063,6 +1096,9 @@ ftrace_filter_write(struct file *file, const char __user *ubuf,
*/
notrace void ftrace_set_filter(unsigned char *buf, int len, int reset)
{
if (unlikely(ftrace_disabled))
return;

mutex_lock(&ftrace_filter_lock);
if (reset)
ftrace_filter_reset();
Expand Down Expand Up @@ -1133,7 +1169,7 @@ int ftrace_force_update(void)
DECLARE_WAITQUEUE(wait, current);
int ret = 0;

if (!ftraced_task)
if (unlikely(ftrace_disabled))
return -ENODEV;

mutex_lock(&ftraced_lock);
Expand All @@ -1142,6 +1178,11 @@ int ftrace_force_update(void)
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&ftraced_waiters, &wait);

if (unlikely(!ftraced_task)) {
ret = -ENODEV;
goto out;
}

do {
mutex_unlock(&ftraced_lock);
wake_up_process(ftraced_task);
Expand All @@ -1154,13 +1195,30 @@ int ftrace_force_update(void)
set_current_state(TASK_INTERRUPTIBLE);
} while (last_counter == ftraced_iteration_counter);

out:
mutex_unlock(&ftraced_lock);
remove_wait_queue(&ftraced_waiters, &wait);
set_current_state(TASK_RUNNING);

return ret;
}

static void ftrace_force_shutdown(void)
{
struct task_struct *task;
int command = FTRACE_DISABLE_CALLS | FTRACE_UPDATE_TRACE_FUNC;

mutex_lock(&ftraced_lock);
task = ftraced_task;
ftraced_task = NULL;
ftraced_suspend = -1;
ftrace_run_update_code(command);
mutex_unlock(&ftraced_lock);

if (task)
kthread_stop(task);
}

static __init int ftrace_init_debugfs(void)
{
struct dentry *d_tracer;
Expand Down Expand Up @@ -1194,21 +1252,29 @@ static int __init notrace ftrace_dynamic_init(void)
stop_machine_run(ftrace_dyn_arch_init, &addr, NR_CPUS);

/* ftrace_dyn_arch_init places the return code in addr */
if (addr)
return addr;
if (addr) {
ret = (int)addr;
goto failed;
}

ret = ftrace_dyn_table_alloc();
if (ret)
return ret;
goto failed;

p = kthread_run(ftraced, NULL, "ftraced");
if (IS_ERR(p))
return -1;
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);
Expand All @@ -1217,8 +1283,30 @@ core_initcall(ftrace_dynamic_init);
# define ftrace_shutdown() do { } while (0)
# define ftrace_startup_sysctl() do { } while (0)
# define ftrace_shutdown_sysctl() do { } while (0)
# define ftrace_force_shutdown() do { } while (0)
#endif /* CONFIG_DYNAMIC_FTRACE */

/**
* ftrace_kill - totally shutdown ftrace
*
* This is a safety measure. If something was detected that seems
* wrong, calling this function will keep ftrace from doing
* any more modifications, and updates.
* used when something went wrong.
*/
void ftrace_kill(void)
{
mutex_lock(&ftrace_sysctl_lock);
ftrace_disabled = 1;
ftrace_enabled = 0;

clear_ftrace_function();
mutex_unlock(&ftrace_sysctl_lock);

/* Try to totally disable ftrace */
ftrace_force_shutdown();
}

/**
* register_ftrace_function - register a function for profiling
* @ops - ops structure that holds the function for profiling.
Expand All @@ -1234,6 +1322,9 @@ int register_ftrace_function(struct ftrace_ops *ops)
{
int ret;

if (unlikely(ftrace_disabled))
return -1;

mutex_lock(&ftrace_sysctl_lock);
ret = __register_ftrace_function(ops);
ftrace_startup();
Expand Down Expand Up @@ -1267,6 +1358,9 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
{
int ret;

if (unlikely(ftrace_disabled))
return -ENODEV;

mutex_lock(&ftrace_sysctl_lock);

ret = proc_dointvec(table, write, file, buffer, lenp, ppos);
Expand Down
4 changes: 4 additions & 0 deletions trunk/kernel/trace/trace_selftest.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
ftrace_enabled = save_ftrace_enabled;
tracer_enabled = save_tracer_enabled;

/* kill ftrace totally if we failed */
if (ret)
ftrace_kill();

return ret;
}
#endif /* CONFIG_FTRACE */
Expand Down

0 comments on commit 6baff18

Please sign in to comment.