123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- #include "ebpf_filesystem.h"
- struct config fs_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 fs_maps[] = {{.name = "tbl_ext4", .internal_input = NETDATA_KEY_CALLS_SYNC,
- .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
- .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
- {.name = "tbl_xfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
- .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
- .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
- {.name = "tbl_nfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
- .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
- .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
- {.name = "tbl_zfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
- .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
- .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
- {.name = "tbl_btrfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
- .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
- .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
- {.name = "tbl_ext_addr", .internal_input = 1,
- .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}};
- ebpf_filesystem_partitions_t localfs[] =
- {{.filesystem = "ext4",
- .optional_filesystem = NULL,
- .family = "ext4",
- .objects = NULL,
- .probe_links = NULL,
- .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
- .enabled = CONFIG_BOOLEAN_YES,
- .addresses = {.function = NULL, .addr = 0},
- .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
- {.filesystem = "xfs",
- .optional_filesystem = NULL,
- .family = "xfs",
- .objects = NULL,
- .probe_links = NULL,
- .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
- .enabled = CONFIG_BOOLEAN_YES,
- .addresses = {.function = NULL, .addr = 0},
- .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
- {.filesystem = "nfs",
- .optional_filesystem = "nfs4",
- .family = "nfs",
- .objects = NULL,
- .probe_links = NULL,
- .flags = NETDATA_FILESYSTEM_ATTR_CHARTS,
- .enabled = CONFIG_BOOLEAN_YES,
- .addresses = {.function = NULL, .addr = 0},
- .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
- {.filesystem = "zfs",
- .optional_filesystem = NULL,
- .family = "zfs",
- .objects = NULL,
- .probe_links = NULL,
- .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
- .enabled = CONFIG_BOOLEAN_YES,
- .addresses = {.function = NULL, .addr = 0},
- .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
- {.filesystem = "btrfs",
- .optional_filesystem = NULL,
- .family = "btrfs",
- .objects = NULL,
- .probe_links = NULL,
- .flags = NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE,
- .enabled = CONFIG_BOOLEAN_YES,
- .addresses = {.function = "btrfs_file_operations", .addr = 0},
- .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10},
- {.filesystem = NULL,
- .optional_filesystem = NULL,
- .family = NULL,
- .objects = NULL,
- .probe_links = NULL,
- .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
- .enabled = CONFIG_BOOLEAN_YES,
- .addresses = {.function = NULL, .addr = 0},
- .kernels = 0}};
- struct netdata_static_thread filesystem_threads = {"EBPF FS READ",
- NULL, NULL, 1, NULL,
- NULL, NULL };
- static int read_thread_closed = 1;
- static netdata_syscall_stat_t filesystem_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
- static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
- char **dimensions = NULL;
- static netdata_idx_t *filesystem_hash_values = NULL;
- /*****************************************************************
- *
- * COMMON FUNCTIONS
- *
- *****************************************************************/
- /**
- * Create Filesystem chart
- *
- * Create latency charts
- *
- * @param update_every value to overwrite the update frequency set by the server.
- */
- static void ebpf_obsolete_fs_charts(int update_every)
- {
- int i;
- uint32_t test = NETDATA_FILESYSTEM_FLAG_CHART_CREATED | NETDATA_FILESYSTEM_REMOVE_CHARTS;
- for (i = 0; localfs[i].filesystem; i++) {
- ebpf_filesystem_partitions_t *efp = &localfs[i];
- uint32_t flags = efp->flags;
- if ((flags & test) == test) {
- flags &= ~NETDATA_FILESYSTEM_FLAG_CHART_CREATED;
- ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, efp->hread.name,
- efp->hread.title,
- EBPF_COMMON_DIMENSION_CALL, efp->family_name,
- NULL, NETDATA_EBPF_CHART_TYPE_STACKED, efp->hread.order, update_every);
- ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, efp->hwrite.name,
- efp->hwrite.title,
- EBPF_COMMON_DIMENSION_CALL, efp->family_name,
- NULL, NETDATA_EBPF_CHART_TYPE_STACKED, efp->hwrite.order, update_every);
- ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, efp->hopen.name, efp->hopen.title,
- EBPF_COMMON_DIMENSION_CALL, efp->family_name,
- NULL, NETDATA_EBPF_CHART_TYPE_STACKED, efp->hopen.order, update_every);
- ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, efp->hadditional.name, efp->hadditional.title,
- EBPF_COMMON_DIMENSION_CALL, efp->family_name,
- NULL, NETDATA_EBPF_CHART_TYPE_STACKED, efp->hadditional.order,
- update_every);
- }
- efp->flags = flags;
- }
- }
- /**
- * Create Filesystem chart
- *
- * Create latency charts
- *
- * @param update_every value to overwrite the update frequency set by the server.
- */
- static void ebpf_create_fs_charts(int update_every)
- {
- static int order = NETDATA_CHART_PRIO_EBPF_FILESYSTEM_CHARTS;
- char chart_name[64], title[256], family[64];
- int i;
- uint32_t test = NETDATA_FILESYSTEM_FLAG_CHART_CREATED|NETDATA_FILESYSTEM_REMOVE_CHARTS;
- for (i = 0; localfs[i].filesystem; i++) {
- ebpf_filesystem_partitions_t *efp = &localfs[i];
- uint32_t flags = efp->flags;
- if (flags & NETDATA_FILESYSTEM_FLAG_HAS_PARTITION && !(flags & test)) {
- snprintfz(title, 255, "%s latency for each read request.", efp->filesystem);
- snprintfz(family, 63, "%s_latency", efp->family);
- snprintfz(chart_name, 63, "%s_read_latency", efp->filesystem);
- efp->hread.name = strdupz(chart_name);
- efp->hread.title = strdupz(title);
- efp->hread.order = order;
- efp->family_name = strdupz(family);
- ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hread.name,
- title,
- EBPF_COMMON_DIMENSION_CALL, family,
- NULL, NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
- filesystem_publish_aggregated, NETDATA_EBPF_HIST_MAX_BINS,
- update_every, NETDATA_EBPF_MODULE_NAME_FILESYSTEM);
- order++;
- snprintfz(title, 255, "%s latency for each write request.", efp->filesystem);
- snprintfz(chart_name, 63, "%s_write_latency", efp->filesystem);
- efp->hwrite.name = strdupz(chart_name);
- efp->hwrite.title = strdupz(title);
- efp->hwrite.order = order;
- ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hwrite.name,
- title,
- EBPF_COMMON_DIMENSION_CALL, family,
- NULL, NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
- filesystem_publish_aggregated, NETDATA_EBPF_HIST_MAX_BINS,
- update_every, NETDATA_EBPF_MODULE_NAME_FILESYSTEM);
- order++;
- snprintfz(title, 255, "%s latency for each open request.", efp->filesystem);
- snprintfz(chart_name, 63, "%s_open_latency", efp->filesystem);
- efp->hopen.name = strdupz(chart_name);
- efp->hopen.title = strdupz(title);
- efp->hopen.order = order;
- ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hopen.name,
- title,
- EBPF_COMMON_DIMENSION_CALL, family,
- NULL, NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
- filesystem_publish_aggregated, NETDATA_EBPF_HIST_MAX_BINS,
- update_every, NETDATA_EBPF_MODULE_NAME_FILESYSTEM);
- order++;
- char *type = (efp->flags & NETDATA_FILESYSTEM_ATTR_CHARTS) ? "attribute" : "sync";
- snprintfz(title, 255, "%s latency for each %s request.", efp->filesystem, type);
- snprintfz(chart_name, 63, "%s_%s_latency", efp->filesystem, type);
- efp->hadditional.name = strdupz(chart_name);
- efp->hadditional.title = strdupz(title);
- efp->hadditional.order = order;
- ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hadditional.name, title,
- EBPF_COMMON_DIMENSION_CALL, family,
- NULL, NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
- filesystem_publish_aggregated, NETDATA_EBPF_HIST_MAX_BINS,
- update_every, NETDATA_EBPF_MODULE_NAME_FILESYSTEM);
- order++;
- efp->flags |= NETDATA_FILESYSTEM_FLAG_CHART_CREATED;
- }
- }
- }
- /**
- * Initialize eBPF data
- *
- * @param em main thread structure.
- *
- * @return it returns 0 on success and -1 otherwise.
- */
- int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em)
- {
- int i;
- const char *saved_name = em->thread_name;
- uint64_t kernels = em->kernels;
- for (i = 0; localfs[i].filesystem; i++) {
- ebpf_filesystem_partitions_t *efp = &localfs[i];
- if (!efp->probe_links && efp->flags & NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM) {
- em->thread_name = efp->filesystem;
- em->kernels = efp->kernels;
- efp->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &efp->objects);
- if (!efp->probe_links) {
- em->thread_name = saved_name;
- em->kernels = kernels;
- return -1;
- }
- efp->flags |= NETDATA_FILESYSTEM_FLAG_HAS_PARTITION;
- // Nedeed for filesystems like btrfs
- if ((efp->flags & NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE) && (efp->addresses.function)) {
- ebpf_load_addresses(&efp->addresses, fs_maps[i + 1].map_fd);
- }
- }
- efp->flags &= ~NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM;
- }
- em->thread_name = saved_name;
- em->kernels = kernels;
- if (!dimensions) {
- dimensions = ebpf_fill_histogram_dimension(NETDATA_EBPF_HIST_MAX_BINS);
- memset(filesystem_aggregated_data, 0 , NETDATA_EBPF_HIST_MAX_BINS * sizeof(netdata_syscall_stat_t));
- memset(filesystem_publish_aggregated, 0 , NETDATA_EBPF_HIST_MAX_BINS * sizeof(netdata_publish_syscall_t));
- filesystem_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
- }
- return 0;
- }
- /**
- * Read Local partitions
- *
- * @return the total of partitions that will be monitored
- */
- static int ebpf_read_local_partitions()
- {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", netdata_configured_host_prefix);
- procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) {
- snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", netdata_configured_host_prefix);
- ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 0;
- }
- ff = procfile_readall(ff);
- if(unlikely(!ff))
- return 0;
- int count = 0;
- unsigned long l, i, lines = procfile_lines(ff);
- for (i = 0; localfs[i].filesystem; i++) {
- localfs[i].flags |= NETDATA_FILESYSTEM_REMOVE_CHARTS;
- }
- for(l = 0; l < lines ; l++) {
- // In "normal" situation the expected value is at column 7
- // When `shared` options is added to mount information, the filesystem is at column 8
- // Finally when we have systemd starting netdata, it will be at column 9
- unsigned long index = procfile_linewords(ff, l) - 3;
- char *fs = procfile_lineword(ff, l, index);
- for (i = 0; localfs[i].filesystem; i++) {
- ebpf_filesystem_partitions_t *w = &localfs[i];
- if (w->enabled && (!strcmp(fs, w->filesystem) ||
- (w->optional_filesystem && !strcmp(fs, w->optional_filesystem)))) {
- localfs[i].flags |= NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM;
- localfs[i].flags &= ~NETDATA_FILESYSTEM_REMOVE_CHARTS;
- count++;
- break;
- }
- }
- }
- procfile_close(ff);
- return count;
- }
- /**
- * Update partition
- *
- * Update the partition structures before to plot
- *
- * @param em main thread structure
- *
- * @return 0 on success and -1 otherwise.
- */
- static int ebpf_update_partitions(ebpf_module_t *em)
- {
- static time_t update_every = 0;
- time_t curr = now_realtime_sec();
- if (curr < update_every)
- return 0;
- update_every = curr + 5 * em->update_every;
- if (!ebpf_read_local_partitions()) {
- em->optional = -1;
- return -1;
- }
- if (ebpf_filesystem_initialize_ebpf_data(em)) {
- return -1;
- }
- return 0;
- }
- /*****************************************************************
- *
- * CLEANUP FUNCTIONS
- *
- *****************************************************************/
- /*
- * Cleanup eBPF data
- */
- void ebpf_filesystem_cleanup_ebpf_data()
- {
- int i;
- for (i = 0; localfs[i].filesystem; i++) {
- ebpf_filesystem_partitions_t *efp = &localfs[i];
- if (efp->probe_links) {
- freez(efp->family_name);
- freez(efp->hread.name);
- freez(efp->hread.title);
- freez(efp->hwrite.name);
- freez(efp->hwrite.title);
- freez(efp->hopen.name);
- freez(efp->hopen.title);
- freez(efp->hadditional.name);
- freez(efp->hadditional.title);
- struct bpf_link **probe_links = efp->probe_links;
- size_t j = 0 ;
- struct bpf_program *prog;
- bpf_object__for_each_program(prog, efp->objects) {
- bpf_link__destroy(probe_links[j]);
- j++;
- }
- bpf_object__close(efp->objects);
- }
- }
- }
- /**
- * Clean up the main thread.
- *
- * @param ptr thread data.
- */
- static void ebpf_filesystem_cleanup(void *ptr)
- {
- ebpf_module_t *em = (ebpf_module_t *)ptr;
- if (!em->enabled)
- return;
- heartbeat_t hb;
- heartbeat_init(&hb);
- uint32_t tick = 2*USEC_PER_MS;
- while (!read_thread_closed) {
- usec_t dt = heartbeat_next(&hb, tick);
- UNUSED(dt);
- }
- freez(filesystem_threads.thread);
- ebpf_cleanup_publish_syscall(filesystem_publish_aggregated);
- ebpf_filesystem_cleanup_ebpf_data();
- if (dimensions)
- ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
- freez(filesystem_hash_values);
- }
- /*****************************************************************
- *
- * MAIN THREAD
- *
- *****************************************************************/
- /**
- * Select hist
- *
- * Select a histogram to store data.
- *
- * @param efp pointer for the structure with pointers.
- * @param id histogram selector
- *
- * @return It returns a pointer for the histogram
- */
- static inline netdata_ebpf_histogram_t *select_hist(ebpf_filesystem_partitions_t *efp, uint32_t *idx, uint32_t id)
- {
- if (id < NETDATA_KEY_CALLS_READ) {
- *idx = id;
- return &efp->hread;
- } else if (id < NETDATA_KEY_CALLS_WRITE) {
- *idx = id - NETDATA_KEY_CALLS_READ;
- return &efp->hwrite;
- } else if (id < NETDATA_KEY_CALLS_OPEN) {
- *idx = id - NETDATA_KEY_CALLS_WRITE;
- return &efp->hopen;
- } else if (id < NETDATA_KEY_CALLS_SYNC ){
- *idx = id - NETDATA_KEY_CALLS_OPEN;
- return &efp->hadditional;
- }
- return NULL;
- }
- /**
- * Read hard disk table
- *
- * @param table index for the hash table
- *
- * Read the table with number of calls for all functions
- */
- static void read_filesystem_table(ebpf_filesystem_partitions_t *efp, int fd)
- {
- netdata_idx_t *values = filesystem_hash_values;
- uint32_t key;
- uint32_t idx;
- for (key = 0; key < NETDATA_KEY_CALLS_SYNC; key++) {
- netdata_ebpf_histogram_t *w = select_hist(efp, &idx, key);
- if (!w) {
- continue;
- }
- int test = bpf_map_lookup_elem(fd, &key, values);
- if (test < 0) {
- continue;
- }
- uint64_t total = 0;
- int i;
- int end = ebpf_nprocs;
- for (i = 0; i < end; i++) {
- total += values[i];
- }
- if (idx >= NETDATA_EBPF_HIST_MAX_BINS)
- idx = NETDATA_EBPF_HIST_MAX_BINS - 1;
- w->histogram[idx] = total;
- }
- }
- /**
- * Read hard disk table
- *
- * @param table index for the hash table
- *
- * Read the table with number of calls for all functions
- */
- static void read_filesystem_tables()
- {
- int i;
- for (i = 0; localfs[i].filesystem; i++) {
- ebpf_filesystem_partitions_t *efp = &localfs[i];
- if (efp->flags & NETDATA_FILESYSTEM_FLAG_HAS_PARTITION) {
- read_filesystem_table(efp, fs_maps[i].map_fd);
- }
- }
- }
- /**
- * Socket read hash
- *
- * This is the thread callback.
- * This thread is necessary, because we cannot freeze the whole plugin to read the data on very busy socket.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
- void *ebpf_filesystem_read_hash(void *ptr)
- {
- ebpf_module_t *em = (ebpf_module_t *)ptr;
- read_thread_closed = 0;
- heartbeat_t hb;
- heartbeat_init(&hb);
- usec_t step = NETDATA_FILESYSTEM_READ_SLEEP_MS * em->update_every;
- int update_every = em->update_every;
- while (!close_ebpf_plugin) {
- usec_t dt = heartbeat_next(&hb, step);
- (void)dt;
- (void) ebpf_update_partitions(em);
- ebpf_obsolete_fs_charts(update_every);
- // No more partitions, it is not necessary to read tables
- if (em->optional)
- continue;
- read_filesystem_tables();
- }
- read_thread_closed = 1;
- return NULL;
- }
- /**
- * Send Hard disk data
- *
- * Send hard disk information to Netdata.
- */
- static void ebpf_histogram_send_data()
- {
- uint32_t i;
- uint32_t test = NETDATA_FILESYSTEM_FLAG_HAS_PARTITION | NETDATA_FILESYSTEM_REMOVE_CHARTS;
- for (i = 0; localfs[i].filesystem; i++) {
- ebpf_filesystem_partitions_t *efp = &localfs[i];
- if ((efp->flags & test) == NETDATA_FILESYSTEM_FLAG_HAS_PARTITION) {
- write_histogram_chart(NETDATA_FILESYSTEM_FAMILY, efp->hread.name,
- efp->hread.histogram, dimensions, NETDATA_EBPF_HIST_MAX_BINS);
- write_histogram_chart(NETDATA_FILESYSTEM_FAMILY, efp->hwrite.name,
- efp->hwrite.histogram, dimensions, NETDATA_EBPF_HIST_MAX_BINS);
- write_histogram_chart(NETDATA_FILESYSTEM_FAMILY, efp->hopen.name,
- efp->hopen.histogram, dimensions, NETDATA_EBPF_HIST_MAX_BINS);
- write_histogram_chart(NETDATA_FILESYSTEM_FAMILY, efp->hadditional.name,
- efp->hadditional.histogram, dimensions, NETDATA_EBPF_HIST_MAX_BINS);
- }
- }
- }
- /**
- * Main loop for this collector.
- *
- * @param em main structure for this thread
- */
- static void filesystem_collector(ebpf_module_t *em)
- {
- filesystem_threads.thread = mallocz(sizeof(netdata_thread_t));
- filesystem_threads.start_routine = ebpf_filesystem_read_hash;
- netdata_thread_create(filesystem_threads.thread, filesystem_threads.name,
- NETDATA_THREAD_OPTION_JOINABLE, ebpf_filesystem_read_hash, em);
- int update_every = em->update_every;
- int counter = update_every - 1;
- while (!close_ebpf_plugin || em->optional) {
- pthread_mutex_lock(&collect_data_mutex);
- pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
- if (++counter == update_every) {
- counter = 0;
- pthread_mutex_lock(&lock);
- ebpf_create_fs_charts(update_every);
- ebpf_histogram_send_data();
- pthread_mutex_unlock(&lock);
- }
- pthread_mutex_unlock(&collect_data_mutex);
- }
- }
- /*****************************************************************
- *
- * ENTRY THREAD
- *
- *****************************************************************/
- /**
- * Update Filesystem
- *
- * Update file system structure using values read from configuration file.
- */
- static void ebpf_update_filesystem()
- {
- char dist[NETDATA_FS_MAX_DIST_NAME + 1];
- int i;
- for (i = 0; localfs[i].filesystem; i++) {
- snprintfz(dist, NETDATA_FS_MAX_DIST_NAME, "%sdist", localfs[i].filesystem);
- localfs[i].enabled = appconfig_get_boolean(&fs_config, NETDATA_FILESYSTEM_CONFIG_NAME, dist,
- CONFIG_BOOLEAN_YES);
- }
- }
- /**
- * Filesystem thread
- *
- * Thread used to generate socket charts.
- *
- * @param ptr a pointer to `struct ebpf_module`
- *
- * @return It always return NULL
- */
- void *ebpf_filesystem_thread(void *ptr)
- {
- netdata_thread_cleanup_push(ebpf_filesystem_cleanup, ptr);
- ebpf_module_t *em = (ebpf_module_t *)ptr;
- em->maps = fs_maps;
- ebpf_update_filesystem();
- if (!em->enabled)
- goto endfilesystem;
- // Initialize optional as zero, to identify when there are not partitions to monitor
- em->optional = 0;
- if (ebpf_update_partitions(em)) {
- if (em->optional)
- info("Netdata cannot monitor the filesystems used on this host.");
- em->enabled = CONFIG_BOOLEAN_NO;
- goto endfilesystem;
- }
- int algorithms[NETDATA_EBPF_HIST_MAX_BINS];
- ebpf_fill_algorithms(algorithms, NETDATA_EBPF_HIST_MAX_BINS, NETDATA_EBPF_INCREMENTAL_IDX);
- ebpf_global_labels(filesystem_aggregated_data, filesystem_publish_aggregated, dimensions, dimensions,
- algorithms, NETDATA_EBPF_HIST_MAX_BINS);
- pthread_mutex_lock(&lock);
- ebpf_create_fs_charts(em->update_every);
- ebpf_update_stats(&plugin_statistics, em);
- pthread_mutex_unlock(&lock);
- filesystem_collector(em);
- endfilesystem:
- if (!em->enabled)
- ebpf_update_disabled_plugin_stats(em);
- netdata_thread_cleanup_pop(1);
- return NULL;
- }
|