diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2013-03-14 15:03:53 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2013-03-14 23:40:21 -0400 |
commit | 613f04a0f51e6e68ac6fe571ab79da3c0a5eb4da (patch) | |
tree | 2bc6da65edff6669f68010a22595861af26fe44d /kernel/trace/trace.c | |
parent | 80902822658aab18330569587cdb69ac1dfdcea8 (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.c | 38 |
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 | ||
2884 | static void set_tracer_flags(unsigned int mask, int enabled) | 2884 | /* Some tracers require overwrite to stay enabled */ |
2885 | int 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 | |||
2893 | int 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 | ||
2909 | static int trace_set_options(char *option) | 2925 | static 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; |