* [PATCH 1/5] uprobes: Ensure inode != NULL in create_trace_uprobe()
2013-01-28 18:24 [PATCH 0/5] uprobes: kill uprobe_trace_consumer and other cleanups Oleg Nesterov
@ 2013-01-28 18:24 ` Oleg Nesterov
2013-01-28 18:24 ` [PATCH 2/5] uprobes: Introduce trace_uprobe->enabled Oleg Nesterov
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Oleg Nesterov @ 2013-01-28 18:24 UTC (permalink / raw)
To: Ingo Molnar, Srikar Dronamraju, Steven Rostedt
Cc: Anton Arapov, Frank Eigler, Josh Stone, Masami Hiramatsu,
Suzuki K. Poulose, linux-kernel
probe_event_enable/disable() check tu->inode != NULL at the start.
This is ugly, if igrab() can fail create_trace_uprobe() should not
succeed and "postpone" the failure.
Note: alloc_uprobe() should probably check igrab() != NULL as well.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/trace/trace_uprobe.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 0c05288..f49ccf9 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -349,6 +349,8 @@ static int create_trace_uprobe(int argc, char **argv)
inode = igrab(path.dentry->d_inode);
path_put(&path);
+ if (!inode)
+ goto fail_address_parse;
ret = kstrtoul(arg, 0, &offset);
if (ret)
@@ -645,7 +647,7 @@ static int probe_event_enable(struct trace_uprobe *tu, int flag)
struct uprobe_trace_consumer *utc;
int ret = 0;
- if (!tu->inode || tu->consumer)
+ if (tu->consumer)
return -EINTR;
utc = kzalloc(sizeof(struct uprobe_trace_consumer), GFP_KERNEL);
@@ -670,7 +672,7 @@ static int probe_event_enable(struct trace_uprobe *tu, int flag)
static void probe_event_disable(struct trace_uprobe *tu, int flag)
{
- if (!tu->inode || !tu->consumer)
+ if (!tu->consumer)
return;
uprobe_unregister(tu->inode, tu->offset, &tu->consumer->cons);
--
1.5.5.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 2/5] uprobes: Introduce trace_uprobe->enabled
2013-01-28 18:24 [PATCH 0/5] uprobes: kill uprobe_trace_consumer and other cleanups Oleg Nesterov
2013-01-28 18:24 ` [PATCH 1/5] uprobes: Ensure inode != NULL in create_trace_uprobe() Oleg Nesterov
@ 2013-01-28 18:24 ` Oleg Nesterov
2013-01-28 18:24 ` [PATCH 3/5] uprobes: Kill uprobe_trace_consumer, embed uprobe_consumer into trace_uprobe Oleg Nesterov
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Oleg Nesterov @ 2013-01-28 18:24 UTC (permalink / raw)
To: Ingo Molnar, Srikar Dronamraju, Steven Rostedt
Cc: Anton Arapov, Frank Eigler, Josh Stone, Masami Hiramatsu,
Suzuki K. Poulose, linux-kernel
probe_event_enable/disable() check tu->consumer != NULL to avoid
the wrong uprobe_register/unregister().
We are going to kill uprobe_trace_consumer, so we add the explicit
trace_uprobe->enabled member which can be used instead.
This is the temporary change to simplify the next patch, the new
member will go away after cleanups.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/trace/trace_uprobe.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index f49ccf9..c430d01 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -46,6 +46,7 @@ struct trace_uprobe {
struct list_head list;
struct ftrace_event_class class;
struct ftrace_event_call call;
+ bool enabled;
struct uprobe_trace_consumer *consumer;
struct trace_uprobe_filter filter;
struct inode *inode;
@@ -647,7 +648,7 @@ static int probe_event_enable(struct trace_uprobe *tu, int flag)
struct uprobe_trace_consumer *utc;
int ret = 0;
- if (tu->consumer)
+ if (tu->enabled)
return -EINTR;
utc = kzalloc(sizeof(struct uprobe_trace_consumer), GFP_KERNEL);
@@ -665,6 +666,8 @@ static int probe_event_enable(struct trace_uprobe *tu, int flag)
tu->consumer = NULL;
tu->flags &= ~flag;
kfree(utc);
+ } else {
+ tu->enabled = true;
}
return ret;
@@ -672,11 +675,12 @@ static int probe_event_enable(struct trace_uprobe *tu, int flag)
static void probe_event_disable(struct trace_uprobe *tu, int flag)
{
- if (!tu->consumer)
+ if (!tu->enabled)
return;
uprobe_unregister(tu->inode, tu->offset, &tu->consumer->cons);
tu->flags &= ~flag;
+ tu->enabled = false;
kfree(tu->consumer);
tu->consumer = NULL;
}
--
1.5.5.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 3/5] uprobes: Kill uprobe_trace_consumer, embed uprobe_consumer into trace_uprobe
2013-01-28 18:24 [PATCH 0/5] uprobes: kill uprobe_trace_consumer and other cleanups Oleg Nesterov
2013-01-28 18:24 ` [PATCH 1/5] uprobes: Ensure inode != NULL in create_trace_uprobe() Oleg Nesterov
2013-01-28 18:24 ` [PATCH 2/5] uprobes: Introduce trace_uprobe->enabled Oleg Nesterov
@ 2013-01-28 18:24 ` Oleg Nesterov
2013-01-28 18:25 ` [PATCH 4/5] uprobes: Kill set_trace_uprobe_filter_func() Oleg Nesterov
2013-01-28 18:25 ` [PATCH 5/5] uprobes: Kill trace_uprobe->enabled, introduce is_trace_uprobe_enabled() Oleg Nesterov
4 siblings, 0 replies; 6+ messages in thread
From: Oleg Nesterov @ 2013-01-28 18:24 UTC (permalink / raw)
To: Ingo Molnar, Srikar Dronamraju, Steven Rostedt
Cc: Anton Arapov, Frank Eigler, Josh Stone, Masami Hiramatsu,
Suzuki K. Poulose, linux-kernel
trace_uprobe->consumer and "struct uprobe_trace_consumer" add the
unnecessary indirection and complicate the code for no reason.
This patch simply embeds uprobe_consumer into "struct trace_uprobe",
all other changes only fix the compilation errors.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/trace/trace_uprobe.c | 44 ++++++++++--------------------------------
1 files changed, 11 insertions(+), 33 deletions(-)
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index c430d01..6551b77 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -32,12 +32,6 @@
/*
* uprobe event core functions
*/
-struct trace_uprobe;
-struct uprobe_trace_consumer {
- struct uprobe_consumer cons;
- struct trace_uprobe *tu;
-};
-
struct trace_uprobe_filter {
struct pid *tgid;
};
@@ -47,7 +41,7 @@ struct trace_uprobe {
struct ftrace_event_class class;
struct ftrace_event_call call;
bool enabled;
- struct uprobe_trace_consumer *consumer;
+ struct uprobe_consumer consumer;
struct trace_uprobe_filter filter;
struct inode *inode;
char *filename;
@@ -122,13 +116,13 @@ static bool trace_uprobe_filter_func(struct uprobe_consumer *uc,
enum uprobe_filter_ctx ctx,
struct mm_struct *mm)
{
- struct uprobe_trace_consumer *utc;
+ struct trace_uprobe *tu;
struct trace_uprobe_filter *filter;
struct task_struct *p, *t;
bool ret;
- utc = container_of(uc, struct uprobe_trace_consumer, cons);
- filter = &utc->tu->filter;
+ tu = container_of(uc, struct trace_uprobe, consumer);
+ filter = &tu->filter;
if (ctx == UPROBE_FILTER_MMAP)
return trace_uprobe_filter_current(filter);
@@ -645,30 +639,20 @@ partial:
static int probe_event_enable(struct trace_uprobe *tu, int flag)
{
- struct uprobe_trace_consumer *utc;
int ret = 0;
if (tu->enabled)
return -EINTR;
- utc = kzalloc(sizeof(struct uprobe_trace_consumer), GFP_KERNEL);
- if (!utc)
- return -EINTR;
-
- set_trace_uprobe_filter_func(&utc->cons, &tu->filter);
- utc->cons.handler = uprobe_dispatcher;
- utc->tu = tu;
- tu->consumer = utc;
+ set_trace_uprobe_filter_func(&tu->consumer, &tu->filter);
+ tu->consumer.handler = uprobe_dispatcher;
tu->flags |= flag;
- ret = uprobe_register(tu->inode, tu->offset, &utc->cons);
- if (ret) {
- tu->consumer = NULL;
+ ret = uprobe_register(tu->inode, tu->offset, &tu->consumer);
+ if (ret)
tu->flags &= ~flag;
- kfree(utc);
- } else {
+ else
tu->enabled = true;
- }
return ret;
}
@@ -678,11 +662,9 @@ static void probe_event_disable(struct trace_uprobe *tu, int flag)
if (!tu->enabled)
return;
- uprobe_unregister(tu->inode, tu->offset, &tu->consumer->cons);
+ uprobe_unregister(tu->inode, tu->offset, &tu->consumer);
tu->flags &= ~flag;
tu->enabled = false;
- kfree(tu->consumer);
- tu->consumer = NULL;
}
static int uprobe_event_define_fields(struct ftrace_event_call *event_call)
@@ -820,13 +802,9 @@ int trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type,
static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
{
- struct uprobe_trace_consumer *utc;
struct trace_uprobe *tu;
- utc = container_of(con, struct uprobe_trace_consumer, cons);
- tu = utc->tu;
- if (!tu || tu->consumer != utc)
- return 0;
+ tu = container_of(con, struct trace_uprobe, consumer);
if (!trace_uprobe_filter_current(&tu->filter))
return UPROBE_HANDLER_REMOVE;
--
1.5.5.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 4/5] uprobes: Kill set_trace_uprobe_filter_func()
2013-01-28 18:24 [PATCH 0/5] uprobes: kill uprobe_trace_consumer and other cleanups Oleg Nesterov
` (2 preceding siblings ...)
2013-01-28 18:24 ` [PATCH 3/5] uprobes: Kill uprobe_trace_consumer, embed uprobe_consumer into trace_uprobe Oleg Nesterov
@ 2013-01-28 18:25 ` Oleg Nesterov
2013-01-28 18:25 ` [PATCH 5/5] uprobes: Kill trace_uprobe->enabled, introduce is_trace_uprobe_enabled() Oleg Nesterov
4 siblings, 0 replies; 6+ messages in thread
From: Oleg Nesterov @ 2013-01-28 18:25 UTC (permalink / raw)
To: Ingo Molnar, Srikar Dronamraju, Steven Rostedt
Cc: Anton Arapov, Frank Eigler, Josh Stone, Masami Hiramatsu,
Suzuki K. Poulose, linux-kernel
Now that uprobe_consumer is embedded into "struct trace_uprobe" we
can remove the ugly set_trace_uprobe_filter_func() and initialize
consumer->handler/filter at create_ time.
The patch looks complicated, but this is only because it moves
trace_uprobe_filter_func() up before init_trace_uprobe_filter().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/trace/trace_uprobe.c | 97 ++++++++++++++++++++-----------------------
1 files changed, 45 insertions(+), 52 deletions(-)
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 6551b77..642e003 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -63,50 +63,6 @@ static void unregister_uprobe_event(struct trace_uprobe *tu);
static DEFINE_MUTEX(uprobe_lock);
static LIST_HEAD(uprobe_list);
-static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs);
-
-static int init_trace_uprobe_filter(struct trace_uprobe_filter *filter,
- const char *arg)
-{
- struct task_struct *p;
- pid_t tgid;
-
- if (!arg)
- return 0;
-
- if (kstrtouint(arg, 0, &tgid))
- goto err;
-
- filter->tgid = find_get_pid(tgid);
- if (!filter->tgid)
- goto err;
-
- rcu_read_lock();
- p = pid_task(filter->tgid, PIDTYPE_PID);
- if (!p || !has_group_leader_pid(p) || (p->flags & PF_KTHREAD))
- p = NULL;
- rcu_read_unlock();
-
- if (p)
- return 0;
-err:
- pr_info("Failed to find the process by pid=%s\n", arg);
- /* free_trace_uprobe() will take care of ->tgid != NULL */
- return -ESRCH;
-}
-
-static void free_trace_uprobe_filter(struct trace_uprobe_filter *filter)
-{
- put_pid(filter->tgid);
-}
-
-static void probes_seq_show_filter(struct trace_uprobe_filter *filter,
- struct seq_file *m)
-{
- if (filter->tgid)
- seq_printf(m, " pid=%d", pid_vnr(filter->tgid));
-}
-
static bool trace_uprobe_filter_current(struct trace_uprobe_filter *filter)
{
return !filter->tgid || filter->tgid == task_tgid(current);
@@ -144,13 +100,52 @@ static bool trace_uprobe_filter_func(struct uprobe_consumer *uc,
return ret;
}
-static inline void set_trace_uprobe_filter_func(struct uprobe_consumer *uc,
- struct trace_uprobe_filter *filter)
+static int init_trace_uprobe_filter(struct trace_uprobe *tu, const char *arg)
+{
+ struct task_struct *p;
+ pid_t tgid;
+
+ if (!arg)
+ return 0;
+
+ if (kstrtouint(arg, 0, &tgid))
+ goto err;
+
+ tu->filter.tgid = find_get_pid(tgid);
+ if (!tu->filter.tgid)
+ goto err;
+
+ rcu_read_lock();
+ p = pid_task(tu->filter.tgid, PIDTYPE_PID);
+ if (!p || !has_group_leader_pid(p) || (p->flags & PF_KTHREAD))
+ p = NULL;
+ rcu_read_unlock();
+
+ if (!p)
+ goto err;
+
+ tu->consumer.filter = trace_uprobe_filter_func;
+ return 0;
+err:
+ pr_info("Failed to find the process by pid=%s\n", arg);
+ /* free_trace_uprobe() will take care of ->tgid != NULL */
+ return -ESRCH;
+}
+
+static void free_trace_uprobe_filter(struct trace_uprobe *tu)
+{
+ put_pid(tu->filter.tgid);
+}
+
+static void probes_seq_show_filter(struct trace_uprobe_filter *filter,
+ struct seq_file *m)
{
if (filter->tgid)
- uc->filter = trace_uprobe_filter_func;
+ seq_printf(m, " pid=%d", pid_vnr(filter->tgid));
}
+static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs);
+
/*
* Allocate new trace_uprobe and initialize it (including uprobes).
*/
@@ -179,6 +174,7 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs)
goto error;
INIT_LIST_HEAD(&tu->list);
+ tu->consumer.handler = uprobe_dispatcher;
return tu;
error:
@@ -196,7 +192,7 @@ static void free_trace_uprobe(struct trace_uprobe *tu)
traceprobe_free_probe_arg(&tu->args[i]);
iput(tu->inode);
- free_trace_uprobe_filter(&tu->filter);
+ free_trace_uprobe_filter(tu);
kfree(tu->call.class->system);
kfree(tu->call.name);
kfree(tu->filename);
@@ -397,7 +393,7 @@ static int create_trace_uprobe(int argc, char **argv)
goto error;
}
- ret = init_trace_uprobe_filter(&tu->filter, filter_arg);
+ ret = init_trace_uprobe_filter(tu, filter_arg);
if (ret)
goto error;
@@ -644,10 +640,7 @@ static int probe_event_enable(struct trace_uprobe *tu, int flag)
if (tu->enabled)
return -EINTR;
- set_trace_uprobe_filter_func(&tu->consumer, &tu->filter);
- tu->consumer.handler = uprobe_dispatcher;
tu->flags |= flag;
-
ret = uprobe_register(tu->inode, tu->offset, &tu->consumer);
if (ret)
tu->flags &= ~flag;
--
1.5.5.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 5/5] uprobes: Kill trace_uprobe->enabled, introduce is_trace_uprobe_enabled()
2013-01-28 18:24 [PATCH 0/5] uprobes: kill uprobe_trace_consumer and other cleanups Oleg Nesterov
` (3 preceding siblings ...)
2013-01-28 18:25 ` [PATCH 4/5] uprobes: Kill set_trace_uprobe_filter_func() Oleg Nesterov
@ 2013-01-28 18:25 ` Oleg Nesterov
4 siblings, 0 replies; 6+ messages in thread
From: Oleg Nesterov @ 2013-01-28 18:25 UTC (permalink / raw)
To: Ingo Molnar, Srikar Dronamraju, Steven Rostedt
Cc: Anton Arapov, Frank Eigler, Josh Stone, Masami Hiramatsu,
Suzuki K. Poulose, linux-kernel
Finally kill trace_uprobe->enabled and add is_trace_uprobe_enabled()
which can rely on TP_FLAG_TRACE/TP_FLAG_PROFILE bits we set/clear
anyway.
Note that we could do this from the very beginning, ->enabled was
never strictly needed. But I'd prefer to do this as a last change
so that it can be dropped if the reviewers do not like the (ab)use
of tu->flags.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/trace/trace_uprobe.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 642e003..1e1633c 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -40,7 +40,6 @@ struct trace_uprobe {
struct list_head list;
struct ftrace_event_class class;
struct ftrace_event_call call;
- bool enabled;
struct uprobe_consumer consumer;
struct trace_uprobe_filter filter;
struct inode *inode;
@@ -633,31 +632,33 @@ partial:
return TRACE_TYPE_PARTIAL_LINE;
}
+static inline bool is_trace_uprobe_enabled(struct trace_uprobe *tu)
+{
+ return tu->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE);
+}
+
static int probe_event_enable(struct trace_uprobe *tu, int flag)
{
int ret = 0;
- if (tu->enabled)
+ if (is_trace_uprobe_enabled(tu))
return -EINTR;
tu->flags |= flag;
ret = uprobe_register(tu->inode, tu->offset, &tu->consumer);
if (ret)
tu->flags &= ~flag;
- else
- tu->enabled = true;
return ret;
}
static void probe_event_disable(struct trace_uprobe *tu, int flag)
{
- if (!tu->enabled)
+ if (!is_trace_uprobe_enabled(tu))
return;
uprobe_unregister(tu->inode, tu->offset, &tu->consumer);
tu->flags &= ~flag;
- tu->enabled = false;
}
static int uprobe_event_define_fields(struct ftrace_event_call *event_call)
--
1.5.5.1
^ permalink raw reply related [flat|nested] 6+ messages in thread