From bb50acdcb8073654ea667b8c0272e335bd43f844 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 14 Apr 2022 20:12:14 +0200 Subject: Merging upstream version 1.34.0. Signed-off-by: Daniel Baumann --- collectors/ebpf.plugin/ebpf_sync.c | 205 +++++++++++++++++++++++++++++++++++-- 1 file changed, 194 insertions(+), 11 deletions(-) (limited to 'collectors/ebpf.plugin/ebpf_sync.c') diff --git a/collectors/ebpf.plugin/ebpf_sync.c b/collectors/ebpf.plugin/ebpf_sync.c index b3f1b6524..233c34a5b 100644 --- a/collectors/ebpf.plugin/ebpf_sync.c +++ b/collectors/ebpf.plugin/ebpf_sync.c @@ -44,21 +44,179 @@ struct config sync_config = { .first_section = NULL, .rwlock = AVL_LOCK_INITIALIZER } }; ebpf_sync_syscalls_t local_syscalls[] = { - {.syscall = "sync", .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, - {.syscall = "syncfs", .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, - {.syscall = "msync", .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, - {.syscall = "fsync", .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, - {.syscall = "fdatasync", .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, - {.syscall = "sync_file_range", .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, + {.syscall = NETDATA_SYSCALLS_SYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, + {.syscall = NETDATA_SYSCALLS_SYNCFS, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, + {.syscall = NETDATA_SYSCALLS_MSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, + {.syscall = NETDATA_SYSCALLS_FSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, + {.syscall = NETDATA_SYSCALLS_FDATASYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, + {.syscall = NETDATA_SYSCALLS_SYNC_FILE_RANGE, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL}, {.syscall = NULL, .enabled = CONFIG_BOOLEAN_NO, .objects = NULL, .probe_links = NULL} }; +netdata_ebpf_targets_t sync_targets[] = { {.name = NETDATA_SYSCALLS_SYNC, .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = NETDATA_SYSCALLS_SYNCFS, .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = NETDATA_SYSCALLS_MSYNC, .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = NETDATA_SYSCALLS_FSYNC, .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = NETDATA_SYSCALLS_FDATASYNC, .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = NETDATA_SYSCALLS_SYNC_FILE_RANGE, .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}}; + + +#ifdef LIBBPF_MAJOR_VERSION +/***************************************************************** + * + * BTF FUNCTIONS + * + *****************************************************************/ + +/** + * Disable probe + * + * Disable kprobe to use another method. + * + * @param obj is the main structure for bpf objects. + */ +static inline void ebpf_sync_disable_probe(struct sync_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_sync_kprobe, false); +} + +/** + * Disable tramppoline + * + * Disable trampoline to use another method. + * + * @param obj is the main structure for bpf objects. + */ +static inline void ebpf_sync_disable_trampoline(struct sync_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_sync_fentry, false); +} + +/** + * Disable tracepoint + * + * Disable tracepoints according information given. + * + * @param obj object loaded + * @param idx Which syscall will not be disabled + */ +void ebpf_sync_disable_tracepoints(struct sync_bpf *obj, sync_syscalls_index_t idx) +{ + if (idx != NETDATA_SYNC_SYNC_IDX) + bpf_program__set_autoload(obj->progs.netdata_sync_entry, false); + + if (idx != NETDATA_SYNC_SYNCFS_IDX) + bpf_program__set_autoload(obj->progs.netdata_syncfs_entry, false); + + if (idx != NETDATA_SYNC_MSYNC_IDX) + bpf_program__set_autoload(obj->progs.netdata_msync_entry, false); + + if (idx != NETDATA_SYNC_FSYNC_IDX) + bpf_program__set_autoload(obj->progs.netdata_fsync_entry, false); + + if (idx != NETDATA_SYNC_FDATASYNC_IDX) + bpf_program__set_autoload(obj->progs.netdata_fdatasync_entry, false); + + if (idx != NETDATA_SYNC_SYNC_FILE_RANGE_IDX) + bpf_program__set_autoload(obj->progs.netdata_sync_file_range_entry, false); +} + +/** + * Set hash tables + * + * Set the values for maps according the value given by kernel. + * + * @param obj is the main structure for bpf objects. + * @param idx the index for the main structure + */ +static void ebpf_sync_set_hash_tables(struct sync_bpf *obj, sync_syscalls_index_t idx) +{ + sync_maps[idx].map_fd = bpf_map__fd(obj->maps.tbl_sync); +} + +/** + * Load and attach + * + * Load and attach the eBPF code in kernel. + * + * @param obj is the main structure for bpf objects. + * @param em the structure with configuration + * @param target the syscall that we are attaching a tracer. + * @param idx the index for the main structure + * + * @return it returns 0 on succes and -1 otherwise + */ +static inline int ebpf_sync_load_and_attach(struct sync_bpf *obj, ebpf_module_t *em, char *target, + sync_syscalls_index_t idx) +{ + netdata_ebpf_targets_t *synct = em->targets; + netdata_ebpf_program_loaded_t test = synct[NETDATA_SYNC_SYNC_IDX].mode; + + if (test == EBPF_LOAD_TRAMPOLINE) { + ebpf_sync_disable_probe(obj); + ebpf_sync_disable_tracepoints(obj, NETDATA_SYNC_IDX_END); + + bpf_program__set_attach_target(obj->progs.netdata_sync_fentry, 0, + target); + } else if (test == EBPF_LOAD_PROBE || + test == EBPF_LOAD_RETPROBE) { + ebpf_sync_disable_tracepoints(obj, NETDATA_SYNC_IDX_END); + ebpf_sync_disable_trampoline(obj); + } else { + ebpf_sync_disable_probe(obj); + ebpf_sync_disable_trampoline(obj); + + ebpf_sync_disable_tracepoints(obj, idx); + } + + int ret = sync_bpf__load(obj); + if (!ret) { + if (test != EBPF_LOAD_PROBE && test != EBPF_LOAD_RETPROBE) { + ret = sync_bpf__attach(obj); + } else { + obj->links.netdata_sync_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_sync_kprobe, + false, target); + ret = (int)libbpf_get_error(obj->links.netdata_sync_kprobe); + } + + if (!ret) + ebpf_sync_set_hash_tables(obj, idx); + } + + return ret; +} +#endif + /***************************************************************** * * INITIALIZE THREAD * *****************************************************************/ +/** + * Load Legacy + * + * Load legacy code. + * + * @param w is the sync output structure with pointers to objects loaded. + * @param em is structure with configuration + * + * @return 0 on success and -1 otherwise. + */ +static int ebpf_sync_load_legacy(ebpf_sync_syscalls_t *w, ebpf_module_t *em) +{ + em->thread_name = w->syscall; + if (!w->probe_links) { + w->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &w->objects); + if (!w->probe_links) { + return -1; + } + } + + return 0; +} + /* * Initialize Syscalls * @@ -70,15 +228,33 @@ static int ebpf_sync_initialize_syscall(ebpf_module_t *em) { int i; const char *saved_name = em->thread_name; + sync_syscalls_index_t errors = 0; for (i = 0; local_syscalls[i].syscall; i++) { ebpf_sync_syscalls_t *w = &local_syscalls[i]; - if (!w->probe_links && w->enabled) { - em->thread_name = w->syscall; - w->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &w->objects); - if (!w->probe_links) { + if (w->enabled) { + if (em->load == EBPF_LOAD_LEGACY) { + if (ebpf_sync_load_legacy(w, em)) + errors++; + em->thread_name = saved_name; - return -1; } +#ifdef LIBBPF_MAJOR_VERSION + else { + char syscall[NETDATA_EBPF_MAX_SYSCALL_LENGTH]; + ebpf_select_host_prefix(syscall, NETDATA_EBPF_MAX_SYSCALL_LENGTH, w->syscall, running_on_kernel); + w->sync_obj = sync_bpf__open(); + if (!w->sync_obj) { + errors++; + } else { + if (ebpf_sync_load_and_attach(w->sync_obj, em, syscall, i)) { + if (ebpf_sync_load_legacy(w, em)) + errors++; + + em->thread_name = saved_name; + } + } + } +#endif } } em->thread_name = saved_name; @@ -254,6 +430,10 @@ void ebpf_sync_cleanup_objects() } bpf_object__close(w->objects); } +#ifdef LIBBPF_MAJOR_VERSION + else if (w->sync_obj) + sync_bpf__destroy(w->sync_obj); +#endif } } @@ -386,6 +566,9 @@ void *ebpf_sync_thread(void *ptr) if (!em->enabled) goto endsync; +#ifdef LIBBPF_MAJOR_VERSION + ebpf_adjust_thread_load(em, default_btf); +#endif if (ebpf_sync_initialize_syscall(em)) { em->enabled = CONFIG_BOOLEAN_NO; goto endsync; -- cgit v1.2.3