Commit cf90a20d authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov
Browse files

libbpf: remove internal multi-instance prog support



Clean up internals that had to deal with the possibility of
multi-instance bpf_programs. Libbpf 1.0 doesn't support this, so all
this is not necessary now and can be simplified.

Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20220627211527.2245459-12-andrii@kernel.org


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent a11113a2
Loading
Loading
Loading
Loading
+34 −283
Original line number Diff line number Diff line
@@ -366,16 +366,6 @@ struct bpf_sec_def {
	libbpf_prog_attach_fn_t prog_attach_fn;
};

struct bpf_prog_prep_result {
	struct bpf_insn *new_insn_ptr;
	int new_insn_cnt;
	int *pfd;
};

typedef int (*bpf_program_prep_t)(struct bpf_program *prog, int n,
				  struct bpf_insn *insns, int insns_cnt,
				  struct bpf_prog_prep_result *res);

/*
 * bpf_prog should be a better name but it has been used in
 * linux/filter.h.
@@ -429,22 +419,19 @@ struct bpf_program {
	size_t log_size;
	__u32 log_level;

	struct {
		int nr;
		int *fds;
	} instances;
	bpf_program_prep_t preprocessor;

	struct bpf_object *obj;

	int fd;
	bool autoload;
	bool mark_btf_static;
	enum bpf_prog_type type;
	enum bpf_attach_type expected_attach_type;

	int prog_ifindex;
	__u32 attach_btf_obj_fd;
	__u32 attach_btf_id;
	__u32 attach_prog_fd;

	void *func_info;
	__u32 func_info_rec_size;
	__u32 func_info_cnt;
@@ -695,25 +682,10 @@ static Elf64_Rel *elf_rel_by_idx(Elf_Data *data, size_t idx);

void bpf_program__unload(struct bpf_program *prog)
{
	int i;

	if (!prog)
		return;

	/*
	 * If the object is opened but the program was never loaded,
	 * it is possible that prog->instances.nr == -1.
	 */
	if (prog->instances.nr > 0) {
		for (i = 0; i < prog->instances.nr; i++)
			zclose(prog->instances.fds[i]);
	} else if (prog->instances.nr != -1) {
		pr_warn("Internal error: instances.nr is %d\n",
			prog->instances.nr);
	}

	prog->instances.nr = -1;
	zfree(&prog->instances.fds);
	zclose(prog->fd);

	zfree(&prog->func_info);
	zfree(&prog->line_info);
@@ -797,6 +769,7 @@ bpf_object__init_prog(struct bpf_object *obj, struct bpf_program *prog,
	prog->insns_cnt = prog->sec_insn_cnt;

	prog->type = BPF_PROG_TYPE_UNSPEC;
	prog->fd = -1;

	/* libbpf's convention for SEC("?abc...") is that it's just like
	 * SEC("abc...") but the corresponding bpf_program starts out with
@@ -810,9 +783,6 @@ bpf_object__init_prog(struct bpf_object *obj, struct bpf_program *prog,
		prog->autoload = true;
	}

	prog->instances.fds = NULL;
	prog->instances.nr = -1;

	/* inherit object's log_level */
	prog->log_level = obj->log_level;

@@ -6862,10 +6832,9 @@ static int libbpf_prepare_prog_load(struct bpf_program *prog,

static void fixup_verifier_log(struct bpf_program *prog, char *buf, size_t buf_sz);

static int bpf_object_load_prog_instance(struct bpf_object *obj, struct bpf_program *prog,
static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog,
				struct bpf_insn *insns, int insns_cnt,
					 const char *license, __u32 kern_version,
					 int *prog_fd)
				const char *license, __u32 kern_version, int *prog_fd)
{
	LIBBPF_OPTS(bpf_prog_load_opts, load_attr);
	const char *prog_name = NULL;
@@ -7232,88 +7201,6 @@ static int bpf_program_record_relos(struct bpf_program *prog)
	return 0;
}

static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog,
				const char *license, __u32 kern_ver)
{
	int err = 0, fd, i;

	if (obj->loaded) {
		pr_warn("prog '%s': can't load after object was loaded\n", prog->name);
		return libbpf_err(-EINVAL);
	}

	if (prog->instances.nr < 0 || !prog->instances.fds) {
		if (prog->preprocessor) {
			pr_warn("Internal error: can't load program '%s'\n",
				prog->name);
			return libbpf_err(-LIBBPF_ERRNO__INTERNAL);
		}

		prog->instances.fds = malloc(sizeof(int));
		if (!prog->instances.fds) {
			pr_warn("Not enough memory for BPF fds\n");
			return libbpf_err(-ENOMEM);
		}
		prog->instances.nr = 1;
		prog->instances.fds[0] = -1;
	}

	if (!prog->preprocessor) {
		if (prog->instances.nr != 1) {
			pr_warn("prog '%s': inconsistent nr(%d) != 1\n",
				prog->name, prog->instances.nr);
		}
		if (obj->gen_loader)
			bpf_program_record_relos(prog);
		err = bpf_object_load_prog_instance(obj, prog,
						    prog->insns, prog->insns_cnt,
						    license, kern_ver, &fd);
		if (!err)
			prog->instances.fds[0] = fd;
		goto out;
	}

	for (i = 0; i < prog->instances.nr; i++) {
		struct bpf_prog_prep_result result;
		bpf_program_prep_t preprocessor = prog->preprocessor;

		memset(&result, 0, sizeof(result));
		err = preprocessor(prog, i, prog->insns,
				   prog->insns_cnt, &result);
		if (err) {
			pr_warn("Preprocessing the %dth instance of program '%s' failed\n",
				i, prog->name);
			goto out;
		}

		if (!result.new_insn_ptr || !result.new_insn_cnt) {
			pr_debug("Skip loading the %dth instance of program '%s'\n",
				 i, prog->name);
			prog->instances.fds[i] = -1;
			if (result.pfd)
				*result.pfd = -1;
			continue;
		}

		err = bpf_object_load_prog_instance(obj, prog,
						    result.new_insn_ptr, result.new_insn_cnt,
						    license, kern_ver, &fd);
		if (err) {
			pr_warn("Loading the %dth instance of program '%s' failed\n",
				i, prog->name);
			goto out;
		}

		if (result.pfd)
			*result.pfd = fd;
		prog->instances.fds[i] = fd;
	}
out:
	if (err)
		pr_warn("failed to load program '%s'\n", prog->name);
	return libbpf_err(err);
}

