Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
User visible changes:
- Mark events as (x86 only) in help output for 'perf kvm stat live" (Alexander Yarygin)
- Provide a better explanation when mmap fails in 'trace' (Arnaldo Carvalho de Melo)
- Add --buildid-dir option to set cache directory, i.e. use:
$ perf --buildid-dir /path/to/dir tool --tool-options
(Jiri Olsa)
- Fix memcpy/memset 'perf bench' output (Rabin Vicent)
- Fix 'perf test' attr tests size values to cope with machine state on
interrupt ABI changes (Jiri Olsa)
- Fixup callchain type parameter handling error message (Kan Liang)
Infrastructure changes and cleanups:
- calloc/xcalloc: Fix argument order (Arjun Sreedharan)
- Move filename__read_int from tools/perf/ to tools/lib, add sysctl__read_int
there and use it in place of ad-hoc copies (Arnaldo Carvalho de Melo)
- Use single strcmp call instead of two (Jiri Olsa)
- Remove extra debugdir variables in 'perf buildid-cache' (Jiri Olsa)
- Fix -a segfault related to kcore handling in 'perf buildid-cache' (Jiri Olsa)
- Move cpumode resolve code to add_callchain_ip (Kan Liang)
- Merge memset into memcpy 'perf bench' (Rabin Vincent)
- Change print format from %lu to %PRIu64 in the hists browser (Tom Huynh)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -410,21 +410,18 @@ int perf_session__cache_build_ids(struct perf_session *session)
|
||||
{
|
||||
struct rb_node *nd;
|
||||
int ret;
|
||||
char debugdir[PATH_MAX];
|
||||
|
||||
if (no_buildid_cache)
|
||||
return 0;
|
||||
|
||||
snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
|
||||
|
||||
if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
|
||||
if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST)
|
||||
return -1;
|
||||
|
||||
ret = machine__cache_build_ids(&session->machines.host, debugdir);
|
||||
ret = machine__cache_build_ids(&session->machines.host, buildid_dir);
|
||||
|
||||
for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
|
||||
struct machine *pos = rb_entry(nd, struct machine, rb_node);
|
||||
ret |= machine__cache_build_ids(pos, debugdir);
|
||||
ret |= machine__cache_build_ids(pos, buildid_dir);
|
||||
}
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ int parse_callchain_record_opt(const char *arg)
|
||||
ret = 0;
|
||||
} else
|
||||
pr_err("callchain: No more arguments "
|
||||
"needed for -g fp\n");
|
||||
"needed for --call-graph fp\n");
|
||||
break;
|
||||
|
||||
#ifdef HAVE_DWARF_UNWIND_SUPPORT
|
||||
|
||||
@@ -522,7 +522,7 @@ static int buildid_dir_command_config(const char *var, const char *value,
|
||||
const char *v;
|
||||
|
||||
/* same dir for all commands */
|
||||
if (!prefixcmp(var, "buildid.") && !strcmp(var + 8, "dir")) {
|
||||
if (!strcmp(var, "buildid.dir")) {
|
||||
v = perf_config_dirname(var, value);
|
||||
if (!v)
|
||||
return -1;
|
||||
@@ -539,12 +539,14 @@ static void check_buildid_dir_config(void)
|
||||
perf_config(buildid_dir_command_config, &c);
|
||||
}
|
||||
|
||||
void set_buildid_dir(void)
|
||||
void set_buildid_dir(const char *dir)
|
||||
{
|
||||
buildid_dir[0] = '\0';
|
||||
if (dir)
|
||||
scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir);
|
||||
|
||||
/* try config file */
|
||||
check_buildid_dir_config();
|
||||
if (buildid_dir[0] == '\0')
|
||||
check_buildid_dir_config();
|
||||
|
||||
/* default to $HOME/.debug */
|
||||
if (buildid_dir[0] == '\0') {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#include "util.h"
|
||||
#include <api/fs/debugfs.h>
|
||||
#include <api/fs/fs.h>
|
||||
#include <poll.h>
|
||||
#include "cpumap.h"
|
||||
#include "thread_map.h"
|
||||
@@ -1483,6 +1484,28 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
|
||||
{
|
||||
char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
|
||||
int value;
|
||||
|
||||
switch (err) {
|
||||
case EPERM:
|
||||
sysctl__read_int("kernel/perf_event_mlock_kb", &value);
|
||||
scnprintf(buf, size, "Error:\t%s.\n"
|
||||
"Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
|
||||
"Hint:\tTried using %zd kB.\n"
|
||||
"Hint:\tTry using a bigger -m/--mmap-pages value.",
|
||||
emsg, value, evlist->mmap_len / 1024);
|
||||
break;
|
||||
default:
|
||||
scnprintf(buf, size, "%s", emsg);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void perf_evlist__to_front(struct perf_evlist *evlist,
|
||||
struct perf_evsel *move_evsel)
|
||||
{
|
||||
|
||||
@@ -185,6 +185,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
|
||||
|
||||
int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size);
|
||||
int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
|
||||
int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
|
||||
|
||||
static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
|
||||
{
|
||||
|
||||
+35
-37
@@ -1385,19 +1385,46 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
|
||||
static int add_callchain_ip(struct thread *thread,
|
||||
struct symbol **parent,
|
||||
struct addr_location *root_al,
|
||||
int cpumode,
|
||||
bool branch_history,
|
||||
u64 ip)
|
||||
{
|
||||
struct addr_location al;
|
||||
|
||||
al.filtered = 0;
|
||||
al.sym = NULL;
|
||||
if (cpumode == -1)
|
||||
if (branch_history)
|
||||
thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
|
||||
ip, &al);
|
||||
else
|
||||
else {
|
||||
u8 cpumode = PERF_RECORD_MISC_USER;
|
||||
|
||||
if (ip >= PERF_CONTEXT_MAX) {
|
||||
switch (ip) {
|
||||
case PERF_CONTEXT_HV:
|
||||
cpumode = PERF_RECORD_MISC_HYPERVISOR;
|
||||
break;
|
||||
case PERF_CONTEXT_KERNEL:
|
||||
cpumode = PERF_RECORD_MISC_KERNEL;
|
||||
break;
|
||||
case PERF_CONTEXT_USER:
|
||||
cpumode = PERF_RECORD_MISC_USER;
|
||||
break;
|
||||
default:
|
||||
pr_debug("invalid callchain context: "
|
||||
"%"PRId64"\n", (s64) ip);
|
||||
/*
|
||||
* It seems the callchain is corrupted.
|
||||
* Discard all.
|
||||
*/
|
||||
callchain_cursor_reset(&callchain_cursor);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
|
||||
ip, &al);
|
||||
}
|
||||
|
||||
if (al.sym != NULL) {
|
||||
if (sort__has_parent && !*parent &&
|
||||
symbol__match_regex(al.sym, &parent_regex))
|
||||
@@ -1480,11 +1507,8 @@ static int thread__resolve_callchain_sample(struct thread *thread,
|
||||
struct addr_location *root_al,
|
||||
int max_stack)
|
||||
{
|
||||
u8 cpumode = PERF_RECORD_MISC_USER;
|
||||
int chain_nr = min(max_stack, (int)chain->nr);
|
||||
int i;
|
||||
int j;
|
||||
int err;
|
||||
int i, j, err;
|
||||
int skip_idx = -1;
|
||||
int first_call = 0;
|
||||
|
||||
@@ -1542,10 +1566,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
err = add_callchain_ip(thread, parent, root_al,
|
||||
-1, be[i].to);
|
||||
true, be[i].to);
|
||||
if (!err)
|
||||
err = add_callchain_ip(thread, parent, root_al,
|
||||
-1, be[i].from);
|
||||
true, be[i].from);
|
||||
if (err == -EINVAL)
|
||||
break;
|
||||
if (err)
|
||||
@@ -1574,36 +1598,10 @@ check_calls:
|
||||
#endif
|
||||
ip = chain->ips[j];
|
||||
|
||||
if (ip >= PERF_CONTEXT_MAX) {
|
||||
switch (ip) {
|
||||
case PERF_CONTEXT_HV:
|
||||
cpumode = PERF_RECORD_MISC_HYPERVISOR;
|
||||
break;
|
||||
case PERF_CONTEXT_KERNEL:
|
||||
cpumode = PERF_RECORD_MISC_KERNEL;
|
||||
break;
|
||||
case PERF_CONTEXT_USER:
|
||||
cpumode = PERF_RECORD_MISC_USER;
|
||||
break;
|
||||
default:
|
||||
pr_debug("invalid callchain context: "
|
||||
"%"PRId64"\n", (s64) ip);
|
||||
/*
|
||||
* It seems the callchain is corrupted.
|
||||
* Discard all.
|
||||
*/
|
||||
callchain_cursor_reset(&callchain_cursor);
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
err = add_callchain_ip(thread, parent, root_al, false, ip);
|
||||
|
||||
err = add_callchain_ip(thread, parent, root_al,
|
||||
cpumode, ip);
|
||||
if (err == -EINVAL)
|
||||
break;
|
||||
if (err)
|
||||
return err;
|
||||
return (err < 0) ? err : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -137,16 +137,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
|
||||
|
||||
static int get_max_rate(unsigned int *rate)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
const char *procfs = procfs__mountpoint();
|
||||
|
||||
if (!procfs)
|
||||
return -1;
|
||||
|
||||
snprintf(path, PATH_MAX,
|
||||
"%s/sys/kernel/perf_event_max_sample_rate", procfs);
|
||||
|
||||
return filename__read_int(path, (int *) rate);
|
||||
return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate);
|
||||
}
|
||||
|
||||
static int record_opts__config_freq(struct record_opts *opts)
|
||||
|
||||
+1
-25
@@ -442,23 +442,6 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
|
||||
return (unsigned long) -1;
|
||||
}
|
||||
|
||||
int filename__read_int(const char *filename, int *value)
|
||||
{
|
||||
char line[64];
|
||||
int fd = open(filename, O_RDONLY), err = -1;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (read(fd, line, sizeof(line)) > 0) {
|
||||
*value = atoi(line);
|
||||
err = 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return err;
|
||||
}
|
||||
|
||||
int filename__read_str(const char *filename, char **buf, size_t *sizep)
|
||||
{
|
||||
size_t size = 0, alloc_size = 0;
|
||||
@@ -523,16 +506,9 @@ const char *get_filename_for_perf_kvm(void)
|
||||
|
||||
int perf_event_paranoid(void)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
const char *procfs = procfs__mountpoint();
|
||||
int value;
|
||||
|
||||
if (!procfs)
|
||||
return INT_MAX;
|
||||
|
||||
scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs);
|
||||
|
||||
if (filename__read_int(path, &value))
|
||||
if (sysctl__read_int("kernel/perf_event_paranoid", &value))
|
||||
return INT_MAX;
|
||||
|
||||
return value;
|
||||
|
||||
@@ -153,7 +153,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)))
|
||||
extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
|
||||
|
||||
extern int prefixcmp(const char *str, const char *prefix);
|
||||
extern void set_buildid_dir(void);
|
||||
extern void set_buildid_dir(const char *dir);
|
||||
|
||||
static inline const char *skip_prefix(const char *str, const char *prefix)
|
||||
{
|
||||
@@ -343,7 +343,6 @@ char *get_srcline(struct dso *dso, unsigned long addr, struct symbol *sym,
|
||||
bool show_sym);
|
||||
void free_srcline(char *srcline);
|
||||
|
||||
int filename__read_int(const char *filename, int *value);
|
||||
int filename__read_str(const char *filename, char **buf, size_t *sizep);
|
||||
int perf_event_paranoid(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user