Skip to content

Commit

Permalink
libbpf-tools: add fsdist
Browse files Browse the repository at this point in the history
fsdist is a multitool which show filesystem latency.
Currently we support btrfs/ext4/nfs/xfs filesystems.
It behaves the same as its counterpart in BCC tools
named btrfsdist.py/ext4dist.py/nfsdist.py/xfsdist.py

Signed-off-by: Hengqi Chen <[email protected]>
  • Loading branch information
chenhengqi authored and yonghong-song committed Jun 2, 2021
1 parent f2bb8f1 commit 5a69ec3
Show file tree
Hide file tree
Showing 5 changed files with 668 additions and 0 deletions.
1 change: 1 addition & 0 deletions libbpf-tools/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
/execsnoop
/ext4dist
/filelife
/fsdist
/funclatency
/gethostlatency
/hardirqs
Expand Down
1 change: 1 addition & 0 deletions libbpf-tools/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ APPS = \
execsnoop \
ext4dist \
filelife \
fsdist \
funclatency \
gethostlatency \
hardirqs \
Expand Down
193 changes: 193 additions & 0 deletions libbpf-tools/fsdist.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2021 Hengqi Chen */
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include "bits.bpf.h"
#include "fsdist.h"

#define MAX_ENTRIES 10240

const volatile pid_t target_pid = 0;
const volatile bool in_ms = false;

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_ENTRIES);
__type(key, __u32);
__type(value, __u64);
} starts SEC(".maps");

struct hist hists[MAX_OP] = {};

static int probe_entry()
{
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
__u32 tid = (__u32)pid_tgid;
__u64 ts;

if (target_pid && target_pid != pid)
return 0;

ts = bpf_ktime_get_ns();
bpf_map_update_elem(&starts, &tid, &ts, BPF_ANY);
return 0;
}

static int probe_return(enum fs_file_op op)
{
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
__u32 tid = (__u32)pid_tgid;
__u64 ts = bpf_ktime_get_ns();
__u64 *tsp, slot;
__s64 delta;

tsp = bpf_map_lookup_elem(&starts, &tid);
if (!tsp)
return 0;

if (op >= MAX_OP)
goto cleanup;

delta = (__s64)(ts - *tsp);
if (delta < 0)
goto cleanup;

if (in_ms)
delta /= 1000000;
else
delta /= 1000;

slot = log2l(delta);
if (slot >= MAX_SLOTS)
slot = MAX_SLOTS - 1;
__sync_fetch_and_add(&hists[op].slots[slot], 1);

cleanup:
bpf_map_delete_elem(&starts, &tid);
return 0;
}

SEC("kprobe/dummy_file_read")
int BPF_KPROBE(file_read_entry)
{
return probe_entry();
}

SEC("kretprobe/dummy_file_read")
int BPF_KRETPROBE(file_read_exit)
{
return probe_return(READ);
}

SEC("kprobe/dummy_file_write")
int BPF_KPROBE(file_write_entry)
{
return probe_entry();
}

SEC("kretprobe/dummy_file_write")
int BPF_KRETPROBE(file_write_exit)
{
return probe_return(WRITE);
}

SEC("kprobe/dummy_file_open")
int BPF_KPROBE(file_open_entry)
{
return probe_entry();
}

SEC("kretprobe/dummy_file_open")
int BPF_KRETPROBE(file_open_exit)
{
return probe_return(OPEN);
}

SEC("kprobe/dummy_file_sync")
int BPF_KPROBE(file_sync_entry)
{
return probe_entry();
}

SEC("kretprobe/dummy_file_sync")
int BPF_KRETPROBE(file_sync_exit)
{
return probe_return(FSYNC);
}

SEC("kprobe/dummy_getattr")
int BPF_KPROBE(getattr_entry)
{
return probe_entry();
}

SEC("kretprobe/dummy_getattr")
int BPF_KRETPROBE(getattr_exit)
{
return probe_return(GETATTR);
}

SEC("fentry/dummy_file_read")
int BPF_PROG(file_read_fentry)
{
return probe_entry();
}

SEC("fexit/dummy_file_read")
int BPF_PROG(file_read_fexit)
{
return probe_return(READ);
}

SEC("fentry/dummy_file_write")
int BPF_PROG(file_write_fentry)
{
return probe_entry();
}

SEC("fexit/dummy_file_write")
int BPF_PROG(file_write_fexit)
{
return probe_return(WRITE);
}

SEC("fentry/dummy_file_open")
int BPF_PROG(file_open_fentry)
{
return probe_entry();
}

SEC("fexit/dummy_file_open")
int BPF_PROG(file_open_fexit)
{
return probe_return(OPEN);
}

SEC("fentry/dummy_file_sync")
int BPF_PROG(file_sync_fentry)
{
return probe_entry();
}

SEC("fexit/dummy_file_sync")
int BPF_PROG(file_sync_fexit)
{
return probe_return(FSYNC);
}

SEC("fentry/dummy_getattr")
int BPF_PROG(getattr_fentry)
{
return probe_entry();
}

SEC("fexit/dummy_getattr")
int BPF_PROG(getattr_fexit)
{
return probe_return(GETATTR);
}

char LICENSE[] SEC("license") = "Dual BSD/GPL";
Loading

0 comments on commit 5a69ec3

Please sign in to comment.