Skip to content

Commit

Permalink
libbpf: Store map pin path and status in struct bpf_map
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Toke Høiland-Jørgensen authored and Alexei Starovoitov committed Nov 2, 2019
1 parent d1b4574 commit 4580b25
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 41 deletions.
164 changes: 123 additions & 41 deletions tools/lib/bpf/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;

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, buf);
err = bpf_map__unpin(map, pin_path);
if (err)
return err;
}
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions tools/lib/bpf/libbpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down
3 changes: 3 additions & 0 deletions tools/lib/bpf/libbpf.map
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 4580b25

Please sign in to comment.