|
@@ -2881,11 +2881,25 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
-static void set_tracer_flags(unsigned int mask, int enabled)
|
|
|
+/* Some tracers require overwrite to stay enabled */
|
|
|
+int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
|
|
|
+{
|
|
|
+ if (tracer->enabled && (mask & TRACE_ITER_OVERWRITE) && !set)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int set_tracer_flag(unsigned int mask, int enabled)
|
|
|
{
|
|
|
/* do nothing if flag is already set */
|
|
|
if (!!(trace_flags & mask) == !!enabled)
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Give the tracer a chance to approve the change */
|
|
|
+ if (current_trace->flag_changed)
|
|
|
+ if (current_trace->flag_changed(current_trace, mask, !!enabled))
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
if (enabled)
|
|
|
trace_flags |= mask;
|
|
@@ -2895,18 +2909,24 @@ static void set_tracer_flags(unsigned int mask, int enabled)
|
|
|
if (mask == TRACE_ITER_RECORD_CMD)
|
|
|
trace_event_enable_cmd_record(enabled);
|
|
|
|
|
|
- if (mask == TRACE_ITER_OVERWRITE)
|
|
|
+ if (mask == TRACE_ITER_OVERWRITE) {
|
|
|
ring_buffer_change_overwrite(global_trace.buffer, enabled);
|
|
|
+#ifdef CONFIG_TRACER_MAX_TRACE
|
|
|
+ ring_buffer_change_overwrite(max_tr.buffer, enabled);
|
|
|
+#endif
|
|
|
+ }
|
|
|
|
|
|
if (mask == TRACE_ITER_PRINTK)
|
|
|
trace_printk_start_stop_comm(enabled);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int trace_set_options(char *option)
|
|
|
{
|
|
|
char *cmp;
|
|
|
int neg = 0;
|
|
|
- int ret = 0;
|
|
|
+ int ret = -ENODEV;
|
|
|
int i;
|
|
|
|
|
|
cmp = strstrip(option);
|
|
@@ -2916,19 +2936,20 @@ static int trace_set_options(char *option)
|
|
|
cmp += 2;
|
|
|
}
|
|
|
|
|
|
+ mutex_lock(&trace_types_lock);
|
|
|
+
|
|
|
for (i = 0; trace_options[i]; i++) {
|
|
|
if (strcmp(cmp, trace_options[i]) == 0) {
|
|
|
- set_tracer_flags(1 << i, !neg);
|
|
|
+ ret = set_tracer_flag(1 << i, !neg);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* If no option could be set, test the specific tracer options */
|
|
|
- if (!trace_options[i]) {
|
|
|
- mutex_lock(&trace_types_lock);
|
|
|
+ if (!trace_options[i])
|
|
|
ret = set_tracer_option(current_trace, cmp, neg);
|
|
|
- mutex_unlock(&trace_types_lock);
|
|
|
- }
|
|
|
+
|
|
|
+ mutex_unlock(&trace_types_lock);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -2938,6 +2959,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
|
|
|
size_t cnt, loff_t *ppos)
|
|
|
{
|
|
|
char buf[64];
|
|
|
+ int ret;
|
|
|
|
|
|
if (cnt >= sizeof(buf))
|
|
|
return -EINVAL;
|
|
@@ -2947,7 +2969,9 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
|
|
|
|
|
|
buf[cnt] = 0;
|
|
|
|
|
|
- trace_set_options(buf);
|
|
|
+ ret = trace_set_options(buf);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
|
|
|
*ppos += cnt;
|
|
|
|
|
@@ -3251,6 +3275,9 @@ static int tracing_set_tracer(const char *buf)
|
|
|
goto out;
|
|
|
|
|
|
trace_branch_disable();
|
|
|
+
|
|
|
+ current_trace->enabled = false;
|
|
|
+
|
|
|
if (current_trace->reset)
|
|
|
current_trace->reset(tr);
|
|
|
|
|
@@ -3295,6 +3322,7 @@ static int tracing_set_tracer(const char *buf)
|
|
|
}
|
|
|
|
|
|
current_trace = t;
|
|
|
+ current_trace->enabled = true;
|
|
|
trace_branch_enable(tr);
|
|
|
out:
|
|
|
mutex_unlock(&trace_types_lock);
|
|
@@ -4781,7 +4809,13 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
|
|
|
|
|
|
if (val != 0 && val != 1)
|
|
|
return -EINVAL;
|
|
|
- set_tracer_flags(1 << index, val);
|
|
|
+
|
|
|
+ mutex_lock(&trace_types_lock);
|
|
|
+ ret = set_tracer_flag(1 << index, val);
|
|
|
+ mutex_unlock(&trace_types_lock);
|
|
|
+
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
|
|
|
*ppos += cnt;
|
|
|
|