src/samplers/ext4/bpf.c (68 lines of code) (raw):

// Based on: https://github.com/iovisor/bcc/blob/master/tools/ext4dist.py #include <uapi/linux/ptrace.h> #include <linux/fs.h> #include <linux/sched.h> #define OP_NAME_LEN 8 typedef struct dist_key { char op[OP_NAME_LEN]; u64 slot; } dist_key_t; BPF_HASH(start, u32); // value_to_index2() gives us from 0-460 as the index BPF_HISTOGRAM(read, int, 461); BPF_HISTOGRAM(write, int, 461); BPF_HISTOGRAM(open, int, 461); BPF_HISTOGRAM(fsync, int, 461); VALUE_TO_INDEX2_FUNC int trace_entry(struct pt_regs *ctx) { u32 pid = bpf_get_current_pid_tgid(); u64 ts = bpf_ktime_get_ns(); start.update(&pid, &ts); return 0; } int trace_read_entry(struct pt_regs *ctx, struct kiocb *iocb) { u32 pid = bpf_get_current_pid_tgid(); struct file *fp = iocb->ki_filp; if ((u64)fp->f_op == EXT4_FILE_OPERATIONS) return 0; u64 ts = bpf_ktime_get_ns(); start.update(&pid, &ts); return 0; } static int trace_return(struct pt_regs *ctx, int op) { // get pid u32 pid = bpf_get_current_pid_tgid(); // lookup start u64 *tsp = start.lookup(&pid); // skip events with unknown start if (tsp == 0) { return 0; } // calculate latency u64 delta = (bpf_ktime_get_ns() - *tsp) / 1000; // store as histogram unsigned int index = value_to_index2(delta); if (op == 0) { read.increment(index); } else if (op == 1) { write.increment(index); } else if (op == 2) { open.increment(index); } else if (op == 3) { fsync.increment(index); } // clear the start entry from the map start.delete(&pid); return 0; } int trace_read_return(struct pt_regs *ctx) { return trace_return(ctx, 0); } int trace_write_return(struct pt_regs *ctx) { return trace_return(ctx, 1); } int trace_open_return(struct pt_regs *ctx) { return trace_return(ctx, 2); } int trace_fsync_return(struct pt_regs *ctx) { return trace_return(ctx, 3); }