aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/arraymap.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/arraymap.c')
-rw-r--r--kernel/bpf/arraymap.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 027107f4be53..0fd8d8f1a398 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -11,11 +11,13 @@
11 * General Public License for more details. 11 * General Public License for more details.
12 */ 12 */
13#include <linux/bpf.h> 13#include <linux/bpf.h>
14#include <linux/btf.h>
14#include <linux/err.h> 15#include <linux/err.h>
15#include <linux/slab.h> 16#include <linux/slab.h>
16#include <linux/mm.h> 17#include <linux/mm.h>
17#include <linux/filter.h> 18#include <linux/filter.h>
18#include <linux/perf_event.h> 19#include <linux/perf_event.h>
20#include <uapi/linux/btf.h>
19 21
20#include "map_in_map.h" 22#include "map_in_map.h"
21 23
@@ -336,6 +338,52 @@ static void array_map_free(struct bpf_map *map)
336 bpf_map_area_free(array); 338 bpf_map_area_free(array);
337} 339}
338 340
341static void array_map_seq_show_elem(struct bpf_map *map, void *key,
342 struct seq_file *m)
343{
344 void *value;
345
346 rcu_read_lock();
347
348 value = array_map_lookup_elem(map, key);
349 if (!value) {
350 rcu_read_unlock();
351 return;
352 }
353
354 seq_printf(m, "%u: ", *(u32 *)key);
355 btf_type_seq_show(map->btf, map->btf_value_id, value, m);
356 seq_puts(m, "\n");
357
358 rcu_read_unlock();
359}
360
361static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf,
362 u32 btf_key_id, u32 btf_value_id)
363{
364 const struct btf_type *key_type, *value_type;
365 u32 key_size, value_size;
366 u32 int_data;
367
368 key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
369 if (!key_type || BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
370 return -EINVAL;
371
372 int_data = *(u32 *)(key_type + 1);
373 /* bpf array can only take a u32 key. This check makes
374 * sure that the btf matches the attr used during map_create.
375 */
376 if (BTF_INT_BITS(int_data) != 32 || key_size != 4 ||
377 BTF_INT_OFFSET(int_data))
378 return -EINVAL;
379
380 value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
381 if (!value_type || value_size > map->value_size)
382 return -EINVAL;
383
384 return 0;
385}
386
339const struct bpf_map_ops array_map_ops = { 387const struct bpf_map_ops array_map_ops = {
340 .map_alloc_check = array_map_alloc_check, 388 .map_alloc_check = array_map_alloc_check,
341 .map_alloc = array_map_alloc, 389 .map_alloc = array_map_alloc,
@@ -345,6 +393,8 @@ const struct bpf_map_ops array_map_ops = {
345 .map_update_elem = array_map_update_elem, 393 .map_update_elem = array_map_update_elem,
346 .map_delete_elem = array_map_delete_elem, 394 .map_delete_elem = array_map_delete_elem,
347 .map_gen_lookup = array_map_gen_lookup, 395 .map_gen_lookup = array_map_gen_lookup,
396 .map_seq_show_elem = array_map_seq_show_elem,
397 .map_check_btf = array_map_check_btf,
348}; 398};
349 399
350const struct bpf_map_ops percpu_array_map_ops = { 400const struct bpf_map_ops percpu_array_map_ops = {