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:
committed by
Lennart Poettering
parent
d92681a65e
commit
76dc17254f
+25
-29
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user