|
@@ -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;
|
|
|
|