0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-04-14 17:48:37 +00:00

eBPF mount ()

This commit is contained in:
thiagoftsm 2021-07-29 18:26:11 +00:00 committed by GitHub
parent d6e8972e21
commit 561557c5ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 358 additions and 5 deletions

View file

@ -492,6 +492,8 @@ set(EBPF_PROCESS_PLUGIN_FILES
collectors/ebpf.plugin/ebpf_dcstat.h
collectors/ebpf.plugin/ebpf_disk.c
collectors/ebpf.plugin/ebpf_disk.h
collectors/ebpf.plugin/ebpf_mount.c
collectors/ebpf.plugin/ebpf_mount.h
collectors/ebpf.plugin/ebpf_filesystem.c
collectors/ebpf.plugin/ebpf_filesystem.h
collectors/ebpf.plugin/ebpf_process.c

View file

@ -297,6 +297,8 @@ EBPF_PLUGIN_FILES = \
collectors/ebpf.plugin/ebpf_disk.h \
collectors/ebpf.plugin/ebpf_filesystem.c \
collectors/ebpf.plugin/ebpf_filesystem.h \
collectors/ebpf.plugin/ebpf_mount.c \
collectors/ebpf.plugin/ebpf_mount.h \
collectors/ebpf.plugin/ebpf_process.c \
collectors/ebpf.plugin/ebpf_process.h \
collectors/ebpf.plugin/ebpf_socket.c \

View file

@ -153,6 +153,9 @@
#define NETDATA_CHART_PRIO_EBPF_FILESYSTEM_CHARTS 2160
// Mount Points
#define NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS 2195
// NFS (server)
#define NETDATA_CHART_PRIO_NFSD_READCACHE 2200

View file

@ -36,6 +36,7 @@ dist_ebpfconfig_DATA = \
ebpf.d/dcstat.conf \
ebpf.d/disk.conf \
ebpf.d/filesystem.conf \
ebpf.d/mount.conf \
ebpf.d/network.conf \
ebpf.d/process.conf \
ebpf.d/sync.conf \

View file

@ -120,6 +120,11 @@ ebpf_module_t ebpf_modules[] = {
.optional = 0, .apps_routine = NULL, .maps = NULL,
.pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config,
.config_file = NETDATA_SYNC_CONFIG_FILE},
{ .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread,
.update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
.optional = 0, .apps_routine = NULL, .maps = NULL,
.pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config,
.config_file = NETDATA_SYNC_CONFIG_FILE},
{ .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_time = 1,
.global_charts = 0, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
.optional = 0, .apps_routine = NULL, .maps = NULL, .pid_map_size = 0, .names = NULL,
@ -692,6 +697,8 @@ void ebpf_print_help()
"\n"
" --filesystem or -i Enable chart related to filesystem run time.\n"
"\n"
" --mount or -m Enable charts related to mount monitoring.\n"
"\n"
" --net or -n Enable network viewer charts.\n"
"\n"
" --process or -p Enable charts related to process run time.\n"
@ -1021,6 +1028,13 @@ static void read_collector_values(int *disable_apps)
started++;
}
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "mount",
CONFIG_BOOLEAN_YES);
if (enabled) {
ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, *disable_apps);
started++;
}
if (!started){
ebpf_enable_all_charts(*disable_apps);
// Read network viewer section
@ -1107,6 +1121,7 @@ static void parse_args(int argc, char **argv)
{"dcstat", no_argument, 0, 'd' },
{"disk", no_argument, 0, 'k' },
{"filesystem", no_argument, 0, 'i' },
{"mount", no_argument, 0, 'm' },
{"net", no_argument, 0, 'n' },
{"process", no_argument, 0, 'p' },
{"return", no_argument, 0, 'r' },
@ -1187,6 +1202,14 @@ static void parse_args(int argc, char **argv)
ebpf_enable_chart(EBPF_MODULE_DISK_IDX, disable_apps);
#ifdef NETDATA_INTERNAL_CHECKS
info("EBPF enabling \"disk\" chart, because it was started with the option \"--disk\" or \"-k\".");
#endif
break;
}
case 'm': {
enabled = 1;
ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, disable_apps);
#ifdef NETDATA_INTERNAL_CHECKS
info("EBPF enabling \"mount\" chart, because it was started with the option \"--mount\" or \"-m\".");
#endif
break;
}
@ -1514,6 +1537,8 @@ int main(int argc, char **argv)
NULL, NULL, ebpf_modules[EBPF_MODULE_FILESYSTEM_IDX].start_routine},
{"EBPF DISK" , NULL, NULL, 1,
NULL, NULL, ebpf_modules[EBPF_MODULE_DISK_IDX].start_routine},
{"EBPF MOUNT" , NULL, NULL, 1,
NULL, NULL, ebpf_modules[EBPF_MODULE_MOUNT_IDX].start_routine},
{NULL , NULL, NULL, 0,
NULL, NULL, NULL}
};

