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

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull perf fixes from Ingo Molnar:
"Various fixlets:

On the kernel side:

- fix a race
- fix a bug in the handling of the perf ring-buffer data page

On the tooling side:

- fix the handling of certain corrupted perf.data files
- fix a bug in 'perf probe'
- fix a bug in 'perf record + perf sched'
- fix a bug in 'make install'
- fix a bug in libaudit feature-detection on certain distros"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf session: Fix infinite loop on invalid perf.data file
perf tools: Fix installation of libexec components
perf probe: Fix to find line information for probe list
perf tools: Fix libaudit test
perf stat: Set child_pid after perf_evlist__prepare_workload()
perf tools: Add default handler for mmap2 events
perf/x86: Clean up cap_user_time* setting
perf: Fix perf_pmu_migrate_context

+107 -36
+3 -8
arch/x86/kernel/cpu/perf_event.c
··· 1888 1888 userpg->cap_user_rdpmc = x86_pmu.attr_rdpmc; 1889 1889 userpg->pmc_width = x86_pmu.cntval_bits; 1890 1890 1891 - if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) 1892 - return; 1893 - 1894 - if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) 1891 + if (!sched_clock_stable) 1895 1892 return; 1896 1893 1897 1894 userpg->cap_user_time = 1; ··· 1896 1899 userpg->time_shift = CYC2NS_SCALE_FACTOR; 1897 1900 userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; 1898 1901 1899 - if (sched_clock_stable && !check_tsc_disabled()) { 1900 - userpg->cap_user_time_zero = 1; 1901 - userpg->time_zero = this_cpu_read(cyc2ns_offset); 1902 - } 1902 + userpg->cap_user_time_zero = 1; 1903 + userpg->time_zero = this_cpu_read(cyc2ns_offset); 1903 1904 } 1904 1905 1905 1906 /*
+23 -1
include/linux/perf_event.h
··· 294 294 */ 295 295 struct perf_event { 296 296 #ifdef CONFIG_PERF_EVENTS 297 - struct list_head group_entry; 297 + /* 298 + * entry onto perf_event_context::event_list; 299 + * modifications require ctx->lock 300 + * RCU safe iterations. 301 + */ 298 302 struct list_head event_entry; 303 + 304 + /* 305 + * XXX: group_entry and sibling_list should be mutually exclusive; 306 + * either you're a sibling on a group, or you're the group leader. 307 + * Rework the code to always use the same list element. 308 + * 309 + * Locked for modification by both ctx->mutex and ctx->lock; holding 310 + * either sufficies for read. 311 + */ 312 + struct list_head group_entry; 299 313 struct list_head sibling_list; 314 + 315 + /* 316 + * We need storage to track the entries in perf_pmu_migrate_context; we 317 + * cannot use the event_entry because of RCU and we want to keep the 318 + * group in tact which avoids us using the other two entries. 319 + */ 320 + struct list_head migrate_entry; 321 + 300 322 struct hlist_node hlist_entry; 301 323 int nr_siblings; 302 324 int group_flags;
+3 -3
kernel/events/core.c
··· 7234 7234 perf_remove_from_context(event); 7235 7235 unaccount_event_cpu(event, src_cpu); 7236 7236 put_ctx(src_ctx); 7237 - list_add(&event->event_entry, &events); 7237 + list_add(&event->migrate_entry, &events); 7238 7238 } 7239 7239 mutex_unlock(&src_ctx->mutex); 7240 7240 7241 7241 synchronize_rcu(); 7242 7242 7243 7243 mutex_lock(&dst_ctx->mutex); 7244 - list_for_each_entry_safe(event, tmp, &events, event_entry) { 7245 - list_del(&event->event_entry); 7244 + list_for_each_entry_safe(event, tmp, &events, migrate_entry) { 7245 + list_del(&event->migrate_entry); 7246 7246 if (event->state >= PERF_EVENT_STATE_OFF) 7247 7247 event->state = PERF_EVENT_STATE_INACTIVE; 7248 7248 account_event_cpu(event, dst_cpu);
+1
tools/perf/Makefile
··· 770 770 install-bin: all 771 771 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' 772 772 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)' 773 + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 773 774 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 774 775 ifndef NO_LIBPERL 775 776 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
+1
tools/perf/builtin-stat.c
··· 457 457 perror("failed to prepare workload"); 458 458 return -1; 459 459 } 460 + child_pid = evsel_list->workload.pid; 460 461 } 461 462 462 463 if (group)
+1 -1
tools/perf/config/feature-tests.mak
··· 219 219 220 220 int main(void) 221 221 { 222 - printf(\"error message: %s\n\", audit_errno_to_name(0)); 222 + printf(\"error message: %s\", audit_errno_to_name(0)); 223 223 return audit_open(); 224 224 } 225 225 endef
+22 -5
tools/perf/util/dwarf-aux.c
··· 426 426 * @die_mem: a buffer for result DIE 427 427 * 428 428 * Search a non-inlined function DIE which includes @addr. Stores the 429 - * DIE to @die_mem and returns it if found. Returns NULl if failed. 429 + * DIE to @die_mem and returns it if found. Returns NULL if failed. 430 430 */ 431 431 Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, 432 432 Dwarf_Die *die_mem) ··· 454 454 } 455 455 456 456 /** 457 - * die_find_inlinefunc - Search an inlined function at given address 458 - * @cu_die: a CU DIE which including @addr 457 + * die_find_top_inlinefunc - Search the top inlined function at given address 458 + * @sp_die: a subprogram DIE which including @addr 459 459 * @addr: target address 460 460 * @die_mem: a buffer for result DIE 461 461 * 462 462 * Search an inlined function DIE which includes @addr. Stores the 463 - * DIE to @die_mem and returns it if found. Returns NULl if failed. 463 + * DIE to @die_mem and returns it if found. Returns NULL if failed. 464 + * Even if several inlined functions are expanded recursively, this 465 + * doesn't trace it down, and returns the topmost one. 466 + */ 467 + Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 468 + Dwarf_Die *die_mem) 469 + { 470 + return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); 471 + } 472 + 473 + /** 474 + * die_find_inlinefunc - Search an inlined function at given address 475 + * @sp_die: a subprogram DIE which including @addr 476 + * @addr: target address 477 + * @die_mem: a buffer for result DIE 478 + * 479 + * Search an inlined function DIE which includes @addr. Stores the 480 + * DIE to @die_mem and returns it if found. Returns NULL if failed. 464 481 * If several inlined functions are expanded recursively, this trace 465 - * it and returns deepest one. 482 + * it down and returns deepest one. 466 483 */ 467 484 Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 468 485 Dwarf_Die *die_mem)
+5 -1
tools/perf/util/dwarf-aux.h
··· 79 79 extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, 80 80 Dwarf_Die *die_mem); 81 81 82 - /* Search an inlined function including given address */ 82 + /* Search the top inlined function including given address */ 83 + extern Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 84 + Dwarf_Die *die_mem); 85 + 86 + /* Search the deepest inlined function including given address */ 83 87 extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 84 88 Dwarf_Die *die_mem); 85 89
+12
tools/perf/util/header.c
··· 2768 2768 if (perf_file_header__read(&f_header, header, fd) < 0) 2769 2769 return -EINVAL; 2770 2770 2771 + /* 2772 + * Sanity check that perf.data was written cleanly; data size is 2773 + * initialized to 0 and updated only if the on_exit function is run. 2774 + * If data size is still 0 then the file contains only partial 2775 + * information. Just warn user and process it as much as it can. 2776 + */ 2777 + if (f_header.data.size == 0) { 2778 + pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n" 2779 + "Was the 'perf record' command properly terminated?\n", 2780 + session->filename); 2781 + } 2782 + 2771 2783 nr_attrs = f_header.attrs.size / f_header.attr_size; 2772 2784 lseek(fd, f_header.attrs.offset, SEEK_SET); 2773 2785
+33 -16
tools/perf/util/probe-finder.c
··· 1327 1327 struct perf_probe_point *ppt) 1328 1328 { 1329 1329 Dwarf_Die cudie, spdie, indie; 1330 - Dwarf_Addr _addr, baseaddr; 1331 - const char *fname = NULL, *func = NULL, *tmp; 1330 + Dwarf_Addr _addr = 0, baseaddr = 0; 1331 + const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1332 1332 int baseline = 0, lineno = 0, ret = 0; 1333 1333 1334 1334 /* Adjust address with bias */ ··· 1349 1349 /* Find a corresponding function (name, baseline and baseaddr) */ 1350 1350 if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) { 1351 1351 /* Get function entry information */ 1352 - tmp = dwarf_diename(&spdie); 1353 - if (!tmp || 1352 + func = basefunc = dwarf_diename(&spdie); 1353 + if (!func || 1354 1354 dwarf_entrypc(&spdie, &baseaddr) != 0 || 1355 - dwarf_decl_line(&spdie, &baseline) != 0) 1355 + dwarf_decl_line(&spdie, &baseline) != 0) { 1356 + lineno = 0; 1356 1357 goto post; 1357 - func = tmp; 1358 + } 1358 1359 1359 - if (addr == (unsigned long)baseaddr) 1360 + if (addr == (unsigned long)baseaddr) { 1360 1361 /* Function entry - Relative line number is 0 */ 1361 1362 lineno = baseline; 1362 - else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, 1363 - &indie)) { 1363 + fname = dwarf_decl_file(&spdie); 1364 + goto post; 1365 + } 1366 + 1367 + /* Track down the inline functions step by step */ 1368 + while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr, 1369 + &indie)) { 1370 + /* There is an inline function */ 1364 1371 if (dwarf_entrypc(&indie, &_addr) == 0 && 1365 - _addr == addr) 1372 + _addr == addr) { 1366 1373 /* 1367 1374 * addr is at an inline function entry. 1368 1375 * In this case, lineno should be the call-site 1369 - * line number. 1376 + * line number. (overwrite lineinfo) 1370 1377 */ 1371 1378 lineno = die_get_call_lineno(&indie); 1372 - else { 1379 + fname = die_get_call_file(&indie); 1380 + break; 1381 + } else { 1373 1382 /* 1374 1383 * addr is in an inline function body. 1375 1384 * Since lineno points one of the lines ··· 1386 1377 * be the entry line of the inline function. 1387 1378 */ 1388 1379 tmp = dwarf_diename(&indie); 1389 - if (tmp && 1390 - dwarf_decl_line(&spdie, &baseline) == 0) 1391 - func = tmp; 1380 + if (!tmp || 1381 + dwarf_decl_line(&indie, &baseline) != 0) 1382 + break; 1383 + func = tmp; 1384 + spdie = indie; 1392 1385 } 1393 1386 } 1387 + /* Verify the lineno and baseline are in a same file */ 1388 + tmp = dwarf_decl_file(&spdie); 1389 + if (!tmp || strcmp(tmp, fname) != 0) 1390 + lineno = 0; 1394 1391 } 1395 1392 1396 1393 post: 1397 1394 /* Make a relative line number or an offset */ 1398 1395 if (lineno) 1399 1396 ppt->line = lineno - baseline; 1400 - else if (func) 1397 + else if (basefunc) { 1401 1398 ppt->offset = addr - (unsigned long)baseaddr; 1399 + func = basefunc; 1400 + } 1402 1401 1403 1402 /* Duplicate strings */ 1404 1403 if (func) {
+3 -1
tools/perf/util/session.c
··· 256 256 tool->sample = process_event_sample_stub; 257 257 if (tool->mmap == NULL) 258 258 tool->mmap = process_event_stub; 259 + if (tool->mmap2 == NULL) 260 + tool->mmap2 = process_event_stub; 259 261 if (tool->comm == NULL) 260 262 tool->comm = process_event_stub; 261 263 if (tool->fork == NULL) ··· 1312 1310 file_offset = page_offset; 1313 1311 head = data_offset - page_offset; 1314 1312 1315 - if (data_offset + data_size < file_size) 1313 + if (data_size && (data_offset + data_size < file_size)) 1316 1314 file_size = data_offset + data_size; 1317 1315 1318 1316 progress_next = file_size / 16;