diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-07-20 04:49:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-07-20 04:49:55 +0000 |
commit | ab1bb5b7f1c3c3a7b240ab7fc8661459ecd7decb (patch) | |
tree | 7a900833aad3ccc685712c6c2a7d87576d54f427 /collectors/ebpf.plugin/ebpf_filesystem.c | |
parent | Adding upstream version 1.40.1. (diff) | |
download | netdata-878715cc218c4a71a71c4cb4b4634082aa9627ba.tar.xz netdata-878715cc218c4a71a71c4cb4b4634082aa9627ba.zip |
Adding upstream version 1.41.0.upstream/1.41.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'collectors/ebpf.plugin/ebpf_filesystem.c')
-rw-r--r-- | collectors/ebpf.plugin/ebpf_filesystem.c | 387 |
1 files changed, 350 insertions, 37 deletions
diff --git a/collectors/ebpf.plugin/ebpf_filesystem.c b/collectors/ebpf.plugin/ebpf_filesystem.c index 63f592eb9..2bff738ca 100644 --- a/collectors/ebpf.plugin/ebpf_filesystem.c +++ b/collectors/ebpf.plugin/ebpf_filesystem.c @@ -131,6 +131,202 @@ static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST char **dimensions = NULL; static netdata_idx_t *filesystem_hash_values = NULL; +#ifdef LIBBPF_MAJOR_VERSION +/** + * FS disable kprobe + * + * Disable kprobes, because system will use trampolines. + * We are not calling this function for while, because we are prioritizing kprobes. We opted by this road, because + * distribution are still not deliverying necessary btf files per FS. + * + * @param obj FS object loaded. + */ +static void ebpf_fs_disable_kprobe(struct filesystem_bpf *obj) + { + // kprobe + bpf_program__set_autoload(obj->progs.netdata_fs_file_read_probe, false); + bpf_program__set_autoload(obj->progs.netdata_fs_file_write_probe, false); + bpf_program__set_autoload(obj->progs.netdata_fs_file_open_probe, false); + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_probe, false); + bpf_program__set_autoload(obj->progs.netdata_fs_getattr_probe, false); + // kretprobe + bpf_program__set_autoload(obj->progs.netdata_fs_file_read_retprobe, false); + bpf_program__set_autoload(obj->progs.netdata_fs_file_write_retprobe, false); + bpf_program__set_autoload(obj->progs.netdata_fs_file_open_retprobe, false); + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_retprobe, false); + bpf_program__set_autoload(obj->progs.netdata_fs_getattr_retprobe, false); + } + + /** + * Disable trampoline + * + * Disable trampolines to use kprobes. + * + * @param obj FS object loaded. + */ + static void ebpf_fs_disable_trampoline(struct filesystem_bpf *obj) + { + // entry + bpf_program__set_autoload(obj->progs.netdata_fs_file_read_entry, false); + bpf_program__set_autoload(obj->progs.netdata_fs_file_write_entry, false); + bpf_program__set_autoload(obj->progs.netdata_fs_file_open_entry, false); + bpf_program__set_autoload(obj->progs.netdata_fs_getattr_entry, false); + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_entry, false); + + // exit + bpf_program__set_autoload(obj->progs.netdata_fs_file_read_exit, false); + bpf_program__set_autoload(obj->progs.netdata_fs_file_write_exit, false); + bpf_program__set_autoload(obj->progs.netdata_fs_file_open_exit, false); + bpf_program__set_autoload(obj->progs.netdata_fs_getattr_exit, false); + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_exit, false); + } + + /** + * Set targets + * + * Set targets for each objects. + * + * @param obj FS object loaded. + * @param functions array with function names. + */ + static void ebpf_fs_set_target(struct filesystem_bpf *obj, const char **functions) +{ + // entry + bpf_program__set_attach_target(obj->progs.netdata_fs_file_read_entry, 0, + functions[NETDATA_KEY_BTF_READ]); + bpf_program__set_attach_target(obj->progs.netdata_fs_file_write_entry, 0, + functions[NETDATA_KEY_BTF_WRITE]); + bpf_program__set_attach_target(obj->progs.netdata_fs_file_open_entry, 0, + functions[NETDATA_KEY_BTF_OPEN]); + bpf_program__set_attach_target(obj->progs.netdata_fs_getattr_entry, 0, + functions[NETDATA_KEY_BTF_SYNC_ATTR]); + + // exit + bpf_program__set_attach_target(obj->progs.netdata_fs_file_read_exit, 0, + functions[NETDATA_KEY_BTF_READ]); + bpf_program__set_attach_target(obj->progs.netdata_fs_file_write_exit, 0, + functions[NETDATA_KEY_BTF_WRITE]); + bpf_program__set_attach_target(obj->progs.netdata_fs_file_open_exit, 0, + functions[NETDATA_KEY_BTF_OPEN]); + bpf_program__set_attach_target(obj->progs.netdata_fs_getattr_exit, 0, + functions[NETDATA_KEY_BTF_SYNC_ATTR]); + + if (functions[NETDATA_KEY_BTF_OPEN2]) { + bpf_program__set_attach_target(obj->progs.netdata_fs_2nd_file_open_entry, 0, + functions[NETDATA_KEY_BTF_OPEN2]); + bpf_program__set_attach_target(obj->progs.netdata_fs_2nd_file_open_exit, 0, + functions[NETDATA_KEY_BTF_OPEN2]); + } else { + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_entry, false); + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_exit, false); + } +} + +/** + * Attach Kprobe + * + * Attach kprobe on targets + * + * @param obj FS object loaded. + * @param functions array with function names. + */ +static int ebpf_fs_attach_kprobe(struct filesystem_bpf *obj, const char **functions) +{ + // kprobe + obj->links.netdata_fs_file_read_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_read_probe, + false, functions[NETDATA_KEY_BTF_READ]); + if (libbpf_get_error(obj->links.netdata_fs_file_read_probe)) + return -1; + + obj->links.netdata_fs_file_write_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_write_probe, + false, functions[NETDATA_KEY_BTF_WRITE]); + if (libbpf_get_error(obj->links.netdata_fs_file_write_probe)) + return -1; + + obj->links.netdata_fs_file_open_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_open_probe, + false, functions[NETDATA_KEY_BTF_OPEN]); + if (libbpf_get_error(obj->links.netdata_fs_file_open_probe)) + return -1; + + obj->links.netdata_fs_getattr_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_getattr_probe, + false, functions[NETDATA_KEY_BTF_SYNC_ATTR]); + if (libbpf_get_error(obj->links.netdata_fs_getattr_probe)) + return -1; + + // kretprobe + obj->links.netdata_fs_file_read_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_read_retprobe, + false, functions[NETDATA_KEY_BTF_READ]); + if (libbpf_get_error(obj->links.netdata_fs_file_read_retprobe)) + return -1; + + obj->links.netdata_fs_file_write_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_write_retprobe, + false, functions[NETDATA_KEY_BTF_WRITE]); + if (libbpf_get_error(obj->links.netdata_fs_file_write_retprobe)) + return -1; + + obj->links.netdata_fs_file_open_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_open_retprobe, + false, functions[NETDATA_KEY_BTF_OPEN]); + if (libbpf_get_error(obj->links.netdata_fs_file_open_retprobe)) + return -1; + + obj->links.netdata_fs_getattr_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_getattr_retprobe, + false, functions[NETDATA_KEY_BTF_SYNC_ATTR]); + if (libbpf_get_error(obj->links.netdata_fs_getattr_retprobe)) + return -1; + + if (functions[NETDATA_KEY_BTF_OPEN2]) { + obj->links.netdata_fs_2nd_file_open_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_2nd_file_open_probe, + false, functions[NETDATA_KEY_BTF_OPEN2]); + if (libbpf_get_error(obj->links.netdata_fs_2nd_file_open_probe)) + return -1; + + obj->links.netdata_fs_2nd_file_open_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_2nd_file_open_retprobe, + false, functions[NETDATA_KEY_BTF_OPEN2]); + if (libbpf_get_error(obj->links.netdata_fs_2nd_file_open_retprobe)) + return -1; + } + + return 0; +} + +/** + * Load and Attach + * + * Load binary and attach to targets. + * + * @param map Structure with information about maps. + * @param obj FS object loaded. + * @param functions array with function names. + * @param bf sttruct with btf file loaded. + */ +static inline int ebpf_fs_load_and_attach(ebpf_local_maps_t *map, struct filesystem_bpf *obj, + const char **functions, struct btf *bf) +{ + if (bf) { + ebpf_fs_disable_kprobe(obj); + ebpf_fs_set_target(obj, functions); + } else { + ebpf_fs_disable_trampoline(obj); + } + + int ret = filesystem_bpf__load(obj); + if (ret) { + fprintf(stderr, "failed to load BPF object: %d\n", ret); + return -1; + } + + if (bf) + ret = filesystem_bpf__attach(obj); + else + ret = ebpf_fs_attach_kprobe(obj, functions); + + if (!ret) + map->map_fd = bpf_map__fd(obj->maps.tbl_fs);; + + return ret; +} +#endif + /***************************************************************** * * COMMON FUNCTIONS @@ -199,13 +395,15 @@ static void ebpf_create_fs_charts(int update_every) snprintfz(chart_name, 63, "%s_read_latency", efp->filesystem); efp->hread.name = strdupz(chart_name); efp->hread.title = strdupz(title); + efp->hread.ctx = NULL; efp->hread.order = order; efp->family_name = strdupz(family); ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hread.name, - title, - EBPF_COMMON_DIMENSION_CALL, family, - "filesystem.read_latency", NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension, + efp->hread.title, + EBPF_COMMON_DIMENSION_CALL, efp->family_name, + "filesystem.read_latency", 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++; @@ -214,11 +412,13 @@ static void ebpf_create_fs_charts(int update_every) snprintfz(chart_name, 63, "%s_write_latency", efp->filesystem); efp->hwrite.name = strdupz(chart_name); efp->hwrite.title = strdupz(title); + efp->hwrite.ctx = NULL; efp->hwrite.order = order; ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hwrite.name, - title, - EBPF_COMMON_DIMENSION_CALL, family, - "filesystem.write_latency", NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension, + efp->hwrite.title, + EBPF_COMMON_DIMENSION_CALL, efp->family_name, + "filesystem.write_latency", 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++; @@ -227,11 +427,13 @@ static void ebpf_create_fs_charts(int update_every) snprintfz(chart_name, 63, "%s_open_latency", efp->filesystem); efp->hopen.name = strdupz(chart_name); efp->hopen.title = strdupz(title); + efp->hopen.ctx = NULL; efp->hopen.order = order; ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hopen.name, - title, - EBPF_COMMON_DIMENSION_CALL, family, - "filesystem.open_latency", NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension, + efp->hopen.title, + EBPF_COMMON_DIMENSION_CALL, efp->family_name, + "filesystem.open_latency", 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++; @@ -242,9 +444,10 @@ static void ebpf_create_fs_charts(int update_every) snprintfz(ctx, 63, "filesystem.%s_latency", type); efp->hadditional.name = strdupz(chart_name); efp->hadditional.title = strdupz(title); + efp->hadditional.ctx = strdupz(ctx); efp->hadditional.order = order; - ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hadditional.name, title, - EBPF_COMMON_DIMENSION_CALL, family, + ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hadditional.name, efp->hadditional.title, + EBPF_COMMON_DIMENSION_CALL, efp->family_name, ctx, 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); @@ -252,6 +455,8 @@ static void ebpf_create_fs_charts(int update_every) efp->flags |= NETDATA_FILESYSTEM_FLAG_CHART_CREATED; } } + + fflush(stdout); } /** @@ -263,6 +468,7 @@ static void ebpf_create_fs_charts(int update_every) */ int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em) { + pthread_mutex_lock(&lock); int i; const char *saved_name = em->thread_name; uint64_t kernels = em->kernels; @@ -275,17 +481,32 @@ int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em) #ifdef LIBBPF_MAJOR_VERSION ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel); #endif - 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; - em->maps = NULL; - return -1; + if (em->load & EBPF_LOAD_LEGACY) { + 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; + em->maps = NULL; + pthread_mutex_unlock(&lock); + return -1; + } } +#ifdef LIBBPF_MAJOR_VERSION + else { + efp->fs_obj = filesystem_bpf__open(); + if (!efp->fs_obj) { + em->thread_name = saved_name; + em->kernels = kernels; + return -1; + } else { + if (ebpf_fs_load_and_attach(em->maps, efp->fs_obj, + efp->functions, NULL)) + return -1; + } + } +#endif efp->flags |= NETDATA_FILESYSTEM_FLAG_HAS_PARTITION; - pthread_mutex_lock(&lock); ebpf_update_kernel_memory(&plugin_statistics, efp->fs_maps, EBPF_ACTION_STAT_ADD); - pthread_mutex_unlock(&lock); // Nedeed for filesystems like btrfs if ((efp->flags & NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE) && (efp->addresses.function)) { @@ -295,6 +516,7 @@ int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em) efp->flags &= ~NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM; } em->thread_name = saved_name; + pthread_mutex_unlock(&lock); em->kernels = kernels; em->maps = NULL; @@ -405,43 +627,88 @@ void ebpf_filesystem_cleanup_ebpf_data() ebpf_filesystem_partitions_t *efp = &localfs[i]; if (efp->probe_links) { freez(efp->family_name); + efp->family_name = NULL; freez(efp->hread.name); + efp->hread.name = NULL; freez(efp->hread.title); + efp->hread.title = NULL; freez(efp->hwrite.name); + efp->hwrite.name = NULL; freez(efp->hwrite.title); + efp->hwrite.title = NULL; freez(efp->hopen.name); + efp->hopen.name = NULL; freez(efp->hopen.title); + efp->hopen.title = NULL; freez(efp->hadditional.name); + efp->hadditional.name = NULL; freez(efp->hadditional.title); + efp->hadditional.title = NULL; + freez(efp->hadditional.ctx); + efp->hadditional.ctx = NULL; } } } /** - * Filesystem Free + * Obsolete global * - * Cleanup variables after child threads to stop + * Obsolete global charts created by thread. * - * @param ptr thread data. + * @param em a pointer to `struct ebpf_module` */ -static void ebpf_filesystem_free(ebpf_module_t *em) +static void ebpf_obsolete_filesystem_global(ebpf_module_t *em) { - pthread_mutex_lock(&ebpf_exit_cleanup); - em->enabled = NETDATA_THREAD_EBPF_STOPPING; - pthread_mutex_unlock(&ebpf_exit_cleanup); - - ebpf_filesystem_cleanup_ebpf_data(); - if (dimensions) - ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS); - freez(filesystem_hash_values); + int i; + for (i = 0; localfs[i].filesystem; i++) { + ebpf_filesystem_partitions_t *efp = &localfs[i]; + if (!efp->objects) + continue; - pthread_mutex_lock(&ebpf_exit_cleanup); - em->enabled = NETDATA_THREAD_EBPF_STOPPED; - pthread_mutex_unlock(&ebpf_exit_cleanup); + ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, + efp->hread.name, + efp->hread.title, + EBPF_COMMON_DIMENSION_CALL, + efp->family_name, + NETDATA_EBPF_CHART_TYPE_STACKED, + "filesystem.read_latency", + efp->hread.order, + em->update_every); + + ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, + efp->hwrite.name, + efp->hwrite.title, + EBPF_COMMON_DIMENSION_CALL, + efp->family_name, + NETDATA_EBPF_CHART_TYPE_STACKED, + "filesystem.write_latency", + efp->hwrite.order, + em->update_every); + + ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, + efp->hopen.name, + efp->hopen.title, + EBPF_COMMON_DIMENSION_CALL, + efp->family_name, + NETDATA_EBPF_CHART_TYPE_STACKED, + "filesystem.open_latency", + efp->hopen.order, + em->update_every); + + ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, + efp->hadditional.name, + efp->hadditional.title, + EBPF_COMMON_DIMENSION_CALL, + efp->family_name, + NETDATA_EBPF_CHART_TYPE_STACKED, + efp->hadditional.ctx, + efp->hadditional.order, + em->update_every); + } } /** @@ -454,7 +721,39 @@ static void ebpf_filesystem_free(ebpf_module_t *em) static void ebpf_filesystem_exit(void *ptr) { ebpf_module_t *em = (ebpf_module_t *)ptr; - ebpf_filesystem_free(em); + + if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) { + pthread_mutex_lock(&lock); + ebpf_obsolete_filesystem_global(em); + + pthread_mutex_unlock(&lock); + fflush(stdout); + } + + ebpf_filesystem_cleanup_ebpf_data(); + if (dimensions) { + ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS); + dimensions = NULL; + } + + freez(filesystem_hash_values); + + int i; + for (i = 0; localfs[i].filesystem; i++) { + ebpf_filesystem_partitions_t *efp = &localfs[i]; + if (!efp->probe_links) + continue; + + ebpf_unload_legacy_code(efp->objects, efp->probe_links); + efp->objects = NULL; + efp->probe_links = NULL; + efp->flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION; + } + + pthread_mutex_lock(&ebpf_exit_cleanup); + em->enabled = NETDATA_THREAD_EBPF_STOPPED; + ebpf_update_stats(&plugin_statistics, em); + pthread_mutex_unlock(&ebpf_exit_cleanup); } /***************************************************************** @@ -608,7 +907,9 @@ static void filesystem_collector(ebpf_module_t *em) heartbeat_t hb; heartbeat_init(&hb); int counter = update_every - 1; - while (!ebpf_exit_plugin) { + uint32_t running_time = 0; + uint32_t lifetime = em->lifetime; + while (!ebpf_exit_plugin && running_time < lifetime) { (void)heartbeat_next(&hb, USEC_PER_SEC); if (ebpf_exit_plugin || ++counter != update_every) @@ -622,6 +923,15 @@ static void filesystem_collector(ebpf_module_t *em) ebpf_histogram_send_data(); pthread_mutex_unlock(&lock); + + pthread_mutex_lock(&ebpf_exit_cleanup); + if (running_time && !em->running_time) + running_time = update_every; + else + running_time += update_every; + + em->running_time = running_time; + pthread_mutex_unlock(&ebpf_exit_cleanup); } } @@ -683,9 +993,12 @@ void *ebpf_filesystem_thread(void *ptr) // Initialize optional as zero, to identify when there are not partitions to monitor em->optional = 0; +#ifdef LIBBPF_MAJOR_VERSION + ebpf_adjust_thread_load(em, default_btf); +#endif if (ebpf_update_partitions(em)) { if (em->optional) - info("Netdata cannot monitor the filesystems used on this host."); + netdata_log_info("Netdata cannot monitor the filesystems used on this host."); goto endfilesystem; } |