aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorKen Chen <kenchen@google.com>2008-11-10 03:26:08 -0500
committerAlexey Dobriyan <adobriyan@gmail.com>2009-01-05 04:27:44 -0500
commit2ec220e27f5040aec1e88901c1b6ea3d135787ad (patch)
tree06ed111c8e331d47927d9b46386f4063b74ec419 /fs/proc
parent631f9c1868b970197747c80fc5168ad7d9fd5d53 (diff)
proc: add /proc/*/stack
/proc/*/stack adds the ability to query a task's stack trace. It is more useful than /proc/*/wchan as it provides full stack trace instead of single depth. Example output: $ cat /proc/self/stack [<c010a271>] save_stack_trace_tsk+0x17/0x35 [<c01827b4>] proc_pid_stack+0x4a/0x76 [<c018312d>] proc_single_show+0x4a/0x5e [<c016bdec>] seq_read+0xf3/0x29f [<c015a004>] vfs_read+0x6d/0x91 [<c015a0c1>] sys_read+0x3b/0x60 [<c0102eda>] syscall_call+0x7/0xb [<ffffffff>] 0xffffffff [add save_stack_trace_tsk() on mips, ACK Ralf --adobriyan] Signed-off-by: Ken Chen <kenchen@google.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ce7a6da1b6a0..eb7b4654d6aa 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -65,6 +65,7 @@
65#include <linux/mm.h> 65#include <linux/mm.h>
66#include <linux/rcupdate.h> 66#include <linux/rcupdate.h>
67#include <linux/kallsyms.h> 67#include <linux/kallsyms.h>
68#include <linux/stacktrace.h>
68#include <linux/resource.h> 69#include <linux/resource.h>
69#include <linux/module.h> 70#include <linux/module.h>
70#include <linux/mount.h> 71#include <linux/mount.h>
@@ -337,6 +338,37 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
337} 338}
338#endif /* CONFIG_KALLSYMS */ 339#endif /* CONFIG_KALLSYMS */
339 340
341#ifdef CONFIG_STACKTRACE
342
343#define MAX_STACK_TRACE_DEPTH 64
344
345static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
346 struct pid *pid, struct task_struct *task)
347{
348 struct stack_trace trace;
349 unsigned long *entries;
350 int i;
351
352 entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL);
353 if (!entries)
354 return -ENOMEM;
355
356 trace.nr_entries = 0;
357 trace.max_entries = MAX_STACK_TRACE_DEPTH;
358 trace.entries = entries;
359 trace.skip = 0;
360 save_stack_trace_tsk(task, &trace);
361
362 for (i = 0; i < trace.nr_entries; i++) {
363 seq_printf(m, "[<%p>] %pS\n",
364 (void *)entries[i], (void *)entries[i]);
365 }
366 kfree(entries);
367
368 return 0;
369}
370#endif
371
340#ifdef CONFIG_SCHEDSTATS 372#ifdef CONFIG_SCHEDSTATS
341/* 373/*
342 * Provides /proc/PID/schedstat 374 * Provides /proc/PID/schedstat
@@ -2500,6 +2532,9 @@ static const struct pid_entry tgid_base_stuff[] = {
2500#ifdef CONFIG_KALLSYMS 2532#ifdef CONFIG_KALLSYMS
2501 INF("wchan", S_IRUGO, proc_pid_wchan), 2533 INF("wchan", S_IRUGO, proc_pid_wchan),
2502#endif 2534#endif
2535#ifdef CONFIG_STACKTRACE
2536 ONE("stack", S_IRUSR, proc_pid_stack),
2537#endif
2503#ifdef CONFIG_SCHEDSTATS 2538#ifdef CONFIG_SCHEDSTATS
2504 INF("schedstat", S_IRUGO, proc_pid_schedstat), 2539 INF("schedstat", S_IRUGO, proc_pid_schedstat),
2505#endif 2540#endif
@@ -2835,6 +2870,9 @@ static const struct pid_entry tid_base_stuff[] = {
2835#ifdef CONFIG_KALLSYMS 2870#ifdef CONFIG_KALLSYMS
2836 INF("wchan", S_IRUGO, proc_pid_wchan), 2871 INF("wchan", S_IRUGO, proc_pid_wchan),
2837#endif 2872#endif
2873#ifdef CONFIG_STACKTRACE
2874 ONE("stack", S_IRUSR, proc_pid_stack),
2875#endif
2838#ifdef CONFIG_SCHEDSTATS 2876#ifdef CONFIG_SCHEDSTATS
2839 INF("schedstat", S_IRUGO, proc_pid_schedstat), 2877 INF("schedstat", S_IRUGO, proc_pid_schedstat),
2840#endif 2878#endif