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

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
"Misc kernel and tooling fixes"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
tools lib traceevent: Fix conversion of pointer to integer of different size
perf/trace: Properly use u64 to hold event_id
perf: Remove fragile swevent hlist optimization
ftrace, perf: Avoid infinite event generation loop
tools lib traceevent: Fix use of multiple options in processing field
perf header: Fix possible memory leaks in process_group_desc()
perf header: Fix bogus group name
perf tools: Tag thread comm as overriden

+76 -20
+11
arch/x86/include/asm/trace/irq_vectors.h
··· 72 72 DEFINE_IRQ_VECTOR_EVENT(irq_work); 73 73 74 74 /* 75 + * We must dis-allow sampling irq_work_exit() because perf event sampling 76 + * itself can cause irq_work, which would lead to an infinite loop; 77 + * 78 + * 1) irq_work_exit happens 79 + * 2) generates perf sample 80 + * 3) generates irq_work 81 + * 4) goto 1 82 + */ 83 + TRACE_EVENT_PERF_PERM(irq_work_exit, is_sampling_event(p_event) ? -EPERM : 0); 84 + 85 + /* 75 86 * call_function - called when entering/exiting a call function interrupt 76 87 * vector handler 77 88 */
+16
include/linux/ftrace_event.h
··· 248 248 #ifdef CONFIG_PERF_EVENTS 249 249 int perf_refcount; 250 250 struct hlist_head __percpu *perf_events; 251 + 252 + int (*perf_perm)(struct ftrace_event_call *, 253 + struct perf_event *); 251 254 #endif 252 255 }; 253 256 ··· 319 316 return 0; \ 320 317 } \ 321 318 early_initcall(trace_init_flags_##name); 319 + 320 + #define __TRACE_EVENT_PERF_PERM(name, expr...) \ 321 + static int perf_perm_##name(struct ftrace_event_call *tp_event, \ 322 + struct perf_event *p_event) \ 323 + { \ 324 + return ({ expr; }); \ 325 + } \ 326 + static int __init trace_init_perf_perm_##name(void) \ 327 + { \ 328 + event_##name.perf_perm = &perf_perm_##name; \ 329 + return 0; \ 330 + } \ 331 + early_initcall(trace_init_perf_perm_##name); 322 332 323 333 #define PERF_MAX_TRACE_SIZE 2048 324 334
+4
include/linux/tracepoint.h
··· 267 267 268 268 #define TRACE_EVENT_FLAGS(event, flag) 269 269 270 + #define TRACE_EVENT_PERF_PERM(event, expr...) 271 + 270 272 #endif /* DECLARE_TRACE */ 271 273 272 274 #ifndef TRACE_EVENT ··· 400 398 PARAMS(args), PARAMS(cond)) 401 399 402 400 #define TRACE_EVENT_FLAGS(event, flag) 401 + 402 + #define TRACE_EVENT_PERF_PERM(event, expr...) 403 403 404 404 #endif /* ifdef TRACE_EVENT (see note above) */
+7
include/trace/ftrace.h
··· 90 90 #define TRACE_EVENT_FLAGS(name, value) \ 91 91 __TRACE_EVENT_FLAGS(name, value) 92 92 93 + #undef TRACE_EVENT_PERF_PERM 94 + #define TRACE_EVENT_PERF_PERM(name, expr...) \ 95 + __TRACE_EVENT_PERF_PERM(name, expr) 96 + 93 97 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 94 98 95 99 ··· 143 139 144 140 #undef TRACE_EVENT_FLAGS 145 141 #define TRACE_EVENT_FLAGS(event, flag) 142 + 143 + #undef TRACE_EVENT_PERF_PERM 144 + #define TRACE_EVENT_PERF_PERM(event, expr...) 146 145 147 146 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 148 147
-8
kernel/events/core.c
··· 5680 5680 { 5681 5681 int cpu; 5682 5682 5683 - if (event->cpu != -1) { 5684 - swevent_hlist_put_cpu(event, event->cpu); 5685 - return; 5686 - } 5687 - 5688 5683 for_each_possible_cpu(cpu) 5689 5684 swevent_hlist_put_cpu(event, cpu); 5690 5685 } ··· 5712 5717 { 5713 5718 int err; 5714 5719 int cpu, failed_cpu; 5715 - 5716 - if (event->cpu != -1) 5717 - return swevent_hlist_get_cpu(event, event->cpu); 5718 5720 5719 5721 get_online_cpus(); 5720 5722 for_each_possible_cpu(cpu) {
+7 -1
kernel/trace/trace_event_perf.c
··· 24 24 static int perf_trace_event_perm(struct ftrace_event_call *tp_event, 25 25 struct perf_event *p_event) 26 26 { 27 + if (tp_event->perf_perm) { 28 + int ret = tp_event->perf_perm(tp_event, p_event); 29 + if (ret) 30 + return ret; 31 + } 32 + 27 33 /* The ftrace function trace is allowed only for root. */ 28 34 if (ftrace_event_is_function(tp_event) && 29 35 perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN)) ··· 179 173 int perf_trace_init(struct perf_event *p_event) 180 174 { 181 175 struct ftrace_event_call *tp_event; 182 - int event_id = p_event->attr.config; 176 + u64 event_id = p_event->attr.config; 183 177 int ret = -EINVAL; 184 178 185 179 mutex_lock(&event_mutex);
+22 -3
tools/lib/traceevent/event-parse.c
··· 1606 1606 static enum event_type 1607 1607 process_op(struct event_format *event, struct print_arg *arg, char **tok); 1608 1608 1609 + /* 1610 + * For __print_symbolic() and __print_flags, we need to completely 1611 + * evaluate the first argument, which defines what to print next. 1612 + */ 1613 + static enum event_type 1614 + process_field_arg(struct event_format *event, struct print_arg *arg, char **tok) 1615 + { 1616 + enum event_type type; 1617 + 1618 + type = process_arg(event, arg, tok); 1619 + 1620 + while (type == EVENT_OP) { 1621 + type = process_op(event, arg, tok); 1622 + } 1623 + 1624 + return type; 1625 + } 1626 + 1609 1627 static enum event_type 1610 1628 process_cond(struct event_format *event, struct print_arg *top, char **tok) 1611 1629 { ··· 2389 2371 goto out_free; 2390 2372 } 2391 2373 2392 - type = process_arg(event, field, &token); 2374 + type = process_field_arg(event, field, &token); 2393 2375 2394 2376 /* Handle operations in the first argument */ 2395 2377 while (type == EVENT_OP) ··· 2442 2424 goto out_free; 2443 2425 } 2444 2426 2445 - type = process_arg(event, field, &token); 2427 + type = process_field_arg(event, field, &token); 2428 + 2446 2429 if (test_type_token(type, token, EVENT_DELIM, ",")) 2447 2430 goto out_free_field; 2448 2431 ··· 3465 3446 * is in the bottom half of the 32 bit field. 3466 3447 */ 3467 3448 offset &= 0xffff; 3468 - val = (unsigned long long)(data + offset); 3449 + val = (unsigned long long)((unsigned long)data + offset); 3469 3450 break; 3470 3451 default: /* not sure what to do there */ 3471 3452 return 0;
+4 -2
tools/perf/util/header.c
··· 2078 2078 if (evsel->idx == (int) desc[i].leader_idx) { 2079 2079 evsel->leader = evsel; 2080 2080 /* {anon_group} is a dummy name */ 2081 - if (strcmp(desc[i].name, "{anon_group}")) 2081 + if (strcmp(desc[i].name, "{anon_group}")) { 2082 2082 evsel->group_name = desc[i].name; 2083 + desc[i].name = NULL; 2084 + } 2083 2085 evsel->nr_members = desc[i].nr_members; 2084 2086 2085 2087 if (i >= nr_groups || nr > 0) { ··· 2107 2105 2108 2106 ret = 0; 2109 2107 out_free: 2110 - while ((int) --i >= 0) 2108 + for (i = 0; i < nr_groups; i++) 2111 2109 free(desc[i].name); 2112 2110 free(desc); 2113 2111
+5 -6
tools/perf/util/thread.c
··· 70 70 /* Override latest entry if it had no specific time coverage */ 71 71 if (!curr->start) { 72 72 comm__override(curr, str, timestamp); 73 - return 0; 73 + } else { 74 + new = comm__new(str, timestamp); 75 + if (!new) 76 + return -ENOMEM; 77 + list_add(&new->list, &thread->comm_list); 74 78 } 75 79 76 - new = comm__new(str, timestamp); 77 - if (!new) 78 - return -ENOMEM; 79 - 80 - list_add(&new->list, &thread->comm_list); 81 80 thread->comm_set = true; 82 81 83 82 return 0;