From 78c96511e4d0e660d7ae806c3ae485c7478dd2e0 Mon Sep 17 00:00:00 2001 From: Serhei Makarov Date: Thu, 16 Aug 2018 11:38:27 -0400 Subject: [PATCH] stapbpf maps, PR23407: increase BPF_MAXMAP_ENTRIES, ensure space with setrlimit eBPF maps can be arbitrarily large, but they live in memlocked memory which has a very low default maximum per-process. This patch increases RLIMIT_MEMLOCK to allow larger maps, and increases BPF_MAX_MAPENTRIES to 2048. Since the rlimit is set separately for each process, impact on the system should not be significant. TODO: The exact amount by which to increase the rlimit is a matter for some experimentation. In addition to the space for keys and values, there is a per-entry overhead that may need to be tweaked upwards based on further testing. * bpf-internal.h (BPF_MAXMAPENTRIES): now bigger. * stapbpf.cxx (instantiate_maps): increase RLIMIT_MEMLOCK before allocating maps, add diagnostic printfs. --- bpf-internal.h | 9 ++++----- stapbpf/stapbpf.cxx | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/bpf-internal.h b/bpf-internal.h index 9d787c9ad..8ec545370 100644 --- a/bpf-internal.h +++ b/bpf-internal.h @@ -28,14 +28,13 @@ struct vardecl; namespace bpf { #define MAX_BPF_STACK 512 +#define BPF_REG_SIZE 8 #define BPF_MAXSTRINGLEN 64 #define BPF_MAXFORMATLEN 256 -#define BPF_MAXMAPENTRIES 16 -//#define BPF_MAXMAPENTRIES 2048 // TODO requires setrlimit +#define BPF_MAXMAPENTRIES 2048 // TODO: add BPF_MAXSPRINTFLEN -#define BPF_REG_SIZE 8 -// TODO: BPF_MAX{STRING,FORMAT}LEN,BPF_MAXMAPSIZE should be user-configurable. -// TODO: BPF_MAXMAPSIZE may depend on kernel version and rlimit. May need to setrlimit to create a bigger map (would like to default to 2048). +// TODO: BPF_MAX{STRING,FORMAT}LEN,BPF_MAXMAPENTRIES,BPF_MAXSPRINTFLEN should be user-configurable. +// XXX: BPF_MAXMAPENTRIES may depend on kernel version. May need to experiment with rlimit in instantiate_maps(). typedef unsigned short regno; static const regno max_regno = BPF_MAXINSNS; diff --git a/stapbpf/stapbpf.cxx b/stapbpf/stapbpf.cxx index 89e00ece7..ddb268756 100644 --- a/stapbpf/stapbpf.cxx +++ b/stapbpf/stapbpf.cxx @@ -37,6 +37,7 @@ #include #include #include +#include #include "bpfinterp.h" extern "C" { @@ -225,8 +226,55 @@ instantiate_maps (Elf64_Shdr *shdr, Elf_Data *data) map_attrs = attrs; map_fds.assign(n, -1); + /* First, make room for the maps in this process' RLIMIT_MEMLOCK: */ + size_t rlimit_increase = 0; for (i = 0; i < n; ++i) { + // TODO: The 58 bytes of overhead space per entry has been + // decided by trial and error, and may require further tweaking: + rlimit_increase += (58 + attrs[i].key_size + attrs[i].value_size) * attrs[i].max_entries; + } + + struct rlimit curr_rlimit; + int rc; + + rc = getrlimit(RLIMIT_MEMLOCK, &curr_rlimit); + if (rc < 0) + fatal("could not get map resource limit: %s\n", + strerror(errno)); + + size_t rlim_orig = curr_rlimit.rlim_cur; + size_t rlim_max_orig = curr_rlimit.rlim_max; + curr_rlimit.rlim_cur += rlimit_increase; + curr_rlimit.rlim_max += rlimit_increase; + if (curr_rlimit.rlim_cur < rlim_orig) // handle overflow + curr_rlimit.rlim_cur = rlim_orig; + if (curr_rlimit.rlim_max < rlim_max_orig) // handle overflow + curr_rlimit.rlim_max = rlim_max_orig; + + rc = setrlimit(RLIMIT_MEMLOCK, &curr_rlimit); + if (rc < 0) + fatal("could not increase map resource limit -- " + "cur from %lu to %lu, max from %lu to %lu: %s\n", + rlim_orig, curr_rlimit.rlim_cur, + rlim_max_orig, curr_rlimit.rlim_max, + strerror(errno)); + if (log_level > 1) + { + fprintf(stderr, "increasing map cur resource limit from %lu to %lu\n", + rlim_orig, curr_rlimit.rlim_cur); + fprintf(stderr, "increasing map max resource limit from %lu to %lu\n", + rlim_max_orig, curr_rlimit.rlim_max); + } + + /* Now create the maps: */ + for (i = 0; i < n; ++i) + { + if (log_level > 2) + fprintf(stderr, "creating map entry %zu: key_size %u, value_size %u, " + "max_entries %u, map_flags %u\n", i, + attrs[i].key_size, attrs[i].value_size, + attrs[i].max_entries, attrs[i].map_flags); int fd = bpf_create_map(static_cast(attrs[i].type), attrs[i].key_size, attrs[i].value_size, attrs[i].max_entries, attrs[i].map_flags); -- 2.43.5