Commit 110bf2b7 authored by Steven Rostedt's avatar Steven Rostedt Committed by Steven Rostedt

tracing: add protection around module events unload

When reading the trace buffer, there is a race that when a module
is unloaded it removes events that is stilled referenced in the buffers.
This patch adds the protection around the unloading of the events
from modules and the reading of the trace buffers.
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 725c624a
...@@ -1050,12 +1050,13 @@ static void trace_module_remove_events(struct module *mod) ...@@ -1050,12 +1050,13 @@ static void trace_module_remove_events(struct module *mod)
struct ftrace_event_call *call, *p; struct ftrace_event_call *call, *p;
bool found = false; bool found = false;
down_write(&trace_event_mutex);
list_for_each_entry_safe(call, p, &ftrace_events, list) { list_for_each_entry_safe(call, p, &ftrace_events, list) {
if (call->mod == mod) { if (call->mod == mod) {
found = true; found = true;
ftrace_event_enable_disable(call, 0); ftrace_event_enable_disable(call, 0);
if (call->event) if (call->event)
unregister_ftrace_event(call->event); __unregister_ftrace_event(call->event);
debugfs_remove_recursive(call->dir); debugfs_remove_recursive(call->dir);
list_del(&call->list); list_del(&call->list);
trace_destroy_fields(call); trace_destroy_fields(call);
...@@ -1079,6 +1080,7 @@ static void trace_module_remove_events(struct module *mod) ...@@ -1079,6 +1080,7 @@ static void trace_module_remove_events(struct module *mod)
*/ */
if (found) if (found)
tracing_reset_current_online_cpus(); tracing_reset_current_online_cpus();
up_write(&trace_event_mutex);
} }
static int trace_module_notify(struct notifier_block *self, static int trace_module_notify(struct notifier_block *self,
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
/* must be a power of 2 */ /* must be a power of 2 */
#define EVENT_HASHSIZE 128 #define EVENT_HASHSIZE 128
static DECLARE_RWSEM(trace_event_mutex); DECLARE_RWSEM(trace_event_mutex);
DEFINE_PER_CPU(struct trace_seq, ftrace_event_seq); DEFINE_PER_CPU(struct trace_seq, ftrace_event_seq);
EXPORT_PER_CPU_SYMBOL(ftrace_event_seq); EXPORT_PER_CPU_SYMBOL(ftrace_event_seq);
...@@ -702,6 +702,16 @@ int register_ftrace_event(struct trace_event *event) ...@@ -702,6 +702,16 @@ int register_ftrace_event(struct trace_event *event)
} }
EXPORT_SYMBOL_GPL(register_ftrace_event); EXPORT_SYMBOL_GPL(register_ftrace_event);
/*
* Used by module code with the trace_event_mutex held for write.
*/
int __unregister_ftrace_event(struct trace_event *event)
{
hlist_del(&event->node);
list_del(&event->list);
return 0;
}
/** /**
* unregister_ftrace_event - remove a no longer used event * unregister_ftrace_event - remove a no longer used event
* @event: the event to remove * @event: the event to remove
...@@ -709,8 +719,7 @@ EXPORT_SYMBOL_GPL(register_ftrace_event); ...@@ -709,8 +719,7 @@ EXPORT_SYMBOL_GPL(register_ftrace_event);
int unregister_ftrace_event(struct trace_event *event) int unregister_ftrace_event(struct trace_event *event)
{ {
down_write(&trace_event_mutex); down_write(&trace_event_mutex);
hlist_del(&event->node); __unregister_ftrace_event(event);
list_del(&event->list);
up_write(&trace_event_mutex); up_write(&trace_event_mutex);
return 0; return 0;
......
...@@ -27,6 +27,10 @@ extern struct trace_event *ftrace_find_event(int type); ...@@ -27,6 +27,10 @@ extern struct trace_event *ftrace_find_event(int type);
extern enum print_line_t trace_nop_print(struct trace_iterator *iter, extern enum print_line_t trace_nop_print(struct trace_iterator *iter,
int flags); int flags);
/* used by module unregistering */
extern int __unregister_ftrace_event(struct trace_event *event);
extern struct rw_semaphore trace_event_mutex;
#define MAX_MEMHEX_BYTES 8 #define MAX_MEMHEX_BYTES 8
#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1) #define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment