|
@@ -2460,32 +2460,44 @@ struct event_probe_data {
|
|
bool enable;
|
|
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
|
|
static void
|
|
event_enable_probe(unsigned long ip, unsigned long parent_ip,
|
|
event_enable_probe(unsigned long ip, unsigned long parent_ip,
|
|
struct ftrace_probe_ops *ops, void **_data)
|
|
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;
|
|
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
|
|
static void
|
|
event_enable_count_probe(unsigned long ip, unsigned long parent_ip,
|
|
event_enable_count_probe(unsigned long ip, unsigned long parent_ip,
|
|
struct ftrace_probe_ops *ops, void **_data)
|
|
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;
|
|
return;
|
|
|
|
|
|
|
|
+ data = *pdata;
|
|
|
|
+
|
|
if (!data->count)
|
|
if (!data->count)
|
|
return;
|
|
return;
|
|
|
|
|
|
@@ -2496,14 +2508,23 @@ event_enable_count_probe(unsigned long ip, unsigned long parent_ip,
|
|
if (data->count != -1)
|
|
if (data->count != -1)
|
|
(data->count)--;
|
|
(data->count)--;
|
|
|
|
|
|
- event_enable_probe(ip, parent_ip, ops, _data);
|
|
|
|
|
|
+ update_event_probe(data);
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
static int
|
|
event_enable_print(struct seq_file *m, unsigned long ip,
|
|
event_enable_print(struct seq_file *m, unsigned long ip,
|
|
struct ftrace_probe_ops *ops, void *_data)
|
|
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);
|
|
seq_printf(m, "%ps:", (void *)ip);
|
|
|
|
|
|
@@ -2524,10 +2545,17 @@ static int
|
|
event_enable_init(struct ftrace_probe_ops *ops, unsigned long ip,
|
|
event_enable_init(struct ftrace_probe_ops *ops, unsigned long ip,
|
|
void **_data)
|
|
void **_data)
|
|
{
|
|
{
|
|
|
|
+ struct ftrace_func_mapper *mapper = ops->private_data;
|
|
struct event_probe_data **pdata = (struct event_probe_data **)_data;
|
|
struct event_probe_data **pdata = (struct event_probe_data **)_data;
|
|
struct event_probe_data *data = *pdata;
|
|
struct event_probe_data *data = *pdata;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = ftrace_func_mapper_add_ip(mapper, ip, data);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
|
|
data->ref++;
|
|
data->ref++;
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2535,8 +2563,13 @@ static void
|
|
event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
|
|
event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
|
|
void **_data)
|
|
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))
|
|
if (WARN_ON_ONCE(data->ref <= 0))
|
|
return;
|
|
return;
|
|
@@ -2548,7 +2581,6 @@ event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
|
|
module_put(data->file->event_call->mod);
|
|
module_put(data->file->event_call->mod);
|
|
kfree(data);
|
|
kfree(data);
|
|
}
|
|
}
|
|
- *pdata = NULL;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static struct ftrace_probe_ops event_enable_probe_ops = {
|
|
static struct ftrace_probe_ops event_enable_probe_ops = {
|
|
@@ -2627,6 +2659,13 @@ event_enable_func(struct ftrace_hash *hash,
|
|
}
|
|
}
|
|
|
|
|
|
ret = -ENOMEM;
|
|
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);
|
|
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
|
if (!data)
|
|
if (!data)
|
|
goto out;
|
|
goto out;
|
|
@@ -2663,6 +2702,7 @@ event_enable_func(struct ftrace_hash *hash,
|
|
ret = __ftrace_event_enable_disable(file, 1, 1);
|
|
ret = __ftrace_event_enable_disable(file, 1, 1);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto out_put;
|
|
goto out_put;
|
|
|
|
+
|
|
ret = register_ftrace_function_probe(glob, ops, data);
|
|
ret = register_ftrace_function_probe(glob, ops, data);
|
|
/*
|
|
/*
|
|
* The above returns on success the # of functions enabled,
|
|
* The above returns on success the # of functions enabled,
|