thiagoftsm 3 лет назад
Родитель
Сommit
c0398b5ee5
3 измененных файлов с 174 добавлено и 4 удалено
  1. 3 0
      Makefile.am
  2. 140 4
      collectors/cgroups.plugin/sys_fs_cgroup.c
  3. 31 0
      collectors/cgroups.plugin/sys_fs_cgroup.h

+ 3 - 0
Makefile.am

@@ -918,6 +918,9 @@ NETDATACLI_FILES = \
 sbin_PROGRAMS += netdata
 netdata_SOURCES = $(NETDATA_FILES)
 
+if LINUX
+    NETDATA_COMMON_LIBS += -lrt
+endif
 
 netdata_LDADD = \
     $(NETDATA_COMMON_LIBS) \

+ 140 - 4
collectors/cgroups.plugin/sys_fs_cgroup.c

@@ -94,6 +94,11 @@ static struct cgroups_systemd_config_setting cgroups_systemd_options[] = {
     { .name = NULL,      .setting = SYSTEMD_CGROUP_ERR     },
 };
 
+// Shared memory with information from detected cgroups
+netdata_ebpf_cgroup_shm_t shm_cgroup_ebpf = {NULL, NULL};
+static int shm_fd_cgroup_ebpf = -1;
+sem_t *shm_mutex_cgroup_ebpf = SEM_FAILED;
+
 /* on Fed systemd is not in PATH for some reason */
 #define SYSTEMD_CMD_RHEL "/usr/lib/systemd/systemd --version"
 #define SYSTEMD_HIERARCHY_STRING "default-hierarchy="
@@ -461,6 +466,61 @@ void read_cgroup_plugin_configuration() {
     mountinfo_free_all(root);
 }
 
+void netdata_cgroup_ebpf_set_values(size_t length)
+{
+    sem_wait(shm_mutex_cgroup_ebpf);
+
+    shm_cgroup_ebpf.header->cgroup_max = cgroup_root_max;
+    shm_cgroup_ebpf.header->systemd_enabled = cgroup_enable_systemd_services |
+                                              cgroup_enable_systemd_services_detailed_memory |
+                                              cgroup_used_memory;
+    shm_cgroup_ebpf.header->body_length = length;
+
+    sem_post(shm_mutex_cgroup_ebpf);
+}
+
+void netdata_cgroup_ebpf_initialize_shm()
+{
+    shm_fd_cgroup_ebpf = shm_open(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME, O_CREAT | O_RDWR, 0660);
+    if (shm_fd_cgroup_ebpf < 0) {
+        error("Cannot initialize shared memory used by cgroup and eBPF, integration won't happen.");
+        return;
+    }
+
+    size_t length = sizeof(netdata_ebpf_cgroup_shm_header_t) + cgroup_root_max * sizeof(netdata_ebpf_cgroup_shm_body_t);
+    if (ftruncate(shm_fd_cgroup_ebpf, length)) {
+        error("Cannot set size for shared memory.");
+        goto end_init_shm;
+    }
+
+    shm_cgroup_ebpf.header = (netdata_ebpf_cgroup_shm_header_t *) mmap(NULL, length,
+                                                                       PROT_READ | PROT_WRITE, MAP_SHARED,
+                                                                       shm_fd_cgroup_ebpf, 0);
+
+    if (!shm_cgroup_ebpf.header) {
+        error("Cannot map shared memory used between cgroup and eBPF, integration won't happen");
+        goto end_init_shm;
+    }
+    shm_cgroup_ebpf.body = (netdata_ebpf_cgroup_shm_body_t *) (shm_cgroup_ebpf.header +
+                                                              sizeof(netdata_ebpf_cgroup_shm_header_t));
+
+    shm_mutex_cgroup_ebpf = sem_open(NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME, O_CREAT,
+                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, 1);
+
+    if (shm_mutex_cgroup_ebpf != SEM_FAILED) {
+        netdata_cgroup_ebpf_set_values(length);
+        return;
+    }
+
+    error("Cannot create semaphore, integration between eBPF and cgroup won't happen");
+    munmap(shm_cgroup_ebpf.header, length);
+
+end_init_shm:
+    close(shm_fd_cgroup_ebpf);
+    shm_fd_cgroup_ebpf = -1;
+    shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME);
+}
+
 // ----------------------------------------------------------------------------
 // cgroup objects
 
@@ -595,10 +655,6 @@ struct cgroup_network_interface {
     struct cgroup_network_interface *next;
 };
 
-#define CGROUP_OPTIONS_DISABLED_DUPLICATE   0x00000001
-#define CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE 0x00000002
-#define CGROUP_OPTIONS_IS_UNIFIED           0x00000004
-
 // *** WARNING *** The fields are not thread safe. Take care of safe usage.
 struct cgroup {
     uint32_t options;
@@ -2054,6 +2110,69 @@ static inline void copy_discovered_cgroups()
     cgroup_root = discovered_cgroup_root;
 }
 
