This patch introduced a few functions to print the event trace log to
STM buffer when the trace event happen and the event information
would be committed to ring buffer.
Before outputting the trace log to STM, we have to get the human readable
trace log content and print it into a local buffer in the format of a
string, the function 'trace_event_buf_vprintf()' is just for this purpose.
Signed-off-by: Chunyan Zhang <[email protected]>
---
kernel/trace/Makefile | 1 +
kernel/trace/trace_output_stm.c | 99 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 100 insertions(+)
create mode 100644 kernel/trace/trace_output_stm.c
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 9b1044e..002de34 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -67,4 +67,5 @@ obj-$(CONFIG_UPROBE_EVENT) += trace_uprobe.o
obj-$(CONFIG_TRACEPOINT_BENCHMARK) += trace_benchmark.o
+obj-$(CONFIG_STM_TRACE_EVENT) += trace_output_stm.o
libftrace-y := ftrace.o
diff --git a/kernel/trace/trace_output_stm.c b/kernel/trace/trace_output_stm.c
new file mode 100644
index 0000000..1cf6d87
--- /dev/null
+++ b/kernel/trace/trace_output_stm.c
@@ -0,0 +1,99 @@
+#include <linux/ftrace_event.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include "trace.h"
+
+#define STM_OUTPUT_STRLEN 128
+
+/* store the event trace log for STM */
+struct trace_buffer_stm {
+ char buffer[STM_OUTPUT_STRLEN];
+ unsigned int used_len;
+ unsigned int size;
+};
+
+static struct trace_buffer_stm *trace_event_stm_buffer;
+static struct trace_seq *stm_tmp_seq;
+static int stm_buffers_allocated;
+
+void trace_event_buf_vprintf(struct trace_buffer_stm *tb, const char *fmt, ...)
+{
+ va_list ap;
+ char *buffer = tb->buffer + tb->used_len;
+ unsigned int size = tb->size - tb->used_len;
+
+ va_start(ap, fmt);
+ tb->used_len += vsnprintf(buffer, size, fmt, ap);
+ va_end(ap);
+}
+EXPORT_SYMBOL_GPL(trace_event_buf_vprintf);
+
+static inline void stm_buf_reset(struct trace_buffer_stm *tb)
+{
+ tb->used_len = 0;
+}
+
+void trace_event_stm_log(struct ftrace_event_buffer *fbuffer)
+{
+
+ struct trace_seq *p = stm_tmp_seq;
+ struct trace_buffer_stm *tb;
+ struct ftrace_event_call *event_call = fbuffer->ftrace_file->event_call;
+ struct trace_entry *entry = (struct trace_entry *)fbuffer->entry;
+
+ if (!stm_buffers_allocated)
+ return;
+
+ tb = trace_event_stm_buffer;
+
+ if (event_call->output_stm)
+ event_call->output_stm(p, entry, tb);
+
+ stm_trace_event_write(tb->buffer, tb->used_len);
+
+ stm_buf_reset(tb);
+}
+EXPORT_SYMBOL_GPL(trace_event_stm_log);
+
+static int alloc_stm_tmp_seq(void)
+{
+ struct trace_seq *seq;
+
+ seq = kzalloc(sizeof(struct trace_seq), GFP_KERNEL);
+ if (!seq)
+ return -ENOMEM;
+
+ stm_tmp_seq = seq;
+
+ return 0;
+}
+
+static int alloc_stm_trace_buffer(void)
+{
+ struct trace_buffer_stm *buffer;
+
+ buffer = kzalloc(sizeof(struct trace_buffer_stm), GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ buffer->used_len = 0;
+ buffer->size = ARRAY_SIZE(buffer->buffer);
+
+ trace_event_stm_buffer = buffer;
+
+ return 0;
+}
+
+static __init int trace_stm_init_buffers(void)
+{
+ if (alloc_stm_trace_buffer())
+ return -ENOMEM;
+
+ if (alloc_stm_tmp_seq())
+ return -ENOMEM;
+
+ stm_buffers_allocated = 1;
+
+ return 0;
+}
+fs_initcall(trace_stm_init_buffers);
--
1.9.1