diff mbox series

[v3,1/2] libbpf: Add setter for initial value for internal maps

Message ID 20200328182834.196578-1-toke@redhat.com
State Changes Requested
Delegated to: BPF Maintainers
Headers show
Series [v3,1/2] libbpf: Add setter for initial value for internal maps | expand

Commit Message

Toke Høiland-Jørgensen March 28, 2020, 6:28 p.m. UTC
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 function to set a new value for that data, which can be used to
before it is loaded into the kernel. This is especially relevant for RODATA
maps, since those are frozen on load.

Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
v3:
  - Add a setter for the initial value instead of a getter for the pointer to it
  - Add selftest
v2:
  - Add per-map getter for data area instead of a global rodata getter for bpf_obj

 tools/lib/bpf/libbpf.c   | 11 +++++++++++
 tools/lib/bpf/libbpf.h   |  2 ++
 tools/lib/bpf/libbpf.map |  1 +
 3 files changed, 14 insertions(+)

Comments

Andrii Nakryiko March 28, 2020, 8:01 p.m. UTC | #1
On Sat, Mar 28, 2020 at 11:29 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>
> 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 function to set a new value for that data, which can be used to
> before it is loaded into the kernel. This is especially relevant for RODATA
> maps, since those are frozen on load.
>
> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
> ---
> v3:
>   - Add a setter for the initial value instead of a getter for the pointer to it
>   - Add selftest
> v2:
>   - Add per-map getter for data area instead of a global rodata getter for bpf_obj
>
>  tools/lib/bpf/libbpf.c   | 11 +++++++++++
>  tools/lib/bpf/libbpf.h   |  2 ++
>  tools/lib/bpf/libbpf.map |  1 +
>  3 files changed, 14 insertions(+)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 085e41f9b68e..f9953a8ffcfa 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -6756,6 +6756,17 @@ void *bpf_map__priv(const struct bpf_map *map)
>         return map ? map->priv : ERR_PTR(-EINVAL);
>  }
>
> +int bpf_map__set_initial_value(struct bpf_map *map,
> +                              void *data, size_t size)

nit: const void *


> +{
> +       if (!map->mmaped || map->libbpf_type == LIBBPF_MAP_KCONFIG ||
> +           size != map->def.value_size)
> +               return -EINVAL;
> +

How about also checking that bpf_map wasn't yet created? Checking
map->fd >= 0 should be enough.

> +       memcpy(map->mmaped, data, size);
> +       return 0;
> +}
> +
>  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..ee30ed487221 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -407,6 +407,8 @@ 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 int bpf_map__set_initial_value(struct bpf_map *map,
> +                                         void *data, 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..f46873b9fe5e 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__set_initial_value;
>                 bpf_program__set_attach_target;
>  } LIBBPF_0.0.7;
> --
> 2.26.0
>
Toke Høiland-Jørgensen March 29, 2020, 12:17 p.m. UTC | #2
Andrii Nakryiko <andrii.nakryiko@gmail.com> writes:

> On Sat, Mar 28, 2020 at 11:29 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>>
>> 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 function to set a new value for that data, which can be used to
>> before it is loaded into the kernel. This is especially relevant for RODATA
>> maps, since those are frozen on load.
>>
>> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
>> ---
>> v3:
>>   - Add a setter for the initial value instead of a getter for the pointer to it
>>   - Add selftest
>> v2:
>>   - Add per-map getter for data area instead of a global rodata getter for bpf_obj
>>
>>  tools/lib/bpf/libbpf.c   | 11 +++++++++++
>>  tools/lib/bpf/libbpf.h   |  2 ++
>>  tools/lib/bpf/libbpf.map |  1 +
>>  3 files changed, 14 insertions(+)
>>
>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>> index 085e41f9b68e..f9953a8ffcfa 100644
>> --- a/tools/lib/bpf/libbpf.c
>> +++ b/tools/lib/bpf/libbpf.c
>> @@ -6756,6 +6756,17 @@ void *bpf_map__priv(const struct bpf_map *map)
>>         return map ? map->priv : ERR_PTR(-EINVAL);
>>  }
>>
>> +int bpf_map__set_initial_value(struct bpf_map *map,
>> +                              void *data, size_t size)
>
> nit: const void *

ACK.

>> +{
>> +       if (!map->mmaped || map->libbpf_type == LIBBPF_MAP_KCONFIG ||
>> +           size != map->def.value_size)
>> +               return -EINVAL;
>> +
>
> How about also checking that bpf_map wasn't yet created? Checking
> map->fd >= 0 should be enough.


Yup, makes sense.

>> +       memcpy(map->mmaped, data, size);
>> +       return 0;
>> +}
>> +
>>  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..ee30ed487221 100644
>> --- a/tools/lib/bpf/libbpf.h
>> +++ b/tools/lib/bpf/libbpf.h
>> @@ -407,6 +407,8 @@ 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 int bpf_map__set_initial_value(struct bpf_map *map,
>> +                                         void *data, 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..f46873b9fe5e 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__set_initial_value;
>>                 bpf_program__set_attach_target;
>>  } LIBBPF_0.0.7;
>> --
>> 2.26.0
>>
diff mbox series

Patch

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 085e41f9b68e..f9953a8ffcfa 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -6756,6 +6756,17 @@  void *bpf_map__priv(const struct bpf_map *map)
 	return map ? map->priv : ERR_PTR(-EINVAL);
 }
 
+int bpf_map__set_initial_value(struct bpf_map *map,
+			       void *data, size_t size)
+{
+	if (!map->mmaped || map->libbpf_type == LIBBPF_MAP_KCONFIG ||
+	    size != map->def.value_size)
+		return -EINVAL;
+
+	memcpy(map->mmaped, data, size);
+	return 0;
+}
+
 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..ee30ed487221 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -407,6 +407,8 @@  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 int bpf_map__set_initial_value(struct bpf_map *map,
+					  void *data, 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..f46873b9fe5e 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__set_initial_value;
 		bpf_program__set_attach_target;
 } LIBBPF_0.0.7;