View file

@ -28,6 +28,7 @@
# `cachestat` : Make charts for kernel functions related to page cache.
# `dcstat` : Make charts for kernel functions related to directory cache.
# `disk` : Monitor I/O latencies for disks
# `mount` : Monitor calls for syscalls mount and umount
# `filesystem`: Monitor calls for functions used to manipulate specific filesystems
# `process` : This eBPF program creates charts that show information about process creation, and file manipulation.
# `socket` : This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
@ -41,6 +42,7 @@
dcstat = no
disk = no
filesystem = no
mount = yes
process = yes
socket = yes
sync = yes

View file

@ -0,0 +1,8 @@
# The `ebpf load mode` option accepts the following values :
# `entry` : The eBPF collector only monitors calls for the functions, and does not show charts related to errors.
# `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
# new charts for the return of these functions, such as errors.
#
[global]
ebpf load mode = entry
update every = 2

View file

@ -82,7 +82,8 @@ enum ebpf_module_indexes {
EBPF_MODULE_SWAP_IDX,
EBPF_MODULE_VFS_IDX,
EBPF_MODULE_FILESYSTEM_IDX,
EBPF_MODULE_DISK_IDX
EBPF_MODULE_DISK_IDX,
EBPF_MODULE_MOUNT_IDX
};
// Copied from musl header
@ -97,6 +98,7 @@ enum ebpf_module_indexes {
// Chart definitions
#define NETDATA_EBPF_FAMILY "ebpf"
#define NETDATA_FILESYSTEM_FAMILY "filesystem"
#define NETDATA_EBPF_MOUNT_GLOBAL_FAMILY "mount_points"
#define NETDATA_EBPF_CHART_TYPE_LINE "line"
#define NETDATA_EBPF_CHART_TYPE_STACKED "stacked"
#define NETDATA_EBPF_MEMORY_GROUP "mem"

View file

@ -23,6 +23,7 @@
#include "ebpf_disk.h"
#include "ebpf_filesystem.h"
#include "ebpf_cachestat.h"
#include "ebpf_mount.h"
#include "ebpf_sync.h"
#include "ebpf_swap.h"
#include "ebpf_vfs.h"

View file

@ -0,0 +1,255 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include "ebpf.h"
#include "ebpf_mount.h"
static ebpf_local_maps_t mount_maps[] = {{.name = "tbl_mount", .internal_input = NETDATA_MOUNT_END,
.user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
{.name = NULL, .internal_input = 0, .user_input = 0,
.type = NETDATA_EBPF_MAP_CONTROLLER,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
static ebpf_data_t mount_data;
static char *mount_dimension_name[NETDATA_EBPF_MOUNT_SYSCALL] = { "mount", "umount" };
static netdata_syscall_stat_t mount_aggregated_data[NETDATA_EBPF_MOUNT_SYSCALL];
static netdata_publish_syscall_t mount_publish_aggregated[NETDATA_EBPF_MOUNT_SYSCALL];
struct config mount_config = { .first_section = NULL, .last_section = NULL, .mutex = NETDATA_MUTEX_INITIALIZER,
.index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare },
.rwlock = AVL_LOCK_INITIALIZER } };
static int read_thread_closed = 1;
static netdata_idx_t *mount_values = NULL;
static struct bpf_link **probe_links = NULL;
static struct bpf_object *objects = NULL;
static netdata_idx_t mount_hash_values[NETDATA_MOUNT_END];
struct netdata_static_thread mount_thread = {"MOUNT KERNEL",
NULL, NULL, 1, NULL,
NULL, NULL};
/*****************************************************************
*
* FUNCTIONS TO CLOSE THE THREAD
*
*****************************************************************/
/**
* Clean up the main thread.
*
* @param ptr thread data.
*/
static void ebpf_mount_cleanup(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
if (!em->enabled)
return;
freez(mount_thread.thread);
freez(mount_values);
if (probe_links) {
struct bpf_program *prog;
size_t i = 0 ;
bpf_object__for_each_program(prog, objects) {
bpf_link__destroy(probe_links[i]);
i++;
}
bpf_object__close(objects);
}
}
/*****************************************************************
*
* MAIN LOOP
*
*****************************************************************/
/**
* Read global table
*
* Read the table with number of calls for all functions
*/
static void read_global_table()
{
uint32_t idx;
netdata_idx_t *val = mount_hash_values;
netdata_idx_t *stored = mount_values;
int fd = mount_maps[NETDATA_KEY_MOUNT_TABLE].map_fd;
for (idx = NETDATA_KEY_MOUNT_CALL; idx < NETDATA_MOUNT_END; idx++) {
if (!bpf_map_lookup_elem(fd, &idx, stored)) {
int i;
int end = ebpf_nprocs;
netdata_idx_t total = 0;
for (i = 0; i < end; i++)
total += stored[i];
val[idx] = total;
}
}
}
/**
* Mount read hash
*
* This is the thread callback.
* This thread is necessary, because we cannot freeze the whole plugin to read the data.
*
* @param ptr It is a NULL value for this thread.
*
* @return It always returns NULL.
*/
void *ebpf_mount_read_hash(void *ptr)
{
read_thread_closed = 0;
heartbeat_t hb;
heartbeat_init(&hb);
ebpf_module_t *em = (ebpf_module_t *)ptr;
usec_t step = NETDATA_LATENCY_MOUNT_SLEEP_MS * em->update_time;
while (!close_ebpf_plugin) {
usec_t dt = heartbeat_next(&hb, step);
(void)dt;
read_global_table();
}
read_thread_closed = 1;
return NULL;
}
/**
* Send data to Netdata calling auxiliar functions.
*/
static void ebpf_mount_send_data()
{
int i, j;
int end = NETDATA_EBPF_MOUNT_SYSCALL;
for (i = NETDATA_KEY_MOUNT_CALL, j = NETDATA_KEY_MOUNT_ERROR; i < end; i++, j++) {
mount_publish_aggregated[i].ncall = mount_hash_values[i];
mount_publish_aggregated[i].nerr = mount_hash_values[j];
}
write_count_chart(NETDATA_EBPF_MOUNT_CALLS, NETDATA_EBPF_MOUNT_GLOBAL_FAMILY,
mount_publish_aggregated, NETDATA_EBPF_MOUNT_SYSCALL);
write_err_chart(NETDATA_EBPF_MOUNT_ERRORS, NETDATA_EBPF_MOUNT_GLOBAL_FAMILY,
mount_publish_aggregated, NETDATA_EBPF_MOUNT_SYSCALL);
}
/**
* Main loop for this collector.
*/
static void mount_collector(ebpf_module_t *em)
{
mount_thread.thread = mallocz(sizeof(netdata_thread_t));
mount_thread.start_routine = ebpf_mount_read_hash;
memset(mount_hash_values, 0, sizeof(mount_hash_values));
mount_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
netdata_thread_create(mount_thread.thread, mount_thread.name, NETDATA_THREAD_OPTION_JOINABLE,
ebpf_mount_read_hash, em);
while (!close_ebpf_plugin) {
pthread_mutex_lock(&collect_data_mutex);
pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
pthread_mutex_lock(&lock);
ebpf_mount_send_data();
pthread_mutex_unlock(&lock);
pthread_mutex_unlock(&collect_data_mutex);
}
}
/*****************************************************************
*
* INITIALIZE THREAD
*
*****************************************************************/
/**
* Create mount charts
*
* Call ebpf_create_chart to create the charts for the collector.
*/
static void ebpf_create_mount_charts()
{
ebpf_create_chart(NETDATA_EBPF_MOUNT_GLOBAL_FAMILY, NETDATA_EBPF_MOUNT_CALLS,
"Calls to mount and umount syscalls.",
EBPF_COMMON_DIMENSION_CALL, NETDATA_EBPF_MOUNT_FAMILY,
NULL,
NETDATA_EBPF_CHART_TYPE_LINE,
NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS,
ebpf_create_global_dimension,
mount_publish_aggregated, NETDATA_EBPF_MOUNT_SYSCALL);
ebpf_create_chart(NETDATA_EBPF_MOUNT_GLOBAL_FAMILY, NETDATA_EBPF_MOUNT_ERRORS,
"Errors to mount and umount syscalls.",
EBPF_COMMON_DIMENSION_CALL, NETDATA_EBPF_MOUNT_FAMILY,
NULL,
NETDATA_EBPF_CHART_TYPE_LINE,
NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS + 1,
ebpf_create_global_dimension,
mount_publish_aggregated, NETDATA_EBPF_MOUNT_SYSCALL);
fflush(stdout);
}
/*****************************************************************
*
* MAIN THREAD
*
*****************************************************************/
/**
* Mount thread
*
* Thread used to make mount thread
*
* @param ptr a pointer to `struct ebpf_module`
*
* @return It always returns NULL
*/
void *ebpf_mount_thread(void *ptr)
{
netdata_thread_cleanup_push(ebpf_mount_cleanup, ptr);
ebpf_module_t *em = (ebpf_module_t *)ptr;
em->maps = mount_maps;
fill_ebpf_data(&mount_data);
if (!em->enabled)
goto endmount;
if (ebpf_update_kernel(&mount_data))
goto endmount;
probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string, &objects, mount_data.map_fd);
if (!probe_links) {
goto endmount;
}
int algorithms[NETDATA_EBPF_MOUNT_SYSCALL] = { NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX };
ebpf_global_labels(mount_aggregated_data, mount_publish_aggregated, mount_dimension_name, mount_dimension_name,
algorithms, NETDATA_EBPF_MOUNT_SYSCALL);
pthread_mutex_lock(&lock);
ebpf_create_mount_charts();
pthread_mutex_unlock(&lock);
mount_collector(em);
endmount:
netdata_thread_cleanup_pop(1);
return NULL;
}

View file

@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef NETDATA_EBPF_MOUNT_H
#define NETDATA_EBPF_MOUNT_H 1
#define NETDATA_EBPF_MOUNT_SYSCALL 2
#define NETDATA_LATENCY_MOUNT_SLEEP_MS 700000ULL
#define NETDATA_EBPF_MOUNT_CALLS "call"
#define NETDATA_EBPF_MOUNT_ERRORS "error"
#define NETDATA_EBPF_MOUNT_FAMILY "mount (eBPF)"
enum mount_counters {
NETDATA_KEY_MOUNT_CALL,
NETDATA_KEY_UMOUNT_CALL,
NETDATA_KEY_MOUNT_ERROR,
NETDATA_KEY_UMOUNT_ERROR,
NETDATA_MOUNT_END
};
enum mount_tables {
NETDATA_KEY_MOUNT_TABLE
};
extern struct config mount_config;
extern void *ebpf_mount_thread(void *ptr);
#endif /* NETDATA_EBPF_MOUNT_H */

View file

@ -1,3 +1,3 @@
9144ec509b1d8dc43bfb5275935cfb9329d0da7a90bfefa5f1c2796d60991dd1 netdata-kernel-collector-glibc-v0.7.5.tar.xz
a2c901e7f67472108c015a66b0c2dedf0cc3a791bbd8f75145c9c066aa7e0567 netdata-kernel-collector-musl-v0.7.5.tar.xz
04231b6a5997c6f3330eeffa1897a4b331e70a21cb46278e4346c006824d7cb1 netdata-kernel-collector-static-v0.7.5.tar.xz
0e5d9bbbffeef735534edaf5efa73e2f44b705699268bcc3028e48434e7fe8d0 netdata-kernel-collector-glibc-v0.7.6.tar.xz
ee189fd82dae3c9e68756f88364bfdb97a29adb134ea7d95ae22f6059db4a632 netdata-kernel-collector-musl-v0.7.6.tar.xz
98a31a53b9f7ca7b95c44ec12126357dc7d4c4d4a547142c8573a886ac6de430 netdata-kernel-collector-static-v0.7.6.tar.xz

View file

@ -1 +1 @@
v0.7.5
v0.7.6

View file

@ -127,6 +127,12 @@ netdataDashboard.menu = {
info: 'Charts with performance information for all the system disks. Special care has been given to present disk performance metrics in a way compatible with <code>iostat -x</code>. netdata by default prevents rendering performance charts for individual partitions and unmounted virtual disks. Disabled charts can still be enabled by configuring the relative settings in the netdata configuration file.'
},
'mount': {
title: 'Mount Points',
icon: '<i class="fas fa-hdd"></i>',
info: ''
},
'mdstat': {
title: 'MD arrays',
icon: '<i class="fas fa-hdd"></i>'
@ -3588,6 +3594,14 @@ netdataDashboard.context = {
info: 'Netdata is attaching <code>kprobes</code> for when the function <code>btrfs_sync_file</code>.'
},
'mount_points.call': {
info: 'Monitor calls to syscalls <code>mount(2)</code> and <code>umount(2)</code> that are responsible for attaching or removing filesystems.'
},
'mount_points.error': {
info: 'Monitor errors in calls to syscalls <code>mount(2)</code> and <code>umount(2)</code>.'
},
// ------------------------------------------------------------------------
// eBPF

View file

@ -1410,6 +1410,14 @@ function enrichChartData(chart) {
}
break;
case 'mount':
if (parts.length > 2) {
chart.menu = tmp + '_' + parts[1];
} else {
chart.menu = tmp;
}
break;
case 'isc':
chart.menu = chart.type;
if (parts.length > 2 && parts[1] === 'dhcpd') {