You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'trace-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing updates from Steven Rostedt:
"There was a lot of clean ups and minor fixes. One of those clean ups
was to the trace_seq code. It also removed the return values to the
trace_seq_*() functions and use trace_seq_has_overflowed() to see if
the buffer filled up or not. This is similar to work being done to
the seq_file code as well in another tree.
Some of the other goodies include:
- Added some "!" (NOT) logic to the tracing filter.
- Fixed the frame pointer logic to the x86_64 mcount trampolines
- Added the logic for dynamic trampolines on !CONFIG_PREEMPT systems.
That is, the ftrace trampoline can be dynamically allocated and be
called directly by functions that only have a single hook to them"
* tag 'trace-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (55 commits)
tracing: Truncated output is better than nothing
tracing: Add additional marks to signal very large time deltas
Documentation: describe trace_buf_size parameter more accurately
tracing: Allow NOT to filter AND and OR clauses
tracing: Add NOT to filtering logic
ftrace/fgraph/x86: Have prepare_ftrace_return() take ip as first parameter
ftrace/x86: Get rid of ftrace_caller_setup
ftrace/x86: Have save_mcount_regs macro also save stack frames if needed
ftrace/x86: Add macro MCOUNT_REG_SIZE for amount of stack used to save mcount regs
ftrace/x86: Simplify save_mcount_regs on getting RIP
ftrace/x86: Have save_mcount_regs store RIP in %rdi for first parameter
ftrace/x86: Rename MCOUNT_SAVE_FRAME and add more detailed comments
ftrace/x86: Move MCOUNT_SAVE_FRAME out of header file
ftrace/x86: Have static tracing also use ftrace_caller_setup
ftrace/x86: Have static function tracing always test for function graph
kprobes: Add IPMODIFY flag to kprobe_ftrace_ops
ftrace, kprobes: Support IPMODIFY flag to find IP modify conflict
kprobes/ftrace: Recover original IP if pre_handler doesn't change it
tracing/trivial: Fix typos and make an int into a bool
tracing: Deletion of an unnecessary check before iput()
...
This commit is contained in:
+66
-82
@@ -1142,9 +1142,9 @@ static void get_pdu_remap(const struct trace_entry *ent,
|
||||
r->sector_from = be64_to_cpu(sector_from);
|
||||
}
|
||||
|
||||
typedef int (blk_log_action_t) (struct trace_iterator *iter, const char *act);
|
||||
typedef void (blk_log_action_t) (struct trace_iterator *iter, const char *act);
|
||||
|
||||
static int blk_log_action_classic(struct trace_iterator *iter, const char *act)
|
||||
static void blk_log_action_classic(struct trace_iterator *iter, const char *act)
|
||||
{
|
||||
char rwbs[RWBS_LEN];
|
||||
unsigned long long ts = iter->ts;
|
||||
@@ -1154,33 +1154,33 @@ static int blk_log_action_classic(struct trace_iterator *iter, const char *act)
|
||||
|
||||
fill_rwbs(rwbs, t);
|
||||
|
||||
return trace_seq_printf(&iter->seq,
|
||||
"%3d,%-3d %2d %5d.%09lu %5u %2s %3s ",
|
||||
MAJOR(t->device), MINOR(t->device), iter->cpu,
|
||||
secs, nsec_rem, iter->ent->pid, act, rwbs);
|
||||
trace_seq_printf(&iter->seq,
|
||||
"%3d,%-3d %2d %5d.%09lu %5u %2s %3s ",
|
||||
MAJOR(t->device), MINOR(t->device), iter->cpu,
|
||||
secs, nsec_rem, iter->ent->pid, act, rwbs);
|
||||
}
|
||||
|
||||
static int blk_log_action(struct trace_iterator *iter, const char *act)
|
||||
static void blk_log_action(struct trace_iterator *iter, const char *act)
|
||||
{
|
||||
char rwbs[RWBS_LEN];
|
||||
const struct blk_io_trace *t = te_blk_io_trace(iter->ent);
|
||||
|
||||
fill_rwbs(rwbs, t);
|
||||
return trace_seq_printf(&iter->seq, "%3d,%-3d %2s %3s ",
|
||||
MAJOR(t->device), MINOR(t->device), act, rwbs);
|
||||
trace_seq_printf(&iter->seq, "%3d,%-3d %2s %3s ",
|
||||
MAJOR(t->device), MINOR(t->device), act, rwbs);
|
||||
}
|
||||
|
||||
static int blk_log_dump_pdu(struct trace_seq *s, const struct trace_entry *ent)
|
||||
static void blk_log_dump_pdu(struct trace_seq *s, const struct trace_entry *ent)
|
||||
{
|
||||
const unsigned char *pdu_buf;
|
||||
int pdu_len;
|
||||
int i, end, ret;
|
||||
int i, end;
|
||||
|
||||
pdu_buf = pdu_start(ent);
|
||||
pdu_len = te_blk_io_trace(ent)->pdu_len;
|
||||
|
||||
if (!pdu_len)
|
||||
return 1;
|
||||
return;
|
||||
|
||||
/* find the last zero that needs to be printed */
|
||||
for (end = pdu_len - 1; end >= 0; end--)
|
||||
@@ -1188,119 +1188,107 @@ static int blk_log_dump_pdu(struct trace_seq *s, const struct trace_entry *ent)
|
||||
break;
|
||||
end++;
|
||||
|
||||
if (!trace_seq_putc(s, '('))
|
||||
return 0;
|
||||
trace_seq_putc(s, '(');
|
||||
|
||||
for (i = 0; i < pdu_len; i++) {
|
||||
|
||||
ret = trace_seq_printf(s, "%s%02x",
|
||||
i == 0 ? "" : " ", pdu_buf[i]);
|
||||
if (!ret)
|
||||
return ret;
|
||||
trace_seq_printf(s, "%s%02x",
|
||||
i == 0 ? "" : " ", pdu_buf[i]);
|
||||
|
||||
/*
|
||||
* stop when the rest is just zeroes and indicate so
|
||||
* with a ".." appended
|
||||
*/
|
||||
if (i == end && end != pdu_len - 1)
|
||||
return trace_seq_puts(s, " ..) ");
|
||||
if (i == end && end != pdu_len - 1) {
|
||||
trace_seq_puts(s, " ..) ");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return trace_seq_puts(s, ") ");
|
||||
trace_seq_puts(s, ") ");
|
||||
}
|
||||
|
||||
static int blk_log_generic(struct trace_seq *s, const struct trace_entry *ent)
|
||||
static void blk_log_generic(struct trace_seq *s, const struct trace_entry *ent)
|
||||
{
|
||||
char cmd[TASK_COMM_LEN];
|
||||
|
||||
trace_find_cmdline(ent->pid, cmd);
|
||||
|
||||
if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) {
|
||||
int ret;
|
||||
|
||||
ret = trace_seq_printf(s, "%u ", t_bytes(ent));
|
||||
if (!ret)
|
||||
return 0;
|
||||
ret = blk_log_dump_pdu(s, ent);
|
||||
if (!ret)
|
||||
return 0;
|
||||
return trace_seq_printf(s, "[%s]\n", cmd);
|
||||
trace_seq_printf(s, "%u ", t_bytes(ent));
|
||||
blk_log_dump_pdu(s, ent);
|
||||
trace_seq_printf(s, "[%s]\n", cmd);
|
||||
} else {
|
||||
if (t_sec(ent))
|
||||
return trace_seq_printf(s, "%llu + %u [%s]\n",
|
||||
trace_seq_printf(s, "%llu + %u [%s]\n",
|
||||
t_sector(ent), t_sec(ent), cmd);
|
||||
return trace_seq_printf(s, "[%s]\n", cmd);
|
||||
else
|
||||
trace_seq_printf(s, "[%s]\n", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static int blk_log_with_error(struct trace_seq *s,
|
||||
static void blk_log_with_error(struct trace_seq *s,
|
||||
const struct trace_entry *ent)
|
||||
{
|
||||
if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) {
|
||||
int ret;
|
||||
|
||||
ret = blk_log_dump_pdu(s, ent);
|
||||
if (ret)
|
||||
return trace_seq_printf(s, "[%d]\n", t_error(ent));
|
||||
return 0;
|
||||
blk_log_dump_pdu(s, ent);
|
||||
trace_seq_printf(s, "[%d]\n", t_error(ent));
|
||||
} else {
|
||||
if (t_sec(ent))
|
||||
return trace_seq_printf(s, "%llu + %u [%d]\n",
|
||||
t_sector(ent),
|
||||
t_sec(ent), t_error(ent));
|
||||
return trace_seq_printf(s, "%llu [%d]\n",
|
||||
t_sector(ent), t_error(ent));
|
||||
trace_seq_printf(s, "%llu + %u [%d]\n",
|
||||
t_sector(ent),
|
||||
t_sec(ent), t_error(ent));
|
||||
else
|
||||
trace_seq_printf(s, "%llu [%d]\n",
|
||||
t_sector(ent), t_error(ent));
|
||||
}
|
||||
}
|
||||
|
||||
static int blk_log_remap(struct trace_seq *s, const struct trace_entry *ent)
|
||||
static void blk_log_remap(struct trace_seq *s, const struct trace_entry *ent)
|
||||
{
|
||||
struct blk_io_trace_remap r = { .device_from = 0, };
|
||||
|
||||
get_pdu_remap(ent, &r);
|
||||
return trace_seq_printf(s, "%llu + %u <- (%d,%d) %llu\n",
|
||||
t_sector(ent), t_sec(ent),
|
||||
MAJOR(r.device_from), MINOR(r.device_from),
|
||||
(unsigned long long)r.sector_from);
|
||||
trace_seq_printf(s, "%llu + %u <- (%d,%d) %llu\n",
|
||||
t_sector(ent), t_sec(ent),
|
||||
MAJOR(r.device_from), MINOR(r.device_from),
|
||||
(unsigned long long)r.sector_from);
|
||||
}
|
||||
|
||||
static int blk_log_plug(struct trace_seq *s, const struct trace_entry *ent)
|
||||
static void blk_log_plug(struct trace_seq *s, const struct trace_entry *ent)
|
||||
{
|
||||
char cmd[TASK_COMM_LEN];
|
||||
|
||||
trace_find_cmdline(ent->pid, cmd);
|
||||
|
||||
return trace_seq_printf(s, "[%s]\n", cmd);
|
||||
trace_seq_printf(s, "[%s]\n", cmd);
|
||||
}
|
||||
|
||||
static int blk_log_unplug(struct trace_seq *s, const struct trace_entry *ent)
|
||||
static void blk_log_unplug(struct trace_seq *s, const struct trace_entry *ent)
|
||||
{
|
||||
char cmd[TASK_COMM_LEN];
|
||||
|
||||
trace_find_cmdline(ent->pid, cmd);
|
||||
|
||||
return trace_seq_printf(s, "[%s] %llu\n", cmd, get_pdu_int(ent));
|
||||
trace_seq_printf(s, "[%s] %llu\n", cmd, get_pdu_int(ent));
|
||||
}
|
||||
|
||||
static int blk_log_split(struct trace_seq *s, const struct trace_entry *ent)
|
||||
static void blk_log_split(struct trace_seq *s, const struct trace_entry *ent)
|
||||
{
|
||||
char cmd[TASK_COMM_LEN];
|
||||
|
||||
trace_find_cmdline(ent->pid, cmd);
|
||||
|
||||
return trace_seq_printf(s, "%llu / %llu [%s]\n", t_sector(ent),
|
||||
get_pdu_int(ent), cmd);
|
||||
trace_seq_printf(s, "%llu / %llu [%s]\n", t_sector(ent),
|
||||
get_pdu_int(ent), cmd);
|
||||
}
|
||||
|
||||
static int blk_log_msg(struct trace_seq *s, const struct trace_entry *ent)
|
||||
static void blk_log_msg(struct trace_seq *s, const struct trace_entry *ent)
|
||||
{
|
||||
int ret;
|
||||
const struct blk_io_trace *t = te_blk_io_trace(ent);
|
||||
|
||||
ret = trace_seq_putmem(s, t + 1, t->pdu_len);
|
||||
if (ret)
|
||||
return trace_seq_putc(s, '\n');
|
||||
return ret;
|
||||
trace_seq_putmem(s, t + 1, t->pdu_len);
|
||||
trace_seq_putc(s, '\n');
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1339,7 +1327,7 @@ static void blk_tracer_reset(struct trace_array *tr)
|
||||
|
||||
static const struct {
|
||||
const char *act[2];
|
||||
int (*print)(struct trace_seq *s, const struct trace_entry *ent);
|
||||
void (*print)(struct trace_seq *s, const struct trace_entry *ent);
|
||||
} what2act[] = {
|
||||
[__BLK_TA_QUEUE] = {{ "Q", "queue" }, blk_log_generic },
|
||||
[__BLK_TA_BACKMERGE] = {{ "M", "backmerge" }, blk_log_generic },
|
||||
@@ -1364,7 +1352,6 @@ static enum print_line_t print_one_line(struct trace_iterator *iter,
|
||||
struct trace_seq *s = &iter->seq;
|
||||
const struct blk_io_trace *t;
|
||||
u16 what;
|
||||
int ret;
|
||||
bool long_act;
|
||||
blk_log_action_t *log_action;
|
||||
|
||||
@@ -1374,21 +1361,18 @@ static enum print_line_t print_one_line(struct trace_iterator *iter,
|
||||
log_action = classic ? &blk_log_action_classic : &blk_log_action;
|
||||
|
||||
if (t->action == BLK_TN_MESSAGE) {
|
||||
ret = log_action(iter, long_act ? "message" : "m");
|
||||
if (ret)
|
||||
ret = blk_log_msg(s, iter->ent);
|
||||
goto out;
|
||||
log_action(iter, long_act ? "message" : "m");
|
||||
blk_log_msg(s, iter->ent);
|
||||
}
|
||||
|
||||
if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act)))
|
||||
ret = trace_seq_printf(s, "Unknown action %x\n", what);
|
||||
trace_seq_printf(s, "Unknown action %x\n", what);
|
||||
else {
|
||||
ret = log_action(iter, what2act[what].act[long_act]);
|
||||
if (ret)
|
||||
ret = what2act[what].print(s, iter->ent);
|
||||
log_action(iter, what2act[what].act[long_act]);
|
||||
what2act[what].print(s, iter->ent);
|
||||
}
|
||||
out:
|
||||
return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
return trace_handle_return(s);
|
||||
}
|
||||
|
||||
static enum print_line_t blk_trace_event_print(struct trace_iterator *iter,
|
||||
@@ -1397,7 +1381,7 @@ static enum print_line_t blk_trace_event_print(struct trace_iterator *iter,
|
||||
return print_one_line(iter, false);
|
||||
}
|
||||
|
||||
static int blk_trace_synthesize_old_trace(struct trace_iterator *iter)
|
||||
static void blk_trace_synthesize_old_trace(struct trace_iterator *iter)
|
||||
{
|
||||
struct trace_seq *s = &iter->seq;
|
||||
struct blk_io_trace *t = (struct blk_io_trace *)iter->ent;
|
||||
@@ -1407,18 +1391,18 @@ static int blk_trace_synthesize_old_trace(struct trace_iterator *iter)
|
||||
.time = iter->ts,
|
||||
};
|
||||
|
||||
if (!trace_seq_putmem(s, &old, offset))
|
||||
return 0;
|
||||
return trace_seq_putmem(s, &t->sector,
|
||||
sizeof(old) - offset + t->pdu_len);
|
||||
trace_seq_putmem(s, &old, offset);
|
||||
trace_seq_putmem(s, &t->sector,
|
||||
sizeof(old) - offset + t->pdu_len);
|
||||
}
|
||||
|
||||
static enum print_line_t
|
||||
blk_trace_event_print_binary(struct trace_iterator *iter, int flags,
|
||||
struct trace_event *event)
|
||||
{
|
||||
return blk_trace_synthesize_old_trace(iter) ?
|
||||
TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE;
|
||||
blk_trace_synthesize_old_trace(iter);
|
||||
|
||||
return trace_handle_return(&iter->seq);
|
||||
}
|
||||
|
||||
static enum print_line_t blk_tracer_print_line(struct trace_iterator *iter)
|
||||
|
||||
+299
-33
File diff suppressed because it is too large
Load Diff
+32
-35
@@ -34,21 +34,19 @@ static void update_pages_handler(struct work_struct *work);
|
||||
*/
|
||||
int ring_buffer_print_entry_header(struct trace_seq *s)
|
||||
{
|
||||
int ret;
|
||||
trace_seq_puts(s, "# compressed entry header\n");
|
||||
trace_seq_puts(s, "\ttype_len : 5 bits\n");
|
||||
trace_seq_puts(s, "\ttime_delta : 27 bits\n");
|
||||
trace_seq_puts(s, "\tarray : 32 bits\n");
|
||||
trace_seq_putc(s, '\n');
|
||||
trace_seq_printf(s, "\tpadding : type == %d\n",
|
||||
RINGBUF_TYPE_PADDING);
|
||||
trace_seq_printf(s, "\ttime_extend : type == %d\n",
|
||||
RINGBUF_TYPE_TIME_EXTEND);
|
||||
trace_seq_printf(s, "\tdata max type_len == %d\n",
|
||||
RINGBUF_TYPE_DATA_TYPE_LEN_MAX);
|
||||
|
||||
ret = trace_seq_puts(s, "# compressed entry header\n");
|
||||
ret = trace_seq_puts(s, "\ttype_len : 5 bits\n");
|
||||
ret = trace_seq_puts(s, "\ttime_delta : 27 bits\n");
|
||||
ret = trace_seq_puts(s, "\tarray : 32 bits\n");
|
||||
ret = trace_seq_putc(s, '\n');
|
||||
ret = trace_seq_printf(s, "\tpadding : type == %d\n",
|
||||
RINGBUF_TYPE_PADDING);
|
||||
ret = trace_seq_printf(s, "\ttime_extend : type == %d\n",
|
||||
RINGBUF_TYPE_TIME_EXTEND);
|
||||
ret = trace_seq_printf(s, "\tdata max type_len == %d\n",
|
||||
RINGBUF_TYPE_DATA_TYPE_LEN_MAX);
|
||||
|
||||
return ret;
|
||||
return !trace_seq_has_overflowed(s);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -419,32 +417,31 @@ static inline int test_time_stamp(u64 delta)
|
||||
int ring_buffer_print_page_header(struct trace_seq *s)
|
||||
{
|
||||
struct buffer_data_page field;
|
||||
int ret;
|
||||
|
||||
ret = trace_seq_printf(s, "\tfield: u64 timestamp;\t"
|
||||
"offset:0;\tsize:%u;\tsigned:%u;\n",
|
||||
(unsigned int)sizeof(field.time_stamp),
|
||||
(unsigned int)is_signed_type(u64));
|
||||
trace_seq_printf(s, "\tfield: u64 timestamp;\t"
|
||||
"offset:0;\tsize:%u;\tsigned:%u;\n",
|
||||
(unsigned int)sizeof(field.time_stamp),
|
||||
(unsigned int)is_signed_type(u64));
|
||||
|
||||
ret = trace_seq_printf(s, "\tfield: local_t commit;\t"
|
||||
"offset:%u;\tsize:%u;\tsigned:%u;\n",
|
||||
(unsigned int)offsetof(typeof(field), commit),
|
||||
(unsigned int)sizeof(field.commit),
|
||||
(unsigned int)is_signed_type(long));
|
||||
trace_seq_printf(s, "\tfield: local_t commit;\t"
|
||||
"offset:%u;\tsize:%u;\tsigned:%u;\n",
|
||||
(unsigned int)offsetof(typeof(field), commit),
|
||||
(unsigned int)sizeof(field.commit),
|
||||
(unsigned int)is_signed_type(long));
|
||||
|
||||
ret = trace_seq_printf(s, "\tfield: int overwrite;\t"
|
||||
"offset:%u;\tsize:%u;\tsigned:%u;\n",
|
||||
(unsigned int)offsetof(typeof(field), commit),
|
||||
1,
|
||||
(unsigned int)is_signed_type(long));
|
||||
trace_seq_printf(s, "\tfield: int overwrite;\t"
|
||||
"offset:%u;\tsize:%u;\tsigned:%u;\n",
|
||||
(unsigned int)offsetof(typeof(field), commit),
|
||||
1,
|
||||
(unsigned int)is_signed_type(long));
|
||||
|
||||
ret = trace_seq_printf(s, "\tfield: char data;\t"
|
||||
"offset:%u;\tsize:%u;\tsigned:%u;\n",
|
||||
(unsigned int)offsetof(typeof(field), data),
|
||||
(unsigned int)BUF_PAGE_SIZE,
|
||||
(unsigned int)is_signed_type(char));
|
||||
trace_seq_printf(s, "\tfield: char data;\t"
|
||||
"offset:%u;\tsize:%u;\tsigned:%u;\n",
|
||||
(unsigned int)offsetof(typeof(field), data),
|
||||
(unsigned int)BUF_PAGE_SIZE,
|
||||
(unsigned int)is_signed_type(char));
|
||||
|
||||
return ret;
|
||||
return !trace_seq_has_overflowed(s);
|
||||
}
|
||||
|
||||
struct rb_irq_work {
|
||||
|
||||
+79
-80
@@ -155,10 +155,11 @@ __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops);
|
||||
|
||||
static int __init stop_trace_on_warning(char *str)
|
||||
{
|
||||
__disable_trace_on_warning = 1;
|
||||
if ((strcmp(str, "=0") != 0 && strcmp(str, "=off") != 0))
|
||||
__disable_trace_on_warning = 1;
|
||||
return 1;
|
||||
}
|
||||
__setup("traceoff_on_warning=", stop_trace_on_warning);
|
||||
__setup("traceoff_on_warning", stop_trace_on_warning);
|
||||
|
||||
static int __init boot_alloc_snapshot(char *str)
|
||||
{
|
||||
@@ -2158,9 +2159,7 @@ __trace_array_vprintk(struct ring_buffer *buffer,
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = vsnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);
|
||||
if (len > TRACE_BUF_SIZE)
|
||||
goto out;
|
||||
len = vscnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);
|
||||
|
||||
local_save_flags(flags);
|
||||
size = sizeof(*entry) + len + 1;
|
||||
@@ -2171,8 +2170,7 @@ __trace_array_vprintk(struct ring_buffer *buffer,
|
||||
entry = ring_buffer_event_data(event);
|
||||
entry->ip = ip;
|
||||
|
||||
memcpy(&entry->buf, tbuffer, len);
|
||||
entry->buf[len] = '\0';
|
||||
memcpy(&entry->buf, tbuffer, len + 1);
|
||||
if (!call_filter_check_discard(call, entry, buffer, event)) {
|
||||
__buffer_unlock_commit(buffer, event);
|
||||
ftrace_trace_stack(buffer, flags, 6, pc);
|
||||
@@ -2509,14 +2507,14 @@ get_total_entries(struct trace_buffer *buf,
|
||||
|
||||
static void print_lat_help_header(struct seq_file *m)
|
||||
{
|
||||
seq_puts(m, "# _------=> CPU# \n");
|
||||
seq_puts(m, "# / _-----=> irqs-off \n");
|
||||
seq_puts(m, "# | / _----=> need-resched \n");
|
||||
seq_puts(m, "# || / _---=> hardirq/softirq \n");
|
||||
seq_puts(m, "# ||| / _--=> preempt-depth \n");
|
||||
seq_puts(m, "# |||| / delay \n");
|
||||
seq_puts(m, "# cmd pid ||||| time | caller \n");
|
||||
seq_puts(m, "# \\ / ||||| \\ | / \n");
|
||||
seq_puts(m, "# _------=> CPU# \n"
|
||||
"# / _-----=> irqs-off \n"
|
||||
"# | / _----=> need-resched \n"
|
||||
"# || / _---=> hardirq/softirq \n"
|
||||
"# ||| / _--=> preempt-depth \n"
|
||||
"# |||| / delay \n"
|
||||
"# cmd pid ||||| time | caller \n"
|
||||
"# \\ / ||||| \\ | / \n");
|
||||
}
|
||||
|
||||
static void print_event_info(struct trace_buffer *buf, struct seq_file *m)
|
||||
@@ -2533,20 +2531,20 @@ static void print_event_info(struct trace_buffer *buf, struct seq_file *m)
|
||||
static void print_func_help_header(struct trace_buffer *buf, struct seq_file *m)
|
||||
{
|
||||
print_event_info(buf, m);
|
||||
seq_puts(m, "# TASK-PID CPU# TIMESTAMP FUNCTION\n");
|
||||
seq_puts(m, "# | | | | |\n");
|
||||
seq_puts(m, "# TASK-PID CPU# TIMESTAMP FUNCTION\n"
|
||||
"# | | | | |\n");
|
||||
}
|
||||
|
||||
static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file *m)
|
||||
{
|
||||
print_event_info(buf, m);
|
||||
seq_puts(m, "# _-----=> irqs-off\n");
|
||||
seq_puts(m, "# / _----=> need-resched\n");
|
||||
seq_puts(m, "# | / _---=> hardirq/softirq\n");
|
||||
seq_puts(m, "# || / _--=> preempt-depth\n");
|
||||
seq_puts(m, "# ||| / delay\n");
|
||||
seq_puts(m, "# TASK-PID CPU# |||| TIMESTAMP FUNCTION\n");
|
||||
seq_puts(m, "# | | | |||| | |\n");
|
||||
seq_puts(m, "# _-----=> irqs-off\n"
|
||||
"# / _----=> need-resched\n"
|
||||
"# | / _---=> hardirq/softirq\n"
|
||||
"# || / _--=> preempt-depth\n"
|
||||
"# ||| / delay\n"
|
||||
"# TASK-PID CPU# |||| TIMESTAMP FUNCTION\n"
|
||||
"# | | | |||| | |\n");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2649,24 +2647,21 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
|
||||
event = ftrace_find_event(entry->type);
|
||||
|
||||
if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
|
||||
if (iter->iter_flags & TRACE_FILE_LAT_FMT) {
|
||||
if (!trace_print_lat_context(iter))
|
||||
goto partial;
|
||||
} else {
|
||||
if (!trace_print_context(iter))
|
||||
goto partial;
|
||||
}
|
||||
if (iter->iter_flags & TRACE_FILE_LAT_FMT)
|
||||
trace_print_lat_context(iter);
|
||||
else
|
||||
trace_print_context(iter);
|
||||
}
|
||||
|
||||
if (trace_seq_has_overflowed(s))
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
if (event)
|
||||
return event->funcs->trace(iter, sym_flags, event);
|
||||
|
||||
if (!trace_seq_printf(s, "Unknown type %d\n", entry->type))
|
||||
goto partial;
|
||||
trace_seq_printf(s, "Unknown type %d\n", entry->type);
|
||||
|
||||
return TRACE_TYPE_HANDLED;
|
||||
partial:
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
return trace_handle_return(s);
|
||||
}
|
||||
|
||||
static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
|
||||
@@ -2677,22 +2672,20 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
|
||||
|
||||
entry = iter->ent;
|
||||
|
||||
if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
|
||||
if (!trace_seq_printf(s, "%d %d %llu ",
|
||||
entry->pid, iter->cpu, iter->ts))
|
||||
goto partial;
|
||||
}
|
||||
if (trace_flags & TRACE_ITER_CONTEXT_INFO)
|
||||
trace_seq_printf(s, "%d %d %llu ",
|
||||
entry->pid, iter->cpu, iter->ts);
|
||||
|
||||
if (trace_seq_has_overflowed(s))
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
event = ftrace_find_event(entry->type);
|
||||
if (event)
|
||||
return event->funcs->raw(iter, 0, event);
|
||||
|
||||
if (!trace_seq_printf(s, "%d ?\n", entry->type))
|
||||
goto partial;
|
||||
trace_seq_printf(s, "%d ?\n", entry->type);
|
||||
|
||||
return TRACE_TYPE_HANDLED;
|
||||
partial:
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
return trace_handle_return(s);
|
||||
}
|
||||
|
||||
static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
|
||||
@@ -2705,9 +2698,11 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
|
||||
entry = iter->ent;
|
||||
|
||||
if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
|
||||
SEQ_PUT_HEX_FIELD_RET(s, entry->pid);
|
||||
SEQ_PUT_HEX_FIELD_RET(s, iter->cpu);
|
||||
SEQ_PUT_HEX_FIELD_RET(s, iter->ts);
|
||||
SEQ_PUT_HEX_FIELD(s, entry->pid);
|
||||
SEQ_PUT_HEX_FIELD(s, iter->cpu);
|
||||
SEQ_PUT_HEX_FIELD(s, iter->ts);
|
||||
if (trace_seq_has_overflowed(s))
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
event = ftrace_find_event(entry->type);
|
||||
@@ -2717,9 +2712,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
|
||||
return ret;
|
||||
}
|
||||
|
||||
SEQ_PUT_FIELD_RET(s, newline);
|
||||
SEQ_PUT_FIELD(s, newline);
|
||||
|
||||
return TRACE_TYPE_HANDLED;
|
||||
return trace_handle_return(s);
|
||||
}
|
||||
|
||||
static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
|
||||
@@ -2731,9 +2726,11 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
|
||||
entry = iter->ent;
|
||||
|
||||
if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
|
||||
SEQ_PUT_FIELD_RET(s, entry->pid);
|
||||
SEQ_PUT_FIELD_RET(s, iter->cpu);
|
||||
SEQ_PUT_FIELD_RET(s, iter->ts);
|
||||
SEQ_PUT_FIELD(s, entry->pid);
|
||||
SEQ_PUT_FIELD(s, iter->cpu);
|
||||
SEQ_PUT_FIELD(s, iter->ts);
|
||||
if (trace_seq_has_overflowed(s))
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
event = ftrace_find_event(entry->type);
|
||||
@@ -2779,10 +2776,12 @@ enum print_line_t print_trace_line(struct trace_iterator *iter)
|
||||
{
|
||||
enum print_line_t ret;
|
||||
|
||||
if (iter->lost_events &&
|
||||
!trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n",
|
||||
iter->cpu, iter->lost_events))
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
if (iter->lost_events) {
|
||||
trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n",
|
||||
iter->cpu, iter->lost_events);
|
||||
if (trace_seq_has_overflowed(&iter->seq))
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
if (iter->trace && iter->trace->print_line) {
|
||||
ret = iter->trace->print_line(iter);
|
||||
@@ -2860,44 +2859,44 @@ static void test_ftrace_alive(struct seq_file *m)
|
||||
{
|
||||
if (!ftrace_is_dead())
|
||||
return;
|
||||
seq_printf(m, "# WARNING: FUNCTION TRACING IS CORRUPTED\n");
|
||||
seq_printf(m, "# MAY BE MISSING FUNCTION EVENTS\n");
|
||||
seq_puts(m, "# WARNING: FUNCTION TRACING IS CORRUPTED\n"
|
||||
"# MAY BE MISSING FUNCTION EVENTS\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TRACER_MAX_TRACE
|
||||
static void show_snapshot_main_help(struct seq_file *m)
|
||||
{
|
||||
seq_printf(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n");
|
||||
seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n");
|
||||
seq_printf(m, "# Takes a snapshot of the main buffer.\n");
|
||||
seq_printf(m, "# echo 2 > snapshot : Clears snapshot buffer (but does not allocate or free)\n");
|
||||
seq_printf(m, "# (Doesn't have to be '2' works with any number that\n");
|
||||
seq_printf(m, "# is not a '0' or '1')\n");
|
||||
seq_puts(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n"
|
||||
"# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n"
|
||||
"# Takes a snapshot of the main buffer.\n"
|
||||
"# echo 2 > snapshot : Clears snapshot buffer (but does not allocate or free)\n"
|
||||
"# (Doesn't have to be '2' works with any number that\n"
|
||||
"# is not a '0' or '1')\n");
|
||||
}
|
||||
|
||||
static void show_snapshot_percpu_help(struct seq_file *m)
|
||||
{
|
||||
seq_printf(m, "# echo 0 > snapshot : Invalid for per_cpu snapshot file.\n");
|
||||
seq_puts(m, "# echo 0 > snapshot : Invalid for per_cpu snapshot file.\n");
|
||||
#ifdef CONFIG_RING_BUFFER_ALLOW_SWAP
|
||||
seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n");
|
||||
seq_printf(m, "# Takes a snapshot of the main buffer for this cpu.\n");
|
||||
seq_puts(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n"
|
||||
"# Takes a snapshot of the main buffer for this cpu.\n");
|
||||
#else
|
||||
seq_printf(m, "# echo 1 > snapshot : Not supported with this kernel.\n");
|
||||
seq_printf(m, "# Must use main snapshot file to allocate.\n");
|
||||
seq_puts(m, "# echo 1 > snapshot : Not supported with this kernel.\n"
|
||||
"# Must use main snapshot file to allocate.\n");
|
||||
#endif
|
||||
seq_printf(m, "# echo 2 > snapshot : Clears this cpu's snapshot buffer (but does not allocate)\n");
|
||||
seq_printf(m, "# (Doesn't have to be '2' works with any number that\n");
|
||||
seq_printf(m, "# is not a '0' or '1')\n");
|
||||
seq_puts(m, "# echo 2 > snapshot : Clears this cpu's snapshot buffer (but does not allocate)\n"
|
||||
"# (Doesn't have to be '2' works with any number that\n"
|
||||
"# is not a '0' or '1')\n");
|
||||
}
|
||||
|
||||
static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter)
|
||||
{
|
||||
if (iter->tr->allocated_snapshot)
|
||||
seq_printf(m, "#\n# * Snapshot is allocated *\n#\n");
|
||||
seq_puts(m, "#\n# * Snapshot is allocated *\n#\n");
|
||||
else
|
||||
seq_printf(m, "#\n# * Snapshot is freed *\n#\n");
|
||||
seq_puts(m, "#\n# * Snapshot is freed *\n#\n");
|
||||
|
||||
seq_printf(m, "# Snapshot commands:\n");
|
||||
seq_puts(m, "# Snapshot commands:\n");
|
||||
if (iter->cpu_file == RING_BUFFER_ALL_CPUS)
|
||||
show_snapshot_main_help(m);
|
||||
else
|
||||
@@ -3251,7 +3250,7 @@ static int t_show(struct seq_file *m, void *v)
|
||||
if (!t)
|
||||
return 0;
|
||||
|
||||
seq_printf(m, "%s", t->name);
|
||||
seq_puts(m, t->name);
|
||||
if (t->next)
|
||||
seq_putc(m, ' ');
|
||||
else
|
||||
@@ -5749,10 +5748,10 @@ ftrace_snapshot_print(struct seq_file *m, unsigned long ip,
|
||||
|
||||
seq_printf(m, "%ps:", (void *)ip);
|
||||
|
||||
seq_printf(m, "snapshot");
|
||||
seq_puts(m, "snapshot");
|
||||
|
||||
if (count == -1)
|
||||
seq_printf(m, ":unlimited\n");
|
||||
seq_puts(m, ":unlimited\n");
|
||||
else
|
||||
seq_printf(m, ":count=%ld\n", count);
|
||||
|
||||
|
||||
+4
-13
@@ -14,6 +14,7 @@
|
||||
#include <linux/trace_seq.h>
|
||||
#include <linux/ftrace_event.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/trace_seq.h>
|
||||
|
||||
#ifdef CONFIG_FTRACE_SYSCALLS
|
||||
#include <asm/unistd.h> /* For NR_SYSCALLS */
|
||||
@@ -569,15 +570,6 @@ void trace_init_global_iter(struct trace_iterator *iter);
|
||||
|
||||
void tracing_iter_reset(struct trace_iterator *iter, int cpu);
|
||||
|
||||
void tracing_sched_switch_trace(struct trace_array *tr,
|
||||
struct task_struct *prev,
|
||||
struct task_struct *next,
|
||||
unsigned long flags, int pc);
|
||||
|
||||
void tracing_sched_wakeup_trace(struct trace_array *tr,
|
||||
struct task_struct *wakee,
|
||||
struct task_struct *cur,
|
||||
unsigned long flags, int pc);
|
||||
void trace_function(struct trace_array *tr,
|
||||
unsigned long ip,
|
||||
unsigned long parent_ip,
|
||||
@@ -597,9 +589,6 @@ void set_graph_array(struct trace_array *tr);
|
||||
|
||||
void tracing_start_cmdline_record(void);
|
||||
void tracing_stop_cmdline_record(void);
|
||||
void tracing_sched_switch_assign_trace(struct trace_array *tr);
|
||||
void tracing_stop_sched_switch_record(void);
|
||||
void tracing_start_sched_switch_record(void);
|
||||
int register_tracer(struct tracer *type);
|
||||
int is_tracing_stopped(void);
|
||||
|
||||
@@ -719,6 +708,8 @@ enum print_line_t print_trace_line(struct trace_iterator *iter);
|
||||
|
||||
extern unsigned long trace_flags;
|
||||
|
||||
extern char trace_find_mark(unsigned long long duration);
|
||||
|
||||
/* Standard output formatting function used for function return traces */
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
|
||||
@@ -737,7 +728,7 @@ extern unsigned long trace_flags;
|
||||
extern enum print_line_t
|
||||
print_graph_function_flags(struct trace_iterator *iter, u32 flags);
|
||||
extern void print_graph_headers_flags(struct seq_file *s, u32 flags);
|
||||
extern enum print_line_t
|
||||
extern void
|
||||
trace_print_graph_duration(unsigned long long duration, struct trace_seq *s);
|
||||
extern void graph_trace_open(struct trace_iterator *iter);
|
||||
extern void graph_trace_close(struct trace_iterator *iter);
|
||||
|
||||
+22
-23
@@ -151,22 +151,21 @@ static enum print_line_t trace_branch_print(struct trace_iterator *iter,
|
||||
|
||||
trace_assign_type(field, iter->ent);
|
||||
|
||||
if (trace_seq_printf(&iter->seq, "[%s] %s:%s:%d\n",
|
||||
field->correct ? " ok " : " MISS ",
|
||||
field->func,
|
||||
field->file,
|
||||
field->line))
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
trace_seq_printf(&iter->seq, "[%s] %s:%s:%d\n",
|
||||
field->correct ? " ok " : " MISS ",
|
||||
field->func,
|
||||
field->file,
|
||||
field->line);
|
||||
|
||||
return TRACE_TYPE_HANDLED;
|
||||
return trace_handle_return(&iter->seq);
|
||||
}
|
||||
|
||||
static void branch_print_header(struct seq_file *s)
|
||||
{
|
||||
seq_puts(s, "# TASK-PID CPU# TIMESTAMP CORRECT"
|
||||
" FUNC:FILE:LINE\n");
|
||||
seq_puts(s, "# | | | | | "
|
||||
" |\n");
|
||||
" FUNC:FILE:LINE\n"
|
||||
"# | | | | | "
|
||||
" |\n");
|
||||
}
|
||||
|
||||
static struct trace_event_functions trace_branch_funcs = {
|
||||
@@ -233,12 +232,12 @@ extern unsigned long __stop_annotated_branch_profile[];
|
||||
|
||||
static int annotated_branch_stat_headers(struct seq_file *m)
|
||||
{
|
||||
seq_printf(m, " correct incorrect %% ");
|
||||
seq_printf(m, " Function "
|
||||
" File Line\n"
|
||||
" ------- --------- - "
|
||||
" -------- "
|
||||
" ---- ----\n");
|
||||
seq_puts(m, " correct incorrect % "
|
||||
" Function "
|
||||
" File Line\n"
|
||||
" ------- --------- - "
|
||||
" -------- "
|
||||
" ---- ----\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -274,7 +273,7 @@ static int branch_stat_show(struct seq_file *m, void *v)
|
||||
|
||||
seq_printf(m, "%8lu %8lu ", p->correct, p->incorrect);
|
||||
if (percent < 0)
|
||||
seq_printf(m, " X ");
|
||||
seq_puts(m, " X ");
|
||||
else
|
||||
seq_printf(m, "%3ld ", percent);
|
||||
seq_printf(m, "%-30.30s %-20.20s %d\n", p->func, f, p->line);
|
||||
@@ -362,12 +361,12 @@ extern unsigned long __stop_branch_profile[];
|
||||
|
||||
static int all_branch_stat_headers(struct seq_file *m)
|
||||
{
|
||||
seq_printf(m, " miss hit %% ");
|
||||
seq_printf(m, " Function "
|
||||
" File Line\n"
|
||||
" ------- --------- - "
|
||||
" -------- "
|
||||
" ---- ----\n");
|
||||
seq_puts(m, " miss hit % "
|
||||
" Function "
|
||||
" File Line\n"
|
||||
" ------- --------- - "
|
||||
" -------- "
|
||||
" ---- ----\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -918,7 +918,7 @@ static int f_show(struct seq_file *m, void *v)
|
||||
case FORMAT_HEADER:
|
||||
seq_printf(m, "name: %s\n", ftrace_event_name(call));
|
||||
seq_printf(m, "ID: %d\n", call->event.type);
|
||||
seq_printf(m, "format:\n");
|
||||
seq_puts(m, "format:\n");
|
||||
return 0;
|
||||
|
||||
case FORMAT_FIELD_SEPERATOR:
|
||||
@@ -1988,7 +1988,7 @@ event_enable_print(struct seq_file *m, unsigned long ip,
|
||||
ftrace_event_name(data->file->event_call));
|
||||
|
||||
if (data->count == -1)
|
||||
seq_printf(m, ":unlimited\n");
|
||||
seq_puts(m, ":unlimited\n");
|
||||
else
|
||||
seq_printf(m, ":count=%ld\n", data->count);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ enum filter_op_ids
|
||||
OP_GT,
|
||||
OP_GE,
|
||||
OP_BAND,
|
||||
OP_NOT,
|
||||
OP_NONE,
|
||||
OP_OPEN_PAREN,
|
||||
};
|
||||
@@ -67,6 +68,7 @@ static struct filter_op filter_ops[] = {
|
||||
{ OP_GT, ">", 5 },
|
||||
{ OP_GE, ">=", 5 },
|
||||
{ OP_BAND, "&", 6 },
|
||||
{ OP_NOT, "!", 6 },
|
||||
{ OP_NONE, "OP_NONE", 0 },
|
||||
{ OP_OPEN_PAREN, "(", 0 },
|
||||
};
|
||||
@@ -85,6 +87,7 @@ enum {
|
||||
FILT_ERR_MISSING_FIELD,
|
||||
FILT_ERR_INVALID_FILTER,
|
||||
FILT_ERR_IP_FIELD_ONLY,
|
||||
FILT_ERR_ILLEGAL_NOT_OP,
|
||||
};
|
||||
|
||||
static char *err_text[] = {
|
||||
@@ -101,6 +104,7 @@ static char *err_text[] = {
|
||||
"Missing field name and/or value",
|
||||
"Meaningless filter expression",
|
||||
"Only 'ip' field is supported for function trace",
|
||||
"Illegal use of '!'",
|
||||
};
|
||||
|
||||
struct opstack_op {
|
||||
@@ -139,6 +143,7 @@ struct pred_stack {
|
||||
int index;
|
||||
};
|
||||
|
||||
/* If not of not match is equal to not of not, then it is a match */
|
||||
#define DEFINE_COMPARISON_PRED(type) \
|
||||
static int filter_pred_##type(struct filter_pred *pred, void *event) \
|
||||
{ \
|
||||
@@ -166,7 +171,7 @@ static int filter_pred_##type(struct filter_pred *pred, void *event) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return match; \
|
||||
return !!match == !pred->not; \
|
||||
}
|
||||
|
||||
#define DEFINE_EQUALITY_PRED(size) \
|
||||
@@ -484,9 +489,10 @@ static int process_ops(struct filter_pred *preds,
|
||||
if (!WARN_ON_ONCE(!pred->fn))
|
||||
match = pred->fn(pred, rec);
|
||||
if (!!match == type)
|
||||
return match;
|
||||
break;
|
||||
}
|
||||
return match;
|
||||
/* If not of not match is equal to not of not, then it is a match */
|
||||
return !!match == !op->not;
|
||||
}
|
||||
|
||||
struct filter_match_preds_data {
|
||||
@@ -735,10 +741,10 @@ static int filter_set_pred(struct event_filter *filter,
|
||||
* then this op can be folded.
|
||||
*/
|
||||
if (left->index & FILTER_PRED_FOLD &&
|
||||
(left->op == dest->op ||
|
||||
((left->op == dest->op && !left->not) ||
|
||||
left->left == FILTER_PRED_INVALID) &&
|
||||
right->index & FILTER_PRED_FOLD &&
|
||||
(right->op == dest->op ||
|
||||
((right->op == dest->op && !right->not) ||
|
||||
right->left == FILTER_PRED_INVALID))
|
||||
dest->index |= FILTER_PRED_FOLD;
|
||||
|
||||
@@ -1028,7 +1034,7 @@ static int init_pred(struct filter_parse_state *ps,
|
||||
}
|
||||
|
||||
if (pred->op == OP_NE)
|
||||
pred->not = 1;
|
||||
pred->not ^= 1;
|
||||
|
||||
pred->fn = fn;
|
||||
return 0;
|
||||
@@ -1590,6 +1596,17 @@ static int replace_preds(struct ftrace_event_call *call,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (elt->op == OP_NOT) {
|
||||
if (!n_preds || operand1 || operand2) {
|
||||
parse_error(ps, FILT_ERR_ILLEGAL_NOT_OP, 0);
|
||||
err = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
if (!dry_run)
|
||||
filter->preds[n_preds - 1].not ^= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (WARN_ON(n_preds++ == MAX_FILTER_PRED)) {
|
||||
parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
|
||||
err = -ENOSPC;
|
||||
|
||||
@@ -373,7 +373,7 @@ event_trigger_print(const char *name, struct seq_file *m,
|
||||
{
|
||||
long count = (long)data;
|
||||
|
||||
seq_printf(m, "%s", name);
|
||||
seq_puts(m, name);
|
||||
|
||||
if (count == -1)
|
||||
seq_puts(m, ":unlimited");
|
||||
@@ -383,7 +383,7 @@ event_trigger_print(const char *name, struct seq_file *m,
|
||||
if (filter_str)
|
||||
seq_printf(m, " if %s\n", filter_str);
|
||||
else
|
||||
seq_puts(m, "\n");
|
||||
seq_putc(m, '\n');
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1105,7 +1105,7 @@ event_enable_trigger_print(struct seq_file *m, struct event_trigger_ops *ops,
|
||||
if (data->filter_str)
|
||||
seq_printf(m, " if %s\n", data->filter_str);
|
||||
else
|
||||
seq_puts(m, "\n");
|
||||
seq_putc(m, '\n');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -261,37 +261,74 @@ static struct tracer function_trace __tracer_data =
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
static int update_count(void **data)
|
||||
static void update_traceon_count(void **data, bool on)
|
||||
{
|
||||
unsigned long *count = (long *)data;
|
||||
long *count = (long *)data;
|
||||
long old_count = *count;
|
||||
|
||||
if (!*count)
|
||||
return 0;
|
||||
/*
|
||||
* Tracing gets disabled (or enabled) once per count.
|
||||
* This function can be called at the same time on multiple CPUs.
|
||||
* It is fine if both disable (or enable) tracing, as disabling
|
||||
* (or enabling) the second time doesn't do anything as the
|
||||
* state of the tracer is already disabled (or enabled).
|
||||
* What needs to be synchronized in this case is that the count
|
||||
* only gets decremented once, even if the tracer is disabled
|
||||
* (or enabled) twice, as the second one is really a nop.
|
||||
*
|
||||
* The memory barriers guarantee that we only decrement the
|
||||
* counter once. First the count is read to a local variable
|
||||
* and a read barrier is used to make sure that it is loaded
|
||||
* before checking if the tracer is in the state we want.
|
||||
* If the tracer is not in the state we want, then the count
|
||||
* is guaranteed to be the old count.
|
||||
*
|
||||
* Next the tracer is set to the state we want (disabled or enabled)
|
||||
* then a write memory barrier is used to make sure that
|
||||
* the new state is visible before changing the counter by
|
||||
* one minus the old counter. This guarantees that another CPU
|
||||
* executing this code will see the new state before seeing
|
||||
* the new counter value, and would not do anything if the new
|
||||
* counter is seen.
|
||||
*
|
||||
* Note, there is no synchronization between this and a user
|
||||
* setting the tracing_on file. But we currently don't care
|
||||
* about that.
|
||||
*/
|
||||
if (!old_count)
|
||||
return;
|
||||
|
||||
if (*count != -1)
|
||||
(*count)--;
|
||||
/* Make sure we see count before checking tracing state */
|
||||
smp_rmb();
|
||||
|
||||
return 1;
|
||||
if (on == !!tracing_is_on())
|
||||
return;
|
||||
|
||||
if (on)
|
||||
tracing_on();
|
||||
else
|
||||
tracing_off();
|
||||
|
||||
/* unlimited? */
|
||||
if (old_count == -1)
|
||||
return;
|
||||
|
||||
/* Make sure tracing state is visible before updating count */
|
||||
smp_wmb();
|
||||
|
||||
*count = old_count - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ftrace_traceon_count(unsigned long ip, unsigned long parent_ip, void **data)
|
||||
{
|
||||
if (tracing_is_on())
|
||||
return;
|
||||
|
||||
if (update_count(data))
|
||||
tracing_on();
|
||||
update_traceon_count(data, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
ftrace_traceoff_count(unsigned long ip, unsigned long parent_ip, void **data)
|
||||
{
|
||||
if (!tracing_is_on())
|
||||
return;
|
||||
|
||||
if (update_count(data))
|
||||
tracing_off();
|
||||
update_traceon_count(data, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -330,11 +367,49 @@ ftrace_stacktrace(unsigned long ip, unsigned long parent_ip, void **data)
|
||||
static void
|
||||
ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, void **data)
|
||||
{
|
||||
if (!tracing_is_on())
|
||||
return;
|
||||
long *count = (long *)data;
|
||||
long old_count;
|
||||
long new_count;
|
||||
|
||||
if (update_count(data))
|
||||
trace_dump_stack(STACK_SKIP);
|
||||
/*
|
||||
* Stack traces should only execute the number of times the
|
||||
* user specified in the counter.
|
||||
*/
|
||||
do {
|
||||
|
||||
if (!tracing_is_on())
|
||||
return;
|
||||
|
||||
old_count = *count;
|
||||
|
||||
if (!old_count)
|
||||
return;
|
||||
|
||||
/* unlimited? */
|
||||
if (old_count == -1) {
|
||||
trace_dump_stack(STACK_SKIP);
|
||||
return;
|
||||
}
|
||||
|
||||
new_count = old_count - 1;
|
||||
new_count = cmpxchg(count, old_count, new_count);
|
||||
if (new_count == old_count)
|
||||
trace_dump_stack(STACK_SKIP);
|
||||
|
||||
} while (new_count != old_count);
|
||||
}
|
||||
|
||||
static int update_count(void **data)
|
||||
{
|
||||
unsigned long *count = (long *)data;
|
||||
|
||||
if (!*count)
|
||||
return 0;
|
||||
|
||||
if (*count != -1)
|
||||
(*count)--;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -361,7 +436,7 @@ ftrace_probe_print(const char *name, struct seq_file *m,
|
||||
seq_printf(m, "%ps:%s", (void *)ip, name);
|
||||
|
||||
if (count == -1)
|
||||
seq_printf(m, ":unlimited\n");
|
||||
seq_puts(m, ":unlimited\n");
|
||||
else
|
||||
seq_printf(m, ":count=%ld\n", count);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,10 +20,12 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
|
||||
{
|
||||
/* use static because iter can be a bit big for the stack */
|
||||
static struct trace_iterator iter;
|
||||
static struct ring_buffer_iter *buffer_iter[CONFIG_NR_CPUS];
|
||||
unsigned int old_userobj;
|
||||
int cnt = 0, cpu;
|
||||
|
||||
trace_init_global_iter(&iter);
|
||||
iter.buffer_iter = buffer_iter;
|
||||
|
||||
for_each_tracing_cpu(cpu) {
|
||||
atomic_inc(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
|
||||
@@ -57,19 +59,19 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
|
||||
ring_buffer_read_start(iter.buffer_iter[cpu_file]);
|
||||
tracing_iter_reset(&iter, cpu_file);
|
||||
}
|
||||
if (!trace_empty(&iter))
|
||||
trace_find_next_entry_inc(&iter);
|
||||
while (!trace_empty(&iter)) {
|
||||
|
||||
while (trace_find_next_entry_inc(&iter)) {
|
||||
if (!cnt)
|
||||
kdb_printf("---------------------------------\n");
|
||||
cnt++;
|
||||
|
||||
if (trace_find_next_entry_inc(&iter) != NULL && !skip_lines)
|
||||
if (!skip_lines) {
|
||||
print_trace_line(&iter);
|
||||
if (!skip_lines)
|
||||
trace_printk_seq(&iter.seq);
|
||||
else
|
||||
} else {
|
||||
skip_lines--;
|
||||
}
|
||||
|
||||
if (KDB_FLAG(CMD_INTERRUPT))
|
||||
goto out;
|
||||
}
|
||||
@@ -86,9 +88,12 @@ out:
|
||||
atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
|
||||
}
|
||||
|
||||
for_each_tracing_cpu(cpu)
|
||||
if (iter.buffer_iter[cpu])
|
||||
for_each_tracing_cpu(cpu) {
|
||||
if (iter.buffer_iter[cpu]) {
|
||||
ring_buffer_read_finish(iter.buffer_iter[cpu]);
|
||||
iter.buffer_iter[cpu] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+18
-28
@@ -826,7 +826,7 @@ static int probes_seq_show(struct seq_file *m, void *v)
|
||||
struct trace_kprobe *tk = v;
|
||||
int i;
|
||||
|
||||
seq_printf(m, "%c", trace_kprobe_is_return(tk) ? 'r' : 'p');
|
||||
seq_putc(m, trace_kprobe_is_return(tk) ? 'r' : 'p');
|
||||
seq_printf(m, ":%s/%s", tk->tp.call.class->system,
|
||||
ftrace_event_name(&tk->tp.call));
|
||||
|
||||
@@ -840,7 +840,7 @@ static int probes_seq_show(struct seq_file *m, void *v)
|
||||
|
||||
for (i = 0; i < tk->tp.nr_args; i++)
|
||||
seq_printf(m, " %s=%s", tk->tp.args[i].name, tk->tp.args[i].comm);
|
||||
seq_printf(m, "\n");
|
||||
seq_putc(m, '\n');
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1024,27 +1024,22 @@ print_kprobe_event(struct trace_iterator *iter, int flags,
|
||||
field = (struct kprobe_trace_entry_head *)iter->ent;
|
||||
tp = container_of(event, struct trace_probe, call.event);
|
||||
|
||||
if (!trace_seq_printf(s, "%s: (", ftrace_event_name(&tp->call)))
|
||||
goto partial;
|
||||
trace_seq_printf(s, "%s: (", ftrace_event_name(&tp->call));
|
||||
|
||||
if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET))
|
||||
goto partial;
|
||||
goto out;
|
||||
|
||||
if (!trace_seq_puts(s, ")"))
|
||||
goto partial;
|
||||
trace_seq_putc(s, ')');
|
||||
|
||||
data = (u8 *)&field[1];
|
||||
for (i = 0; i < tp->nr_args; i++)
|
||||
if (!tp->args[i].type->print(s, tp->args[i].name,
|
||||
data + tp->args[i].offset, field))
|
||||
goto partial;
|
||||
goto out;
|
||||
|
||||
if (!trace_seq_puts(s, "\n"))
|
||||
goto partial;
|
||||
|
||||
return TRACE_TYPE_HANDLED;
|
||||
partial:
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
trace_seq_putc(s, '\n');
|
||||
out:
|
||||
return trace_handle_return(s);
|
||||
}
|
||||
|
||||
static enum print_line_t
|
||||
@@ -1060,33 +1055,28 @@ print_kretprobe_event(struct trace_iterator *iter, int flags,
|
||||
field = (struct kretprobe_trace_entry_head *)iter->ent;
|
||||
tp = container_of(event, struct trace_probe, call.event);
|
||||
|
||||
if (!trace_seq_printf(s, "%s: (", ftrace_event_name(&tp->call)))
|
||||
goto partial;
|
||||
trace_seq_printf(s, "%s: (", ftrace_event_name(&tp->call));
|
||||
|
||||
if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET))
|
||||
goto partial;
|
||||
goto out;
|
||||
|
||||
if (!trace_seq_puts(s, " <- "))
|
||||
goto partial;
|
||||
trace_seq_puts(s, " <- ");
|
||||
|
||||
if (!seq_print_ip_sym(s, field->func, flags & ~TRACE_ITER_SYM_OFFSET))
|
||||
goto partial;
|
||||
goto out;
|
||||
|
||||
if (!trace_seq_puts(s, ")"))
|
||||
goto partial;
|
||||
trace_seq_putc(s, ')');
|
||||
|
||||
data = (u8 *)&field[1];
|
||||
for (i = 0; i < tp->nr_args; i++)
|
||||
if (!tp->args[i].type->print(s, tp->args[i].name,
|
||||
data + tp->args[i].offset, field))
|
||||
goto partial;
|
||||
goto out;
|
||||
|
||||
if (!trace_seq_puts(s, "\n"))
|
||||
goto partial;
|
||||
trace_seq_putc(s, '\n');
|
||||
|
||||
return TRACE_TYPE_HANDLED;
|
||||
partial:
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
out:
|
||||
return trace_handle_return(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -59,17 +59,15 @@ static void mmio_trace_start(struct trace_array *tr)
|
||||
mmio_reset_data(tr);
|
||||
}
|
||||
|
||||
static int mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev)
|
||||
static void mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
resource_size_t start, end;
|
||||
const struct pci_driver *drv = pci_dev_driver(dev);
|
||||
|
||||
/* XXX: incomplete checks for trace_seq_printf() return value */
|
||||
ret += trace_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x",
|
||||
dev->bus->number, dev->devfn,
|
||||
dev->vendor, dev->device, dev->irq);
|
||||
trace_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x",
|
||||
dev->bus->number, dev->devfn,
|
||||
dev->vendor, dev->device, dev->irq);
|
||||
/*
|
||||
* XXX: is pci_resource_to_user() appropriate, since we are
|
||||
* supposed to interpret the __ioremap() phys_addr argument based on
|
||||
@@ -77,21 +75,20 @@ static int mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev)
|
||||
*/
|
||||
for (i = 0; i < 7; i++) {
|
||||
pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
|
||||
ret += trace_seq_printf(s, " %llx",
|
||||
trace_seq_printf(s, " %llx",
|
||||
(unsigned long long)(start |
|
||||
(dev->resource[i].flags & PCI_REGION_FLAG_MASK)));
|
||||
}
|
||||
for (i = 0; i < 7; i++) {
|
||||
pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
|
||||
ret += trace_seq_printf(s, " %llx",
|
||||
trace_seq_printf(s, " %llx",
|
||||
dev->resource[i].start < dev->resource[i].end ?
|
||||
(unsigned long long)(end - start) + 1 : 0);
|
||||
}
|
||||
if (drv)
|
||||
ret += trace_seq_printf(s, " %s\n", drv->name);
|
||||
trace_seq_printf(s, " %s\n", drv->name);
|
||||
else
|
||||
ret += trace_seq_puts(s, " \n");
|
||||
return ret;
|
||||
trace_seq_puts(s, " \n");
|
||||
}
|
||||
|
||||
static void destroy_header_iter(struct header_iter *hiter)
|
||||
@@ -179,28 +176,27 @@ static enum print_line_t mmio_print_rw(struct trace_iterator *iter)
|
||||
unsigned long long t = ns2usecs(iter->ts);
|
||||
unsigned long usec_rem = do_div(t, USEC_PER_SEC);
|
||||
unsigned secs = (unsigned long)t;
|
||||
int ret = 1;
|
||||
|
||||
trace_assign_type(field, entry);
|
||||
rw = &field->rw;
|
||||
|
||||
switch (rw->opcode) {
|
||||
case MMIO_READ:
|
||||
ret = trace_seq_printf(s,
|
||||
trace_seq_printf(s,
|
||||
"R %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
|
||||
rw->width, secs, usec_rem, rw->map_id,
|
||||
(unsigned long long)rw->phys,
|
||||
rw->value, rw->pc, 0);
|
||||
break;
|
||||
case MMIO_WRITE:
|
||||
ret = trace_seq_printf(s,
|
||||
trace_seq_printf(s,
|
||||
"W %d %u.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
|
||||
rw->width, secs, usec_rem, rw->map_id,
|
||||
(unsigned long long)rw->phys,
|
||||
rw->value, rw->pc, 0);
|
||||
break;
|
||||
case MMIO_UNKNOWN_OP:
|
||||
ret = trace_seq_printf(s,
|
||||
trace_seq_printf(s,
|
||||
"UNKNOWN %u.%06lu %d 0x%llx %02lx,%02lx,"
|
||||
"%02lx 0x%lx %d\n",
|
||||
secs, usec_rem, rw->map_id,
|
||||
@@ -209,12 +205,11 @@ static enum print_line_t mmio_print_rw(struct trace_iterator *iter)
|
||||
(rw->value >> 0) & 0xff, rw->pc, 0);
|
||||
break;
|
||||
default:
|
||||
ret = trace_seq_puts(s, "rw what?\n");
|
||||
trace_seq_puts(s, "rw what?\n");
|
||||
break;
|
||||
}
|
||||
if (ret)
|
||||
return TRACE_TYPE_HANDLED;
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
return trace_handle_return(s);
|
||||
}
|
||||
|
||||
static enum print_line_t mmio_print_map(struct trace_iterator *iter)
|
||||
@@ -226,31 +221,29 @@ static enum print_line_t mmio_print_map(struct trace_iterator *iter)
|
||||
unsigned long long t = ns2usecs(iter->ts);
|
||||
unsigned long usec_rem = do_div(t, USEC_PER_SEC);
|
||||
unsigned secs = (unsigned long)t;
|
||||
int ret;
|
||||
|
||||
trace_assign_type(field, entry);
|
||||
m = &field->map;
|
||||
|
||||
switch (m->opcode) {
|
||||
case MMIO_PROBE:
|
||||
ret = trace_seq_printf(s,
|
||||
trace_seq_printf(s,
|
||||
"MAP %u.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n",
|
||||
secs, usec_rem, m->map_id,
|
||||
(unsigned long long)m->phys, m->virt, m->len,
|
||||
0UL, 0);
|
||||
break;
|
||||
case MMIO_UNPROBE:
|
||||
ret = trace_seq_printf(s,
|
||||
trace_seq_printf(s,
|
||||
"UNMAP %u.%06lu %d 0x%lx %d\n",
|
||||
secs, usec_rem, m->map_id, 0UL, 0);
|
||||
break;
|
||||
default:
|
||||
ret = trace_seq_puts(s, "map what?\n");
|
||||
trace_seq_puts(s, "map what?\n");
|
||||
break;
|
||||
}
|
||||
if (ret)
|
||||
return TRACE_TYPE_HANDLED;
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
return trace_handle_return(s);
|
||||
}
|
||||
|
||||
static enum print_line_t mmio_print_mark(struct trace_iterator *iter)
|
||||
@@ -262,14 +255,11 @@ static enum print_line_t mmio_print_mark(struct trace_iterator *iter)
|
||||
unsigned long long t = ns2usecs(iter->ts);
|
||||
unsigned long usec_rem = do_div(t, USEC_PER_SEC);
|
||||
unsigned secs = (unsigned long)t;
|
||||
int ret;
|
||||
|
||||
/* The trailing newline must be in the message. */
|
||||
ret = trace_seq_printf(s, "MARK %u.%06lu %s", secs, usec_rem, msg);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
trace_seq_printf(s, "MARK %u.%06lu %s", secs, usec_rem, msg);
|
||||
|
||||
return TRACE_TYPE_HANDLED;
|
||||
return trace_handle_return(s);
|
||||
}
|
||||
|
||||
static enum print_line_t mmio_print_line(struct trace_iterator *iter)
|
||||
|
||||
+189
-253
File diff suppressed because it is too large
Load Diff
@@ -35,17 +35,11 @@ trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry);
|
||||
extern int __unregister_ftrace_event(struct trace_event *event);
|
||||
extern struct rw_semaphore trace_event_sem;
|
||||
|
||||
#define SEQ_PUT_FIELD_RET(s, x) \
|
||||
do { \
|
||||
if (!trace_seq_putmem(s, &(x), sizeof(x))) \
|
||||
return TRACE_TYPE_PARTIAL_LINE; \
|
||||
} while (0)
|
||||
#define SEQ_PUT_FIELD(s, x) \
|
||||
trace_seq_putmem(s, &(x), sizeof(x))
|
||||
|
||||
#define SEQ_PUT_HEX_FIELD_RET(s, x) \
|
||||
do { \
|
||||
if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \
|
||||
return TRACE_TYPE_PARTIAL_LINE; \
|
||||
} while (0)
|
||||
#define SEQ_PUT_HEX_FIELD(s, x) \
|
||||
trace_seq_putmem_hex(s, &(x), sizeof(x))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -305,7 +305,7 @@ static int t_show(struct seq_file *m, void *v)
|
||||
seq_puts(m, "\\t");
|
||||
break;
|
||||
case '\\':
|
||||
seq_puts(m, "\\");
|
||||
seq_putc(m, '\\');
|
||||
break;
|
||||
case '"':
|
||||
seq_puts(m, "\\\"");
|
||||
|
||||
@@ -40,7 +40,8 @@ const char *reserved_field_names[] = {
|
||||
int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, const char *name, \
|
||||
void *data, void *ent) \
|
||||
{ \
|
||||
return trace_seq_printf(s, " %s=" fmt, name, *(type *)data); \
|
||||
trace_seq_printf(s, " %s=" fmt, name, *(type *)data); \
|
||||
return !trace_seq_has_overflowed(s); \
|
||||
} \
|
||||
const char PRINT_TYPE_FMT_NAME(type)[] = fmt; \
|
||||
NOKPROBE_SYMBOL(PRINT_TYPE_FUNC_NAME(type));
|
||||
@@ -61,10 +62,11 @@ int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, const char *name,
|
||||
int len = *(u32 *)data >> 16;
|
||||
|
||||
if (!len)
|
||||
return trace_seq_printf(s, " %s=(fault)", name);
|
||||
trace_seq_printf(s, " %s=(fault)", name);
|
||||
else
|
||||
return trace_seq_printf(s, " %s=\"%s\"", name,
|
||||
(const char *)get_loc_data(data, ent));
|
||||
trace_seq_printf(s, " %s=\"%s\"", name,
|
||||
(const char *)get_loc_data(data, ent));
|
||||
return !trace_seq_has_overflowed(s);
|
||||
}
|
||||
NOKPROBE_SYMBOL(PRINT_TYPE_FUNC_NAME(string));
|
||||
|
||||
|
||||
@@ -14,122 +14,26 @@
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
static struct trace_array *ctx_trace;
|
||||
static int __read_mostly tracer_enabled;
|
||||
static int sched_ref;
|
||||
static DEFINE_MUTEX(sched_register_mutex);
|
||||
static int sched_stopped;
|
||||
|
||||
|
||||
void
|
||||
tracing_sched_switch_trace(struct trace_array *tr,
|
||||
struct task_struct *prev,
|
||||
struct task_struct *next,
|
||||
unsigned long flags, int pc)
|
||||
{
|
||||
struct ftrace_event_call *call = &event_context_switch;
|
||||
struct ring_buffer *buffer = tr->trace_buffer.buffer;
|
||||
struct ring_buffer_event *event;
|
||||
struct ctx_switch_entry *entry;
|
||||
|
||||
event = trace_buffer_lock_reserve(buffer, TRACE_CTX,
|
||||
sizeof(*entry), flags, pc);
|
||||
if (!event)
|
||||
return;
|
||||
entry = ring_buffer_event_data(event);
|
||||
entry->prev_pid = prev->pid;
|
||||
entry->prev_prio = prev->prio;
|
||||
entry->prev_state = prev->state;
|
||||
entry->next_pid = next->pid;
|
||||
entry->next_prio = next->prio;
|
||||
entry->next_state = next->state;
|
||||
entry->next_cpu = task_cpu(next);
|
||||
|
||||
if (!call_filter_check_discard(call, entry, buffer, event))
|
||||
trace_buffer_unlock_commit(buffer, event, flags, pc);
|
||||
}
|
||||
|
||||
static void
|
||||
probe_sched_switch(void *ignore, struct task_struct *prev, struct task_struct *next)
|
||||
{
|
||||
struct trace_array_cpu *data;
|
||||
unsigned long flags;
|
||||
int cpu;
|
||||
int pc;
|
||||
|
||||
if (unlikely(!sched_ref))
|
||||
return;
|
||||
|
||||
tracing_record_cmdline(prev);
|
||||
tracing_record_cmdline(next);
|
||||
|
||||
if (!tracer_enabled || sched_stopped)
|
||||
return;
|
||||
|
||||
pc = preempt_count();
|
||||
local_irq_save(flags);
|
||||
cpu = raw_smp_processor_id();
|
||||
data = per_cpu_ptr(ctx_trace->trace_buffer.data, cpu);
|
||||
|
||||
if (likely(!atomic_read(&data->disabled)))
|
||||
tracing_sched_switch_trace(ctx_trace, prev, next, flags, pc);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void
|
||||
tracing_sched_wakeup_trace(struct trace_array *tr,
|
||||
struct task_struct *wakee,
|
||||
struct task_struct *curr,
|
||||
unsigned long flags, int pc)
|
||||
{
|
||||
struct ftrace_event_call *call = &event_wakeup;
|
||||
struct ring_buffer_event *event;
|
||||
struct ctx_switch_entry *entry;
|
||||
struct ring_buffer *buffer = tr->trace_buffer.buffer;
|
||||
|
||||
event = trace_buffer_lock_reserve(buffer, TRACE_WAKE,
|
||||
sizeof(*entry), flags, pc);
|
||||
if (!event)
|
||||
return;
|
||||
entry = ring_buffer_event_data(event);
|
||||
entry->prev_pid = curr->pid;
|
||||
entry->prev_prio = curr->prio;
|
||||
entry->prev_state = curr->state;
|
||||
entry->next_pid = wakee->pid;
|
||||
entry->next_prio = wakee->prio;
|
||||
entry->next_state = wakee->state;
|
||||
entry->next_cpu = task_cpu(wakee);
|
||||
|
||||
if (!call_filter_check_discard(call, entry, buffer, event))
|
||||
trace_buffer_unlock_commit(buffer, event, flags, pc);
|
||||
}
|
||||
|
||||
static void
|
||||
probe_sched_wakeup(void *ignore, struct task_struct *wakee, int success)
|
||||
{
|
||||
struct trace_array_cpu *data;
|
||||
unsigned long flags;
|
||||
int cpu, pc;
|
||||
|
||||
if (unlikely(!sched_ref))
|
||||
return;
|
||||
|
||||
tracing_record_cmdline(current);
|
||||
|
||||
if (!tracer_enabled || sched_stopped)
|
||||
return;
|
||||
|
||||
pc = preempt_count();
|
||||
local_irq_save(flags);
|
||||
cpu = raw_smp_processor_id();
|
||||
data = per_cpu_ptr(ctx_trace->trace_buffer.data, cpu);
|
||||
|
||||
if (likely(!atomic_read(&data->disabled)))
|
||||
tracing_sched_wakeup_trace(ctx_trace, wakee, current,
|
||||
flags, pc);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int tracing_sched_register(void)
|
||||
@@ -197,51 +101,3 @@ void tracing_stop_cmdline_record(void)
|
||||
{
|
||||
tracing_stop_sched_switch();
|
||||
}
|
||||
|
||||
/**
|
||||
* tracing_start_sched_switch_record - start tracing context switches
|
||||
*
|
||||
* Turns on context switch tracing for a tracer.
|
||||
*/
|
||||
void tracing_start_sched_switch_record(void)
|
||||
{
|
||||
if (unlikely(!ctx_trace)) {
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
tracing_start_sched_switch();
|
||||
|
||||
mutex_lock(&sched_register_mutex);
|
||||
tracer_enabled++;
|
||||
mutex_unlock(&sched_register_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* tracing_stop_sched_switch_record - start tracing context switches
|
||||
*
|
||||
* Turns off context switch tracing for a tracer.
|
||||
*/
|
||||
void tracing_stop_sched_switch_record(void)
|
||||
{
|
||||
mutex_lock(&sched_register_mutex);
|
||||
tracer_enabled--;
|
||||
WARN_ON(tracer_enabled < 0);
|
||||
mutex_unlock(&sched_register_mutex);
|
||||
|
||||
tracing_stop_sched_switch();
|
||||
}
|
||||
|
||||
/**
|
||||
* tracing_sched_switch_assign_trace - assign a trace array for ctx switch
|
||||
* @tr: trace array pointer to assign
|
||||
*
|
||||
* Some tracers might want to record the context switches in their
|
||||
* trace. This function lets those tracers assign the trace array
|
||||
* to use.
|
||||
*/
|
||||
void tracing_sched_switch_assign_trace(struct trace_array *tr)
|
||||
{
|
||||
ctx_trace = tr;
|
||||
}
|
||||
|
||||
|
||||
@@ -365,6 +365,62 @@ probe_wakeup_migrate_task(void *ignore, struct task_struct *task, int cpu)
|
||||
wakeup_current_cpu = cpu;
|
||||
}
|
||||
|
||||
static void
|
||||
tracing_sched_switch_trace(struct trace_array *tr,
|
||||
struct task_struct *prev,
|
||||
struct task_struct *next,
|
||||
unsigned long flags, int pc)
|
||||
{
|
||||
struct ftrace_event_call *call = &event_context_switch;
|
||||
struct ring_buffer *buffer = tr->trace_buffer.buffer;
|
||||
struct ring_buffer_event *event;
|
||||
struct ctx_switch_entry *entry;
|
||||
|
||||
event = trace_buffer_lock_reserve(buffer, TRACE_CTX,
|
||||
sizeof(*entry), flags, pc);
|
||||
if (!event)
|
||||
return;
|
||||
entry = ring_buffer_event_data(event);
|
||||
entry->prev_pid = prev->pid;
|
||||
entry->prev_prio = prev->prio;
|
||||
entry->prev_state = prev->state;
|
||||
entry->next_pid = next->pid;
|
||||
entry->next_prio = next->prio;
|
||||
entry->next_state = next->state;
|
||||
entry->next_cpu = task_cpu(next);
|
||||
|
||||
if (!call_filter_check_discard(call, entry, buffer, event))
|
||||
trace_buffer_unlock_commit(buffer, event, flags, pc);
|
||||
}
|
||||
|
||||
static void
|
||||
tracing_sched_wakeup_trace(struct trace_array *tr,
|
||||
struct task_struct *wakee,
|
||||
struct task_struct *curr,
|
||||
unsigned long flags, int pc)
|
||||
{
|
||||
struct ftrace_event_call *call = &event_wakeup;
|
||||
struct ring_buffer_event *event;
|
||||
struct ctx_switch_entry *entry;
|
||||
struct ring_buffer *buffer = tr->trace_buffer.buffer;
|
||||
|
||||
event = trace_buffer_lock_reserve(buffer, TRACE_WAKE,
|
||||
sizeof(*entry), flags, pc);
|
||||
if (!event)
|
||||
return;
|
||||
entry = ring_buffer_event_data(event);
|
||||
entry->prev_pid = curr->pid;
|
||||
entry->prev_prio = curr->prio;
|
||||
entry->prev_state = curr->state;
|
||||
entry->next_pid = wakee->pid;
|
||||
entry->next_prio = wakee->prio;
|
||||
entry->next_state = wakee->state;
|
||||
entry->next_cpu = task_cpu(wakee);
|
||||
|
||||
if (!call_filter_check_discard(call, entry, buffer, event))
|
||||
trace_buffer_unlock_commit(buffer, event, flags, pc);
|
||||
}
|
||||
|
||||
static void notrace
|
||||
probe_wakeup_sched_switch(void *ignore,
|
||||
struct task_struct *prev, struct task_struct *next)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user