static int
bpf_object__load_progs(struct bpf_object *obj, int log_level)
{
@@ -7337,10 +7224,17 @@ bpf_object__load_progs(struct bpf_object *obj, int log_level)
			continue;
		}
		prog->log_level |= log_level;
		err = bpf_object_load_prog(obj, prog, obj->license, obj->kern_version);
		if (err)

		if (obj->gen_loader)
			bpf_program_record_relos(prog);

		err = bpf_object_load_prog(obj, prog, prog->insns, prog->insns_cnt,
					   obj->license, obj->kern_version, &prog->fd);
		if (err) {
			pr_warn("prog '%s': failed to load: %d\n", prog->name, err);
			return err;
		}
	}

	bpf_object__free_relocs(obj);
	return 0;
@@ -7985,11 +7879,16 @@ static int check_path(const char *path)
	return err;
}

static int bpf_program_pin_instance(struct bpf_program *prog, const char *path, int instance)
int bpf_program__pin(struct bpf_program *prog, const char *path)
{
	char *cp, errmsg[STRERR_BUFSIZE];
	int err;

	if (prog->fd < 0) {
		pr_warn("prog '%s': can't pin program that wasn't loaded\n", prog->name);
		return libbpf_err(-EINVAL);
	}

	err = make_parent_dir(path);
	if (err)
		return libbpf_err(err);
@@ -7998,164 +7897,35 @@ static int bpf_program_pin_instance(struct bpf_program *prog, const char *path,
	if (err)
		return libbpf_err(err);

	if (prog == NULL) {
		pr_warn("invalid program pointer\n");
		return libbpf_err(-EINVAL);
	}

	if (instance < 0 || instance >= prog->instances.nr) {
		pr_warn("invalid prog instance %d of prog %s (max %d)\n",
			instance, prog->name, prog->instances.nr);
		return libbpf_err(-EINVAL);
	}

	if (bpf_obj_pin(prog->instances.fds[instance], path)) {
	if (bpf_obj_pin(prog->fd, path)) {
		err = -errno;
		cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg));
		pr_warn("failed to pin program: %s\n", cp);
		pr_warn("prog '%s': failed to pin at '%s': %s\n", prog->name, path, cp);
		return libbpf_err(err);
	}
	pr_debug("pinned program '%s'\n", path);

	pr_debug("prog '%s': pinned at '%s'\n", prog->name, path);
	return 0;
}

