LIBTRACEFS(3)
π LIBTRACEFS(3) β libtracefs manual, but make it a group chat
okay so this is the libtracefs(3) page, bestie, and today we're deep-diving tracefs_eprobe_alloc. yes it's a mouthful, no you're not going to pronounce it right the first time, and yes it slays anyway. let's go π«Ά
β¨ NAME β¨
tracefs_eprobe_alloc β allocate a new event probe (eprobe). that's it. that's the whole name section. iconic brevity π
π¦ SYNOPSIS π¦
#include <tracefs.h>
struct tracefs_dynevent *
tracefs_eprobe_alloc(const char *system, const char *event,
const char *target_system, const char *target_event,
const char *fetchargs);
five arguments, one struct pointer coming back, zero drama. drink water before you type it though π
πΈ DESCRIPTION πΈ
so tracefs_eprobe_alloc() allocates a brand-new eprobe context for you. and like β key thing β the eprobe is not configured in the system yet. it's just a descriptor chillin'. nothing has actually happened to your kernel. we love a low-commitment queen β¨
the new eprobe will live in the system group β or, if system is NULL, it goes in eprobes (nice, a sensible default, we stan). its name will be event.
the eprobe gets attached to target_event, which is located in target_system. and the list of arguments described in fetchargs gets fetched from target_event. so like, you're pulling data out of the target event and stuffing it into your new probe. very "borrowing your bestie's notes" energy ngl π
heads up: the pointer you get back must be freed with tracefs_dynevent_free(). don't just ghost it, free it. π
π₯ RETURN VALUE π₯
tracefs_eprobe_alloc() returns a pointer to an allocated tracefs_dynevent structure that describes the event probe. that pointer must be freed by tracefs_dynevent_free(3). periodt.
note β and this is the important bit β this function only allocates a descriptor representing the eprobe. it does not modify the running system. it's giving "draft in your notes app," not "posted to the group chat." π
on error, NULL is returned. so check it. always check it. i'm literally begging π
π EXAMPLE π
here's the whole thing, verbatim, no cap β a full program that sets up an eprobe on sys_enter_openat2, runs a command, and prints out which files got opened:
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <tracefs.h>
static struct tep_event *open_event;
static struct tep_format_field *file_field;
static int callback(struct tep_event *event, struct tep_record *record,
int cpu, void *data)
{
struct trace_seq seq;
trace_seq_init(&seq);
tep_print_event(event->tep, &seq, record, "%d-%s: ", TEP_PRINT_PID, TEP_PRINT_COMM);
if (event->id == open_event->id) {
trace_seq_puts(&seq, "open file='");
tep_print_field(&seq, record->data, file_field);
trace_seq_puts(&seq, "'\n");
}
trace_seq_terminate(&seq);
trace_seq_do_printf(&seq);
trace_seq_destroy(&seq);
return 0;
}
static pid_t run_exec(char **argv, char **env)
{
pid_t pid;
pid = fork();
if (pid)
return pid;
execve(argv[0], argv, env);
perror("exec");
exit(-1);
}
const char *myprobe = "my_eprobes";
int main (int argc, char **argv, char **env)
{
struct tracefs_dynevent *eprobe;
struct tracefs_instance *instance;
struct tep_handle *tep;
const char *sysnames[] = { myprobe, NULL };
pid_t pid;
if (argc < 2) {
printf("usage: %s command\n", argv[0]);
exit(-1);
}
instance = tracefs_instance_create("exec_open");
if (!instance) {
perror("creating instance");
exit(-1);
}
tracefs_dynevent_destroy_all(TRACEFS_DYNEVENT_EPROBE, true);
eprobe = tracefs_eprobe_alloc(myprobe, "sopen", "syscalls", "sys_enter_openat2",
"file=+0($filename):ustring");
if (!eprobe) {
perror("allocating event probe");
exit(-1);
}
if (tracefs_dynevent_create(eprobe)) {
perror("creating event probe");
exit(-1);
}
tep = tracefs_local_events_system(NULL, sysnames);
if (!tep) {
perror("reading events");
exit(-1);
}
open_event = tep_find_event_by_name(tep, myprobe, "sopen");
file_field = tep_find_field(open_event, "file");
tracefs_event_enable(instance, myprobe, "sopen");
pid = run_exec(&argv[1], env);
/* Let the child start to run */
sched_yield();
do {
tracefs_load_cmdlines(NULL, tep);
tracefs_iterate_raw_events(tep, instance, NULL, 0, callback, NULL);
} while (waitpid(pid, NULL, WNOHANG) != pid);
/* Will disable the events */
tracefs_dynevent_destroy(eprobe, true);
tracefs_dynevent_free(eprobe);
tracefs_instance_destroy(instance);
tep_free(tep);
return 0;
}
notice the "file=+0($filename):ustring" fetcharg β that's the "pull the filename out of the target event" part, main character energy honestly π
π FILES π
tracefs.hβ the header file you include to get access to the library APIs. include it, don't fight it.-ltracefsβ the linker switch you add when building a program that uses the library. yes, it goes at the end, you know this π
π SEE ALSO π
go read those too, i'm not joking, they're literally right there π¦
π AUTHOR π
- Steven Rostedt
<rostedt@goodmis.org[1]> - Tzvetomir Stoyanov
<tz.stoyanov@gmail.com[2]>
legends. both of them. π«Ά
π REPORTING BUGS π
report bugs to <linux-trace-devel@vger.kernel.org[3]>
not me, bestie, i just write the vibes π
β LICENSE β
libtracefs is Free Software licensed under the GNU LGPL 2.1. read it, respect it, love it π§
π RESOURCES π
https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
the source. the mothership. go touch it πΈ
πΈ COPYING πΈ
Copyright (C) 2021 VMware, Inc. Free use of this software is granted under the terms of the GNU Public License (GPL).
π NOTES π
rostedt@goodmis.orgβmailto:rostedt@goodmis.orgtz.stoyanov@gmail.comβmailto:tz.stoyanov@gmail.comlinux-trace-devel@vger.kernel.orgβmailto:linux-trace-devel@vger.kernel.org
and that's the whole page!! π this was libtracefs 1.8.4, dated 10/21/2026 β screenshot it, bookmark it, tattoo it on your forearm, whatever you need to do. mwah πβ¨
π¦ where this page comes from
- arch rolling: libtracefs 1.8.4-1 Β· GPL-2.0-only AND LGPL-2.1-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms