uprobes: kill uprobe_trace_consumer and other cleanups
PATCH 1/5 uprobes: Ensure inode != NULL in create_trace_uprobe()
In reply to Oleg Nesterovprobe_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.
--- kernel/trace/trace_uprobe.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
kernel/trace/trace_uprobe.c +4 -2
@@ -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);
Signature · 1 line
1.5.5.1
PATCH 2/5 uprobes: Introduce trace_uprobe->enabled
In reply to Oleg Nesterovprobe_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.
--- kernel/trace/trace_uprobe.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)
kernel/trace/trace_uprobe.c +6 -2
@@ -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 ; }
Signature · 1 line
1.5.5.1
PATCH 5/5 uprobes: Kill trace_uprobe->enabled, introduce is_trace_uprobe_enabled()
In reply to Oleg NesterovFinally 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.
--- kernel/trace/trace_uprobe.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
kernel/trace/trace_uprobe.c +7 -6
@@ -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)
Signature · 1 line
1.5.5.1
cover uprobes: kill uprobe_trace_consumer and other cleanups
Hello.
On top of
"[PATCH 0/4] uprobes: Teach debug/tracing/uprobe_events to do the filtering" I sent yesterday.
I tried to test that series, seems to work...
This one tries to cleanup the code. No functional changes. Almost untested so far, but please review.
Since I had to look at this code, I simply can't resist. uprobe_trace_consumer complicates the code for no reason and imho should die.
Oleg.
kernel/trace/trace_uprobe.c | 146 ++++++++++++++++++------------------------- 1 files changed, 62 insertions(+), 84 deletions(-)
PATCH 3/5 uprobes: Kill uprobe_trace_consumer, embed uprobe_consumer into trace_uprobe
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.
--- kernel/trace/trace_uprobe.c | 44 ++++++++++-------------------------------- 1 files changed, 11 insertions(+), 33 deletions(-)
kernel/trace/trace_uprobe.c +11 -33
@@ -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 ;
Signature · 1 line
1.5.5.1
PATCH 4/5 uprobes: Kill set_trace_uprobe_filter_func()
In reply to Oleg NesterovNow 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().
--- kernel/trace/trace_uprobe.c | 97 ++++++++++++++++++++----------------------- 1 files changed, 45 insertions(+), 52 deletions(-)
kernel/trace/trace_uprobe.c +45 -52
@@ -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;
Signature · 1 line
1.5.5.1