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";