]>
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> | |
11 | #include "bpf_helpers.h" | |
12 | ||
13 | struct bpf_map_def SEC("maps") my_map = { | |
14 | .type = BPF_MAP_TYPE_HASH, | |
15 | .key_size = sizeof(long), | |
16 | .value_size = sizeof(u64), | |
17 | .max_entries = 4096, | |
18 | }; | |
19 | ||
20 | /* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe | |
21 | * example will no longer be meaningful | |
22 | */ | |
3059303f | 23 | SEC("kprobe/blk_start_request") |
5c7fc2d2 AS |
24 | int bpf_prog1(struct pt_regs *ctx) |
25 | { | |
d912557b | 26 | long rq = PT_REGS_PARM1(ctx); |
5c7fc2d2 AS |
27 | u64 val = bpf_ktime_get_ns(); |
28 | ||
29 | bpf_map_update_elem(&my_map, &rq, &val, BPF_ANY); | |
30 | return 0; | |
31 | } | |
32 | ||
33 | static unsigned int log2l(unsigned long long n) | |
34 | { | |
35 | #define S(k) if (n >= (1ull << k)) { i += k; n >>= k; } | |
36 | int i = -(n == 0); | |
37 | S(32); S(16); S(8); S(4); S(2); S(1); | |
38 | return i; | |
39 | #undef S | |
40 | } | |
41 | ||
42 | #define SLOTS 100 | |
43 | ||
44 | struct bpf_map_def SEC("maps") lat_map = { | |
3059303f | 45 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, |
5c7fc2d2 AS |
46 | .key_size = sizeof(u32), |
47 | .value_size = sizeof(u64), | |
48 | .max_entries = SLOTS, | |
49 | }; | |
50 | ||
3059303f | 51 | SEC("kprobe/blk_account_io_completion") |
5c7fc2d2 AS |
52 | int bpf_prog2(struct pt_regs *ctx) |
53 | { | |
d912557b | 54 | long rq = PT_REGS_PARM1(ctx); |
5c7fc2d2 AS |
55 | u64 *value, l, base; |
56 | u32 index; | |
57 | ||
58 | value = bpf_map_lookup_elem(&my_map, &rq); | |
59 | if (!value) | |
60 | return 0; | |
61 | ||
62 | u64 cur_time = bpf_ktime_get_ns(); | |
63 | u64 delta = cur_time - *value; | |
64 | ||
65 | bpf_map_delete_elem(&my_map, &rq); | |
66 | ||
67 | /* the lines below are computing index = log10(delta)*10 | |
68 | * using integer arithmetic | |
69 | * index = 29 ~ 1 usec | |
70 | * index = 59 ~ 1 msec | |
71 | * index = 89 ~ 1 sec | |
72 | * index = 99 ~ 10sec or more | |
73 | * log10(x)*10 = log2(x)*10/log2(10) = log2(x)*3 | |
74 | */ | |
75 | l = log2l(delta); | |
76 | base = 1ll << l; | |
77 | index = (l * 64 + (delta - base) * 64 / base) * 3 / 64; | |
78 | ||
79 | if (index >= SLOTS) | |
80 | index = SLOTS - 1; | |
81 | ||
82 | value = bpf_map_lookup_elem(&lat_map, &index); | |
83 | if (value) | |
3059303f | 84 | *value += 1; |
5c7fc2d2 AS |
85 | |
86 | return 0; | |
87 | } | |
88 | char _license[] SEC("license") = "GPL"; | |
89 | u32 _version SEC("version") = LINUX_VERSION_CODE; |