@@ -24,15 +24,10 @@ void tracecmd_parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigne
extern int tracecmd_disable_sys_plugins;
extern int tracecmd_disable_plugins;
-char **tracecmd_event_systems(const char *tracing_dir);
-char **tracecmd_system_events(const char *tracing_dir, const char *system);
struct tep_handle *tracecmd_local_events(const char *tracing_dir);
int tracecmd_fill_local_events(const char *tracing_dir,
struct tep_handle *pevent, int *parsing_failures);
-char **tracecmd_local_plugins(const char *tracing_dir);
-char **tracecmd_add_list(char **list, const char *name, int len);
-void tracecmd_free_list(char **list);
int *tracecmd_add_id(int *list, int id, int len);
enum {
@@ -143,9 +138,6 @@ void tracecmd_print_stats(struct tracecmd_input *handle);
void tracecmd_print_uname(struct tracecmd_input *handle);
void tracecmd_print_version(struct tracecmd_input *handle);
-struct tep_record *
-tracecmd_read_page_record(struct tep_handle *pevent, void *page, int size,
- struct tep_record *last_record);
struct tep_record *
tracecmd_peek_data(struct tracecmd_input *handle, int cpu);
@@ -33,4 +33,20 @@ int tracefs_instance_file_write(struct tracefs_instance *instance,
char *tracefs_instance_file_read(struct tracefs_instance *instance,
char *file, int *psize);
+/* events */
+struct tep_record *
+tracefs_read_page_record(struct tep_handle *tep, void *page, int size,
+ struct tep_record *last_record);
+void tracefs_list_free(char **list);
+char **tracefs_event_systems(const char *tracing_dir);
+char **tracefs_system_events(const char *tracing_dir, const char *system);
+int tracefs_iterate_raw_events(struct tep_handle *tep,
+ struct tracefs_instance *instance,
+ int (*callback)(struct tep_event *,
+ struct tep_record *,
+ int, void *),
+ void *callback_context);
+
+char **tracefs_tracers(const char *tracing_dir);
+
#endif /* _TRACE_FS_H */
@@ -204,7 +204,7 @@ QStringList KsCaptureControl::_getPlugins()
QStringList pluginList;
char **all_plugins;
- all_plugins = tracecmd_local_plugins(tracefs_get_tracing_dir());
+ all_plugins = tracefs_tracers(tracefs_get_tracing_dir());
if (!all_plugins)
return pluginList;
@@ -1663,101 +1663,6 @@ tracecmd_translate_data(struct tracecmd_input *handle,
return record;
}
-/**
- * tracecmd_read_page_record - read a record off of a page
- * @pevent: pevent used to parse the page
- * @page: the page to read
- * @size: the size of the page
- * @last_record: last record read from this page.
- *
- * If a ring buffer page is available, and the need to parse it
- * without having a handle, then this function can be used.
- *
- * The @pevent needs to be initialized to have the page header information
- * already available.
- *
- * The @last_record is used to know where to read the next record from.
- * If @last_record is NULL, the first record on the page will be read.
- *
- * Returns:
- * A newly allocated record that must be freed with free_record() if
- * a record is found. Otherwise NULL is returned if the record is bad
- * or no more records exist.
- */
-struct tep_record *
-tracecmd_read_page_record(struct tep_handle *pevent, void *page, int size,
- struct tep_record *last_record)
-{
- unsigned long long ts;
- struct kbuffer *kbuf;
- struct tep_record *record = NULL;
- enum kbuffer_long_size long_size;
- enum kbuffer_endian endian;
- void *ptr;
-
- if (tep_is_file_bigendian(pevent))
- endian = KBUFFER_ENDIAN_BIG;
- else
- endian = KBUFFER_ENDIAN_LITTLE;
-
- if (tep_get_header_page_size(pevent) == 8)
- long_size = KBUFFER_LSIZE_8;
- else
- long_size = KBUFFER_LSIZE_4;
-
- kbuf = kbuffer_alloc(long_size, endian);
- if (!kbuf)
- return NULL;
-
- kbuffer_load_subbuffer(kbuf, page);
- if (kbuffer_subbuffer_size(kbuf) > size) {
- warning("tracecmd_read_page_record: page_size > size");
- goto out_free;
- }
-
- if (last_record) {
- if (last_record->data < page || last_record->data >= (page + size)) {
- warning("tracecmd_read_page_record: bad last record (size=%u)",
- last_record->size);
- goto out_free;
- }
-
- ptr = kbuffer_read_event(kbuf, &ts);
- while (ptr < last_record->data) {
- ptr = kbuffer_next_event(kbuf, NULL);
- if (!ptr)
- break;
- if (ptr == last_record->data)
- break;
- }
- if (ptr != last_record->data) {
- warning("tracecmd_read_page_record: could not find last_record");
- goto out_free;
- }
- ptr = kbuffer_next_event(kbuf, &ts);
- } else
- ptr = kbuffer_read_event(kbuf, &ts);
-
- if (!ptr)
- goto out_free;
-
- record = malloc(sizeof(*record));
- if (!record)
- return NULL;
- memset(record, 0, sizeof(*record));
-
- record->ts = ts;
- record->size = kbuffer_event_size(kbuf);
- record->record_size = kbuffer_curr_size(kbuf);
- record->cpu = 0;
- record->data = ptr;
- record->ref_count = 1;
-
- out_free:
- kbuffer_free(kbuf);
- return record;
-}
-
/**
* tracecmd_peek_data - return the record at the current location.
* @handle: input handle for the trace.dat file
@@ -153,56 +153,6 @@ static char *append_file(const char *dir, const char *name)
return ret < 0 ? NULL : file;
}
-/**
- * tracecmd_add_list - add an new string to a string list.
- * @list: list to add the string to (may be NULL)
- * @name: the string to add
- * @len: current length of list of strings.
- *
- * The typical usage is:
- *
- * systems = tracecmd_add_list(systems, name, len++);
- *
- * Returns the new allocated list with an allocated name added.
- * The list will end with NULL.
- */
-char **tracecmd_add_list(char **list, const char *name, int len)
-{
- if (!list)
- list = malloc(sizeof(*list) * 2);
- else
- list = realloc(list, sizeof(*list) * (len + 2));
- if (!list)
- return NULL;
-
- list[len] = strdup(name);
- if (!list[len])
- return NULL;
-
- list[len + 1] = NULL;
-
- return list;
-}
-
-/**
- * tracecmd_free_list - free a list created with tracecmd_add_list.
- * @list: The list to free.
- *
- * Frees the list as well as the names within the list.
- */
-void tracecmd_free_list(char **list)
-{
- int i;
-
- if (!list)
- return;
-
- for (i = 0; list[i]; i++)
- free(list[i]);
-
- free(list);
-}
-
/**
* tracecmd_add_id - add an int to the event id list
* @list: list to add the id to
@@ -233,160 +183,6 @@ int *tracecmd_add_id(int *list, int id, int len)
return list;
}
-/**
- * tracecmd_event_systems - return list of systems for tracing
- * @tracing_dir: directory holding the "events" directory
- *
- * Returns an allocated list of system names. Both the names and
- * the list must be freed with free().
- * The list returned ends with a "NULL" pointer.
- */
-char **tracecmd_event_systems(const char *tracing_dir)
-{
- struct dirent *dent;
- char **systems = NULL;
- char *events_dir;
- struct stat st;
- DIR *dir;
- int len = 0;
- int ret;
-
- if (!tracing_dir)
- return NULL;
-
- events_dir = append_file(tracing_dir, "events");
- if (!events_dir)
- return NULL;
-
- /*
- * Search all the directories in the events directory,
- * and collect the ones that have the "enable" file.
- */
- ret = stat(events_dir, &st);
- if (ret < 0 || !S_ISDIR(st.st_mode))
- goto out_free;
-
- dir = opendir(events_dir);
- if (!dir)
- goto out_free;
-
- while ((dent = readdir(dir))) {
- const char *name = dent->d_name;
- char *enable;
- char *sys;
-
- if (strcmp(name, ".") == 0 ||
- strcmp(name, "..") == 0)
- continue;
-
- sys = append_file(events_dir, name);
- ret = stat(sys, &st);
- if (ret < 0 || !S_ISDIR(st.st_mode)) {
- free(sys);
- continue;
- }
-
- enable = append_file(sys, "enable");
-
- ret = stat(enable, &st);
- if (ret >= 0)
- systems = tracecmd_add_list(systems, name, len++);
-
- free(enable);
- free(sys);
- }
-
- closedir(dir);
-
- out_free:
- free(events_dir);
- return systems;
-}
-
-/**
- * tracecmd_system_events - return list of events for system
- * @tracing_dir: directory holding the "events" directory
- * @system: the system to return the events for
- *
- * Returns an allocated list of event names. Both the names and
- * the list must be freed with free().
- * The list returned ends with a "NULL" pointer.
- */
-char **tracecmd_system_events(const char *tracing_dir, const char *system)
-{
- struct dirent *dent;
- char **events = NULL;
- char *events_dir;
- char *system_dir;
- struct stat st;
- DIR *dir;
- int len = 0;
- int ret;
-
- if (!tracing_dir || !system)
- return NULL;
-
- events_dir = append_file(tracing_dir, "events");
- if (!events_dir)
- return NULL;
-
- /*
- * Search all the directories in the systems directory,
- * and collect the ones that have the "enable" file.
- */
- ret = stat(events_dir, &st);
- if (ret < 0 || !S_ISDIR(st.st_mode))
- goto out_free;
-
- system_dir = append_file(events_dir, system);
- if (!system_dir)
- goto out_free;
-
- ret = stat(system_dir, &st);
- if (ret < 0 || !S_ISDIR(st.st_mode))
- goto out_free_sys;
-
- dir = opendir(system_dir);
- if (!dir)
- goto out_free_sys;
-
- while ((dent = readdir(dir))) {
- const char *name = dent->d_name;
- char *enable;
- char *event;
-
- if (strcmp(name, ".") == 0 ||
- strcmp(name, "..") == 0)
- continue;
-
- event = append_file(system_dir, name);
- ret = stat(event, &st);
- if (ret < 0 || !S_ISDIR(st.st_mode)) {
- free(event);
- continue;
- }
-
- enable = append_file(event, "enable");
-
- ret = stat(enable, &st);
- if (ret >= 0)
- events = tracecmd_add_list(events, name, len++);
-
- free(enable);
- free(event);
- }
-
- closedir(dir);
-
- out_free_sys:
- free(system_dir);
-
- out_free:
- free(events_dir);
-
- return events;
-}
-
static int read_file(const char *file, char **buffer)
{
char *buf;
@@ -604,67 +400,6 @@ int tracecmd_fill_local_events(const char *tracing_dir,
return ret;
}
-/**
- * tracecmd_local_plugins - returns an array of available tracer plugins
- * @tracing_dir: The directory that contains the tracing directory
- *
- * Returns an allocate list of plugins. The array ends with NULL.
- * Both the plugin names and array must be freed with free().
- */
-char **tracecmd_local_plugins(const char *tracing_dir)
-{
- char *available_tracers;
- struct stat st;
- char **plugins = NULL;
- char *buf;
- char *str, *saveptr;
- char *plugin;
- int slen;
- int len;
- int ret;
-
- if (!tracing_dir)
- return NULL;
-
- available_tracers = append_file(tracing_dir, "available_tracers");
- if (!available_tracers)
- return NULL;
-
- ret = stat(available_tracers, &st);
- if (ret < 0)
- goto out_free;
-
- len = read_file(available_tracers, &buf);
- if (len < 0)
- goto out_free;
-
- len = 0;
- for (str = buf; ; str = NULL) {
- plugin = strtok_r(str, " ", &saveptr);
- if (!plugin)
- break;
- if (!(slen = strlen(plugin)))
- continue;
-
- /* chop off any newlines */
- if (plugin[slen - 1] == '\n')
- plugin[slen - 1] = '\0';
-
- /* Skip the non tracers */
- if (strcmp(plugin, "nop") == 0 ||
- strcmp(plugin, "none") == 0)
- continue;
-
- plugins = tracecmd_add_list(plugins, plugin, len++);
- }
- free(buf);
-
- out_free:
- free(available_tracers);
-
- return plugins;
-}
-
struct add_plugin_data {
int ret;
int index;
@@ -9,6 +9,7 @@ DEFAULT_TARGET = $(bdir)/libtracefs.a
OBJS =
OBJS += tracefs-utils.o
OBJS += tracefs-instance.o
+OBJS += tracefs-events.o
OBJS := $(OBJS:%.o=$(bdir)/%.o)
DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d)
new file mode 100644
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * Updates:
+ * Copyright (C) 2019, VMware, Tzvetomir Stoyanov <tz.stoyanov@gmail.com>
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "kbuffer.h"
+#include "tracefs.h"
+#include "tracefs-local.h"
+
+static struct kbuffer *
+page_to_kbuf(struct tep_handle *tep, void *page, int size)
+{
+ enum kbuffer_long_size long_size;
+ enum kbuffer_endian endian;
+ struct kbuffer *kbuf;
+
+ if (tep_is_file_bigendian(tep))
+ endian = KBUFFER_ENDIAN_BIG;
+ else
+ endian = KBUFFER_ENDIAN_LITTLE;
+
+ if (tep_get_header_page_size(tep) == 8)
+ long_size = KBUFFER_LSIZE_8;
+ else
+ long_size = KBUFFER_LSIZE_4;
+
+ kbuf = kbuffer_alloc(long_size, endian);
+ if (!kbuf)
+ return NULL;
+
+ kbuffer_load_subbuffer(kbuf, page);
+ if (kbuffer_subbuffer_size(kbuf) > size) {
+ warning("%s: page_size > size", __func__);
+ kbuffer_free(kbuf);
+ kbuf = NULL;
+ }
+
+ return kbuf;
+}
+
+static int read_kbuf_record(struct kbuffer *kbuf, struct tep_record *record)
+{
+ unsigned long long ts;
+ void *ptr;
+
+ ptr = kbuffer_read_event(kbuf, &ts);
+ if (!ptr || !record)
+ return -1;
+
+ memset(record, 0, sizeof(*record));
+ record->ts = ts;
+ record->size = kbuffer_event_size(kbuf);
+ record->record_size = kbuffer_curr_size(kbuf);
+ record->cpu = 0;
+ record->data = ptr;
+ record->ref_count = 1;
+
+ kbuffer_next_event(kbuf, NULL);
+
+ return 0;
+}
+
+static int
+get_events_in_page(struct tep_handle *tep, void *page,
+ int size, int cpu,
+ int (*callback)(struct tep_event *,
+ struct tep_record *,
+ int, void *),
+ void *callback_context)
+{
+ struct tep_record record;
+ struct tep_event *event;
+ struct kbuffer *kbuf;
+ int id, cnt = 0;
+ int ret;
+
+ if (size <= 0)
+ return 0;
+
+ kbuf = page_to_kbuf(tep, page, size);
+ if (!kbuf)
+ return 0;
+
+ ret = read_kbuf_record(kbuf, &record);
+ while (!ret) {
+ id = tep_data_type(tep, &record);
+ event = tep_find_event(tep, id);
+ if (event) {
+ cnt++;
+ if (callback &&
+ callback(event, &record, cpu, callback_context))
+ break;
+ }
+ ret = read_kbuf_record(kbuf, &record);
+ }
+
+ kbuffer_free(kbuf);
+
+ return cnt;
+}
+
+/*
+ * tracefs_iterate_raw_events - Iterate through events in trace_pipe_raw,
+ * per CPU trace buffers
+ * @tep: a handle to the trace event parser context
+ * @instance: ftrace instance, can be NULL for the top instance
+ * @callback: A user function, called for each record from the file
+ * @callback_context: A custom context, passed to the user callback function
+ *
+ * If the @callback returns non-zero, the iteration stops - in that case all
+ * records from the current page will be lost from future reads
+ *
+ * Returns -1 in case of an error, or 0 otherwise
+ */
+int tracefs_iterate_raw_events(struct tep_handle *tep,
+ struct tracefs_instance *instance,
+ int (*callback)(struct tep_event *,
+ struct tep_record *,
+ int, void *),
+ void *callback_context)
+{
+ unsigned int p_size;
+ struct dirent *dent;
+ char file[PATH_MAX];
+ void *page = NULL;
+ struct stat st;
+ char *path;
+ DIR *dir;
+ int ret;
+ int cpu;
+ int fd;
+ int r;
+
+ if (!tep || !callback)
+ return -1;
+
+ p_size = getpagesize();
+ path = tracefs_instance_get_file(instance, "per_cpu");
+ if (!path)
+ return -1;
+ dir = opendir(path);
+ if (!dir) {
+ ret = -1;
+ goto error;
+ }
+ page = malloc(p_size);
+ if (!page) {
+ ret = -1;
+ goto error;
+ }
+ while ((dent = readdir(dir))) {
+ const char *name = dent->d_name;
+
+ if (strlen(name) < 4 || strncmp(name, "cpu", 3) != 0)
+ continue;
+ cpu = atoi(name + 3);
+ sprintf(file, "%s/%s", path, name);
+ ret = stat(file, &st);
+ if (ret < 0 || !S_ISDIR(st.st_mode))
+ continue;
+
+ sprintf(file, "%s/%s/trace_pipe_raw", path, name);
+ fd = open(file, O_RDONLY | O_NONBLOCK);
+ if (fd < 0)
+ continue;
+ do {
+ r = read(fd, page, p_size);
+ if (r > 0)
+ get_events_in_page(tep, page, r, cpu,
+ callback, callback_context);
+ } while (r > 0);
+ close(fd);
+ }
+ ret = 0;
+
+error:
+ if (dir)
+ closedir(dir);
+ free(page);
+ tracefs_put_tracing_file(path);
+ return ret;
+}
+
+static char **add_list_string(char **list, const char *name, int len)
+{
+ if (!list)
+ list = malloc(sizeof(*list) * 2);
+ else
+ list = realloc(list, sizeof(*list) * (len + 2));
+ if (!list)
+ return NULL;
+
+ list[len] = strdup(name);
+ if (!list[len])
+ return NULL;
+
+ list[len + 1] = NULL;
+
+ return list;
+}
+
+static char *append_file(const char *dir, const char *name)
+{
+ char *file;
+ int ret;
+
+ ret = asprintf(&file, "%s/%s", dir, name);
+
+ return ret < 0 ? NULL : file;
+}
+
+/**
+ * tracefs_list_free - free list if strings, returned by APIs
+ * tracefs_event_systems()
+ * tracefs_system_events()
+ *
+ *@list pointer to a list of strings, the last one must be NULL
+ */
+void tracefs_list_free(char **list)
+{
+ int i;
+
+ if (!list)
+ return;
+
+ for (i = 0; list[i]; i++)
+ free(list[i]);
+
+ free(list);
+}
+
+/**
+ * tracefs_event_systems - return list of systems for tracing
+ * @tracing_dir: directory holding the "events" directory
+ * if NULL, top tracing directory is used
+ *
+ * Returns an allocated list of system names. Both the names and
+ * the list must be freed with tracefs_list_free()
+ * The list returned ends with a "NULL" pointer
+ */
+char **tracefs_event_systems(const char *tracing_dir)
+{
+ struct dirent *dent;
+ char **systems = NULL;
+ char *events_dir;
+ struct stat st;
+ DIR *dir;
+ int len = 0;
+ int ret;
+
+ if (!tracing_dir)
+ tracing_dir = tracefs_get_tracing_dir();
+
+ if (!tracing_dir)
+ return NULL;
+
+ events_dir = append_file(tracing_dir, "events");
+ if (!events_dir)
+ return NULL;
+
+ /*
+ * Search all the directories in the events directory,
+ * and collect the ones that have the "enable" file.
+ */
+ ret = stat(events_dir, &st);
+ if (ret < 0 || !S_ISDIR(st.st_mode))
+ goto out_free;
+
+ dir = opendir(events_dir);
+ if (!dir)
+ goto out_free;
+
+ while ((dent = readdir(dir))) {
+ const char *name = dent->d_name;
+ char *enable;
+ char *sys;
+
+ if (strcmp(name, ".") == 0 ||
+ strcmp(name, "..") == 0)
+ continue;
+
+ sys = append_file(events_dir, name);
+ ret = stat(sys, &st);
+ if (ret < 0 || !S_ISDIR(st.st_mode)) {
+ free(sys);
+ continue;
+ }
+
+ enable = append_file(sys, "enable");
+
+ ret = stat(enable, &st);
+ if (ret >= 0)
+ systems = add_list_string(systems, name, len++);
+
+ free(enable);
+ free(sys);
+ }
+
+ closedir(dir);
+
+ out_free:
+ free(events_dir);
+ return systems;
+}
+
+/**
+ * tracefs_system_events - return list of events for system
+ * @tracing_dir: directory holding the "events" directory
+ * @system: the system to return the events for
+ *
+ * Returns an allocated list of event names. Both the names and
+ * the list must be freed with tracefs_list_free()
+ * The list returned ends with a "NULL" pointer
+ */
+char **tracefs_system_events(const char *tracing_dir, const char *system)
+{
+ struct dirent *dent;
+ char **events = NULL;
+ char *system_dir = NULL;
+ struct stat st;
+ DIR *dir;
+ int len = 0;
+ int ret;
+
+ if (!tracing_dir)
+ tracing_dir = tracefs_get_tracing_dir();
+
+ if (!tracing_dir || !system)
+ return NULL;
+
+ asprintf(&system_dir, "%s/events/%s", tracing_dir, system);
+ if (!system_dir)
+ return NULL;
+
+ ret = stat(system_dir, &st);
+ if (ret < 0 || !S_ISDIR(st.st_mode))
+ goto out_free;
+
+ dir = opendir(system_dir);
+ if (!dir)
+ goto out_free;
+
+ while ((dent = readdir(dir))) {
+ const char *name = dent->d_name;
+ char *event;
+
+ if (strcmp(name, ".") == 0 ||
+ strcmp(name, "..") == 0)
+ continue;
+
+ event = append_file(system_dir, name);
+ ret = stat(event, &st);
+ if (ret < 0 || !S_ISDIR(st.st_mode)) {
+ free(event);
+ continue;
+ }
+
+ events = add_list_string(events, name, len++);
+
+ free(event);
+ }
+
+ closedir(dir);
+
+ out_free:
+ free(system_dir);
+
+ return events;
+}
+
+/**
+ * tracefs_tracers - returns an array of available tracers
+ * @tracing_dir: The directory that contains the tracing directory
+ *
+ * Returns an allocate list of plugins. The array ends with NULL
+ * Both the plugin names and array must be freed with free()
+ */
+char **tracefs_tracers(const char *tracing_dir)
+{
+ char *available_tracers;
+ struct stat st;
+ char **plugins = NULL;
+ char *buf;
+ char *str, *saveptr;
+ char *plugin;
+ int slen;
+ int len;
+ int ret;
+
+ if (!tracing_dir)
+ return NULL;
+
+ available_tracers = append_file(tracing_dir, "available_tracers");
+ if (!available_tracers)
+ return NULL;
+
+ ret = stat(available_tracers, &st);
+ if (ret < 0)
+ goto out_free;
+
+ len = str_read_file(available_tracers, &buf);
+ if (len < 0)
+ goto out_free;
+
+ len = 0;
+ for (str = buf; ; str = NULL) {
+ plugin = strtok_r(str, " ", &saveptr);
+ if (!plugin)
+ break;
+ slen = strlen(plugin);
+ if (!slen)
+ continue;
+
+ /* chop off any newlines */
+ if (plugin[slen - 1] == '\n')
+ plugin[slen - 1] = '\0';
+
+ /* Skip the non tracers */
+ if (strcmp(plugin, "nop") == 0 ||
+ strcmp(plugin, "none") == 0)
+ continue;
+
+ plugins = add_list_string(plugins, plugin, len++);
+ }
+ free(buf);
+
+ out_free:
+ free(available_tracers);
+
+ return plugins;
+}
@@ -4164,96 +4164,35 @@ static void add_func(struct func_list **list, const char *mod, const char *func)
*list = item;
}
-static unsigned long long
-find_ts_in_page(struct tep_handle *pevent, void *page, int size)
+static int find_ts(struct tep_event *event, struct tep_record *record,
+ int cpu, void *context)
{
+ unsigned long long *ts = (unsigned long long *)context;
struct tep_format_field *field;
- struct tep_record *last_record = NULL;
- struct tep_record *record;
- struct tep_event *event;
- unsigned long long ts = 0;
- int id;
- if (size <= 0)
- return 0;
+ if (!ts)
+ return -1;
- while (!ts) {
- record = tracecmd_read_page_record(pevent, page, size,
- last_record);
- if (!record)
- break;
- free_record(last_record);
- id = tep_data_type(pevent, record);
- event = tep_find_event(pevent, id);
- if (event) {
- /* Make sure this is our event */
- field = tep_find_field(event, "buf");
- /* the trace_marker adds a '\n' */
- if (field && strcmp(STAMP"\n", record->data + field->offset) == 0)
- ts = record->ts;
- }
- last_record = record;
+ field = tep_find_field(event, "buf");
+ if (field && strcmp(STAMP"\n", record->data + field->offset) == 0) {
+ *ts = record->ts;
+ return 1;
}
- free_record(last_record);
- return ts;
+ return 0;
}
-static unsigned long long find_time_stamp(struct tep_handle *pevent)
+static unsigned long long find_time_stamp(struct tep_handle *tep)
{
- struct dirent *dent;
unsigned long long ts = 0;
- void *page;
- char *path;
- char *file;
- DIR *dir;
- int len;
- int fd;
- int r;
-
- path = tracefs_get_tracing_file("per_cpu");
- if (!path)
- return 0;
-
- dir = opendir(path);
- if (!dir)
- goto out;
- len = strlen(path);
- file = malloc(len + strlen("trace_pipe_raw") + 32);
- page = malloc(page_size);
- if (!file || !page)
- die("Failed to allocate time_stamp info");
+ if (!tracefs_iterate_raw_events(tep, NULL, find_ts, &ts))
+ return ts;
- while ((dent = readdir(dir))) {
- const char *name = dent->d_name;
-
- if (strncmp(name, "cpu", 3) != 0)
- continue;
-
- sprintf(file, "%s/%s/trace_pipe_raw", path, name);
- fd = open(file, O_RDONLY | O_NONBLOCK);
- if (fd < 0)
- continue;
- do {
- r = read(fd, page, page_size);
- ts = find_ts_in_page(pevent, page, r);
- if (ts)
- break;
- } while (r > 0);
- close(fd);
- if (ts)
- break;
- }
- free(file);
- free(page);
- closedir(dir);
-
- out:
- tracefs_put_tracing_file(path);
- return ts;
+ return 0;
}
+
static char *read_file(char *file, int *psize)
{
return tracefs_instance_file_read(top_instance.tracefs, file, psize);
@@ -4271,7 +4210,7 @@ static char *get_date_to_ts(void)
unsigned long long min_stamp;
unsigned long long min_ts;
unsigned long long ts;
- struct tep_handle *pevent;
+ struct tep_handle *tep;
struct timespec start;
struct timespec end;
char *date2ts = NULL;
@@ -4283,16 +4222,18 @@ static char *get_date_to_ts(void)
int i;
/* Set up a pevent to read the raw format */
- pevent = tep_alloc();
- if (!pevent) {
+ tep = tep_alloc();
+ if (!tep) {
warning("failed to alloc pevent, --date ignored");
return NULL;
}
+ tep_set_file_bigendian(tep, tracecmd_host_bigendian());
+
buf = read_file("events/header_page", &size);
if (!buf)
goto out_pevent;
- ret = tep_parse_header_page(pevent, buf, size, sizeof(unsigned long));
+ ret = tep_parse_header_page(tep, buf, size, sizeof(unsigned long));
free(buf);
if (ret < 0) {
warning("Can't parse header page, --date ignored");
@@ -4303,7 +4244,7 @@ static char *get_date_to_ts(void)
buf = read_file("events/ftrace/print/format", &size);
if (!buf)
goto out_pevent;
- ret = tep_parse_event(pevent, buf, size, "ftrace");
+ ret = tep_parse_event(tep, buf, size, "ftrace");
free(buf);
if (ret < 0) {
warning("Can't parse print event, --date ignored");
@@ -4328,7 +4269,7 @@ static char *get_date_to_ts(void)
clock_gettime(CLOCK_REALTIME, &end);
tracecmd_disable_tracing();
- ts = find_time_stamp(pevent);
+ ts = find_time_stamp(tep);
if (!ts)
continue;
@@ -4365,7 +4306,7 @@ static char *get_date_to_ts(void)
snprintf(date2ts, 19, "0x%llx", diff/1000);
out_pevent:
- tep_free(pevent);
+ tep_free(tep);
return date2ts;
}
The functionality related to ftrace events and systems is moved from trace-cmd application and libtracecmd to libtracefs. The following libtracecmd APIs are removed: tracecmd_read_page_record(); tracecmd_event_systems(); tracecmd_system_events(); tracecmd_local_plugins(); tracecmd_add_list(); tracecmd_free_list(); The following new library APIs are introduced: tracefs_read_page_record(); tracefs_event_systems(); tracefs_system_events(); tracefs_local_plugins(); tracefs_iterate_raw_events(); tracefs_list_free(); Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com> --- include/trace-cmd/trace-cmd.h | 8 - include/tracefs/tracefs.h | 16 + kernel-shark/src/KsCaptureDialog.cpp | 2 +- lib/trace-cmd/trace-input.c | 95 ------ lib/trace-cmd/trace-util.c | 265 ---------------- lib/tracefs/Makefile | 1 + lib/tracefs/tracefs-events.c | 442 +++++++++++++++++++++++++++ tracecmd/trace-record.c | 107 ++----- 8 files changed, 484 insertions(+), 452 deletions(-) create mode 100644 lib/tracefs/tracefs-events.c