diff mbox series

[2/3] libtracefs: Add tracefs_function_notrace() API

Message ID 20210407202126.1870994-3-rostedt@goodmis.org (mailing list archive)
State Superseded
Headers show
Series libtracefs: Update filtering functions | expand

Commit Message

Steven Rostedt April 7, 2021, 8:21 p.m. UTC
From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Add the API of tracefs_function_notrace() that is identical to how
tracefs_function_filter() works, but will work with the set_ftrace_notrace
filter file.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 Documentation/libtracefs-function-filter.txt | 19 ++++++++---
 include/tracefs-local.h                      |  1 +
 include/tracefs.h                            |  3 ++
 src/tracefs-instance.c                       |  1 +
 src/tracefs-tools.c                          | 33 ++++++++++++++++++++
 5 files changed, 53 insertions(+), 4 deletions(-)

Comments

Tzvetomir Stoyanov (VMware) April 8, 2021, 4:25 a.m. UTC | #1
On Thu, Apr 8, 2021 at 1:02 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
>
> Add the API of tracefs_function_notrace() that is identical to how
> tracefs_function_filter() works, but will work with the set_ftrace_notrace
> filter file.
>
> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
> ---
>  Documentation/libtracefs-function-filter.txt | 19 ++++++++---
>  include/tracefs-local.h                      |  1 +
>  include/tracefs.h                            |  3 ++
>  src/tracefs-instance.c                       |  1 +
>  src/tracefs-tools.c                          | 33 ++++++++++++++++++++
>  5 files changed, 53 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/libtracefs-function-filter.txt b/Documentation/libtracefs-function-filter.txt
> index ccf20e9..746be37 100644
> --- a/Documentation/libtracefs-function-filter.txt
> +++ b/Documentation/libtracefs-function-filter.txt
> @@ -4,6 +4,7 @@ libtracefs(3)
>  NAME
>  ----
>  tracefs_function_filter - Function to limit kernel functions that are traced
> +tracefs_function_notrace - Function to filter kernel functions that not to be traced
>
>  SYNOPSIS
>  --------
> @@ -12,15 +13,18 @@ SYNOPSIS
>  *#include <tracefs.h>*
>
>  int *tracefs_function_filter*(struct tracefs_instance pass:[*]_instance_, const char pass:[*]_filter_, const char pass:[*]_module_, int _flags_);
> +int *tracefs_function_notrace*(struct tracefs_instance pass:[*]_instance_, const char pass:[*]_filter_, const char pass:[*]_module_, int _flags_);
>  --
>
>  DESCRIPTION
>  -----------
> -This function can be used to limit the Linux kernel functions that would be
> -traced by the function and function-graph tracers
> +*tracefs_function_filter* and *tracefs_function_notrace* can be used to limit the
> +Linux kernel functions that would be traced by the function and function-graph tracers.
> +The *tracefs_function_filter* defines a list of functions that can be traced.
> +The *tracefs_function_notrace* defines a list of functions that will not be traced.
> +If a function is in both lists, it will not be traced.
>
> -It will take an
> -_instance_ , that can be NULL for the top level tracing,
> +They take an _instance_ , that can be NULL for the top level tracing,
>  _filter_, a string that represents a filter that should
>  be applied to define what functions are to be traced,
>  _module_, to limit the filtering on a specific module (or NULL to filter on all functions),
> @@ -125,6 +129,13 @@ int main(int argc, char *argv[])
>                 /* Error creating new trace instance */
>         }
>
> +       /* Do not trace any function with the word "lock" in it */
> +       ret = tracefs_function_notrace(inst, "*lock*", NULL, TRACEFS_FL_RESET);
> +       if (ret) {
> +               printf("Failed to set the notrace filter\n");
> +               goto out;
> +       }
> +
>         /* First reset the filter */
>         ret = tracefs_function_filter(inst, NULL, NULL,
>                                       TRACEFS_FL_RESET | TRACEFS_FL_CONTINUE);
> diff --git a/include/tracefs-local.h b/include/tracefs-local.h
> index 73ec113..060de7e 100644
> --- a/include/tracefs-local.h
> +++ b/include/tracefs-local.h
> @@ -19,6 +19,7 @@ struct tracefs_instance {
>         char    *name;
>         int     flags;
>         int     ftrace_filter_fd;
> +       int     ftrace_notrace_fd;
>  };
>
>  /* Can be overridden */
> diff --git a/include/tracefs.h b/include/tracefs.h
> index befcc48..70b7ebe 100644
> --- a/include/tracefs.h
> +++ b/include/tracefs.h
> @@ -160,4 +160,7 @@ enum {
>
>  int tracefs_function_filter(struct tracefs_instance *instance, const char *filter,
>                             const char *module, unsigned int flags);
> +int tracefs_function_notrace(struct tracefs_instance *instance, const char *filter,
> +                            const char *module, unsigned int flags);
> +
>  #endif /* _TRACE_FS_H */
> diff --git a/src/tracefs-instance.c b/src/tracefs-instance.c
> index bf2fabf..9f45624 100644
> --- a/src/tracefs-instance.c
> +++ b/src/tracefs-instance.c
> @@ -44,6 +44,7 @@ static struct tracefs_instance *instance_alloc(const char *trace_dir, const char
>         }
>
>         instance->ftrace_filter_fd = -1;
> +       instance->ftrace_notrace_fd = -1;

These descriptors should be closed in tracefs_instance_free(), as part
of the instance cleanup.

>
>         return instance;
>
> diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c
> index 21a9bd3..b41806b 100644
> --- a/src/tracefs-tools.c
> +++ b/src/tracefs-tools.c
> @@ -21,10 +21,12 @@
>
>  #define TRACE_CTRL             "tracing_on"
>  #define TRACE_FILTER           "set_ftrace_filter"
> +#define TRACE_NOTRACE          "set_ftrace_notrace"
>  #define TRACE_FILTER_LIST      "available_filter_functions"
>
>  /* File descriptor for Top level set_ftrace_filter  */
>  static int ftrace_filter_fd = -1;
> +static int ftrace_notrace_fd = -1;
>  static pthread_mutex_t filter_lock = PTHREAD_MUTEX_INITIALIZER;

I'm wondering if we should free these global resources somehow. A
cleanup API for the whole library can be implemented  using
__attribute__((destructor)), or some other way ?

>
>  static const char * const options_map[] = {
> @@ -898,3 +900,34 @@ int tracefs_function_filter(struct tracefs_instance *instance, const char *filte
>         tracefs_put_tracing_file(filter_path);
>         return ret;
>  }
> +
> +/**
> + * tracefs_function_notrace - filter the functions that are not to be traced
> + * @instance: ftrace instance, can be NULL for top tracing instance.
> + * @filter: The filter to filter what functions are not to be traced
> + * @module: Module to be traced or NULL if all functions are to be examined.
> + * @flags: flags on modifying the filter file
> + *
> + * See tracefs_function_filter, as this has the same functionality but
> + * for adding to the "notrace" filter.
> + */
> +int tracefs_function_notrace(struct tracefs_instance *instance, const char *filter,
> +                            const char *module, unsigned int flags)
> +{
> +       char *filter_path;
> +       int *fd;
> +       int ret;
> +
> +       filter_path = tracefs_instance_get_file(instance, TRACE_NOTRACE);
> +       if (!filter_path)
> +               return -1;
> +
> +       if (instance)
> +               fd = &instance->ftrace_notrace_fd;
> +       else
> +               fd = &ftrace_notrace_fd;
> +
> +       ret = update_filter(filter_path, fd, instance, filter, module, flags);
> +       tracefs_put_tracing_file(filter_path);
> +       return ret;
> +}
> --
> 2.29.2
>
Steven Rostedt April 8, 2021, 12:53 p.m. UTC | #2
On Thu, 8 Apr 2021 07:25:20 +0300
Tzvetomir Stoyanov <tz.stoyanov@gmail.com> wrote:

> > diff --git a/src/tracefs-instance.c b/src/tracefs-instance.c
> > index bf2fabf..9f45624 100644
> > --- a/src/tracefs-instance.c
> > +++ b/src/tracefs-instance.c
> > @@ -44,6 +44,7 @@ static struct tracefs_instance *instance_alloc(const char *trace_dir, const char
> >         }
> >
> >         instance->ftrace_filter_fd = -1;
> > +       instance->ftrace_notrace_fd = -1;  
> 
> These descriptors should be closed in tracefs_instance_free(), as part
> of the instance cleanup.

Good point. I'll add a patch on top of this one to close both of them.

> 
> >
> >         return instance;
> >
> > diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c
> > index 21a9bd3..b41806b 100644
> > --- a/src/tracefs-tools.c
> > +++ b/src/tracefs-tools.c
> > @@ -21,10 +21,12 @@
> >
> >  #define TRACE_CTRL             "tracing_on"
> >  #define TRACE_FILTER           "set_ftrace_filter"
> > +#define TRACE_NOTRACE          "set_ftrace_notrace"
> >  #define TRACE_FILTER_LIST      "available_filter_functions"
> >
> >  /* File descriptor for Top level set_ftrace_filter  */
> >  static int ftrace_filter_fd = -1;
> > +static int ftrace_notrace_fd = -1;
> >  static pthread_mutex_t filter_lock = PTHREAD_MUTEX_INITIALIZER;  
> 
> I'm wondering if we should free these global resources somehow. A
> cleanup API for the whole library can be implemented  using
> __attribute__((destructor)), or some other way ?

No need. The OS will close them for you when the application exits. All
file descriptors that are opened will be closed by the OS.

That said, we should probably add O_CLOEXEC in the open for them such that
they don't stay open if the application does an exec() system call.

-- Steve
diff mbox series

Patch

diff --git a/Documentation/libtracefs-function-filter.txt b/Documentation/libtracefs-function-filter.txt
index ccf20e9..746be37 100644
--- a/Documentation/libtracefs-function-filter.txt
+++ b/Documentation/libtracefs-function-filter.txt
@@ -4,6 +4,7 @@  libtracefs(3)
 NAME
 ----
 tracefs_function_filter - Function to limit kernel functions that are traced
+tracefs_function_notrace - Function to filter kernel functions that not to be traced
 
 SYNOPSIS
 --------
@@ -12,15 +13,18 @@  SYNOPSIS
 *#include <tracefs.h>*
 
 int *tracefs_function_filter*(struct tracefs_instance pass:[*]_instance_, const char pass:[*]_filter_, const char pass:[*]_module_, int _flags_);
+int *tracefs_function_notrace*(struct tracefs_instance pass:[*]_instance_, const char pass:[*]_filter_, const char pass:[*]_module_, int _flags_);
 --
 
 DESCRIPTION
 -----------
-This function can be used to limit the Linux kernel functions that would be
-traced by the function and function-graph tracers
+*tracefs_function_filter* and *tracefs_function_notrace* can be used to limit the
+Linux kernel functions that would be traced by the function and function-graph tracers.
+The *tracefs_function_filter* defines a list of functions that can be traced.
+The *tracefs_function_notrace* defines a list of functions that will not be traced.
+If a function is in both lists, it will not be traced.
 
-It will take an
-_instance_ , that can be NULL for the top level tracing,
+They take an _instance_ , that can be NULL for the top level tracing,
 _filter_, a string that represents a filter that should
 be applied to define what functions are to be traced,
 _module_, to limit the filtering on a specific module (or NULL to filter on all functions),
@@ -125,6 +129,13 @@  int main(int argc, char *argv[])
 		/* Error creating new trace instance */
 	}
 
+	/* Do not trace any function with the word "lock" in it */
+	ret = tracefs_function_notrace(inst, "*lock*", NULL, TRACEFS_FL_RESET);
+	if (ret) {
+		printf("Failed to set the notrace filter\n");
+		goto out;
+	}
+
 	/* First reset the filter */
 	ret = tracefs_function_filter(inst, NULL, NULL,
 				      TRACEFS_FL_RESET | TRACEFS_FL_CONTINUE);
diff --git a/include/tracefs-local.h b/include/tracefs-local.h
index 73ec113..060de7e 100644
--- a/include/tracefs-local.h
+++ b/include/tracefs-local.h
@@ -19,6 +19,7 @@  struct tracefs_instance {
 	char	*name;
 	int	flags;
 	int	ftrace_filter_fd;
+	int	ftrace_notrace_fd;
 };
 
 /* Can be overridden */
diff --git a/include/tracefs.h b/include/tracefs.h
index befcc48..70b7ebe 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -160,4 +160,7 @@  enum {
 
 int tracefs_function_filter(struct tracefs_instance *instance, const char *filter,
 			    const char *module, unsigned int flags);
+int tracefs_function_notrace(struct tracefs_instance *instance, const char *filter,
+			     const char *module, unsigned int flags);
+
 #endif /* _TRACE_FS_H */
diff --git a/src/tracefs-instance.c b/src/tracefs-instance.c
index bf2fabf..9f45624 100644
--- a/src/tracefs-instance.c
+++ b/src/tracefs-instance.c
@@ -44,6 +44,7 @@  static struct tracefs_instance *instance_alloc(const char *trace_dir, const char
 	}
 
 	instance->ftrace_filter_fd = -1;
+	instance->ftrace_notrace_fd = -1;
 
 	return instance;
 
diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c
index 21a9bd3..b41806b 100644
--- a/src/tracefs-tools.c
+++ b/src/tracefs-tools.c
@@ -21,10 +21,12 @@ 
 
 #define TRACE_CTRL		"tracing_on"
 #define TRACE_FILTER		"set_ftrace_filter"
+#define TRACE_NOTRACE		"set_ftrace_notrace"
 #define TRACE_FILTER_LIST	"available_filter_functions"
 
 /* File descriptor for Top level set_ftrace_filter  */
 static int ftrace_filter_fd = -1;
+static int ftrace_notrace_fd = -1;
 static pthread_mutex_t filter_lock = PTHREAD_MUTEX_INITIALIZER;
 
 static const char * const options_map[] = {
@@ -898,3 +900,34 @@  int tracefs_function_filter(struct tracefs_instance *instance, const char *filte
 	tracefs_put_tracing_file(filter_path);
 	return ret;
 }
+
+/**
+ * tracefs_function_notrace - filter the functions that are not to be traced
+ * @instance: ftrace instance, can be NULL for top tracing instance.
+ * @filter: The filter to filter what functions are not to be traced
+ * @module: Module to be traced or NULL if all functions are to be examined.
+ * @flags: flags on modifying the filter file
+ *
+ * See tracefs_function_filter, as this has the same functionality but
+ * for adding to the "notrace" filter.
+ */
+int tracefs_function_notrace(struct tracefs_instance *instance, const char *filter,
+			     const char *module, unsigned int flags)
+{
+	char *filter_path;
+	int *fd;
+	int ret;
+
+	filter_path = tracefs_instance_get_file(instance, TRACE_NOTRACE);
+	if (!filter_path)
+		return -1;
+
+	if (instance)
+		fd = &instance->ftrace_notrace_fd;
+	else
+		fd = &ftrace_notrace_fd;
+
+	ret = update_filter(filter_path, fd, instance, filter, module, flags);
+	tracefs_put_tracing_file(filter_path);
+	return ret;
+}