Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: Add lookup_and_delete_elem for BPF_MAP_STACK_TRACE

The stacktrace map can be easily full, which will lead to failure in
obtaining the stack. In addition to increasing the size of the map,
another solution is to delete the stack_id after looking it up from
the user, so extend the existing bpf_map_lookup_and_delete_elem()
functionality to stacktrace map types.

Signed-off-by: Tao Chen <chen.dylane@linux.dev>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20250925175030.1615837-1-chen.dylane@linux.dev

authored by

Tao Chen and committed by
Andrii Nakryiko
17f0d1f6 105eb5dc

+20 -6
+1 -1
include/linux/bpf.h
··· 2724 2724 int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value, 2725 2725 u64 flags); 2726 2726 2727 - int bpf_stackmap_copy(struct bpf_map *map, void *key, void *value); 2727 + int bpf_stackmap_extract(struct bpf_map *map, void *key, void *value, bool delete); 2728 2728 2729 2729 int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file, 2730 2730 void *key, void *value, u64 map_flags);
+14 -2
kernel/bpf/stackmap.c
··· 646 646 } 647 647 648 648 /* Called from syscall */ 649 - int bpf_stackmap_copy(struct bpf_map *map, void *key, void *value) 649 + static int stack_map_lookup_and_delete_elem(struct bpf_map *map, void *key, 650 + void *value, u64 flags) 651 + { 652 + return bpf_stackmap_extract(map, key, value, true); 653 + } 654 + 655 + /* Called from syscall */ 656 + int bpf_stackmap_extract(struct bpf_map *map, void *key, void *value, 657 + bool delete) 650 658 { 651 659 struct bpf_stack_map *smap = container_of(map, struct bpf_stack_map, map); 652 660 struct stack_map_bucket *bucket, *old_bucket; ··· 671 663 memcpy(value, bucket->data, trace_len); 672 664 memset(value + trace_len, 0, map->value_size - trace_len); 673 665 674 - old_bucket = xchg(&smap->buckets[id], bucket); 666 + if (delete) 667 + old_bucket = bucket; 668 + else 669 + old_bucket = xchg(&smap->buckets[id], bucket); 675 670 if (old_bucket) 676 671 pcpu_freelist_push(&smap->freelist, &old_bucket->fnode); 677 672 return 0; ··· 765 754 .map_free = stack_map_free, 766 755 .map_get_next_key = stack_map_get_next_key, 767 756 .map_lookup_elem = stack_map_lookup_elem, 757 + .map_lookup_and_delete_elem = stack_map_lookup_and_delete_elem, 768 758 .map_update_elem = stack_map_update_elem, 769 759 .map_delete_elem = stack_map_delete_elem, 770 760 .map_check_btf = map_check_no_btf,
+5 -3
kernel/bpf/syscall.c
··· 320 320 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) { 321 321 err = bpf_percpu_cgroup_storage_copy(map, key, value); 322 322 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) { 323 - err = bpf_stackmap_copy(map, key, value); 323 + err = bpf_stackmap_extract(map, key, value, false); 324 324 } else if (IS_FD_ARRAY(map) || IS_FD_PROG_ARRAY(map)) { 325 325 err = bpf_fd_array_map_lookup_elem(map, key, value); 326 326 } else if (IS_FD_HASH(map)) { ··· 1666 1666 } 1667 1667 EXPORT_SYMBOL_GPL(bpf_map_inc_not_zero); 1668 1668 1669 - int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value) 1669 + int __weak bpf_stackmap_extract(struct bpf_map *map, void *key, void *value, 1670 + bool delete) 1670 1671 { 1671 1672 return -ENOTSUPP; 1672 1673 } ··· 2198 2197 } else if (map->map_type == BPF_MAP_TYPE_HASH || 2199 2198 map->map_type == BPF_MAP_TYPE_PERCPU_HASH || 2200 2199 map->map_type == BPF_MAP_TYPE_LRU_HASH || 2201 - map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) { 2200 + map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH || 2201 + map->map_type == BPF_MAP_TYPE_STACK_TRACE) { 2202 2202 if (!bpf_map_is_offloaded(map)) { 2203 2203 bpf_disable_instrumentation(); 2204 2204 rcu_read_lock();