LIBTRACEFS(3)

πŸ’– NAME πŸ’–

okay so bestie, welcome to the libtracefs manual β€” this is page LIBTRACEFS(3), and it's all about event filters: adding them, checking them, applying them, and clearing them. The whole crew is here: tracefs_filter_string_append, tracefs_filter_string_verify, tracefs_event_filter_apply, and tracefs_event_filter_clear. filter girlies, rise πŸ’…βœ¨


✨ SYNOPSIS ✨

#include <tracefs.h>

int tracefs_filter_string_append(struct tep_event *event, char **filter,
                                 struct tracefs_filter type, const char *field,
                                 enum tracefs_synth_compare compare, const char *val);
int tracefs_filter_string_verify(struct tep_event *event, const char *filter, char **err);
int tracefs_event_filter_apply(struct tracefs_instance *instance, struct tep_event *event, const char *filter);
int tracefs_event_filter_clear(struct tracefs_instance *instance, struct tep_event *event);

πŸ¦‹ DESCRIPTION πŸ¦‹

πŸŽ€ tracefs_filter_string_append()

tracefs_filter_string_append() is the little function that helps you create and verify event filters for a given event. It verifies that field belongs to the event, that the compare option you're using is valid for the type of the field, as well as val. For a type that is not TRACEFS_FILTER_COMPARE, it builds the logical string and also makes sure the syntax is correct β€” like, no more close parenthesis than open parenthesis, an AND (&&) or OR (||) isn't misplaced, etc. syntax check slay πŸ”₯

🌸 tracefs_synth_append_start_filter()

The page also brings up tracefs_synth_append_start_filter(): it 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 statements, or it may add a comparison of field to val based on compare.

🧚 the type tokens

If type is one of these, here's what gets appended to the filter:

  • 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

field, compare, and val are ignored unless type is equal to TRACEFS_FILTER_COMPARE. When it is compare time, _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 <= val
  • TRACEFS_COMPARE_RE β€” field ~ "val" : where field is a string.
  • TRACEFS_COMPARE_AND β€” field & val : where field is a flags field.

πŸ¦‹ tracefs_filter_string_verify()

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

bestie, err must be freed with free(). no leaky vibes, okay? 🫢

🌈 tracefs_event_filter_apply()

tracefs_event_filter_apply() applies the given filter string on event in the given instance. doing the thing πŸ’…

⭐ tracefs_event_filter_clear()

tracefs_event_filter_clear() clears all filters on event in the given instance. bye-bye filters, iconic behavior πŸŽ€


πŸ”₯ RETURN VALUE πŸ”₯

  • tracefs_filter_string_append() β€” returns 0 on success and -1 on error.
  • tracefs_filter_string_verify() β€” 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().
  • tracefs_event_filter_apply() β€” returns 0 on success and -1 on error.
  • tracefs_event_filter_clear() β€” returns 0 on success and -1 on error.

🌸 EXAMPLE 🌸

okay bestie, this one's a whole main character example β€” a little program that takes a filter string, checks it with the library, re-parses it into a shiny new filter, and applies it to an event. it's giving "I read the whole manpage and now I'm dangerous" πŸ’…

#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_filter_string_verify(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_filter_string_append(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);
                }
        }

        if (tracefs_event_filter_apply(NULL, event, new_filter))
                fprintf(stderr, "Failed to apply filter on event");

        tep_free(tep);

        printf("Created new filter: '%s'\n", new_filter);
        free(new_filter);

        exit(0);
}

no cap, that's the whole thing β€” copy it, build it, run it, feel iconic πŸ’–


πŸ“ FILES πŸ“

the receipts, bestie β€” here's what you actually touch:

  • tracefs.h β€” the header file you include so you get access to all the library APIs. like, the whole personality lives in here ✨
  • -ltracefs β€” the linker switch you add when building a program that uses the library. yes, you have to actually link it, she doesn't come free πŸŽ€

πŸ‘€ SEE ALSO πŸ‘€

go read these next, i'm obsessed with the cross-references:

libtracefs(3), libtraceevent(3), trace-cmd(1), tracefs_hist_alloc(3), tracefs_hist_alloc_2d(3), tracefs_hist_alloc_nd(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)

(and yes, tracefs_hist_destory(3) is spelled exactly like that in the original β€” she's got a typo and we love her for it πŸ™ˆ)


✨ AUTHOR ✨

the legends behind this:

  • Steven Rostedt <rostedt@goodmis.org[1]>
  • Tzvetomir Stoyanov <tz.stoyanov@gmail.com[2]>
  • sameeruddin shaik <sameeruddin.shaik8@gmail.com[3]>

πŸ› REPORTING BUGS πŸ›

found a bug? don't suffer in silence, bestie β€” report it to <linux-trace-devel@vger.kernel.org[4]> and let the maintainers slay 🫢


πŸ“œ LICENSE πŸ“œ

libtracefs is Free Software licensed under the GNU LGPL 2.1. periodt. πŸ’…


πŸ”— RESOURCES πŸ”—

the mothership, go touch grass (the kernel kind):

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


πŸ“ NOTES πŸ“

the link footnotes, preserved in all their glory πŸŽ€

  1. rostedt@goodmis.org mailto:rostedt@goodmis.org
  2. tz.stoyanov@gmail.com mailto:tz.stoyanov@gmail.com
  3. sameeruddin.shaik8@gmail.com mailto:sameeruddin.shaik8@gmail.com
  4. linux-trace-devel@vger.kernel.org mailto:linux-trace-devel@vger.kernel.org

and that's a wrap on the whole page, bestie πŸ¦‹ this was libtracefs 1.8.4, dated 10/21/2026 β€” screenshot it, memorise it, go write some iconic filters. ily, bye πŸ’–βœ¨

πŸ“¦ where this page comes from