forked from luck/tmp_suning_uos_patched
bpf: Simplify __cgroup_bpf_attach
__cgroup_bpf_attach has a lot of identical code to handle two scenarios: BPF_F_ALLOW_MULTI is set and unset. Simplify it by splitting the two main steps: * First, the decision is made whether a new bpf_prog_list entry should be allocated or existing entry should be reused for the new program. This decision is saved in replace_pl pointer; * Next, replace_pl pointer is used to handle both possible states of BPF_F_ALLOW_MULTI flag (set / unset) instead of doing similar work for them separately. This splitting, in turn, allows to make further simplifications: * The check for attaching same program twice in BPF_F_ALLOW_MULTI mode can be done before allocating cgroup storage, so that if user tries to attach same program twice no alloc/free happens as it was before; * pl_was_allocated becomes redundant so it's removed. Signed-off-by: Andrey Ignatov <rdna@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Martin KaFai Lau <kafai@fb.com> Acked-by: Andrii Nakryiko <andriin@fb.com> Link: https://lore.kernel.org/bpf/c6193db6fe630797110b0d3ff06c125d093b834c.1576741281.git.rdna@fb.com
This commit is contained in:
parent
c92bbaa0fd
commit
1020c1f24a
|
@ -295,9 +295,8 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
|
||||||
struct bpf_prog *old_prog = NULL;
|
struct bpf_prog *old_prog = NULL;
|
||||||
struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE],
|
struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE],
|
||||||
*old_storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {NULL};
|
*old_storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {NULL};
|
||||||
|
struct bpf_prog_list *pl, *replace_pl = NULL;
|
||||||
enum bpf_cgroup_storage_type stype;
|
enum bpf_cgroup_storage_type stype;
|
||||||
struct bpf_prog_list *pl;
|
|
||||||
bool pl_was_allocated;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((flags & BPF_F_ALLOW_OVERRIDE) && (flags & BPF_F_ALLOW_MULTI))
|
if ((flags & BPF_F_ALLOW_OVERRIDE) && (flags & BPF_F_ALLOW_MULTI))
|
||||||
|
@ -317,6 +316,16 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
|
||||||
if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS)
|
if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS)
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
|
|
||||||
|
if (flags & BPF_F_ALLOW_MULTI) {
|
||||||
|
list_for_each_entry(pl, progs, node) {
|
||||||
|
if (pl->prog == prog)
|
||||||
|
/* disallow attaching the same prog twice */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
} else if (!list_empty(progs)) {
|
||||||
|
replace_pl = list_first_entry(progs, typeof(*pl), node);
|
||||||
|
}
|
||||||
|
|
||||||
for_each_cgroup_storage_type(stype) {
|
for_each_cgroup_storage_type(stype) {
|
||||||
storage[stype] = bpf_cgroup_storage_alloc(prog, stype);
|
storage[stype] = bpf_cgroup_storage_alloc(prog, stype);
|
||||||
if (IS_ERR(storage[stype])) {
|
if (IS_ERR(storage[stype])) {
|
||||||
|
@ -327,52 +336,27 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & BPF_F_ALLOW_MULTI) {
|
if (replace_pl) {
|
||||||
list_for_each_entry(pl, progs, node) {
|
pl = replace_pl;
|
||||||
if (pl->prog == prog) {
|
old_prog = pl->prog;
|
||||||
/* disallow attaching the same prog twice */
|
for_each_cgroup_storage_type(stype) {
|
||||||
for_each_cgroup_storage_type(stype)
|
old_storage[stype] = pl->storage[stype];
|
||||||
bpf_cgroup_storage_free(storage[stype]);
|
bpf_cgroup_storage_unlink(old_storage[stype]);
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
pl = kmalloc(sizeof(*pl), GFP_KERNEL);
|
pl = kmalloc(sizeof(*pl), GFP_KERNEL);
|
||||||
if (!pl) {
|
if (!pl) {
|
||||||
for_each_cgroup_storage_type(stype)
|
for_each_cgroup_storage_type(stype)
|
||||||
bpf_cgroup_storage_free(storage[stype]);
|
bpf_cgroup_storage_free(storage[stype]);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
pl_was_allocated = true;
|
|
||||||
pl->prog = prog;
|
|
||||||
for_each_cgroup_storage_type(stype)
|
|
||||||
pl->storage[stype] = storage[stype];
|
|
||||||
list_add_tail(&pl->node, progs);
|
list_add_tail(&pl->node, progs);
|
||||||
} else {
|
|
||||||
if (list_empty(progs)) {
|
|
||||||
pl = kmalloc(sizeof(*pl), GFP_KERNEL);
|
|
||||||
if (!pl) {
|
|
||||||
for_each_cgroup_storage_type(stype)
|
|
||||||
bpf_cgroup_storage_free(storage[stype]);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
pl_was_allocated = true;
|
|
||||||
list_add_tail(&pl->node, progs);
|
|
||||||
} else {
|
|
||||||
pl = list_first_entry(progs, typeof(*pl), node);
|
|
||||||
old_prog = pl->prog;
|
|
||||||
for_each_cgroup_storage_type(stype) {
|
|
||||||
old_storage[stype] = pl->storage[stype];
|
|
||||||
bpf_cgroup_storage_unlink(old_storage[stype]);
|
|
||||||
}
|
|
||||||
pl_was_allocated = false;
|
|
||||||
}
|
|
||||||
pl->prog = prog;
|
|
||||||
for_each_cgroup_storage_type(stype)
|
|
||||||
pl->storage[stype] = storage[stype];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pl->prog = prog;
|
||||||
|
for_each_cgroup_storage_type(stype)
|
||||||
|
pl->storage[stype] = storage[stype];
|
||||||
|
|
||||||
cgrp->bpf.flags[type] = flags;
|
cgrp->bpf.flags[type] = flags;
|
||||||
|
|
||||||
err = update_effective_progs(cgrp, type);
|
err = update_effective_progs(cgrp, type);
|
||||||
|
@ -401,7 +385,7 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
|
||||||
pl->storage[stype] = old_storage[stype];
|
pl->storage[stype] = old_storage[stype];
|
||||||
bpf_cgroup_storage_link(old_storage[stype], cgrp, type);
|
bpf_cgroup_storage_link(old_storage[stype], cgrp, type);
|
||||||
}
|
}
|
||||||
if (pl_was_allocated) {
|
if (!replace_pl) {
|
||||||
list_del(&pl->node);
|
list_del(&pl->node);
|
||||||
kfree(pl);
|
kfree(pl);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user