]>
Commit | Line | Data |
---|---|---|
5c7fc2d2 AS |
1 | /* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com |
2 | * | |
3 | * This program is free software; you can redistribute it and/or | |
4 | * modify it under the terms of version 2 of the GNU General Public | |
5 | * License as published by the Free Software Foundation. | |
6 | */ | |
7 | #include <linux/skbuff.h> | |
8 | #include <linux/netdevice.h> | |
9 | #include <linux/version.h> | |
10 | #include <uapi/linux/bpf.h> | |
7cf245a3 THJ |
11 | #include <bpf/bpf_helpers.h> |
12 | #include <bpf/bpf_tracing.h> | |
5c7fc2d2 | 13 | |
59929cd1 DL |
14 | struct { |
15 | __uint(type, BPF_MAP_TYPE_HASH); | |
16 | __type(key, long); | |
17 | __type(value, u64); | |
18 | __uint(max_entries, 4096); | |
19 | } my_map SEC(".maps"); | |
5c7fc2d2 AS |
20 | |
21 | /* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe | |
22 | * example will no longer be meaningful | |
23 | */ | |
d2e614cb | 24 | SEC("kprobe/blk_mq_start_request") |
5c7fc2d2 AS |
25 | int bpf_prog1(struct pt_regs *ctx) |
26 | { | |
d912557b | 27 | long rq = PT_REGS_PARM1(ctx); |
5c7fc2d2 AS |
28 | u64 val = bpf_ktime_get_ns(); |
29 | ||
30 | bpf_map_update_elem(&my_map, &rq, &val, BPF_ANY); | |
31 | return 0; | |
32 | } | |
33 | ||
34 | static unsigned int log2l(unsigned long long n) | |
35 | { | |
36 | #define S(k) if (n >= (1ull << k)) { i += k; n >>= k; } | |
37 | int i = -(n == 0); | |
38 | S(32); S(16); S(8); S(4); S(2); S(1); | |
39 | return i; | |
40 | #undef S | |
41 | } | |
42 | ||
43 | #define SLOTS 100 | |
44 | ||
59929cd1 DL |
45 | struct { |
46 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); | |
47 | __uint(key_size, sizeof(u32)); | |
48 | __uint(value_size, sizeof(u64)); | |
49 | __uint(max_entries, SLOTS); | |
50 | } lat_map SEC(".maps"); | |
5c7fc2d2 | 51 | |
bc069da6 | 52 | SEC("kprobe/__blk_account_io_done") |
5c7fc2d2 AS |
53 | int bpf_prog2(struct pt_regs *ctx) |
54 | { | |
d912557b | 55 | long rq = PT_REGS_PARM1(ctx); |
5c7fc2d2 AS |
56 | u64 *value, l, base; |
57 | u32 index; | |
58 | ||
59 | value = bpf_map_lookup_elem(&my_map, &rq); | |
60 | if (!value) | |
61 | return 0; | |
62 | ||
63 | u64 cur_time = bpf_ktime_get_ns(); | |
64 | u64 delta = cur_time - *value; | |
65 | ||
66 | bpf_map_delete_elem(&my_map, &rq); | |
67 | ||
68 | /* the lines below are computing index = log10(delta)*10 | |
69 | * using integer arithmetic | |
70 | * index = 29 ~ 1 usec | |
71 | * index = 59 ~ 1 msec | |
72 | * index = 89 ~ 1 sec | |
73 | * index = 99 ~ 10sec or more | |
74 | * log10(x)*10 = log2(x)*10/log2(10) = log2(x)*3 | |
75 | */ | |
76 | l = log2l(delta); | |
77 | base = 1ll << l; | |
78 | index = (l * 64 + (delta - base) * 64 / base) * 3 / 64; | |
79 | ||
80 | if (index >= SLOTS) | |
81 | index = SLOTS - 1; | |
82 | ||
83 | value = bpf_map_lookup_elem(&lat_map, &index); | |
84 | if (value) | |
3059303f | 85 | *value += 1; |
5c7fc2d2 AS |
86 | |
87 | return 0; | |
88 | } | |
89 | char _license[] SEC("license") = "GPL"; | |
90 | u32 _version SEC("version") = LINUX_VERSION_CODE; |