Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -2703,7 +2703,7 @@ int bpf_percpu_hash_update(struct bpf_map *map, void *key, void *value,
int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
u64 flags);

int bpf_stackmap_copy(struct bpf_map *map, void *key, void *value);
int bpf_stackmap_copy_and_delete(struct bpf_map *map, void *key, void *value, bool delete);

int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file,
void *key, void *value, u64 map_flags);
Expand Down
16 changes: 14 additions & 2 deletions kernel/bpf/stackmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,15 @@ static void *stack_map_lookup_elem(struct bpf_map *map, void *key)
}

/* Called from syscall */
int bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
static int stack_map_lookup_and_delete_elem(struct bpf_map *map, void *key,
void *value, u64 flags)
{
return bpf_stackmap_copy_and_delete(map, key, value, true);
}

/* Called from syscall */
int bpf_stackmap_copy_and_delete(struct bpf_map *map, void *key, void *value,
bool delete)
{
struct bpf_stack_map *smap = container_of(map, struct bpf_stack_map, map);
struct stack_map_bucket *bucket, *old_bucket;
Expand All @@ -663,7 +671,10 @@ int bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
memcpy(value, bucket->data, trace_len);
memset(value + trace_len, 0, map->value_size - trace_len);

old_bucket = xchg(&smap->buckets[id], bucket);
if (delete)
old_bucket = bucket;
else
old_bucket = xchg(&smap->buckets[id], bucket);
if (old_bucket)
pcpu_freelist_push(&smap->freelist, &old_bucket->fnode);
return 0;
Expand Down Expand Up @@ -754,6 +765,7 @@ const struct bpf_map_ops stack_trace_map_ops = {
.map_free = stack_map_free,
.map_get_next_key = stack_map_get_next_key,
.map_lookup_elem = stack_map_lookup_elem,
.map_lookup_and_delete_elem = stack_map_lookup_and_delete_elem,
.map_update_elem = stack_map_update_elem,
.map_delete_elem = stack_map_delete_elem,
.map_check_btf = map_check_no_btf,
Expand Down
8 changes: 5 additions & 3 deletions kernel/bpf/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ static int bpf_map_copy_value(struct bpf_map *map, void *key, void *value,
} else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
err = bpf_percpu_cgroup_storage_copy(map, key, value);
} else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
err = bpf_stackmap_copy(map, key, value);
err = bpf_stackmap_copy_and_delete(map, key, value, false);
} else if (IS_FD_ARRAY(map) || IS_FD_PROG_ARRAY(map)) {
err = bpf_fd_array_map_lookup_elem(map, key, value);
} else if (IS_FD_HASH(map)) {
Expand Down Expand Up @@ -1627,7 +1627,8 @@ struct bpf_map *bpf_map_inc_not_zero(struct bpf_map *map)
}
EXPORT_SYMBOL_GPL(bpf_map_inc_not_zero);

int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
int __weak bpf_stackmap_copy_and_delete(struct bpf_map *map, void *key, void *value,
bool delete)
{
return -ENOTSUPP;
}
Expand Down Expand Up @@ -2158,7 +2159,8 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
} else if (map->map_type == BPF_MAP_TYPE_HASH ||
map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_LRU_HASH ||
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
if (!bpf_map_is_offloaded(map)) {
bpf_disable_instrumentation();
rcu_read_lock();
Expand Down
18 changes: 17 additions & 1 deletion tools/testing/selftests/bpf/prog_tests/stacktrace_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@

void test_stacktrace_map(void)
{
int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd;
int control_map_fd, stackid_hmap_fd, stackmap_fd, stack_amap_fd, stack_key_map_fd;
const char *prog_name = "oncpu";
int err, prog_fd, stack_trace_len;
const char *file = "./test_stacktrace_map.bpf.o";
__u32 key, val, duration = 0;
struct bpf_program *prog;
struct bpf_object *obj;
struct bpf_link *link;
__u32 stackmap_key;
char val_buf[PERF_MAX_STACK_DEPTH *
sizeof(struct bpf_stack_build_id)];

err = bpf_prog_test_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
Expand Down Expand Up @@ -41,6 +44,10 @@ void test_stacktrace_map(void)
if (CHECK_FAIL(stack_amap_fd < 0))
goto disable_pmu;

stack_key_map_fd = bpf_find_map(__func__, obj, "stack_key_map");
if (CHECK_FAIL(stack_key_map_fd < 0))
goto disable_pmu;

/* give some time for bpf program run */
sleep(1);

Expand Down Expand Up @@ -68,6 +75,15 @@ void test_stacktrace_map(void)
"err %d errno %d\n", err, errno))
goto disable_pmu;

err = bpf_map_lookup_elem(stack_key_map_fd, &key, &stackmap_key);
if (CHECK(err, "stack_key_map lookup", "err %d errno %d\n", err, errno))
goto disable_pmu;

err = bpf_map_lookup_and_delete_elem(stackmap_fd, &stackmap_key, &val_buf);
if (CHECK(err, "stackmap lookup and detele",
"err %d errno %d\n", err, errno))
goto disable_pmu;

disable_pmu:
bpf_link__destroy(link);
close_prog:
Expand Down
12 changes: 11 additions & 1 deletion tools/testing/selftests/bpf/progs/test_stacktrace_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ struct {
__type(value, stack_trace_t);
} stack_amap SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, __u32);
__type(value, __u32);
} stack_key_map SEC(".maps");

/* taken from /sys/kernel/tracing/events/sched/sched_switch/format */
struct sched_switch_args {
unsigned long long pad;
Expand All @@ -54,7 +61,7 @@ SEC("tracepoint/sched/sched_switch")
int oncpu(struct sched_switch_args *ctx)
{
__u32 max_len = PERF_MAX_STACK_DEPTH * sizeof(__u64);
__u32 key = 0, val = 0, *value_p;
__u32 key = 0, val = 0, *value_p, stackmap_key = 0;
void *stack_p;

value_p = bpf_map_lookup_elem(&control_map, &key);
Expand All @@ -64,6 +71,9 @@ int oncpu(struct sched_switch_args *ctx)
/* The size of stackmap and stackid_hmap should be the same */
key = bpf_get_stackid(ctx, &stackmap, 0);
if ((int)key >= 0) {
val = key;
bpf_map_update_elem(&stack_key_map, &stackmap_key, &val, 0);
val = 0;
bpf_map_update_elem(&stackid_hmap, &key, &val, 0);
stack_p = bpf_map_lookup_elem(&stack_amap, &key);
if (stack_p)
Expand Down
Loading