selftests/bpf: Add a test case for bpf_cgroup_from_id()
[platform/kernel/linux-starfive.git] / tools / testing / selftests / bpf / progs / cgrp_kfunc_success.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3
4 #include <vmlinux.h>
5 #include <bpf/bpf_tracing.h>
6 #include <bpf/bpf_helpers.h>
7
8 #include "cgrp_kfunc_common.h"
9
10 char _license[] SEC("license") = "GPL";
11
12 int err, pid, invocations;
13
14 /* Prototype for all of the program trace events below:
15  *
16  * TRACE_EVENT(cgroup_mkdir,
17  *         TP_PROTO(struct cgroup *cgrp, const char *path),
18  *         TP_ARGS(cgrp, path)
19  */
20
21 static bool is_test_kfunc_task(void)
22 {
23         int cur_pid = bpf_get_current_pid_tgid() >> 32;
24         bool same = pid == cur_pid;
25
26         if (same)
27                 __sync_fetch_and_add(&invocations, 1);
28
29         return same;
30 }
31
32 SEC("tp_btf/cgroup_mkdir")
33 int BPF_PROG(test_cgrp_acquire_release_argument, struct cgroup *cgrp, const char *path)
34 {
35         struct cgroup *acquired;
36
37         if (!is_test_kfunc_task())
38                 return 0;
39
40         acquired = bpf_cgroup_acquire(cgrp);
41         bpf_cgroup_release(acquired);
42
43         return 0;
44 }
45
46 SEC("tp_btf/cgroup_mkdir")
47 int BPF_PROG(test_cgrp_acquire_leave_in_map, struct cgroup *cgrp, const char *path)
48 {
49         long status;
50
51         if (!is_test_kfunc_task())
52                 return 0;
53
54         status = cgrps_kfunc_map_insert(cgrp);
55         if (status)
56                 err = 1;
57
58         return 0;
59 }
60
61 SEC("tp_btf/cgroup_mkdir")
62 int BPF_PROG(test_cgrp_xchg_release, struct cgroup *cgrp, const char *path)
63 {
64         struct cgroup *kptr;
65         struct __cgrps_kfunc_map_value *v;
66         long status;
67
68         if (!is_test_kfunc_task())
69                 return 0;
70
71         status = cgrps_kfunc_map_insert(cgrp);
72         if (status) {
73                 err = 1;
74                 return 0;
75         }
76
77         v = cgrps_kfunc_map_value_lookup(cgrp);
78         if (!v) {
79                 err = 2;
80                 return 0;
81         }
82
83         kptr = bpf_kptr_xchg(&v->cgrp, NULL);
84         if (!kptr) {
85                 err = 3;
86                 return 0;
87         }
88
89         bpf_cgroup_release(kptr);
90
91         return 0;
92 }
93
94 SEC("tp_btf/cgroup_mkdir")
95 int BPF_PROG(test_cgrp_get_release, struct cgroup *cgrp, const char *path)
96 {
97         struct cgroup *kptr;
98         struct __cgrps_kfunc_map_value *v;
99         long status;
100
101         if (!is_test_kfunc_task())
102                 return 0;
103
104         status = cgrps_kfunc_map_insert(cgrp);
105         if (status) {
106                 err = 1;
107                 return 0;
108         }
109
110         v = cgrps_kfunc_map_value_lookup(cgrp);
111         if (!v) {
112                 err = 2;
113                 return 0;
114         }
115
116         kptr = bpf_cgroup_kptr_get(&v->cgrp);
117         if (!kptr) {
118                 err = 3;
119                 return 0;
120         }
121
122         bpf_cgroup_release(kptr);
123
124         return 0;
125 }
126
127 SEC("tp_btf/cgroup_mkdir")
128 int BPF_PROG(test_cgrp_get_ancestors, struct cgroup *cgrp, const char *path)
129 {
130         struct cgroup *self, *ancestor1, *invalid;
131
132         if (!is_test_kfunc_task())
133                 return 0;
134
135         self = bpf_cgroup_ancestor(cgrp, cgrp->level);
136         if (!self) {
137                 err = 1;
138                 return 0;
139         }
140
141         if (self->self.id != cgrp->self.id) {
142                 bpf_cgroup_release(self);
143                 err = 2;
144                 return 0;
145         }
146         bpf_cgroup_release(self);
147
148         ancestor1 = bpf_cgroup_ancestor(cgrp, cgrp->level - 1);
149         if (!ancestor1) {
150                 err = 3;
151                 return 0;
152         }
153         bpf_cgroup_release(ancestor1);
154
155         invalid = bpf_cgroup_ancestor(cgrp, 10000);
156         if (invalid) {
157                 bpf_cgroup_release(invalid);
158                 err = 4;
159                 return 0;
160         }
161
162         invalid = bpf_cgroup_ancestor(cgrp, -1);
163         if (invalid) {
164                 bpf_cgroup_release(invalid);
165                 err = 5;
166                 return 0;
167         }
168
169         return 0;
170 }
171
172 SEC("tp_btf/cgroup_mkdir")
173 int BPF_PROG(test_cgrp_from_id, struct cgroup *cgrp, const char *path)
174 {
175         struct cgroup *parent, *res;
176         u64 parent_cgid;
177
178         if (!is_test_kfunc_task())
179                 return 0;
180
181         /* @cgrp's ID is not visible yet, let's test with the parent */
182         parent = bpf_cgroup_ancestor(cgrp, cgrp->level - 1);
183         if (!parent) {
184                 err = 1;
185                 return 0;
186         }
187
188         parent_cgid = parent->kn->id;
189         bpf_cgroup_release(parent);
190
191         res = bpf_cgroup_from_id(parent_cgid);
192         if (!res) {
193                 err = 2;
194                 return 0;
195         }
196
197         bpf_cgroup_release(res);
198
199         if (res != parent) {
200                 err = 3;
201                 return 0;
202         }
203
204         res = bpf_cgroup_from_id((u64)-1);
205         if (res) {
206                 bpf_cgroup_release(res);
207                 err = 4;
208                 return 0;
209         }
210
211         return 0;
212 }