tracing/uprobes fixes
Subsystems (3)
Oleg Nesterov
maintainercover tracing/uprobes fixes
Hello,
It took me several hours to realize that the strange bug I hit was caused by the change I have nacked in the past ;)
But it appears that I should take the blame. I was cc'ed, but I missed that email or forgot to reply, so another attempt to push this "trivial" change was successful.
I think that 1/4 should go to stable. 2-4 are "while at it" fixes.
Oleg.
kernel/events/uprobes.c | 6 ++-- kernel/trace/trace_uprobe.c | 46 +++++++++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 22 deletions(-)
Oleg Nesterov
maintainerPATCH 1/4 tracing/uprobes: Revert "Support mix of ftrace and perf"
This reverts commit 43fe98913c9f67e3b523615ee3316f9520a623e0.
This patch is very wrong. Firstly, this change leads to unbalanced uprobe_unregister(). Just for example,
# perf probe -x /lib/libc.so.6 syscall # echo 1 >> /sys/kernel/debug/tracing/events/probe_libc/enable # perf record -e probe_libc:syscall whatever
after that uprobe is dead (unregistered) but the user of ftrace/perf can't know this, and it looks as if nobody hits this probe.
This would be easy to fix, but there are other reasons why it is not simple to mix ftrace and perf. If nothing else, they can't share the same ->consumer.filter. This is fixable too, but probably we need to fix the poorly designed uprobe_register() interface first. At least "register" and "apply" should be clearly separated.
--- kernel/trace/trace_uprobe.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
kernel/trace/trace_uprobe.c +8 -1
@@ -893,6 +893,9 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file,int ret;if (file) { +if (tu->tp.flags &TP_FLAG_PROFILE ) +return -EINTR ; + link =kmalloc (sizeof (*link),GFP_KERNEL );if (!link)return -ENOMEM ;
@@ -901,8 +904,12 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file,list_add_tail_rcu (&link->list, &tu->tp.files); tu->tp.flags |=TP_FLAG_TRACE ; - }else + }else { +if (tu->tp.flags &TP_FLAG_TRACE ) +return -EINTR ; + tu->tp.flags |=TP_FLAG_PROFILE ; + } ret =uprobe_buffer_enable ();if (ret <0 )
Signature · 1 line
1.5.5.1
Re: [PATCH 1/4] tracing/uprobes: Revert "Support mix of ftrace and perf"
Hi Oleg,
Quoted 11 lines · Oleg Nesterov
This reverts commit
43fe98913c9f67e3b523615ee3316f9520a623e0.This patch is very wrong. Firstly, this change leads to unbalanced
uprobe_unregister(). Just for example,# perf probe -x /lib/libc.so.6 syscall # echo 1 >> /sys/kernel/debug/tracing/events/probe_libc/enable # perf record -e probe_libc:syscall whateverafter that uprobe is dead (unregistered) but the user of ftrace/perf can't know this, and it looks as if nobody hits this probe.
Nah, I missed to check the unregister path.. :-/
Quoted 6 lines
This would be easy to fix, but there are other reasons why it is not simple to mix ftrace and perf. If nothing else, they can't share the same ->consumer.filter. This is fixable too, but probably we need to fix the poorly designed
uprobe_register()interface first. At least "register" and "apply" should be clearly separated.
Hmm.. right. It seems the current filter logic only cares about the perf. If ftrace comes after perf, it might not see some events due to the filter, right?
Quoted 3 lines
Cc [email protected] # v3.14Signed-off-by Oleg Nesterov <[email protected]>
Thanks,
Namhyung
Quoted 32 lines
--- kernel/trace/trace_uprobe.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)kernel/trace/trace_uprobe.c +8
-1@@ -893,6 +893,9 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file,int ret;if (file) { +if (tu->tp.flags &TP_FLAG_PROFILE ) +return -EINTR ; + link =kmalloc (sizeof (*link),GFP_KERNEL );if (!link)return -ENOMEM ;@@ -901,8 +904,12 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file,list_add_tail_rcu (&link->list, &tu->tp.files); tu->tp.flags |=TP_FLAG_TRACE ; - }else + }else { +if (tu->tp.flags &TP_FLAG_TRACE ) +return -EINTR ; + tu->tp.flags |=TP_FLAG_PROFILE ; + } ret =uprobe_buffer_enable ();if (ret <0 )
Oleg Nesterov
maintainerRe: [PATCH 1/4] tracing/uprobes: Revert "Support mix of ftrace and perf"
Hi Namhyung,
Quoted 9 lines · Namhyung Kim
Quoted 6 lines · Oleg Nesterov
This would be easy to fix, but there are other reasons why it is not simple to mix ftrace and perf. If nothing else, they can't share the same ->consumer.filter. This is fixable too, but probably we need to fix the poorly designed
uprobe_register()interface first. At least "register" and "apply" should be clearly separated.
Quoted 3 lines
Hmm.. right. It seems the current filter logic only cares about the perf. If ftrace comes after perf, it might not see some events due to the filter, right?
Yes. Or vice versa, ftrace can miss the events because perf can return UPROBE_HANDLER_REMOVE. Or ftrace can come after perf, but in this case it should call uprobe_apply() or it won't add the new breakpoints.
Actually, I'll probably try to make the patch tomorrow. It looks simple enough, the main complication is CONFIG_PERF. And, to keep this patch simple, I won't try to optimize (say) the TP_FLAG_TRACE-comes-first case which could avoid uprobe_apply().
Yes, I still think it would be better to change the register/unregister API first, but I do not know when I do this ;)
Quoted 4 lines
Quoted 2 lines
Cc [email protected] # v3.14Signed-off-by Oleg Nesterov <[email protected]>Acked-by Namhyung Kim <[email protected]>
Thanks!
Oleg.
Oleg Nesterov
maintainerprobe_event_disable()->synchronize_sched() (Was: tracing/uprobes: Revert "Support mix of ftrace and perf")
Namhyung, Masami,
Please look at the question below. Perhaps we discussed this before, but I can recall nothing.
Quoted 5 lines · Oleg Nesterov
Actually, I'll probably try to make the patch tomorrow. It looks simple enough, the main complication is
CONFIG_PERF. And, to keep this patch simple, I won't try to optimize (say) the TP_FLAG_TRACE-comes-first case which could avoiduprobe_apply().
I regret very much I said this ;) OK, I'll probably try anyway, but...
Quoted 2 lines
Yes, I still think it would be better to change the register/unregister API first, but I do not know when I do this ;)
OK, we can do this later.
But it turns out that trace_uprobe.c needs other cleanups, and I simply can't uglify this code more without these cleanups... Starting from set/clear TP_FLAG_*. I'll recheck, but it seems that there is no reason to carefully set (say) TP_FLAG_TRACE before uprobe_register() and then clear it if _register() fails. And uprobe_dispatcher() is very ugly if is_ret_probe(). And more. So it needs a series.
-------------------------------------------------------------------------
And. I am puzzled by probe_event_disable()->synchronize_sched(). Why do we need it? I mean, why we can't use call_rcu() ? The comment says "synchronize with u{,ret}probe_trace_func" but it doesn't explain _why_ do we need to sync.
I thought that perhaps the caller needs to synch with the callbacks. Say, __trace_remove_event_call() can destroy the data which can be used by the callbacks. But no, this is only possible if we are going to call uprobe_unregister(), and this adds the necessary serialization.
So why? Looks like, the only reason is instance_rmdir() which can do TRACE_REG_UNREGISTER and after that destroy this ftrace_event_file? But event_trace_del_tracer() also has synchronize_sched() right after __ftrace_set_clr_event_nolock() ?
So please tell me why do we need this synchronize_sched ;) And imo this should be documented.
Oleg.
Re: probe_event_disable()->synchronize_sched()
Hi Oleg,
Quoted 4 lines · Oleg Nesterov
Namhyung, Masami,
Please look at the question below. Perhaps we discussed this before, but I can recall nothing.
I'm not sure I grok the code enough to answer your question, but...
Quoted 14 lines · Oleg Nesterov
Quoted 5 lines
Actually, I'll probably try to make the patch tomorrow. It looks simple enough, the main complication is
CONFIG_PERF. And, to keep this patch simple, I won't try to optimize (say) the TP_FLAG_TRACE-comes-first case which could avoiduprobe_apply().I regret very much I said this ;) OK, I'll probably try anyway, but...
Quoted 2 lines
Yes, I still think it would be better to change the register/unregister API first, but I do not know when I do this ;)
Quoted 8 lines
OK, we can do this later.
But it turns out that
trace_uprobe.cneeds other cleanups, and I simply can't uglify this code more without these cleanups... Starting from set/clear TP_FLAG_*. I'll recheck, but it seems that there is no reason to carefully set (say)TP_FLAG_TRACEbeforeuprobe_register()and then clear it if_register()fails. Anduprobe_dispatcher()is very ugly ifis_ret_probe(). And more. So it needs a series.
Okay, I'd like to see it. :)
Quoted 6 lines
-------------------------------------------------------------------------
And. I am puzzled by probe_event_disable()->synchronize_sched(). Why do we need it? I mean, why we can't usecall_rcu()? The comment says "synchronize with u{,ret}probe_trace_func" but it doesn't explain _why_ do we need to sync.
It looks like the code was copied from trace_kprobe.c file. But IIUC, unlike kprobes, uprobe events are always called in a process context.
Also u{,ret}probe_trace_func() call handlers under rcu_read_lock() not rcu_read_lock_sched() so I guess the synchronize_sched() can go.
Thanks,
Namhyung
Quoted 15 lines
I thought that perhaps the caller needs to synch with the callbacks. Say,
__trace_remove_event_call()can destroy the data which can be used by the callbacks. But no, this is only possible if we are going to calluprobe_unregister(), and this adds the necessary serialization.So why? Looks like, the only reason is
instance_rmdir()which can doTRACE_REG_UNREGISTERand after that destroy thisftrace_event_file? Butevent_trace_del_tracer()also hassynchronize_sched()right after__ftrace_set_clr_event_nolock()?So please tell me why do we need this
synchronize_sched;) And imo this should be documented.Oleg.
Oleg Nesterov
maintainerRe: probe_event_disable()->synchronize_sched()
Quoted 8 lines · Namhyung Kim
Quoted 5 lines · Oleg Nesterov
And. I am puzzled by probe_event_disable()->synchronize_sched(). Why do we need it? I mean, why we can't use
call_rcu()? The comment says "synchronize with u{,ret}probe_trace_func" but it doesn't explain _why_ do we need to sync.
Quoted 5 lines
It looks like the code was copied from
trace_kprobe.cfile. But IIUC, unlike kprobes, uprobe events are always called in a process context.Also u{,ret}probe_trace_func() call handlers under
rcu_read_lock()notrcu_read_lock_sched()so I guess thesynchronize_sched()can go.
Heh ;) I didn't even notice that "synchronize" and "lock" do not match. So this should be fixed anyway. But lets discuss other issues first.
Oleg.
Re: probe_event_disable()->synchronize_sched() (Was: tracing/uprobes: Revert "Support mix of ftrace and perf")
In reply to Oleg NesterovQuoted 33 lines · Oleg Nesterov
Namhyung, Masami,
Please look at the question below. Perhaps we discussed this before, but I can recall nothing.
Quoted 5 lines · Oleg Nesterov
Actually, I'll probably try to make the patch tomorrow. It looks simple enough, the main complication is
CONFIG_PERF. And, to keep this patch simple, I won't try to optimize (say) the TP_FLAG_TRACE-comes-first case which could avoiduprobe_apply().I regret very much I said this ;) OK, I'll probably try anyway, but...
Quoted 2 lines
Yes, I still think it would be better to change the register/unregister API first, but I do not know when I do this ;)
OK, we can do this later.
But it turns out that
trace_uprobe.cneeds other cleanups, and I simply can't uglify this code more without these cleanups... Starting from set/clear TP_FLAG_*. I'll recheck, but it seems that there is no reason to carefully set (say)TP_FLAG_TRACEbeforeuprobe_register()and then clear it if_register()fails. Anduprobe_dispatcher()is very ugly ifis_ret_probe(). And more. So it needs a series.-------------------------------------------------------------------------
And. I am puzzled by probe_event_disable()->synchronize_sched(). Why do we need it? I mean, why we can't usecall_rcu()? The comment says "synchronize with u{,ret}probe_trace_func" but it doesn't explain _why_ do we need to sync.
Quoted 4 lines
I thought that perhaps the caller needs to synch with the callbacks. Say,
__trace_remove_event_call()can destroy the data which can be used by the callbacks. But no, this is only possible if we are going to calluprobe_unregister(), and this adds the necessary serialization.
Hmm, similar code in the trace_kprobe.c said that trace_remove_event_call() will remove something, so it should be synchronized.
Here, I tracked down the path from trace_remove_event_call().
1) trace_remove_event_call() locks mutexes to protect event status from others, and calls probe_remove_event_call()
2) probe_remove_event_call() checks call's refcount and state of files which related to the call. If there is any enabled file or reference, it returns EBUSY.
If there is no active user of the call, it calls __trace_remove_event_call()
3) __trace_remove_event_call() calls event_remove(call) and after that it releases all objects related to the call [*1].
4) Finally, event_remove() tries to disable each file on the call and soon after that calls destroy_preds() [*2]. Here, to disable the file, it calls ftrace_event_enable_disable() and it finally calls probe_event_disable(), only if the event is *enabled*.
And as above described, probe_remove_event_call() already checked that no user enables this event. This means that nobody calls probe_event_disable() on the path from trace_remove_event_call().
Hmm, however, for [*1] and [*2], both are free event_file related objects right after disabling the event. This means those expects that calling ftrace_event_enable_disable() ensures no event handlers running. synchronize_sched makes it true, but as long as calling __trace_remove_event_call() from probe_remove_event_call(), probe_event_disable() is not called at all because the event has to be disabled when probe_remove_event_call() is called.
One possible scenario is here; someone disables an event and tries to remove it (both will be done by different syscalls). If we don't synchronize the first disabling, the event flag set disabled, but the event itself is not disabled. Thus event handler is still possible to be running somewhere when it is removed.
The other path of __trace_remove_event_call() is trace_module_remove_events() which is not related to kprobes/uprobes (Even so, there is no obvious check of that.)
Quoted 4 lines
So why? Looks like, the only reason is
instance_rmdir()which can doTRACE_REG_UNREGISTERand after that destroy thisftrace_event_file? Butevent_trace_del_tracer()also hassynchronize_sched()right after__ftrace_set_clr_event_nolock()?
I think it doesn't need to call synchronize_sched() because event_trace_del_tracer() ensures that all events are disabled (handlers are not running anymore)
Thank you,
Quoted 3 lines
So please tell me why do we need this
synchronize_sched;) And imo this should be documented.
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Research Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Re: probe_event_disable()->synchronize_sched() (Was: tracing/uprobes: Revert "Support mix of ftrace and perf")
In reply to Oleg NesterovQuoted 33 lines · Oleg Nesterov
Namhyung, Masami,
Please look at the question below. Perhaps we discussed this before, but I can recall nothing.
Quoted 5 lines · Oleg Nesterov
Actually, I'll probably try to make the patch tomorrow. It looks simple enough, the main complication is
CONFIG_PERF. And, to keep this patch simple, I won't try to optimize (say) the TP_FLAG_TRACE-comes-first case which could avoiduprobe_apply().I regret very much I said this ;) OK, I'll probably try anyway, but...
Quoted 2 lines
Yes, I still think it would be better to change the register/unregister API first, but I do not know when I do this ;)
OK, we can do this later.
But it turns out that
trace_uprobe.cneeds other cleanups, and I simply can't uglify this code more without these cleanups... Starting from set/clear TP_FLAG_*. I'll recheck, but it seems that there is no reason to carefully set (say)TP_FLAG_TRACEbeforeuprobe_register()and then clear it if_register()fails. Anduprobe_dispatcher()is very ugly ifis_ret_probe(). And more. So it needs a series.-------------------------------------------------------------------------
And. I am puzzled by probe_event_disable()->synchronize_sched(). Why do we need it? I mean, why we can't usecall_rcu()? The comment says "synchronize with u{,ret}probe_trace_func" but it doesn't explain _why_ do we need to sync.
Quoted 4 lines
I thought that perhaps the caller needs to synch with the callbacks. Say,
__trace_remove_event_call()can destroy the data which can be used by the callbacks. But no, this is only possible if we are going to calluprobe_unregister(), and this adds the necessary serialization.
Hmm, similar code in the trace_kprobe.c said that trace_remove_event_call() will remove something, so it should be synchronized.
Here, I tracked down the path from trace_remove_event_call().
1) trace_remove_event_call() locks mutexes to protect event status from others, and calls probe_remove_event_call()
2) probe_remove_event_call() checks call's refcount and state of files which related to the call. If there is any enabled file or reference, it returns EBUSY.
If there is no active user of the call, it calls __trace_remove_event_call()
3) __trace_remove_event_call() calls event_remove(call) and after that it releases all objects related to the call [*1].
4) Finally, event_remove() tries to disable each file on the call and soon after that calls destroy_preds() [*2]. Here, to disable the file, it calls ftrace_event_enable_disable() and it finally calls probe_event_disable(), only if the event is *enabled*.
And as above described, probe_remove_event_call() already checked that no user enables this event. This means that nobody calls probe_event_disable() on the path from trace_remove_event_call().
Hmm, however, for [*1] and [*2], both are free event_file related objects right after disabling the event. This means those expects that calling ftrace_event_enable_disable() ensures no event handlers running. synchronize_sched makes it true, but as long as calling __trace_remove_event_call() from probe_remove_event_call(), probe_event_disable() is not called at all because the event has to be disabled when probe_remove_event_call() is called.
One possible scenario is here; someone disables an event and tries to remove it (both will be done by different syscalls). If we don't synchronize the first disabling, the event flag set disabled, but the event itself is not disabled. Thus event handler is still possible to be running somewhere when it is removed.
The other path of __trace_remove_event_call() is trace_module_remove_events() which is not related to kprobes/uprobes (Even so, there is no obvious check of that.)
Quoted 4 lines
So why? Looks like, the only reason is
instance_rmdir()which can doTRACE_REG_UNREGISTERand after that destroy thisftrace_event_file? Butevent_trace_del_tracer()also hassynchronize_sched()right after__ftrace_set_clr_event_nolock()?
I think it doesn't need to call synchronize_sched() because event_trace_del_tracer() ensures that all events are disabled (handlers are not running anymore)
Thank you,
Quoted 3 lines
So please tell me why do we need this
synchronize_sched;) And imo this should be documented.
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Research Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Namhyung Kim
maintainerRe: probe_event_disable()->synchronize_sched()
Hi Masami,
Quoted 5 lines · Masami Hiramatsu
One possible scenario is here; someone disables an event and tries to remove it (both will be done by different syscalls). If we don't synchronize the first disabling, the event flag set disabled, but the event itself is not disabled. Thus event handler is still possible to be running somewhere when it is removed.
But, IIUC both of disable and remove path are protected by event_mutex. So one cannot see the case of disabled event flag but enabled event, no?
Thanks,
Namhyung
Re: probe_event_disable()->synchronize_sched()
Quoted 11 lines · Namhyung Kim
Hi Masami,
Quoted 5 lines · Masami Hiramatsu
One possible scenario is here; someone disables an event and tries to remove it (both will be done by different syscalls). If we don't synchronize the first disabling, the event flag set disabled, but the event itself is not disabled. Thus event handler is still possible to be running somewhere when it is removed.
But, IIUC both of disable and remove path are protected by
event_mutex. So one cannot see the case of disabled event flag but enabled event, no?
No, the flag is not protect the trace event handler itself. I meant that running handlers and the flag was not synchronized.
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Research Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Namhyung Kim
maintainerRe: probe_event_disable()->synchronize_sched()
Hi Masami,
Quoted 10 lines · Masami Hiramatsu
Quoted 9 lines · Namhyung Kim
Hi Masami,
Quoted 5 lines · Masami Hiramatsu
One possible scenario is here; someone disables an event and tries to remove it (both will be done by different syscalls). If we don't synchronize the first disabling, the event flag set disabled, but the event itself is not disabled. Thus event handler is still possible to be running somewhere when it is removed.
Quoted 5 lines
Quoted 2 lines
But, IIUC both of disable and remove path are protected by
event_mutex. So one cannot see the case of disabled event flag but enabled event, no?No, the flag is not protect the trace event handler itself. I meant that running handlers and the flag was not synchronized.
Ah, right. Thanks for explanation. :)
Thanks,
Namhyung
Oleg Nesterov
maintainerRe: probe_event_disable()->synchronize_sched() (Was: tracing/uprobes: Revert "Support mix of ftrace and perf")
In reply to Masami HiramatsuQuoted 15 lines · Masami Hiramatsu
Quoted 9 lines · Oleg Nesterov
And. I am puzzled by probe_event_disable()->synchronize_sched(). Why do we need it? I mean, why we can't use
call_rcu()? The comment says "synchronize with u{,ret}probe_trace_func" but it doesn't explain _why_ do we need to sync.I thought that perhaps the caller needs to synch with the callbacks. Say,
__trace_remove_event_call()can destroy the data which can be used by the callbacks. But no, this is only possible if we are going to calluprobe_unregister(), and this adds the necessary serialization.Hmm, similar code in the
trace_kprobe.csaid thattrace_remove_event_call()will remove something, so it should be synchronized.
Quoted 8 lines
Here, I tracked down the path from
trace_remove_event_call().1)
trace_remove_event_call()locks mutexes to protect event status from others, and callsprobe_remove_event_call()2)
probe_remove_event_call()checks call's refcount and state of files which related to the call. If there is any enabled file or reference, it returns EBUSY.
Yep. So this path is fine. uprobe_unregister() was already called (FTRACE_EVENT_FL_ENABLED is not set), there are no callbacks in flight.
Quoted 5 lines
One possible scenario is here; someone disables an event and tries to remove it (both will be done by different syscalls). If we don't synchronize the first disabling, the event flag set disabled, but the event itself is not disabled. Thus event handler is still possible to be running somewhere when it is removed.
See above. "remove" can't succed until all ftrace_event_file's are inactive. And probe_event_disable() does uprobe_unregister() in this case which (again) serializes with the callbacks itself.
Quoted 3 lines
The other path of
__trace_remove_event_call()istrace_module_remove_events()which is not related to kprobes/uprobes (Even so, there is no obvious check of that.)
Yes, uprobe can ignore modules ;)
Quoted 8 lines
Quoted 4 lines
So why? Looks like, the only reason is
instance_rmdir()which can doTRACE_REG_UNREGISTERand after that destroy thisftrace_event_file? Butevent_trace_del_tracer()also hassynchronize_sched()right after__ftrace_set_clr_event_nolock()?I think it doesn't need to call
synchronize_sched()becauseevent_trace_del_tracer()ensures that all events are disabled (handlers are not running anymore)
Not really, afaics... Well yes, it calls __ftrace_set_clr_event_nolock(), but this can race with the callbacks; this doesn't necessary call uprobe_unregister() because there can be other active ftrace_event_file's. So we need to synchronize before we start to destroy the data.
So do you agree that we can remove that synchronize_sched() in trace_uprobe.c and replace it with call_rcu?
Hmm. Off-topic, but it seems that instance_rmdir() leaks the memory? Say, file->filter?
Oleg.
Oleg Nesterov
maintainer__trace_remove_event_dirs() leaks file->filter ? (Was: probe_event_disable()->synchronize_sched())
Quoted 3 lines · Oleg Nesterov
Hmm. Off-topic, but it seems that
instance_rmdir()leaks the memory? Say,file->filter?
Perhaps I am totally confused, but don't we need something like the patch below? I'll try to recheck later...
Better yet, we can probably move destroy_preds() from event_remove() to remove_event_file_dir()... not sure, need to recheck.
Oleg.
kernel/trace/trace_events.c +1 -0
@@ -470,6 +470,7 @@ static void remove_event_file_dir(struct ftrace_event_file *file)list_del (&file->list);remove_subsystem (file->system); +destroy_file_preds (file);kmem_cache_free (file_cachep, file); }
Re: __trace_remove_event_dirs() leaks file->filter ? (Was: probe_event_disable()->synchronize_sched())
Quoted 10 lines · Oleg Nesterov
Quoted 3 lines · Oleg Nesterov
Hmm. Off-topic, but it seems that
instance_rmdir()leaks the memory? Say,file->filter?Perhaps I am totally confused, but don't we need something like the patch below? I'll try to recheck later...
Better yet, we can probably move
destroy_preds()fromevent_remove()toremove_event_file_dir()... not sure, need to recheck.
Ah, yes, it seems event_remove releases preds, and remove_event_file_dir() called from event_trace_del_tracer() doesn't release it.
BTW, with following patch, we'd better remove destroy_preds() from event_remove() and add destroy_call_preds() at the very last of the function.
Thank you,
Quoted 15 lines
Oleg.
kernel/trace/trace_events.c +1
-0@@ -470,6 +470,7 @@ static void remove_event_file_dir(struct ftrace_event_file *file)list_del (&file->list);remove_subsystem (file->system); +destroy_file_preds (file);kmem_cache_free (file_cachep, file); }
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Research Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Oleg Nesterov
maintainerRe: __trace_remove_event_dirs() leaks file->filter ? (Was: probe_event_disable()->synchronize_sched())
Quoted 13 lines · Masami Hiramatsu
Quoted 10 lines · Oleg Nesterov
Quoted 3 lines · Oleg Nesterov
Hmm. Off-topic, but it seems that
instance_rmdir()leaks the memory? Say,file->filter?Perhaps I am totally confused, but don't we need something like the patch below? I'll try to recheck later...
Better yet, we can probably move
destroy_preds()fromevent_remove()toremove_event_file_dir()... not sure, need to recheck.
Quoted 6 lines
Ah, yes, it seems
event_removereleases preds, andremove_event_file_dir()called fromevent_trace_del_tracer()doesn't release it.BTW, with following patch, we'd better remove
destroy_preds()fromevent_remove()and adddestroy_call_preds()at the very last of the function.
Yes, please see "Better yet" above. And probably we can simply remove destroy_preds() after that.
But I still need to reccheck, didn't have time today. And you know what? call->filter logic looks broken too ;)
Oleg.
Re: probe_event_disable()->synchronize_sched() (Was: tracing/uprobes: Revert "Support mix of ftrace and perf")
In reply to Oleg NesterovQuoted 9 lines · Oleg Nesterov
Quoted 5 lines
One possible scenario is here; someone disables an event and tries to remove it (both will be done by different syscalls). If we don't synchronize the first disabling, the event flag set disabled, but the event itself is not disabled. Thus event handler is still possible to be running somewhere when it is removed.
See above. "remove" can't succed until all ftrace_event_file's are inactive. And
probe_event_disable()doesuprobe_unregister()in this case which (again) serializes with the callbacks itself.
Ah, I see. kprobes uses disable_kprobe() instead of unregister, and that is not serialized.
Quoted 15 lines
Quoted 3 lines
The other path of
__trace_remove_event_call()istrace_module_remove_events()which is not related to kprobes/uprobes (Even so, there is no obvious check of that.)Yes, uprobe can ignore modules ;)
Quoted 8 lines
Quoted 4 lines
So why? Looks like, the only reason is
instance_rmdir()which can doTRACE_REG_UNREGISTERand after that destroy thisftrace_event_file? Butevent_trace_del_tracer()also hassynchronize_sched()right after__ftrace_set_clr_event_nolock()?I think it doesn't need to call
synchronize_sched()becauseevent_trace_del_tracer()ensures that all events are disabled (handlers are not running anymore)
Quoted 7 lines
Not really, afaics... Well yes, it calls
__ftrace_set_clr_event_nolock(), but this can race with the callbacks; this doesn't necessary calluprobe_unregister()because there can be other active ftrace_event_file's. So we need to synchronize before we start to destroy the data.So do you agree that we can remove that
synchronize_sched()intrace_uprobe.cand replace it withcall_rcu?
Yes for uprobes, kprobes still need it. :)
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Research Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Re: [PATCH 1/4] tracing/uprobes: Revert "Support mix of ftrace and perf"
In reply to Oleg NesterovQuoted 9 lines · Oleg Nesterov
This reverts commit
43fe98913c9f67e3b523615ee3316f9520a623e0.This patch is very wrong. Firstly, this change leads to unbalanced
uprobe_unregister(). Just for example,# perf probe -x /lib/libc.so.6 syscall # echo 1 >> /sys/kernel/debug/tracing/events/probe_libc/enable # perf record -e probe_libc:syscall whatever
Quoted 8 lines
after that uprobe is dead (unregistered) but the user of ftrace/perf can't know this, and it looks as if nobody hits this probe.
This would be easy to fix, but there are other reasons why it is not simple to mix ftrace and perf. If nothing else, they can't share the same ->consumer.filter. This is fixable too, but probably we need to fix the poorly designed
uprobe_register()interface first. At least "register" and "apply" should be clearly separated.
Hm, it should be a uprobes original issue. it's different from kprobes.
Thank you,
Quoted 36 lines
Cc [email protected] # v3.14Signed-off-by Oleg Nesterov <[email protected]>--- kernel/trace/trace_uprobe.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)kernel/trace/trace_uprobe.c +8
-1@@ -893,6 +893,9 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file,int ret;if (file) { +if (tu->tp.flags &TP_FLAG_PROFILE ) +return -EINTR ; + link =kmalloc (sizeof (*link),GFP_KERNEL );if (!link)return -ENOMEM ;@@ -901,8 +904,12 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file,list_add_tail_rcu (&link->list, &tu->tp.files); tu->tp.flags |=TP_FLAG_TRACE ; - }else + }else { +if (tu->tp.flags &TP_FLAG_TRACE ) +return -EINTR ; + tu->tp.flags |=TP_FLAG_PROFILE ; + } ret =uprobe_buffer_enable ();if (ret <0 )
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Research Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Re: [PATCH 1/4] tracing/uprobes: Revert "Support mix of ftrace and perf"
In reply to Oleg NesterovQuoted 12 lines · Oleg Nesterov
This reverts commit
43fe98913c9f67e3b523615ee3316f9520a623e0.This patch is very wrong. Firstly, this change leads to unbalanced
uprobe_unregister(). Just for example,# perf probe -x /lib/libc.so.6 syscall # echo 1 >> /sys/kernel/debug/tracing/events/probe_libc/enable # perf record -e probe_libc:syscall whateverafter that uprobe is dead (unregistered) but the user of ftrace/perf can't know this, and it looks as if nobody hits this probe.
Quoted 8 lines
This would be easy to fix, but there are other reasons why it is not simple to mix ftrace and perf. If nothing else, they can't share the same ->consumer.filter. This is fixable too, but probably we need to fix the poorly designed
uprobe_register()interface first. At least "register" and "apply" should be clearly separated.Cc [email protected] # v3.14Signed-off-by Oleg Nesterov <[email protected]>
Signature · 2 lines
Thanks and Regards Srikar Dronamraju
Oleg Nesterov
maintainerPATCH 2/4 uprobes: Change unregister/apply to WARN() if uprobe/consumer is gone
In reply to Oleg NesterovAdd WARN_ON's into uprobe_unregister() and uprobe_apply() to ensure that nobody tries to play with the dead uprobe/consumer. This helps to catch the bugs like the one fixed by the previous patch.
In the longer term we should fix this poorly designed interface. uprobe_register() should return "struct uprobe *" which should be passed to apply/unregister. Plus other semantic changes, see the changelog in commit 41ccba029e94.
--- kernel/events/uprobes.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
kernel/events/uprobes.c +3 -3
@@ -846,7 +846,7 @@ static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *u {int err; -if (!consumer_del (uprobe, uc))/* WARN? */ +if (WARN_ON (!consumer_del (uprobe, uc)))return ; err =register_for_each_vma (uprobe,NULL );
@@ -927,7 +927,7 @@ int uprobe_apply(struct inode *inode, loff_t offset,int ret = -ENOENT ; uprobe =find_uprobe (inode, offset); -if (!uprobe) +if (WARN_ON (!uprobe))return ret;down_write (&uprobe->register_rwsem);
@@ -952,7 +952,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumestruct uprobe *uprobe; uprobe =find_uprobe (inode, offset); -if (!uprobe) +if (WARN_ON (!uprobe))return ;down_write (&uprobe->register_rwsem);
Signature · 1 line
1.5.5.1
Re: [PATCH 2/4] uprobes: Change unregister/apply to WARN() if uprobe/consumer is gone
Quoted 10 lines · Oleg Nesterov
Add WARN_ON's into
uprobe_unregister()anduprobe_apply()to ensure that nobody tries to play with the dead uprobe/consumer. This helps to catch the bugs like the one fixed by the previous patch.In the longer term we should fix this poorly designed interface.
uprobe_register()should return "struct uprobe *" which should be passed to apply/unregister. Plus other semantic changes, see the changelog in commit41ccba029e94.Signed-off-by Oleg Nesterov <[email protected]>
Thanks,
Namhyung
Quoted 35 lines
--- kernel/events/uprobes.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)kernel/events/uprobes.c +3
-3@@ -846,7 +846,7 @@ static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *u {int err; -if (!consumer_del (uprobe, uc))/* WARN? */ +if (WARN_ON (!consumer_del (uprobe, uc)))return ; err =register_for_each_vma (uprobe,NULL );@@ -927,7 +927,7 @@ int uprobe_apply(struct inode *inode, loff_t offset,int ret = -ENOENT ; uprobe =find_uprobe (inode, offset); -if (!uprobe) +if (WARN_ON (!uprobe))return ret;down_write (&uprobe->register_rwsem);@@ -952,7 +952,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumestruct uprobe *uprobe; uprobe =find_uprobe (inode, offset); -if (!uprobe) +if (WARN_ON (!uprobe))return ;down_write (&uprobe->register_rwsem);
Re: [PATCH 2/4] uprobes: Change unregister/apply to WARN() if uprobe/consumer is gone
In reply to Oleg NesterovQuoted 10 lines · Oleg Nesterov
Add WARN_ON's into
uprobe_unregister()anduprobe_apply()to ensure that nobody tries to play with the dead uprobe/consumer. This helps to catch the bugs like the one fixed by the previous patch.In the longer term we should fix this poorly designed interface.
uprobe_register()should return "struct uprobe *" which should be passed to apply/unregister. Plus other semantic changes, see the changelog in commit41ccba029e94.Signed-off-by Oleg Nesterov <[email protected]>
Signature · 2 lines
Thanks and Regards Srikar Dronamraju
Oleg Nesterov
maintainerPATCH 3/4 tracing/uprobes: Kill the bogus UPROBE_HANDLER_REMOVE code in uprobe_dispatcher()
In reply to Oleg NesterovI do not know why dd9fa555d7bb "tracing/uprobes: Move argument fetching to uprobe_dispatcher()" added the UPROBE_HANDLER_REMOVE, but it looks wrong.
OK, perhaps it makes sense to avoid store_trace_args() if the tracee is nacked by uprobe_perf_filter(). But then we should kill the same code in uprobe_perf_func() and unify the TRACE/PROFILE filtering (we need to do this anyway to mix perf/ftrace). Until then this code actually adds the pessimization because uprobe_perf_filter() will be called twice and return T in likely case.
--- kernel/trace/trace_uprobe.c | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-)
kernel/trace/trace_uprobe.c +0 -6
@@ -1208,12 +1208,6 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs) current->utask->vaddr = (unsigned long ) &udd; -#ifdef CONFIG_PERF_EVENTS -if ((tu->tp.flags &TP_FLAG_TRACE ) ==0 && - !uprobe_perf_filter (&tu->consumer,0 , current->mm)) -return UPROBE_HANDLER_REMOVE ; -#endif -if (WARN_ON_ONCE (!uprobe_cpu_buffer))return 0 ;
Signature · 1 line
1.5.5.1
Re: [PATCH 3/4] tracing/uprobes: Kill the bogus UPROBE_HANDLER_REMOVE code in uprobe_dispatcher()
Quoted 10 lines · Oleg Nesterov
I do not know why
dd9fa555d7bb"tracing/uprobes: Move argument fetching touprobe_dispatcher()" added theUPROBE_HANDLER_REMOVE, but it looks wrong.OK, perhaps it makes sense to avoid
store_trace_args()if the tracee is nacked byuprobe_perf_filter(). But then we should kill the same code inuprobe_perf_func()and unify the TRACE/PROFILE filtering (we need to do this anyway to mix perf/ftrace). Until then this code actually adds the pessimization becauseuprobe_perf_filter()will be called twice and return T in likely case.
Right, I wanted to avoid to call the store_trace_args() which might be costly if possible. But it seems not necessary since it doesn't get called once handler returns UPROBE_HANDLER_REMOVE. And we need to fix the filtering first..
So I'm okay with removing this "pessimization". :)
Thanks,
Namhyung
Quoted 22 lines
Signed-off-by Oleg Nesterov <[email protected]>--- kernel/trace/trace_uprobe.c | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-)kernel/trace/trace_uprobe.c +0
-6@@ -1208,12 +1208,6 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs) current->utask->vaddr = (unsigned long ) &udd; -#ifdef CONFIG_PERF_EVENTS -if ((tu->tp.flags &TP_FLAG_TRACE ) ==0 && - !uprobe_perf_filter (&tu->consumer,0 , current->mm)) -return UPROBE_HANDLER_REMOVE ; -#endif -if (WARN_ON_ONCE (!uprobe_cpu_buffer))return 0 ;
Re: [PATCH 3/4] tracing/uprobes: Kill the bogus UPROBE_HANDLER_REMOVE code in uprobe_dispatcher()
In reply to Oleg NesterovQuoted 4 lines · Oleg Nesterov
I do not know why
dd9fa555d7bb"tracing/uprobes: Move argument fetching touprobe_dispatcher()" added theUPROBE_HANDLER_REMOVE, but it looks wrong.
Quoted 8 lines
OK, perhaps it makes sense to avoid
store_trace_args()if the tracee is nacked byuprobe_perf_filter(). But then we should kill the same code inuprobe_perf_func()and unify the TRACE/PROFILE filtering (we need to do this anyway to mix perf/ftrace). Until then this code actually adds the pessimization becauseuprobe_perf_filter()will be called twice and return T in likely case.Signed-off-by Oleg Nesterov <[email protected]>
Signature · 2 lines
Thanks and Regards Srikar Dronamraju
Oleg Nesterov
maintainerPATCH 4/4 tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
In reply to Oleg NesterovThe usage of uprobe_buffer_enable() added by dcad1a20 is very wrong,
1. uprobe_buffer_enable() and uprobe_buffer_disable() are not balanced, _enable() should be called only if !enabled.
2. If uprobe_buffer_enable() fails probe_event_enable() should clear tp.flags and free event_file_link.
3. If uprobe_register() fails it should do uprobe_buffer_disable().
--- kernel/trace/trace_uprobe.c | 31 +++++++++++++++++++------------ 1 files changed, 19 insertions(+), 12 deletions(-)
kernel/trace/trace_uprobe.c +19 -12
@@ -911,26 +911,33 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, tu->tp.flags |=TP_FLAG_PROFILE ; } - ret =uprobe_buffer_enable (); -if (ret <0 ) -return ret; -WARN_ON (!uprobe_filter_is_empty (&tu->filter));if (enabled)return 0 ; + ret =uprobe_buffer_enable (); +if (ret) + goto err_flags; + tu->consumer.filter = filter; ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); -if (ret) { -if (file) { -list_del (&link->list); -kfree (link); - tu->tp.flags &= ~TP_FLAG_TRACE ; - }else - tu->tp.flags &= ~TP_FLAG_PROFILE ; - } +if (ret) + goto err_buffer; +return 0 ; + + err_buffer: +uprobe_buffer_disable (); + + err_flags: +if (file) { +list_del (&link->list); +kfree (link); + tu->tp.flags &= ~TP_FLAG_TRACE ; + }else { + tu->tp.flags &= ~TP_FLAG_PROFILE ; + }return ret; }
Signature · 1 line
1.5.5.1
Re: [PATCH 4/4] tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
Quoted 11 lines · Oleg Nesterov
The usage of
uprobe_buffer_enable()added bydcad1a20is very wrong,1.
uprobe_buffer_enable()anduprobe_buffer_disable()are not balanced,_enable()should be called only if !enabled.2. If
uprobe_buffer_enable()failsprobe_event_enable()should clear tp.flags and freeevent_file_link.3. If
uprobe_register()fails it should douprobe_buffer_disable().Signed-off-by Oleg Nesterov <[email protected]>
Thanks for the fix.
Quoted 53 lines
--- kernel/trace/trace_uprobe.c | 31 +++++++++++++++++++------------ 1 files changed, 19 insertions(+), 12 deletions(-)kernel/trace/trace_uprobe.c +19
-12@@ -911,26 +911,33 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, tu->tp.flags |=TP_FLAG_PROFILE ; } - ret =uprobe_buffer_enable (); -if (ret <0 ) -return ret; -WARN_ON (!uprobe_filter_is_empty (&tu->filter));if (enabled)return 0 ; + ret =uprobe_buffer_enable (); +if (ret) + goto err_flags; + tu->consumer.filter = filter; ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); -if (ret) { -if (file) { -list_del (&link->list); -kfree (link); - tu->tp.flags &= ~TP_FLAG_TRACE ; - }else - tu->tp.flags &= ~TP_FLAG_PROFILE ; - } +if (ret) + goto err_buffer; +return 0 ; + + err_buffer: +uprobe_buffer_disable (); + + err_flags: +if (file) { +list_del (&link->list); +kfree (link); + tu->tp.flags &= ~TP_FLAG_TRACE ; + }else { + tu->tp.flags &= ~TP_FLAG_PROFILE ; + }return ret; }
Re: [PATCH 4/4] tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
In reply to Oleg NesterovQuoted 9 lines · Oleg Nesterov
The usage of
uprobe_buffer_enable()added bydcad1a20is very wrong,1.
uprobe_buffer_enable()anduprobe_buffer_disable()are not balanced,_enable()should be called only if !enabled.2. If
uprobe_buffer_enable()failsprobe_event_enable()should clear tp.flags and freeevent_file_link.3. If
uprobe_register()fails it should douprobe_buffer_disable().
Looks good to me ;)
Thanks,
Quoted 57 lines
Signed-off-by Oleg Nesterov <[email protected]>--- kernel/trace/trace_uprobe.c | 31 +++++++++++++++++++------------ 1 files changed, 19 insertions(+), 12 deletions(-)kernel/trace/trace_uprobe.c +19
-12@@ -911,26 +911,33 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, tu->tp.flags |=TP_FLAG_PROFILE ; } - ret =uprobe_buffer_enable (); -if (ret <0 ) -return ret; -WARN_ON (!uprobe_filter_is_empty (&tu->filter));if (enabled)return 0 ; + ret =uprobe_buffer_enable (); +if (ret) + goto err_flags; + tu->consumer.filter = filter; ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); -if (ret) { -if (file) { -list_del (&link->list); -kfree (link); - tu->tp.flags &= ~TP_FLAG_TRACE ; - }else - tu->tp.flags &= ~TP_FLAG_PROFILE ; - } +if (ret) + goto err_buffer; +return 0 ; + + err_buffer: +uprobe_buffer_disable (); + + err_flags: +if (file) { +list_del (&link->list); +kfree (link); + tu->tp.flags &= ~TP_FLAG_TRACE ; + }else { + tu->tp.flags &= ~TP_FLAG_PROFILE ; + }return ret; }
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Research Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Re: [PATCH 4/4] tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
In reply to Oleg NesterovQuoted 11 lines
The usage of
uprobe_buffer_enable()added bydcad1a20is very wrong,1.
uprobe_buffer_enable()anduprobe_buffer_disable()are not balanced,_enable()should be called only if !enabled.2. If
uprobe_buffer_enable()failsprobe_event_enable()should clear tp.flags and freeevent_file_link.3. If
uprobe_register()fails it should douprobe_buffer_disable().Signed-off-by Oleg Nesterov <[email protected]>
(one nit .. )
Quoted 12 lines
kernel/trace/trace_uprobe.c +4
-6+ ret =uprobe_buffer_enable (); +if (ret) + goto err_flags; + tu->consumer.filter = filter; ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); -if (ret) { -if (file) { -list_del (&link->list); -kfree (link); - tu->tp.flags &= ~TP_FLAG_TRACE ; - }else
kernel/trace/trace_uprobe.c probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, · line 932
Quoted 10 lines
kernel/trace/trace_uprobe.c +7
-2- tu->tp.flags &= ~TP_FLAG_PROFILE ; - } +if (ret) + goto err_buffer; +return 0 ; + + err_buffer: +uprobe_buffer_disable (); +
How about avoiding err_buffer label?
+ if (!ret)
+ return 0;
+ uprobe_buffer_disable();
+
Quoted 7 lines
+
err_flags:kernel/trace/trace_uprobe.c +2
-0+if (file) { +list_del (&link->list);Signature · 2 lines
-- 1.5.5.1
Signature · 2 lines
Thanks and Regards Srikar Dronamraju
Steven Rostedt
maintainerRe: [PATCH 4/4] tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
Quoted 28 lines · On Mon, 30 Jun 2014 22:34:09 +0530 Srikar Dronamraju…
(one nit .. )
Quoted 12 lines
kernel/trace/trace_uprobe.c +4
-6+ ret =uprobe_buffer_enable (); +if (ret) + goto err_flags; + tu->consumer.filter = filter; ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); -if (ret) { -if (file) { -list_del (&link->list); -kfree (link); - tu->tp.flags &= ~TP_FLAG_TRACE ; - }else kernel/trace/trace_uprobe.c probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, · line 932
Quoted 10 lines
kernel/trace/trace_uprobe.c +7
-2- tu->tp.flags &= ~TP_FLAG_PROFILE ; - } +if (ret) + goto err_buffer; +return 0 ; + + err_buffer: +uprobe_buffer_disable (); +How about avoiding
err_bufferlabel?
kernel/trace/trace_uprobe.c probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, · line 932
Quoted 5 lines
kernel/trace/trace_uprobe.c +4
-0+if (!ret) +return 0 ; +uprobe_buffer_disable (); +
Oleg, you OK with this update?
I can kill my tests and restart with this update. Or you can resend this patch. Or we can just push it as is, and have this be a patch that get's queued as a cleanup for 3.17?
-- Steve
Quoted 9 lines
Quoted 8 lines
+
err_flags:kernel/trace/trace_uprobe.c +2
-0+if (file) { +list_del (&link->list);Signature · 2 lines
-- 1.5.5.1
Oleg Nesterov
maintainerRe: [PATCH 4/4] tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
Quoted 23 lines · Steven Rostedt
Quoted 11 lines · On Mon, 30 Jun 2014 22:34:09 +0530 Srikar Dronamraju…
kernel/trace/trace_uprobe.c probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, · line 932
Quoted 8 lines
kernel/trace/trace_uprobe.c +7
-0+if (ret) + goto err_buffer; +return 0 ; + + err_buffer: +uprobe_buffer_disable (); +How about avoiding
err_bufferlabel?kernel/trace/trace_uprobe.c probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, · line 932
Quoted 5 lines
kernel/trace/trace_uprobe.c +4
-0+if (!ret) +return 0 ; +uprobe_buffer_disable (); +Oleg, you OK with this update?
Quoted 3 lines
I can kill my tests and restart with this update. Or you can resend this patch. Or we can just push it as is, and have this be a patch that get's queued as a cleanup for 3.17?
Well, if you too think that this change can make the code cleaner I should probably make it ;)
But, to me
err = init_1(); if (err) goto err_1; err = init_2(); if (err) goto err_2; return 0; err_2: cleanup_2(); err_1: cleanup_1();
looks better than
err = init_1(); if (err) goto err_1; err = init_2(); if (!err) return 0; cleanup_2(); err_1: cleanup_1();
just because the 1st variant is more symmetrical. And in fact it is more flexible, we might add init_3/etc.
But I won't insist, this is subjective. So please let me know if you still think it would be better to add this change, I'll send v2.
Oleg.
Steven Rostedt
maintainerRe: [PATCH 4/4] tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
Quoted 2 lines · On Mon, 30 Jun 2014 19:58:36 +0200 Oleg Nesterov <[email protected]> wrote:
But I won't insist, this is subjective. So please let me know if you still think it would be better to add this change, I'll send v2.
Don't bother. I didn't look at the patch in context to make that reply. I think your original patch looks better than the alternative. I'll keep it as is.
Thanks,
-- Steve
Oleg Nesterov
maintainerRe: [PATCH 4/4] tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
In reply to Srikar DronamrajuQuoted 6 lines · Srikar Dronamraju
Quoted 6 lines
The usage of
uprobe_buffer_enable()added bydcad1a20is very wrong,1.
uprobe_buffer_enable()anduprobe_buffer_disable()are not balanced,_enable()should be called only if !enabled.
Quoted 8 lines
Quoted 6 lines
2. If
uprobe_buffer_enable()failsprobe_event_enable()should clear tp.flags and freeevent_file_link.3. If
uprobe_register()fails it should douprobe_buffer_disable().Signed-off-by Oleg Nesterov <[email protected]>
Thanks!
Quoted 26 lines
(one nit .. )
Quoted 12 lines
kernel/trace/trace_uprobe.c +4
-6+ ret =uprobe_buffer_enable (); +if (ret) + goto err_flags; + tu->consumer.filter = filter; ret =uprobe_register (tu->inode, tu->offset, &tu->consumer); -if (ret) { -if (file) { -list_del (&link->list); -kfree (link); - tu->tp.flags &= ~TP_FLAG_TRACE ; - }else kernel/trace/trace_uprobe.c probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, · line 932
Quoted 10 lines
kernel/trace/trace_uprobe.c +7
-2- tu->tp.flags &= ~TP_FLAG_PROFILE ; - } +if (ret) + goto err_buffer; +return 0 ; + + err_buffer: +uprobe_buffer_disable (); +How about avoiding
err_bufferlabel?
kernel/trace/trace_uprobe.c probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, · line 932
Quoted 5 lines
kernel/trace/trace_uprobe.c +4
-0+if (!ret) +return 0 ; +uprobe_buffer_disable (); +
Well, I do not really mind. But to me it looks more consistent this way, if-something-fail-goto-err_label.
IOW, I think that the code should either not use err-labels, or always use them like above.
Besides, perhaps we will add "if (file) uprobe_apply()" after _register() to mix perf/ftrace, then we will need to change this "if (!ret)" code again.
Oleg.
Steven Rostedt
maintainerRe: [PATCH 4/4] tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
Quoted 5 lines · On Mon, 30 Jun 2014 19:50:25 +0200 Oleg Nesterov <[email protected]> wrote:
Well, I do not really mind. But to me it looks more consistent this way, if-something-fail-goto-err_label.
IOW, I think that the code should either not use err-labels, or always use them like above.
Ah I missed the other error labels. Yeah, we should keep the patch as is to be consistent (also it means I don't need to restart a test that's already been running for hours).
-- Steve
Quoted 5 lines
Besides, perhaps we will add "if (file)
uprobe_apply()" after_register()to mix perf/ftrace, then we will need to change this "if (!ret)" code again.Oleg.
Steven Rostedt
maintainerQuoted 9 lines · On Fri, 27 Jun 2014 19:01:16 +0200 Oleg Nesterov <[email protected]> wrote:
Hello,
It took me several hours to realize that the strange bug I hit was caused by the change I have nacked in the past ;)
But it appears that I should take the blame. I was cc'ed, but I missed that email or forgot to reply, so another attempt to push this "trivial" change was successful.
Quoted 7 lines
I think that 1/4 should go to stable. 2-4 are "while at it" fixes.
Oleg.
kernel/events/uprobes.c | 6 ++-- kernel/trace/trace_uprobe.c | 46 +++++++++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 22 deletions(-)
I pulled these into my urgent branch and I'm testing them now.
Thanks Oleg!
-- Steve