|
@@ -683,6 +683,34 @@ static struct trace_probe *find_trace_probe(const char *event,
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */
|
|
|
|
+static int enable_trace_probe(struct trace_probe *tp, int flag)
|
|
|
|
+{
|
|
|
|
+ int ret = 0;
|
|
|
|
+
|
|
|
|
+ tp->flags |= flag;
|
|
|
|
+ if (tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE)) {
|
|
|
|
+ if (trace_probe_is_return(tp))
|
|
|
|
+ ret = enable_kretprobe(&tp->rp);
|
|
|
|
+ else
|
|
|
|
+ ret = enable_kprobe(&tp->rp.kp);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */
|
|
|
|
+static void disable_trace_probe(struct trace_probe *tp, int flag)
|
|
|
|
+{
|
|
|
|
+ tp->flags &= ~flag;
|
|
|
|
+ if (!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE))) {
|
|
|
|
+ if (trace_probe_is_return(tp))
|
|
|
|
+ disable_kretprobe(&tp->rp);
|
|
|
|
+ else
|
|
|
|
+ disable_kprobe(&tp->rp.kp);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/* Unregister a trace_probe and probe_event: call with locking probe_lock */
|
|
/* Unregister a trace_probe and probe_event: call with locking probe_lock */
|
|
static void unregister_trace_probe(struct trace_probe *tp)
|
|
static void unregister_trace_probe(struct trace_probe *tp)
|
|
{
|
|
{
|
|
@@ -1514,30 +1542,6 @@ partial:
|
|
return TRACE_TYPE_PARTIAL_LINE;
|
|
return TRACE_TYPE_PARTIAL_LINE;
|
|
}
|
|
}
|
|
|
|
|
|
-static int probe_event_enable(struct ftrace_event_call *call)
|
|
|
|
-{
|
|
|
|
- struct trace_probe *tp = (struct trace_probe *)call->data;
|
|
|
|
-
|
|
|
|
- tp->flags |= TP_FLAG_TRACE;
|
|
|
|
- if (trace_probe_is_return(tp))
|
|
|
|
- return enable_kretprobe(&tp->rp);
|
|
|
|
- else
|
|
|
|
- return enable_kprobe(&tp->rp.kp);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void probe_event_disable(struct ftrace_event_call *call)
|
|
|
|
-{
|
|
|
|
- struct trace_probe *tp = (struct trace_probe *)call->data;
|
|
|
|
-
|
|
|
|
- tp->flags &= ~TP_FLAG_TRACE;
|
|
|
|
- if (!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE))) {
|
|
|
|
- if (trace_probe_is_return(tp))
|
|
|
|
- disable_kretprobe(&tp->rp);
|
|
|
|
- else
|
|
|
|
- disable_kprobe(&tp->rp.kp);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
#undef DEFINE_FIELD
|
|
#undef DEFINE_FIELD
|
|
#define DEFINE_FIELD(type, item, name, is_signed) \
|
|
#define DEFINE_FIELD(type, item, name, is_signed) \
|
|
do { \
|
|
do { \
|
|
@@ -1716,49 +1720,25 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,
|
|
head = this_cpu_ptr(call->perf_events);
|
|
head = this_cpu_ptr(call->perf_events);
|
|
perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head);
|
|
perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head);
|
|
}
|
|
}
|
|
-
|
|
|
|
-static int probe_perf_enable(struct ftrace_event_call *call)
|
|
|
|
-{
|
|
|
|
- struct trace_probe *tp = (struct trace_probe *)call->data;
|
|
|
|
-
|
|
|
|
- tp->flags |= TP_FLAG_PROFILE;
|
|
|
|
-
|
|
|
|
- if (trace_probe_is_return(tp))
|
|
|
|
- return enable_kretprobe(&tp->rp);
|
|
|
|
- else
|
|
|
|
- return enable_kprobe(&tp->rp.kp);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void probe_perf_disable(struct ftrace_event_call *call)
|
|
|
|
-{
|
|
|
|
- struct trace_probe *tp = (struct trace_probe *)call->data;
|
|
|
|
-
|
|
|
|
- tp->flags &= ~TP_FLAG_PROFILE;
|
|
|
|
-
|
|
|
|
- if (!(tp->flags & TP_FLAG_TRACE)) {
|
|
|
|
- if (trace_probe_is_return(tp))
|
|
|
|
- disable_kretprobe(&tp->rp);
|
|
|
|
- else
|
|
|
|
- disable_kprobe(&tp->rp.kp);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
#endif /* CONFIG_PERF_EVENTS */
|
|
#endif /* CONFIG_PERF_EVENTS */
|
|
|
|
|
|
static __kprobes
|
|
static __kprobes
|
|
int kprobe_register(struct ftrace_event_call *event, enum trace_reg type)
|
|
int kprobe_register(struct ftrace_event_call *event, enum trace_reg type)
|
|
{
|
|
{
|
|
|
|
+ struct trace_probe *tp = (struct trace_probe *)event->data;
|
|
|
|
+
|
|
switch (type) {
|
|
switch (type) {
|
|
case TRACE_REG_REGISTER:
|
|
case TRACE_REG_REGISTER:
|
|
- return probe_event_enable(event);
|
|
|
|
|
|
+ return enable_trace_probe(tp, TP_FLAG_TRACE);
|
|
case TRACE_REG_UNREGISTER:
|
|
case TRACE_REG_UNREGISTER:
|
|
- probe_event_disable(event);
|
|
|
|
|
|
+ disable_trace_probe(tp, TP_FLAG_TRACE);
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
#ifdef CONFIG_PERF_EVENTS
|
|
#ifdef CONFIG_PERF_EVENTS
|
|
case TRACE_REG_PERF_REGISTER:
|
|
case TRACE_REG_PERF_REGISTER:
|
|
- return probe_perf_enable(event);
|
|
|
|
|
|
+ return enable_trace_probe(tp, TP_FLAG_PROFILE);
|
|
case TRACE_REG_PERF_UNREGISTER:
|
|
case TRACE_REG_PERF_UNREGISTER:
|
|
- probe_perf_disable(event);
|
|
|
|
|
|
+ disable_trace_probe(tp, TP_FLAG_PROFILE);
|
|
return 0;
|
|
return 0;
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
@@ -1905,7 +1885,7 @@ static __init int kprobe_trace_self_tests_init(void)
|
|
pr_warning("error on getting new probe.\n");
|
|
pr_warning("error on getting new probe.\n");
|
|
warn++;
|
|
warn++;
|
|
} else
|
|
} else
|
|
- probe_event_enable(&tp->call);
|
|
|
|
|
|
+ enable_trace_probe(tp, TP_FLAG_TRACE);
|
|
}
|
|
}
|
|
|
|
|
|
ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target "
|
|
ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target "
|
|
@@ -1920,7 +1900,7 @@ static __init int kprobe_trace_self_tests_init(void)
|
|
pr_warning("error on getting new probe.\n");
|
|
pr_warning("error on getting new probe.\n");
|
|
warn++;
|
|
warn++;
|
|
} else
|
|
} else
|
|
- probe_event_enable(&tp->call);
|
|
|
|
|
|
+ enable_trace_probe(tp, TP_FLAG_TRACE);
|
|
}
|
|
}
|
|
|
|
|
|
if (warn)
|
|
if (warn)
|