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

perf core: Add a 'nr' field to perf_event_callchain_context

We will use it to count how many addresses are in the entry->ip[] array,
excluding PERF_CONTEXT_{KERNEL,USER,etc} entries, so that we can really
return the number of entries specified by the user via the relevant
sysctl, kernel.perf_event_max_contexts, or via the per event
perf_event_attr.sample_max_stack knob.

This way we keep the perf_sample->ip_callchain->nr meaning, that is the
number of entries, be it real addresses or PERF_CONTEXT_ entries, while
honouring the max_stack knobs, i.e. the end result will be max_stack
entries if we have at least that many entries in a given stack trace.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/n/tip-s8teto51tdqvlfhefndtat9r@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

+18 -17
+1 -1
arch/arm/kernel/perf_callchain.c
··· 75 75 76 76 tail = (struct frame_tail __user *)regs->ARM_fp - 1; 77 77 78 - while ((entry->entry->nr < entry->max_stack) && 78 + while ((entry->nr < entry->max_stack) && 79 79 tail && !((unsigned long)tail & 0x3)) 80 80 tail = user_backtrace(tail, entry); 81 81 }
+2 -2
arch/arm64/kernel/perf_callchain.c
··· 122 122 123 123 tail = (struct frame_tail __user *)regs->regs[29]; 124 124 125 - while (entry->entry->nr < entry->max_stack && 125 + while (entry->nr < entry->max_stack && 126 126 tail && !((unsigned long)tail & 0xf)) 127 127 tail = user_backtrace(tail, entry); 128 128 } else { ··· 132 132 133 133 tail = (struct compat_frame_tail __user *)regs->compat_fp - 1; 134 134 135 - while ((entry->entry->nr < entry->max_stack) && 135 + while ((entry->nr < entry->max_stack) && 136 136 tail && !((unsigned long)tail & 0x3)) 137 137 tail = compat_user_backtrace(tail, entry); 138 138 #endif
+1 -1
arch/metag/kernel/perf_callchain.c
··· 65 65 66 66 --frame; 67 67 68 - while ((entry->entry->nr < entry->max_stack) && frame) 68 + while ((entry->nr < entry->max_stack) && frame) 69 69 frame = user_backtrace(frame, entry); 70 70 } 71 71
+2 -2
arch/mips/kernel/perf_event.c
··· 35 35 addr = *sp++; 36 36 if (__kernel_text_address(addr)) { 37 37 perf_callchain_store(entry, addr); 38 - if (entry->entry->nr >= entry->max_stack) 38 + if (entry->nr >= entry->max_stack) 39 39 break; 40 40 } 41 41 } ··· 59 59 } 60 60 do { 61 61 perf_callchain_store(entry, pc); 62 - if (entry->entry->nr >= entry->max_stack) 62 + if (entry->nr >= entry->max_stack) 63 63 break; 64 64 pc = unwind_stack(current, &sp, pc, &ra); 65 65 } while (pc);
+2 -2
arch/powerpc/perf/callchain.c
··· 247 247 sp = regs->gpr[1]; 248 248 perf_callchain_store(entry, next_ip); 249 249 250 - while (entry->entry->nr < entry->max_stack) { 250 + while (entry->nr < entry->max_stack) { 251 251 fp = (unsigned long __user *) sp; 252 252 if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp)) 253 253 return; ··· 453 453 sp = regs->gpr[1]; 454 454 perf_callchain_store(entry, next_ip); 455 455 456 - while (entry->entry->nr < entry->max_stack) { 456 + while (entry->nr < entry->max_stack) { 457 457 fp = (unsigned int __user *) (unsigned long) sp; 458 458 if (!valid_user_sp(sp, 0) || read_user_stack_32(fp, &next_sp)) 459 459 return;
+3 -3
arch/sparc/kernel/perf_event.c
··· 1756 1756 } 1757 1757 } 1758 1758 #endif 1759 - } while (entry->entry->nr < entry->max_stack); 1759 + } while (entry->nr < entry->max_stack); 1760 1760 } 1761 1761 1762 1762 static inline int ··· 1790 1790 pc = sf.callers_pc; 1791 1791 ufp = (unsigned long)sf.fp + STACK_BIAS; 1792 1792 perf_callchain_store(entry, pc); 1793 - } while (entry->entry->nr < entry->max_stack); 1793 + } while (entry->nr < entry->max_stack); 1794 1794 } 1795 1795 1796 1796 static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, ··· 1822 1822 ufp = (unsigned long)sf.fp; 1823 1823 } 1824 1824 perf_callchain_store(entry, pc); 1825 - } while (entry->entry->nr < entry->max_stack); 1825 + } while (entry->nr < entry->max_stack); 1826 1826 } 1827 1827 1828 1828 void
+2 -2
arch/x86/events/core.c
··· 2283 2283 2284 2284 fp = compat_ptr(ss_base + regs->bp); 2285 2285 pagefault_disable(); 2286 - while (entry->entry->nr < entry->max_stack) { 2286 + while (entry->nr < entry->max_stack) { 2287 2287 unsigned long bytes; 2288 2288 frame.next_frame = 0; 2289 2289 frame.return_address = 0; ··· 2343 2343 return; 2344 2344 2345 2345 pagefault_disable(); 2346 - while (entry->entry->nr < entry->max_stack) { 2346 + while (entry->nr < entry->max_stack) { 2347 2347 unsigned long bytes; 2348 2348 frame.next_frame = NULL; 2349 2349 frame.return_address = 0;
+4 -2
include/linux/perf_event.h
··· 64 64 struct perf_callchain_entry_ctx { 65 65 struct perf_callchain_entry *entry; 66 66 u32 max_stack; 67 + u32 nr; 67 68 }; 68 69 69 70 struct perf_raw_record { ··· 1081 1080 1082 1081 static inline int perf_callchain_store(struct perf_callchain_entry_ctx *ctx, u64 ip) 1083 1082 { 1084 - struct perf_callchain_entry *entry = ctx->entry; 1085 - if (entry->nr < ctx->max_stack) { 1083 + if (ctx->nr < ctx->max_stack) { 1084 + struct perf_callchain_entry *entry = ctx->entry; 1086 1085 entry->ip[entry->nr++] = ip; 1086 + ++ctx->nr; 1087 1087 return 0; 1088 1088 } else { 1089 1089 return -1; /* no more room, stop walking the stack */
+1 -2
kernel/events/callchain.c
··· 196 196 197 197 ctx.entry = entry; 198 198 ctx.max_stack = max_stack; 199 - 200 - entry->nr = init_nr; 199 + ctx.nr = entry->nr = init_nr; 201 200 202 201 if (kernel && !user_mode(regs)) { 203 202 if (add_mark)