forked from Minki/linux
libbpf: Store map pin path and status in struct bpf_map
Support storing and setting a pin path in struct bpf_map, which can be used for automatic pinning. Also store the pin status so we can avoid attempts to re-pin a map that has already been pinned (or reused from a previous pinning). The behaviour of bpf_object__{un,}pin_maps() is changed so that if it is called with a NULL path argument (which was previously illegal), it will (un)pin only those maps that have a pin_path set. Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Andrii Nakryiko <andriin@fb.com> Link: https://lore.kernel.org/bpf/157269297876.394725.14782206533681896279.stgit@toke.dk
This commit is contained in:
parent
d1b4574a4b
commit
4580b25fce
@ -227,6 +227,8 @@ struct bpf_map {
|
||||
void *priv;
|
||||
bpf_map_clear_priv_t clear_priv;
|
||||
enum libbpf_map_type libbpf_type;
|
||||
char *pin_path;
|
||||
bool pinned;
|
||||
};
|
||||
|
||||
struct bpf_secdata {
|
||||
@ -4036,47 +4038,119 @@ int bpf_map__pin(struct bpf_map *map, const char *path)
|
||||
char *cp, errmsg[STRERR_BUFSIZE];
|
||||
int err;
|
||||
|
||||
err = check_path(path);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (map == NULL) {
|
||||
pr_warn("invalid map pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bpf_obj_pin(map->fd, path)) {
|
||||
cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
|
||||
pr_warn("failed to pin map: %s\n", cp);
|
||||
return -errno;
|
||||
if (map->pin_path) {
|
||||
if (path && strcmp(path, map->pin_path)) {
|
||||
pr_warn("map '%s' already has pin path '%s' different from '%s'\n",
|
||||
bpf_map__name(map), map->pin_path, path);
|
||||
return -EINVAL;
|
||||
} else if (map->pinned) {
|
||||
pr_debug("map '%s' already pinned at '%s'; not re-pinning\n",
|
||||
bpf_map__name(map), map->pin_path);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!path) {
|
||||
pr_warn("missing a path to pin map '%s' at\n",
|
||||
bpf_map__name(map));
|
||||
return -EINVAL;
|
||||
} else if (map->pinned) {
|
||||
pr_warn("map '%s' already pinned\n", bpf_map__name(map));
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
map->pin_path = strdup(path);
|
||||
if (!map->pin_path) {
|
||||
err = -errno;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
pr_debug("pinned map '%s'\n", path);
|
||||
err = check_path(map->pin_path);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (bpf_obj_pin(map->fd, map->pin_path)) {
|
||||
err = -errno;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
map->pinned = true;
|
||||
pr_debug("pinned map '%s'\n", map->pin_path);
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
cp = libbpf_strerror_r(-err, errmsg, sizeof(errmsg));
|
||||
pr_warn("failed to pin map: %s\n", cp);
|
||||
return err;
|
||||
}
|
||||
|
||||
int bpf_map__unpin(struct bpf_map *map, const char *path)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = check_path(path);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (map == NULL) {
|
||||
pr_warn("invalid map pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (map->pin_path) {
|
||||
if (path && strcmp(path, map->pin_path)) {
|
||||
pr_warn("map '%s' already has pin path '%s' different from '%s'\n",
|
||||
bpf_map__name(map), map->pin_path, path);
|
||||
return -EINVAL;
|
||||
}
|
||||
path = map->pin_path;
|
||||
} else if (!path) {
|
||||
pr_warn("no path to unpin map '%s' from\n",
|
||||
bpf_map__name(map));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = check_path(path);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = unlink(path);
|
||||
if (err != 0)
|
||||
return -errno;
|
||||
pr_debug("unpinned map '%s'\n", path);
|
||||
|
||||
map->pinned = false;
|
||||
pr_debug("unpinned map '%s' from '%s'\n", bpf_map__name(map), path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bpf_map__set_pin_path(struct bpf_map *map, const char *path)
|
||||
{
|
||||
char *new = NULL;
|
||||
|
||||
if (path) {
|
||||
new = strdup(path);
|
||||
if (!new)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
free(map->pin_path);
|
||||
map->pin_path = new;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *bpf_map__get_pin_path(const struct bpf_map *map)
|
||||
{
|
||||
return map->pin_path;
|
||||
}
|
||||
|
||||
bool bpf_map__is_pinned(const struct bpf_map *map)
|
||||
{
|
||||
return map->pinned;
|
||||
}
|
||||
|
||||
int bpf_object__pin_maps(struct bpf_object *obj, const char *path)
|
||||
{
|
||||
struct bpf_map *map;
|
||||
@ -4095,20 +4169,27 @@ int bpf_object__pin_maps(struct bpf_object *obj, const char *path)
|
||||
return err;
|
||||
|
||||
bpf_object__for_each_map(map, obj) {
|
||||
char *pin_path = NULL;
|
||||
char buf[PATH_MAX];
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path,
|
||||
bpf_map__name(map));
|
||||
if (len < 0) {
|
||||
err = -EINVAL;
|
||||
goto err_unpin_maps;
|
||||
} else if (len >= PATH_MAX) {
|
||||
err = -ENAMETOOLONG;
|
||||
goto err_unpin_maps;
|
||||
if (path) {
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path,
|
||||
bpf_map__name(map));
|
||||
if (len < 0) {
|
||||
err = -EINVAL;
|
||||
goto err_unpin_maps;
|
||||
} else if (len >= PATH_MAX) {
|
||||
err = -ENAMETOOLONG;
|
||||
goto err_unpin_maps;
|
||||
}
|
||||
pin_path = buf;
|
||||
} else if (!map->pin_path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = bpf_map__pin(map, buf);
|
||||
err = bpf_map__pin(map, pin_path);
|
||||
if (err)
|
||||
goto err_unpin_maps;
|
||||
}
|
||||
@ -4117,17 +4198,10 @@ int bpf_object__pin_maps(struct bpf_object *obj, const char *path)
|
||||
|
||||
err_unpin_maps:
|
||||
while ((map = bpf_map__prev(map, obj))) {
|
||||
char buf[PATH_MAX];
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path,
|
||||
bpf_map__name(map));
|
||||
if (len < 0)
|
||||
continue;
|
||||
else if (len >= PATH_MAX)
|
||||
if (!map->pin_path)
|
||||
continue;
|
||||
|
||||
bpf_map__unpin(map, buf);
|
||||
bpf_map__unpin(map, NULL);
|
||||
}
|
||||
|
||||
return err;
|
||||
@ -4142,17 +4216,24 @@ int bpf_object__unpin_maps(struct bpf_object *obj, const char *path)
|
||||
return -ENOENT;
|
||||
|
||||
bpf_object__for_each_map(map, obj) {
|
||||
char *pin_path = NULL;
|
||||
char buf[PATH_MAX];
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path,
|
||||
bpf_map__name(map));
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
else if (len >= PATH_MAX)
|
||||
return -ENAMETOOLONG;
|
||||
if (path) {
|
||||
int len;
|
||||
|
||||
err = bpf_map__unpin(map, buf);
|
||||
len = snprintf(buf, PATH_MAX, "%s/%s", path,
|
||||
bpf_map__name(map));
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
else if (len >= PATH_MAX)
|
||||
return -ENAMETOOLONG;
|
||||
pin_path = buf;
|
||||
} else if (!map->pin_path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = bpf_map__unpin(map, pin_path);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@ -4277,6 +4358,7 @@ void bpf_object__close(struct bpf_object *obj)
|
||||
|
||||
for (i = 0; i < obj->nr_maps; i++) {
|
||||
zfree(&obj->maps[i].name);
|
||||
zfree(&obj->maps[i].pin_path);
|
||||
if (obj->maps[i].clear_priv)
|
||||
obj->maps[i].clear_priv(&obj->maps[i],
|
||||
obj->maps[i].priv);
|
||||
|
@ -124,6 +124,11 @@ int bpf_object__section_size(const struct bpf_object *obj, const char *name,
|
||||
__u32 *size);
|
||||
int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
|
||||
__u32 *off);
|
||||
|
||||
/* pin_maps and unpin_maps can both be called with a NULL path, in which case
|
||||
* they will use the pin_path attribute of each map (and ignore all maps that
|
||||
* don't have a pin_path set).
|
||||
*/
|
||||
LIBBPF_API int bpf_object__pin_maps(struct bpf_object *obj, const char *path);
|
||||
LIBBPF_API int bpf_object__unpin_maps(struct bpf_object *obj,
|
||||
const char *path);
|
||||
@ -387,6 +392,9 @@ 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);
|
||||
LIBBPF_API bool bpf_map__is_internal(const struct bpf_map *map);
|
||||
LIBBPF_API void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex);
|
||||
LIBBPF_API int bpf_map__set_pin_path(struct bpf_map *map, const char *path);
|
||||
LIBBPF_API const char *bpf_map__get_pin_path(const struct bpf_map *map);
|
||||
LIBBPF_API bool bpf_map__is_pinned(const struct bpf_map *map);
|
||||
LIBBPF_API int bpf_map__pin(struct bpf_map *map, const char *path);
|
||||
LIBBPF_API int bpf_map__unpin(struct bpf_map *map, const char *path);
|
||||
|
||||
|
@ -193,6 +193,9 @@ LIBBPF_0.0.5 {
|
||||
|
||||
LIBBPF_0.0.6 {
|
||||
global:
|
||||
bpf_map__get_pin_path;
|
||||
bpf_map__is_pinned;
|
||||
bpf_map__set_pin_path;
|
||||
bpf_object__open_file;
|
||||
bpf_object__open_mem;
|
||||
bpf_program__get_expected_attach_type;
|
||||
|
Loading…
Reference in New Issue
Block a user