diff mbox series

[6/6] libtracefs: Add man pages for tracefs_event_append_filter()

Message ID 20210730030307.574270-7-rostedt@goodmis.org (mailing list archive)
State Accepted
Commit 54809d3cbcc9ef1b3b3122981a317def4a4acc78
Headers show
Series libtracefs: Updates to event filtering | expand

Commit Message

Steven Rostedt July 30, 2021, 3:03 a.m. UTC
From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Add man pages for tracefs_event_append_filter() and
tracefs_event_verify_filter()

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 Documentation/libtracefs-filter.txt | 329 ++++++++++++++++++++++++++++
 1 file changed, 329 insertions(+)
 create mode 100644 Documentation/libtracefs-filter.txt
diff mbox series

Patch

diff --git a/Documentation/libtracefs-filter.txt b/Documentation/libtracefs-filter.txt
new file mode 100644
index 000000000000..7e167bc8f34a
--- /dev/null
+++ b/Documentation/libtracefs-filter.txt
@@ -0,0 +1,329 @@ 
+libtracefs(3)
+=============
+
+NAME
+----
+tracefs_event_append_filter, tracefs_event_verify_filter - Add and verify event filters
+
+SYNOPSIS
+--------
+[verse]
+--
+*#include <tracefs.h>*
+
+int tracefs_event_append_filter(struct tep_event pass:[*]event, char pass:[**] filter,
+				 struct tracefs_filter type, const char pass:[*]field,
+				 enum tracefs_synth_compare compare, const char pass:[*]val);
+int tracefs_event_verify_filter(struct tep_event pass:[*]event, const char pass:[*]filter, char pass:[**]err);
+
+--
+
+DESCRIPTION
+-----------
+*tracefs_event_append_filter*() is a way to create and verify event filters for
+a given event. It will verify that the _field_ belongs to the event and that
+the _compare_ option that is used is valid for the type of the field, as well
+as _val_. For the _type_ that is not of *TRACEFS_FILTER_COMPARE*, it will build
+the logical string and also make sure that the syntax is correct. For example,
+there are no more close parenthesis than open parenthesis. An AND (&&) or OR
+(||) is not misplaced, etc.
+
+*tracefs_synth_append_start_filter*() creates a filter or appends to it for the
+starting event. Depending on _type_, it will build a string of tokens for
+parenthesis or logic statemens, or it may add a comparison of _field_
+to _val_ based on _compare_.
+
+If _type_ is:
+*TRACEFS_FILTER_COMPARE*     -  See below
+*TRACEFS_FILTER_AND*         -  Append "&&" to the filter
+*TRACEFS_FILTER_OR*          -  Append "||" to the filter
+*TRACEFS_FILTER_NOT*         -  Append "!" to the filter
+*TRACEFS_FILTER_OPEN_PAREN*  -  Append "(" to the filter
+*TRACEFS_FILTER_CLOSE_PAREN* -  Append ")" to the filter
+
+_field_, _compare_, and _val_ are ignored unless _type_ is equal to
+*TRACEFS_FILTER_COMPARE*, then _compare will be used for the following:
+
+*TRACEFS_COMPARE_EQ* - _field_ == _val_
+
+*TRACEFS_COMPARE_NE* - _field_ != _val_
+
+*TRACEFS_COMPARE_GT* - _field_ > _val_
+
+*TRACEFS_COMPARE_GE* - _field_ >= _val_
+
+*TRACEFS_COMPARE_LT* - _field_ < _val_
+
+*TRACEFS_COMPARE_LE* - _field_ <pass:[=] _val_
+
+*TRACEFS_COMPARE_RE* - _field_ ~ "_val_" : where _field_ is a string.
+
+*TRACEFS_COMPARE_AND* - _field_ & _val_ : where _field_ is a flags field.
+
+*tracefs_event_verify_filter*() will parse _filter_ to make sure that the
+fields are for the _event_, and that the syntax is correct. If there's an
+error in the syntax, and _err_ is not NULL, then it will be allocated with an
+error message stating what was found wrong with the filter. _err_ must be freed
+with *free*().
+
+RETURN VALUE
+------------
+*tracefs_event_append_filter*() returns 0 on success and -1 on error.
+
+*tracefs_event_verify_filter*() returns 0 on success and -1 on error. if there
+is an error, and _errno_ is not *ENOMEM*, then _err_ is allocated and will
+contain a string describing what was found wrong with _filter_. _err_ must be
+freed with *free*().
+
+EXAMPLE
+-------
+[source,c]
+--
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <tracefs.h>
+
+static void usage(char **argv)
+{
+	fprintf(stderr, "usage: %s [system] event filter\n", argv[0]);
+	exit(-1);
+}
+
+int main (int argc, char **argv)
+{
+	struct tep_handle *tep;
+	struct tep_event *event;
+	const char *system = NULL;
+	const char *event_name;
+	const char *filter;
+	char *new_filter = NULL;
+	char *err = NULL;
+	int i;
+
+	if (argc < 3)
+		usage(argv);
+
+	if (argc < 4) {
+		event_name = argv[1];
+		filter = argv[2];
+	} else {
+		system = argv[1];
+		event_name = argv[2];
+		filter = argv[3];
+	}
+
+	/* Load all events from the system */
+	tep = tracefs_local_events(NULL);
+	if (!tep) {
+		perror("tep");
+		exit(-1);
+	}
+
+	event = tep_find_event_by_name(tep, system, event_name);
+	if (!event) {
+		fprintf(stderr, "Event %s%s%s not found\n",
+			system ? system : "" , system ? " " : "",
+			event_name);
+		exit(-1);
+	}
+
+	if (tracefs_event_verify_filter(event, filter, &err) < 0) {
+		perror("tracecfs_event_verify_filter");
+		if (err)
+			fprintf(stderr, "%s", err);
+		free(err);
+		exit(-1);
+	}
+
+	for (i = 0; filter[i]; i++) {
+		char buf[strlen(filter)];
+		char *field = NULL;
+		char *val = NULL;
+		enum tracefs_filter type;
+		enum tracefs_compare compare = 0;
+		int start_i, n;
+		int quote;
+		bool backslash;
+
+		while (isspace(filter[i]))
+			i++;
+
+		switch(filter[i]) {
+		case '(':
+			type = TRACEFS_FILTER_OPEN_PAREN;
+			break;
+		case ')':
+			type = TRACEFS_FILTER_CLOSE_PAREN;
+			break;
+		case '!':
+			type = TRACEFS_FILTER_NOT;
+			break;
+		case '&':
+			type = TRACEFS_FILTER_AND;
+			i++;
+			break;
+		case '|':
+			type = TRACEFS_FILTER_OR;
+			i++;
+			break;
+		default:
+			type = TRACEFS_FILTER_COMPARE;
+
+			while (isspace(filter[i]))
+				i++;
+
+			start_i = i;
+			for (; filter[i]; i++) {
+				switch(filter[i]) {
+				case 'a' ... 'z':
+				case 'A' ... 'Z':
+				case '0' ... '9':
+				case '_':
+					continue;
+				}
+				break;
+			}
+
+			n = i - start_i;
+			field = buf;
+			strncpy(field, filter + start_i, n);
+			field[n++] = '\0';
+
+			val = buf + n;
+
+			while (isspace(filter[i]))
+				i++;
+
+			start_i = i;
+			switch(filter[i++]) {
+			case '>':
+				compare = TRACEFS_COMPARE_GT;
+				if (filter[i] == '=') {
+					i++;
+					compare = TRACEFS_COMPARE_GE;
+				}
+				break;
+			case '<':
+				compare = TRACEFS_COMPARE_LT;
+				if (filter[i] == '=') {
+					i++;
+					compare = TRACEFS_COMPARE_LE;
+				}
+				break;
+			case '=':
+				compare = TRACEFS_COMPARE_EQ;
+				i++;
+				break;
+			case '!':
+				compare = TRACEFS_COMPARE_NE;
+				i++;
+				break;
+			case '~':
+				compare = TRACEFS_COMPARE_RE;
+				break;
+			case '&':
+				compare = TRACEFS_COMPARE_AND;
+				break;
+			}
+
+			while (isspace(filter[i]))
+				i++;
+
+			quote = 0;
+			backslash = false;
+			start_i = i;
+			for (; filter[i]; i++) {
+				if (quote) {
+					if (backslash)
+						backslash = false;
+					else if (filter[i] == '\\')
+						backslash = true;
+					else if (filter[i] == quote)
+						quote = 0;
+					continue;
+				}
+				switch(filter[i]) {
+				case '"': case '\'':
+					quote = filter[i];
+					continue;
+				case 'a' ... 'z':
+				case 'A' ... 'Z':
+				case '0' ... '9':
+				case '_':
+					continue;
+				}
+				break;
+			}
+			n = i - start_i;
+			strncpy(val, filter + start_i, n);
+			val[n] = '\0';
+			break;
+		}
+		n = tracefs_event_append_filter(event, &new_filter, type,
+						field, compare, val);
+		if (n < 0) {
+			fprintf(stderr, "Failed making new filter:\n'%s'\n",
+				new_filter ? new_filter : "(null)");
+			exit(-1);
+		}
+	}
+
+	tep_free(tep);
+
+	printf("Created new filter: '%s'\n", new_filter);
+	free(new_filter);
+
+	exit(0);
+}
+--
+
+FILES
+-----
+[verse]
+--
+*tracefs.h*
+	Header file to include in order to have access to the library APIs.
+*-ltracefs*
+	Linker switch to add when building a program that uses the library.
+--
+
+SEE ALSO
+--------
+_libtracefs(3)_,
+_libtraceevent(3)_,
+_trace-cmd(1)_,
+_tracefs_hist_alloc(3)_,
+_tracefs_hist_free(3)_,
+_tracefs_hist_add_key(3)_,
+_tracefs_hist_add_value(3)_,
+_tracefs_hist_add_name(3)_,
+_tracefs_hist_start(3)_,
+_tracefs_hist_destory(3)_,
+_tracefs_hist_add_sort_key(3)_,
+_tracefs_hist_sort_key_direction(3)_
+
+AUTHOR
+------
+[verse]
+--
+*Steven Rostedt* <rostedt@goodmis.org>
+*Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>
+*sameeruddin shaik* <sameeruddin.shaik8@gmail.com>
+--
+REPORTING BUGS
+--------------
+Report bugs to  <linux-trace-devel@vger.kernel.org>
+
+LICENSE
+-------
+libtracefs is Free Software licensed under the GNU LGPL 2.1
+
+RESOURCES
+---------
+https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
+
+COPYING
+-------
+Copyright \(C) 2020 VMware, Inc. Free use of this software is granted under
+the terms of the GNU Public License (GPL).