static int bpf_program_unpin_instance(struct bpf_program *prog, const char *path, int instance)
int bpf_program__unpin(struct bpf_program *prog, const char *path)
{
	int err;

	err = check_path(path);
	if (err)
		return libbpf_err(err);

	if (prog == NULL) {
		pr_warn("invalid program pointer\n");
		return libbpf_err(-EINVAL);
	}

	if (instance < 0 || instance >= prog->instances.nr) {
		pr_warn("invalid prog instance %d of prog %s (max %d)\n",
			instance, prog->name, prog->instances.nr);
	if (prog->fd < 0) {
		pr_warn("prog '%s': can't unpin program that wasn't loaded\n", prog->name);
		return libbpf_err(-EINVAL);
	}

	err = unlink(path);
	if (err != 0)
		return libbpf_err(-errno);

	pr_debug("unpinned program '%s'\n", path);

	return 0;
}

int bpf_program__pin(struct bpf_program *prog, const char *path)
{
	int i, err;

	err = make_parent_dir(path);
	if (err)
		return libbpf_err(err);

	err = check_path(path);
	if (err)
		return libbpf_err(err);

	if (prog == NULL) {
		pr_warn("invalid program pointer\n");
		return libbpf_err(-EINVAL);
	}

	if (prog->instances.nr <= 0) {
		pr_warn("no instances of prog %s to pin\n", prog->name);
		return libbpf_err(-EINVAL);
	}

	if (prog->instances.nr == 1) {
		/* don't create subdirs when pinning single instance */
		return bpf_program_pin_instance(prog, path, 0);
	}

	for (i = 0; i < prog->instances.nr; i++) {
		char buf[PATH_MAX];
		int len;

		len = snprintf(buf, PATH_MAX, "%s/%d", path, i);
		if (len < 0) {
			err = -EINVAL;
			goto err_unpin;
		} else if (len >= PATH_MAX) {
			err = -ENAMETOOLONG;
			goto err_unpin;
		}

		err = bpf_program_pin_instance(prog, buf, i);
		if (err)
			goto err_unpin;
	}

	return 0;

err_unpin:
	for (i = i - 1; i >= 0; i--) {
		char buf[PATH_MAX];
		int len;

		len = snprintf(buf, PATH_MAX, "%s/%d", path, i);
		if (len < 0)
			continue;
		else if (len >= PATH_MAX)
			continue;

		bpf_program_unpin_instance(prog, buf, i);
	}

	rmdir(path);

	return libbpf_err(err);
}

int bpf_program__unpin(struct bpf_program *prog, const char *path)
{
	int i, err;

	err = check_path(path);
	if (err)
		return libbpf_err(err);

	if (prog == NULL) {
		pr_warn("invalid program pointer\n");
		return libbpf_err(-EINVAL);
	}

	if (prog->instances.nr <= 0) {
		pr_warn("no instances of prog %s to pin\n", prog->name);
		return libbpf_err(-EINVAL);
	}

	if (prog->instances.nr == 1) {
		/* don't create subdirs when pinning single instance */
		return bpf_program_unpin_instance(prog, path, 0);
	}

	for (i = 0; i < prog->instances.nr; i++) {
		char buf[PATH_MAX];
		int len;

		len = snprintf(buf, PATH_MAX, "%s/%d", path, i);
		if (len < 0)
			return libbpf_err(-EINVAL);
		else if (len >= PATH_MAX)
			return libbpf_err(-ENAMETOOLONG);

		err = bpf_program_unpin_instance(prog, buf, i);
		if (err)
			return err;
	}

	err = rmdir(path);
	err = unlink(path);
	if (err)
		return libbpf_err(-errno);

	pr_debug("prog '%s': unpinned from '%s'\n", prog->name, path);
	return 0;
}

@@ -8672,13 +8442,6 @@ int bpf_program__set_autoload(struct bpf_program *prog, bool autoload)
	return 0;
}

static int bpf_program_nth_fd(const struct bpf_program *prog, int n);

int bpf_program__fd(const struct bpf_program *prog)
{
	return bpf_program_nth_fd(prog, 0);
}

const struct bpf_insn *bpf_program__insns(const struct bpf_program *prog)
{
	return prog->insns;
@@ -8709,27 +8472,15 @@ int bpf_program__set_insns(struct bpf_program *prog,
	return 0;
}

static int bpf_program_nth_fd(const struct bpf_program *prog, int n)
int bpf_program__fd(const struct bpf_program *prog)
{
	int fd;

	if (!prog)
		return libbpf_err(-EINVAL);

	if (n >= prog->instances.nr || n < 0) {
		pr_warn("Can't get the %dth fd from program %s: only %d instances\n",
			n, prog->name, prog->instances.nr);
		return libbpf_err(-EINVAL);
	}

	fd = prog->instances.fds[n];
	if (fd < 0) {
		pr_warn("%dth instance of program '%s' is invalid\n",
			n, prog->name);
	if (prog->fd < 0)
		return libbpf_err(-ENOENT);
	}

	return fd;
	return prog->fd;
}

__alias(bpf_program__type)