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.c59
1 files changed, 47 insertions, 12 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 1f835a83cb2c..4f1dade56981 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -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
@@ -2880,11 +2881,25 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
2880 return -EINVAL; 2881 return -EINVAL;
2881} 2882}
2882 2883
2883static void set_tracer_flags(unsigned int mask, int enabled) 2884/* Some tracers require overwrite to stay enabled */
2885int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
2886{
2887 if (tracer->enabled && (mask & TRACE_ITER_OVERWRITE) && !set)
2888 return -1;
2889
2890 return 0;
2891}
2892
2893int set_tracer_flag(unsigned int mask, int enabled)
2884{ 2894{
2885 /* do nothing if flag is already set */ 2895 /* do nothing if flag is already set */
2886 if (!!(trace_flags & mask) == !!enabled) 2896 if (!!(trace_flags & mask) == !!enabled)
2887 return; 2897 return 0;
2898
2899 /* Give the tracer a chance to approve the change */
2900 if (current_trace->flag_changed)
2901 if (current_trace->flag_changed(current_trace, mask, !!enabled))
2902 return -EINVAL;
2888 2903
2889 if (enabled) 2904 if (enabled)
2890 trace_flags |= mask; 2905 trace_flags |= mask;
@@ -2894,18 +2909,24 @@ static void set_tracer_flags(unsigned int mask, int enabled)
2894 if (mask == TRACE_ITER_RECORD_CMD) 2909 if (mask == TRACE_ITER_RECORD_CMD)
2895 trace_event_enable_cmd_record(enabled); 2910 trace_event_enable_cmd_record(enabled);
2896 2911
2897 if (mask == TRACE_ITER_OVERWRITE) 2912 if (mask == TRACE_ITER_OVERWRITE) {
2898 ring_buffer_change_overwrite(global_trace.buffer, enabled); 2913 ring_buffer_change_overwrite(global_trace.buffer, enabled);
2914#ifdef CONFIG_TRACER_MAX_TRACE
2915 ring_buffer_change_overwrite(max_tr.buffer, enabled);
2916#endif
2917 }
2899 2918
2900 if (mask == TRACE_ITER_PRINTK) 2919 if (mask == TRACE_ITER_PRINTK)
2901 trace_printk_start_stop_comm(enabled); 2920 trace_printk_start_stop_comm(enabled);
2921
2922 return 0;
2902} 2923}
2903 2924
2904static int trace_set_options(char *option) 2925static int trace_set_options(char *option)
2905{ 2926{
2906 char *cmp; 2927 char *cmp;
2907 int neg = 0; 2928 int neg = 0;
2908 int ret = 0; 2929 int ret = -ENODEV;
2909 int i; 2930 int i;
2910 2931
2911 cmp = strstrip(option); 2932 cmp = strstrip(option);
@@ -2915,19 +2936,20 @@ static int trace_set_options(char *option)
2915 cmp += 2; 2936 cmp += 2;
2916 } 2937 }
2917 2938
2939 mutex_lock(&trace_types_lock);
2940
2918 for (i = 0; trace_options[i]; i++) { 2941 for (i = 0; trace_options[i]; i++) {
2919 if (strcmp(cmp, trace_options[i]) == 0) { 2942 if (strcmp(cmp, trace_options[i]) == 0) {
2920 set_tracer_flags(1 << i, !neg); 2943 ret = set_tracer_flag(1 << i, !neg);
2921 break; 2944 break;
2922 } 2945 }
2923 } 2946 }
2924 2947
2925 /* If no option could be set, test the specific tracer options */ 2948 /* If no option could be set, test the specific tracer options */
2926 if (!trace_options[i]) { 2949 if (!trace_options[i])
2927 mutex_lock(&trace_types_lock);
2928 ret = set_tracer_option(current_trace, cmp, neg); 2950 ret = set_tracer_option(current_trace, cmp, neg);
2929 mutex_unlock(&trace_types_lock); 2951
2930 } 2952 mutex_unlock(&trace_types_lock);
2931 2953
2932 return ret; 2954 return ret;
2933} 2955}
@@ -2937,6 +2959,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2937 size_t cnt, loff_t *ppos) 2959 size_t cnt, loff_t *ppos)
2938{ 2960{
2939 char buf[64]; 2961 char buf[64];
2962 int ret;
2940 2963
2941 if (cnt >= sizeof(buf)) 2964 if (cnt >= sizeof(buf))
2942 return -EINVAL; 2965 return -EINVAL;
@@ -2946,7 +2969,9 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2946 2969
2947 buf[cnt] = 0; 2970 buf[cnt] = 0;
2948 2971
2949 trace_set_options(buf); 2972 ret = trace_set_options(buf);
2973 if (ret < 0)
2974 return ret;
2950 2975
2951 *ppos += cnt; 2976 *ppos += cnt;
2952 2977
@@ -3250,6 +3275,9 @@ static int tracing_set_tracer(const char *buf)
3250 goto out; 3275 goto out;
3251 3276
3252 trace_branch_disable(); 3277 trace_branch_disable();
3278
3279 current_trace->enabled = false;
3280
3253 if (current_trace->reset) 3281 if (current_trace->reset)
3254 current_trace->reset(tr); 3282 current_trace->reset(tr);
3255 3283
@@ -3294,6 +3322,7 @@ static int tracing_set_tracer(const char *buf)
3294 } 3322 }
3295 3323
3296 current_trace = t; 3324 current_trace = t;
3325 current_trace->enabled = true;
3297 trace_branch_enable(tr); 3326 trace_branch_enable(tr);
3298 out: 3327 out:
3299 mutex_unlock(&trace_types_lock); 3328 mutex_unlock(&trace_types_lock);
@@ -4780,7 +4809,13 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
4780 4809
4781 if (val != 0 && val != 1) 4810 if (val != 0 && val != 1)
4782 return -EINVAL; 4811 return -EINVAL;
4783 set_tracer_flags(1 << index, val); 4812
4813 mutex_lock(&trace_types_lock);
4814 ret = set_tracer_flag(1 << index, val);
4815 mutex_unlock(&trace_types_lock);
4816
4817 if (ret < 0)
4818 return ret;
4784 4819
4785 *ppos += cnt; 4820 *ppos += cnt;
4786 4821