Skip to content

Commit 4e06d4f

Browse files
author
Ingo Molnar
committed
Merge tag 'perf-urgent-for-mingo-4.10-20170104' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/urgent fixes and one improvement from Arnaldo Carvalho de Melo: Fixes: - Fix prev/next_prio formatting for deadline tasks in libtraceevent (Daniel Bristot de Oliveira) - Robustify reading of build-ids from /sys/kernel/note (Arnaldo Carvalho de Melo) - Fix building some sample/bpf in Alpine Linux 3.4 (Arnaldo Carvalho de Melo) - Fix 'make install-bin' to install libtraceevent plugins (Arnaldo Carvalho de Melo) - Fix 'perf record --switch-output' documentation and comment (Jiri Olsa) - Fix 'perf probe' for cross arch probing (Masami Hiramatsu) Improvement: - Show total scheduling time in 'perf sched timehist' (Namhyumg Kim) Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
2 parents 0c744ea + 8a937a2 commit 4e06d4f

File tree

11 files changed

+108
-47
lines changed

11 files changed

+108
-47
lines changed

samples/bpf/sock_example.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <unistd.h>
55
#include <string.h>
66
#include <errno.h>
7-
#include <net/ethernet.h>
7+
#include <linux/if_ether.h>
88
#include <net/if.h>
99
#include <linux/if_packet.h>
1010
#include <arpa/inet.h>

samples/bpf/trace_output_user.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <string.h>
1010
#include <fcntl.h>
1111
#include <poll.h>
12-
#include <sys/ioctl.h>
1312
#include <linux/perf_event.h>
1413
#include <linux/bpf.h>
1514
#include <errno.h>

