1f583ddf1SDavid Vernet /* SPDX-License-Identifier: GPL-2.0 */
2f583ddf1SDavid Vernet /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3f583ddf1SDavid Vernet 
4f583ddf1SDavid Vernet #ifndef _CGRP_KFUNC_COMMON_H
5f583ddf1SDavid Vernet #define _CGRP_KFUNC_COMMON_H
6f583ddf1SDavid Vernet 
7f583ddf1SDavid Vernet #include <errno.h>
8f583ddf1SDavid Vernet #include <vmlinux.h>
9f583ddf1SDavid Vernet #include <bpf/bpf_helpers.h>
10f583ddf1SDavid Vernet #include <bpf/bpf_tracing.h>
11f583ddf1SDavid Vernet 
12f583ddf1SDavid Vernet struct __cgrps_kfunc_map_value {
1303b77e17SAlexei Starovoitov 	struct cgroup __kptr * cgrp;
14f583ddf1SDavid Vernet };
15f583ddf1SDavid Vernet 
16f583ddf1SDavid Vernet struct hash_map {
17f583ddf1SDavid Vernet 	__uint(type, BPF_MAP_TYPE_HASH);
18f583ddf1SDavid Vernet 	__type(key, int);
19f583ddf1SDavid Vernet 	__type(value, struct __cgrps_kfunc_map_value);
20f583ddf1SDavid Vernet 	__uint(max_entries, 1);
21f583ddf1SDavid Vernet } __cgrps_kfunc_map SEC(".maps");
22f583ddf1SDavid Vernet 
23f583ddf1SDavid Vernet struct cgroup *bpf_cgroup_acquire(struct cgroup *p) __ksym;
24f583ddf1SDavid Vernet void bpf_cgroup_release(struct cgroup *p) __ksym;
25227a89cfSDavid Vernet struct cgroup *bpf_cgroup_ancestor(struct cgroup *cgrp, int level) __ksym;
26d0093aaeSTejun Heo struct cgroup *bpf_cgroup_from_id(u64 cgid) __ksym;
27*6499fe6eSDavid Vernet void bpf_rcu_read_lock(void) __ksym;
28*6499fe6eSDavid Vernet void bpf_rcu_read_unlock(void) __ksym;
29f583ddf1SDavid Vernet 
cgrps_kfunc_map_value_lookup(struct cgroup * cgrp)30f583ddf1SDavid Vernet static inline struct __cgrps_kfunc_map_value *cgrps_kfunc_map_value_lookup(struct cgroup *cgrp)
31f583ddf1SDavid Vernet {
32f583ddf1SDavid Vernet 	s32 id;
33f583ddf1SDavid Vernet 	long status;
34f583ddf1SDavid Vernet 
35f583ddf1SDavid Vernet 	status = bpf_probe_read_kernel(&id, sizeof(id), &cgrp->self.id);
36f583ddf1SDavid Vernet 	if (status)
37f583ddf1SDavid Vernet 		return NULL;
38f583ddf1SDavid Vernet 
39f583ddf1SDavid Vernet 	return bpf_map_lookup_elem(&__cgrps_kfunc_map, &id);
40f583ddf1SDavid Vernet }
41f583ddf1SDavid Vernet 
cgrps_kfunc_map_insert(struct cgroup * cgrp)42f583ddf1SDavid Vernet static inline int cgrps_kfunc_map_insert(struct cgroup *cgrp)
43f583ddf1SDavid Vernet {
44f583ddf1SDavid Vernet 	struct __cgrps_kfunc_map_value local, *v;
45f583ddf1SDavid Vernet 	long status;
46f583ddf1SDavid Vernet 	struct cgroup *acquired, *old;
47f583ddf1SDavid Vernet 	s32 id;
48f583ddf1SDavid Vernet 
49f583ddf1SDavid Vernet 	status = bpf_probe_read_kernel(&id, sizeof(id), &cgrp->self.id);
50f583ddf1SDavid Vernet 	if (status)
51f583ddf1SDavid Vernet 		return status;
52f583ddf1SDavid Vernet 
53f583ddf1SDavid Vernet 	local.cgrp = NULL;
54f583ddf1SDavid Vernet 	status = bpf_map_update_elem(&__cgrps_kfunc_map, &id, &local, BPF_NOEXIST);
55f583ddf1SDavid Vernet 	if (status)
56f583ddf1SDavid Vernet 		return status;
57f583ddf1SDavid Vernet 
58f583ddf1SDavid Vernet 	v = bpf_map_lookup_elem(&__cgrps_kfunc_map, &id);
59f583ddf1SDavid Vernet 	if (!v) {
60f583ddf1SDavid Vernet 		bpf_map_delete_elem(&__cgrps_kfunc_map, &id);
61f583ddf1SDavid Vernet 		return -ENOENT;
62f583ddf1SDavid Vernet 	}
63f583ddf1SDavid Vernet 
64f583ddf1SDavid Vernet 	acquired = bpf_cgroup_acquire(cgrp);
651d712839SDavid Vernet 	if (!acquired) {
661d712839SDavid Vernet 		bpf_map_delete_elem(&__cgrps_kfunc_map, &id);
671d712839SDavid Vernet 		return -ENOENT;
681d712839SDavid Vernet 	}
691d712839SDavid Vernet 
70f583ddf1SDavid Vernet 	old = bpf_kptr_xchg(&v->cgrp, acquired);
71f583ddf1SDavid Vernet 	if (old) {
72f583ddf1SDavid Vernet 		bpf_cgroup_release(old);
73f583ddf1SDavid Vernet 		return -EEXIST;
74f583ddf1SDavid Vernet 	}
75f583ddf1SDavid Vernet 
76f583ddf1SDavid Vernet 	return 0;
77f583ddf1SDavid Vernet }
78f583ddf1SDavid Vernet 
79f583ddf1SDavid Vernet #endif /* _CGRP_KFUNC_COMMON_H */
80