tracing/uprobes: Support ftrace_event_file base multibuffer
PATCH v2 1/1 tracing/uprobes: Support ftrace_event_file base multibuffer
Support multi-buffer on uprobe-based dynamic events by using ftrace_event_file.
This patch is based kprobe-based dynamic events multibuffer support work initially, commited by Masami(commit 41a7dd420c), but revised as below:
Oleg changed the kprobe-based multibuffer design from array-pointers of ftrace_event_file into simple list, so this patch also change to the list degisn.
rcu_read_lock/unlock added into uprobe_trace_func/uretprobe_trace_func, to synchronize with ftrace_event_file list add and delete.
Even though we allow multi-uprobes instances now,
but TP_FLAG_PROFILE/TP_FLAG_TRACE are still mutually exclusive in probe_event_enable currently, this means we cannot allow one user is using uprobe-tracer, and another user is using perf-probe on same uprobe at same time.
(Perhaps this will be fix in future)
--- kernel/trace/trace_uprobe.c | 132 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 110 insertions(+), 22 deletions(-)
kernel/trace/trace_uprobe.c +110 -22
@@ -53,6 +53,7 @@ struct trace_uprobe {struct list_head list;struct ftrace_event_class class;struct ftrace_event_call call; +struct list_head files;struct trace_uprobe_filter filter;struct uprobe_consumer consumer;struct inode *inode;
@@ -65,6 +66,11 @@ struct trace_uprobe {struct probe_arg args[]; }; +struct event_file_link { +struct ftrace_event_file *file; +struct list_head list; +}; +#define SIZEOF_TRACE_UPROBE (n) \ (offsetof(struct trace_uprobe, args) + \ (sizeof(struct probe_arg) * (n)))
@@ -124,6 +130,7 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret) goto error;INIT_LIST_HEAD (&tu->list); +INIT_LIST_HEAD (&tu->files); tu->consumer.handler = uprobe_dispatcher;if (is_ret) tu->consumer.ret_handler = uretprobe_dispatcher;
@@ -511,7 +518,8 @@ static const struct file_operations uprobe_profile_ops = { };static void uprobe_trace_print (struct trace_uprobe *tu, -unsigned long func,struct pt_regs *regs) +unsigned long func,struct pt_regs *regs, +struct ftrace_event_file *ftrace_file) {struct uprobe_trace_entry_head *entry;struct ring_buffer_event *event;
@@ -520,9 +528,15 @@ static void uprobe_trace_print(struct trace_uprobe *tu,int size, i;struct ftrace_event_call *call = &tu->call; +WARN_ON (call != ftrace_file->event_call); + +if (test_bit (FTRACE_EVENT_FL_SOFT_DISABLED_BIT , &ftrace_file->flags)) +return ; + size =SIZEOF_TRACE_ENTRY (is_ret_probe (tu)); - event =trace_current_buffer_lock_reserve (&buffer, call->event.type, - size + tu->size,0 ,0 ); + event =trace_event_buffer_lock_reserve (&buffer, ftrace_file, + call->event.type, + size + tu->size,0 ,0 );if (!event)return ;
@@ -546,15 +560,32 @@ static void uprobe_trace_print(struct trace_uprobe *tu,/* uprobe handler */ static int uprobe_trace_func (struct trace_uprobe *tu,struct pt_regs *regs) { -if (!is_ret_probe (tu)) -uprobe_trace_print (tu,0 , regs); +struct event_file_link *link; + +if (is_ret_probe (tu)) +return 0 ; + +rcu_read_lock (); + +list_for_each_entry (link, &tu->files, list) +uprobe_trace_print (tu,0 , regs, link->file); + +rcu_read_unlock (); +return 0 ; }static void uretprobe_trace_func (struct trace_uprobe *tu,unsigned long func,struct pt_regs *regs) { -uprobe_trace_print (tu, func, regs); +struct event_file_link *link; + +rcu_read_lock (); + +list_for_each_entry (link, &tu->files, list) +uprobe_trace_print (tu, func, regs, link->file); + +rcu_read_unlock (); }/* Event entry printers */
@@ -605,33 +636,89 @@ typedef bool (*filter_func_t)(struct uprobe_consumer *self, struct mm_struct *mm);static int -probe_event_enable (struct trace_uprobe *tu,int flag,filter_func_t filter) +probe_event_enable (struct trace_uprobe *tu,struct ftrace_event_file *file, +filter_func_t filter) { +int enabled =0 ;int ret =0 ; -if (is_trace_uprobe_enabled (tu)) +/* +* Currently TP_FLAG_TRACE/TP_FLAG_PROFILE are mutually exclusive +* for uprobe(filter argument issue), this need to fix in future. +*/ +if ((file && (tu->flags &TP_FLAG_PROFILE )) || + (!file && (tu->flags &TP_FLAG_TRACE )))return -EINTR ; +/* Currently we cannot call uprobe_register twice for same tu */ +if (is_trace_uprobe_enabled (tu)) + enabled =1 ; + +if (file) { +struct event_file_link *link; + + link =kmalloc (sizeof (*link),GFP_KERNEL ); +if (!link) +return -ENOMEM ; + + link->file = file; +list_add_rcu (&link->list, &tu->files); + + tu->flags |=TP_FLAG_TRACE ; + }else + tu->flags |=TP_FLAG_PROFILE ; +WARN_ON (!uprobe_filter_is_empty (&tu->filter)); - tu->flags |= flag; - tu->consumer.filter = filter; - ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); -if (ret) - tu->flags &= ~flag; +if (!enabled) { + tu->consumer.filter = filter; + ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); +if (ret) + tu->flags &= file ? ~TP_FLAG_TRACE : ~TP_FLAG_PROFILE ; + }return ret; } -static void probe_event_disable (struct trace_uprobe *tu,int flag) +static struct event_file_link * +find_event_file_link (struct trace_uprobe *tu,struct ftrace_event_file *file) { -if (!is_trace_uprobe_enabled (tu)) -return ; +struct event_file_link *link; + +list_for_each_entry (link, &tu->files, list) +if (link->file == file) +return link; + +return NULL ; +} + +static void +probe_event_disable (struct trace_uprobe *tu,struct ftrace_event_file *file) +{ +if (file) { +struct event_file_link *link; + + link =find_event_file_link (tu, file); +if (!link) +return ; + +list_del_rcu (&link->list); +/* synchronize with uprobe_trace_func/uretprobe_trace_func */ +synchronize_sched (); +kfree (link); + +if (!list_empty (&tu->files)) +return ; + + tu->flags &= ~TP_FLAG_TRACE ; + }else + tu->flags &= ~TP_FLAG_PROFILE ; +WARN_ON (!uprobe_filter_is_empty (&tu->filter)); -uprobe_unregister (tu->inode, tu->offset, &tu->consumer); - tu->flags &= ~flag; +if (!is_trace_uprobe_enabled (tu)) +uprobe_unregister (tu->inode, tu->offset, &tu->consumer); }static int uprobe_event_define_fields (struct ftrace_event_call *event_call)
@@ -867,21 +954,22 @@ staticint trace_uprobe_register (struct ftrace_event_call *event,enum trace_reg type,void *data) {struct trace_uprobe *tu = event->data; +struct ftrace_event_file *file = data;switch (type) {case TRACE_REG_REGISTER : -return probe_event_enable (tu,TP_FLAG_TRACE ,NULL ); +return probe_event_enable (tu, file,NULL );case TRACE_REG_UNREGISTER : -probe_event_disable (tu,TP_FLAG_TRACE ); +probe_event_disable (tu, file);return 0 ;#ifdef CONFIG_PERF_EVENTS case TRACE_REG_PERF_REGISTER : -return probe_event_enable (tu,TP_FLAG_PROFILE , uprobe_perf_filter); +return probe_event_enable (tu,NULL , uprobe_perf_filter);case TRACE_REG_PERF_UNREGISTER : -probe_event_disable (tu,TP_FLAG_PROFILE ); +probe_event_disable (tu,NULL );return 0 ;case TRACE_REG_PERF_OPEN :
Signature · 1 line
1.7.9.7
Quoted 14 lines · zhangwei(Jovi)
Support multi-buffer on uprobe-based dynamic events by using
ftrace_event_file.This patch is based kprobe-based dynamic events multibuffer support work initially, commited by Masami(commit
41a7dd420c), but revised as below:Oleg changed the kprobe-based multibuffer design from array-pointers of
ftrace_event_fileinto simple list, so this patch also change to the list degisn.rcu_read_lock/unlock added into uprobe_trace_func/uretprobe_trace_func, to synchronize with
ftrace_event_filelist add and delete.
Quoted 6 lines
Even though we allow multi-uprobes instances now,
but TP_FLAG_PROFILE/TP_FLAG_TRACE are still mutually exclusive inprobe_event_enablecurrently, this means we cannot allow one user is using uprobe-tracer, and another user is using perf-probe on same uprobe at same time.
(Perhaps this will be fix in future)
Oh... BTW, in the early stage, kprobe-tracer also has same limitation and fixed by commit 50d78056.
Quoted 53 lines
Signed-off-by zhangwei(Jovi) <[email protected]>Cc Masami Hiramatsu <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Oleg Nesterov <[email protected]>Cc Srikar Dronamraju <[email protected]>--- kernel/trace/trace_uprobe.c | 132 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 110 insertions(+), 22 deletions(-)kernel/trace/trace_uprobe.c +9
-1@@ -53,6 +53,7 @@ struct trace_uprobe {struct list_head list;struct ftrace_event_class class;struct ftrace_event_call call; +struct list_head files;struct trace_uprobe_filter filter;struct uprobe_consumer consumer;struct inode *inode;@@ -65,6 +66,11 @@ struct trace_uprobe {struct probe_arg args[]; }; +struct event_file_link { +struct ftrace_event_file *file; +struct list_head list; +}; +#define SIZEOF_TRACE_UPROBE (n) \ (offsetof(struct trace_uprobe, args) + \ (sizeof(struct probe_arg) * (n)))@@ -124,6 +130,7 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret) goto error;INIT_LIST_HEAD (&tu->list); +INIT_LIST_HEAD (&tu->files); tu->consumer.handler = uprobe_dispatcher;if (is_ret) tu->consumer.ret_handler = uretprobe_dispatcher;@@ -511,7 +518,8 @@ static const struct file_operations uprobe_profile_ops = { };static void uprobe_trace_print (struct trace_uprobe *tu, -unsigned long func,struct pt_regs *regs) +unsigned long func,struct pt_regs *regs, +struct ftrace_event_file *ftrace_file) {struct uprobe_trace_entry_head *entry;struct ring_buffer_event *event;
kernel/trace/trace_uprobe.c static void uprobe_trace_print(struct trace_uprobe *tu, · line 534
Quoted 7 lines
kernel/trace/trace_uprobe.c +4
-0@@ -520,9 +528,15 @@ static void uprobe_trace_print(struct trace_uprobe *tu,int size, i;struct ftrace_event_call *call = &tu->call; +WARN_ON (call != ftrace_file->event_call); + +if (test_bit (FTRACE_EVENT_FL_SOFT_DISABLED_BIT , &ftrace_file->flags)) +return ;
One note, here you added "soft disabling support" which is different from multibuffer support. It would be nice to note this in patch description or make a separated patch.
Other parts look good for me :)
Thank you,
Quoted 176 lines
kernel/trace/trace_uprobe.c +97
-21+ size =SIZEOF_TRACE_ENTRY (is_ret_probe (tu)); - event =trace_current_buffer_lock_reserve (&buffer, call->event.type, - size + tu->size,0 ,0 ); + event =trace_event_buffer_lock_reserve (&buffer, ftrace_file, + call->event.type, + size + tu->size,0 ,0 );if (!event)return ;@@ -546,15 +560,32 @@ static void uprobe_trace_print(struct trace_uprobe *tu,/* uprobe handler */ static int uprobe_trace_func (struct trace_uprobe *tu,struct pt_regs *regs) { -if (!is_ret_probe (tu)) -uprobe_trace_print (tu,0 , regs); +struct event_file_link *link; + +if (is_ret_probe (tu)) +return 0 ; + +rcu_read_lock (); + +list_for_each_entry (link, &tu->files, list) +uprobe_trace_print (tu,0 , regs, link->file); + +rcu_read_unlock (); +return 0 ; }static void uretprobe_trace_func (struct trace_uprobe *tu,unsigned long func,struct pt_regs *regs) { -uprobe_trace_print (tu, func, regs); +struct event_file_link *link; + +rcu_read_lock (); + +list_for_each_entry (link, &tu->files, list) +uprobe_trace_print (tu, func, regs, link->file); + +rcu_read_unlock (); }/* Event entry printers */ @@ -605,33 +636,89 @@ typedef bool (*filter_func_t)(struct uprobe_consumer *self, struct mm_struct *mm);static int -probe_event_enable (struct trace_uprobe *tu,int flag,filter_func_t filter) +probe_event_enable (struct trace_uprobe *tu,struct ftrace_event_file *file, +filter_func_t filter) { +int enabled =0 ;int ret =0 ; -if (is_trace_uprobe_enabled (tu)) +/* +* Currently TP_FLAG_TRACE/TP_FLAG_PROFILE are mutually exclusive +* for uprobe(filter argument issue), this need to fix in future. +*/ +if ((file && (tu->flags &TP_FLAG_PROFILE )) || + (!file && (tu->flags &TP_FLAG_TRACE )))return -EINTR ; +/* Currently we cannot call uprobe_register twice for same tu */ +if (is_trace_uprobe_enabled (tu)) + enabled =1 ; + +if (file) { +struct event_file_link *link; + + link =kmalloc (sizeof (*link),GFP_KERNEL ); +if (!link) +return -ENOMEM ; + + link->file = file; +list_add_rcu (&link->list, &tu->files); + + tu->flags |=TP_FLAG_TRACE ; + }else + tu->flags |=TP_FLAG_PROFILE ; +WARN_ON (!uprobe_filter_is_empty (&tu->filter)); - tu->flags |= flag; - tu->consumer.filter = filter; - ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); -if (ret) - tu->flags &= ~flag; +if (!enabled) { + tu->consumer.filter = filter; + ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); +if (ret) + tu->flags &= file ? ~TP_FLAG_TRACE : ~TP_FLAG_PROFILE ; + }return ret; } -static void probe_event_disable (struct trace_uprobe *tu,int flag) +static struct event_file_link * +find_event_file_link (struct trace_uprobe *tu,struct ftrace_event_file *file) { -if (!is_trace_uprobe_enabled (tu)) -return ; +struct event_file_link *link; + +list_for_each_entry (link, &tu->files, list) +if (link->file == file) +return link; + +return NULL ; +} + +static void +probe_event_disable (struct trace_uprobe *tu,struct ftrace_event_file *file) +{ +if (file) { +struct event_file_link *link; + + link =find_event_file_link (tu, file); +if (!link) +return ; + +list_del_rcu (&link->list); +/* synchronize with uprobe_trace_func/uretprobe_trace_func */ +synchronize_sched (); +kfree (link); + +if (!list_empty (&tu->files)) +return ; + + tu->flags &= ~TP_FLAG_TRACE ; + }else + tu->flags &= ~TP_FLAG_PROFILE ; +WARN_ON (!uprobe_filter_is_empty (&tu->filter)); -uprobe_unregister (tu->inode, tu->offset, &tu->consumer); - tu->flags &= ~flag; +if (!is_trace_uprobe_enabled (tu)) +uprobe_unregister (tu->inode, tu->offset, &tu->consumer); }static int uprobe_event_define_fields (struct ftrace_event_call *event_call)@@ -867,21 +954,22 @@ staticint trace_uprobe_register (struct ftrace_event_call *event,enum trace_reg type,void *data) {struct trace_uprobe *tu = event->data; +struct ftrace_event_file *file = data;switch (type) {case TRACE_REG_REGISTER : -return probe_event_enable (tu,TP_FLAG_TRACE ,NULL ); +return probe_event_enable (tu, file,NULL );case TRACE_REG_UNREGISTER : -probe_event_disable (tu,TP_FLAG_TRACE ); +probe_event_disable (tu, file);return 0 ;#ifdef CONFIG_PERF_EVENTS case TRACE_REG_PERF_REGISTER : -return probe_event_enable (tu,TP_FLAG_PROFILE , uprobe_perf_filter); +return probe_event_enable (tu,NULL , uprobe_perf_filter);case TRACE_REG_PERF_UNREGISTER : -probe_event_disable (tu,TP_FLAG_PROFILE ); +probe_event_disable (tu,NULL );return 0 ;case TRACE_REG_PERF_OPEN :
Signature · 4 lines
Masami HIRAMATSU IT Management Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Hi Jovi,
I'll try to read this patch carefully tomorrow.
Looks fine at first glance, but some nits below.
Quoted 6 lines · zhangwei(Jovi)
static int
uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs){kernel/trace/trace_uprobe.c +1
-2-if (!is_ret_probe (tu)) -uprobe_trace_print (tu,0 , regs); +struct event_file_link *link;
kernel/trace/trace_uprobe.c static void uprobe_trace_print(struct trace_uprobe *tu, · line 573
Quoted 10 lines
kernel/trace/trace_uprobe.c +10
-0+ +if (is_ret_probe (tu)) +return 0 ; + +rcu_read_lock (); + +list_for_each_entry (link, &tu->files, list) +uprobe_trace_print (tu,0 , regs, link->file); + +rcu_read_unlock ();
Purely cosmetic and I won't argue, but why the empty lines around list_for_each_entry() ?
Quoted 6 lines
static int
kernel/trace/trace_uprobe.c +3
-1-probe_event_enable(struct trace_uprobe *tu, int flag, filter_func_t filter) +probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, + filter_func_t filter) { + int enabled = 0;
kernel/trace/trace_uprobe.c typedef bool (*filter_func_t)(struct uprobe_consumer *self, · line 651
Quoted 10 lines
kernel/trace/trace_uprobe.c +6
-1int ret =0 ; -if (is_trace_uprobe_enabled (tu)) +/* +* Currently TP_FLAG_TRACE/TP_FLAG_PROFILE are mutually exclusive +* for uprobe(filter argument issue), this need to fix in future. +*/ +if ((file && (tu->flags &TP_FLAG_PROFILE )) || + (!file && (tu->flags &TP_FLAG_TRACE )))return -EINTR ;
Well, this looks confusing and overcomplicated, see below.
kernel/trace/trace_uprobe.c typedef bool (*filter_func_t)(struct uprobe_consumer *self, · line 655
Quoted 3 lines
kernel/trace/trace_uprobe.c +3
-0+/* Currently we cannot call uprobe_register twice for same tu */ +if (is_trace_uprobe_enabled (tu)) + enabled =1 ;
The comment is wrong. It is not that we can't do this "Currently".
We must not do uprobe_register(..., consumer) twice, consumer/uprobe are linked together.
kernel/trace/trace_uprobe.c typedef bool (*filter_func_t)(struct uprobe_consumer *self, · line 659
Quoted 3 lines
kernel/trace/trace_uprobe.c +3
-0+if (file) { +struct event_file_link *link; +
Just add
if (TP_FLAG_PROFILE) return -EINTR;
here and kill the complicated check below. Same for the "else" branch.
Quoted 19 lines
kernel/trace/trace_uprobe.c +19
-0+static void +probe_event_disable (struct trace_uprobe *tu,struct ftrace_event_file *file) +{ +if (file) { +struct event_file_link *link; + + link =find_event_file_link (tu, file); +if (!link) +return ; + +list_del_rcu (&link->list); +/* synchronize with uprobe_trace_func/uretprobe_trace_func */ +synchronize_sched (); +kfree (link); + +if (!list_empty (&tu->files)) +return ; + + tu->flags &= ~TP_FLAG_TRACE ;
kernel/trace/trace_uprobe.c typedef bool (*filter_func_t)(struct uprobe_consumer *self, · line 721
Quoted 10 lines
kernel/trace/trace_uprobe.c +5
-2+ }else + tu->flags &= ~TP_FLAG_PROFILE ; +WARN_ON (!uprobe_filter_is_empty (&tu->filter)); -uprobe_unregister (tu->inode, tu->offset, &tu->consumer); - tu->flags &= ~flag; +if (!is_trace_uprobe_enabled (tu)) +uprobe_unregister (tu->inode, tu->offset, &tu->consumer);
Well, this is not exactly right... Currently this is fine, but still.
It would be better to clear TP_FLAG_TRACE/TP_FLAG_PROFILE after uprobe_unregister(), when we can't race with the running handler which can check ->flags.
And I'd suggest you to send the soft-enable/disable change in a separate (and trivial) patch.
Oleg.
forgot to mention,
Quoted 4 lines · Oleg Nesterov
kernel/trace/trace_uprobe.c typedef bool (*filter_func_t)(struct uprobe_consumer *self, · line 647
Quoted 4 lines
kernel/trace/trace_uprobe.c +3
-0+/* +* Currently TP_FLAG_TRACE/TP_FLAG_PROFILE are mutually exclusive +* for uprobe(filter argument issue), this need to fix in future.
^^^^^^^^^^^^^^^^^^^^^
Just in case, this is not that simple.
For example, suppose that TRACE_REG_REGISTER comes after TRACE_REG_PERF_REGISTER. In this case we need uprobe_perf_open-like code to establish nr_systemwide != 0 and do uprobe_apply() if necessary.
Oleg.
Quoted 97 lines · Oleg Nesterov
Hi Jovi,
I'll try to read this patch carefully tomorrow.
Looks fine at first glance, but some nits below.
Quoted 6 lines · zhangwei(Jovi)
static int
uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs){kernel/trace/trace_uprobe.c +1
-2-if (!is_ret_probe (tu)) -uprobe_trace_print (tu,0 , regs); +struct event_file_link *link;kernel/trace/trace_uprobe.c static void uprobe_trace_print(struct trace_uprobe *tu, · line 573
Quoted 10 lines
kernel/trace/trace_uprobe.c +10
-0+ +if (is_ret_probe (tu)) +return 0 ; + +rcu_read_lock (); + +list_for_each_entry (link, &tu->files, list) +uprobe_trace_print (tu,0 , regs, link->file); + +rcu_read_unlock ();Purely cosmetic and I won't argue, but why the empty lines around
list_for_each_entry()?Quoted 6 lines
static int
kernel/trace/trace_uprobe.c +3
-1-probe_event_enable(struct trace_uprobe *tu, int flag, filter_func_t filter) +probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, + filter_func_t filter) { + int enabled = 0;kernel/trace/trace_uprobe.c typedef bool (*filter_func_t)(struct uprobe_consumer *self, · line 651
Quoted 10 lines
kernel/trace/trace_uprobe.c +6
-1int ret =0 ; -if (is_trace_uprobe_enabled (tu)) +/* +* Currently TP_FLAG_TRACE/TP_FLAG_PROFILE are mutually exclusive +* for uprobe(filter argument issue), this need to fix in future. +*/ +if ((file && (tu->flags &TP_FLAG_PROFILE )) || + (!file && (tu->flags &TP_FLAG_TRACE )))return -EINTR ;Well, this looks confusing and overcomplicated, see below.
kernel/trace/trace_uprobe.c typedef bool (*filter_func_t)(struct uprobe_consumer *self, · line 655
Quoted 3 lines
kernel/trace/trace_uprobe.c +3
-0+/* Currently we cannot call uprobe_register twice for same tu */ +if (is_trace_uprobe_enabled (tu)) + enabled =1 ;The comment is wrong. It is not that we can't do this "Currently".
We must not do
uprobe_register(..., consumer)twice, consumer/uprobe are linked together.kernel/trace/trace_uprobe.c typedef bool (*filter_func_t)(struct uprobe_consumer *self, · line 659
Quoted 3 lines
kernel/trace/trace_uprobe.c +3
-0+if (file) { +struct event_file_link *link; +Just add
if (TP_FLAG_PROFILE) return -EINTR;here and kill the complicated check below. Same for the "else" branch.
Quoted 19 lines
kernel/trace/trace_uprobe.c +19
-0+static void +probe_event_disable (struct trace_uprobe *tu,struct ftrace_event_file *file) +{ +if (file) { +struct event_file_link *link; + + link =find_event_file_link (tu, file); +if (!link) +return ; + +list_del_rcu (&link->list); +/* synchronize with uprobe_trace_func/uretprobe_trace_func */ +synchronize_sched (); +kfree (link); + +if (!list_empty (&tu->files)) +return ; + + tu->flags &= ~TP_FLAG_TRACE ;kernel/trace/trace_uprobe.c typedef bool (*filter_func_t)(struct uprobe_consumer *self, · line 721
Quoted 10 lines
kernel/trace/trace_uprobe.c +5
-2+ }else + tu->flags &= ~TP_FLAG_PROFILE ; +WARN_ON (!uprobe_filter_is_empty (&tu->filter)); -uprobe_unregister (tu->inode, tu->offset, &tu->consumer); - tu->flags &= ~flag; +if (!is_trace_uprobe_enabled (tu)) +uprobe_unregister (tu->inode, tu->offset, &tu->consumer);Well, this is not exactly right... Currently this is fine, but still.
Quoted 8 lines
It would be better to clear TP_FLAG_TRACE/TP_FLAG_PROFILE after
uprobe_unregister(), when we can't race with the running handler which can check ->flags.And I'd suggest you to send the soft-enable/disable change in a separate (and trivial) patch.
Oleg.
Thanks Oleg, you are right, please check v3 patch.
.jovi