summaryrefslogtreecommitdiffstats
path: root/libnetdata
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2021-05-19 12:33:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2021-05-19 12:33:59 +0000
commit1ee0c09c5742557e037df5421ca62abddb90ae22 (patch)
tree71c0fa48bb6d31d036c9badd7e038527f90d1a73 /libnetdata
parentReleasing debian version 1.30.1-1. (diff)
downloadnetdata-1ee0c09c5742557e037df5421ca62abddb90ae22.tar.xz
netdata-1ee0c09c5742557e037df5421ca62abddb90ae22.zip
Merging upstream version 1.31.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libnetdata')
-rw-r--r--libnetdata/clocks/clocks.h4
-rw-r--r--libnetdata/config/appconfig.c2
-rw-r--r--libnetdata/config/appconfig.h2
-rw-r--r--libnetdata/ebpf/ebpf.c161
-rw-r--r--libnetdata/ebpf/ebpf.h23
-rw-r--r--libnetdata/health/health.c2
-rw-r--r--libnetdata/json/json.c6
-rw-r--r--libnetdata/libnetdata.c30
-rw-r--r--libnetdata/libnetdata.h5
-rw-r--r--libnetdata/log/log.h1
-rw-r--r--libnetdata/popen/popen.c10
-rw-r--r--libnetdata/procfile/procfile.c6
-rw-r--r--libnetdata/procfile/procfile.h2
-rw-r--r--libnetdata/socket/security.c4
-rw-r--r--libnetdata/storage_number/storage_number.h2
-rw-r--r--libnetdata/storage_number/tests/test_storage_number.c4
-rw-r--r--libnetdata/url/url.c4
17 files changed, 228 insertions, 40 deletions
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 <bpf/libbpf.h>
#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 <sys/statfs.h>
#endif
+#ifdef HAVE_LINUX_MAGIC_H
+#include <linux/magic.h>
+#endif
+
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#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 <setjmp.h>
#include <cmocka.h>
-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;