bpf/tracebiolatency.c (73 lines of code) (raw):

/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ // +build ignore #include <vmlinux.h> #include <bpf_helpers.h> #include <bpf_tracing.h> #include <bpf_core_read.h> #include <inspector.h> struct insp_biolat_metric_t { u32 pid; u32 bucket; }; struct insp_biolat_event_t { char target[TASK_COMM_LEN]; char disk[TASK_COMM_LEN]; u32 pid; u64 latency; }; struct insp_biolat_entry_t { char target[TASK_COMM_LEN]; char disk[TASK_COMM_LEN]; u32 pid; u64 start; u64 latency; }__attribute__((packed)); struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, struct request *); __type(value, struct insp_biolat_entry_t ); __uint(max_entries, 10000); } insp_biolat_metric SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, struct request *); __type(value, struct insp_biolat_entry_t ); __uint(max_entries, 10000); } insp_biolat_entry SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(key_size, sizeof(u32)); __uint(value_size, sizeof(u32)); } insp_biolat_evts SEC(".maps"); struct insp_biolat_event_t *unused_event __attribute__((unused)); SEC("kprobe/blk_account_io_start") int biolat_start(struct pt_regs *ctx) { struct request * rq = (struct request *)PT_REGS_PARM1(ctx); struct insp_biolat_entry_t et = {0}; et.pid = bpf_get_current_pid_tgid()>> 32; et.start = bpf_ktime_get_ns(); // bpf_printk("now %llu\n",et.start); // void * __tmp = (void *)rq->rq_disk->disk_name; // bpf_probe_read(&et.disk, sizeof(et.disk), __tmp); bpf_get_current_comm(&et.target, sizeof(et.target)); bpf_map_update_elem(&insp_biolat_entry,&rq,&et,0); return 0; } SEC("kprobe/blk_account_io_done") int biolat_finish(struct pt_regs *ctx) { struct request * rq = (struct request *)PT_REGS_PARM1(ctx); struct insp_biolat_entry_t * biot = bpf_map_lookup_elem(&insp_biolat_entry, &rq); if (biot){ u64 now = bpf_ktime_get_ns(); u64 latency; latency = now - biot->start; if (latency > 10000000){ bpf_printk("now %llu start %llu latency %llu\n",now,biot->start,latency); struct insp_biolat_event_t event = {0}; event.latency = latency; event.pid = biot->pid; bpf_probe_read(&event.target,sizeof(event.target),&biot->target); bpf_perf_event_output(ctx, &insp_biolat_evts, BPF_F_CURRENT_CPU, &event, sizeof(event)); } bpf_map_delete_elem(&insp_biolat_entry, &rq); } return 0; } char LICENSE[] SEC("license") = "Dual BSD/GPL";