core: remove refcount for bpf program

Currently ref count of bpf-program is kept in user space. However, the
kernel already implements its own ref count. Thus the ref count we keep for
bpf-program is redundant.

This PR removes ref count for bpf program as part of a task to simplify
bpf-program and remove redundancies, which will make the switch to
code-compiled BPF programs easier.

Part of #19270
This commit is contained in:
alexlzhu
2021-10-12 12:48:23 +02:00
committed by Lennart Poettering
parent d92681a65e
commit 76dc17254f
11 changed files with 79 additions and 92 deletions
+25 -29
View File
@@ -38,7 +38,27 @@ static const char *const bpf_cgroup_attach_type_table[__MAX_BPF_ATTACH_TYPE] = {
DEFINE_STRING_TABLE_LOOKUP(bpf_cgroup_attach_type, int);
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(bpf_program_hash_ops, void, trivial_hash_func, trivial_compare_func, bpf_program_unref);
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(bpf_program_hash_ops, void, trivial_hash_func, trivial_compare_func, bpf_program_free);
BPFProgram *bpf_program_free(BPFProgram *p) {
if (!p)
return NULL;
/* Unfortunately, the kernel currently doesn't implicitly detach BPF programs from their cgroups when the last
* fd to the BPF program is closed. This has nasty side-effects since this means that abnormally terminated
* programs that attached one of their BPF programs to a cgroup will leave this program pinned for good with
* zero chance of recovery, until the cgroup is removed. This is particularly problematic if the cgroup in
* question is the root cgroup (or any other cgroup belonging to a service that cannot be restarted during
* operation, such as dbus), as the memory for the BPF program can only be reclaimed through a reboot. To
* counter this, we track closely to which cgroup a program was attached to and will detach it on our own
* whenever we close the BPF fd. */
(void) bpf_program_cgroup_detach(p);
safe_close(p->kernel_fd);
free(p->instructions);
free(p->attached_path);
return mfree(p);
}
/* struct bpf_prog_info info must be initialized since its value is both input and output
* for BPF_OBJ_GET_INFO_BY_FD syscall. */
@@ -61,14 +81,13 @@ static int bpf_program_get_info_by_fd(int prog_fd, struct bpf_prog_info *info, u
}
int bpf_program_new(uint32_t prog_type, BPFProgram **ret) {
_cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;
_cleanup_(bpf_program_freep) BPFProgram *p = NULL;
p = new(BPFProgram, 1);
if (!p)
return -ENOMEM;
*p = (BPFProgram) {
.n_ref = 1,
.prog_type = prog_type,
.kernel_fd = -1,
};
@@ -79,7 +98,7 @@ int bpf_program_new(uint32_t prog_type, BPFProgram **ret) {
}
int bpf_program_new_from_bpffs_path(const char *path, BPFProgram **ret) {
_cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;
_cleanup_(bpf_program_freep) BPFProgram *p = NULL;
struct bpf_prog_info info = {};
int r;
@@ -92,7 +111,6 @@ int bpf_program_new_from_bpffs_path(const char *path, BPFProgram **ret) {
*p = (BPFProgram) {
.prog_type = BPF_PROG_TYPE_UNSPEC,
.n_ref = 1,
.kernel_fd = -1,
};
@@ -110,27 +128,6 @@ int bpf_program_new_from_bpffs_path(const char *path, BPFProgram **ret) {
return 0;
}
static BPFProgram *bpf_program_free(BPFProgram *p) {
assert(p);
/* Unfortunately, the kernel currently doesn't implicitly detach BPF programs from their cgroups when the last
* fd to the BPF program is closed. This has nasty side-effects since this means that abnormally terminated
* programs that attached one of their BPF programs to a cgroup will leave this programs pinned for good with
* zero chance of recovery, until the cgroup is removed. This is particularly problematic if the cgroup in
* question is the root cgroup (or any other cgroup belonging to a service that cannot be restarted during
* operation, such as dbus), as the memory for the BPF program can only be reclaimed through a reboot. To
* counter this, we track closely to which cgroup a program was attached to and will detach it on our own
* whenever we close the BPF fd. */
(void) bpf_program_cgroup_detach(p);
safe_close(p->kernel_fd);
free(p->instructions);
free(p->attached_path);
return mfree(p);
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(BPFProgram, bpf_program, bpf_program_free);
int bpf_program_add_instructions(BPFProgram *p, const struct bpf_insn *instructions, size_t count) {
@@ -424,7 +421,7 @@ int bpf_program_serialize_attachment_set(FILE *f, FDSet *fds, const char *key, S
int bpf_program_deserialize_attachment(const char *v, FDSet *fds, BPFProgram **bpfp) {
_cleanup_free_ char *sfd = NULL, *sat = NULL, *unescaped = NULL;
_cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;
_cleanup_(bpf_program_freep) BPFProgram *p = NULL;
_cleanup_close_ int fd = -1;
ssize_t l;
int ifd, at, r;
@@ -470,7 +467,6 @@ int bpf_program_deserialize_attachment(const char *v, FDSet *fds, BPFProgram **b
return -ENOMEM;
*p = (BPFProgram) {
.n_ref = 1,
.kernel_fd = TAKE_FD(fd),
.prog_type = BPF_PROG_TYPE_UNSPEC,
.attached_path = TAKE_PTR(unescaped),
@@ -478,7 +474,7 @@ int bpf_program_deserialize_attachment(const char *v, FDSet *fds, BPFProgram **b
};
if (*bpfp)
bpf_program_unref(*bpfp);
bpf_program_free(*bpfp);
*bpfp = TAKE_PTR(p);
return 0;