aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2008-08-29 16:51:43 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-14 04:36:28 -0400
commit1b6cced6ec9677fa65471e890dfdcb4bf5387643 (patch)
tree3728f61fff36a4c2f1f41ae15e638be58437c6bc
parentd53475b5aa946752e3306b2ecb5a8c9c51cf8dd0 (diff)
ftrace: stack trace add indexes
This patch adds indexes into the stack that the functions in the stack dump were found at. As an added bonus, I also added a diff to show which function is the most notorious consumer of the stack. The output now looks like this: # cat /debug/tracing/stack_trace Depth Size Location (48 entries) ----- ---- -------- 0) 2476 212 blk_recount_segments+0x39/0x59 1) 2264 12 bio_phys_segments+0x16/0x1d 2) 2252 20 blk_rq_bio_prep+0x23/0xaf 3) 2232 12 init_request_from_bio+0x74/0x77 4) 2220 56 __make_request+0x294/0x331 5) 2164 136 generic_make_request+0x34f/0x37d 6) 2028 56 submit_bio+0xe7/0xef 7) 1972 28 submit_bh+0xd1/0xf0 8) 1944 112 block_read_full_page+0x299/0x2a9 9) 1832 8 blkdev_readpage+0x14/0x16 10) 1824 28 read_cache_page_async+0x7e/0x109 11) 1796 16 read_cache_page+0x11/0x49 12) 1780 32 read_dev_sector+0x3c/0x72 13) 1748 48 read_lba+0x4d/0xaa 14) 1700 168 efi_partition+0x85/0x61b 15) 1532 72 rescan_partitions+0x10e/0x266 16) 1460 40 do_open+0x1c7/0x24e 17) 1420 292 __blkdev_get+0x79/0x84 18) 1128 12 blkdev_get+0x12/0x14 19) 1116 20 register_disk+0xd1/0x11e 20) 1096 28 add_disk+0x34/0x90 21) 1068 52 sd_probe+0x2b1/0x366 22) 1016 20 driver_probe_device+0xa5/0x120 23) 996 8 __device_attach+0xd/0xf 24) 988 32 bus_for_each_drv+0x3e/0x68 25) 956 24 device_attach+0x56/0x6c 26) 932 16 bus_attach_device+0x26/0x4d 27) 916 64 device_add+0x380/0x4b4 28) 852 28 scsi_sysfs_add_sdev+0xa1/0x1c9 29) 824 160 scsi_probe_and_add_lun+0x919/0xa2a 30) 664 36 __scsi_add_device+0x88/0xae 31) 628 44 ata_scsi_scan_host+0x9e/0x21c 32) 584 28 ata_host_register+0x1cb/0x1db 33) 556 24 ata_host_activate+0x98/0xb5 34) 532 192 ahci_init_one+0x9bd/0x9e9 35) 340 20 pci_device_probe+0x3e/0x5e 36) 320 20 driver_probe_device+0xa5/0x120 37) 300 20 __driver_attach+0x3f/0x5e 38) 280 36 bus_for_each_dev+0x40/0x62 39) 244 12 driver_attach+0x19/0x1b 40) 232 28 bus_add_driver+0x9c/0x1af 41) 204 28 driver_register+0x76/0xd2 42) 176 20 __pci_register_driver+0x44/0x71 43) 156 8 ahci_init+0x14/0x16 44) 148 100 _stext+0x42/0x122 45) 48 20 kernel_init+0x175/0x1dc 46) 28 28 kernel_thread_helper+0x7/0x10 The first column is simply an index starting from the inner most function and counting down to the outer most. The next column is the location that the function was found on the stack. The next column is the size of the stack for that function. Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/trace/trace_stack.c90
1 files changed, 73 insertions, 17 deletions
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 4d1e522e3fe8..74c5d9a3afae 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -16,8 +16,10 @@
16 16
17#define STACK_TRACE_ENTRIES 500 17#define STACK_TRACE_ENTRIES 500
18 18
19static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES] = 19static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] =
20 { [0 ... (STACK_TRACE_ENTRIES-1)] = ULONG_MAX }; 20 { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX };
21static unsigned stack_dump_index[STACK_TRACE_ENTRIES];
22
21static struct stack_trace max_stack_trace = { 23static struct stack_trace max_stack_trace = {
22 .max_entries = STACK_TRACE_ENTRIES, 24 .max_entries = STACK_TRACE_ENTRIES,
23 .entries = stack_dump_trace, 25 .entries = stack_dump_trace,
@@ -32,8 +34,9 @@ static DEFINE_PER_CPU(int, trace_active);
32 34
33static inline void check_stack(void) 35static inline void check_stack(void)
34{ 36{
35 unsigned long this_size; 37 unsigned long this_size, flags;
36 unsigned long flags; 38 unsigned long *p, *top, *start;
39 int i;
37 40
38 this_size = ((unsigned long)&this_size) & (THREAD_SIZE-1); 41 this_size = ((unsigned long)&this_size) & (THREAD_SIZE-1);
39 this_size = THREAD_SIZE - this_size; 42 this_size = THREAD_SIZE - this_size;
@@ -51,10 +54,42 @@ static inline void check_stack(void)
51 max_stack_size = this_size; 54 max_stack_size = this_size;
52 55
53 max_stack_trace.nr_entries = 0; 56 max_stack_trace.nr_entries = 0;
54 max_stack_trace.skip = 1; 57 max_stack_trace.skip = 3;
55 58
56 save_stack_trace(&max_stack_trace); 59 save_stack_trace(&max_stack_trace);
57 60
61 /*
62 * Now find where in the stack these are.
63 */
64 i = 0;
65 start = &this_size;
66 top = (unsigned long *)
67 (((unsigned long)start & ~(THREAD_SIZE-1)) + THREAD_SIZE);
68
69 /*
70 * Loop through all the entries. One of the entries may
71 * for some reason be missed on the stack, so we may
72 * have to account for them. If they are all there, this
73 * loop will only happen once. This code only takes place
74 * on a new max, so it is far from a fast path.
75 */
76 while (i < max_stack_trace.nr_entries) {
77
78 stack_dump_index[i] = this_size;
79 p = start;
80
81 for (; p < top && i < max_stack_trace.nr_entries; p++) {
82 if (*p == stack_dump_trace[i]) {
83 this_size = stack_dump_index[i++] =
84 (top - p) * sizeof(unsigned long);
85 /* Start the search from here */
86 start = p + 1;
87 }
88 }
89
90 i++;
91 }
92
58 out: 93 out:
59 __raw_spin_unlock(&max_stack_lock); 94 __raw_spin_unlock(&max_stack_lock);
60 raw_local_irq_restore(flags); 95 raw_local_irq_restore(flags);
@@ -145,22 +180,24 @@ static struct file_operations stack_max_size_fops = {
145static void * 180static void *
146t_next(struct seq_file *m, void *v, loff_t *pos) 181t_next(struct seq_file *m, void *v, loff_t *pos)
147{ 182{
148 unsigned long *t = m->private; 183 long i = (long)m->private;
149 184
150 (*pos)++; 185 (*pos)++;
151 186
152 if (!t || *t == ULONG_MAX) 187 i++;
188
189 if (i >= max_stack_trace.nr_entries ||
190 stack_dump_trace[i] == ULONG_MAX)
153 return NULL; 191 return NULL;
154 192
155 t++; 193 m->private = (void *)i;
156 m->private = t;
157 194
158 return t; 195 return &m->private;
159} 196}
160 197
161static void *t_start(struct seq_file *m, loff_t *pos) 198static void *t_start(struct seq_file *m, loff_t *pos)
162{ 199{
163 unsigned long *t = m->private; 200 void *t = &m->private;
164 loff_t l = 0; 201 loff_t l = 0;
165 202
166 local_irq_disable(); 203 local_irq_disable();
@@ -178,14 +215,15 @@ static void t_stop(struct seq_file *m, void *p)
178 local_irq_enable(); 215 local_irq_enable();
179} 216}
180 217
181static int trace_lookup_stack(struct seq_file *m, unsigned long addr) 218static int trace_lookup_stack(struct seq_file *m, long i)
182{ 219{
220 unsigned long addr = stack_dump_trace[i];
183#ifdef CONFIG_KALLSYMS 221#ifdef CONFIG_KALLSYMS
184 char str[KSYM_SYMBOL_LEN]; 222 char str[KSYM_SYMBOL_LEN];
185 223
186 sprint_symbol(str, addr); 224 sprint_symbol(str, addr);
187 225
188 return seq_printf(m, "[<%p>] %s\n", (void*)addr, str); 226 return seq_printf(m, "%s\n", str);
189#else 227#else
190 return seq_printf(m, "%p\n", (void*)addr); 228 return seq_printf(m, "%p\n", (void*)addr);
191#endif 229#endif
@@ -193,12 +231,30 @@ static int trace_lookup_stack(struct seq_file *m, unsigned long addr)
193 231
194static int t_show(struct seq_file *m, void *v) 232static int t_show(struct seq_file *m, void *v)
195{ 233{
196 unsigned long *t = v; 234 long i = *(long *)v;
235 int size;
236
237 if (i < 0) {
238 seq_printf(m, " Depth Size Location"
239 " (%d entries)\n"
240 " ----- ---- --------\n",
241 max_stack_trace.nr_entries);
242 return 0;
243 }
197 244
198 if (!t || *t == ULONG_MAX) 245 if (i >= max_stack_trace.nr_entries ||
246 stack_dump_trace[i] == ULONG_MAX)
199 return 0; 247 return 0;
200 248
201 trace_lookup_stack(m, *t); 249 if (i+1 == max_stack_trace.nr_entries ||
250 stack_dump_trace[i+1] == ULONG_MAX)
251 size = stack_dump_index[i];
252 else
253 size = stack_dump_index[i] - stack_dump_index[i+1];
254
255 seq_printf(m, "%3ld) %8d %5d ", i, stack_dump_index[i], size);
256
257 trace_lookup_stack(m, i);
202 258
203 return 0; 259 return 0;
204} 260}
@@ -217,7 +273,7 @@ static int stack_trace_open(struct inode *inode, struct file *file)
217 ret = seq_open(file, &stack_trace_seq_ops); 273 ret = seq_open(file, &stack_trace_seq_ops);
218 if (!ret) { 274 if (!ret) {
219 struct seq_file *m = file->private_data; 275 struct seq_file *m = file->private_data;
220 m->private = stack_dump_trace; 276 m->private = (void *)-1;
221 } 277 }
222 278
223 return ret; 279 return ret;