github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadgets/top/file/tracer/bpf/filetop.bpf.c (about)

     1  /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
     2  /* Copyright (c) 2021 Hengqi Chen */
     3  #include <vmlinux.h>
     4  #include <bpf/bpf_helpers.h>
     5  #include <bpf/bpf_core_read.h>
     6  #include <bpf/bpf_tracing.h>
     7  #include "filetop.h"
     8  #include "stat.h"
     9  #include <gadget/mntns_filter.h>
    10  
    11  #define MAX_ENTRIES 10240
    12  
    13  const volatile pid_t target_pid = 0;
    14  const volatile bool regular_file_only = true;
    15  static struct file_stat zero_value = {};
    16  
    17  struct {
    18  	__uint(type, BPF_MAP_TYPE_HASH);
    19  	__uint(max_entries, MAX_ENTRIES);
    20  	__type(key, struct file_id);
    21  	__type(value, struct file_stat);
    22  } entries SEC(".maps");
    23  
    24  static void get_file_path(struct file *file, __u8 *buf, size_t size)
    25  {
    26  	struct qstr dname;
    27  
    28  	dname = BPF_CORE_READ(file, f_path.dentry, d_name);
    29  	bpf_probe_read_kernel(buf, size, dname.name);
    30  }
    31  
    32  static int probe_entry(struct pt_regs *ctx, struct file *file, size_t count,
    33  		       enum op op)
    34  {
    35  	__u64 pid_tgid = bpf_get_current_pid_tgid();
    36  	__u32 pid = pid_tgid >> 32;
    37  	__u32 tid = (__u32)pid_tgid;
    38  	int mode;
    39  	struct file_id key = {};
    40  	struct file_stat *valuep;
    41  	u64 mntns_id;
    42  
    43  	if (target_pid && target_pid != pid)
    44  		return 0;
    45  
    46  	mntns_id = gadget_get_mntns_id();
    47  
    48  	if (gadget_should_discard_mntns_id(mntns_id))
    49  		return 0;
    50  
    51  	mode = BPF_CORE_READ(file, f_inode, i_mode);
    52  	if (regular_file_only && !S_ISREG(mode))
    53  		return 0;
    54  
    55  	key.dev = BPF_CORE_READ(file, f_inode, i_rdev);
    56  	key.inode = BPF_CORE_READ(file, f_inode, i_ino);
    57  	key.pid = pid;
    58  	key.tid = tid;
    59  	valuep = bpf_map_lookup_elem(&entries, &key);
    60  	if (!valuep) {
    61  		bpf_map_update_elem(&entries, &key, &zero_value, BPF_ANY);
    62  		valuep = bpf_map_lookup_elem(&entries, &key);
    63  		if (!valuep)
    64  			return 0;
    65  		valuep->pid = pid;
    66  		valuep->tid = tid;
    67  		valuep->mntns_id = mntns_id;
    68  		bpf_get_current_comm(&valuep->comm, sizeof(valuep->comm));
    69  		get_file_path(file, valuep->filename, sizeof(valuep->filename));
    70  		if (S_ISREG(mode)) {
    71  			valuep->type_ = 'R';
    72  		} else if (S_ISSOCK(mode)) {
    73  			valuep->type_ = 'S';
    74  		} else {
    75  			valuep->type_ = 'O';
    76  		}
    77  	}
    78  	if (op == READ) {
    79  		valuep->reads++;
    80  		valuep->read_bytes += count;
    81  	} else { /* op == WRITE */
    82  		valuep->writes++;
    83  		valuep->write_bytes += count;
    84  	}
    85  	return 0;
    86  };
    87  
    88  SEC("kprobe/vfs_read")
    89  int BPF_KPROBE(ig_topfile_rd_e, struct file *file, char *buf, size_t count,
    90  	       loff_t *pos)
    91  {
    92  	return probe_entry(ctx, file, count, READ);
    93  }
    94  
    95  SEC("kprobe/vfs_write")
    96  int BPF_KPROBE(ig_topfile_wr_e, struct file *file, const char *buf,
    97  	       size_t count, loff_t *pos)
    98  {
    99  	return probe_entry(ctx, file, count, WRITE);
   100  }
   101  
   102  char LICENSE[] SEC("license") = "Dual BSD/GPL";