+static void is_there_cgroup_procs(netdata_ebpf_cgroup_shm_body_t *out, char *id)
+{
+    struct stat buf;
+
+    snprintfz(out->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_cpuset_base, id);
+    if (likely(stat(out->path, &buf) == 0)) {
+        return;
+    }
+
+    snprintfz(out->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_blkio_base, id);
+    if (likely(stat(out->path, &buf) == 0)) {
+        return;
+    }
+
+    snprintfz(out->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_memory_base, id);
+    if (likely(stat(out->path, &buf) == 0)) {
+        return;
+    }
+
+    snprintfz(out->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_devices_base, id);
+    if (likely(stat(out->path, &buf) == 0)) {
+        return;
+    }
+
+    out->path[0] = '\0';
+    out->enabled = 0;
+}
+
+static inline void share_cgroups()
+{
+    struct cgroup *cg;
+    int count;
+    struct stat buf;
+
+    if (shm_mutex_cgroup_ebpf == SEM_FAILED) {
+        return;
+    }
+    sem_wait(shm_mutex_cgroup_ebpf);
+
+    for (cg = cgroup_root, count = 0; cg ; cg = cg->next, count++) {
+        netdata_ebpf_cgroup_shm_body_t *ptr = &shm_cgroup_ebpf.body[count];
+        char *prefix = (cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE) ? "" : "cgroup_";
+        snprintfz(ptr->name, CGROUP_EBPF_NAME_SHARED_LENGTH - 1, "%s%s", prefix, cg->chart_title);
+        ptr->hash = simple_hash(ptr->name);
+        ptr->options = cg->options;
+        ptr->enabled = cg->enabled;
+        if (cgroup_use_unified_cgroups) {
+            snprintfz(ptr->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_unified_base, cg->id);
+            if (likely(stat(ptr->path, &buf) == -1)) {
+                ptr->path[0] = '\0';
+                ptr->enabled = 0;
+            }
+        } else {
+            is_there_cgroup_procs(ptr, cg->id);
+        }
+
+        debug(D_CGROUP, "cgroup shared: NAME=%s, ENABLED=%d", ptr->name, ptr->enabled);
+    }
+
+    shm_cgroup_ebpf.header->cgroup_root_count = count;
+    sem_post(shm_mutex_cgroup_ebpf);
+}
+
 static inline void find_all_cgroups() {
     debug(D_CGROUP, "searching for cgroups");
 
@@ -2110,6 +2229,8 @@ static inline void find_all_cgroups() {
     copy_discovered_cgroups();
     uv_mutex_unlock(&cgroup_root_mutex);
 
+    share_cgroups();
+
     debug(D_CGROUP, "done searching for cgroups");
 }
 
@@ -4020,6 +4141,20 @@ static void cgroup_main_cleanup(void *ptr) {
         sleep_usec(step);
     }
 
+    if (shm_mutex_cgroup_ebpf != SEM_FAILED) {
+        sem_close(shm_mutex_cgroup_ebpf);
+        sem_unlink(NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME);
+    }
+
+    if (shm_cgroup_ebpf.header) {
+        munmap(shm_cgroup_ebpf.header, shm_cgroup_ebpf.header->body_length);
+    }
+
+    if (shm_fd_cgroup_ebpf > 0) {
+        close(shm_fd_cgroup_ebpf);
+        shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME);
+    }
+
     static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
 }
 
@@ -4032,6 +4167,7 @@ void *cgroups_main(void *ptr) {
     int vdo_cpu_netdata = config_get_boolean("plugin:cgroups", "cgroups plugin resource charts", 1);
 
     read_cgroup_plugin_configuration();
+    netdata_cgroup_ebpf_initialize_shm();
 
     RRDSET *stcpu_thread = NULL;
 

+ 31 - 0
collectors/cgroups.plugin/sys_fs_cgroup.h

@@ -20,6 +20,37 @@
 
 extern void *cgroups_main(void *ptr);
 
+#define CGROUP_OPTIONS_DISABLED_DUPLICATE   0x00000001
+#define CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE 0x00000002
+#define CGROUP_OPTIONS_IS_UNIFIED           0x00000004
+
+typedef struct netdata_ebpf_cgroup_shm_header {
+    int cgroup_root_count;
+    int cgroup_max;
+    int systemd_enabled;
+    size_t body_length;
+} netdata_ebpf_cgroup_shm_header_t;
+
+#define CGROUP_EBPF_NAME_SHARED_LENGTH 256
+
+typedef struct netdata_ebpf_cgroup_shm_body {
+    // Considering what is exposed in this link https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits
+    // this length is enough to store what we want.
+    char name[CGROUP_EBPF_NAME_SHARED_LENGTH];
+    uint32_t hash;
+    uint32_t options;
+    int enabled;
+    char path[FILENAME_MAX + 1];
+} netdata_ebpf_cgroup_shm_body_t;
+
+typedef struct netdata_ebpf_cgroup_shm {
+    netdata_ebpf_cgroup_shm_header_t *header;
+    netdata_ebpf_cgroup_shm_body_t *body;
+} netdata_ebpf_cgroup_shm_t;
+
+#define NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME "netdata_shm_cgroup_ebpf"
+#define NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME "/netdata_sem_cgroup_ebpf"
+
 #include "../proc.plugin/plugin_proc.h"
 
 #else // (TARGET_OS == OS_LINUX)