aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ftrace.h4
-rw-r--r--kernel/trace/ftrace.c51
2 files changed, 55 insertions, 0 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index a42390c1d6e1..2c1670c65236 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -54,6 +54,8 @@ struct dyn_ftrace {
54 unsigned long flags; 54 unsigned long flags;
55}; 55};
56 56
57int ftrace_force_update(void);
58
57/* defined in arch */ 59/* defined in arch */
58extern int ftrace_ip_converted(unsigned long ip); 60extern int ftrace_ip_converted(unsigned long ip);
59extern unsigned char *ftrace_nop_replace(void); 61extern unsigned char *ftrace_nop_replace(void);
@@ -66,6 +68,8 @@ extern int ftrace_update_ftrace_func(ftrace_func_t func);
66extern void ftrace_caller(void); 68extern void ftrace_caller(void);
67extern void ftrace_call(void); 69extern void ftrace_call(void);
68extern void mcount_call(void); 70extern void mcount_call(void);
71#else
72# define ftrace_force_update() do { } while (0)
69#endif 73#endif
70 74
71static inline void tracer_disable(void) 75static inline void tracer_disable(void)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 97d5cb7b7e75..4facf5ceeb86 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -146,6 +146,10 @@ static int notrace __unregister_ftrace_function(struct ftrace_ops *ops)
146 146
147#ifdef CONFIG_DYNAMIC_FTRACE 147#ifdef CONFIG_DYNAMIC_FTRACE
148 148
149static struct task_struct *ftraced_task;
150static DECLARE_WAIT_QUEUE_HEAD(ftraced_waiters);
151static unsigned long ftraced_iteration_counter;
152
149enum { 153enum {
150 FTRACE_ENABLE_CALLS = (1 << 0), 154 FTRACE_ENABLE_CALLS = (1 << 0),
151 FTRACE_DISABLE_CALLS = (1 << 1), 155 FTRACE_DISABLE_CALLS = (1 << 1),
@@ -590,9 +594,12 @@ static int notrace ftraced(void *ignore)
590 ftraced_trigger = 0; 594 ftraced_trigger = 0;
591 ftrace_record_suspend--; 595 ftrace_record_suspend--;
592 } 596 }
597 ftraced_iteration_counter++;
593 mutex_unlock(&ftraced_lock); 598 mutex_unlock(&ftraced_lock);
594 mutex_unlock(&ftrace_sysctl_lock); 599 mutex_unlock(&ftrace_sysctl_lock);
595 600
601 wake_up_interruptible(&ftraced_waiters);
602
596 ftrace_shutdown_replenish(); 603 ftrace_shutdown_replenish();
597 604
598 set_current_state(TASK_INTERRUPTIBLE); 605 set_current_state(TASK_INTERRUPTIBLE);
@@ -1050,6 +1057,49 @@ static struct file_operations ftrace_filter_fops = {
1050 .release = ftrace_filter_release, 1057 .release = ftrace_filter_release,
1051}; 1058};
1052 1059
1060/**
1061 * ftrace_force_update - force an update to all recording ftrace functions
1062 *
1063 * The ftrace dynamic update daemon only wakes up once a second.
1064 * There may be cases where an update needs to be done immediately
1065 * for tests or internal kernel tracing to begin. This function
1066 * wakes the daemon to do an update and will not return until the
1067 * update is complete.
1068 */
1069int ftrace_force_update(void)
1070{
1071 unsigned long last_counter;
1072 DECLARE_WAITQUEUE(wait, current);
1073 int ret = 0;
1074
1075 if (!ftraced_task)
1076 return -ENODEV;
1077
1078 mutex_lock(&ftraced_lock);
1079 last_counter = ftraced_iteration_counter;
1080
1081 set_current_state(TASK_INTERRUPTIBLE);
1082 add_wait_queue(&ftraced_waiters, &wait);
1083
1084 do {
1085 mutex_unlock(&ftraced_lock);
1086 wake_up_process(ftraced_task);
1087 schedule();
1088 mutex_lock(&ftraced_lock);
1089 if (signal_pending(current)) {
1090 ret = -EINTR;
1091 break;
1092 }
1093 set_current_state(TASK_INTERRUPTIBLE);
1094 } while (last_counter == ftraced_iteration_counter);
1095
1096 mutex_unlock(&ftraced_lock);
1097 remove_wait_queue(&ftraced_waiters, &wait);
1098 set_current_state(TASK_RUNNING);
1099
1100 return ret;
1101}
1102
1053static __init int ftrace_init_debugfs(void) 1103static __init int ftrace_init_debugfs(void)
1054{ 1104{
1055 struct dentry *d_tracer; 1105 struct dentry *d_tracer;
@@ -1095,6 +1145,7 @@ static int __init notrace ftrace_dynamic_init(void)
1095 return -1; 1145 return -1;
1096 1146
1097 last_ftrace_enabled = ftrace_enabled = 1; 1147 last_ftrace_enabled = ftrace_enabled = 1;
1148 ftraced_task = p;
1098 1149
1099 return 0; 1150 return 0;
1100} 1151}