diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-05-12 15:20:48 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-23 17:40:13 -0400 |
| commit | 9f6b4e3f4a24f2590f1c96f117fc45fbea9b0fa4 (patch) | |
| tree | 88ff9c7f68116addae7bf3f3b7c59e204be7d06e /kernel/trace | |
| parent | ef4ab15ff34fd9c65e92bee70f58e7179da881c5 (diff) | |
ftrace: sysprof fix
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/trace_sysprof.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c index 7f6fcccffb88..f9a09fe705b0 100644 --- a/kernel/trace/trace_sysprof.c +++ b/kernel/trace/trace_sysprof.c | |||
| @@ -37,21 +37,26 @@ struct stack_frame { | |||
| 37 | 37 | ||
| 38 | static int copy_stack_frame(const void __user *fp, struct stack_frame *frame) | 38 | static int copy_stack_frame(const void __user *fp, struct stack_frame *frame) |
| 39 | { | 39 | { |
| 40 | int ret; | ||
| 41 | |||
| 40 | if (!access_ok(VERIFY_READ, fp, sizeof(*frame))) | 42 | if (!access_ok(VERIFY_READ, fp, sizeof(*frame))) |
| 41 | return 0; | 43 | return 0; |
| 42 | 44 | ||
| 43 | if (__copy_from_user_inatomic(frame, frame_pointer, sizeof(*frame))) | 45 | ret = 1; |
| 44 | return 0; | 46 | pagefault_disable(); |
| 47 | if (__copy_from_user_inatomic(frame, fp, sizeof(*frame))) | ||
| 48 | ret = 0; | ||
| 49 | pagefault_enable(); | ||
| 45 | 50 | ||
| 46 | return 1; | 51 | return ret; |
| 47 | } | 52 | } |
| 48 | 53 | ||
| 49 | static void timer_notify(struct pt_regs *regs, int cpu) | 54 | static void timer_notify(struct pt_regs *regs, int cpu) |
| 50 | { | 55 | { |
| 51 | const void __user *frame_pointer; | ||
| 52 | struct trace_array_cpu *data; | 56 | struct trace_array_cpu *data; |
| 53 | struct stack_frame frame; | 57 | struct stack_frame frame; |
| 54 | struct trace_array *tr; | 58 | struct trace_array *tr; |
| 59 | const void __user *fp; | ||
| 55 | int is_user; | 60 | int is_user; |
| 56 | int i; | 61 | int i; |
| 57 | 62 | ||
| @@ -77,21 +82,26 @@ static void timer_notify(struct pt_regs *regs, int cpu) | |||
| 77 | 82 | ||
| 78 | trace_special(tr, data, 0, current->pid, regs->ip); | 83 | trace_special(tr, data, 0, current->pid, regs->ip); |
| 79 | 84 | ||
| 80 | frame_pointer = (void __user *)regs->bp; | 85 | fp = (void __user *)regs->bp; |
| 81 | 86 | ||
| 82 | for (i = 0; i < sample_max_depth; i++) { | 87 | for (i = 0; i < sample_max_depth; i++) { |
| 83 | if (!copy_stack_frame(frame_pointer, &frame)) | 88 | frame.next_fp = 0; |
| 89 | frame.return_address = 0; | ||
| 90 | if (!copy_stack_frame(fp, &frame)) | ||
| 84 | break; | 91 | break; |
| 85 | if ((unsigned long)frame_pointer < regs->sp) | 92 | if ((unsigned long)fp < regs->sp) |
| 86 | break; | 93 | break; |
| 87 | 94 | ||
| 88 | trace_special(tr, data, 1, frame.return_address, | 95 | trace_special(tr, data, 1, frame.return_address, |
| 89 | (unsigned long)frame_pointer); | 96 | (unsigned long)fp); |
| 90 | frame_pointer = frame.next_fp; | 97 | fp = frame.next_fp; |
| 91 | } | 98 | } |
| 92 | 99 | ||
| 93 | trace_special(tr, data, 2, current->pid, i); | 100 | trace_special(tr, data, 2, current->pid, i); |
| 94 | 101 | ||
| 102 | /* | ||
| 103 | * Special trace entry if we overflow the max depth: | ||
| 104 | */ | ||
| 95 | if (i == sample_max_depth) | 105 | if (i == sample_max_depth) |
| 96 | trace_special(tr, data, -1, -1, -1); | 106 | trace_special(tr, data, -1, -1, -1); |
| 97 | } | 107 | } |
