1*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) PLUMgrid, Inc.
2*387f9dfdSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License")
3*387f9dfdSAndroid Build Coastguard Worker #include <linux/ptrace.h>
4*387f9dfdSAndroid Build Coastguard Worker #include <linux/blkdev.h>
5*387f9dfdSAndroid Build Coastguard Worker struct Request { u64 rq; };
6*387f9dfdSAndroid Build Coastguard Worker struct Time { u64 start; };
7*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(requests, struct Request, struct Time, 1024);
8*387f9dfdSAndroid Build Coastguard Worker #define SLOTS 100
9*387f9dfdSAndroid Build Coastguard Worker BPF_ARRAY(latency, u64, SLOTS);
10*387f9dfdSAndroid Build Coastguard Worker
log2(u32 v)11*387f9dfdSAndroid Build Coastguard Worker static u32 log2(u32 v) {
12*387f9dfdSAndroid Build Coastguard Worker u32 r, shift;
13*387f9dfdSAndroid Build Coastguard Worker
14*387f9dfdSAndroid Build Coastguard Worker r = (v > 0xFFFF) << 4; v >>= r;
15*387f9dfdSAndroid Build Coastguard Worker shift = (v > 0xFF) << 3; v >>= shift; r |= shift;
16*387f9dfdSAndroid Build Coastguard Worker shift = (v > 0xF) << 2; v >>= shift; r |= shift;
17*387f9dfdSAndroid Build Coastguard Worker shift = (v > 0x3) << 1; v >>= shift; r |= shift;
18*387f9dfdSAndroid Build Coastguard Worker r |= (v >> 1);
19*387f9dfdSAndroid Build Coastguard Worker return r;
20*387f9dfdSAndroid Build Coastguard Worker }
21*387f9dfdSAndroid Build Coastguard Worker
log2l(u64 v)22*387f9dfdSAndroid Build Coastguard Worker static u32 log2l(u64 v) {
23*387f9dfdSAndroid Build Coastguard Worker u32 hi = v >> 32;
24*387f9dfdSAndroid Build Coastguard Worker if (hi)
25*387f9dfdSAndroid Build Coastguard Worker return log2(hi) + 32;
26*387f9dfdSAndroid Build Coastguard Worker else
27*387f9dfdSAndroid Build Coastguard Worker return log2(v);
28*387f9dfdSAndroid Build Coastguard Worker }
29*387f9dfdSAndroid Build Coastguard Worker
probe_blk_start_request(struct pt_regs * ctx)30*387f9dfdSAndroid Build Coastguard Worker int probe_blk_start_request(struct pt_regs *ctx) {
31*387f9dfdSAndroid Build Coastguard Worker struct Request rq = {.rq = PT_REGS_PARM1(ctx)};
32*387f9dfdSAndroid Build Coastguard Worker struct Time tm = {.start = bpf_ktime_get_ns()};
33*387f9dfdSAndroid Build Coastguard Worker requests.update(&rq, &tm);
34*387f9dfdSAndroid Build Coastguard Worker return 0;
35*387f9dfdSAndroid Build Coastguard Worker }
36*387f9dfdSAndroid Build Coastguard Worker
probe_blk_update_request(struct pt_regs * ctx)37*387f9dfdSAndroid Build Coastguard Worker int probe_blk_update_request(struct pt_regs *ctx) {
38*387f9dfdSAndroid Build Coastguard Worker struct Request rq = {.rq = PT_REGS_PARM1(ctx)};
39*387f9dfdSAndroid Build Coastguard Worker struct Time *tm = requests.lookup(&rq);
40*387f9dfdSAndroid Build Coastguard Worker if (!tm) return 0;
41*387f9dfdSAndroid Build Coastguard Worker u64 delta = bpf_ktime_get_ns() - tm->start;
42*387f9dfdSAndroid Build Coastguard Worker requests.delete(&rq);
43*387f9dfdSAndroid Build Coastguard Worker u64 lg = log2l(delta);
44*387f9dfdSAndroid Build Coastguard Worker u64 base = 1ull << lg;
45*387f9dfdSAndroid Build Coastguard Worker u32 index = (lg * 64 + (delta - base) * 64 / base) * 3 / 64;
46*387f9dfdSAndroid Build Coastguard Worker if (index >= SLOTS)
47*387f9dfdSAndroid Build Coastguard Worker index = SLOTS - 1;
48*387f9dfdSAndroid Build Coastguard Worker
49*387f9dfdSAndroid Build Coastguard Worker u64 zero = 0;
50*387f9dfdSAndroid Build Coastguard Worker u64 *val = latency.lookup_or_try_init(&index, &zero);
51*387f9dfdSAndroid Build Coastguard Worker if (val) {
52*387f9dfdSAndroid Build Coastguard Worker lock_xadd(val, 1);
53*387f9dfdSAndroid Build Coastguard Worker }
54*387f9dfdSAndroid Build Coastguard Worker return 0;
55*387f9dfdSAndroid Build Coastguard Worker }
56