summaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_events.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r--kernel/trace/trace_events.c70
1 files changed, 55 insertions, 15 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 9dbac1881b03..ee308312fe87 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -2460,32 +2460,44 @@ struct event_probe_data {
bool enable;
};
+static void update_event_probe(struct event_probe_data *data)
+{
+ if (data->enable)
+ clear_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &data->file->flags);
+ else
+ set_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &data->file->flags);
+}
+
static void
event_enable_probe(unsigned long ip, unsigned long parent_ip,
struct ftrace_probe_ops *ops, void **_data)
{
- struct event_probe_data **pdata = (struct event_probe_data **)_data;
- struct event_probe_data *data = *pdata;
+ struct ftrace_func_mapper *mapper = ops->private_data;
+ struct event_probe_data *data;
+ void **pdata;
- if (!data)
+ pdata = ftrace_func_mapper_find_ip(mapper, ip);
+ if (!pdata || !*pdata)
return;
- if (data->enable)
- clear_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &data->file->flags);
- else
- set_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &data->file->flags);
+ data = *pdata;
+ update_event_probe(data);
}
static void
event_enable_count_probe(unsigned long ip, unsigned long parent_ip,
struct ftrace_probe_ops *ops, void **_data)
{
- struct event_probe_data **pdata = (struct event_probe_data **)_data;
- struct event_probe_data *data = *pdata;
+ struct ftrace_func_mapper *mapper = ops->private_data;
+ struct event_probe_data *data;
+ void **pdata;
- if (!data)
+ pdata = ftrace_func_mapper_find_ip(mapper, ip);
+ if (!pdata || !*pdata)
return;
+ data = *pdata;
+
if (!data->count)
return;
@@ -2496,14 +2508,23 @@ event_enable_count_probe(unsigned long ip, unsigned long parent_ip,
if (data->count != -1)
(data->count)--;
- event_enable_probe(ip, parent_ip, ops, _data);
+ update_event_probe(data);
}
static int
event_enable_print(struct seq_file *m, unsigned long ip,
struct ftrace_probe_ops *ops, void *_data)
{
- struct event_probe_data *data = _data;
+ struct ftrace_func_mapper *mapper = ops->private_data;
+ struct event_probe_data *data;
+ void **pdata;
+
+ pdata = ftrace_func_mapper_find_ip(mapper, ip);
+
+ if (WARN_ON_ONCE(!pdata || !*pdata))
+ return 0;
+
+ data = *pdata;
seq_printf(m, "%ps:", (void *)ip);
@@ -2524,10 +2545,17 @@ static int
event_enable_init(struct ftrace_probe_ops *ops, unsigned long ip,
void **_data)
{
+ struct ftrace_func_mapper *mapper = ops->private_data;
struct event_probe_data **pdata = (struct event_probe_data **)_data;
struct event_probe_data *data = *pdata;
+ int ret;
+
+ ret = ftrace_func_mapper_add_ip(mapper, ip, data);
+ if (ret < 0)
+ return ret;
data->ref++;
+
return 0;
}
@@ -2535,8 +2563,13 @@ static void
event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
void **_data)
{
- struct event_probe_data **pdata = (struct event_probe_data **)_data;
- struct event_probe_data *data = *pdata;
+ struct ftrace_func_mapper *mapper = ops->private_data;
+ struct event_probe_data *data;
+
+ data = ftrace_func_mapper_remove_ip(mapper, ip);
+
+ if (WARN_ON_ONCE(!data))
+ return;
if (WARN_ON_ONCE(data->ref <= 0))
return;
@@ -2548,7 +2581,6 @@ event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
module_put(data->file->event_call->mod);
kfree(data);
}
- *pdata = NULL;
}
static struct ftrace_probe_ops event_enable_probe_ops = {
@@ -2627,6 +2659,13 @@ event_enable_func(struct ftrace_hash *hash,
}
ret = -ENOMEM;
+
+ if (!ops->private_data) {
+ ops->private_data = allocate_ftrace_func_mapper();
+ if (!ops->private_data)
+ goto out;
+ }
+
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
goto out;
@@ -2663,6 +2702,7 @@ event_enable_func(struct ftrace_hash *hash,
ret = __ftrace_event_enable_disable(file, 1, 1);
if (ret < 0)
goto out_put;
+
ret = register_ftrace_function_probe(glob, ops, data);
/*
* The above returns on success the # of functions enabled,
OpenPOWER on IntegriCloud