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.c56
1 files changed, 35 insertions, 21 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 5e00b2333c26..d771a3872500 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -86,6 +86,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
86 array->map.key_size = attr->key_size; 86 array->map.key_size = attr->key_size;
87 array->map.value_size = attr->value_size; 87 array->map.value_size = attr->value_size;
88 array->map.max_entries = attr->max_entries; 88 array->map.max_entries = attr->max_entries;
89 array->map.map_flags = attr->map_flags;
89 array->elem_size = elem_size; 90 array->elem_size = elem_size;
90 91
91 if (!percpu) 92 if (!percpu)
@@ -334,6 +335,26 @@ static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
334} 335}
335 336
336/* only called from syscall */ 337/* only called from syscall */
338int bpf_fd_array_map_lookup_elem(struct bpf_map *map, void *key, u32 *value)
339{
340 void **elem, *ptr;
341 int ret = 0;
342
343 if (!map->ops->map_fd_sys_lookup_elem)
344 return -ENOTSUPP;
345
346 rcu_read_lock();
347 elem = array_map_lookup_elem(map, key);
348 if (elem && (ptr = READ_ONCE(*elem)))
349 *value = map->ops->map_fd_sys_lookup_elem(ptr);
350 else
351 ret = -ENOENT;
352 rcu_read_unlock();
353
354 return ret;
355}
356
357/* only called from syscall */
337int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file, 358int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file,
338 void *key, void *value, u64 map_flags) 359 void *key, void *value, u64 map_flags)
339{ 360{
@@ -399,6 +420,11 @@ static void prog_fd_array_put_ptr(void *ptr)
399 bpf_prog_put(ptr); 420 bpf_prog_put(ptr);
400} 421}
401 422
423static u32 prog_fd_array_sys_lookup_elem(void *ptr)
424{
425 return ((struct bpf_prog *)ptr)->aux->id;
426}
427
402/* decrement refcnt of all bpf_progs that are stored in this map */ 428/* decrement refcnt of all bpf_progs that are stored in this map */
403void bpf_fd_array_map_clear(struct bpf_map *map) 429void bpf_fd_array_map_clear(struct bpf_map *map)
404{ 430{
@@ -417,6 +443,7 @@ const struct bpf_map_ops prog_array_map_ops = {
417 .map_delete_elem = fd_array_map_delete_elem, 443 .map_delete_elem = fd_array_map_delete_elem,
418 .map_fd_get_ptr = prog_fd_array_get_ptr, 444 .map_fd_get_ptr = prog_fd_array_get_ptr,
419 .map_fd_put_ptr = prog_fd_array_put_ptr, 445 .map_fd_put_ptr = prog_fd_array_put_ptr,
446 .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem,
420}; 447};
421 448
422static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file, 449static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file,
@@ -451,38 +478,24 @@ static void bpf_event_entry_free_rcu(struct bpf_event_entry *ee)
451static void *perf_event_fd_array_get_ptr(struct bpf_map *map, 478static void *perf_event_fd_array_get_ptr(struct bpf_map *map,
452 struct file *map_file, int fd) 479 struct file *map_file, int fd)
453{ 480{
454 const struct perf_event_attr *attr;
455 struct bpf_event_entry *ee; 481 struct bpf_event_entry *ee;
456 struct perf_event *event; 482 struct perf_event *event;
457 struct file *perf_file; 483 struct file *perf_file;
484 u64 value;
458 485
459 perf_file = perf_event_get(fd); 486 perf_file = perf_event_get(fd);
460 if (IS_ERR(perf_file)) 487 if (IS_ERR(perf_file))
461 return perf_file; 488 return perf_file;
462 489
490 ee = ERR_PTR(-EOPNOTSUPP);
463 event = perf_file->private_data; 491 event = perf_file->private_data;
464 ee = ERR_PTR(-EINVAL); 492 if (perf_event_read_local(event, &value) == -EOPNOTSUPP)
465
466 attr = perf_event_attrs(event);
467 if (IS_ERR(attr) || attr->inherit)
468 goto err_out; 493 goto err_out;
469 494
470 switch (attr->type) { 495 ee = bpf_event_entry_gen(perf_file, map_file);
471 case PERF_TYPE_SOFTWARE: 496 if (ee)
472 if (attr->config != PERF_COUNT_SW_BPF_OUTPUT) 497 return ee;
473 goto err_out; 498 ee = ERR_PTR(-ENOMEM);
474 /* fall-through */
475 case PERF_TYPE_RAW:
476 case PERF_TYPE_HARDWARE:
477 ee = bpf_event_entry_gen(perf_file, map_file);
478 if (ee)
479 return ee;
480 ee = ERR_PTR(-ENOMEM);
481 /* fall-through */
482 default:
483 break;
484 }
485
486err_out: 499err_out:
487 fput(perf_file); 500 fput(perf_file);
488 return ee; 501 return ee;
@@ -598,4 +611,5 @@ const struct bpf_map_ops array_of_maps_map_ops = {
598 .map_delete_elem = fd_array_map_delete_elem, 611 .map_delete_elem = fd_array_map_delete_elem,
599 .map_fd_get_ptr = bpf_map_fd_get_ptr, 612 .map_fd_get_ptr = bpf_map_fd_get_ptr,
600 .map_fd_put_ptr = bpf_map_fd_put_ptr, 613 .map_fd_put_ptr = bpf_map_fd_put_ptr,
614 .map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem,
601}; 615};