@cryptotaxi247 / netdata-1 / commits / c0398b5ee

Add shared memory to cgroup (#11559)

thiagoftsm committed Sep 24, 2021 at 15:17 UTC c0398b5ee5bc58ff1f3e12d786f2495c9fde25d6
3 files changed +174 -4
Makefile.am
+3
@@ -918,6 +918,9 @@ NETDATACLI_FILES = \
918 sbin_PROGRAMS += netdata
919 netdata_SOURCES = $(NETDATA_FILES)
920
921 +if LINUX
922 + NETDATA_COMMON_LIBS += -lrt
923 +endif
924
925 netdata_LDADD = \
926 $(NETDATA_COMMON_LIBS) \
collectors/cgroups.plugin/sys_fs_cgroup.c
+140 -4
@@ -94,6 +94,11 @@ static struct cgroups_systemd_config_setting cgroups_systemd_options[] = {
94 { .name = NULL, .setting = SYSTEMD_CGROUP_ERR },
95 };
96
97 +// Shared memory with information from detected cgroups
98 +netdata_ebpf_cgroup_shm_t shm_cgroup_ebpf = {NULL, NULL};
99 +static int shm_fd_cgroup_ebpf = -1;
100 +sem_t *shm_mutex_cgroup_ebpf = SEM_FAILED;
101 +
102 /* on Fed systemd is not in PATH for some reason */
103 #define SYSTEMD_CMD_RHEL "/usr/lib/systemd/systemd --version"
104 #define SYSTEMD_HIERARCHY_STRING "default-hierarchy="
@@ -461,6 +466,61 @@ void read_cgroup_plugin_configuration() {
466 mountinfo_free_all(root);
467 }
468
469 +void netdata_cgroup_ebpf_set_values(size_t length)
470 +{
471 + sem_wait(shm_mutex_cgroup_ebpf);
472 +
473 + shm_cgroup_ebpf.header->cgroup_max = cgroup_root_max;
474 + shm_cgroup_ebpf.header->systemd_enabled = cgroup_enable_systemd_services |
475 + cgroup_enable_systemd_services_detailed_memory |
476 + cgroup_used_memory;
477 + shm_cgroup_ebpf.header->body_length = length;
478 +
479 + sem_post(shm_mutex_cgroup_ebpf);
480 +}
481 +
482 +void netdata_cgroup_ebpf_initialize_shm()
483 +{
484 + shm_fd_cgroup_ebpf = shm_open(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME, O_CREAT | O_RDWR, 0660);
485 + if (shm_fd_cgroup_ebpf < 0) {
486 + error("Cannot initialize shared memory used by cgroup and eBPF, integration won't happen.");
487 + return;
488 + }
489 +
490 + size_t length = sizeof(netdata_ebpf_cgroup_shm_header_t) + cgroup_root_max * sizeof(netdata_ebpf_cgroup_shm_body_t);
491 + if (ftruncate(shm_fd_cgroup_ebpf, length)) {
492 + error("Cannot set size for shared memory.");
493 + goto end_init_shm;
494 + }
495 +
496 + shm_cgroup_ebpf.header = (netdata_ebpf_cgroup_shm_header_t *) mmap(NULL, length,
497 + PROT_READ | PROT_WRITE, MAP_SHARED,
498 + shm_fd_cgroup_ebpf, 0);
499 +
500 + if (!shm_cgroup_ebpf.header) {
501 + error("Cannot map shared memory used between cgroup and eBPF, integration won't happen");
502 + goto end_init_shm;
503 + }
504 + shm_cgroup_ebpf.body = (netdata_ebpf_cgroup_shm_body_t *) (shm_cgroup_ebpf.header +
505 + sizeof(netdata_ebpf_cgroup_shm_header_t));
506 +
507 + shm_mutex_cgroup_ebpf = sem_open(NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME, O_CREAT,
508 + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, 1);
509 +
510 + if (shm_mutex_cgroup_ebpf != SEM_FAILED) {
511 + netdata_cgroup_ebpf_set_values(length);
512 + return;
513 + }
514 +
515 + error("Cannot create semaphore, integration between eBPF and cgroup won't happen");
516 + munmap(shm_cgroup_ebpf.header, length);
517 +
518 +end_init_shm:
519 + close(shm_fd_cgroup_ebpf);
520 + shm_fd_cgroup_ebpf = -1;
521 + shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME);
522 +}
523 +
524 // ----------------------------------------------------------------------------
525 // cgroup objects
526
@@ -595,10 +655,6 @@ struct cgroup_network_interface {
655 struct cgroup_network_interface *next;
656 };
657
598 -#define CGROUP_OPTIONS_DISABLED_DUPLICATE 0x00000001
599 -#define CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE 0x00000002
600 -#define CGROUP_OPTIONS_IS_UNIFIED 0x00000004
601 -
658 // *** WARNING *** The fields are not thread safe. Take care of safe usage.
659 struct cgroup {
660 uint32_t options;
@@ -2054,6 +2110,69 @@ static inline void copy_discovered_cgroups()
2110 cgroup_root = discovered_cgroup_root;
2111 }
2112
2113 +static void is_there_cgroup_procs(netdata_ebpf_cgroup_shm_body_t *out, char *id)
2114 +{
2115 + struct stat buf;
2116 +
2117 + snprintfz(out->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_cpuset_base, id);
2118 + if (likely(stat(out->path, &buf) == 0)) {
2119 + return;
2120 + }
2121 +
2122 + snprintfz(out->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_blkio_base, id);
2123 + if (likely(stat(out->path, &buf) == 0)) {
2124 + return;
2125 + }
2126 +
2127 + snprintfz(out->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_memory_base, id);
2128 + if (likely(stat(out->path, &buf) == 0)) {
2129 + return;
2130 + }
2131 +
2132 + snprintfz(out->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_devices_base, id);
2133 + if (likely(stat(out->path, &buf) == 0)) {
2134 + return;
2135 + }
2136 +
2137 + out->path[0] = '\0';
2138 + out->enabled = 0;
2139 +}
2140 +
2141 +static inline void share_cgroups()
2142 +{
2143 + struct cgroup *cg;
2144 + int count;
2145 + struct stat buf;
2146 +
2147 + if (shm_mutex_cgroup_ebpf == SEM_FAILED) {
2148 + return;
2149 + }
2150 + sem_wait(shm_mutex_cgroup_ebpf);
2151 +
2152 + for (cg = cgroup_root, count = 0; cg ; cg = cg->next, count++) {
2153 + netdata_ebpf_cgroup_shm_body_t *ptr = &shm_cgroup_ebpf.body[count];
2154 + char *prefix = (cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE) ? "" : "cgroup_";
2155 + snprintfz(ptr->name, CGROUP_EBPF_NAME_SHARED_LENGTH - 1, "%s%s", prefix, cg->chart_title);
2156 + ptr->hash = simple_hash(ptr->name);
2157 + ptr->options = cg->options;
2158 + ptr->enabled = cg->enabled;
2159 + if (cgroup_use_unified_cgroups) {
2160 + snprintfz(ptr->path, FILENAME_MAX, "%s%s/cgroup.procs", cgroup_unified_base, cg->id);
2161 + if (likely(stat(ptr->path, &buf) == -1)) {
2162 + ptr->path[0] = '\0';
2163 + ptr->enabled = 0;
2164 + }
2165 + } else {
2166 + is_there_cgroup_procs(ptr, cg->id);
2167 + }
2168 +
2169 + debug(D_CGROUP, "cgroup shared: NAME=%s, ENABLED=%d", ptr->name, ptr->enabled);
2170 + }
2171 +
2172 + shm_cgroup_ebpf.header->cgroup_root_count = count;
2173 + sem_post(shm_mutex_cgroup_ebpf);
2174 +}
2175 +
2176 static inline void find_all_cgroups() {
2177 debug(D_CGROUP, "searching for cgroups");
2178
@@ -2110,6 +2229,8 @@ static inline void find_all_cgroups() {
2229 copy_discovered_cgroups();
2230 uv_mutex_unlock(&cgroup_root_mutex);
2231
2232 + share_cgroups();
2233 +
2234 debug(D_CGROUP, "done searching for cgroups");
2235 }
2236
@@ -4020,6 +4141,20 @@ static void cgroup_main_cleanup(void *ptr) {
4141 sleep_usec(step);
4142 }
4143
4144 + if (shm_mutex_cgroup_ebpf != SEM_FAILED) {
4145 + sem_close(shm_mutex_cgroup_ebpf);
4146 + sem_unlink(NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME);
4147 + }
4148 +
4149 + if (shm_cgroup_ebpf.header) {
4150 + munmap(shm_cgroup_ebpf.header, shm_cgroup_ebpf.header->body_length);
4151 + }
4152 +
4153 + if (shm_fd_cgroup_ebpf > 0) {
4154 + close(shm_fd_cgroup_ebpf);
4155 + shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME);
4156 + }
4157 +
4158 static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
4159 }
4160
@@ -4032,6 +4167,7 @@ void *cgroups_main(void *ptr) {
4167 int vdo_cpu_netdata = config_get_boolean("plugin:cgroups", "cgroups plugin resource charts", 1);
4168
4169 read_cgroup_plugin_configuration();
4170 + netdata_cgroup_ebpf_initialize_shm();
4171
4172 RRDSET *stcpu_thread = NULL;
4173
collectors/cgroups.plugin/sys_fs_cgroup.h
+31
@@ -20,6 +20,37 @@
20
21 extern void *cgroups_main(void *ptr);
22
23 +#define CGROUP_OPTIONS_DISABLED_DUPLICATE 0x00000001
24 +#define CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE 0x00000002
25 +#define CGROUP_OPTIONS_IS_UNIFIED 0x00000004
26 +
27 +typedef struct netdata_ebpf_cgroup_shm_header {
28 + int cgroup_root_count;
29 + int cgroup_max;
30 + int systemd_enabled;
31 + size_t body_length;
32 +} netdata_ebpf_cgroup_shm_header_t;
33 +
34 +#define CGROUP_EBPF_NAME_SHARED_LENGTH 256
35 +
36 +typedef struct netdata_ebpf_cgroup_shm_body {
37 + // Considering what is exposed in this link https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits
38 + // this length is enough to store what we want.
39 + char name[CGROUP_EBPF_NAME_SHARED_LENGTH];
40 + uint32_t hash;
41 + uint32_t options;
42 + int enabled;
43 + char path[FILENAME_MAX + 1];
44 +} netdata_ebpf_cgroup_shm_body_t;
45 +
46 +typedef struct netdata_ebpf_cgroup_shm {
47 + netdata_ebpf_cgroup_shm_header_t *header;
48 + netdata_ebpf_cgroup_shm_body_t *body;
49 +} netdata_ebpf_cgroup_shm_t;
50 +
51 +#define NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME "netdata_shm_cgroup_ebpf"
52 +#define NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME "/netdata_sem_cgroup_ebpf"
53 +
54 #include "../proc.plugin/plugin_proc.h"
55
56 #else // (TARGET_OS == OS_LINUX)