|
4 | 4 | #include <linux/slab.h>
|
5 | 5 | #include <linux/bpf.h>
|
6 | 6 | #include <linux/btf.h>
|
| 7 | +#include <linux/rcupdate.h> |
7 | 8 |
|
8 | 9 | #include "map_in_map.h"
|
9 | 10 |
|
@@ -139,3 +140,53 @@ u32 bpf_map_fd_sys_lookup_elem(void *ptr)
|
139 | 140 | {
|
140 | 141 | return ((struct bpf_map *)ptr)->id;
|
141 | 142 | }
|
| 143 | + |
| 144 | +void *bpf_map_of_map_fd_get_ptr(struct bpf_map *map, struct file *map_file, |
| 145 | + int ufd) |
| 146 | +{ |
| 147 | + struct bpf_inner_map_element *element; |
| 148 | + struct bpf_map *inner_map; |
| 149 | + |
| 150 | + element = kmalloc(sizeof(*element), GFP_KERNEL); |
| 151 | + if (!element) |
| 152 | + return ERR_PTR(-ENOMEM); |
| 153 | + |
| 154 | + inner_map = bpf_map_fd_get_ptr(map, map_file, ufd); |
| 155 | + if (IS_ERR(inner_map)) { |
| 156 | + kfree(element); |
| 157 | + return inner_map; |
| 158 | + } |
| 159 | + |
| 160 | + element->map = inner_map; |
| 161 | + return element; |
| 162 | +} |
| 163 | + |
| 164 | +static void bpf_inner_map_element_free_rcu(struct rcu_head *rcu) |
| 165 | +{ |
| 166 | + struct bpf_inner_map_element *elem = container_of(rcu, struct bpf_inner_map_element, rcu); |
| 167 | + |
| 168 | + bpf_map_put(elem->map); |
| 169 | + kfree(elem); |
| 170 | +} |
| 171 | + |
| 172 | +static void bpf_inner_map_element_free_tt_rcu(struct rcu_head *rcu) |
| 173 | +{ |
| 174 | + if (rcu_trace_implies_rcu_gp()) |
| 175 | + bpf_inner_map_element_free_rcu(rcu); |
| 176 | + else |
| 177 | + call_rcu(rcu, bpf_inner_map_element_free_rcu); |
| 178 | +} |
| 179 | + |
| 180 | +void bpf_map_of_map_fd_put_ptr(void *ptr, bool need_defer) |
| 181 | +{ |
| 182 | + struct bpf_inner_map_element *element = ptr; |
| 183 | + |
| 184 | + /* Do bpf_map_put() after a RCU grace period and a tasks trace |
| 185 | + * RCU grace period, so it is certain that the bpf program which is |
| 186 | + * manipulating the map now has exited when bpf_map_put() is called. |
| 187 | + */ |
| 188 | + if (need_defer) |
| 189 | + call_rcu_tasks_trace(&element->rcu, bpf_inner_map_element_free_tt_rcu); |
| 190 | + else |
| 191 | + bpf_inner_map_element_free_rcu(&element->rcu); |
| 192 | +} |
0 commit comments