Skip to content

Commit 45493ec

Browse files
haoluo1022Nobody
authored andcommitted
bpf: Introduce cgroup iter
Introduce a new type of iter prog: cgroup. Unlike other bpf_iter, this iter doesn't iterate a set of kernel objects. Instead, it is supposed to be parameterized by a cgroup id and prints only that cgroup. So one needs to specify a target cgroup id when attaching this iter. The target cgroup's state can be read out via a link of this iter. Typically, we can monitor cgroup creation and deletion using sleepable tracing and use it to create corresponding directories in bpffs and pin a cgroup id parameterized link in the directory. Then we can read the auto-pinned iter link to get cgroup's state. The output of the iter link is determined by the program. See the selftest test_cgroup_stats.c for an example. Signed-off-by: Hao Luo <haoluo@google.com> Reported-by: kernel test robot <lkp@intel.com> Reported-by: kernel test robot <lkp@intel.com> Reported-by: kernel test robot <lkp@intel.com>
1 parent d39cae0 commit 45493ec

File tree

5 files changed

+155
-1
lines changed

5 files changed

+155
-1
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,7 @@ int bpf_obj_get_path(bpfptr_t pathname, int flags);
15951595

15961596
struct bpf_iter_aux_info {
15971597
struct bpf_map *map;
1598+
u64 cgroup_id;
15981599
};
15991600

