cgroup: bpf: Add BPF_MAP_TYPE_CGROUP_ARRAY
authorMartin KaFai Lau <kafai@fb.com>
Thu, 30 Jun 2016 17:28:43 +0000 (10:28 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 Jul 2016 20:30:38 +0000 (16:30 -0400)
Add a BPF_MAP_TYPE_CGROUP_ARRAY and its bpf_map_ops's implementations.
To update an element, the caller is expected to obtain a cgroup2 backed
fd by open(cgroup2_dir) and then update the array with that fd.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Tejun Heo <tj@kernel.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/bpf.h
kernel/bpf/arraymap.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c

index be6ac12916808d85786f124d8dff58f5415c72f1..26c04be32003132a5866799fa42a767d22c9bc37 100644 (file)
@@ -84,6 +84,7 @@ enum bpf_map_type {
        BPF_MAP_TYPE_PERCPU_HASH,
        BPF_MAP_TYPE_PERCPU_ARRAY,
        BPF_MAP_TYPE_STACK_TRACE,
+       BPF_MAP_TYPE_CGROUP_ARRAY,
 };
 
 enum bpf_prog_type {
index 4ec57a649b1f542fbc824caada40a79bd3abbec3..db1a743e3db2bc791c6f4393e3ff565353dc4cfc 100644 (file)
@@ -537,3 +537,46 @@ static int __init register_perf_event_array_map(void)
        return 0;
 }
 late_initcall(register_perf_event_array_map);
+
+#ifdef CONFIG_SOCK_CGROUP_DATA
+static void *cgroup_fd_array_get_ptr(struct bpf_map *map,
+                                    struct file *map_file /* not used */,
+                                    int fd)
+{
+       return cgroup_get_from_fd(fd);
+}
+
+static void cgroup_fd_array_put_ptr(void *ptr)
+{
+       /* cgroup_put free cgrp after a rcu grace period */
+       cgroup_put(ptr);
+}
+
+static void cgroup_fd_array_free(struct bpf_map *map)
+{
+       bpf_fd_array_map_clear(map);
+       fd_array_map_free(map);
+}
+
+static const struct bpf_map_ops cgroup_array_ops = {
+       .map_alloc = fd_array_map_alloc,
+       .map_free = cgroup_fd_array_free,
+       .map_get_next_key = array_map_get_next_key,
+       .map_lookup_elem = fd_array_map_lookup_elem,
+       .map_delete_elem = fd_array_map_delete_elem,
+       .map_fd_get_ptr = cgroup_fd_array_get_ptr,
+       .map_fd_put_ptr = cgroup_fd_array_put_ptr,
+};
+
+static struct bpf_map_type_list cgroup_array_type __read_mostly = {
+       .ops = &cgroup_array_ops,
+       .type = BPF_MAP_TYPE_CGROUP_ARRAY,
+};
+
+static int __init register_cgroup_array_map(void)
+{
+       bpf_register_map_type(&cgroup_array_type);
+       return 0;
+}
+late_initcall(register_cgroup_array_map);
+#endif
index 22863d9872b1eda47349d208005f0ef26e02a0a1..96d938a2205016f17223e76851b6e9b4b1a881f3 100644 (file)
@@ -393,7 +393,8 @@ static int map_update_elem(union bpf_attr *attr)
        } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
                err = bpf_percpu_array_update(map, key, value, attr->flags);
        } else if (map->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY ||
-                  map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
+                  map->map_type == BPF_MAP_TYPE_PROG_ARRAY ||
+                  map->map_type == BPF_MAP_TYPE_CGROUP_ARRAY) {
                rcu_read_lock();
                err = bpf_fd_array_map_update_elem(map, f.file, key, value,
                                                   attr->flags);
index eec9f90ba030410a5104991cfcd377400cb4bb7d..69ba2251a22ba2a1c9e49c94ba7e20387d542840 100644 (file)
@@ -1035,6 +1035,8 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id)
                if (func_id != BPF_FUNC_get_stackid)
                        goto error;
                break;
+       case BPF_MAP_TYPE_CGROUP_ARRAY:
+               goto error;
        default:
                break;
        }