diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c index c5d05ec17220..dede0c388ed4 100644 --- a/tools/perf/util/cloexec.c +++ b/tools/perf/util/cloexec.c @@ -25,7 +25,7 @@ static int perf_flag_probe(void) return 1; } - WARN_ONCE(err != EINVAL, + WARN_ONCE(err != EINVAL && err != EBUSY, "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", err, strerror(err)); @@ -33,7 +33,7 @@ static int perf_flag_probe(void) fd = sys_perf_event_open(&attr, 0, -1, -1, 0); err = errno; - if (WARN_ONCE(fd < 0, + if (WARN_ONCE(fd < 0 && err != EBUSY, "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", err, strerror(err))) return -1; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 92e5235f5377..0c8919decac8 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2039,6 +2039,12 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); #endif break; + case EBUSY: + if (find_process("oprofiled")) + return scnprintf(msg, size, + "The PMU counters are busy/taken by another profiler.\n" + "We found oprofile daemon running, please stop it and try again."); + break; default: break; } diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index e52e7461911b..b82a93cb1694 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -536,3 +536,39 @@ void mem_bswap_64(void *src, int byte_size) ++m; } } + +bool find_process(const char *name) +{ + size_t len = strlen(name); + DIR *dir; + struct dirent *d; + int ret = -1; + + dir = opendir(procfs__mountpoint()); + if (!dir) + return -1; + + /* Walk through the directory. */ + while (ret && (d = readdir(dir)) != NULL) { + char path[PATH_MAX]; + char *data; + size_t size; + + if ((d->d_type != DT_DIR) || + !strcmp(".", d->d_name) || + !strcmp("..", d->d_name)) + continue; + + scnprintf(path, sizeof(path), "%s/%s/comm", + procfs__mountpoint(), d->d_name); + + if (filename__read_str(path, &data, &size)) + continue; + + ret = strncmp(name, data, len); + free(data); + } + + closedir(dir); + return ret ? false : true; +} diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 38af77550c75..03a1ea2266b8 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -346,4 +346,5 @@ void mem_bswap_64(void *src, int byte_size); void mem_bswap_32(void *src, int byte_size); const char *get_filename_for_perf_kvm(void); +bool find_process(const char *name); #endif /* GIT_COMPAT_UTIL_H */