summaryrefslogtreecommitdiffstats
path: root/kernel/cgroup
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@fb.com>2017-10-03 01:50:21 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-04 19:05:05 -0400
commit324bda9e6c5add86ba2e1066476481c48132aca0 (patch)
tree31d4267d10e934e6b3c180556c91aff8ea6dd990 /kernel/cgroup
parentc818fa9e288be5be7e360c33cf4f5e30f9fa206e (diff)
bpf: multi program support for cgroup+bpf
introduce BPF_F_ALLOW_MULTI flag that can be used to attach multiple bpf programs to a cgroup. The difference between three possible flags for BPF_PROG_ATTACH command: - NONE(default): No further bpf programs allowed in the subtree. - BPF_F_ALLOW_OVERRIDE: If a sub-cgroup installs some bpf program, the program in this cgroup yields to sub-cgroup program. - BPF_F_ALLOW_MULTI: If a sub-cgroup installs some bpf program, that cgroup program gets run in addition to the program in this cgroup. NONE and BPF_F_ALLOW_OVERRIDE existed before. This patch doesn't change their behavior. It only clarifies the semantics in relation to new flag. Only one program is allowed to be attached to a cgroup with NONE or BPF_F_ALLOW_OVERRIDE flag. Multiple programs are allowed to be attached to a cgroup with BPF_F_ALLOW_MULTI flag. They are executed in FIFO order (those that were attached first, run first) The programs of sub-cgroup are executed first, then programs of this cgroup and then programs of parent cgroup. All eligible programs are executed regardless of return code from earlier programs. To allow efficient execution of multiple programs attached to a cgroup and to avoid penalizing cgroups without any programs attached introduce 'struct bpf_prog_array' which is RCU protected array of pointers to bpf programs. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Martin KaFai Lau <kafai@fb.com> for cgroup bits Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/cgroup')
-rw-r--r--kernel/cgroup/cgroup.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index d6551cd45238..57eb866ae78d 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1896,6 +1896,9 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask, int ref_flags)
1896 if (ret) 1896 if (ret)
1897 goto destroy_root; 1897 goto destroy_root;
1898 1898
1899 ret = cgroup_bpf_inherit(root_cgrp);
1900 WARN_ON_ONCE(ret);
1901
1899 trace_cgroup_setup_root(root); 1902 trace_cgroup_setup_root(root);
1900 1903
1901 /* 1904 /*
@@ -4713,6 +4716,9 @@ static struct cgroup *cgroup_create(struct cgroup *parent)
4713 cgrp->self.parent = &parent->self; 4716 cgrp->self.parent = &parent->self;
4714 cgrp->root = root; 4717 cgrp->root = root;
4715 cgrp->level = level; 4718 cgrp->level = level;
4719 ret = cgroup_bpf_inherit(cgrp);
4720 if (ret)
4721 goto out_idr_free;
4716 4722
4717 for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp)) { 4723 for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp)) {
4718 cgrp->ancestor_ids[tcgrp->level] = tcgrp->id; 4724 cgrp->ancestor_ids[tcgrp->level] = tcgrp->id;
@@ -4747,13 +4753,12 @@ static struct cgroup *cgroup_create(struct cgroup *parent)
4747 if (!cgroup_on_dfl(cgrp)) 4753 if (!cgroup_on_dfl(cgrp))
4748 cgrp->subtree_control = cgroup_control(cgrp); 4754 cgrp->subtree_control = cgroup_control(cgrp);
4749 4755
4750 if (parent)
4751 cgroup_bpf_inherit(cgrp, parent);
4752
4753 cgroup_propagate_control(cgrp); 4756 cgroup_propagate_control(cgrp);
4754 4757
4755 return cgrp; 4758 return cgrp;
4756 4759
4760out_idr_free:
4761 cgroup_idr_remove(&root->cgroup_idr, cgrp->id);
4757out_cancel_ref: 4762out_cancel_ref:
4758 percpu_ref_exit(&cgrp->self.refcnt); 4763 percpu_ref_exit(&cgrp->self.refcnt);
4759out_free_cgrp: 4764out_free_cgrp:
@@ -5736,14 +5741,23 @@ void cgroup_sk_free(struct sock_cgroup_data *skcd)
5736#endif /* CONFIG_SOCK_CGROUP_DATA */ 5741#endif /* CONFIG_SOCK_CGROUP_DATA */
5737 5742
5738#ifdef CONFIG_CGROUP_BPF 5743#ifdef CONFIG_CGROUP_BPF
5739int cgroup_bpf_update(struct cgroup *cgrp, struct bpf_prog *prog, 5744int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
5740 enum bpf_attach_type type, bool overridable) 5745 enum bpf_attach_type type, u32 flags)
5746{
5747 int ret;
5748
5749 mutex_lock(&cgroup_mutex);
5750 ret = __cgroup_bpf_attach(cgrp, prog, type, flags);
5751 mutex_unlock(&cgroup_mutex);
5752 return ret;
5753}
5754int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
5755 enum bpf_attach_type type, u32 flags)
5741{ 5756{
5742 struct cgroup *parent = cgroup_parent(cgrp);
5743 int ret; 5757 int ret;
5744 5758
5745 mutex_lock(&cgroup_mutex); 5759 mutex_lock(&cgroup_mutex);
5746 ret = __cgroup_bpf_update(cgrp, parent, prog, type, overridable); 5760 ret = __cgroup_bpf_detach(cgrp, prog, type, flags);
5747 mutex_unlock(&cgroup_mutex); 5761 mutex_unlock(&cgroup_mutex);
5748 return ret; 5762 return ret;
5749} 5763}