diff mbox series

trace-cmd record: Use tracefs_filter_function() for function filtering

Message ID 20210408123804.1f3e0f2d@gandalf.local.home (mailing list archive)
State Accepted
Headers show
Series trace-cmd record: Use tracefs_filter_function() for function filtering | expand

Commit Message

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

By having the implementation for -l and -n use tracefs_function_filter()
and tracefs_function_notrace() it extends the filtering capability to use
full regex expressions.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 .../trace-cmd/trace-cmd-record.1.txt          |  9 +--
 tracecmd/trace-record.c                       | 58 ++++++++++++++++++-
 2 files changed, 60 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/Documentation/trace-cmd/trace-cmd-record.1.txt b/Documentation/trace-cmd/trace-cmd-record.1.txt
index d992002e..55a8891b 100644
--- a/Documentation/trace-cmd/trace-cmd-record.1.txt
+++ b/Documentation/trace-cmd/trace-cmd-record.1.txt
@@ -134,10 +134,11 @@  OPTIONS
 *-l* 'function-name'::
     This will limit the 'function' and 'function_graph' tracers to only trace
     the given function name. More than one *-l* may be specified on the
-    command line to trace more than one function. The limited use of glob
-    expressions are also allowed. These are 'match\*' to only filter functions
-    that start with 'match'. '\*match' to only filter functions that end with
-    'match'. '\*match\*' to only filter on functions that contain 'match'.
+    command line to trace more than one function. This supports both full
+    regex(3) parsing, or basic glob parsing. If the filter has only alphanumeric,
+    '_', '*', '?' and '.' characters, then it will be parsed as a basic glob.
+    to force it to be a regex, prefix the filter with '^' or append it with '$'
+    and it will then be parsed as a regex.
 
 *-g* 'function-name'::
     This option is for the function_graph plugin. It will graph the given
diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c
index 6b608ad5..fd03a605 100644
--- a/tracecmd/trace-record.c
+++ b/tracecmd/trace-record.c
@@ -4351,6 +4351,58 @@  static void record_data(struct common_record_context *ctx)
 	tracecmd_output_close(handle);
 }
 
+enum filter_type {
+	FUNC_FILTER,
+	FUNC_NOTRACE,
+};
+
+static int write_func_filter(enum filter_type type, struct buffer_instance *instance,
+			     struct func_list **list)
+{
+	struct func_list *item;
+	const char *file;
+	int ret = -1;
+	int (*filter_function)(struct tracefs_instance *instance, const char *filter,
+			       const char *module, unsigned int flags);
+
+	if (!*list)
+		return 0;
+
+	switch (type) {
+	case FUNC_FILTER:
+		filter_function = tracefs_function_filter;
+		file = "set_ftrace_filter";
+		break;
+	case FUNC_NOTRACE:
+		filter_function = tracefs_function_notrace;
+		file = "set_ftrace_notrace";
+		break;
+	}
+
+	ret = filter_function(instance->tracefs, NULL, NULL,
+			      TRACEFS_FL_RESET | TRACEFS_FL_CONTINUE);
+	if (ret < 0)
+		return ret;
+
+	while (*list) {
+		item = *list;
+		*list = item->next;
+		ret = filter_function(instance->tracefs, item->func, item->mod,
+				      TRACEFS_FL_CONTINUE);
+		if (ret < 0)
+			goto failed;
+		free(item);
+	}
+	ret = filter_function(instance->tracefs, NULL, NULL, 0);
+	return ret;
+ failed:
+	die("Failed to write %s to %s.\n"
+	    "Perhaps this function is not available for tracing.\n"
+	    "run 'trace-cmd list -f %s' to see if it is.",
+	    item->func, file, item->func);
+	return ret;
+}
+
 static int write_func_file(struct buffer_instance *instance,
 			    const char *file, struct func_list **list)
 {
@@ -4439,7 +4491,7 @@  static void set_funcs(struct buffer_instance *instance)
 	if (is_guest(instance))
 		return;
 
-	ret = write_func_file(instance, "set_ftrace_filter", &instance->filter_funcs);
+	ret = write_func_filter(FUNC_FILTER, instance, &instance->filter_funcs);
 	if (ret < 0)
 		die("set_ftrace_filter does not exist. Can not filter functions");
 
@@ -4455,13 +4507,13 @@  static void set_funcs(struct buffer_instance *instance)
 				set_notrace = 1;
 		}
 		if (!set_notrace) {
-			ret = write_func_file(instance, "set_ftrace_notrace",
+			ret = write_func_filter(FUNC_NOTRACE, instance,
 					      &instance->notrace_funcs);
 			if (ret < 0)
 				die("set_ftrace_notrace does not exist. Can not filter functions");
 		}
 	} else
-		write_func_file(instance, "set_ftrace_notrace", &instance->notrace_funcs);
+		write_func_filter(FUNC_NOTRACE, instance, &instance->notrace_funcs);
 
 	/* make sure we are filtering functions */
 	if (func_stack && is_top_instance(instance)) {