]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ftrace: sysprof fix
authorIngo Molnar <mingo@elte.hu>
Mon, 12 May 2008 19:20:48 +0000 (21:20 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 23 May 2008 21:40:13 +0000 (23:40 +0200)
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
kernel/trace/trace_sysprof.c

index 7f6fcccffb88acdf837a0d5c5e799c028494473a..f9a09fe705b014066378039c1c32e0e904e478ad 100644 (file)
@@ -37,21 +37,26 @@ struct stack_frame {
 
 static int copy_stack_frame(const void __user *fp, struct stack_frame *frame)
 {
+       int ret;
+
        if (!access_ok(VERIFY_READ, fp, sizeof(*frame)))
                return 0;
 
-       if (__copy_from_user_inatomic(frame, frame_pointer, sizeof(*frame)))
-               return 0;
+       ret = 1;
+       pagefault_disable();
+       if (__copy_from_user_inatomic(frame, fp, sizeof(*frame)))
+               ret = 0;
+       pagefault_enable();
 
-       return 1;
+       return ret;
 }
 
 static void timer_notify(struct pt_regs *regs, int cpu)
 {
-       const void __user *frame_pointer;
        struct trace_array_cpu *data;
        struct stack_frame frame;
        struct trace_array *tr;
+       const void __user *fp;
        int is_user;
        int i;
 
@@ -77,21 +82,26 @@ static void timer_notify(struct pt_regs *regs, int cpu)
 
        trace_special(tr, data, 0, current->pid, regs->ip);
 
-       frame_pointer = (void __user *)regs->bp;
+       fp = (void __user *)regs->bp;
 
        for (i = 0; i < sample_max_depth; i++) {
-               if (!copy_stack_frame(frame_pointer, &frame))
+               frame.next_fp = 0;
+               frame.return_address = 0;
+               if (!copy_stack_frame(fp, &frame))
                        break;
-               if ((unsigned long)frame_pointer < regs->sp)
+               if ((unsigned long)fp < regs->sp)
                        break;
 
                trace_special(tr, data, 1, frame.return_address,
-                             (unsigned long)frame_pointer);
-               frame_pointer = frame.next_fp;
+                             (unsigned long)fp);
+               fp = frame.next_fp;
        }
 
        trace_special(tr, data, 2, current->pid, i);
 
+       /*
+        * Special trace entry if we overflow the max depth:
+        */
        if (i == sample_max_depth)
                trace_special(tr, data, -1, -1, -1);
 }