[PATCH 05/11] trace-cmd: allow for custom show and handle init

From: Josef Bacik
Date: Fri Nov 20 2015 - 15:59:44 EST


External applications that need to hook into the streaming infrastructure need a
way to have the handle init'ed in a specific way and need a way to provide their
own read function so they can intercept events. This patch adds the neccessary
definitions and hooks. Thanks,

Signed-off-by: Josef Bacik <jbacik@xxxxxx>
---
trace-cmd.h | 10 ++++++++++
trace-input.c | 24 ++++++++++++++++++++++++
trace-local.h | 11 ++++-------
trace-profile.c | 10 +++++-----
trace-read.c | 13 ++++++-------
trace-record.c | 21 +++++++++------------
trace-stream.c | 12 ++++++------
7 files changed, 64 insertions(+), 37 deletions(-)

diff --git a/trace-cmd.h b/trace-cmd.h
index 9a9ca30..7bf836f 100644
--- a/trace-cmd.h
+++ b/trace-cmd.h
@@ -61,6 +61,7 @@ void free_record(struct pevent_record *record);
struct tracecmd_input;
struct tracecmd_output;
struct tracecmd_recorder;
+struct hook_list;

static inline int tracecmd_host_bigendian(void)
{
@@ -102,6 +103,11 @@ struct tracecmd_ftrace {
int long_size;
};

+typedef void (*tracecmd_show_data_func)(struct tracecmd_input *handle,
+ struct pevent_record *record);
+typedef void (*tracecmd_handle_init_func)(struct tracecmd_input *handle,
+ struct hook_list *hook, int global);
+
struct tracecmd_input *tracecmd_alloc(const char *file);
struct tracecmd_input *tracecmd_alloc_fd(int fd);
struct tracecmd_input *tracecmd_open(const char *file);
@@ -186,6 +192,10 @@ tracecmd_get_cursor(struct tracecmd_input *handle, int cpu);
int tracecmd_ftrace_overrides(struct tracecmd_input *handle, struct tracecmd_ftrace *finfo);
struct pevent *tracecmd_get_pevent(struct tracecmd_input *handle);
bool tracecmd_get_use_trace_clock(struct tracecmd_input *handle);
+tracecmd_show_data_func
+tracecmd_get_show_data_func(struct tracecmd_input *handle);
+void tracecmd_set_show_data_func(struct tracecmd_input *handle,
+ tracecmd_show_data_func func);

char *tracecmd_get_tracing_file(const char *name);
void tracecmd_put_tracing_file(char *name);
diff --git a/trace-input.c b/trace-input.c
index 4b3aed8..8a131fc 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -37,6 +37,7 @@
#include <errno.h>

#include "trace-cmd-local.h"
+#include "trace-local.h"
#include "kbuffer.h"
#include "list.h"

@@ -108,6 +109,9 @@ struct tracecmd_input {
size_t ftrace_files_start;
size_t event_files_start;
size_t total_file_size;
+
+ /* For custom profilers. */
+ tracecmd_show_data_func show_data_func;
};

__thread struct tracecmd_input *tracecmd_curr_thread_handle;
@@ -3001,3 +3005,23 @@ bool tracecmd_get_use_trace_clock(struct tracecmd_input *handle)
{
return handle->use_trace_clock;
}
+
+/**
+ * tracecmd_get_show_data_func - return the show data func
+ * @handle: input handle for the trace.dat file
+ */
+tracecmd_show_data_func
+tracecmd_get_show_data_func(struct tracecmd_input *handle)
+{
+ return handle->show_data_func;
+}
+
+/**
+ * tracecmd_set_show_data_func - set the show data func
+ * @handle: input handle for the trace.dat file
+ */
+void tracecmd_set_show_data_func(struct tracecmd_input *handle,
+ tracecmd_show_data_func func)
+{
+ handle->show_data_func = func;
+}
diff --git a/trace-local.h b/trace-local.h
index a1596e7..f21f665 100644
--- a/trace-local.h
+++ b/trace-local.h
@@ -77,8 +77,6 @@ void trace_stat(int argc, char **argv);

struct hook_list;

-int trace_profile_record(struct tracecmd_input *handle,
- struct pevent_record *record, int cpu);
void trace_init_profile(struct tracecmd_input *handle, struct hook_list *hooks,
int global);
int trace_profile(void);
@@ -86,12 +84,11 @@ void trace_profile_set_merge_like_comms(void);

struct tracecmd_input *
trace_stream_init(struct buffer_instance *instance, int cpu, int fd, int cpus,
- int profile, struct hook_list *hooks, int global);
-int trace_stream_read(struct pid_record_data *pids, int nr_pids, struct timeval *tv,
- int profile);
+ struct hook_list *hooks,
+ tracecmd_handle_init_func handle_init, int global);
+int trace_stream_read(struct pid_record_data *pids, int nr_pids, struct timeval *tv);

