aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2013-03-14 15:03:53 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-03-14 23:40:21 -0400
commit613f04a0f51e6e68ac6fe571ab79da3c0a5eb4da (patch)
tree2bc6da65edff6669f68010a22595861af26fe44d /kernel/trace/trace.c
parent80902822658aab18330569587cdb69ac1dfdcea8 (diff)
tracing: Prevent buffer overwrite disabled for latency tracers
The latency tracers require the buffers to be in overwrite mode, otherwise they get screwed up. Force the buffers to stay in overwrite mode when latency tracers are enabled. Added a flag_changed() method to the tracer structure to allow the tracers to see what flags are being changed, and also be able to prevent the change from happing. Cc: stable@vger.kernel.org Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 02debabe9ed4..4f1dade56981 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2881,11 +2881,25 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
2881 return -EINVAL; 2881 return -EINVAL;
2882} 2882}
2883 2883
2884static 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)
2885{ 2894{
2886 /* do nothing if flag is already set */ 2895 /* do nothing if flag is already set */
2887 if (!!(trace_flags & mask) == !!enabled) 2896 if (!!(trace_flags & mask) == !!enabled)
2888 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;
2889 2903
2890 if (enabled) 2904 if (enabled)
2891 trace_flags |= mask; 2905 trace_flags |= mask;
@@ -2904,13 +2918,15 @@ static void set_tracer_flags(unsigned int mask, int enabled)
2904 2918
2905 if (mask == TRACE_ITER_PRINTK) 2919 if (mask == TRACE_ITER_PRINTK)
2906 trace_printk_start_stop_comm(enabled); 2920 trace_printk_start_stop_comm(enabled);
2921
2922 return 0;
2907} 2923}
2908 2924
2909static int trace_set_options(char *option) 2925static int trace_set_options(char *option)
2910{ 2926{
2911 char *cmp; 2927 char *cmp;
2912 int neg = 0; 2928 int neg = 0;
2913 int ret = 0; 2929 int ret = -ENODEV;
2914 int i; 2930 int i;
2915 2931
2916 cmp = strstrip(option); 2932 cmp = strstrip(option);
@@ -2924,7 +2940,7 @@ static int trace_set_options(char *option)
2924 2940
2925 for (i = 0; trace_options[i]; i++) { 2941 for (i = 0; trace_options[i]; i++) {
2926 if (strcmp(cmp, trace_options[i]) == 0) { 2942 if (strcmp(cmp, trace_options[i]) == 0) {
2927 set_tracer_flags(1 << i, !neg); 2943 ret = set_tracer_flag(1 << i, !neg);
2928 break; 2944 break;
2929 } 2945 }
2930 } 2946 }
@@ -2943,6 +2959,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2943 size_t cnt, loff_t *ppos) 2959 size_t cnt, loff_t *ppos)
2944{ 2960{
2945 char buf[64]; 2961 char buf[64];
2962 int ret;
2946 2963
2947 if (cnt >= sizeof(buf)) 2964 if (cnt >= sizeof(buf))
2948 return -EINVAL; 2965 return -EINVAL;
@@ -2952,7 +2969,9 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2952 2969
2953 buf[cnt] = 0; 2970 buf[cnt] = 0;
2954 2971
2955 trace_set_options(buf); 2972 ret = trace_set_options(buf);
2973 if (ret < 0)
2974 return ret;
2956 2975
2957 *ppos += cnt; 2976 *ppos += cnt;
2958 2977
@@ -3256,6 +3275,9 @@ static int tracing_set_tracer(const char *buf)
3256 goto out; 3275 goto out;
3257 3276
3258 trace_branch_disable(); 3277 trace_branch_disable();
3278
3279 current_trace->enabled = false;
3280
3259 if (current_trace->reset) 3281 if (current_trace->reset)
3260 current_trace->reset(tr); 3282 current_trace->reset(tr);
3261 3283
@@ -3300,6 +3322,7 @@ static int tracing_set_tracer(const char *buf)
3300 } 3322 }
3301 3323
3302 current_trace = t; 3324 current_trace = t;
3325 current_trace->enabled = true;
3303 trace_branch_enable(tr); 3326 trace_branch_enable(tr);
3304 out: 3327 out:
3305 mutex_unlock(&trace_types_lock); 3328 mutex_unlock(&trace_types_lock);
@@ -4788,9 +4811,12 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
4788 return -EINVAL; 4811 return -EINVAL;
4789 4812
4790 mutex_lock(&trace_types_lock); 4813 mutex_lock(&trace_types_lock);
4791 set_tracer_flags(1 << index, val); 4814 ret = set_tracer_flag(1 << index, val);
4792 mutex_unlock(&trace_types_lock); 4815 mutex_unlock(&trace_types_lock);
4793 4816
4817 if (ret < 0)
4818 return ret;
4819
4794 *ppos += cnt; 4820 *ppos += cnt;
4795 4821
4796 return cnt; 4822 return cnt;