From: Steven Rostedt <rostedt@goodmis.org>
To: linux-trace-devel@vger.kernel.org
Cc: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
Subject: [PATCH 6/6] libtracefs: Add man pages for tracefs_event_append_filter()
Date: Thu, 29 Jul 2021 23:03:07 -0400 [thread overview]
Message-ID: <20210730030307.574270-7-rostedt@goodmis.org> (raw)
In-Reply-To: <20210730030307.574270-1-rostedt@goodmis.org>
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 --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).
--
2.30.2
prev parent reply other threads:[~2021-07-30 3:03 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-30 3:03 [PATCH 0/6] libtracefs: Updates to event filtering Steven Rostedt
2021-07-30 3:03 ` [PATCH 1/6] libtracefs: Update to version 1.3-dev Steven Rostedt
2021-07-30 3:03 ` [PATCH 2/6] libtracefs: Rename GR and NQ to GT and NE respectively Steven Rostedt
2021-07-30 3:03 ` [PATCH 3/6] libtracefs: Append the synth filter with parens and conjunctions Steven Rostedt
2021-07-30 3:03 ` [PATCH 4/6] libtracefs: Add kerneldoc comments to the remaining synth functions Steven Rostedt
2021-07-30 3:03 ` [PATCH 5/6] libtracefs: Add filter creating and verify API Steven Rostedt
2021-07-30 3:03 ` 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=20210730030307.574270-7-rostedt@goodmis.org \
--to=rostedt@goodmis.org \
--cc=linux-trace-devel@vger.kernel.org \
/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).