tracing: Have dynamic events have a ref counter
As dynamic events are not created by modules, if something is attached to one, calling "try_module_get()" on its "mod" field, is not going to keep the dynamic event from going away. Since dynamic events do not need the "mod" pointer of the event structure, make a union out of it in order to save memory (there's one structure for each of the thousand+ events in the kernel), and have any event with the DYNAMIC flag set to use a ref counter instead. Link: https://lore.kernel.org/linux-trace-devel/20210813004448.51c7de69ce432d338f4d226b@kernel.org/ Link: https://lkml.kernel.org/r/20210817035027.174869074@goodmis.org Suggested-by: Masami Hiramatsu <mhiramat@kernel.org> Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
@ -13,11 +13,49 @@
|
||||
#include <linux/tracefs.h>
|
||||
|
||||
#include "trace.h"
|
||||
#include "trace_output.h" /* for trace_event_sem */
|
||||
#include "trace_dynevent.h"
|
||||
|
||||
static DEFINE_MUTEX(dyn_event_ops_mutex);
|
||||
static LIST_HEAD(dyn_event_ops_list);
|
||||
|
||||
bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call)
|
||||
{
|
||||
struct trace_event_call *call;
|
||||
bool ret = false;
|
||||
|
||||
if (WARN_ON_ONCE(!(dyn_call->flags & TRACE_EVENT_FL_DYNAMIC)))
|
||||
return false;
|
||||
|
||||
down_read(&trace_event_sem);
|
||||
list_for_each_entry(call, &ftrace_events, list) {
|
||||
if (call == dyn_call) {
|
||||
atomic_inc(&dyn_call->refcnt);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
up_read(&trace_event_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void trace_event_dyn_put_ref(struct trace_event_call *call)
|
||||
{
|
||||
if (WARN_ON_ONCE(!(call->flags & TRACE_EVENT_FL_DYNAMIC)))
|
||||
return;
|
||||
|
||||
if (WARN_ON_ONCE(atomic_read(&call->refcnt) <= 0)) {
|
||||
atomic_set(&call->refcnt, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_dec(&call->refcnt);
|
||||
}
|
||||
|
||||
bool trace_event_dyn_busy(struct trace_event_call *call)
|
||||
{
|
||||
return atomic_read(&call->refcnt) != 0;
|
||||
}
|
||||
|
||||
int dyn_event_register(struct dyn_event_operations *ops)
|
||||
{
|
||||
if (!ops || !ops->create || !ops->show || !ops->is_busy ||
|
||||
|
Reference in New Issue
Block a user