tools/lib/subcmd/parse-options.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ static int get_value(struct parse_opt_ctx_t *p,
213213
else
214214
err = get_arg(p, opt, flags, (const char **)opt->value);
215215

216+
if (opt->set)
217+
*(bool *)opt->set = true;
218+
216219
/* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
217220
if (opt->flags & PARSE_OPT_NOEMPTY) {
218221
const char *val = *(const char **)opt->value;

tools/lib/subcmd/parse-options.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ struct option {
137137
{ .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
138138
.value = check_vtype(v, const char **), (a), .help = (h), \
139139
.flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
140+
#define OPT_STRING_OPTARG_SET(s, l, v, os, a, h, d) \
141+
{ .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
142+
.value = check_vtype(v, const char **), (a), .help = (h), \
143+
.flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \
144+
.set = check_vtype(os, bool *)}
140145
#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
141146
#define OPT_DATE(s, l, v, h) \
142147
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }

tools/lib/traceevent/plugin_sched_switch.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static int sched_switch_handler(struct trace_seq *s,
111111
trace_seq_printf(s, "%lld ", val);
112112

113113
if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0)
114-
trace_seq_printf(s, "[%lld] ", val);
114+
trace_seq_printf(s, "[%d] ", (int) val);
115115

116116
if (pevent_get_field_val(s, event, "prev_state", record, &val, 0) == 0)
117117
write_state(s, val);
@@ -129,7 +129,7 @@ static int sched_switch_handler(struct trace_seq *s,
129129
trace_seq_printf(s, "%lld", val);
130130

131131
if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0)
132-
trace_seq_printf(s, " [%lld]", val);
132+
trace_seq_printf(s, " [%d]", (int) val);
133133

134134
return 0;
135135
}

tools/perf/Documentation/perf-record.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,10 @@ that gets then processed, possibly via a perf script, to decide if that
430430
particular perf.data snapshot should be kept or not.
431431

432432
Implies --timestamp-filename, --no-buildid and --no-buildid-cache.
433+
The reason for the latter two is to reduce the data file switching
434+
overhead. You can still switch them on with:
435+
436+
--switch-output --no-no-buildid --no-no-buildid-cache
433437

434438
--dry-run::
435439
Parse options then exit. --dry-run can be used to detect errors in cmdline

tools/perf/Makefile.perf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,9 +704,9 @@ install-tests: all install-gtk
704704
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
705705
$(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
706706

707-
install-bin: install-tools install-tests
707+
install-bin: install-tools install-tests install-traceevent-plugins
708708

709-
install: install-bin try-install-man install-traceevent-plugins
709+
install: install-bin try-install-man
710710

711711
install-python_ext:
712712
$(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'

tools/perf/builtin-record.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,7 @@ static bool dry_run;
14051405
* perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
14061406
* using pipes, etc.
14071407
*/
1408-
struct option __record_options[] = {
1408+
static struct option __record_options[] = {
14091409
OPT_CALLBACK('e', "event", &record.evlist, "event",
14101410
"event selector. use 'perf list' to list available events",
14111411
parse_events_option),
@@ -1636,7 +1636,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
16361636
* overhead. Still generate buildid if they are required
16371637
* explicitly using
16381638
*
1639-
* perf record --signal-trigger --no-no-buildid \
1639+
* perf record --switch-output --no-no-buildid \
16401640
* --no-no-buildid-cache
16411641
*
16421642
* Following code equals to:

tools/perf/builtin-sched.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ struct perf_sched {
209209
u64 skipped_samples;
210210
const char *time_str;
211211
struct perf_time_interval ptime;
212+
struct perf_time_interval hist_time;
212213
};
213214

214215
/* per thread run time data */
@@ -2460,6 +2461,11 @@ static int timehist_sched_change_event(struct perf_tool *tool,
24602461
timehist_print_sample(sched, sample, &al, thread, t);
24612462

24622463
out:
2464+
if (sched->hist_time.start == 0 && t >= ptime->start)
2465+
sched->hist_time.start = t;
2466+
if (ptime->end == 0 || t <= ptime->end)
2467+
sched->hist_time.end = t;
2468+
24632469
if (tr) {
24642470
/* time of this sched_switch event becomes last time task seen */
24652471
tr->last_time = sample->time;
@@ -2624,6 +2630,7 @@ static void timehist_print_summary(struct perf_sched *sched,
26242630
struct thread *t;
26252631
struct thread_runtime *r;
26262632
int i;
2633+
u64 hist_time = sched->hist_time.end - sched->hist_time.start;
26272634

26282635
memset(&totals, 0, sizeof(totals));
26292636

@@ -2665,7 +2672,7 @@ static void timehist_print_summary(struct perf_sched *sched,
26652672
totals.sched_count += r->run_stats.n;
26662673
printf(" CPU %2d idle for ", i);
26672674
print_sched_time(r->total_run_time, 6);
2668-
printf(" msec\n");
2675+
printf(" msec (%6.2f%%)\n", 100.0 * r->total_run_time / hist_time);
26692676
} else
26702677
printf(" CPU %2d idle entire time window\n", i);
26712678
}
@@ -2701,12 +2708,16 @@ static void timehist_print_summary(struct perf_sched *sched,
27012708

27022709
printf("\n"
27032710
" Total number of unique tasks: %" PRIu64 "\n"
2704-
"Total number of context switches: %" PRIu64 "\n"
2705-
" Total run time (msec): ",
2711+
"Total number of context switches: %" PRIu64 "\n",
27062712
totals.task_count, totals.sched_count);
27072713

2714+
printf(" Total run time (msec): ");
27082715
print_sched_time(totals.total_run_time, 2);
27092716
printf("\n");
2717+
2718+
printf(" Total scheduling time (msec): ");
2719+
print_sched_time(hist_time, 2);
2720+
printf(" (x %d)\n", sched->max_cpu);
27102721
}
27112722

27122723
typedef int (*sched_handler)(struct perf_tool *tool,

tools/perf/util/probe-event.c

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static struct map *kernel_get_module_map(const char *module)
163163

164164
/* A file path -- this is an offline module */
165165
if (module && strchr(module, '/'))
166-
return machine__findnew_module_map(host_machine, 0, module);
166+
return dso__new_map(module);
167167

168168
if (!module)
169169
module = "kernel";
@@ -173,6 +173,7 @@ static struct map *kernel_get_module_map(const char *module)
173173
if (strncmp(pos->dso->short_name + 1, module,
174174
pos->dso->short_name_len - 2) == 0 &&
175175
module[pos->dso->short_name_len - 2] == '\0') {
176+
map__get(pos);
176177
return pos;
177178
}
178179
}
@@ -188,15 +189,6 @@ struct map *get_target_map(const char *target, bool user)
188189
return kernel_get_module_map(target);
189190
}
190191

191-
static void put_target_map(struct map *map, bool user)
192-
{
193-
if (map && user) {
194-
/* Only the user map needs to be released */
195-
map__put(map);
196-
}
197-
}
198-
199-
200192
static int convert_exec_to_group(const char *exec, char **result)
201193
{
202194
char *ptr1, *ptr2, *exec_copy;
@@ -267,21 +259,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
267259
return true;
268260
}
269261

270-
/*
271-
* NOTE:
272-
* '.gnu.linkonce.this_module' section of kernel module elf directly
273-
* maps to 'struct module' from linux/module.h. This section contains
274-
* actual module name which will be used by kernel after loading it.
275-
* But, we cannot use 'struct module' here since linux/module.h is not
276-
* exposed to user-space. Offset of 'name' has remained same from long
277-
* time, so hardcoding it here.
278-
*/
279-
#ifdef __LP64__
280-
#define MOD_NAME_OFFSET 24
281-
#else
282-
#define MOD_NAME_OFFSET 12
283-
#endif
284-
285262
/*
286263
* @module can be module name of module file path. In case of path,
287264
* inspect elf and find out what is actual module name.
@@ -296,6 +273,7 @@ static char *find_module_name(const char *module)
296273
Elf_Data *data;
297274
Elf_Scn *sec;
298275
char *mod_name = NULL;
276+
int name_offset;
299277

300278
fd = open(module, O_RDONLY);
301279
if (fd < 0)
@@ -317,7 +295,21 @@ static char *find_module_name(const char *module)
317295
if (!data || !data->d_buf)
318296
goto ret_err;
319297

320-
mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET);
298+
/*
299+
* NOTE:
300+
* '.gnu.linkonce.this_module' section of kernel module elf directly
301+
* maps to 'struct module' from linux/module.h. This section contains
302+
* actual module name which will be used by kernel after loading it.
303+
* But, we cannot use 'struct module' here since linux/module.h is not
304+
* exposed to user-space. Offset of 'name' has remained same from long
305+
* time, so hardcoding it here.
306+
*/
307+
if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
308+
name_offset = 12;
309+
else /* expect ELFCLASS64 by default */
310+
name_offset = 24;
311+
312+
mod_name = strdup((char *)data->d_buf + name_offset);
321313

322314
ret_err:
323315
elf_end(elf);
@@ -412,7 +404,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
412404
}
413405

414406
out:
415-
put_target_map(map, uprobes);
407+
map__put(map);
416408
return ret;
417409

418410
}
@@ -618,6 +610,51 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
618610
return ret ? : -ENOENT;
619611
}
620612

613+
/*
614+
* Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions
615+
* and generate new symbols with suffixes such as .constprop.N or .isra.N
616+
* etc. Since those symbols are not recorded in DWARF, we have to find
617+
* correct generated symbols from offline ELF binary.
618+
* For online kernel or uprobes we don't need this because those are
619+
* rebased on _text, or already a section relative address.
620+
*/
621+
static int
622+
post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
623+
int ntevs, const char *pathname)
624+
{
625+
struct symbol *sym;
626+
struct map *map;
627+
unsigned long stext = 0;
628+
u64 addr;
629+
int i;
630+
631+
/* Prepare a map for offline binary */
632+
map = dso__new_map(pathname);
633+
if (!map || get_text_start_address(pathname, &stext) < 0) {
634+
pr_warning("Failed to get ELF symbols for %s\n", pathname);
635+
return -EINVAL;
636+
}
637+
638+
for (i = 0; i < ntevs; i++) {
639+
addr = tevs[i].point.address + tevs[i].point.offset - stext;
640+
sym = map__find_symbol(map, addr);
641+
if (!sym)
642+
continue;
643+
if (!strcmp(sym->name, tevs[i].point.symbol))
644+
continue;
645+
/* If we have no realname, use symbol for it */
646+
if (!tevs[i].point.realname)
647+
tevs[i].point.realname = tevs[i].point.symbol;
648+
else
649+
free(tevs[i].point.symbol);
650+
tevs[i].point.symbol = strdup(sym->name);
651+
tevs[i].point.offset = addr - sym->start;
652+
}
653+
map__put(map);
654+
655+
return 0;
656+
}
657+
621658
static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
622659
int ntevs, const char *exec)
623660
{
@@ -679,7 +716,8 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
679716

680717
/* Skip post process if the target is an offline kernel */
681718
if (symbol_conf.ignore_vmlinux_buildid)
682-
return 0;
719+
return post_process_offline_probe_trace_events(tevs, ntevs,
720+
symbol_conf.vmlinux_name);
683721

684722
reloc_sym = kernel_get_ref_reloc_sym();
685723
if (!reloc_sym) {
@@ -2869,7 +2907,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
28692907
}
28702908

28712909
out:
2872-
put_target_map(map, pev->uprobes);
2910+
map__put(map);
28732911
free(syms);
28742912
return ret;
28752913

@@ -3362,10 +3400,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
33623400
return ret;
33633401

33643402
/* Get a symbol map */
3365-
if (user)
3366-
map = dso__new_map(target);
3367-
else
3368-
map = kernel_get_module_map(target);
3403+
map = get_target_map(target, user);
33693404
if (!map) {
33703405
pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
33713406
return -EINVAL;
@@ -3397,9 +3432,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
33973432
}
33983433

33993434
end:
3400-
if (user) {
3401-
map__put(map);
3402-
}
3435+
map__put(map);
34033436
exit_probe_symbol_maps();
34043437

34053438
return ret;

tools/perf/util/symbol-elf.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,12 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
537537
break;
538538
} else {
539539
int n = namesz + descsz;
540+
541+
if (n > (int)sizeof(bf)) {
542+
n = sizeof(bf);
543+
pr_debug("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n",
544+
__func__, filename, nhdr.n_namesz, nhdr.n_descsz);
545+
}
540546
if (read(fd, bf, n) != n)
541547
break;
542548
}

0 commit comments

Comments
 (0)