aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2009-07-07 01:52:36 -0400
committerIngo Molnar <mingo@elte.hu>2009-07-10 05:59:40 -0400
commitdb59504d89db1462a5281fb55b1d962cb74a398f (patch)
treeb33fcbee2ee8103c15f6e19ab3039af46fc62219
parent9d22b536609abf0d64648f99518676ea58245e3b (diff)
ksym_tracer: Extract trace entry from struct trace_ksym
struct trace_ksym is used as an entry in hbp list, and is also used as trace_entry stored in ring buffer. This is not necessary and is a waste of memory in ring buffer. There is also a bug that dereferencing field->ksym_hbp in ksym_trace_output() can be invalid. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Acked-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: "K.Prasad" <prasad@linux.vnet.ibm.com> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <4A52E2A4.4050007@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/trace/trace.h13
-rw-r--r--kernel/trace/trace_ksym.c26
2 files changed, 22 insertions, 17 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 7d5cc37b8fca..ff1ef411a176 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -215,17 +215,12 @@ struct syscall_trace_exit {
215#define KSYM_SELFTEST_ENTRY "ksym_selftest_dummy" 215#define KSYM_SELFTEST_ENTRY "ksym_selftest_dummy"
216extern int process_new_ksym_entry(char *ksymname, int op, unsigned long addr); 216extern int process_new_ksym_entry(char *ksymname, int op, unsigned long addr);
217 217
218struct trace_ksym { 218struct ksym_trace_entry {
219 struct trace_entry ent; 219 struct trace_entry ent;
220 struct hw_breakpoint *ksym_hbp;
221 unsigned long ksym_addr;
222 unsigned long ip; 220 unsigned long ip;
223#ifdef CONFIG_PROFILE_KSYM_TRACER 221 unsigned char type;
224 unsigned long counter;
225#endif
226 struct hlist_node ksym_hlist;
227 char ksym_name[KSYM_NAME_LEN]; 222 char ksym_name[KSYM_NAME_LEN];
228 char p_name[TASK_COMM_LEN]; 223 char cmd[TASK_COMM_LEN];
229}; 224};
230 225
231/* 226/*
@@ -343,7 +338,7 @@ extern void __ftrace_bad_type(void);
343 TRACE_SYSCALL_ENTER); \ 338 TRACE_SYSCALL_ENTER); \
344 IF_ASSIGN(var, ent, struct syscall_trace_exit, \ 339 IF_ASSIGN(var, ent, struct syscall_trace_exit, \
345 TRACE_SYSCALL_EXIT); \ 340 TRACE_SYSCALL_EXIT); \
346 IF_ASSIGN(var, ent, struct trace_ksym, TRACE_KSYM); \ 341 IF_ASSIGN(var, ent, struct ksym_trace_entry, TRACE_KSYM);\
347 __ftrace_bad_type(); \ 342 __ftrace_bad_type(); \
348 } while (0) 343 } while (0)
349 344
diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c
index eef97e7c8db7..085ff055fdfa 100644
--- a/kernel/trace/trace_ksym.c
+++ b/kernel/trace/trace_ksym.c
@@ -37,6 +37,15 @@
37#define KSYM_TRACER_OP_LEN 3 /* rw- */ 37#define KSYM_TRACER_OP_LEN 3 /* rw- */
38#define KSYM_FILTER_ENTRY_LEN (KSYM_NAME_LEN + KSYM_TRACER_OP_LEN + 1) 38#define KSYM_FILTER_ENTRY_LEN (KSYM_NAME_LEN + KSYM_TRACER_OP_LEN + 1)
39 39
40struct trace_ksym {
41 struct hw_breakpoint *ksym_hbp;
42 unsigned long ksym_addr;
43#ifdef CONFIG_PROFILE_KSYM_TRACER
44 unsigned long counter;
45#endif
46 struct hlist_node ksym_hlist;
47};
48
40static struct trace_array *ksym_trace_array; 49static struct trace_array *ksym_trace_array;
41 50
42static unsigned int ksym_filter_entry_count; 51static unsigned int ksym_filter_entry_count;
@@ -71,7 +80,7 @@ void ksym_hbp_handler(struct hw_breakpoint *hbp, struct pt_regs *regs)
71{ 80{
72 struct ring_buffer_event *event; 81 struct ring_buffer_event *event;
73 struct trace_array *tr; 82 struct trace_array *tr;
74 struct trace_ksym *entry; 83 struct ksym_trace_entry *entry;
75 int pc; 84 int pc;
76 85
77 if (!ksym_tracing_enabled) 86 if (!ksym_tracing_enabled)
@@ -85,11 +94,12 @@ void ksym_hbp_handler(struct hw_breakpoint *hbp, struct pt_regs *regs)
85 if (!event) 94 if (!event)
86 return; 95 return;
87 96
88 entry = ring_buffer_event_data(event); 97 entry = ring_buffer_event_data(event);
98 entry->ip = instruction_pointer(regs);
99 entry->type = hbp->info.type;
89 strlcpy(entry->ksym_name, hbp->info.name, KSYM_SYMBOL_LEN); 100 strlcpy(entry->ksym_name, hbp->info.name, KSYM_SYMBOL_LEN);
90 entry->ksym_hbp = hbp; 101 strlcpy(entry->cmd, current->comm, TASK_COMM_LEN);
91 entry->ip = instruction_pointer(regs); 102
92 strlcpy(entry->p_name, current->comm, TASK_COMM_LEN);
93#ifdef CONFIG_PROFILE_KSYM_TRACER 103#ifdef CONFIG_PROFILE_KSYM_TRACER
94 ksym_collect_stats(hbp->info.address); 104 ksym_collect_stats(hbp->info.address);
95#endif /* CONFIG_PROFILE_KSYM_TRACER */ 105#endif /* CONFIG_PROFILE_KSYM_TRACER */
@@ -380,7 +390,7 @@ static enum print_line_t ksym_trace_output(struct trace_iterator *iter)
380{ 390{
381 struct trace_entry *entry = iter->ent; 391 struct trace_entry *entry = iter->ent;
382 struct trace_seq *s = &iter->seq; 392 struct trace_seq *s = &iter->seq;
383 struct trace_ksym *field; 393 struct ksym_trace_entry *field;
384 char str[KSYM_SYMBOL_LEN]; 394 char str[KSYM_SYMBOL_LEN];
385 int ret; 395 int ret;
386 396
@@ -389,12 +399,12 @@ static enum print_line_t ksym_trace_output(struct trace_iterator *iter)
389 399
390 trace_assign_type(field, entry); 400 trace_assign_type(field, entry);
391 401
392 ret = trace_seq_printf(s, "%-15s %-5d %-3d %-20s ", field->p_name, 402 ret = trace_seq_printf(s, "%-15s %-5d %-3d %-20s ", field->cmd,
393 entry->pid, iter->cpu, field->ksym_name); 403 entry->pid, iter->cpu, field->ksym_name);
394 if (!ret) 404 if (!ret)
395 return TRACE_TYPE_PARTIAL_LINE; 405 return TRACE_TYPE_PARTIAL_LINE;
396 406
397 switch (field->ksym_hbp->info.type) { 407 switch (field->type) {
398 case HW_BREAKPOINT_WRITE: 408 case HW_BREAKPOINT_WRITE:
399 ret = trace_seq_printf(s, " W "); 409 ret = trace_seq_printf(s, " W ");
400 break; 410 break;