*/
#include "util.h"
#include <api/fs/debugfs.h>
+#include <api/fs/fs.h>
#include <poll.h>
#include "cpumap.h"
#include "thread_map.h"
#include <linux/bitops.h>
#include <linux/hash.h>
+#include <linux/log2.h>
static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
static size_t perf_evlist__mmap_size(unsigned long pages)
{
- /* 512 kiB: default amount of unprivileged mlocked memory */
- if (pages == UINT_MAX)
- pages = (512 * 1024) / page_size;
- else if (!is_power_of_2(pages))
+ if (pages == UINT_MAX) {
+ int max;
+
+ if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
+ /*
+ * Pick a once upon a time good value, i.e. things look
+ * strange since we can't read a sysctl value, but lets not
+ * die yet...
+ */
+ max = 512;
+ } else {
+ max -= (page_size / 1024);
+ }
+
+ pages = (max * 1024) / page_size;
+ if (!is_power_of_2(pages))
+ pages = rounddown_pow_of_two(pages);
+ } else if (!is_power_of_2(pages))
return 0;
return (pages + 1) * page_size;
/* leave number of pages at 0 */
} else if (!is_power_of_2(pages)) {
/* round pages up to next power of 2 */
- pages = next_pow2_l(pages);
+ pages = roundup_pow_of_two(pages);
if (!pages)
return -EINVAL;
pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
case ENOENT:
scnprintf(buf, size, "%s",
"Error:\tUnable to find debugfs\n"
- "Hint:\tWas your kernel was compiled with debugfs support?\n"
+ "Hint:\tWas your kernel compiled with debugfs support?\n"
"Hint:\tIs the debugfs filesystem mounted?\n"
"Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
break;
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 pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
+
+ switch (err) {
+ case EPERM:
+ sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user);
+ printed += scnprintf(buf + printed, size - printed,
+ "Error:\t%s.\n"
+ "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
+ "Hint:\tTried using %zd kB.\n",
+ emsg, pages_max_per_user, pages_attempted);
+
+ if (pages_attempted >= pages_max_per_user) {
+ printed += scnprintf(buf + printed, size - printed,
+ "Hint:\tTry 'sudo sh -c \"echo %d > /proc/sys/kernel/perf_event_mlock_kb\"', or\n",
+ pages_max_per_user + pages_attempted);
+ }
+
+ printed += scnprintf(buf + printed, size - printed,
+ "Hint:\tTry using a smaller -m/--mmap-pages value.");
+ break;
+ default:
+ scnprintf(buf, size, "%s", emsg);
+ break;
+ }
+
+ return 0;
+}
+
void perf_evlist__to_front(struct perf_evlist *evlist,
struct perf_evsel *move_evsel)
{