github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadgets/top/block-io/tracer/bpf/biotop.bpf.c (about) 1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2022 Francis Laniel <flaniel@linux.microsoft.com> 3 #include <vmlinux.h> 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_core_read.h> 6 #include <bpf/bpf_tracing.h> 7 8 #include "biotop.h" 9 #include <gadget/maps.bpf.h> 10 #include <gadget/core_fixes.bpf.h> 11 #include <gadget/mntns_filter.h> 12 13 struct { 14 __uint(type, BPF_MAP_TYPE_HASH); 15 __uint(max_entries, 10240); 16 __type(key, struct request *); 17 __type(value, struct start_req_t); 18 } start SEC(".maps"); 19 20 struct { 21 __uint(type, BPF_MAP_TYPE_HASH); 22 __uint(max_entries, 10240); 23 __type(key, struct request *); 24 __type(value, struct who_t); 25 } whobyreq SEC(".maps"); 26 27 struct { 28 __uint(type, BPF_MAP_TYPE_HASH); 29 __uint(max_entries, 10240); 30 __type(key, struct info_t); 31 __type(value, struct val_t); 32 } counts SEC(".maps"); 33 34 SEC("kprobe/blk_account_io_start") 35 int BPF_KPROBE(ig_topio_start, struct request *req) 36 { 37 u64 mntns_id; 38 39 mntns_id = gadget_get_mntns_id(); 40 41 if (gadget_should_discard_mntns_id(mntns_id)) 42 return 0; 43 44 struct who_t who = {}; 45 46 // cache PID and comm by-req 47 bpf_get_current_comm(&who.name, sizeof(who.name)); 48 who.pid = bpf_get_current_pid_tgid() >> 32; 49 who.mntnsid = mntns_id; 50 bpf_map_update_elem(&whobyreq, &req, &who, 0); 51 52 return 0; 53 } 54 55 SEC("kprobe/blk_mq_start_request") 56 int BPF_KPROBE(ig_topio_req, struct request *req) 57 { 58 /* time block I/O */ 59 struct start_req_t start_req; 60 u64 mntns_id; 61 62 mntns_id = gadget_get_mntns_id(); 63 64 if (gadget_should_discard_mntns_id(mntns_id)) 65 return 0; 66 67 start_req.ts = bpf_ktime_get_ns(); 68 start_req.data_len = BPF_CORE_READ(req, __data_len); 69 70 bpf_map_update_elem(&start, &req, &start_req, 0); 71 return 0; 72 } 73 74 SEC("kprobe/blk_account_io_done") 75 int BPF_KPROBE(ig_topio_done, struct request *req, u64 now) 76 { 77 struct val_t *valp, zero = {}; 78 struct info_t info = {}; 79 80 struct start_req_t *startp; 81 unsigned int cmd_flags; 82 struct gendisk *disk; 83 struct who_t *whop; 84 u64 delta_us; 85 86 /* fetch timestamp and calculate delta */ 87 startp = bpf_map_lookup_elem(&start, &req); 88 if (!startp) 89 return 0; /* missed tracing issue */ 90 91 delta_us = (bpf_ktime_get_ns() - startp->ts) / 1000; 92 93 /* setup info_t key */ 94 cmd_flags = BPF_CORE_READ(req, cmd_flags); 95 96 disk = get_disk(req); 97 info.major = BPF_CORE_READ(disk, major); 98 info.minor = BPF_CORE_READ(disk, first_minor); 99 info.rwflag = !!((cmd_flags & REQ_OP_MASK) == REQ_OP_WRITE); 100 101 whop = bpf_map_lookup_elem(&whobyreq, &req); 102 if (whop) { 103 info.pid = whop->pid; 104 info.mntnsid = whop->mntnsid; 105 __builtin_memcpy(&info.name, whop->name, sizeof(info.name)); 106 } 107 108 valp = bpf_map_lookup_or_try_init(&counts, &info, &zero); 109 110 if (valp) { 111 /* save stats */ 112 valp->us += delta_us; 113 valp->bytes += startp->data_len; 114 valp->io++; 115 } 116 117 bpf_map_delete_elem(&start, &req); 118 bpf_map_delete_elem(&whobyreq, &req); 119 120 return 0; 121 } 122 123 char LICENSE[] SEC("license") = "GPL";