mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-22 22:51:37 +00:00
tracing: add __print_flags for events
Developers have been asking for the ability in the ftrace event tracer to display names of bits in a flags variable. Instead of printing out c2, it would be easier to read FOO|BAR|GOO, assuming that FOO is bit 1, BAR is bit 6 and GOO is bit 7. Some examples where this would be useful are the state flags in a context switch, kmalloc flags, and even permision flags in accessing files. [ v2 changes include: Frederic Weisbecker's idea of using a mask instead of bits, thus we can output GFP_KERNEL instead of GPF_WAIT|GFP_IO|GFP_FS. Li Zefan's idea of allowing the caller of __print_flags to add their own delimiter (or no delimiter) where we can get for file permissions rwx instead of r|w|x. ] [ v3 changes: Christoph Hellwig's idea of using an array instead of va_args. ] [ Impact: better displaying of flags in trace output ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
This commit is contained in:
parent
0e907c9939
commit
be74b73a57
3 changed files with 65 additions and 1 deletions
|
@ -3,12 +3,23 @@
|
||||||
|
|
||||||
#include <linux/trace_seq.h>
|
#include <linux/trace_seq.h>
|
||||||
#include <linux/ring_buffer.h>
|
#include <linux/ring_buffer.h>
|
||||||
|
#include <linux/percpu.h>
|
||||||
|
|
||||||
struct trace_array;
|
struct trace_array;
|
||||||
struct tracer;
|
struct tracer;
|
||||||
struct dentry;
|
struct dentry;
|
||||||
|
|
||||||
|
DECLARE_PER_CPU(struct trace_seq, ftrace_event_seq);
|
||||||
|
|
||||||
|
struct trace_print_flags {
|
||||||
|
unsigned long mask;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *ftrace_print_flags_seq(struct trace_seq *p, const char *delim,
|
||||||
|
unsigned long flags,
|
||||||
|
const struct trace_print_flags *flag_array);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The trace entry - the most basic unit of tracing. This is what
|
* The trace entry - the most basic unit of tracing. This is what
|
||||||
* is printed in the end as a single line in the trace output, such as:
|
* is printed in the end as a single line in the trace output, such as:
|
||||||
|
|
|
@ -87,6 +87,7 @@
|
||||||
* struct trace_seq *s = &iter->seq;
|
* struct trace_seq *s = &iter->seq;
|
||||||
* struct ftrace_raw_<call> *field; <-- defined in stage 1
|
* struct ftrace_raw_<call> *field; <-- defined in stage 1
|
||||||
* struct trace_entry *entry;
|
* struct trace_entry *entry;
|
||||||
|
* struct trace_seq *p;
|
||||||
* int ret;
|
* int ret;
|
||||||
*
|
*
|
||||||
* entry = iter->ent;
|
* entry = iter->ent;
|
||||||
|
@ -98,7 +99,9 @@
|
||||||
*
|
*
|
||||||
* field = (typeof(field))entry;
|
* field = (typeof(field))entry;
|
||||||
*
|
*
|
||||||
|
* p = get_cpu_var(ftrace_event_seq);
|
||||||
* ret = trace_seq_printf(s, <TP_printk> "\n");
|
* ret = trace_seq_printf(s, <TP_printk> "\n");
|
||||||
|
* put_cpu();
|
||||||
* if (!ret)
|
* if (!ret)
|
||||||
* return TRACE_TYPE_PARTIAL_LINE;
|
* return TRACE_TYPE_PARTIAL_LINE;
|
||||||
*
|
*
|
||||||
|
@ -119,6 +122,14 @@
|
||||||
#undef __get_str
|
#undef __get_str
|
||||||
#define __get_str(field) ((char *)__entry + __entry->__str_loc_##field)
|
#define __get_str(field) ((char *)__entry + __entry->__str_loc_##field)
|
||||||
|
|
||||||
|
#undef __print_flags
|
||||||
|
#define __print_flags(flag, delim, flag_array...) \
|
||||||
|
({ \
|
||||||
|
static const struct trace_print_flags flags[] = \
|
||||||
|
{ flag_array, { -1, NULL }}; \
|
||||||
|
ftrace_print_flags_seq(p, delim, flag, flags); \
|
||||||
|
})
|
||||||
|
|
||||||
#undef TRACE_EVENT
|
#undef TRACE_EVENT
|
||||||
#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
|
#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
|
||||||
enum print_line_t \
|
enum print_line_t \
|
||||||
|
@ -127,6 +138,7 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
|
||||||
struct trace_seq *s = &iter->seq; \
|
struct trace_seq *s = &iter->seq; \
|
||||||
struct ftrace_raw_##call *field; \
|
struct ftrace_raw_##call *field; \
|
||||||
struct trace_entry *entry; \
|
struct trace_entry *entry; \
|
||||||
|
struct trace_seq *p; \
|
||||||
int ret; \
|
int ret; \
|
||||||
\
|
\
|
||||||
entry = iter->ent; \
|
entry = iter->ent; \
|
||||||
|
@ -138,7 +150,9 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
|
||||||
\
|
\
|
||||||
field = (typeof(field))entry; \
|
field = (typeof(field))entry; \
|
||||||
\
|
\
|
||||||
|
p = &get_cpu_var(ftrace_event_seq); \
|
||||||
ret = trace_seq_printf(s, #call ": " print); \
|
ret = trace_seq_printf(s, #call ": " print); \
|
||||||
|
put_cpu(); \
|
||||||
if (!ret) \
|
if (!ret) \
|
||||||
return TRACE_TYPE_PARTIAL_LINE; \
|
return TRACE_TYPE_PARTIAL_LINE; \
|
||||||
\
|
\
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
#define EVENT_HASHSIZE 128
|
#define EVENT_HASHSIZE 128
|
||||||
|
|
||||||
static DECLARE_RWSEM(trace_event_mutex);
|
static DECLARE_RWSEM(trace_event_mutex);
|
||||||
|
|
||||||
|
DEFINE_PER_CPU(struct trace_seq, ftrace_event_seq);
|
||||||
|
|
||||||
static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;
|
static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;
|
||||||
|
|
||||||
static int next_event_type = __TRACE_LAST_TYPE + 1;
|
static int next_event_type = __TRACE_LAST_TYPE + 1;
|
||||||
|
@ -212,6 +215,42 @@ int trace_seq_path(struct trace_seq *s, struct path *path)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
ftrace_print_flags_seq(struct trace_seq *p, const char *delim,
|
||||||
|
unsigned long flags,
|
||||||
|
const struct trace_print_flags *flag_array)
|
||||||
|
{
|
||||||
|
unsigned long mask;
|
||||||
|
const char *str;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
trace_seq_init(p);
|
||||||
|
|
||||||
|
for (i = 0; flag_array[i].name && flags; i++) {
|
||||||
|
|
||||||
|
mask = flag_array[i].mask;
|
||||||
|
if ((flags & mask) != mask)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
str = flag_array[i].name;
|
||||||
|
flags &= ~mask;
|
||||||
|
if (p->len && delim)
|
||||||
|
trace_seq_puts(p, delim);
|
||||||
|
trace_seq_puts(p, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for left over flags */
|
||||||
|
if (flags) {
|
||||||
|
if (p->len && delim)
|
||||||
|
trace_seq_puts(p, delim);
|
||||||
|
trace_seq_printf(p, "0x%lx", flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_seq_putc(p, 0);
|
||||||
|
|
||||||
|
return p->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KRETPROBES
|
#ifdef CONFIG_KRETPROBES
|
||||||
static inline const char *kretprobed(const char *name)
|
static inline const char *kretprobed(const char *name)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue