// SPDX-License-Identifier: GPL-3.0-or-later
#include <sys/resource.h>
#include <stdlib.h>
#include "ebpf.h"
#include "ebpf_disk.h"
struct config disk_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 ebpf_local_maps_t disk_maps[] = {{.name = "tbl_disk_iocall", .internal_input = NETDATA_DISK_HISTOGRAM_LENGTH,
.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 avl_tree_lock disk_tree;
netdata_ebpf_disks_t *disk_list = NULL;
char *tracepoint_block_type = { "block"} ;
char *tracepoint_block_issue = { "block_rq_issue" };
char *tracepoint_block_rq_complete = { "block_rq_complete" };
static int was_block_issue_enabled = 0;
static int was_block_rq_complete_enabled = 0;
static char **dimensions = NULL;
static netdata_syscall_stat_t disk_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
static netdata_publish_syscall_t disk_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
static netdata_idx_t *disk_hash_values = NULL;
static struct netdata_static_thread disk_threads = {
.name = "DISK KERNEL",
.config_section = NULL,
.config_name = NULL,
.env_name = NULL,
.enabled = 1,
.thread = NULL,
.init_routine = NULL,
.start_routine = NULL
};
ebpf_publish_disk_t *plot_disks = NULL;
pthread_mutex_t plot_mutex;
/*****************************************************************
*
* FUNCTIONS TO MANIPULATE HARD DISKS
*
*****************************************************************/
/**
* Parse start
*
* Parse start address of disk
*
* @param w structure where data is stored
* @param filename variable used to store value
*
* @return It returns 0 on success and -1 otherwise
*/
static inline int ebpf_disk_parse_start(netdata_ebpf_disks_t *w, char *filename)
{
char content[FILENAME_MAX + 1];
int fd = open(filename, O_RDONLY, 0);
if (fd < 0) {
return -1;
}
ssize_t file_length = read(fd, content, 4095);
if (file_length > 0) {
if (file_length > FILENAME_MAX)
file_length = FILENAME_MAX;
content[file_length] = '\0';
w->start = strtoul(content, NULL, 10);
}
close(fd);
return 0;
}
/**
* Parse uevent
*
* Parse uevent file
*
* @param w structure where data is stored
* @param filename variable used to store value
*
* @return It returns 0 on success and -1 otherwise
*/
static inline int ebpf_parse_uevent(netdata_ebpf_disks_t *w, char *filename)
{
char content[FILENAME_MAX + 1];
int fd = open(filename, O_RDONLY, 0);
if (fd < 0) {
return -1;
}
ssize_t file_length = read(fd, content, FILENAME_MAX);
if (file_length > 0) {
if (file_length > FILENAME_MAX)
file_length = FILENAME_MAX;
content[file_length] = '\0';
char *s = strstr(content, "PARTNAME=EFI");
if (s) {
w->main->boot_partition = w;
w->flags |= NETDATA_DISK_HAS_EFI;
w->boot_chart = strdupz("disk_bootsector");
}
}
close(fd);
return 0;
}
/**
* Parse Size
*
* @param w structure where data is stored
* @param filename variable used to store value
*
* @return It returns 0 on success and -1 otherwise
*/
static inline int ebpf_parse_size(netdata_ebpf_disks_t *w, char *filename)
{
char content[FILENAME_MAX + 1];
int fd = open(filename, O_RDONLY, 0);
if (fd < 0) {
return -1;
}
ssize_t file_length = read(fd, content, FILENAME_MAX);
if (file_length > 0) {
if (file_length > FILENAME_MAX)