Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf: Fix arch_perf_out_copy_user default

The arch_perf_output_copy_user() default of
__copy_from_user_inatomic() returns bytes not copied, while all other
argument functions given DEFINE_OUTPUT_COPY() return bytes copied.

Since copy_from_user_nmi() is the odd duck out by returning bytes
copied where all other *copy_{to,from}* functions return bytes not
copied, change it over and ammend DEFINE_OUTPUT_COPY() to expect bytes
not copied.

Oddly enough DEFINE_OUTPUT_COPY() already returned bytes not copied
while expecting its worker functions to return bytes copied.

Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Acked-by: will.deacon@arm.com
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Link: http://lkml.kernel.org/r/20131030201622.GR16117@laptop.programming.kicks-ass.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Peter Zijlstra and committed by
Ingo Molnar
0a196848 394570b7

+33 -16
+2 -2
arch/x86/kernel/cpu/perf_event.c
··· 1989 1989 frame.return_address = 0; 1990 1990 1991 1991 bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); 1992 - if (bytes != sizeof(frame)) 1992 + if (bytes != 0) 1993 1993 break; 1994 1994 1995 1995 if (!valid_user_frame(fp, sizeof(frame))) ··· 2041 2041 frame.return_address = 0; 2042 2042 2043 2043 bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); 2044 - if (bytes != sizeof(frame)) 2044 + if (bytes != 0) 2045 2045 break; 2046 2046 2047 2047 if (!valid_user_frame(fp, sizeof(frame)))
+1 -1
arch/x86/kernel/cpu/perf_event_intel_ds.c
··· 789 789 790 790 size = ip - to; /* Must fit our buffer, see above */ 791 791 bytes = copy_from_user_nmi(buf, (void __user *)to, size); 792 - if (bytes != size) 792 + if (bytes != 0) 793 793 return 0; 794 794 795 795 kaddr = buf;
+1 -1
arch/x86/kernel/cpu/perf_event_intel_lbr.c
··· 491 491 492 492 /* may fail if text not present */ 493 493 bytes = copy_from_user_nmi(buf, (void __user *)from, size); 494 - if (bytes != size) 494 + if (bytes != 0) 495 495 return X86_BR_NONE; 496 496 497 497 addr = buf;
+1 -1
arch/x86/lib/usercopy.c
··· 31 31 ret = __copy_from_user_inatomic(to, from, n); 32 32 pagefault_enable(); 33 33 34 - return n - ret; 34 + return ret; 35 35 } 36 36 EXPORT_SYMBOL_GPL(copy_from_user_nmi);
+2 -2
arch/x86/oprofile/backtrace.c
··· 47 47 unsigned long bytes; 48 48 49 49 bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); 50 - if (bytes != sizeof(bufhead)) 50 + if (bytes != 0) 51 51 return NULL; 52 52 53 53 fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame); ··· 93 93 unsigned long bytes; 94 94 95 95 bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); 96 - if (bytes != sizeof(bufhead)) 96 + if (bytes != 0) 97 97 return NULL; 98 98 99 99 oprofile_add_trace(bufhead[0].return_address);
+26 -9
kernel/events/internal.h
··· 82 82 } 83 83 84 84 #define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \ 85 - static inline unsigned int \ 85 + static inline unsigned long \ 86 86 func_name(struct perf_output_handle *handle, \ 87 - const void *buf, unsigned int len) \ 87 + const void *buf, unsigned long len) \ 88 88 { \ 89 89 unsigned long size, written; \ 90 90 \ 91 91 do { \ 92 - size = min_t(unsigned long, handle->size, len); \ 93 - \ 92 + size = min(handle->size, len); \ 94 93 written = memcpy_func(handle->addr, buf, size); \ 94 + written = size - written; \ 95 95 \ 96 96 len -= written; \ 97 97 handle->addr += written; \ ··· 110 110 return len; \ 111 111 } 112 112 113 - static inline int memcpy_common(void *dst, const void *src, size_t n) 113 + static inline unsigned long 114 + memcpy_common(void *dst, const void *src, unsigned long n) 114 115 { 115 116 memcpy(dst, src, n); 116 - return n; 117 + return 0; 117 118 } 118 119 119 120 DEFINE_OUTPUT_COPY(__output_copy, memcpy_common) 120 121 121 - #define MEMCPY_SKIP(dst, src, n) (n) 122 + static inline unsigned long 123 + memcpy_skip(void *dst, const void *src, unsigned long n) 124 + { 125 + return 0; 126 + } 122 127 123 - DEFINE_OUTPUT_COPY(__output_skip, MEMCPY_SKIP) 128 + DEFINE_OUTPUT_COPY(__output_skip, memcpy_skip) 124 129 125 130 #ifndef arch_perf_out_copy_user 126 - #define arch_perf_out_copy_user __copy_from_user_inatomic 131 + #define arch_perf_out_copy_user arch_perf_out_copy_user 132 + 133 + static inline unsigned long 134 + arch_perf_out_copy_user(void *dst, const void *src, unsigned long n) 135 + { 136 + unsigned long ret; 137 + 138 + pagefault_disable(); 139 + ret = __copy_from_user_inatomic(dst, src, n); 140 + pagefault_enable(); 141 + 142 + return ret; 143 + } 127 144 #endif 128 145 129 146 DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user)