Commit 85fc4b16 authored by Roman Gushchin's avatar Roman Gushchin Committed by Daniel Borkmann

bpf: introduce update_effective_progs()

__cgroup_bpf_attach() and __cgroup_bpf_detach() functions have
a good amount of duplicated code, which is possible to eliminate
by introducing the update_effective_progs() helper function.

The update_effective_progs() calls compute_effective_progs()
and then in case of success it calls activate_effective_progs()
for each descendant cgroup. In case of failure (OOM), it releases
allocated prog arrays and return the error code.
Signed-off-by: default avatarRoman Gushchin <guro@fb.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarSong Liu <songliubraving@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 0c261593
...@@ -177,6 +177,45 @@ int cgroup_bpf_inherit(struct cgroup *cgrp) ...@@ -177,6 +177,45 @@ int cgroup_bpf_inherit(struct cgroup *cgrp)
return -ENOMEM; return -ENOMEM;
} }
static int update_effective_progs(struct cgroup *cgrp,
enum bpf_attach_type type)
{
struct cgroup_subsys_state *css;
int err;
/* allocate and recompute effective prog arrays */
css_for_each_descendant_pre(css, &cgrp->self) {
struct cgroup *desc = container_of(css, struct cgroup, self);
err = compute_effective_progs(desc, type, &desc->bpf.inactive);
if (err)
goto cleanup;
}
/* all allocations were successful. Activate all prog arrays */
css_for_each_descendant_pre(css, &cgrp->self) {
struct cgroup *desc = container_of(css, struct cgroup, self);
activate_effective_progs(desc, type, desc->bpf.inactive);
desc->bpf.inactive = NULL;
}
return 0;
cleanup:
/* oom while computing effective. Free all computed effective arrays
* since they were not activated
*/
css_for_each_descendant_pre(css, &cgrp->self) {
struct cgroup *desc = container_of(css, struct cgroup, self);
bpf_prog_array_free(desc->bpf.inactive);
desc->bpf.inactive = NULL;
}
return err;
}
#define BPF_CGROUP_MAX_PROGS 64 #define BPF_CGROUP_MAX_PROGS 64
/** /**
...@@ -194,7 +233,6 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, ...@@ -194,7 +233,6 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
struct list_head *progs = &cgrp->bpf.progs[type]; struct list_head *progs = &cgrp->bpf.progs[type];
struct bpf_prog *old_prog = NULL; struct bpf_prog *old_prog = NULL;
struct bpf_cgroup_storage *storage, *old_storage = NULL; struct bpf_cgroup_storage *storage, *old_storage = NULL;
struct cgroup_subsys_state *css;
struct bpf_prog_list *pl; struct bpf_prog_list *pl;
bool pl_was_allocated; bool pl_was_allocated;
int err; int err;
...@@ -261,22 +299,9 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, ...@@ -261,22 +299,9 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
cgrp->bpf.flags[type] = flags; cgrp->bpf.flags[type] = flags;
/* allocate and recompute effective prog arrays */ err = update_effective_progs(cgrp, type);
css_for_each_descendant_pre(css, &cgrp->self) { if (err)
struct cgroup *desc = container_of(css, struct cgroup, self); goto cleanup;
err = compute_effective_progs(desc, type, &desc->bpf.inactive);
if (err)
goto cleanup;
}
/* all allocations were successful. Activate all prog arrays */
css_for_each_descendant_pre(css, &cgrp->self) {
struct cgroup *desc = container_of(css, struct cgroup, self);
activate_effective_progs(desc, type, desc->bpf.inactive);
desc->bpf.inactive = NULL;
}
static_branch_inc(&cgroup_bpf_enabled_key); static_branch_inc(&cgroup_bpf_enabled_key);
if (old_storage) if (old_storage)
...@@ -289,16 +314,6 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, ...@@ -289,16 +314,6 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
return 0; return 0;
cleanup: cleanup:
/* oom while computing effective. Free all computed effective arrays
* since they were not activated
*/
css_for_each_descendant_pre(css, &cgrp->self) {
struct cgroup *desc = container_of(css, struct cgroup, self);
bpf_prog_array_free(desc->bpf.inactive);
desc->bpf.inactive = NULL;
}
/* and cleanup the prog list */ /* and cleanup the prog list */
pl->prog = old_prog; pl->prog = old_prog;
bpf_cgroup_storage_free(pl->storage); bpf_cgroup_storage_free(pl->storage);
...@@ -326,7 +341,6 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, ...@@ -326,7 +341,6 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
struct list_head *progs = &cgrp->bpf.progs[type]; struct list_head *progs = &cgrp->bpf.progs[type];
u32 flags = cgrp->bpf.flags[type]; u32 flags = cgrp->bpf.flags[type];
struct bpf_prog *old_prog = NULL; struct bpf_prog *old_prog = NULL;
struct cgroup_subsys_state *css;
struct bpf_prog_list *pl; struct bpf_prog_list *pl;
int err; int err;
...@@ -365,22 +379,9 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, ...@@ -365,22 +379,9 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
pl->prog = NULL; pl->prog = NULL;
} }
/* allocate and recompute effective prog arrays */ err = update_effective_progs(cgrp, type);
css_for_each_descendant_pre(css, &cgrp->self) { if (err)
struct cgroup *desc = container_of(css, struct cgroup, self); goto cleanup;
err = compute_effective_progs(desc, type, &desc->bpf.inactive);
if (err)
goto cleanup;
}
/* all allocations were successful. Activate all prog arrays */
css_for_each_descendant_pre(css, &cgrp->self) {
struct cgroup *desc = container_of(css, struct cgroup, self);
activate_effective_progs(desc, type, desc->bpf.inactive);
desc->bpf.inactive = NULL;
}
/* now can actually delete it from this cgroup list */ /* now can actually delete it from this cgroup list */
list_del(&pl->node); list_del(&pl->node);
...@@ -396,16 +397,6 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, ...@@ -396,16 +397,6 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
return 0; return 0;
cleanup: cleanup:
/* oom while computing effective. Free all computed effective arrays
* since they were not activated
*/
css_for_each_descendant_pre(css, &cgrp->self) {
struct cgroup *desc = container_of(css, struct cgroup, self);
bpf_prog_array_free(desc->bpf.inactive);
desc->bpf.inactive = NULL;
}
/* and restore back old_prog */ /* and restore back old_prog */
pl->prog = old_prog; pl->prog = old_prog;
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment