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.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 4d7d5d0ed76a..bc9da93db403 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -17,6 +17,8 @@
17#include <linux/filter.h> 17#include <linux/filter.h>
18#include <linux/perf_event.h> 18#include <linux/perf_event.h>
19 19
20#include "map_in_map.h"
21
20static void bpf_array_free_percpu(struct bpf_array *array) 22static void bpf_array_free_percpu(struct bpf_array *array)
21{ 23{
22 int i; 24 int i;
@@ -602,3 +604,64 @@ static int __init register_cgroup_array_map(void)
602} 604}
603late_initcall(register_cgroup_array_map); 605late_initcall(register_cgroup_array_map);
604#endif 606#endif
607
608static struct bpf_map *array_of_map_alloc(union bpf_attr *attr)
609{
610 struct bpf_map *map, *inner_map_meta;
611
612 inner_map_meta = bpf_map_meta_alloc(attr->inner_map_fd);
613 if (IS_ERR(inner_map_meta))
614 return inner_map_meta;
615
616 map = fd_array_map_alloc(attr);
617 if (IS_ERR(map)) {
618 bpf_map_meta_free(inner_map_meta);
619 return map;
620 }
621
622 map->inner_map_meta = inner_map_meta;
623
624 return map;
625}
626
627static void array_of_map_free(struct bpf_map *map)
628{
629 /* map->inner_map_meta is only accessed by syscall which
630 * is protected by fdget/fdput.
631 */
632 bpf_map_meta_free(map->inner_map_meta);
633 bpf_fd_array_map_clear(map);
634 fd_array_map_free(map);
635}
636
637static void *array_of_map_lookup_elem(struct bpf_map *map, void *key)
638{
639 struct bpf_map **inner_map = array_map_lookup_elem(map, key);
640
641 if (!inner_map)
642 return NULL;
643
644 return READ_ONCE(*inner_map);
645}
646
647static const struct bpf_map_ops array_of_map_ops = {
648 .map_alloc = array_of_map_alloc,
649 .map_free = array_of_map_free,
650 .map_get_next_key = array_map_get_next_key,
651 .map_lookup_elem = array_of_map_lookup_elem,
652 .map_delete_elem = fd_array_map_delete_elem,
653 .map_fd_get_ptr = bpf_map_fd_get_ptr,
654 .map_fd_put_ptr = bpf_map_fd_put_ptr,
655};
656
657static struct bpf_map_type_list array_of_map_type __ro_after_init = {
658 .ops = &array_of_map_ops,
659 .type = BPF_MAP_TYPE_ARRAY_OF_MAPS,
660};
661
662static int __init register_array_of_map(void)
663{
664 bpf_register_map_type(&array_of_map_type);
665 return 0;
666}
667late_initcall(register_array_of_map);