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: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20220627211527.2245459-12-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Andrii Nakryiko 2022-06-27 14:15:23 -07:00 committed by Alexei Starovoitov
parent a11113a2dc
commit cf90a20db8

View File

@ -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,
struct bpf_insn *insns, int insns_cnt,
const char *license, __u32 kern_version,
int *prog_fd)
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)
{
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,9 +7224,16 @@ 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);
@ -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 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);
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;
int err;
if (prog->fd < 0) {
pr_warn("prog '%s': can't unpin program that wasn't loaded\n", prog->name);
return libbpf_err(-EINVAL);
}
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)