The new stackid_new_bucket allocates the new bucket and initializes it with the trace data.
Showing the changes to kernel/bpf/stackmap.c (1 of 1 file). Show all
Unified · Split
| @@ -559,31 +559,52 @@ static int stackid_fastpath(struct stackid *stackid, struct bpf_map *map, · 558 unmodified lines | ||
| 559 | 559 | return -ENOENT; |
| 560 | 560 | } |
| 561 | 561 | |
| 562 | +static struct stack_map_bucket * | |
| 563 | +stackid_new_bucket(struct stackid *stackid, struct bpf_map *map) | |
| 564 | +{ | |
| 565 | + struct bpf_stack_map *smap = container_of(map, struct bpf_stack_map, map); | |
| 566 | + struct bpf_stack_build_id *id_offs; | |
| 567 | + struct stack_map_bucket *bucket; | |
| 568 | + u32 i; | |
| 569 | + | |
| 570 | + bucket = (struct stack_map_bucket *) pcpu_freelist_pop(&smap->freelist); | |
| 571 | + if (unlikely(!bucket)) | |
| 572 | + return NULL; | |
| 573 | + | |
| 574 | + if (stack_map_use_build_id(map)) { | |
| 575 | + id_offs = (struct bpf_stack_build_id *)bucket->data; | |
| 576 | + for (i = 0; i < stackid->nr; i++) | |
| 577 | + id_offs[i].ip = stackid->ips[i]; | |
| 578 | + } else { | |
| 579 | + memcpy(bucket->data, stackid->ips, stackid->len); | |
| 580 | + } | |
| 581 | + | |
| 582 | + bucket->hash = stackid->hash; | |
| 583 | + bucket->nr = stackid->nr; | |
| 584 | + return bucket; | |
| 585 | +} | |
| 586 | + | |
| 562 | 587 | static long __bpf_get_stackid(struct stackid *stackid, struct bpf_map *map, |
| 563 | 588 | struct perf_callchain_entry *trace, u64 flags) |
| 564 | 589 | { |
| 565 | 590 | struct bpf_stack_map *smap = container_of(map, struct bpf_stack_map, map); |
| 566 | 591 | struct stack_map_bucket *new_bucket, *old_bucket; |
| 567 | 592 | bool user = flags & BPF_F_USER_STACK; |
| 568 | − u32 trace_len, i; | |
| 593 | + u32 trace_len; | |
| 569 | 594 | int err; |
| 570 | 595 | |
| 571 | 596 | err = stackid_fastpath(stackid, map, trace, flags); |
| 572 | 597 | if (err != -ENOENT) |
| 573 | 598 | return err; |
| 574 | 599 | |
| 600 | + new_bucket = stackid_new_bucket(stackid, map); | |
| 601 | + if (!new_bucket) | |
| 602 | + return -ENOMEM; | |
| 603 | + | |
| 575 | 604 | if (stack_map_use_build_id(map)) { |
| 576 | 605 | struct bpf_stack_build_id *id_offs; |
| 577 | 606 | |
| 578 | − /* for build_id+offset, pop a bucket before slow cmp */ | |
| 579 | − new_bucket = (struct stack_map_bucket *) | |
| 580 | − pcpu_freelist_pop(&smap->freelist); | |
| 581 | − if (unlikely(!new_bucket)) | |
| 582 | − return -ENOMEM; | |
| 583 | − new_bucket->nr = stackid->nr; | |
| 584 | 607 | id_offs = (struct bpf_stack_build_id *)new_bucket->data; |
| 585 | − for (i = 0; i < stackid->nr; i++) | |
| 586 | − id_offs[i].ip = stackid->ips[i]; | |
| 587 | 608 | stack_map_get_build_id_offset(id_offs, stackid->nr, user, false /* !may_fault */); |
| 588 | 609 | trace_len = stackid->nr * sizeof(struct bpf_stack_build_id); |
| 589 | 610 | if (stackid->hash_matches && stackid->bucket->nr == stackid->nr && |
| @@ -595,17 +616,8 @@ static long __bpf_get_stackid(struct stackid *stackid, struct bpf_map *map, · 5 unmodified lines | ||
| 595 | 616 | pcpu_freelist_push(&smap->freelist, &new_bucket->fnode); |
| 596 | 617 | return -EEXIST; |
| 597 | 618 | } |
| 598 | − } else { | |
| 599 | − new_bucket = (struct stack_map_bucket *) | |
| 600 | − pcpu_freelist_pop(&smap->freelist); | |
| 601 | − if (unlikely(!new_bucket)) | |
| 602 | − return -ENOMEM; | |
| 603 | − memcpy(new_bucket->data, stackid->ips, stackid->len); | |
| 604 | 619 | } |
| 605 | 620 | |
| 606 | − new_bucket->hash = stackid->hash; | |
| 607 | − new_bucket->nr = stackid->nr; | |
| 608 | − | |
| 609 | 621 | old_bucket = xchg(&smap->buckets[stackid->id], new_bucket); |
| 610 | 622 | if (old_bucket) |
| 611 | 623 | pcpu_freelist_push(&smap->freelist, &old_bucket->fnode); |