Re: [PATCH bpf-next v2] libbpf: Add getter for pointer to data area for internal maps
From: Andrii Nakryiko <hidden>
Date: 2020-03-27 19:18:11
Also in:
bpf
On Fri, Mar 27, 2020 at 5:58 AM Toke Høiland-Jørgensen [off-list ref] wrote:
quoted hunk ↗ jump to hunk
For internal maps (most notably the maps backing global variables), libbpf uses an internal mmaped area to store the data after opening the object. This data is subsequently copied into the kernel map when the object is loaded. This adds a getter for the pointer to that internal data store. This can be used to modify the data before it is loaded into the kernel, which is especially relevant for RODATA, which is frozen on load. This same pointer is already exposed to the auto-generated skeletons, so access to it is already API; this just adds a way to get at it without pulling in the full skeleton infrastructure. Signed-off-by: Toke Høiland-Jørgensen <redacted> --- v2: - Add per-map getter for data area instead of a global rodata getter for bpf_obj tools/lib/bpf/libbpf.c | 9 +++++++++ tools/lib/bpf/libbpf.h | 1 + tools/lib/bpf/libbpf.map | 1 + 3 files changed, 11 insertions(+)diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 085e41f9b68e..a0055f8908fd 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c@@ -6756,6 +6756,15 @@ void *bpf_map__priv(const struct bpf_map *map) return map ? map->priv : ERR_PTR(-EINVAL); } +void *bpf_map__data_area(const struct bpf_map *map, size_t *size)
I'm not entirely thrilled about "data_area" name. This is entirely for providing initial value for maps, so maybe something like bpf_map__init_value() or something along those lines? Actually, how about a different API altogether: bpf_map__set_init_value(struct bpf_map *map, void *data, size_t size)? Application will have to prepare data of correct size, which will be copied to libbpf's internal storage. It also doesn't expose any of internal pointer. I don't think extra memcopy is a big deal here. Thoughts?
quoted hunk ↗ jump to hunk
+{ + if (map->mmaped && map->libbpf_type != LIBBPF_MAP_KCONFIG) { + *size = map->def.value_size; + return map->mmaped; + } + return NULL; +} + bool bpf_map__is_offload_neutral(const struct bpf_map *map) { return map->def.type == BPF_MAP_TYPE_PERF_EVENT_ARRAY;diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index d38d7a629417..baef0d2f3205 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h@@ -407,6 +407,7 @@ typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv, bpf_map_clear_priv_t clear_priv); LIBBPF_API void *bpf_map__priv(const struct bpf_map *map); +LIBBPF_API void *bpf_map__data_area(const struct bpf_map *map, size_t *size); LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd); LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries); LIBBPF_API bool bpf_map__is_offload_neutral(const struct bpf_map *map);diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 5129283c0284..258528045a85 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map@@ -243,5 +243,6 @@ LIBBPF_0.0.8 { bpf_link__pin; bpf_link__pin_path; bpf_link__unpin; + bpf_map__data_area; bpf_program__set_attach_target; } LIBBPF_0.0.7; --2.26.0