-void trace_show_data(struct tracecmd_input *handle, struct pevent_record *record,
- int profile);
+void trace_show_data(struct tracecmd_input *handle, struct pevent_record *record);

/* --- event interation --- */

diff --git a/trace-profile.c b/trace-profile.c
index 0304e9b..7e41025 100644
--- a/trace-profile.c
+++ b/trace-profile.c
@@ -704,8 +704,8 @@ find_event_data(struct handle_data *h, int id)
return NULL;
}

-int trace_profile_record(struct tracecmd_input *handle,
- struct pevent_record *record, int cpu)
+static void trace_profile_record(struct tracecmd_input *handle,
+ struct pevent_record *record)
{
static struct handle_data *last_handle;
struct pevent_record *stack_record;
@@ -714,6 +714,7 @@ int trace_profile_record(struct tracecmd_input *handle,
struct handle_data *h;
struct pevent *pevent;
unsigned long long pid;
+ int cpu = record->cpu;
int id;

if (last_handle && last_handle->handle == handle)
@@ -738,7 +739,7 @@ int trace_profile_record(struct tracecmd_input *handle,
event_data = find_event_data(h, id);

if (!event_data)
- return -1;
+ return;


/* Get this current PID */
@@ -757,8 +758,6 @@ int trace_profile_record(struct tracecmd_input *handle,
free_record(stack_record);
task->last_stack = NULL;
}
-
- return 0;
}

static struct event_data *
@@ -1233,6 +1232,7 @@ void trace_init_profile(struct tracecmd_input *handle, struct hook_list *hook,
int ret;
int i;

+ tracecmd_set_show_data_func(handle, trace_profile_record);
h = malloc_or_die(sizeof(*h));
memset(h, 0, sizeof(*h));
h->next = handles;
diff --git a/trace-read.c b/trace-read.c
index 4459ea7..1a71629 100644
--- a/trace-read.c
+++ b/trace-read.c
@@ -739,22 +739,21 @@ static void finish_wakeup(void)
trace_hash_free(&wakeup_hash);
}

-void trace_show_data(struct tracecmd_input *handle, struct pevent_record *record,
- int profile)
+void trace_show_data(struct tracecmd_input *handle, struct pevent_record *record)
{
+ tracecmd_show_data_func func = tracecmd_get_show_data_func(handle);
struct pevent *pevent;
struct trace_seq s;
int cpu = record->cpu;
bool use_trace_clock;

- pevent = tracecmd_get_pevent(handle);
-
test_save(record, cpu);

- if (profile) {
- trace_profile_record(handle, record, cpu);
+ if (func) {
+ func(handle, record);
return;
}
+ pevent = tracecmd_get_pevent(handle);

trace_seq_init(&s);
if (record->missed_events > 0)
@@ -1159,7 +1158,7 @@ static void read_data_info(struct list_head *handle_list, enum output_type otype
}
if (last_record) {
print_handle_file(last_handle);
- trace_show_data(last_handle->handle, last_record, profile);
+ trace_show_data(last_handle->handle, last_record);
free_handle_record(last_handle);
}
} while (last_record);
diff --git a/trace-record.c b/trace-record.c
index 7c471ab..f202d44 100644
--- a/trace-record.c
+++ b/trace-record.c
@@ -67,9 +67,10 @@ enum trace_type {
TRACE_TYPE_START = (1 << 1),
TRACE_TYPE_STREAM = (1 << 2),
TRACE_TYPE_EXTRACT = (1 << 3),
- TRACE_TYPE_PROFILE = (1 << 4) | TRACE_TYPE_STREAM,
};

+static tracecmd_handle_init_func handle_init = NULL;
+
static int rt_prio;

static int use_tcp;
@@ -564,7 +565,6 @@ static void delete_thread_data(void)
static void stop_threads(enum trace_type type)
{
struct timeval tv = { 0, 0 };
- int profile = (type & TRACE_TYPE_PROFILE) == TRACE_TYPE_PROFILE;
int ret;
int i;

@@ -581,7 +581,7 @@ static void stop_threads(enum trace_type type)
/* Flush out the pipes */
if (type & TRACE_TYPE_STREAM) {
do {
- ret = trace_stream_read(pids, recorder_threads, &tv, profile);
+ ret = trace_stream_read(pids, recorder_threads, &tv);
} while (ret > 0);
}

@@ -916,7 +916,6 @@ static pid_t trace_waitpid(enum trace_type type, pid_t pid, int *status, int opt
{
struct timeval tv = { 1, 0 };
int ret;
- int profile = (type & TRACE_TYPE_PROFILE) == TRACE_TYPE_PROFILE;

if (type & TRACE_TYPE_STREAM)
options |= WNOHANG;
@@ -927,7 +926,7 @@ static pid_t trace_waitpid(enum trace_type type, pid_t pid, int *status, int opt
return ret;

if (type & TRACE_TYPE_STREAM)
- trace_stream_read(pids, recorder_threads, &tv, profile);
+ trace_stream_read(pids, recorder_threads, &tv);
} while (1);
}
#ifndef NO_PTRACE
@@ -1085,12 +1084,11 @@ static inline void ptrace_attach(int pid) { }
static void trace_or_sleep(enum trace_type type)
{
struct timeval tv = { 1 , 0 };
- int profile = (type & TRACE_TYPE_PROFILE) == TRACE_TYPE_PROFILE;

if (do_ptrace && filter_pid >= 0)
ptrace_wait(type, filter_pid);
else if (type & TRACE_TYPE_STREAM)
- trace_stream_read(pids, recorder_threads, &tv, profile);
+ trace_stream_read(pids, recorder_threads, &tv);
else
sleep(10);
}
@@ -2576,7 +2574,6 @@ static void finish_network(void)

static void start_threads(enum trace_type type, int global)
{
- int profile = (type & TRACE_TYPE_PROFILE) == TRACE_TYPE_PROFILE;
struct buffer_instance *instance;
int *brass = NULL;
int i = 0;
@@ -2600,7 +2597,7 @@ static void start_threads(enum trace_type type, int global)
die("pipe");
pids[i].stream = trace_stream_init(instance, x,
brass[0], cpu_count,
- profile, hooks,
+ hooks, handle_init,
global);
if (!pids[i].stream)
die("Creating stream for %d", i);
@@ -3869,8 +3866,8 @@ void trace_record (int argc, char **argv)
else if ((stream = strcmp(argv[1], "stream") == 0))
; /* do nothing */
else if ((profile = strcmp(argv[1], "profile") == 0)) {
+ handle_init = trace_init_profile;
events = 1;
-
} else if (strcmp(argv[1], "stop") == 0) {
for (;;) {
int c;
@@ -4238,6 +4235,7 @@ void trace_record (int argc, char **argv)
recorder_flags |= TRACECMD_RECORD_NOSPLICE;
break;
case OPT_profile:
+ handle_init = trace_init_profile;
instance->profile = 1;
events = 1;
break;
@@ -4351,8 +4349,7 @@ void trace_record (int argc, char **argv)
else if (extract)
type = TRACE_TYPE_EXTRACT;
else if (profile)
- /* PROFILE includes the STREAM bit */
- type = TRACE_TYPE_PROFILE;
+ type = TRACE_TYPE_STREAM;
else
type = TRACE_TYPE_START;

diff --git a/trace-stream.c b/trace-stream.c
index 9ebe65b..0dbeaf2 100644
--- a/trace-stream.c
+++ b/trace-stream.c
@@ -35,7 +35,8 @@
*/
struct tracecmd_input *
trace_stream_init(struct buffer_instance *instance, int cpu, int fd, int cpus,
- int profile, struct hook_list *hooks, int global)
+ struct hook_list *hooks,
+ tracecmd_handle_init_func handle_init, int global)
{
struct tracecmd_input *trace_input;
struct tracecmd_output *trace_output;
@@ -75,8 +76,8 @@ trace_stream_init(struct buffer_instance *instance, int cpu, int fd, int cpus,
if (tracecmd_read_headers(trace_input) < 0)
goto fail_free_input;

- if (profile)
- trace_init_profile(trace_input, hooks, global);
+ if (handle_init)
+ handle_init(trace_input, hooks, global);

make_pipe:
/* Do not block on this pipe */
@@ -98,8 +99,7 @@ trace_stream_init(struct buffer_instance *instance, int cpu, int fd, int cpus,
return NULL;
}

-int trace_stream_read(struct pid_record_data *pids, int nr_pids, struct timeval *tv,
- int profile)
+int trace_stream_read(struct pid_record_data *pids, int nr_pids, struct timeval *tv)
{
struct pevent_record *record;
struct pid_record_data *pid;
@@ -127,7 +127,7 @@ int trace_stream_read(struct pid_record_data *pids, int nr_pids, struct timeval
last_pid = pid;
}
if (last_pid) {
- trace_show_data(last_pid->instance->handle, last_pid->record, profile);
+ trace_show_data(last_pid->instance->handle, last_pid->record);
free_record(last_pid->record);
last_pid->record = NULL;
return 1;
--
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/