// 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,
#ifdef LIBBPF_MAJOR_VERSION
.map_type = BPF_MAP_TYPE_PERCPU_HASH
#endif
},
{.name = "tmp_disk_tp_stat", .internal_input = 8192, .user_input = 8192,
.type = NETDATA_EBPF_MAP_STATIC,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
#ifdef LIBBPF_MAJOR_VERSION
.map_type = BPF_MAP_TYPE_PERCPU_HASH
#endif
},
{.name = NULL, .internal_input = 0, .user_input = 0,
.type = NETDATA_EBPF_MAP_CONTROLLER,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
#ifdef LIBBPF_MAJOR_VERSION
.map_type = BPF_MAP_TYPE_PERCPU_ARRAY
#endif
}};
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;
ebpf_publish_disk_t *plot_disks = NULL;
pthread_mutex_t plot_mutex;
#ifdef LIBBPF_MAJOR_VERSION
/**
* Set hash table
*
* Set the values for maps according the value given by kernel.
*
* @param obj is the main structure for bpf objects.
*/
static inline void ebpf_disk_set_hash_table(struct disk_bpf *obj)
{
disk_maps[NETDATA_DISK_IO].map_fd = bpf_map__fd(obj->maps.tbl_disk_iocall);
}
/**
* Load and attach
*
* Load and attach the eBPF code in kernel.
*
* @param obj is the main structure for bpf objects.
*
* @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_disk_load_and_attach(struct disk_bpf *obj)
{
int ret = disk_bpf__load(obj);
if (ret) {
return ret;
}
return disk_bpf__attach(obj);
}
#endif
/*****************************************************************
*
* 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