Move bpf_prog_stats from prog->aux into prog to avoid one extra load in critical path of program execution.
Unified · Split
| @@ -14,7 +14,6 @@ · 13 unmodified lines | |||
| 14 | #include <linux/numa.h> | 14 | #include <linux/numa.h> |
| 15 | #include <linux/mm_types.h> | 15 | #include <linux/mm_types.h> |
| 16 | #include <linux/wait.h> | 16 | #include <linux/wait.h> |
| 17 | #include <linux/u64_stats_sync.h> | ||
| 18 | #include <linux/refcount.h> | 17 | #include <linux/refcount.h> |
| 19 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
| 20 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| @@ -507,12 +506,6 @@ enum bpf_cgroup_storage_type { · 486 unmodified lines | |||
| 507 | */ | 506 | */ |
| 508 | #define MAX_BPF_FUNC_ARGS 12 | 507 | #define MAX_BPF_FUNC_ARGS 12 |
| 509 | 508 | ||
| 510 | struct bpf_prog_stats { | ||
| 511 | u64 cnt; | ||
| 512 | u64 nsecs; | ||
| 513 | struct u64_stats_sync syncp; | ||
| 514 | } __aligned(2 * sizeof(u64)); | ||
| 515 | |||
| 516 | struct btf_func_model { | 509 | struct btf_func_model { |
| 517 | u8 ret_size; | 510 | u8 ret_size; |
| 518 | u8 nr_args; | 511 | u8 nr_args; |
| @@ -845,7 +838,6 @@ struct bpf_prog_aux { · 326 unmodified lines | |||
| 845 | u32 linfo_idx; | 838 | u32 linfo_idx; |
| 846 | u32 num_exentries; | 839 | u32 num_exentries; |
| 847 | struct exception_table_entry *extable; | 840 | struct exception_table_entry *extable; |
| 848 | struct bpf_prog_stats __percpu *stats; | ||
| 849 | union { | 841 | union { |
| 850 | struct work_struct work; | 842 | struct work_struct work; |
| 851 | struct rcu_head rcu; | 843 | struct rcu_head rcu; |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | |||
| 22 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
| 23 | #include <linux/sockptr.h> | 23 | #include <linux/sockptr.h> |
| 24 | #include <crypto/sha1.h> | 24 | #include <crypto/sha1.h> |
| 25 | #include <linux/u64_stats_sync.h> | ||
| 25 | 26 | ||
| 26 | #include <net/sch_generic.h> | 27 | #include <net/sch_generic.h> |
| 27 | 28 | ||
| @@ -539,6 +540,12 @@ struct bpf_binary_header { · 511 unmodified lines | |||
| 539 | u8 image[] __aligned(BPF_IMAGE_ALIGNMENT); | 540 | u8 image[] __aligned(BPF_IMAGE_ALIGNMENT); |
| 540 | }; | 541 | }; |
| 541 | 542 | ||
| 543 | struct bpf_prog_stats { | ||
| 544 | u64 cnt; | ||
| 545 | u64 nsecs; | ||
| 546 | struct u64_stats_sync syncp; | ||
| 547 | } __aligned(2 * sizeof(u64)); | ||
| 548 | |||
| 542 | struct bpf_prog { | 549 | struct bpf_prog { |
| 543 | u16 pages; /* Number of allocated pages */ | 550 | u16 pages; /* Number of allocated pages */ |
| 544 | u16 jited:1, /* Is our filter JIT'ed? */ | 551 | u16 jited:1, /* Is our filter JIT'ed? */ |
| @@ -557,10 +564,11 @@ struct bpf_prog { · 12 unmodified lines | |||
| 557 | u32 len; /* Number of filter blocks */ | 564 | u32 len; /* Number of filter blocks */ |
| 558 | u32 jited_len; /* Size of jited insns in bytes */ | 565 | u32 jited_len; /* Size of jited insns in bytes */ |
| 559 | u8 tag[BPF_TAG_SIZE]; | 566 | u8 tag[BPF_TAG_SIZE]; |
| 560 | struct bpf_prog_aux *aux; /* Auxiliary fields */ | 567 | struct bpf_prog_stats __percpu *stats; |
| 561 | struct sock_fprog_kern *orig_prog; /* Original BPF program */ | ||
| 562 | unsigned int (*bpf_func)(const void *ctx, | 568 | unsigned int (*bpf_func)(const void *ctx, |
| 563 | const struct bpf_insn *insn); | 569 | const struct bpf_insn *insn); |
| 570 | struct bpf_prog_aux *aux; /* Auxiliary fields */ | ||
| 571 | struct sock_fprog_kern *orig_prog; /* Original BPF program */ | ||
| 564 | /* Instructions for interpreter */ | 572 | /* Instructions for interpreter */ |
| 565 | struct sock_filter insns[0]; | 573 | struct sock_filter insns[0]; |
| 566 | struct bpf_insn insnsi[]; | 574 | struct bpf_insn insnsi[]; |
| @@ -581,7 +589,7 @@ DECLARE_STATIC_KEY_FALSE(bpf_stats_enabled_key); · 14 unmodified lines | |||
| 581 | struct bpf_prog_stats *__stats; \ | 589 | struct bpf_prog_stats *__stats; \ |
| 582 | u64 __start = sched_clock(); \ | 590 | u64 __start = sched_clock(); \ |
| 583 | __ret = dfunc(ctx, (prog)->insnsi, (prog)->bpf_func); \ | 591 | __ret = dfunc(ctx, (prog)->insnsi, (prog)->bpf_func); \ |
| 584 | __stats = this_cpu_ptr(prog->aux->stats); \ | 592 | __stats = this_cpu_ptr(prog->stats); \ |
| 585 | u64_stats_update_begin(&__stats->syncp); \ | 593 | u64_stats_update_begin(&__stats->syncp); \ |
| 586 | __stats->cnt++; \ | 594 | __stats->cnt++; \ |
| 587 | __stats->nsecs += sched_clock() - __start; \ | 595 | __stats->nsecs += sched_clock() - __start; \ |
| @@ -114,8 +114,8 @@ struct bpf_prog *bpf_prog_alloc(unsigned int size, gfp_t gfp_extra_flags) · 113 unmodified lines | |||
| 114 | if (!prog) | 114 | if (!prog) |
| 115 | return NULL; | 115 | return NULL; |
| 116 | 116 | ||
| 117 | prog->aux->stats = alloc_percpu_gfp(struct bpf_prog_stats, gfp_flags); | 117 | prog->stats = alloc_percpu_gfp(struct bpf_prog_stats, gfp_flags); |
| 118 | if (!prog->aux->stats) { | 118 | if (!prog->stats) { |
| 119 | kfree(prog->aux); | 119 | kfree(prog->aux); |
| 120 | vfree(prog); | 120 | vfree(prog); |
| 121 | return NULL; | 121 | return NULL; |
| @@ -124,7 +124,7 @@ struct bpf_prog *bpf_prog_alloc(unsigned int size, gfp_t gfp_extra_flags) · 2 unmodified lines | |||
| 124 | for_each_possible_cpu(cpu) { | 124 | for_each_possible_cpu(cpu) { |
| 125 | struct bpf_prog_stats *pstats; | 125 | struct bpf_prog_stats *pstats; |
| 126 | 126 | ||
| 127 | pstats = per_cpu_ptr(prog->aux->stats, cpu); | 127 | pstats = per_cpu_ptr(prog->stats, cpu); |
| 128 | u64_stats_init(&pstats->syncp); | 128 | u64_stats_init(&pstats->syncp); |
| 129 | } | 129 | } |
| 130 | return prog; | 130 | return prog; |
| @@ -249,10 +249,10 @@ void __bpf_prog_free(struct bpf_prog *fp) · 118 unmodified lines | |||
| 249 | if (fp->aux) { | 249 | if (fp->aux) { |
| 250 | mutex_destroy(&fp->aux->used_maps_mutex); | 250 | mutex_destroy(&fp->aux->used_maps_mutex); |
| 251 | mutex_destroy(&fp->aux->dst_mutex); | 251 | mutex_destroy(&fp->aux->dst_mutex); |
| 252 | free_percpu(fp->aux->stats); | ||
| 253 | kfree(fp->aux->poke_tab); | 252 | kfree(fp->aux->poke_tab); |
| 254 | kfree(fp->aux); | 253 | kfree(fp->aux); |
| 255 | } | 254 | } |
| 255 | free_percpu(fp->stats); | ||
| 256 | vfree(fp); | 256 | vfree(fp); |
| 257 | } | 257 | } |
| 258 | 258 | ||
| @@ -1739,7 +1739,7 @@ static void bpf_prog_get_stats(const struct bpf_prog *prog, · 1738 unmodified lines | |||
| 1739 | unsigned int start; | 1739 | unsigned int start; |
| 1740 | u64 tnsecs, tcnt; | 1740 | u64 tnsecs, tcnt; |
| 1741 | 1741 | ||
| 1742 | st = per_cpu_ptr(prog->aux->stats, cpu); | 1742 | st = per_cpu_ptr(prog->stats, cpu); |
| 1743 | do { | 1743 | do { |
| 1744 | start = u64_stats_fetch_begin_irq(&st->syncp); | 1744 | start = u64_stats_fetch_begin_irq(&st->syncp); |
| 1745 | tnsecs = st->nsecs; | 1745 | tnsecs = st->nsecs; |
| @@ -412,7 +412,7 @@ void notrace __bpf_prog_exit(struct bpf_prog *prog, u64 start) · 411 unmodified lines | |||
| 412 | * Hence check that 'start' is not zero. | 412 | * Hence check that 'start' is not zero. |
| 413 | */ | 413 | */ |
| 414 | start) { | 414 | start) { |
| 415 | stats = this_cpu_ptr(prog->aux->stats); | 415 | stats = this_cpu_ptr(prog->stats); |
| 416 | u64_stats_update_begin(&stats->syncp); | 416 | u64_stats_update_begin(&stats->syncp); |
| 417 | stats->cnt++; | 417 | stats->cnt++; |
| 418 | stats->nsecs += sched_clock() - start; | 418 | stats->nsecs += sched_clock() - start; |
| @@ -11253,7 +11253,7 @@ static int jit_subprogs(struct bpf_verifier_env *env) · 11252 unmodified lines | |||
| 11253 | /* BPF_PROG_RUN doesn't call subprogs directly, | 11253 | /* BPF_PROG_RUN doesn't call subprogs directly, |
| 11254 | * hence main prog stats include the runtime of subprogs. | 11254 | * hence main prog stats include the runtime of subprogs. |
| 11255 | * subprogs don't have IDs and not reachable via prog_get_next_id | 11255 | * subprogs don't have IDs and not reachable via prog_get_next_id |
| 11256 | * func[i]->aux->stats will never be accessed and stays NULL | 11256 | * func[i]->stats will never be accessed and stays NULL |
| 11257 | */ | 11257 | */ |
| 11258 | func[i] = bpf_prog_alloc_no_stats(bpf_prog_size(len), GFP_USER); | 11258 | func[i] = bpf_prog_alloc_no_stats(bpf_prog_size(len), GFP_USER); |
| 11259 | if (!func[i]) | 11259 | if (!func[i]) |