]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/bpf/arraymap.c
bpf: Add syscall lookup support for fd array and htab
[linux.git] / kernel / bpf / arraymap.c
index 172dc8ee0e3bda95c39f7e037e7a33baf8012214..d771a38725006379315cc22782efedb3775b4569 100644 (file)
@@ -334,6 +334,26 @@ static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
        return NULL;
 }
 
+/* only called from syscall */
+int bpf_fd_array_map_lookup_elem(struct bpf_map *map, void *key, u32 *value)
+{
+       void **elem, *ptr;
+       int ret =  0;
+
+       if (!map->ops->map_fd_sys_lookup_elem)
+               return -ENOTSUPP;
+
+       rcu_read_lock();
+       elem = array_map_lookup_elem(map, key);
+       if (elem && (ptr = READ_ONCE(*elem)))
+               *value = map->ops->map_fd_sys_lookup_elem(ptr);
+       else
+               ret = -ENOENT;
+       rcu_read_unlock();
+
+       return ret;
+}
+
 /* only called from syscall */
 int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file,
                                 void *key, void *value, u64 map_flags)
@@ -400,6 +420,11 @@ static void prog_fd_array_put_ptr(void *ptr)
        bpf_prog_put(ptr);
 }
 
+static u32 prog_fd_array_sys_lookup_elem(void *ptr)
+{
+       return ((struct bpf_prog *)ptr)->aux->id;
+}
+
 /* decrement refcnt of all bpf_progs that are stored in this map */
 void bpf_fd_array_map_clear(struct bpf_map *map)
 {
@@ -418,6 +443,7 @@ const struct bpf_map_ops prog_array_map_ops = {
        .map_delete_elem = fd_array_map_delete_elem,
        .map_fd_get_ptr = prog_fd_array_get_ptr,
        .map_fd_put_ptr = prog_fd_array_put_ptr,
+       .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem,
 };
 
 static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file,
@@ -452,38 +478,24 @@ static void bpf_event_entry_free_rcu(struct bpf_event_entry *ee)
 static void *perf_event_fd_array_get_ptr(struct bpf_map *map,
                                         struct file *map_file, int fd)
 {
-       const struct perf_event_attr *attr;
        struct bpf_event_entry *ee;
        struct perf_event *event;
        struct file *perf_file;
+       u64 value;
 
        perf_file = perf_event_get(fd);
        if (IS_ERR(perf_file))
                return perf_file;
 
+       ee = ERR_PTR(-EOPNOTSUPP);
        event = perf_file->private_data;
-       ee = ERR_PTR(-EINVAL);
-
-       attr = perf_event_attrs(event);
-       if (IS_ERR(attr) || attr->inherit)
+       if (perf_event_read_local(event, &value) == -EOPNOTSUPP)
                goto err_out;
 
-       switch (attr->type) {
-       case PERF_TYPE_SOFTWARE:
-               if (attr->config != PERF_COUNT_SW_BPF_OUTPUT)
-                       goto err_out;
-               /* fall-through */
-       case PERF_TYPE_RAW:
-       case PERF_TYPE_HARDWARE:
-               ee = bpf_event_entry_gen(perf_file, map_file);
-               if (ee)
-                       return ee;
-               ee = ERR_PTR(-ENOMEM);
-               /* fall-through */
-       default:
-               break;
-       }
-
+       ee = bpf_event_entry_gen(perf_file, map_file);
+       if (ee)
+               return ee;
+       ee = ERR_PTR(-ENOMEM);
 err_out:
        fput(perf_file);
        return ee;
@@ -599,4 +611,5 @@ const struct bpf_map_ops array_of_maps_map_ops = {
        .map_delete_elem = fd_array_map_delete_elem,
        .map_fd_get_ptr = bpf_map_fd_get_ptr,
        .map_fd_put_ptr = bpf_map_fd_put_ptr,
+       .map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem,
 };