From 841395dd16f470e3c051a0a4fff5b91efc983c30 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 19 May 2021 14:33:27 +0200 Subject: Adding upstream version 1.31.0. Signed-off-by: Daniel Baumann --- libnetdata/clocks/clocks.h | 4 +- libnetdata/config/appconfig.c | 2 +- libnetdata/config/appconfig.h | 2 +- libnetdata/ebpf/ebpf.c | 161 ++++++++++++++++++--- libnetdata/ebpf/ebpf.h | 23 ++- libnetdata/health/health.c | 2 +- libnetdata/json/json.c | 6 +- libnetdata/libnetdata.c | 30 ++++ libnetdata/libnetdata.h | 5 + libnetdata/log/log.h | 1 + libnetdata/popen/popen.c | 10 +- libnetdata/procfile/procfile.c | 6 +- libnetdata/procfile/procfile.h | 2 +- libnetdata/socket/security.c | 4 +- libnetdata/storage_number/storage_number.h | 2 +- .../storage_number/tests/test_storage_number.c | 4 +- libnetdata/url/url.c | 4 +- 17 files changed, 228 insertions(+), 40 deletions(-) (limited to 'libnetdata') diff --git a/libnetdata/clocks/clocks.h b/libnetdata/clocks/clocks.h index cfe99f5e7..d3475df6a 100644 --- a/libnetdata/clocks/clocks.h +++ b/libnetdata/clocks/clocks.h @@ -112,8 +112,8 @@ extern int clock_gettime(clockid_t clk_id, struct timespec *ts); * All now_*_timeval() functions fill the `struct timeval` with the time from the appropriate clock. * Those functions return 0 on success, -1 else with errno set appropriately. * - * All now_*_sec() functions return the time in seconds from the approriate clock, or 0 on error. - * All now_*_usec() functions return the time in microseconds from the approriate clock, or 0 on error. + * All now_*_sec() functions return the time in seconds from the appropriate clock, or 0 on error. + * All now_*_usec() functions return the time in microseconds from the appropriate clock, or 0 on error. * * Most functions will attempt to use CLOCK_MONOTONIC_COARSE if available to reduce contention overhead and improve * performance scaling. If high precision is required please use one of the available now_*_high_precision_* functions. diff --git a/libnetdata/config/appconfig.c b/libnetdata/config/appconfig.c index f570f32d7..6e4df2d09 100644 --- a/libnetdata/config/appconfig.c +++ b/libnetdata/config/appconfig.c @@ -302,7 +302,7 @@ int appconfig_move(struct config *root, const char *section_old, const char *nam if(cv_new) goto cleanup; if(unlikely(appconfig_option_index_del(co_old, cv_old) != cv_old)) - error("INTERNAL ERROR: deletion of config '%s' from section '%s', deleted tge wrong config entry.", cv_old->name, co_old->name); + error("INTERNAL ERROR: deletion of config '%s' from section '%s', deleted the wrong config entry.", cv_old->name, co_old->name); if(co_old->values == cv_old) { co_old->values = cv_old->next; diff --git a/libnetdata/config/appconfig.h b/libnetdata/config/appconfig.h index f405eeb09..246d1d5b9 100644 --- a/libnetdata/config/appconfig.h +++ b/libnetdata/config/appconfig.h @@ -131,7 +131,7 @@ struct section { char *name; - struct section *next; // gloabl config_mutex protects just this + struct section *next; // global config_mutex protects just this struct config_option *values; avl_tree_lock values_index; diff --git a/libnetdata/ebpf/ebpf.c b/libnetdata/ebpf/ebpf.c index 8619ae26f..1f71f6a24 100644 --- a/libnetdata/ebpf/ebpf.c +++ b/libnetdata/ebpf/ebpf.c @@ -295,25 +295,112 @@ static int select_file(char *name, const char *program, size_t length, int mode, return ret; } -struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *kernel_string, struct bpf_object **obj, int *map_fd) +void ebpf_update_pid_table(ebpf_local_maps_t *pid, ebpf_module_t *em) +{ + pid->user_input = em->pid_map_size; +} + +void ebpf_update_map_sizes(struct bpf_object *program, ebpf_module_t *em) +{ + struct bpf_map *map; + ebpf_local_maps_t *maps = em->maps; + if (!maps) + return; + + bpf_map__for_each(map, program) + { + const char *map_name = bpf_map__name(map); + int i = 0; ; + while (maps[i].name) { + ebpf_local_maps_t *w = &maps[i]; + if (w->user_input != w->internal_input && !strcmp(w->name, map_name)) { +#ifdef NETDATA_INTERNAL_CHECKS + info("Changing map %s from size %u to %u ", map_name, w->internal_input, w->user_input); +#endif + bpf_map__resize(map, w->user_input); + } + i++; + } + } +} + +size_t ebpf_count_programs(struct bpf_object *obj) +{ + size_t tot = 0; + struct bpf_program *prog; + bpf_object__for_each_program(prog, obj) + { + tot++; + } + + return tot; +} + +static ebpf_specify_name_t *ebpf_find_names(ebpf_specify_name_t *names, const char *prog_name) +{ + size_t i = 0; + while (names[i].program_name) { + if (!strcmp(prog_name, names[i].program_name)) + return &names[i]; + + i++; + } + + return NULL; +} + +static struct bpf_link **ebpf_attach_programs(struct bpf_object *obj, size_t length, ebpf_specify_name_t *names) +{ + struct bpf_link **links = callocz(length , sizeof(struct bpf_link *)); + size_t i = 0; + struct bpf_program *prog; + bpf_object__for_each_program(prog, obj) + { + links[i] = bpf_program__attach(prog); + if (libbpf_get_error(links[i]) && names) { + const char *name = bpf_program__name(prog); + ebpf_specify_name_t *w = ebpf_find_names(names, name); + if (w) { + enum bpf_prog_type type = bpf_program__get_type(prog); + if (type == BPF_PROG_TYPE_KPROBE) + links[i] = bpf_program__attach_kprobe(prog, w->retprobe, w->optional); + } + } + + if (libbpf_get_error(links[i])) { + links[i] = NULL; + } + + i++; + } + + return links; +} + +struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *kernel_string, + struct bpf_object **obj, int *map_fd) { char lpath[4096]; char lname[128]; - int prog_fd; int test = select_file(lname, em->thread_name, (size_t)127, em->mode, kernel_string); if (test < 0 || test > 127) return NULL; snprintf(lpath, 4096, "%s/ebpf.d/%s", plugins_dir, lname); - // We are using BPF_PROG_TYPE_UNSPEC instead a specific type for bpf_prog_load to define the type - // according the eBPF program loaded - if (bpf_prog_load(lpath, BPF_PROG_TYPE_UNSPEC, obj, &prog_fd)) { - em->enabled = CONFIG_BOOLEAN_NO; - info("Cannot load program: %s", lpath); + *obj = bpf_object__open_file(lpath, NULL); + if (libbpf_get_error(obj)) { + error("Cannot open BPF object %s", lpath); + bpf_object__close(*obj); + return NULL; + } + + ebpf_update_map_sizes(*obj, em); + + if (bpf_object__load(*obj)) { + error("ERROR: loading BPF object file failed %s\n", lpath); + bpf_object__close(*obj); return NULL; - } else { - info("The eBPF program %s was loaded with success.", em->thread_name); } struct bpf_map *map; @@ -324,16 +411,53 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char * i++; } - struct bpf_program *prog; - struct bpf_link **links = callocz(NETDATA_MAX_PROBES , sizeof(struct bpf_link *)); - i = 0; - bpf_object__for_each_program(prog, *obj) - { - links[i] = bpf_program__attach(prog); - i++; + size_t count_programs = ebpf_count_programs(*obj); + + return ebpf_attach_programs(*obj, count_programs, em->names); +} + +static char *ebpf_update_name(char *search) +{ + char filename[FILENAME_MAX + 1]; + char *ret = NULL; + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, NETDATA_KALLSYMS); + procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT); + if(unlikely(!ff)) { + error("Cannot open %s%s", netdata_configured_host_prefix, NETDATA_KALLSYMS); + return ret; } - return links; + ff = procfile_readall(ff); + if(unlikely(!ff)) + return ret; + + unsigned long i, lines = procfile_lines(ff); + size_t length = strlen(search); + for(i = 0; i < lines ; i++) { + char *cmp = procfile_lineword(ff, i,2);; + if (!strncmp(search, cmp, length)) { + ret = strdupz(cmp); + break; + } + } + + procfile_close(ff); + + return ret; +} + +void ebpf_update_names(ebpf_specify_name_t *opt, ebpf_module_t *em) +{ + int mode = em->mode; + em->names = opt; + + size_t i = 0; + while (opt[i].program_name) { + opt[i].retprobe = (mode == MODE_RETURN); + opt[i].optional = ebpf_update_name(opt[i].function_to_attach); + + i++; + } } //---------------------------------------------------------------------------------------------------------------------- @@ -368,6 +492,9 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, struct config *cfg) modules->apps_charts = appconfig_get_boolean(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_APPLICATION, CONFIG_BOOLEAN_YES); + + modules->pid_map_size = (uint32_t)appconfig_get_number(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE, + modules->pid_map_size); } diff --git a/libnetdata/ebpf/ebpf.h b/libnetdata/ebpf/ebpf.h index ac3a1a2fc..bc55d9595 100644 --- a/libnetdata/ebpf/ebpf.h +++ b/libnetdata/ebpf/ebpf.h @@ -7,6 +7,7 @@ #include #define NETDATA_DEBUGFS "/sys/kernel/debug/tracing/" +#define NETDATA_KALLSYMS "/proc/kallsyms" // Config files #define EBPF_GLOBAL_SECTION "global" @@ -15,6 +16,7 @@ #define EBPF_CFG_LOAD_MODE_RETURN "return" #define EBPF_CFG_UPDATE_EVERY "update every" +#define EBPF_CFG_PID_SIZE "pid table size" #define EBPF_CFG_APPLICATION "apps" /** @@ -95,6 +97,21 @@ typedef enum { MODE_ENTRY // This attaches kprobe when the function is called } netdata_run_mode_t; +#define ND_EBPF_DEFAULT_PID_SIZE 32768U + +typedef struct ebpf_local_maps { + char *name; + uint32_t internal_input; + uint32_t user_input; +} ebpf_local_maps_t; + +typedef struct ebpf_specify_name { + char *program_name; + char *function_to_attach; + char *optional; + bool retprobe; +} ebpf_specify_name_t; + typedef struct ebpf_module { const char *thread_name; const char *config_name; @@ -107,10 +124,11 @@ typedef struct ebpf_module { uint32_t thread_id; int optional; void (*apps_routine)(struct ebpf_module *em, void *ptr); + ebpf_local_maps_t *maps; + ebpf_specify_name_t *names; + uint32_t pid_map_size; } ebpf_module_t; -#define NETDATA_MAX_PROBES 64 - extern int get_kernel_version(char *out, int size); extern int get_redhat_release(); extern int has_condition_to_run(int version); @@ -126,5 +144,6 @@ extern void ebpf_mount_config_name(char *filename, size_t length, char *path, ch extern int ebpf_load_config(struct config *config, char *filename); extern void ebpf_update_module_using_config(ebpf_module_t *modules, struct config *cfg); extern void ebpf_update_module(ebpf_module_t *em, struct config *cfg, char *cfg_file); +extern void ebpf_update_names(ebpf_specify_name_t *opt, ebpf_module_t *em); #endif /* NETDATA_EBPF_H */ diff --git a/libnetdata/health/health.c b/libnetdata/health/health.c index 74f7a0266..c44ba0828 100644 --- a/libnetdata/health/health.c +++ b/libnetdata/health/health.c @@ -19,7 +19,7 @@ SILENCER *create_silencer(void) { /** * Health Silencers add * - * Add more one silencer to the list of silenecers. + * Add more one silencer to the list of silencers. * * @param silencer */ diff --git a/libnetdata/json/json.c b/libnetdata/json/json.c index bd164aeff..1f391eeaa 100644 --- a/libnetdata/json/json.c +++ b/libnetdata/json/json.c @@ -82,7 +82,7 @@ jsmntok_t *json_tokenise(char *js, size_t len, size_t *count) /** * Callback Print * - * Set callback print case necesary and wrinte an information inside a buffer to write in the log. + * Set callback print case necessary and wrinte an information inside a buffer to write in the log. * * @param e a pointer for a structure that has the complete information about json structure. * @@ -518,8 +518,8 @@ size_t json_walk_tree(char *js, jsmntok_t *t, void *callback_data, int (*callbac * @param callback_data additional data to be used together the callback function * @param callback_function function used to create a silencer. * - * @return JSON_OK case everything happend as expected, JSON_CANNOT_PARSE case there were errors in the - * parsing procces and JSON_CANNOT_DOWNLOAD case the string given(js) is NULL. + * @return JSON_OK case everything happened as expected, JSON_CANNOT_PARSE case there were errors in the + * parsing process and JSON_CANNOT_DOWNLOAD case the string given(js) is NULL. */ int json_parse(char *js, void *callback_data, int (*callback_function)(JSON_ENTRY *)) { diff --git a/libnetdata/libnetdata.c b/libnetdata/libnetdata.c index 6ccb61ede..eb6fce74f 100644 --- a/libnetdata/libnetdata.c +++ b/libnetdata/libnetdata.c @@ -1492,3 +1492,33 @@ char *read_by_filename(char *filename, long *file_size) *file_size = size; return contents; } + +char *find_and_replace(const char *src, const char *find, const char *replace, const char *where) +{ + size_t size = strlen(src) + 1; + size_t find_len = strlen(find); + size_t repl_len = strlen(replace); + char *value, *dst; + + if (likely(where)) + size += (repl_len - find_len); + + value = mallocz(size); + dst = value; + + if (likely(where)) { + size_t count = where - src; + + memmove(dst, src, count); + src += count; + dst += count; + + memmove(dst, replace, repl_len); + src += find_len; + dst += repl_len; + } + + strcpy(dst, src); + + return value; +} diff --git a/libnetdata/libnetdata.h b/libnetdata/libnetdata.h index 212273870..77a1bbe7f 100644 --- a/libnetdata/libnetdata.h +++ b/libnetdata/libnetdata.h @@ -118,6 +118,10 @@ extern "C" { #include #endif +#ifdef HAVE_LINUX_MAGIC_H +#include +#endif + #ifdef HAVE_SYS_MOUNT_H #include #endif @@ -279,6 +283,7 @@ extern void recursive_config_double_dir_load( , size_t depth ); extern char *read_by_filename(char *filename, long *file_size); +extern char *find_and_replace(const char *src, const char *find, const char *replace, const char *where); /* fix for alpine linux */ #ifndef RUSAGE_THREAD diff --git a/libnetdata/log/log.h b/libnetdata/log/log.h index c99c15165..58cc0d26c 100644 --- a/libnetdata/log/log.h +++ b/libnetdata/log/log.h @@ -40,6 +40,7 @@ extern "C" { #define D_STATSD 0x0000000010000000 #define D_POLLFD 0x0000000020000000 #define D_STREAM 0x0000000040000000 +#define D_ANALYTICS 0x0000000080000000 #define D_RRDENGINE 0x0000000100000000 #define D_ACLK 0x0000000200000000 #define D_METADATALOG 0x0000000400000000 diff --git a/libnetdata/popen/popen.c b/libnetdata/popen/popen.c index c0135cf40..33f4bd950 100644 --- a/libnetdata/popen/popen.c +++ b/libnetdata/popen/popen.c @@ -296,8 +296,14 @@ int custom_pclose(FILE *fp, pid_t pid) { return(info.si_status); case CLD_KILLED: - error("child pid %d killed by signal %d.", info.si_pid, info.si_status); - return(-1); + if(info.si_status == 15) { + info("child pid %d killed by signal %d.", info.si_pid, info.si_status); + return(0); + } + else { + error("child pid %d killed by signal %d.", info.si_pid, info.si_status); + return(-1); + } case CLD_DUMPED: error("child pid %d core dumped by signal %d.", info.si_pid, info.si_status); diff --git a/libnetdata/procfile/procfile.c b/libnetdata/procfile/procfile.c index 4a812baab..9867c19f6 100644 --- a/libnetdata/procfile/procfile.c +++ b/libnetdata/procfile/procfile.c @@ -312,9 +312,9 @@ procfile *procfile_readall(procfile *ff) { NOINLINE static void procfile_set_separators(procfile *ff, const char *separators) { static PF_CHAR_TYPE def[256]; - static char initilized = 0; + static char initialized = 0; - if(unlikely(!initilized)) { + if(unlikely(!initialized)) { // this is thread safe // if initialized is zero, multiple threads may be executing // this code at the same time, setting in def[] the exact same values @@ -330,7 +330,7 @@ static void procfile_set_separators(procfile *ff, const char *separators) { def[i] = PF_CHAR_IS_WORD; } - initilized = 1; + initialized = 1; } // copy the default diff --git a/libnetdata/procfile/procfile.h b/libnetdata/procfile/procfile.h index b107358ab..d29adf8e6 100644 --- a/libnetdata/procfile/procfile.h +++ b/libnetdata/procfile/procfile.h @@ -50,7 +50,7 @@ typedef struct { char filename[FILENAME_MAX + 1]; // not populated until profile_filename() is called uint32_t flags; - int fd; // the file desriptor + int fd; // the file descriptor size_t len; // the bytes we have placed into data size_t size; // the bytes we have allocated for data pflines *lines; diff --git a/libnetdata/socket/security.c b/libnetdata/socket/security.c index 53366c4d8..63a71bcbd 100644 --- a/libnetdata/socket/security.c +++ b/libnetdata/socket/security.c @@ -201,7 +201,7 @@ static SSL_CTX * security_initialize_openssl_server() { * @param selector informs the context that must be initialized, the following list has the valid values: * NETDATA_SSL_CONTEXT_SERVER - the server context * NETDATA_SSL_CONTEXT_STREAMING - Starts the streaming context. - * NETDATA_SSL_CONTEXT_EXPORTING - Starts the OpenTSDB contextv + * NETDATA_SSL_CONTEXT_EXPORTING - Starts the OpenTSDB context */ void security_start_ssl(int selector) { switch (selector) { @@ -218,7 +218,7 @@ void security_start_ssl(int selector) { case NETDATA_SSL_CONTEXT_STREAMING: { netdata_client_ctx = security_initialize_openssl_client(); //This is necessary for the stream, because it is working sometimes with nonblock socket. - //It returns the bitmask afte to change, there is not any description of errors in the documentation + //It returns the bitmask after to change, there is not any description of errors in the documentation SSL_CTX_set_mode(netdata_client_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE |SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |SSL_MODE_AUTO_RETRY); break; } diff --git a/libnetdata/storage_number/storage_number.h b/libnetdata/storage_number/storage_number.h index 28b7f267c..4ad7ff624 100644 --- a/libnetdata/storage_number/storage_number.h +++ b/libnetdata/storage_number/storage_number.h @@ -62,7 +62,7 @@ typedef uint32_t storage_number; #define SN_EXISTS (1 << 24) // the value exists #define SN_EXISTS_RESET (1 << 25) // the value has been overflown -#define SN_EXISTS_100 (1 << 26) // very large value (multipler is 100 instead of 10) +#define SN_EXISTS_100 (1 << 26) // very large value (multiplier is 100 instead of 10) // extract the flags #define get_storage_number_flags(value) ((((storage_number)(value)) & (1 << 24)) | (((storage_number)(value)) & (1 << 25)) | (((storage_number)(value)) & (1 << 26))) diff --git a/libnetdata/storage_number/tests/test_storage_number.c b/libnetdata/storage_number/tests/test_storage_number.c index 0e1320877..7ef18b1de 100644 --- a/libnetdata/storage_number/tests/test_storage_number.c +++ b/libnetdata/storage_number/tests/test_storage_number.c @@ -5,7 +5,7 @@ #include #include -static void test_number_pinting(void **state) +static void test_number_printing(void **state) { (void)state; @@ -45,7 +45,7 @@ static void test_number_pinting(void **state) int main(void) { const struct CMUnitTest tests[] = { - cmocka_unit_test(test_number_pinting) + cmocka_unit_test(test_number_printing) }; return cmocka_run_group_tests_name("storage_number", tests, NULL, NULL); diff --git a/libnetdata/url/url.c b/libnetdata/url/url.c index 3de94fde7..f90b3d589 100644 --- a/libnetdata/url/url.c +++ b/libnetdata/url/url.c @@ -68,7 +68,7 @@ char url_percent_escape_decode(char *s) { * * @param c is the utf8 character * * - * @return It reurns the length of the specific character. + * @return It returns the length of the specific character. */ char url_utf8_get_byte_length(char c) { if(!IS_UTF8_BYTE(c)) @@ -226,7 +226,7 @@ char *url_decode_r(char *to, char *url, size_t size) { *d = '\0'; - if(unlikely( utf8_check((unsigned char *)to) )) //NULL means sucess here + if(unlikely( utf8_check((unsigned char *)to) )) //NULL means success here return NULL; return to; -- cgit v1.2.3