Commit fd08f944 authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'Fix pining maps after reuse map fd'



Hangbin Liu says:

====================
When a user reuse map fd after creating a map manually and set the
pin_path, then load the object via libbpf. bpf_object__create_maps()
will skip pinning map if map fd exist. Fix it by add moving bpf creation
to else condition and go on checking map pin_path after that.

v3:
for selftest: use CHECK() for bpf_object__open_file() and close map fd on error

v2:
a) close map fd if init map slots failed
b) add bpf selftest for this scenario
====================

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents dca4121c 44c4aa2b
Loading
Loading
Loading
Loading
+46 −34
Original line number Diff line number Diff line
@@ -4203,6 +4203,36 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map)
	return 0;
}

static int init_map_slots(struct bpf_map *map)
{
	const struct bpf_map *targ_map;
	unsigned int i;
	int fd, err;

	for (i = 0; i < map->init_slots_sz; i++) {
		if (!map->init_slots[i])
			continue;

		targ_map = map->init_slots[i];
		fd = bpf_map__fd(targ_map);
		err = bpf_map_update_elem(map->fd, &i, &fd, 0);
		if (err) {
			err = -errno;
			pr_warn("map '%s': failed to initialize slot [%d] to map '%s' fd=%d: %d\n",
				map->name, i, targ_map->name,
				fd, err);
			return err;
		}
		pr_debug("map '%s': slot [%d] set to map '%s' fd=%d\n",
			 map->name, i, targ_map->name, fd);
	}

	zfree(&map->init_slots);
	map->init_slots_sz = 0;

	return 0;
}

static int
bpf_object__create_maps(struct bpf_object *obj)
{
@@ -4226,15 +4256,13 @@ bpf_object__create_maps(struct bpf_object *obj)
		if (map->fd >= 0) {
			pr_debug("map '%s': skipping creation (preset fd=%d)\n",
				 map->name, map->fd);
			continue;
		}

		} else {
			err = bpf_object__create_map(obj, map);
			if (err)
				goto err_out;

		pr_debug("map '%s': created successfully, fd=%d\n", map->name,
			 map->fd);
			pr_debug("map '%s': created successfully, fd=%d\n",
				 map->name, map->fd);

			if (bpf_map__is_internal(map)) {
				err = bpf_object__populate_internal_map(obj, map);
@@ -4245,28 +4273,12 @@ bpf_object__create_maps(struct bpf_object *obj)
			}

			if (map->init_slots_sz) {
			for (j = 0; j < map->init_slots_sz; j++) {
				const struct bpf_map *targ_map;
				int fd;

				if (!map->init_slots[j])
					continue;

				targ_map = map->init_slots[j];
				fd = bpf_map__fd(targ_map);
				err = bpf_map_update_elem(map->fd, &j, &fd, 0);
				if (err) {
					err = -errno;
					pr_warn("map '%s': failed to initialize slot [%d] to map '%s' fd=%d: %d\n",
						map->name, j, targ_map->name,
						fd, err);
				err = init_map_slots(map);
				if (err < 0) {
					zclose(map->fd);
					goto err_out;
				}
				pr_debug("map '%s': slot [%d] set to map '%s' fd=%d\n",
					 map->name, j, targ_map->name, fd);
			}
			zfree(&map->init_slots);
			map->init_slots_sz = 0;
		}

		if (map->pin_path && !map->pinned) {
+48 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ void test_pinning(void)
	struct stat statbuf = {};
	struct bpf_object *obj;
	struct bpf_map *map;
	int err;
	int err, map_fd;
	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
		.pin_root_path = custpath,
	);
@@ -213,6 +213,53 @@ void test_pinning(void)
	if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
		goto out;

	/* remove the custom pin path to re-test it with reuse fd below */
	err = unlink(custpinpath);
	if (CHECK(err, "unlink custpinpath", "err %d errno %d\n", err, errno))
		goto out;

	err = rmdir(custpath);
	if (CHECK(err, "rmdir custpindir", "err %d errno %d\n", err, errno))
		goto out;

	bpf_object__close(obj);

	/* test pinning at custom path with reuse fd */
	obj = bpf_object__open_file(file, NULL);
	err = libbpf_get_error(obj);
	if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) {
		obj = NULL;
		goto out;
	}

	map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(__u32),
				sizeof(__u64), 1, 0);
	if (CHECK(map_fd < 0, "create pinmap manually", "fd %d\n", map_fd))
		goto out;

	map = bpf_object__find_map_by_name(obj, "pinmap");
	if (CHECK(!map, "find map", "NULL map"))
		goto close_map_fd;

	err = bpf_map__reuse_fd(map, map_fd);
	if (CHECK(err, "reuse pinmap fd", "err %d errno %d\n", err, errno))
		goto close_map_fd;

	err = bpf_map__set_pin_path(map, custpinpath);
	if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
		goto close_map_fd;

	err = bpf_object__load(obj);
	if (CHECK(err, "custom load", "err %d errno %d\n", err, errno))
		goto close_map_fd;

	/* check that pinmap was pinned at the custom path */
	err = stat(custpinpath, &statbuf);
	if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
		goto close_map_fd;

close_map_fd:
	close(map_fd);
out:
	unlink(pinpath);
	unlink(nopinpath);