-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new eBPF program to monitor ZFS filesystem.
- Loading branch information
1 parent
eec36e1
commit c995f8e
Showing
3 changed files
with
210 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,7 @@ NETDATA_APPS= cachestat \ | |
swap \ | ||
vfs \ | ||
xfs \ | ||
zfs \ | ||
# | ||
|
||
all: $(NETDATA_APPS) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
#define KBUILD_MODNAME "zfs_netdata" | ||
#include <linux/bpf.h> | ||
#include <linux/ptrace.h> | ||
#include <linux/genhd.h> | ||
|
||
#include "bpf_helpers.h" | ||
#include "netdata_ebpf.h" | ||
|
||
/************************************************************************************ | ||
* | ||
* MAP Section | ||
* | ||
***********************************************************************************/ | ||
|
||
struct bpf_map_def SEC("maps") tbl_zfs = { | ||
.type = BPF_MAP_TYPE_PERCPU_ARRAY, | ||
.key_size = sizeof(__u32), | ||
.value_size = sizeof(__u64), | ||
.max_entries = NETDATA_FS_MAX_ELEMENTS | ||
}; | ||
|
||
struct bpf_map_def SEC("maps") tmp_zfs = { | ||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) | ||
.type = BPF_MAP_TYPE_HASH, | ||
#else | ||
.type = BPF_MAP_TYPE_PERCPU_HASH, | ||
#endif | ||
.key_size = sizeof(__u32), | ||
.value_size = sizeof(__u64), | ||
.max_entries = 4192 | ||
}; | ||
|
||
/************************************************************************************ | ||
* | ||
* ENTRY Section | ||
* | ||
***********************************************************************************/ | ||
|
||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(5,0,0)) | ||
static int netdata_zfs_entry() | ||
#elif (LINUX_VERSION_CODE > KERNEL_VERSION(4,19,0)) | ||
static __always_inline int netdata_zfs_entry() | ||
#else | ||
static inline int netdata_zfs_entry() | ||
#endif | ||
{ | ||
__u64 pid_tgid = bpf_get_current_pid_tgid(); | ||
__u32 pid = (__u32)(pid_tgid >> 32); | ||
__u64 ts = bpf_ktime_get_ns(); | ||
|
||
bpf_map_update_elem(&tmp_zfs, &pid, &ts, BPF_ANY); | ||
|
||
return 0; | ||
} | ||
|
||
SEC("kprobe/zpl_iter_read") | ||
int netdata_zpl_iter_read(struct pt_regs *ctx) | ||
{ | ||
return netdata_zfs_entry(); | ||
} | ||
|
||
SEC("kprobe/zpl_iter_write") | ||
int netdata_zpl_iter_write(struct pt_regs *ctx) | ||
{ | ||
return netdata_zfs_entry(); | ||
} | ||
|
||
SEC("kprobe/zpl_open") | ||
int netdata_zpl_open(struct pt_regs *ctx) | ||
{ | ||
return netdata_zfs_entry(); | ||
} | ||
|
||
SEC("kprobe/zpl_fsync") | ||
int netdata_zpl_fsync(struct pt_regs *ctx) | ||
{ | ||
return netdata_zfs_entry(); | ||
} | ||
|
||
/************************************************************************************ | ||
* | ||
* END Section | ||
* | ||
***********************************************************************************/ | ||
|
||
static void netdata_zfs_store_bin(__u32 bin, __u32 selection) | ||
{ | ||
__u64 *fill, data; | ||
__u32 idx = selection * NETDATA_FS_MAX_BINS + bin; | ||
if (idx >= NETDATA_FS_MAX_ELEMENTS) | ||
return; | ||
|
||
fill = bpf_map_lookup_elem(&tbl_zfs, &idx); | ||
if (fill) { | ||
libnetdata_update_u64(fill, 1); | ||
return; | ||
} | ||
|
||
data = 1; | ||
bpf_map_update_elem(&tbl_zfs, &idx, &data, BPF_ANY); | ||
} | ||
|
||
SEC("kretprobe/zpl_iter_read") | ||
int netdata_ret_zpl_iter_read(struct pt_regs *ctx) | ||
{ | ||
__u64 *fill, data; | ||
__u64 pid_tgid = bpf_get_current_pid_tgid(); | ||
__u32 bin, pid = (__u32)(pid_tgid >> 32); | ||
|
||
fill = bpf_map_lookup_elem(&tmp_zfs, &pid); | ||
if (!fill) | ||
return 0; | ||
|
||
data = bpf_ktime_get_ns() - *fill; | ||
bpf_map_delete_elem(&tmp_zfs, &pid); | ||
|
||
// Skip entries with backward time | ||
if ( (s64)data < 0) | ||
return 0; | ||
|
||
// convert to microseconds | ||
data /= 1000; | ||
bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); | ||
netdata_zfs_store_bin(bin, NETDATA_KEY_CALLS_READ); | ||
|
||
return 0; | ||
} | ||
|
||
SEC("kretprobe/zpl_iter_write") | ||
int netdata_ret_zpl_iter_write(struct pt_regs *ctx) | ||
{ | ||
__u64 *fill, data; | ||
__u64 pid_tgid = bpf_get_current_pid_tgid(); | ||
__u32 bin, pid = (__u32)(pid_tgid >> 32); | ||
|
||
fill = bpf_map_lookup_elem(&tmp_zfs, &pid); | ||
if (!fill) | ||
return 0; | ||
|
||
data = bpf_ktime_get_ns() - *fill; | ||
bpf_map_delete_elem(&tmp_zfs, &pid); | ||
|
||
// Skip entries with backward time | ||
if ( (s64)data < 0) | ||
return 0; | ||
|
||
// convert to microseconds | ||
data /= 1000; | ||
bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); | ||
netdata_zfs_store_bin(bin, NETDATA_KEY_CALLS_WRITE); | ||
|
||
return 0; | ||
} | ||
|
||
SEC("kretprobe/zpl_open") | ||
int netdata_ret_zpl_open(struct pt_regs *ctx) | ||
{ | ||
__u64 *fill, data; | ||
__u64 pid_tgid = bpf_get_current_pid_tgid(); | ||
__u32 bin, pid = (__u32)(pid_tgid >> 32); | ||
|
||
fill = bpf_map_lookup_elem(&tmp_zfs, &pid); | ||
if (!fill) | ||
return 0; | ||
|
||
data = bpf_ktime_get_ns() - *fill; | ||
bpf_map_delete_elem(&tmp_zfs, &pid); | ||
|
||
// Skip entries with backward time | ||
if ( (s64)data < 0) | ||
return 0; | ||
|
||
// convert to microseconds | ||
data /= 1000; | ||
bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); | ||
netdata_zfs_store_bin(bin, NETDATA_KEY_CALLS_OPEN); | ||
|
||
return 0; | ||
} | ||
|
||
SEC("kretprobe/zpl_fsync") | ||
int netdata_ret_zpl_fsync(struct pt_regs *ctx) | ||
{ | ||
__u64 *fill, data; | ||
__u64 pid_tgid = bpf_get_current_pid_tgid(); | ||
__u32 bin, pid = (__u32)(pid_tgid >> 32); | ||
|
||
fill = bpf_map_lookup_elem(&tmp_zfs, &pid); | ||
if (!fill) | ||
return 0; | ||
|
||
data = bpf_ktime_get_ns() - *fill; | ||
bpf_map_delete_elem(&tmp_zfs, &pid); | ||
|
||
// Skip entries with backward time | ||
if ( (s64)data < 0) | ||
return 0; | ||
|
||
// convert to microseconds | ||
data /= 1000; | ||
bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); | ||
netdata_zfs_store_bin(bin, NETDATA_KEY_CALLS_SYNC); | ||
|
||
return 0; | ||
} | ||
|
||
char _license[] SEC("license") = "GPL"; | ||
|