From: Kyle Tomsic <ktomsic(a)lexmark.com>
The trace extension was written assuming only one trace buffer, the
top-level (global) buffer, is available, which was true until the 3.10
kernel release. Since there was only one buffer, most of the functions
in trace.c accessed it through (static) global variables.
In order to support multiple buffer extraction, the functions that use
the top-level instance were refactored to take it as an argument. This
will allow reusing these functions for other ftrace buffers; support for
extracting these will be added in the other patch in this series.
---
extensions/trace.c | 235 ++++++++++++++++++++++++++++-------------------------
1 file changed, 126 insertions(+), 109 deletions(-)
diff --git a/extensions/trace.c b/extensions/trace.c
index f8ccd91..f97aa6a 100644
--- a/extensions/trace.c
+++ b/extensions/trace.c
@@ -101,16 +101,21 @@ struct ring_buffer_per_cpu {
};
static ulong global_trace;
-static ulong global_trace_buffer;
-static ulong global_max_buffer;
-static ulong global_ring_buffer;
-static unsigned global_pages;
-static struct ring_buffer_per_cpu *global_buffers;
-
static ulong max_tr_trace;
-static ulong max_tr_ring_buffer;
-static unsigned max_tr_pages;
-static struct ring_buffer_per_cpu *max_tr_buffers;
+
+struct trace_instance {
+ ulong trace_buffer;
+ ulong max_buffer;
+ ulong ring_buffer;
+ unsigned pages;
+ struct ring_buffer_per_cpu *buffers;
+
+ ulong max_tr_ring_buffer;
+ unsigned max_tr_pages;
+ struct ring_buffer_per_cpu *max_tr_buffers;
+};
+
+static struct trace_instance global_trace_instance;
static ulong ftrace_events;
static ulong current_trace;
@@ -435,64 +440,54 @@ out_fail:
return -1;
}
-static int ftrace_int_global_trace(void)
+static int ftrace_init_trace(struct trace_instance *ti, ulong instance_addr)
{
if (trace_buffer_available) {
- global_trace_buffer = global_trace + koffset(trace_array, trace_buffer);
- read_value(global_ring_buffer, global_trace_buffer, trace_buffer, buffer);
+ ti->trace_buffer = instance_addr +
+ koffset(trace_array, trace_buffer);
+ read_value(ti->ring_buffer, ti->trace_buffer,
+ trace_buffer, buffer);
+
+ if (max_buffer_available) {
+ ti->max_buffer = instance_addr +
+ koffset(trace_array, max_buffer);
+ read_value(ti->max_tr_ring_buffer, ti->max_buffer,
+ trace_buffer, buffer);
+ }
} else {
- read_value(global_ring_buffer, global_trace, trace_array, buffer);
- read_value(global_pages, global_ring_buffer, ring_buffer, pages);
+ read_value(ti->ring_buffer, instance_addr, trace_array, buffer);
+ read_value(ti->pages, ti->ring_buffer, ring_buffer, pages);
+
+ read_value(ti->max_tr_ring_buffer, max_tr_trace, trace_array, buffer);
+ if (ti->max_tr_ring_buffer)
+ read_value(ti->max_tr_pages, ti->max_tr_ring_buffer, ring_buffer, pages);
}
- global_buffers = calloc(sizeof(*global_buffers), nr_cpu_ids);
- if (global_buffers == NULL)
+ ti->buffers = calloc(sizeof(*ti->buffers), nr_cpu_ids);
+ if (ti->buffers == NULL)
goto out_fail;
- if (ftrace_init_buffers(global_buffers, global_ring_buffer,
- global_pages) < 0)
+ if (ftrace_init_buffers(ti->buffers, ti->ring_buffer,
+ ti->pages) < 0)
goto out_fail;
- return 0;
-
-out_fail:
- free(global_buffers);
- return -1;
-}
-
-static int ftrace_int_max_tr_trace(void)
-{
- if (trace_buffer_available) {
- if (!max_buffer_available)
- return 0;
-
- global_max_buffer = global_trace + koffset(trace_array, max_buffer);
- read_value(max_tr_ring_buffer, global_max_buffer, trace_buffer, buffer);
- } else {
- read_value(max_tr_ring_buffer, max_tr_trace, trace_array, buffer);
-
- if (!max_tr_ring_buffer)
- return 0;
-
- read_value(max_tr_pages, max_tr_ring_buffer, ring_buffer, pages);
- }
-
- max_tr_buffers = calloc(sizeof(*max_tr_buffers), nr_cpu_ids);
- if (max_tr_buffers == NULL)
+ ti->max_tr_buffers = calloc(sizeof(*ti->max_tr_buffers), nr_cpu_ids);
+ if (ti->max_tr_buffers == NULL)
goto out_fail;
- if (ftrace_init_buffers(max_tr_buffers, max_tr_ring_buffer,
- max_tr_pages) < 0)
+ if (ftrace_init_buffers(ti->max_tr_buffers, ti->max_tr_ring_buffer,
+ ti->max_tr_pages) < 0)
goto out_fail;
return 0;
out_fail:
- free(max_tr_buffers);
- max_tr_ring_buffer = 0;
+ free(ti->max_tr_buffers);
+ free(ti->buffers);
return -1;
}
+
static int ftrace_init_current_tracer(void)
{
ulong addr;
@@ -504,7 +499,7 @@ static int ftrace_init_current_tracer(void)
} else {
read_value(addr, current_trace, POINTER_SYM, POINTER);
}
-
+
read_value(addr, addr, tracer, name);
read_string(addr, tmp, 128);
@@ -564,10 +559,9 @@ static int ftrace_init(void)
return -1;
print_offsets();
- if (ftrace_int_global_trace() < 0)
+ if (ftrace_init_trace(&global_trace_instance, global_trace) < 0)
goto out_0;
- ftrace_int_max_tr_trace();
if (ftrace_init_event_types() < 0)
goto out_1;
@@ -580,12 +574,12 @@ static int ftrace_init(void)
out_2:
ftrace_destroy_event_types();
out_1:
- if (max_tr_ring_buffer) {
- ftrace_destroy_buffers(max_tr_buffers);
- free(max_tr_buffers);
+ if (global_trace_instance.max_tr_ring_buffer) {
+ ftrace_destroy_buffers(global_trace_instance.max_tr_buffers);
+ free(global_trace_instance.max_tr_buffers);
}
- ftrace_destroy_buffers(global_buffers);
- free(global_buffers);
+ ftrace_destroy_buffers(global_trace_instance.buffers);
+ free(global_trace_instance.buffers);
out_0:
return -1;
}
@@ -595,13 +589,13 @@ static void ftrace_destroy(void)
free(current_tracer_name);
ftrace_destroy_event_types();
- if (max_tr_ring_buffer) {
- ftrace_destroy_buffers(max_tr_buffers);
- free(max_tr_buffers);
+ if (global_trace_instance.max_tr_ring_buffer) {
+ ftrace_destroy_buffers(global_trace_instance.max_tr_buffers);
+ free(global_trace_instance.max_tr_buffers);
}
- ftrace_destroy_buffers(global_buffers);
- free(global_buffers);
+ ftrace_destroy_buffers(global_trace_instance.buffers);
+ free(global_trace_instance.buffers);
}
static int ftrace_dump_page(int fd, ulong page, void *page_tmp)
@@ -652,7 +646,8 @@ static int try_mkdir(const char *pathname, mode_t mode)
return 0;
}
-static int ftrace_dump_buffers(const char *per_cpu_path)
+static int ftrace_dump_buffers(const char *per_cpu_path,
+ struct trace_instance *ti)
{
int i;
void *page_tmp;
@@ -664,7 +659,7 @@ static int ftrace_dump_buffers(const char *per_cpu_path)
return -1;
for (i = 0; i < nr_cpu_ids; i++) {
- struct ring_buffer_per_cpu *cpu_buffer = &global_buffers[i];
+ struct ring_buffer_per_cpu *cpu_buffer = &ti->buffers[i];
if (!cpu_buffer->kaddr)
continue;
@@ -679,7 +674,7 @@ static int ftrace_dump_buffers(const char *per_cpu_path)
if (fd < 0)
goto out_fail;
- ftrace_dump_buffer(fd, cpu_buffer, global_pages, page_tmp);
+ ftrace_dump_buffer(fd, cpu_buffer, ti->pages, page_tmp);
close(fd);
}
@@ -1478,26 +1473,70 @@ static int dump_kallsyms(const char *dump_tracing_dir)
static int trace_cmd_data_output(int fd);
+#define FTRACE_DUMP_SYMBOLS (1 << 0)
+#define FTRACE_DUMP_META_DATA (1 << 1)
+
+static int populate_ftrace_dir_tree(struct trace_instance *ti,
+ char *root, uint flags)
+{
+ char path[PATH_MAX];
+ int ret;
+
+ ret = mkdir(root, 0755);
+ if (ret < 0) {
+ if (errno == EEXIST)
+ error(INFO, "mkdir: %s exists\n", root);
+ return FALSE;
+ }
+
+ snprintf(path, sizeof(path), "%s/per_cpu", root);
+ if (try_mkdir(path, 0755) < 0)
+ return FALSE;
+
+ if (ftrace_dump_buffers(path, ti) < 0)
+ return FALSE;
+
+ if (flags & FTRACE_DUMP_META_DATA) {
+ /* Dump event types */
+ snprintf(path, sizeof(path), "%s/events", root);
+ if (try_mkdir(path, 0755) < 0)
+ return FALSE;
+
+ if (ftrace_dump_event_types(path) < 0)
+ return FALSE;
+
+ /* Dump pids with corresponding cmdlines */
+ if (dump_saved_cmdlines(root) < 0)
+ return FALSE;
+ }
+
+ if (flags & FTRACE_DUMP_SYMBOLS) {
+ /* Dump all symbols of the kernel */
+ dump_kallsyms(root);
+ }
+
+ return TRUE;
+}
+
static void ftrace_dump(int argc, char *argv[])
{
int c;
- int dump_meta_data = 0;
- int dump_symbols = 0;
+ uint flags = 0;
char *dump_tracing_dir;
- char path[PATH_MAX];
- int ret;
while ((c = getopt(argc, argv, "smt")) != EOF) {
switch(c)
{
case 's':
- dump_symbols = 1;
+ flags |= FTRACE_DUMP_SYMBOLS;
break;
case 'm':
- dump_meta_data = 1;
+ flags |= FTRACE_DUMP_META_DATA;
break;
case 't':
- if (dump_symbols || dump_meta_data || argc - optind > 1)
+ if (flags & FTRACE_DUMP_SYMBOLS ||
+ flags & FTRACE_DUMP_META_DATA ||
+ argc - optind > 1)
cmd_usage(pc->curcmd, SYNOPSIS);
else {
char *trace_dat = "trace.dat";
@@ -1528,38 +1567,7 @@ static void ftrace_dump(int argc, char *argv[])
return;
}
- ret = mkdir(dump_tracing_dir, 0755);
- if (ret < 0) {
- if (errno == EEXIST)
- error(INFO, "mkdir: %s exists\n", dump_tracing_dir);
- return;
- }
-
- snprintf(path, sizeof(path), "%s/per_cpu", dump_tracing_dir);
- if (try_mkdir(path, 0755) < 0)
- return;
-
- if (ftrace_dump_buffers(path) < 0)
- return;
-
- if (dump_meta_data) {
- /* Dump event types */
- snprintf(path, sizeof(path), "%s/events", dump_tracing_dir);
- if (try_mkdir(path, 0755) < 0)
- return;
-
- if (ftrace_dump_event_types(path) < 0)
- return;
-
- /* Dump pids with corresponding cmdlines */
- if (dump_saved_cmdlines(dump_tracing_dir) < 0)
- return;
- }
-
- if (dump_symbols) {
- /* Dump all symbols of the kernel */
- dump_kallsyms(dump_tracing_dir);
- }
+ populate_ftrace_dir_tree(&global_trace_instance, dump_tracing_dir, flags);
}
static void ftrace_show(int argc, char *argv[])
@@ -2182,7 +2190,7 @@ static int save_res_data(int fd, int nr_cpu_buffers)
return 0;
}
-static int save_record_data(int fd, int nr_cpu_buffers)
+static int save_record_data(int fd, int nr_cpu_buffers, struct trace_instance *ti)
{
int i, j;
unsigned long long offset, buffer_offset;
@@ -2194,7 +2202,7 @@ static int save_record_data(int fd, int nr_cpu_buffers)
buffer_offset = offset;
for (i = 0; i < nr_cpu_ids; i++) {
- struct ring_buffer_per_cpu *cpu_buffer = &global_buffers[i];
+ struct ring_buffer_per_cpu *cpu_buffer = &ti->buffers[i];
unsigned long long buffer_size;
if (!cpu_buffer->kaddr)
@@ -2214,7 +2222,7 @@ static int save_record_data(int fd, int nr_cpu_buffers)
lseek(fd, offset, SEEK_SET);
for (i = 0; i < nr_cpu_ids; i++) {
- struct ring_buffer_per_cpu *cpu_buffer = &global_buffers[i];
+ struct ring_buffer_per_cpu *cpu_buffer = &ti->buffers[i];
if (!cpu_buffer->kaddr)
continue;
@@ -2233,13 +2241,13 @@ static int save_record_data(int fd, int nr_cpu_buffers)
return 0;
}
-static int __trace_cmd_data_output(int fd)
+static int get_nr_cpu_buffers(struct trace_instance *ti)
{
int i;
int nr_cpu_buffers = 0;
for (i = 0; i < nr_cpu_ids; i++) {
- struct ring_buffer_per_cpu *cpu_buffer = &global_buffers[i];
+ struct ring_buffer_per_cpu *cpu_buffer = &ti->buffers[i];
if (!cpu_buffer->kaddr)
continue;
@@ -2247,6 +2255,15 @@ static int __trace_cmd_data_output(int fd)
nr_cpu_buffers++;
}
+ return nr_cpu_buffers;
+}
+
+static int __trace_cmd_data_output(int fd)
+{
+ int nr_cpu_buffers;
+
+ nr_cpu_buffers = get_nr_cpu_buffers(&global_trace_instance);
+
if (save_initial_data(fd))
return -1;
if (save_header_files(fd))
@@ -2261,7 +2278,7 @@ static int __trace_cmd_data_output(int fd)
return -1;
if (save_res_data(fd, nr_cpu_buffers))
return -1;
- if (save_record_data(fd, nr_cpu_buffers))
+ if (save_record_data(fd, nr_cpu_buffers, &global_trace_instance))
return -1;
return 0;
--
2.9.2