Skip to content

Commit

Permalink
tracing: Add trace_get/put_event_file()
Browse files Browse the repository at this point in the history
Add a function to get an event file and prevent it from going away on
module or instance removal.

trace_get_event_file() will find an event file in a given instance (if
instance is NULL, it assumes the top trace array) and return it,
pinning the instance's trace array as well as the event's module, if
applicable, so they won't go away while in use.

trace_put_event_file() does the matching release.

Link: http://lkml.kernel.org/r/bb31ac4bdda168d5ed3c4b5f5a4c8f633e8d9118.1580323897.git.zanussi@kernel.org

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Tom Zanussi <zanussi@kernel.org>
[ Moved trace_array_put() to end of trace_put_event_file() ]
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
  • Loading branch information
Tom Zanussi authored and Steven Rostedt (VMware) committed Jan 30, 2020
1 parent 89c95fc commit e3e2a2c
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 0 deletions.
5 changes: 5 additions & 0 deletions include/linux/trace_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,11 @@ enum {
EVENT_FILE_FL_WAS_ENABLED_BIT,
};

extern struct trace_event_file *trace_get_event_file(const char *instance,
const char *system,
const char *event);
extern void trace_put_event_file(struct trace_event_file *file);

/*
* Event file flags:
* ENABLED - The event is enabled
Expand Down
85 changes: 85 additions & 0 deletions kernel/trace/trace_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -2536,6 +2536,91 @@ find_event_file(struct trace_array *tr, const char *system, const char *event)
return file;
}

/**
* trace_get_event_file - Find and return a trace event file
* @instance: The name of the trace instance containing the event
* @system: The name of the system containing the event
* @event: The name of the event
*
* Return a trace event file given the trace instance name, trace
* system, and trace event name. If the instance name is NULL, it
* refers to the top-level trace array.
*
* This function will look it up and return it if found, after calling
* trace_array_get() to prevent the instance from going away, and
* increment the event's module refcount to prevent it from being
* removed.
*
* To release the file, call trace_put_event_file(), which will call
* trace_array_put() and decrement the event's module refcount.
*
* Return: The trace event on success, ERR_PTR otherwise.
*/
struct trace_event_file *trace_get_event_file(const char *instance,
const char *system,
const char *event)
{
struct trace_array *tr = top_trace_array();
struct trace_event_file *file = NULL;
int ret = -EINVAL;

if (instance) {
tr = trace_array_find_get(instance);
if (!tr)
return ERR_PTR(-ENOENT);
} else {
ret = trace_array_get(tr);
if (ret)
return ERR_PTR(ret);
}

mutex_lock(&event_mutex);

file = find_event_file(tr, system, event);
if (!file) {
trace_array_put(tr);
ret = -EINVAL;
goto out;
}

/* Don't let event modules unload while in use */
ret = try_module_get(file->event_call->mod);
if (!ret) {
trace_array_put(tr);
ret = -EBUSY;
goto out;
}

ret = 0;
out:
mutex_unlock(&event_mutex);

if (ret)
file = ERR_PTR(ret);

return file;
}
EXPORT_SYMBOL_GPL(trace_get_event_file);

/**
* trace_put_event_file - Release a file from trace_get_event_file()
* @file: The trace event file
*
* If a file was retrieved using trace_get_event_file(), this should
* be called when it's no longer needed. It will cancel the previous
* trace_array_get() called by that function, and decrement the
* event's module refcount.
*/
void trace_put_event_file(struct trace_event_file *file)
{
mutex_lock(&event_mutex);
module_put(file->event_call->mod);
mutex_unlock(&event_mutex);

trace_array_put(file->tr);
}
EXPORT_SYMBOL_GPL(trace_put_event_file);

#ifdef CONFIG_DYNAMIC_FTRACE

/* Avoid typos */
Expand Down

0 comments on commit e3e2a2c

Please sign in to comment.