aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c95
1 files changed, 77 insertions, 18 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c2e2c2310374..66338c4f7f4b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -132,7 +132,7 @@ static char *default_bootup_tracer;
132 132
133static int __init set_cmdline_ftrace(char *str) 133static int __init set_cmdline_ftrace(char *str)
134{ 134{
135 strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE); 135 strlcpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
136 default_bootup_tracer = bootup_tracer_buf; 136 default_bootup_tracer = bootup_tracer_buf;
137 /* We are using ftrace early, expand it */ 137 /* We are using ftrace early, expand it */
138 ring_buffer_expanded = 1; 138 ring_buffer_expanded = 1;
@@ -162,7 +162,7 @@ static char *trace_boot_options __initdata;
162 162
163static int __init set_trace_boot_options(char *str) 163static int __init set_trace_boot_options(char *str)
164{ 164{
165 strncpy(trace_boot_options_buf, str, MAX_TRACER_SIZE); 165 strlcpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
166 trace_boot_options = trace_boot_options_buf; 166 trace_boot_options = trace_boot_options_buf;
167 return 0; 167 return 0;
168} 168}
@@ -704,7 +704,7 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
704void 704void
705update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) 705update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
706{ 706{
707 struct ring_buffer *buf = tr->buffer; 707 struct ring_buffer *buf;
708 708
709 if (trace_stop_count) 709 if (trace_stop_count)
710 return; 710 return;
@@ -719,6 +719,7 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
719 719
720 arch_spin_lock(&ftrace_max_lock); 720 arch_spin_lock(&ftrace_max_lock);
721 721
722 buf = tr->buffer;
722 tr->buffer = max_tr.buffer; 723 tr->buffer = max_tr.buffer;
723 max_tr.buffer = buf; 724 max_tr.buffer = buf;
724 725
@@ -743,8 +744,11 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
743 return; 744 return;
744 745
745 WARN_ON_ONCE(!irqs_disabled()); 746 WARN_ON_ONCE(!irqs_disabled());
746 if (WARN_ON_ONCE(!current_trace->allocated_snapshot)) 747 if (!current_trace->allocated_snapshot) {
748 /* Only the nop tracer should hit this when disabling */
749 WARN_ON_ONCE(current_trace != &nop_trace);
747 return; 750 return;
751 }
748 752
749 arch_spin_lock(&ftrace_max_lock); 753 arch_spin_lock(&ftrace_max_lock);
750 754
@@ -2400,6 +2404,27 @@ static void test_ftrace_alive(struct seq_file *m)
2400 seq_printf(m, "# MAY BE MISSING FUNCTION EVENTS\n"); 2404 seq_printf(m, "# MAY BE MISSING FUNCTION EVENTS\n");
2401} 2405}
2402 2406
2407#ifdef CONFIG_TRACER_MAX_TRACE
2408static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter)
2409{
2410 if (iter->trace->allocated_snapshot)
2411 seq_printf(m, "#\n# * Snapshot is allocated *\n#\n");
2412 else
2413 seq_printf(m, "#\n# * Snapshot is freed *\n#\n");
2414
2415 seq_printf(m, "# Snapshot commands:\n");
2416 seq_printf(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n");
2417 seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n");
2418 seq_printf(m, "# Takes a snapshot of the main buffer.\n");
2419 seq_printf(m, "# echo 2 > snapshot : Clears snapshot buffer (but does not allocate)\n");
2420 seq_printf(m, "# (Doesn't have to be '2' works with any number that\n");
2421 seq_printf(m, "# is not a '0' or '1')\n");
2422}
2423#else
2424/* Should never be called */
2425static inline void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter) { }
2426#endif
2427
2403static int s_show(struct seq_file *m, void *v) 2428static int s_show(struct seq_file *m, void *v)
2404{ 2429{
2405 struct trace_iterator *iter = v; 2430 struct trace_iterator *iter = v;
@@ -2411,7 +2436,9 @@ static int s_show(struct seq_file *m, void *v)
2411 seq_puts(m, "#\n"); 2436 seq_puts(m, "#\n");
2412 test_ftrace_alive(m); 2437 test_ftrace_alive(m);
2413 } 2438 }
2414 if (iter->trace && iter->trace->print_header) 2439 if (iter->snapshot && trace_empty(iter))
2440 print_snapshot_help(m, iter);
2441 else if (iter->trace && iter->trace->print_header)
2415 iter->trace->print_header(m); 2442 iter->trace->print_header(m);
2416 else 2443 else
2417 trace_default_header(m); 2444 trace_default_header(m);
@@ -2857,11 +2884,25 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
2857 return -EINVAL; 2884 return -EINVAL;
2858} 2885}
2859 2886
2860static void set_tracer_flags(unsigned int mask, int enabled) 2887/* Some tracers require overwrite to stay enabled */
2888int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
2889{
2890 if (tracer->enabled && (mask & TRACE_ITER_OVERWRITE) && !set)
2891 return -1;
2892
2893 return 0;
2894}
2895
2896int set_tracer_flag(unsigned int mask, int enabled)
2861{ 2897{
2862 /* do nothing if flag is already set */ 2898 /* do nothing if flag is already set */
2863 if (!!(trace_flags & mask) == !!enabled) 2899 if (!!(trace_flags & mask) == !!enabled)
2864 return; 2900 return 0;
2901
2902 /* Give the tracer a chance to approve the change */
2903 if (current_trace->flag_changed)
2904 if (current_trace->flag_changed(current_trace, mask, !!enabled))
2905 return -EINVAL;
2865 2906
2866 if (enabled) 2907 if (enabled)
2867 trace_flags |= mask; 2908 trace_flags |= mask;
@@ -2871,18 +2912,24 @@ static void set_tracer_flags(unsigned int mask, int enabled)
2871 if (mask == TRACE_ITER_RECORD_CMD) 2912 if (mask == TRACE_ITER_RECORD_CMD)
2872 trace_event_enable_cmd_record(enabled); 2913 trace_event_enable_cmd_record(enabled);
2873 2914
2874 if (mask == TRACE_ITER_OVERWRITE) 2915 if (mask == TRACE_ITER_OVERWRITE) {
2875 ring_buffer_change_overwrite(global_trace.buffer, enabled); 2916 ring_buffer_change_overwrite(global_trace.buffer, enabled);
2917#ifdef CONFIG_TRACER_MAX_TRACE
2918 ring_buffer_change_overwrite(max_tr.buffer, enabled);
2919#endif
2920 }
2876 2921
2877 if (mask == TRACE_ITER_PRINTK) 2922 if (mask == TRACE_ITER_PRINTK)
2878 trace_printk_start_stop_comm(enabled); 2923 trace_printk_start_stop_comm(enabled);
2924
2925 return 0;
2879} 2926}
2880 2927
2881static int trace_set_options(char *option) 2928static int trace_set_options(char *option)
2882{ 2929{
2883 char *cmp; 2930 char *cmp;
2884 int neg = 0; 2931 int neg = 0;
2885 int ret = 0; 2932 int ret = -ENODEV;
2886 int i; 2933 int i;
2887 2934
2888 cmp = strstrip(option); 2935 cmp = strstrip(option);
@@ -2892,19 +2939,20 @@ static int trace_set_options(char *option)
2892 cmp += 2; 2939 cmp += 2;
2893 } 2940 }
2894 2941
2942 mutex_lock(&trace_types_lock);
2943
2895 for (i = 0; trace_options[i]; i++) { 2944 for (i = 0; trace_options[i]; i++) {
2896 if (strcmp(cmp, trace_options[i]) == 0) { 2945 if (strcmp(cmp, trace_options[i]) == 0) {
2897 set_tracer_flags(1 << i, !neg); 2946 ret = set_tracer_flag(1 << i, !neg);
2898 break; 2947 break;
2899 } 2948 }
2900 } 2949 }
2901 2950
2902 /* If no option could be set, test the specific tracer options */ 2951 /* If no option could be set, test the specific tracer options */
2903 if (!trace_options[i]) { 2952 if (!trace_options[i])
2904 mutex_lock(&trace_types_lock);
2905 ret = set_tracer_option(current_trace, cmp, neg); 2953 ret = set_tracer_option(current_trace, cmp, neg);
2906 mutex_unlock(&trace_types_lock); 2954
2907 } 2955 mutex_unlock(&trace_types_lock);
2908 2956
2909 return ret; 2957 return ret;
2910} 2958}
@@ -2914,6 +2962,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2914 size_t cnt, loff_t *ppos) 2962 size_t cnt, loff_t *ppos)
2915{ 2963{
2916 char buf[64]; 2964 char buf[64];
2965 int ret;
2917 2966
2918 if (cnt >= sizeof(buf)) 2967 if (cnt >= sizeof(buf))
2919 return -EINVAL; 2968 return -EINVAL;
@@ -2923,7 +2972,9 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2923 2972
2924 buf[cnt] = 0; 2973 buf[cnt] = 0;
2925 2974
2926 trace_set_options(buf); 2975 ret = trace_set_options(buf);
2976 if (ret < 0)
2977 return ret;
2927 2978
2928 *ppos += cnt; 2979 *ppos += cnt;
2929 2980
@@ -3227,6 +3278,9 @@ static int tracing_set_tracer(const char *buf)
3227 goto out; 3278 goto out;
3228 3279
3229 trace_branch_disable(); 3280 trace_branch_disable();
3281
3282 current_trace->enabled = false;
3283
3230 if (current_trace->reset) 3284 if (current_trace->reset)
3231 current_trace->reset(tr); 3285 current_trace->reset(tr);
3232 3286
@@ -3271,6 +3325,7 @@ static int tracing_set_tracer(const char *buf)
3271 } 3325 }
3272 3326
3273 current_trace = t; 3327 current_trace = t;
3328 current_trace->enabled = true;
3274 trace_branch_enable(tr); 3329 trace_branch_enable(tr);
3275 out: 3330 out:
3276 mutex_unlock(&trace_types_lock); 3331 mutex_unlock(&trace_types_lock);
@@ -4144,8 +4199,6 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
4144 default: 4199 default:
4145 if (current_trace->allocated_snapshot) 4200 if (current_trace->allocated_snapshot)
4146 tracing_reset_online_cpus(&max_tr); 4201 tracing_reset_online_cpus(&max_tr);
4147 else
4148 ret = -EINVAL;
4149 break; 4202 break;
4150 } 4203 }
4151 4204
@@ -4759,7 +4812,13 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
4759 4812
4760 if (val != 0 && val != 1) 4813 if (val != 0 && val != 1)
4761 return -EINVAL; 4814 return -EINVAL;
4762 set_tracer_flags(1 << index, val); 4815
4816 mutex_lock(&trace_types_lock);
4817 ret = set_tracer_flag(1 << index, val);
4818 mutex_unlock(&trace_types_lock);
4819
4820 if (ret < 0)
4821 return ret;
4763 4822
4764 *ppos += cnt; 4823 *ppos += cnt;
4765 4824