linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH v1] libtracefs: An API to set the filtering of functions
  2021-03-16 17:44 [PATCH v1] libtracefs: An API to set the filtering of functions Sameeruddin shaik
@ 2021-03-16 11:37 ` Tzvetomir Stoyanov
  2021-03-16 11:55   ` Sameeruddin Shaik
  0 siblings, 1 reply; 3+ messages in thread
From: Tzvetomir Stoyanov @ 2021-03-16 11:37 UTC (permalink / raw)
  To: Sameeruddin shaik; +Cc: Steven Rostedt, Linux Trace Devel

Hi Sameer,
I think we are almost there, I have a few comments on the error
handling, that should be addressed before merging the patch.

On Mon, Mar 15, 2021 at 7:49 PM Sameeruddin shaik
<sameeruddin.shaik8@gmail.com> wrote:
>
> This new API will write the function filters into the
> set_ftrace_filter file.
>
> tracefs_function_filter()
>
> https://bugzilla.kernel.org/show_bug.cgi?id=210643
>
> Signed-off-by: Sameeruddin shaik <sameeruddin.shaik8@gmail.com>
> ---
> changed snprintf to asprintf for string formation
> handled the lines over 80 characters
>
> diff --git a/include/tracefs.h b/include/tracefs.h
> index f3eec62..c1f07b0 100644
> --- a/include/tracefs.h
> +++ b/include/tracefs.h
> @@ -145,5 +145,6 @@ bool tracefs_option_is_enabled(struct tracefs_instance *instance, enum tracefs_o
>  int tracefs_option_enable(struct tracefs_instance *instance, enum tracefs_option_id id);
>  int tracefs_option_diasble(struct tracefs_instance *instance, enum tracefs_option_id id);
>  const char *tracefs_option_name(enum tracefs_option_id id);
> -
> +int tracefs_function_filter(struct tracefs_instance *instance, const char **filters,
> +                           const char *module, bool reset, const char ***errs);
>  #endif /* _TRACE_FS_H */
> diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c
> index e2dfc7b..6b33321 100644
> --- a/src/tracefs-tools.c
> +++ b/src/tracefs-tools.c
> @@ -18,6 +18,7 @@
>  #include "tracefs-local.h"
>
>  #define TRACE_CTRL     "tracing_on"
> +#define TRACE_FILTER   "set_ftrace_filter"
>
>  static const char * const options_map[] = {
>         "unknown",
> @@ -387,3 +388,93 @@ void tracefs_option_clear(struct tracefs_options_mask *options, enum tracefs_opt
>         if (options && id > TRACEFS_OPTION_INVALID)
>                 options->mask &= ~(1ULL << (id - 1));
>  }
> +
> +static int controlled_write(const char *filter_path, const char **filters,
> +                           const char *module, bool reset, const char ***errs)
> +{
> +       int flags = reset ? O_TRUNC : O_APPEND;
> +       const char **e = NULL;
> +       char *each_str = NULL;
> +       int write_size = 0;
> +       int size = 0;
> +       int fd = -1;
> +       int ret = 0;
> +       int j = 0;
> +       int i;
> +
> +       fd = open(filter_path, O_WRONLY | flags);
> +       if (fd < 0)
> +               return 1;
> +
> +       for (i = 0; filters[i]; i++) {
> +               if (module)
> +                       write_size = asprintf(&each_str, "%s:mod:%s ", filters[i], module);
> +               else
> +                       write_size = asprintf(&each_str, "%s ", filters[i]);
> +               if (write_size < 0)
> +                       continue;

I think we can consider asprintf() failure as a major problem. There
are two options - break the loop or goto error label.

> +               size = write(fd, each_str, write_size);
> +               /* compare written bytes*/
> +               if (size < write_size) {
> +                       if (errs) {
> +                               e = realloc(e, (j + 1) * (sizeof(char *)));

The realloc return value must be checked. In case of an error - break
the loop or goto error label.

> +                               e[j++] = filters[i];
> +                               ret -= 1;
> +                       }
> +               }
> +               free(each_str);

Set each_str to NULL after the free, This will help with proper
resources cleanup, in case of an error.

> +       }

If you choose the option to break the loop in case of an error, check
here if filters[i] is not NULL, i.e. if the loop exit with an error.
If there was an error - clean up all internally allocated resources
(fd, e, each_str) and return error.
The other option is to add "error" or "out" label at the end of the
function where to do this resource cleanups.

> +       if (errs) {
> +               e = realloc(e, (j + 1) * (sizeof(char *)));

Check that realloc return value too.

> +               e[j] = NULL;
> +               *errs = e;
> +       }
> +       close(fd);

Note: in case of an internal error exit, free e and each_str, if they
were allocated, and do not modify err.

> +       return ret;
> +}
> +
> +/**
> + * tracefs_function_filter - write to set_ftrace_filter file to trace
> + * particular functions
> + * @instance: ftrace instance, can be NULL for top tracing instance
> + * @filters: An array of function names ending with a NULL pointer
> + * @module: Module to be traced
> + * @reset: set to true to reset the file before applying the filter
> + * @errs: A pointer to array of constant strings that will be allocated
> + * on negative return of this function, pointing to the filters that
> + * failed.May be NULL, in which case this field will be ignored.
> + *
> + * The @filters is an array of strings, where each string will be used
> + * to set a function or functions to be traced.
> + *
> + * If @reset is true, then all functions in the filter are cleared
> + * before adding functions from @filters. Otherwise, the functions set
> + * by @filters will be appended to the filter file
> + *
> + * returns -x on filter errors (where x is number of failed filter
> + * srtings) and if @errs is not NULL will be an allocated string array
> + * pointing to the strings in @filters that failed and must be freed
> + * with free().
> + *
> + * returns 1 on general errors not realted to setting the filter.
> + * @errs is not set even if supplied.
> + *
> + * return 0 on success and @errs is not set.
Note: in case of an error exit, free e and each_str, if they were allocated
> + */
> +int tracefs_function_filter(struct tracefs_instance *instance, const char **filters,
> +                           const char *module, bool reset, const char ***errs)
> +{
> +       char *ftrace_filter_path;
> +       int ret = 0;
> +
> +       if (!filters)
> +               return 1;
> +
> +       ftrace_filter_path = tracefs_instance_get_file(instance, TRACE_FILTER);
> +       if (!ftrace_filter_path)
> +               return 1;
> +
> +       ret = controlled_write(ftrace_filter_path, filters, module, reset, errs);
> +       tracefs_put_tracing_file(ftrace_filter_path);
> +       return ret;
> +}
> --
> 2.7.4
>

Thanks, Sameer!

--
Tzvetomir (Ceco) Stoyanov
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v1] libtracefs: An API to set the filtering of functions
  2021-03-16 11:37 ` Tzvetomir Stoyanov
@ 2021-03-16 11:55   ` Sameeruddin Shaik
  0 siblings, 0 replies; 3+ messages in thread
From: Sameeruddin Shaik @ 2021-03-16 11:55 UTC (permalink / raw)
  To: Tzvetomir Stoyanov; +Cc: Steven Rostedt, Linux Trace Devel

Tzvetomir,
Thanks for your review, I will address your comments in the next patch.
steve,
Do you have any other comments on this patch?
Thanks,
sameer.

On Tue, Mar 16, 2021 at 5:07 PM Tzvetomir Stoyanov
<tz.stoyanov@gmail.com> wrote:
>
> Hi Sameer,
> I think we are almost there, I have a few comments on the error
> handling, that should be addressed before merging the patch.
>
> On Mon, Mar 15, 2021 at 7:49 PM Sameeruddin shaik
> <sameeruddin.shaik8@gmail.com> wrote:
> >
> > This new API will write the function filters into the
> > set_ftrace_filter file.
> >
> > tracefs_function_filter()
> >
> > https://bugzilla.kernel.org/show_bug.cgi?id=210643
> >
> > Signed-off-by: Sameeruddin shaik <sameeruddin.shaik8@gmail.com>
> > ---
> > changed snprintf to asprintf for string formation
> > handled the lines over 80 characters
> >
> > diff --git a/include/tracefs.h b/include/tracefs.h
> > index f3eec62..c1f07b0 100644
> > --- a/include/tracefs.h
> > +++ b/include/tracefs.h
> > @@ -145,5 +145,6 @@ bool tracefs_option_is_enabled(struct tracefs_instance *instance, enum tracefs_o
> >  int tracefs_option_enable(struct tracefs_instance *instance, enum tracefs_option_id id);
> >  int tracefs_option_diasble(struct tracefs_instance *instance, enum tracefs_option_id id);
> >  const char *tracefs_option_name(enum tracefs_option_id id);
> > -
> > +int tracefs_function_filter(struct tracefs_instance *instance, const char **filters,
> > +                           const char *module, bool reset, const char ***errs);
> >  #endif /* _TRACE_FS_H */
> > diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c
> > index e2dfc7b..6b33321 100644
> > --- a/src/tracefs-tools.c
> > +++ b/src/tracefs-tools.c
> > @@ -18,6 +18,7 @@
> >  #include "tracefs-local.h"
> >
> >  #define TRACE_CTRL     "tracing_on"
> > +#define TRACE_FILTER   "set_ftrace_filter"
> >
> >  static const char * const options_map[] = {
> >         "unknown",
> > @@ -387,3 +388,93 @@ void tracefs_option_clear(struct tracefs_options_mask *options, enum tracefs_opt
> >         if (options && id > TRACEFS_OPTION_INVALID)
> >                 options->mask &= ~(1ULL << (id - 1));
> >  }
> > +
> > +static int controlled_write(const char *filter_path, const char **filters,
> > +                           const char *module, bool reset, const char ***errs)
> > +{
> > +       int flags = reset ? O_TRUNC : O_APPEND;
> > +       const char **e = NULL;
> > +       char *each_str = NULL;
> > +       int write_size = 0;
> > +       int size = 0;
> > +       int fd = -1;
> > +       int ret = 0;
> > +       int j = 0;
> > +       int i;
> > +
> > +       fd = open(filter_path, O_WRONLY | flags);
> > +       if (fd < 0)
> > +               return 1;
> > +
> > +       for (i = 0; filters[i]; i++) {
> > +               if (module)
> > +                       write_size = asprintf(&each_str, "%s:mod:%s ", filters[i], module);
> > +               else
> > +                       write_size = asprintf(&each_str, "%s ", filters[i]);
> > +               if (write_size < 0)
> > +                       continue;
>
> I think we can consider asprintf() failure as a major problem. There
> are two options - break the loop or goto error label.
>
> > +               size = write(fd, each_str, write_size);
> > +               /* compare written bytes*/
> > +               if (size < write_size) {
> > +                       if (errs) {
> > +                               e = realloc(e, (j + 1) * (sizeof(char *)));
>
> The realloc return value must be checked. In case of an error - break
> the loop or goto error label.
>
> > +                               e[j++] = filters[i];
> > +                               ret -= 1;
> > +                       }
> > +               }
> > +               free(each_str);
>
> Set each_str to NULL after the free, This will help with proper
> resources cleanup, in case of an error.
>
> > +       }
>
> If you choose the option to break the loop in case of an error, check
> here if filters[i] is not NULL, i.e. if the loop exit with an error.
> If there was an error - clean up all internally allocated resources
> (fd, e, each_str) and return error.
> The other option is to add "error" or "out" label at the end of the
> function where to do this resource cleanups.
>
> > +       if (errs) {
> > +               e = realloc(e, (j + 1) * (sizeof(char *)));
>
> Check that realloc return value too.
>
> > +               e[j] = NULL;
> > +               *errs = e;
> > +       }
> > +       close(fd);
>
> Note: in case of an internal error exit, free e and each_str, if they
> were allocated, and do not modify err.
>
> > +       return ret;
> > +}
> > +
> > +/**
> > + * tracefs_function_filter - write to set_ftrace_filter file to trace
> > + * particular functions
> > + * @instance: ftrace instance, can be NULL for top tracing instance
> > + * @filters: An array of function names ending with a NULL pointer
> > + * @module: Module to be traced
> > + * @reset: set to true to reset the file before applying the filter
> > + * @errs: A pointer to array of constant strings that will be allocated
> > + * on negative return of this function, pointing to the filters that
> > + * failed.May be NULL, in which case this field will be ignored.
> > + *
> > + * The @filters is an array of strings, where each string will be used
> > + * to set a function or functions to be traced.
> > + *
> > + * If @reset is true, then all functions in the filter are cleared
> > + * before adding functions from @filters. Otherwise, the functions set
> > + * by @filters will be appended to the filter file
> > + *
> > + * returns -x on filter errors (where x is number of failed filter
> > + * srtings) and if @errs is not NULL will be an allocated string array
> > + * pointing to the strings in @filters that failed and must be freed
> > + * with free().
> > + *
> > + * returns 1 on general errors not realted to setting the filter.
> > + * @errs is not set even if supplied.
> > + *
> > + * return 0 on success and @errs is not set.
> Note: in case of an error exit, free e and each_str, if they were allocated
> > + */
> > +int tracefs_function_filter(struct tracefs_instance *instance, const char **filters,
> > +                           const char *module, bool reset, const char ***errs)
> > +{
> > +       char *ftrace_filter_path;
> > +       int ret = 0;
> > +
> > +       if (!filters)
> > +               return 1;
> > +
> > +       ftrace_filter_path = tracefs_instance_get_file(instance, TRACE_FILTER);
> > +       if (!ftrace_filter_path)
> > +               return 1;
> > +
> > +       ret = controlled_write(ftrace_filter_path, filters, module, reset, errs);
> > +       tracefs_put_tracing_file(ftrace_filter_path);
> > +       return ret;
> > +}
> > --
> > 2.7.4
> >
>
> Thanks, Sameer!
>
> --
> Tzvetomir (Ceco) Stoyanov
> VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v1] libtracefs: An API to set the filtering of functions
@ 2021-03-16 17:44 Sameeruddin shaik
  2021-03-16 11:37 ` Tzvetomir Stoyanov
  0 siblings, 1 reply; 3+ messages in thread
From: Sameeruddin shaik @ 2021-03-16 17:44 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Sameeruddin shaik

This new API will write the function filters into the
set_ftrace_filter file.

tracefs_function_filter()

https://bugzilla.kernel.org/show_bug.cgi?id=210643

Signed-off-by: Sameeruddin shaik <sameeruddin.shaik8@gmail.com>
---
changed snprintf to asprintf for string formation
handled the lines over 80 characters

diff --git a/include/tracefs.h b/include/tracefs.h
index f3eec62..c1f07b0 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -145,5 +145,6 @@ bool tracefs_option_is_enabled(struct tracefs_instance *instance, enum tracefs_o
 int tracefs_option_enable(struct tracefs_instance *instance, enum tracefs_option_id id);
 int tracefs_option_diasble(struct tracefs_instance *instance, enum tracefs_option_id id);
 const char *tracefs_option_name(enum tracefs_option_id id);
-
+int tracefs_function_filter(struct tracefs_instance *instance, const char **filters,
+			    const char *module, bool reset, const char ***errs);
 #endif /* _TRACE_FS_H */
diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c
index e2dfc7b..6b33321 100644
--- a/src/tracefs-tools.c
+++ b/src/tracefs-tools.c
@@ -18,6 +18,7 @@
 #include "tracefs-local.h"
 
 #define TRACE_CTRL	"tracing_on"
+#define TRACE_FILTER	"set_ftrace_filter"
 
 static const char * const options_map[] = {
 	"unknown",
@@ -387,3 +388,93 @@ void tracefs_option_clear(struct tracefs_options_mask *options, enum tracefs_opt
 	if (options && id > TRACEFS_OPTION_INVALID)
 		options->mask &= ~(1ULL << (id - 1));
 }
+
+static int controlled_write(const char *filter_path, const char **filters,
+			    const char *module, bool reset, const char ***errs)
+{
+	int flags = reset ? O_TRUNC : O_APPEND;
+	const char **e = NULL;
+	char *each_str = NULL;
+	int write_size = 0;
+	int size = 0;
+	int fd = -1;
+	int ret = 0;
+	int j = 0;
+	int i;
+
+	fd = open(filter_path, O_WRONLY | flags);
+	if (fd < 0)
+		return 1;
+
+	for (i = 0; filters[i]; i++) {
+		if (module)
+			write_size = asprintf(&each_str, "%s:mod:%s ", filters[i], module);
+		else
+			write_size = asprintf(&each_str, "%s ", filters[i]);
+		if (write_size < 0)
+			continue;
+		size = write(fd, each_str, write_size);
+		/* compare written bytes*/
+		if (size < write_size) {
+			if (errs) {
+				e = realloc(e, (j + 1) * (sizeof(char *)));
+				e[j++] = filters[i];
+				ret -= 1;
+			}
+		}
+		free(each_str);
+	}
+	if (errs) {
+		e = realloc(e, (j + 1) * (sizeof(char *)));
+		e[j] = NULL;
+		*errs = e;
+	}
+	close(fd);
+	return ret;
+}
+
+/**
+ * tracefs_function_filter - write to set_ftrace_filter file to trace
+ * particular functions
+ * @instance: ftrace instance, can be NULL for top tracing instance
+ * @filters: An array of function names ending with a NULL pointer
+ * @module: Module to be traced
+ * @reset: set to true to reset the file before applying the filter
+ * @errs: A pointer to array of constant strings that will be allocated
+ * on negative return of this function, pointing to the filters that
+ * failed.May be NULL, in which case this field will be ignored.
+ *
+ * The @filters is an array of strings, where each string will be used
+ * to set a function or functions to be traced.
+ *
+ * If @reset is true, then all functions in the filter are cleared
+ * before adding functions from @filters. Otherwise, the functions set
+ * by @filters will be appended to the filter file
+ *
+ * returns -x on filter errors (where x is number of failed filter
+ * srtings) and if @errs is not NULL will be an allocated string array
+ * pointing to the strings in @filters that failed and must be freed
+ * with free().
+ *
+ * returns 1 on general errors not realted to setting the filter.
+ * @errs is not set even if supplied.
+ *
+ * return 0 on success and @errs is not set.
+ */
+int tracefs_function_filter(struct tracefs_instance *instance, const char **filters,
+			    const char *module, bool reset, const char ***errs)
+{
+	char *ftrace_filter_path;
+	int ret = 0;
+
+	if (!filters)
+		return 1;
+
+	ftrace_filter_path = tracefs_instance_get_file(instance, TRACE_FILTER);
+	if (!ftrace_filter_path)
+		return 1;
+
+	ret = controlled_write(ftrace_filter_path, filters, module, reset, errs);
+	tracefs_put_tracing_file(ftrace_filter_path);
+	return ret;
+}
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-03-16 11:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-16 17:44 [PATCH v1] libtracefs: An API to set the filtering of functions Sameeruddin shaik
2021-03-16 11:37 ` Tzvetomir Stoyanov
2021-03-16 11:55   ` Sameeruddin Shaik

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).