16001601
typedef int (*bpf_iter_attach_target_t)(struct bpf_prog *prog,

include/uapi/linux/bpf.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ union bpf_iter_link_info {
9191
struct {
9292
__u32 map_fd;
9393
} map;
94+
struct {
95+
__u64 cgroup_id;
96+
} cgroup;
9497
};
9598

9699
/* BPF syscall commands, see bpf(2) man-page for more details. */
@@ -5887,6 +5890,9 @@ struct bpf_link_info {
58875890
struct {
58885891
__u32 map_id;
58895892
} map;
5893+
struct {
5894+
__u64 cgroup_id;
5895+
} cgroup;
58905896
};
58915897
} iter;
58925898
struct {

kernel/bpf/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ CFLAGS_core.o += $(call cc-disable-warning, override-init) $(cflags-nogcse-yy)
88

99
obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o prog_iter.o
1010
obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o bloom_filter.o
11-
obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o
11+
obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o cgroup_iter.o
1212
obj-$(CONFIG_BPF_SYSCALL) += bpf_local_storage.o bpf_task_storage.o
1313
obj-${CONFIG_BPF_LSM} += bpf_inode_storage.o
1414
obj-$(CONFIG_BPF_SYSCALL) += disasm.o

kernel/bpf/cgroup_iter.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright (c) 2022 Google */
3+
#include <linux/bpf.h>
4+
#include <linux/btf_ids.h>
5+
#include <linux/cgroup.h>
6+
#include <linux/kernel.h>
7+
#include <linux/seq_file.h>
8+
9+
struct bpf_iter__cgroup {
10+
__bpf_md_ptr(struct bpf_iter_meta *, meta);
11+
__bpf_md_ptr(struct cgroup *, cgroup);
12+
};
13+
14+
static void *cgroup_iter_seq_start(struct seq_file *seq, loff_t *pos)
15+
{
16+
struct cgroup *cgroup;
17+
u64 cgroup_id;
18+
19+
/* Only one session is supported. */
20+
if (*pos > 0)
21+
return NULL;
22+
23+
cgroup_id = *(u64 *)seq->private;
24+
cgroup = cgroup_get_from_id(cgroup_id);
25+
if (!cgroup)
26+
return NULL;
27+
28+
if (*pos == 0)
29+
++*pos;
30+
31+
return cgroup;
32+
}
33+
34+
static void *cgroup_iter_seq_next(struct seq_file *seq, void *v, loff_t *pos)
35+
{
36+
++*pos;
37+
return NULL;
38+
}
39+
40+
static int cgroup_iter_seq_show(struct seq_file *seq, void *v)
41+
{
42+
struct bpf_iter__cgroup ctx;
43+
struct bpf_iter_meta meta;
44+
struct bpf_prog *prog;
45+
int ret = 0;
46+
47+
ctx.meta = &meta;
48+
ctx.cgroup = v;
49+
meta.seq = seq;
50+
prog = bpf_iter_get_info(&meta, false);
51+
if (prog)
52+
ret = bpf_iter_run_prog(prog, &ctx);
53+
54+
return ret;
55+
}
56+
57+
static void cgroup_iter_seq_stop(struct seq_file *seq, void *v)
58+
{
59+
if (v)
60+
cgroup_put(v);
61+
}
62+
63+
static const struct seq_operations cgroup_iter_seq_ops = {
64+
.start = cgroup_iter_seq_start,
65+
.next = cgroup_iter_seq_next,
66+
.stop = cgroup_iter_seq_stop,
67+
.show = cgroup_iter_seq_show,
68+
};
69+
70+
BTF_ID_LIST_SINGLE(bpf_cgroup_btf_id, struct, cgroup)
71+
72+
static int cgroup_iter_seq_init(void *priv_data, struct bpf_iter_aux_info *aux)
73+
{
74+
*(u64 *)priv_data = aux->cgroup_id;
75+
return 0;
76+
}
77+
78+
static void cgroup_iter_seq_fini(void *priv_data)
79+
{
80+
}
81+
82+
static const struct bpf_iter_seq_info cgroup_iter_seq_info = {
83+
.seq_ops = &cgroup_iter_seq_ops,
84+
.init_seq_private = cgroup_iter_seq_init,
85+
.fini_seq_private = cgroup_iter_seq_fini,
86+
.seq_priv_size = sizeof(u64),
87+
};
88+
89+
static int bpf_iter_attach_cgroup(struct bpf_prog *prog,
90+
union bpf_iter_link_info *linfo,
91+
struct bpf_iter_aux_info *aux)
92+
{
93+
aux->cgroup_id = linfo->cgroup.cgroup_id;
94+
return 0;
95+
}
96+
97+
static void bpf_iter_detach_cgroup(struct bpf_iter_aux_info *aux)
98+
{
99+
}
100+
101+
void bpf_iter_cgroup_show_fdinfo(const struct bpf_iter_aux_info *aux,
102+
struct seq_file *seq)
103+
{
104+
char buf[64] = {0};
105+
106+
cgroup_path_from_kernfs_id(aux->cgroup_id, buf, sizeof(buf));
107+
seq_printf(seq, "cgroup_id:\t%lu\n", aux->cgroup_id);
108+
seq_printf(seq, "cgroup_path:\t%s\n", buf);
109+
}
110+
111+
int bpf_iter_cgroup_fill_link_info(const struct bpf_iter_aux_info *aux,
112+
struct bpf_link_info *info)
113+
{
114+
info->iter.cgroup.cgroup_id = aux->cgroup_id;
115+
return 0;
116+
}
117+
118+
DEFINE_BPF_ITER_FUNC(cgroup, struct bpf_iter_meta *meta,
119+
struct cgroup *cgroup)
120+
121+
static struct bpf_iter_reg bpf_cgroup_reg_info = {
122+
.target = "cgroup",
123+
.attach_target = bpf_iter_attach_cgroup,
124+
.detach_target = bpf_iter_detach_cgroup,
125+
.show_fdinfo = bpf_iter_cgroup_show_fdinfo,
126+
.fill_link_info = bpf_iter_cgroup_fill_link_info,
127+
.ctx_arg_info_size = 1,
128+
.ctx_arg_info = {
129+
{ offsetof(struct bpf_iter__cgroup, cgroup),
130+
PTR_TO_BTF_ID },
131+
},
132+
.seq_info = &cgroup_iter_seq_info,
133+
};
134+
135+
static int __init bpf_cgroup_iter_init(void)
136+
{
137+
bpf_cgroup_reg_info.ctx_arg_info[0].btf_id = bpf_cgroup_btf_id[0];
138+
return bpf_iter_reg_target(&bpf_cgroup_reg_info);
139+
}
140+
141+
late_initcall(bpf_cgroup_iter_init);

tools/include/uapi/linux/bpf.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ union bpf_iter_link_info {
9191
struct {
9292
__u32 map_fd;
9393
} map;
94+
struct {
95+
__u64 cgroup_id;
96+
} cgroup;
9497
};
9598

9699
/* BPF syscall commands, see bpf(2) man-page for more details. */
@@ -5887,6 +5890,9 @@ struct bpf_link_info {
58875890
struct {
58885891
__u32 map_id;
58895892
} map;
5893+
struct {
5894+
__u64 cgroup_id;
5895+
} cgroup;
58905896
};
58915897
} iter;
58925898
struct {

0 commit comments

Comments
 (0)