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)