From: Steven Rostedt <rostedt@goodmis.org>
To: linux-trace-devel@vger.kernel.org
Cc: Sameeruddin shaik <sameeruddin.shaik8@gmail.com>
Subject: [PATCH 4/4] libtracefs: Add TRACEFS_FL_FUTURE flag for future module filtering
Date: Tue, 30 Mar 2021 14:33:28 -0400 [thread overview]
Message-ID: <20210330183546.351496716@goodmis.org> (raw)
In-Reply-To: 20210330183324.709017776@goodmis.org
From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
Starting in Linux v4.13, it is possible to load filters of a function for
a module before it is loaded. That is:
# echo '*:mod:rfkill' > set_ftrace_filter
# echo function > current_tracer
# modprobe rfkill
And the above will enable all functions for the rfkill module to be traced
before it starts to run.
Add a TRACEFS_FL_FUTURE flag to be able to accomplish the same thing.
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
Documentation/libtracefs-function-filter.txt | 9 ++++
include/tracefs.h | 3 ++
src/tracefs-tools.c | 53 +++++++++++++++++---
3 files changed, 58 insertions(+), 7 deletions(-)
diff --git a/Documentation/libtracefs-function-filter.txt b/Documentation/libtracefs-function-filter.txt
index fa0f0de6f567..ccf20e9671c6 100644
--- a/Documentation/libtracefs-function-filter.txt
+++ b/Documentation/libtracefs-function-filter.txt
@@ -71,6 +71,15 @@ the *TRACEFS_FL_CONTINUE* flag set for the same instance will fail if
*TRACEFS_FL_RESET* flag is set, as the reset flag is only applicable for the
first filter to be added before committing.
+*TRACEFS_FL_FUTURE* :
+If _flags_ contains *TRACEFS_FL_FUTURE* and _module_ holds a string of a module,
+then if the module is not loaded it will attemp to write the filter with the module
+in the filter file. Starting in Linux v4.13 module functions could be added to the
+filter before they are loaded. The filter will be cached, and when the module is
+loaded, the filter will be set before the module executes, allowing to trace
+init functions of a module. This will only work if the _filter_ is not a
+regular expression.
+
RETURN VALUE
------------
Returns 0 on success. If the there is an error but the filtering was not
diff --git a/include/tracefs.h b/include/tracefs.h
index 0d98c10ef325..befcc48d265d 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -149,10 +149,13 @@ const char *tracefs_option_name(enum tracefs_option_id id);
/*
* RESET - Reset on opening filter file (O_TRUNC)
* CONTINUE - Do not close filter file on return.
+ * FUTURE - For kernels that support this feature, enable filters for
+ * a module that has yet to be loaded.
*/
enum {
TRACEFS_FL_RESET = (1 << 0),
TRACEFS_FL_CONTINUE = (1 << 1),
+ TRACEFS_FL_FUTURE = (1 << 2),
};
int tracefs_function_filter(struct tracefs_instance *instance, const char *filter,
diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c
index 82809fae3e6d..cb07b6fc1e3a 100644
--- a/src/tracefs-tools.c
+++ b/src/tracefs-tools.c
@@ -553,14 +553,18 @@ static void free_func_list(struct func_list *func_list)
}
enum match_type {
- FILTER_CHECK,
- FILTER_WRITE,
+ FILTER_CHECK = (1 << 0),
+ FILTER_WRITE = (1 << 1),
+ FILTER_FUTURE = (1 << 2),
};
static int match_filters(int fd, struct func_filter *func_filter,
const char *module, struct func_list **func_list,
- enum match_type type)
+ int flags)
{
+ enum match_type type = flags & (FILTER_CHECK | FILTER_WRITE);
+ bool future = flags & FILTER_FUTURE;
+ bool mod_match = false;
char *line = NULL;
size_t size = 0;
char *path;
@@ -602,6 +606,8 @@ static int match_filters(int fd, struct func_filter *func_filter,
if ((strncmp(mtok + 1, module, mlen) != 0) ||
(mtok[mlen + 1] != ']'))
goto next;
+ if (future)
+ mod_match = true;
}
switch (type) {
case FILTER_CHECK:
@@ -620,6 +626,11 @@ static int match_filters(int fd, struct func_filter *func_filter,
goto out;
}
break;
+ default:
+ /* Should never happen */
+ ret = -1;
+ goto out;
+
}
next:
free(line);
@@ -630,14 +641,21 @@ static int match_filters(int fd, struct func_filter *func_filter,
free(line);
fclose(fp);
+ /* If there was no matches and future was set, this is a success */
+ if (future && !mod_match)
+ ret = 0;
+
return ret;
}
static int check_available_filters(struct func_filter *func_filter,
const char *module,
- struct func_list **func_list)
+ struct func_list **func_list,
+ bool future)
{
- return match_filters(-1, func_filter, module, func_list, FILTER_CHECK);
+ int flags = FILTER_CHECK | (future ? FILTER_FUTURE : 0);
+
+ return match_filters(-1, func_filter, module, func_list, flags);
}
static int set_regex_filter(int fd, struct func_filter *func_filter,
@@ -748,6 +766,13 @@ static int write_func_list(int fd, struct func_list *list)
* may be added before they take effect. The last call of this
* function must be called without this flag for the filter
* to take effect.
+ * TRACEFS_FL_FUTURE - only applicable if "module" is set. If no match
+ * is made, and the module is not yet loaded, it will still attempt
+ * to write the filter plus the module; "<filter>:mod:<module>"
+ * to the filter file. Starting with Linux kernels 4.13, it is possible
+ * to load the filter file with module functions for a module that
+ * is not yet loaded, and when the module is loaded, it will then
+ * activate the module.
*
* Returns 0 on success, 1 if there was an error but the filtering has not
* yet started, -1 if there was an error but the filtering has started.
@@ -763,10 +788,17 @@ int tracefs_function_filter(struct tracefs_instance *instance, const char *filte
char *ftrace_filter_path;
bool reset = flags & TRACEFS_FL_RESET;
bool cont = flags & TRACEFS_FL_CONTINUE;
+ bool future = flags & TRACEFS_FL_FUTURE;
int open_flags;
int ret = 1;
int *fd;
+ /* future flag is only applicable to modules */
+ if (future && !module) {
+ errno = EINVAL;
+ return 1;
+ }
+
pthread_mutex_lock(&filter_lock);
if (instance)
fd = &instance->ftrace_filter_fd;
@@ -808,7 +840,7 @@ int tracefs_function_filter(struct tracefs_instance *instance, const char *filte
if (init_func_filter(&func_filter, filter) < 0)
goto out;
- ret = check_available_filters(&func_filter, module, &func_list);
+ ret = check_available_filters(&func_filter, module, &func_list, future);
if (ret)
goto out_free;
@@ -831,7 +863,14 @@ int tracefs_function_filter(struct tracefs_instance *instance, const char *filte
ret = 0;
if (filter) {
- ret = write_func_list(*fd, func_list);
+ /*
+ * If future is set, and no functions were found, then
+ * set it directly.
+ */
+ if (func_list)
+ ret = write_func_list(*fd, func_list);
+ else
+ ret = 1;
if (ret > 0)
ret = controlled_write(*fd, &func_filter, module);
}
--
2.30.1
prev parent reply other threads:[~2021-03-30 18:44 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-30 18:33 [PATCH 0/4] libtracefs: More updates to tracefs_function_filter() Steven Rostedt
2021-03-30 18:33 ` [PATCH 1/4] libtracefs: Only allow RESET flag if file is not already opened Steven Rostedt
2021-03-30 18:33 ` [PATCH 2/4] libtracefs: Allow filter be NULL if RESET flag is set Steven Rostedt
2021-03-30 18:33 ` [PATCH 3/4] libtracefs: Allow filter to be NULL if module is set in tracefs_function_filter() Steven Rostedt
2021-03-30 18:33 ` Steven Rostedt [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210330183546.351496716@goodmis.org \
--to=rostedt@goodmis.org \
--cc=linux-trace-devel@vger.kernel.org \
--cc=sameeruddin.shaik8@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).