Browse Source

Remove SIGSEGV and SIGABRT (ebpf.plugin) (#13407)

thiagoftsm 2 years ago
parent
commit
b8eaf10853

+ 269 - 150
collectors/ebpf.plugin/ebpf.c

@@ -18,8 +18,6 @@ char *ebpf_plugin_dir = PLUGINS_DIR;
 static char *ebpf_configured_log_dir = LOG_DIR;
 
 char *ebpf_algorithms[] = {"absolute", "incremental"};
-static int thread_finished = 0;
-int close_ebpf_plugin = 0;
 struct config collector_config = { .first_section = NULL,
                                    .last_section = NULL,
                                    .mutex = NETDATA_MUTEX_INITIALIZER,
@@ -29,7 +27,6 @@ struct config collector_config = { .first_section = NULL,
 int running_on_kernel = 0;
 int ebpf_nprocs;
 int isrh = 0;
-uint32_t finalized_threads = 1;
 
 pthread_mutex_t lock;
 pthread_mutex_t collect_data_mutex;
@@ -37,132 +34,264 @@ pthread_cond_t collect_data_cond_var;
 
 ebpf_module_t ebpf_modules[] = {
     { .thread_name = "process", .config_name = "process", .enabled = 0, .start_routine = ebpf_process_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
       .apps_routine = ebpf_process_create_apps_charts, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &process_config,
       .config_file = NETDATA_PROCESS_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10,
-      .load = EBPF_LOAD_LEGACY, .targets = NULL},
+      .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
     { .thread_name = "socket", .config_name = "socket", .enabled = 0, .start_routine = ebpf_socket_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
       .apps_routine = ebpf_socket_create_apps_charts, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &socket_config,
       .config_file = NETDATA_NETWORK_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = socket_targets},
+      .load = EBPF_LOAD_LEGACY, .targets = socket_targets, .probe_links = NULL, .objects = NULL},
     { .thread_name = "cachestat", .config_name = "cachestat", .enabled = 0, .start_routine = ebpf_cachestat_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
       .apps_routine = ebpf_cachestat_create_apps_charts, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &cachestat_config,
       .config_file = NETDATA_CACHESTAT_CONFIG_FILE,
-      .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18|
-                 NETDATA_V5_4 | NETDATA_V5_15 | NETDATA_V5_16,
-      .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets},
+      .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18| NETDATA_V5_4 | NETDATA_V5_15 |
+                 NETDATA_V5_16,
+      .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets, .probe_links = NULL, .objects = NULL},
     { .thread_name = "sync", .config_name = "sync", .enabled = 0, .start_routine = ebpf_sync_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &sync_config,
       .config_file = NETDATA_SYNC_CONFIG_FILE,
       // All syscalls have the same kernels
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = sync_targets},
+      .load = EBPF_LOAD_LEGACY, .targets = sync_targets, .probe_links = NULL, .objects = NULL},
     { .thread_name = "dc", .config_name = "dc", .enabled = 0, .start_routine = ebpf_dcstat_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
       .apps_routine = ebpf_dcstat_create_apps_charts, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &dcstat_config,
       .config_file = NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = dc_targets},
+      .load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL},
     { .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
       .apps_routine = ebpf_swap_create_apps_charts, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
       .config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = swap_targets},
+      .load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL},
     { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
       .apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config,
       .config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = NULL},
+      .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
     { .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config,
       .config_file = NETDATA_FILESYSTEM_CONFIG_FILE,
       //We are setting kernels as zero, because we load eBPF programs according the kernel running.
-      .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL },
+      .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL },
     { .thread_name = "disk", .config_name = "disk", .enabled = 0, .start_routine = ebpf_disk_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config,
       .config_file = NETDATA_DISK_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = NULL},
+      .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
     { .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config,
       .config_file = NETDATA_MOUNT_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = mount_targets},
+      .load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL},
     { .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
       .apps_routine = ebpf_fd_create_apps_charts, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fd_config,
       .config_file = NETDATA_FD_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11,
-      .load = EBPF_LOAD_LEGACY, .targets = NULL},
+      .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
     { .thread_name = "hardirq", .config_name = "hardirq", .enabled = 0, .start_routine = ebpf_hardirq_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &hardirq_config,
       .config_file = NETDATA_HARDIRQ_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = NULL},
+      .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
     { .thread_name = "softirq", .config_name = "softirq", .enabled = 0, .start_routine = ebpf_softirq_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &softirq_config,
       .config_file = NETDATA_SOFTIRQ_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = NULL},
+      .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
     { .thread_name = "oomkill", .config_name = "oomkill", .enabled = 0, .start_routine = ebpf_oomkill_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
       .apps_routine = ebpf_oomkill_create_apps_charts, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &oomkill_config,
       .config_file = NETDATA_OOMKILL_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = NULL},
+      .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
     { .thread_name = "shm", .config_name = "shm", .enabled = 0, .start_routine = ebpf_shm_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
       .apps_routine = ebpf_shm_create_apps_charts, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &shm_config,
       .config_file = NETDATA_DIRECTORY_SHM_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = shm_targets},
+      .load = EBPF_LOAD_LEGACY, .targets = shm_targets, .probe_links = NULL, .objects = NULL},
     { .thread_name = "mdflush", .config_name = "mdflush", .enabled = 0, .start_routine = ebpf_mdflush_thread,
-      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
+      .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
       .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
       .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mdflush_config,
       .config_file = NETDATA_DIRECTORY_MDFLUSH_CONFIG_FILE,
       .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
-      .load = EBPF_LOAD_LEGACY, .targets = NULL},
+      .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
     { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_every = EBPF_DEFAULT_UPDATE_EVERY,
-      .global_charts = 0, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
+      .global_charts = 0, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
       .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, .pid_map_size = 0, .names = NULL,
-      .cfg = NULL, .config_name = NULL, .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL},
+      .cfg = NULL, .config_name = NULL, .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL,
+      .objects = NULL},
+};
+
+struct netdata_static_thread ebpf_threads[] = {
+    {"EBPF PROCESS", NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF SOCKET" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF CACHESTAT" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF SYNC" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF DCSTAT" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF SWAP" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF VFS" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF FILESYSTEM" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF DISK" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF MOUNT" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF FD" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF HARDIRQ" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF SOFTIRQ" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF OOMKILL" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF SHM" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {"EBPF MDFLUSH" , NULL, NULL, 1,
+        NULL, NULL, NULL},
+    {NULL          , NULL, NULL, 0,
+                     NULL, NULL, NULL}
+};
+
+ebpf_filesystem_partitions_t localfs[] =
+    {{.filesystem = "ext4",
+      .optional_filesystem = NULL,
+      .family = "ext4",
+      .objects = NULL,
+      .probe_links = NULL,
+      .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
+      .enabled = CONFIG_BOOLEAN_YES,
+      .addresses = {.function = NULL, .addr = 0},
+      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
+     {.filesystem = "xfs",
+      .optional_filesystem = NULL,
+      .family = "xfs",
+      .objects = NULL,
+      .probe_links = NULL,
+      .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
+      .enabled = CONFIG_BOOLEAN_YES,
+      .addresses = {.function = NULL, .addr = 0},
+      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
+     {.filesystem = "nfs",
+      .optional_filesystem = "nfs4",
+      .family = "nfs",
+      .objects = NULL,
+      .probe_links = NULL,
+      .flags = NETDATA_FILESYSTEM_ATTR_CHARTS,
+      .enabled = CONFIG_BOOLEAN_YES,
+      .addresses = {.function = NULL, .addr = 0},
+      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
+     {.filesystem = "zfs",
+      .optional_filesystem = NULL,
+      .family = "zfs",
+      .objects = NULL,
+      .probe_links = NULL,
+      .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
+      .enabled = CONFIG_BOOLEAN_YES,
+      .addresses = {.function = NULL, .addr = 0},
+      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
+     {.filesystem = "btrfs",
+      .optional_filesystem = NULL,
+      .family = "btrfs",
+      .objects = NULL,
+      .probe_links = NULL,
+      .flags = NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE,
+      .enabled = CONFIG_BOOLEAN_YES,
+      .addresses = {.function = "btrfs_file_operations", .addr = 0},
+      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10},
+     {.filesystem = NULL,
+      .optional_filesystem = NULL,
+      .family = NULL,
+      .objects = NULL,
+      .probe_links = NULL,
+      .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
+      .enabled = CONFIG_BOOLEAN_YES,
+      .addresses = {.function = NULL, .addr = 0},
+      .kernels = 0}};
+
+ebpf_sync_syscalls_t local_syscalls[] = {
+    {.syscall = NETDATA_SYSCALLS_SYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
+#ifdef LIBBPF_MAJOR_VERSION
+        .sync_obj = NULL
+#endif
+    },
+    {.syscall = NETDATA_SYSCALLS_SYNCFS, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
+#ifdef LIBBPF_MAJOR_VERSION
+        .sync_obj = NULL
+#endif
+    },
+    {.syscall = NETDATA_SYSCALLS_MSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
+#ifdef LIBBPF_MAJOR_VERSION
+        .sync_obj = NULL
+#endif
+    },
+    {.syscall = NETDATA_SYSCALLS_FSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
+#ifdef LIBBPF_MAJOR_VERSION
+        .sync_obj = NULL
+#endif
+    },
+    {.syscall = NETDATA_SYSCALLS_FDATASYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
+#ifdef LIBBPF_MAJOR_VERSION
+        .sync_obj = NULL
+#endif
+    },
+    {.syscall = NETDATA_SYSCALLS_SYNC_FILE_RANGE, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
+#ifdef LIBBPF_MAJOR_VERSION
+        .sync_obj = NULL
+#endif
+    },
+    {.syscall = NULL, .enabled = CONFIG_BOOLEAN_NO, .objects = NULL, .probe_links = NULL,
+#ifdef LIBBPF_MAJOR_VERSION
+        .sync_obj = NULL
+#endif
+    }
 };
 
 // Link with apps.plugin
@@ -192,18 +321,6 @@ char *btf_path = NULL;
  *
  *****************************************************************/
 
-/**
- * Clean Loaded Events
- *
- * This function cleans the events previous loaded on Linux.
-void clean_loaded_events()
-{
-    int event_pid;
-    for (event_pid = 0; ebpf_modules[event_pid].probes; event_pid++)
-        clean_kprobe_events(NULL, (int)ebpf_modules[event_pid].thread_id, ebpf_modules[event_pid].probes);
-}
- */
-
 /**
  * Close the collector gracefully
  *
@@ -211,64 +328,89 @@ void clean_loaded_events()
  */
 static void ebpf_exit(int sig)
 {
-    close_ebpf_plugin = 1;
-    static int remove_pid = 0;
-
-    // When both threads were not finished case I try to go in front this address, the collector will crash
-    if (!thread_finished) {
-        return;
+#ifdef LIBBPF_MAJOR_VERSION
+    if (default_btf) {
+        btf__free(default_btf);
+        default_btf = NULL;
     }
+#endif
 
-    ebpf_close_cgroup_shm();
+    char filename[FILENAME_MAX + 1];
+    ebpf_pid_file(filename, FILENAME_MAX);
+    if (unlink(filename))
+        error("Cannot remove PID file %s", filename);
 
-    /*
-    int ret = fork();
-    if (ret < 0) // error
-        error("Cannot fork(), so I won't be able to clean %skprobe_events", NETDATA_DEBUGFS);
-    else if (!ret) { // child
-        int i;
-        for (i = getdtablesize(); i >= 0; --i)
-            close(i);
+    exit(sig);
+}
 
-        int fd = open("/dev/null", O_RDWR, 0);
-        if (fd != -1) {
-            dup2(fd, STDIN_FILENO);
-            dup2(fd, STDOUT_FILENO);
-            dup2(fd, STDERR_FILENO);
-        }
+/**
+ * Unload loegacy code
+ *
+ * @param objects       objects loaded from eBPF programs
+ * @param probe_links   links from loader
+ */
+static void ebpf_unload_legacy_code(struct bpf_object *objects, struct bpf_link **probe_links)
+{
+    if (!probe_links || !objects)
+        return;
 
-        if (fd > 2)
-            close(fd);
+    struct bpf_program *prog;
+    size_t j = 0 ;
+    bpf_object__for_each_program(prog, objects) {
+        bpf_link__destroy(probe_links[j]);
+        j++;
+    }
+    freez(probe_links);
+    if (objects)
+        bpf_object__close(objects);
+}
 
-        int sid = setsid();
-        if (sid >= 0) {
-            debug(D_EXIT, "Wait for father %d die", getpid());
-            sleep_usec(200000); // Sleep 200 milliseconds to father dies.
-            clean_loaded_events();
-        } else {
-            error("Cannot become session id leader, so I won't try to clean kprobe_events.\n");
+int ebpf_exit_plugin = 0;
+/**
+ * Close the collector gracefully
+ *
+ * @param sig is the signal number used to close the collector
+ */
+static void ebpf_stop_threads(int sig)
+{
+    ebpf_exit_plugin = 1;
+    int i;
+    for (i = 0; ebpf_threads[i].name != NULL; i++);
+
+    usec_t max = 2 * USEC_PER_SEC, step = 100000;
+    while (i && max) {
+        max -= step;
+        sleep_usec(step);
+        i = 0;
+        int j;
+        for (j = 0; ebpf_threads[j].name != NULL; j++) {
+            if (ebpf_threads[j].enabled != NETDATA_MAIN_THREAD_EXITED)
+                i++;
         }
-    } else { // parent
-        exit(0);
     }
-     */
 
-#ifdef LIBBPF_MAJOR_VERSION
-    if (default_btf) {
-        btf__free(default_btf);
-        default_btf = NULL;
+    //Unload threads(except sync and filesystem)
+    for (i = 0; ebpf_threads[i].name != NULL; i++) {
+        if (ebpf_threads[i].enabled == NETDATA_MAIN_THREAD_EXITED && i != EBPF_MODULE_FILESYSTEM_IDX &&
+            i != EBPF_MODULE_SYNC_IDX)
+            ebpf_unload_legacy_code(ebpf_modules[i].objects, ebpf_modules[i].probe_links);
     }
-#endif
 
-    if (!remove_pid) {
-        remove_pid = 1;
-        char filename[FILENAME_MAX + 1];
-        ebpf_pid_file(filename, FILENAME_MAX);
-        if (unlink(filename))
-            error("Cannot remove PID file %s", filename);
+    //Unload filesystem
+    if (ebpf_threads[EBPF_MODULE_FILESYSTEM_IDX].enabled  == NETDATA_MAIN_THREAD_EXITED) {
+        for (i = 0; localfs[i].filesystem != NULL; i++) {
+            ebpf_unload_legacy_code(localfs[i].objects, localfs[i].probe_links);
+        }
     }
 
-    exit(sig);
+    //Unload Sync
+    if (ebpf_threads[EBPF_MODULE_SYNC_IDX].enabled  == NETDATA_MAIN_THREAD_EXITED) {
+        for (i = 0; local_syscalls[i].syscall != NULL; i++) {
+            ebpf_unload_legacy_code(local_syscalls[i].objects, local_syscalls[i].probe_links);
+        }
+    }
+
+    ebpf_exit(sig);
 }
 
 /*****************************************************************
@@ -659,7 +801,7 @@ static inline void ebpf_enable_specific_chart(struct ebpf_module *em, int disabl
     // oomkill stores data inside apps submenu, so it always need to have apps_enabled for plugin to create
     // its chart, without this comparison eBPF.plugin will try to store invalid data when apps is disabled.
     if (!disable_apps || !strcmp(em->thread_name, "oomkill")) {
-        em->apps_charts = CONFIG_BOOLEAN_YES;
+        em->apps_charts = NETDATA_EBPF_APPS_FLAG_YES;
     }
 
     if (!disable_cgroup) {
@@ -724,7 +866,7 @@ static inline void ebpf_disable_apps()
 {
     int i;
     for (i = 0; ebpf_modules[i].thread_name; i++) {
-        ebpf_modules[i].apps_charts = 0;
+        ebpf_modules[i].apps_charts = NETDATA_EBPF_APPS_FLAG_NO;
     }
 }
 
@@ -1031,7 +1173,6 @@ int ebpf_start_pthread_variables()
     pthread_mutex_init(&collect_data_mutex, NULL);
 
     if (pthread_cond_init(&collect_data_cond_var, NULL)) {
-        thread_finished++;
         error("Cannot start conditional variable to control Apps charts.");
         return -1;
     }
@@ -1051,7 +1192,7 @@ static inline uint32_t ebpf_am_i_collect_pids()
     uint32_t ret = 0;
     int i;
     for (i = 0; ebpf_modules[i].thread_name; i++) {
-        ret |= ebpf_modules[i].cgroup_charts | ebpf_modules[i].apps_charts;
+        ret |= ebpf_modules[i].cgroup_charts | (ebpf_modules[i].apps_charts & NETDATA_EBPF_APPS_FLAG_YES);
     }
 
     return ret;
@@ -1675,7 +1816,6 @@ static void ebpf_parse_args(int argc, char **argv)
                 &apps_groups_default_target, &apps_groups_root_target, ebpf_stock_config_dir, "groups")) {
             error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.",
                   ebpf_stock_config_dir);
-            thread_finished++;
             ebpf_exit(1);
         }
     } else
@@ -1831,6 +1971,19 @@ static void ebpf_manage_pid(pid_t pid)
     ebpf_update_pid_file(filename, pid);
 }
 
+/**
+ * Set start routine
+ *
+ * Set static routine before threads to be created.
+ */
+ static void ebpf_set_static_routine()
+ {
+     int i;
+     for (i = 0; ebpf_modules[i].thread_name; i++) {
+         ebpf_threads[i].start_routine = ebpf_modules[i].start_routine;
+     }
+ }
+
 /**
  * Entry point
  *
@@ -1875,16 +2028,19 @@ int main(int argc, char **argv)
         return 4;
     }
 
-    signal(SIGINT, ebpf_exit);
-    signal(SIGTERM, ebpf_exit);
-    signal(SIGPIPE, ebpf_exit);
+    signal(SIGINT, ebpf_stop_threads);
+    signal(SIGQUIT, ebpf_stop_threads);
+    signal(SIGTERM, ebpf_stop_threads);
+    signal(SIGPIPE, ebpf_stop_threads);
 
     if (ebpf_start_pthread_variables()) {
-        thread_finished++;
         error("Cannot start mutex to control overall charts.");
         ebpf_exit(5);
     }
 
+    netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
+    if(verify_netdata_host_prefix() == -1) ebpf_exit(6);
+
     ebpf_allocate_common_vectors();
 
 #ifdef LIBBPF_MAJOR_VERSION
@@ -1897,44 +2053,7 @@ int main(int argc, char **argv)
     read_local_ports("/proc/net/udp", IPPROTO_UDP);
     read_local_ports("/proc/net/udp6", IPPROTO_UDP);
 
-    struct netdata_static_thread ebpf_threads[] = {
-        {"EBPF PROCESS", NULL, NULL, 1,
-          NULL, NULL, ebpf_modules[EBPF_MODULE_PROCESS_IDX].start_routine},
-        {"EBPF SOCKET" , NULL, NULL, 1,
-          NULL, NULL, ebpf_modules[EBPF_MODULE_SOCKET_IDX].start_routine},
-        {"EBPF CACHESTAT" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_CACHESTAT_IDX].start_routine},
-        {"EBPF SYNC" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_SYNC_IDX].start_routine},
-        {"EBPF DCSTAT" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_DCSTAT_IDX].start_routine},
-        {"EBPF SWAP" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_SWAP_IDX].start_routine},
-        {"EBPF VFS" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_VFS_IDX].start_routine},
-        {"EBPF FILESYSTEM" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_FILESYSTEM_IDX].start_routine},
-        {"EBPF DISK" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_DISK_IDX].start_routine},
-        {"EBPF MOUNT" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_MOUNT_IDX].start_routine},
-        {"EBPF FD" , NULL, NULL, 1,
-             NULL, NULL, ebpf_modules[EBPF_MODULE_FD_IDX].start_routine},
-        {"EBPF HARDIRQ" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_HARDIRQ_IDX].start_routine},
-        {"EBPF SOFTIRQ" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_SOFTIRQ_IDX].start_routine},
-        {"EBPF OOMKILL" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_OOMKILL_IDX].start_routine},
-        {"EBPF SHM" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_SHM_IDX].start_routine},
-        {"EBPF MDFLUSH" , NULL, NULL, 1,
-            NULL, NULL, ebpf_modules[EBPF_MODULE_MDFLUSH_IDX].start_routine},
-        {NULL          , NULL, NULL, 0,
-          NULL, NULL, NULL}
-    };
-
-    //clean_loaded_events();
+    ebpf_set_static_routine();
 
     int i;
     for (i = 0; ebpf_threads[i].name != NULL; i++) {
@@ -1943,16 +2062,16 @@ int main(int argc, char **argv)
 
         ebpf_module_t *em = &ebpf_modules[i];
         em->thread_id = i;
-        netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_JOINABLE, st->start_routine, em);
+        netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, em);
     }
 
-    for (i = 0; ebpf_threads[i].name != NULL; i++) {
-        struct netdata_static_thread *st = &ebpf_threads[i];
-        netdata_thread_join(*st->thread, NULL);
+    usec_t step = 60 * USEC_PER_SEC;
+    heartbeat_t hb;
+    heartbeat_init(&hb);
+    //Plugin will be killed when it receives a signal
+    for (;;) {
+        (void)heartbeat_next(&hb, step);
     }
 
-    thread_finished++;
-    ebpf_exit(0);
-
     return 0;
 }

+ 9 - 2
collectors/ebpf.plugin/ebpf.h

@@ -108,6 +108,12 @@ typedef struct ebpf_tracepoint {
     char *event;
 } ebpf_tracepoint_t;
 
+enum ebpf_threads_status {
+    NETDATA_THREAD_EBPF_RUNNING,
+    NETDATA_THREAD_EBPF_STOPPING,
+    NETDATA_THREAD_EBPF_STOPPED
+};
+
 // Copied from musl header
 #ifndef offsetof
 #if __GNUC__ > 3
@@ -162,7 +168,6 @@ extern void *ebpf_socket_thread(void *ptr);
 
 // Common variables
 extern pthread_mutex_t lock;
-extern int close_ebpf_plugin;
 extern int ebpf_nprocs;
 extern int running_on_kernel;
 extern int isrh;
@@ -265,7 +270,6 @@ extern int shm_fd_ebpf_cgroup;
 extern sem_t *shm_sem_ebpf_cgroup;
 extern pthread_mutex_t mutex_cgroup_shm;
 extern size_t all_pids_count;
-extern uint32_t finalized_threads;
 extern ebpf_plugin_stats_t plugin_statistics;
 extern struct btf *default_btf;
 
@@ -281,6 +285,9 @@ extern void ebpf_write_chart_obsolete(char *type, char *id, char *title, char *u
                                       char *charttype, char *context, int order, int update_every);
 extern void write_histogram_chart(char *family, char *name, const netdata_idx_t *hist, char **dimensions, uint32_t end);
 void ebpf_update_disabled_plugin_stats(ebpf_module_t *em);
+extern ebpf_filesystem_partitions_t localfs[];
+extern ebpf_sync_syscalls_t local_syscalls[];
+extern int ebpf_exit_plugin;
 
 #define EBPF_MAX_SYNCHRONIZATION_TIME 300
 

+ 2 - 2
collectors/ebpf.plugin/ebpf_apps.c

@@ -134,7 +134,7 @@ size_t zero_all_targets(struct target *root)
             while (pid_on_target) {
                 struct pid_on_target *pid_on_target_to_free = pid_on_target;
                 pid_on_target = pid_on_target->next;
-                free(pid_on_target_to_free);
+                freez(pid_on_target_to_free);
             }
 
             w->root_pid = NULL;
@@ -1119,7 +1119,7 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd)
         key = pids->pid;
         ebpf_process_stat_t *w = global_process_stats[key];
         if (!w) {
-            w = mallocz(sizeof(ebpf_process_stat_t));
+            w = callocz(1, sizeof(ebpf_process_stat_t));
             global_process_stats[key] = w;
         }
 

+ 47 - 38
collectors/ebpf.plugin/ebpf_cachestat.c

@@ -5,9 +5,6 @@
 
 netdata_publish_cachestat_t **cachestat_pid;
 
-static struct bpf_link **probe_links = NULL;
-static struct bpf_object *objects = NULL;
-
 static char *cachestat_counter_dimension_name[NETDATA_CACHESTAT_END] = { "ratio", "dirty", "hit",
                                                                          "miss" };
 static netdata_syscall_stat_t cachestat_counter_aggregated_data[NETDATA_CACHESTAT_END];
@@ -18,8 +15,6 @@ netdata_cachestat_pid_t *cachestat_vector = NULL;
 static netdata_idx_t cachestat_hash_values[NETDATA_CACHESTAT_END];
 static netdata_idx_t *cachestat_values = NULL;
 
-static int read_thread_closed = 1;
-
 struct netdata_static_thread cachestat_threads = {"CACHESTAT KERNEL",
                                                   NULL, NULL, 1, NULL,
                                                   NULL,  NULL};
@@ -44,6 +39,7 @@ struct config cachestat_config = { .first_section = NULL,
     .mutex = NETDATA_MUTEX_INITIALIZER,
     .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
         .rwlock = AVL_LOCK_INITIALIZER } };
+static enum ebpf_threads_status ebpf_cachestat_exited = NETDATA_THREAD_EBPF_RUNNING;
 
 netdata_ebpf_targets_t cachestat_targets[] = { {.name = "add_to_page_cache_lru", .mode = EBPF_LOAD_TRAMPOLINE},
                                                {.name = "mark_page_accessed", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -294,43 +290,48 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf
  *****************************************************************/
 
 /**
- * Clean up the main thread.
+ * Cachestat exit.
+ *
+ * Cancel child and exit.
  *
  * @param ptr thread data.
  */
-static void ebpf_cachestat_cleanup(void *ptr)
+static void ebpf_cachestat_exit(void *ptr)
 {
     ebpf_module_t *em = (ebpf_module_t *)ptr;
-    if (!em->enabled)
+    if (!em->enabled) {
+        em->enabled = NETDATA_MAIN_THREAD_EXITED;
         return;
-
-    heartbeat_t hb;
-    heartbeat_init(&hb);
-    uint32_t tick = 2*USEC_PER_MS;
-    while (!read_thread_closed) {
-        usec_t dt = heartbeat_next(&hb, tick);
-        UNUSED(dt);
     }
 
+    ebpf_cachestat_exited = NETDATA_THREAD_EBPF_STOPPING;
+}
+
+/**
+ * Cachestat cleanup
+ *
+ * Clean up allocated addresses.
+ *
+ * @param ptr thread data.
+ */
+static void ebpf_cachestat_cleanup(void *ptr)
+{
+    ebpf_module_t *em = (ebpf_module_t *)ptr;
+    if (ebpf_cachestat_exited != NETDATA_THREAD_EBPF_STOPPED)
+        return;
+
     ebpf_cleanup_publish_syscall(cachestat_counter_publish_aggregated);
 
     freez(cachestat_vector);
     freez(cachestat_values);
+    freez(cachestat_threads.thread);
 
-    if (probe_links) {
-        struct bpf_program *prog;
-        size_t i = 0 ;
-        bpf_object__for_each_program(prog, objects) {
-            bpf_link__destroy(probe_links[i]);
-            i++;
-        }
-        if (objects)
-            bpf_object__close(objects);
-    }
 #ifdef LIBBPF_MAJOR_VERSION
-    else if (bpf_obj)
+    if (bpf_obj)
         cachestat_bpf__destroy(bpf_obj);
 #endif
+    cachestat_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
+    em->enabled = NETDATA_MAIN_THREAD_EXITED;
 }
 
 /*****************************************************************
@@ -594,6 +595,8 @@ void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
                                20093,
                                ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
                                root, em->update_every, NETDATA_EBPF_MODULE_NAME_CACHESTAT);
+
+    em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
 }
 
 /*****************************************************************
@@ -639,22 +642,25 @@ static void read_global_table()
  */
 void *ebpf_cachestat_read_hash(void *ptr)
 {
-    read_thread_closed = 0;
-
+    netdata_thread_cleanup_push(ebpf_cachestat_cleanup, ptr);
     heartbeat_t hb;
     heartbeat_init(&hb);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
 
     usec_t step = NETDATA_LATENCY_CACHESTAT_SLEEP_MS * em->update_every;
-    while (!close_ebpf_plugin) {
+    while (ebpf_cachestat_exited == NETDATA_THREAD_EBPF_RUNNING) {
         usec_t dt = heartbeat_next(&hb, step);
         (void)dt;
+        if (ebpf_cachestat_exited == NETDATA_THREAD_EBPF_STOPPING)
+            break;
 
         read_global_table();
     }
-    read_thread_closed = 1;
 
+    ebpf_cachestat_exited = NETDATA_THREAD_EBPF_STOPPED;
+
+    netdata_thread_cleanup_pop(1);
     return NULL;
 }
 
@@ -1068,23 +1074,26 @@ void ebpf_cachestat_send_cgroup_data(int update_every)
 */
 static void cachestat_collector(ebpf_module_t *em)
 {
-    cachestat_threads.thread = mallocz(sizeof(netdata_thread_t));
+    cachestat_threads.thread = callocz(1, sizeof(netdata_thread_t));
     cachestat_threads.start_routine = ebpf_cachestat_read_hash;
 
-    netdata_thread_create(cachestat_threads.thread, cachestat_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
+    netdata_thread_create(cachestat_threads.thread, cachestat_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
                           ebpf_cachestat_read_hash, em);
 
     netdata_publish_cachestat_t publish;
     memset(&publish, 0, sizeof(publish));
-    int apps = em->apps_charts;
     int cgroups = em->cgroup_charts;
     int update_every = em->update_every;
     heartbeat_t hb;
     heartbeat_init(&hb);
     usec_t step = update_every * USEC_PER_SEC;
-    while (!close_ebpf_plugin) {
+    //This will be cancelled by its parent
+    while (!ebpf_exit_plugin) {
         (void)heartbeat_next(&hb, step);
+        if (ebpf_exit_plugin)
+            break;
 
+        netdata_apps_integration_flags_t apps = em->apps_charts;
         pthread_mutex_lock(&collect_data_mutex);
         if (apps)
             read_apps_table();
@@ -1096,7 +1105,7 @@ static void cachestat_collector(ebpf_module_t *em)
 
         cachestat_send_global(&publish);
 
-        if (apps)
+        if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
             ebpf_cache_send_apps_data(apps_groups_root_target);
 
         if (cgroups)
@@ -1219,8 +1228,8 @@ static int ebpf_cachestat_load_bpf(ebpf_module_t *em)
 {
     int ret = 0;
     if (em->load == EBPF_LOAD_LEGACY) {
-        probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
-        if (!probe_links) {
+        em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
+        if (!em->probe_links) {
             ret = -1;
         }
     }
@@ -1251,7 +1260,7 @@ static int ebpf_cachestat_load_bpf(ebpf_module_t *em)
  */
 void *ebpf_cachestat_thread(void *ptr)
 {
-    netdata_thread_cleanup_push(ebpf_cachestat_cleanup, ptr);
+    netdata_thread_cleanup_push(ebpf_cachestat_exit, ptr);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
     em->maps = cachestat_maps;

+ 43 - 36
collectors/ebpf.plugin/ebpf_dcstat.c

@@ -10,14 +10,9 @@ static netdata_publish_syscall_t dcstat_counter_publish_aggregated[NETDATA_DCSTA
 netdata_dcstat_pid_t *dcstat_vector = NULL;
 netdata_publish_dcstat_t **dcstat_pid = NULL;
 
-static struct bpf_link **probe_links = NULL;
-static struct bpf_object *objects = NULL;
-
 static netdata_idx_t dcstat_hash_values[NETDATA_DCSTAT_IDX_END];
 static netdata_idx_t *dcstat_values = NULL;
 
-static int read_thread_closed = 1;
-
 struct config dcstat_config = { .first_section = NULL,
     .last_section = NULL,
     .mutex = NETDATA_MUTEX_INITIALIZER,
@@ -27,6 +22,7 @@ struct config dcstat_config = { .first_section = NULL,
 struct netdata_static_thread dcstat_threads = {"DCSTAT KERNEL",
                                                NULL, NULL, 1, NULL,
                                                NULL,  NULL};
+static enum ebpf_threads_status ebpf_dcstat_exited = NETDATA_THREAD_EBPF_RUNNING;
 
 static ebpf_local_maps_t dcstat_maps[] = {{.name = "dcstat_global", .internal_input = NETDATA_DIRECTORY_CACHE_END,
                                            .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
@@ -265,6 +261,24 @@ void ebpf_dcstat_clean_names()
     }
 }
 
+/**
+ * DCstat exit
+ *
+ * Cancel child and exit.
+ *
+ * @param ptr thread data.
+ */
+static void ebpf_dcstat_exit(void *ptr)
+{
+    ebpf_module_t *em = (ebpf_module_t *)ptr;
+    if (!em->enabled) {
+        em->enabled = NETDATA_MAIN_THREAD_EXITED;
+        return;
+    }
+
+    ebpf_dcstat_exited = NETDATA_THREAD_EBPF_STOPPING;
+}
+
 /**
  * Clean up the main thread.
  *
@@ -273,38 +287,24 @@ void ebpf_dcstat_clean_names()
 static void ebpf_dcstat_cleanup(void *ptr)
 {
     ebpf_module_t *em = (ebpf_module_t *)ptr;
-    if (!em->enabled)
+    if (ebpf_dcstat_exited != NETDATA_THREAD_EBPF_STOPPED)
         return;
 
-    heartbeat_t hb;
-    heartbeat_init(&hb);
-    uint32_t tick = 2 * USEC_PER_MS;
-    while (!read_thread_closed) {
-        usec_t dt = heartbeat_next(&hb, tick);
-        UNUSED(dt);
-    }
-
     freez(dcstat_vector);
     freez(dcstat_values);
+    freez(dcstat_threads.thread);
 
     ebpf_cleanup_publish_syscall(dcstat_counter_publish_aggregated);
 
     ebpf_dcstat_clean_names();
 
-    if (probe_links) {
-        struct bpf_program *prog;
-        size_t i = 0 ;
-        bpf_object__for_each_program(prog, objects) {
-            bpf_link__destroy(probe_links[i]);
-            i++;
-        }
-        if (objects)
-            bpf_object__close(objects);
-    }
 #ifdef LIBBPF_MAJOR_VERSION
-    else if (bpf_obj)
+    if (bpf_obj)
         dc_bpf__destroy(bpf_obj);
 #endif
+
+    dcstat_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
+    em->enabled = NETDATA_MAIN_THREAD_EXITED;
 }
 
 /*****************************************************************
@@ -358,6 +358,8 @@ void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr)
                                20103,
                                ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
                                root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
+
+    em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
 }
 
 /*****************************************************************
@@ -522,22 +524,25 @@ static void read_global_table()
  */
 void *ebpf_dcstat_read_hash(void *ptr)
 {
-    read_thread_closed = 0;
-
+    netdata_thread_cleanup_push(ebpf_dcstat_cleanup, ptr);
     heartbeat_t hb;
     heartbeat_init(&hb);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
 
     usec_t step = NETDATA_LATENCY_DCSTAT_SLEEP_MS * em->update_every;
-    while (!close_ebpf_plugin) {
+    while (ebpf_dcstat_exited == NETDATA_THREAD_EBPF_RUNNING) {
         usec_t dt = heartbeat_next(&hb, step);
         (void)dt;
+        if (ebpf_dcstat_exited == NETDATA_THREAD_EBPF_STOPPING)
+            break;
 
         read_global_table();
     }
-    read_thread_closed = 1;
 
+    ebpf_dcstat_exited = NETDATA_THREAD_EBPF_STOPPED;
+
+    netdata_thread_cleanup_pop(1);
     return NULL;
 }
 
@@ -1000,20 +1005,22 @@ static void dcstat_collector(ebpf_module_t *em)
     dcstat_threads.thread = mallocz(sizeof(netdata_thread_t));
     dcstat_threads.start_routine = ebpf_dcstat_read_hash;
 
-    netdata_thread_create(dcstat_threads.thread, dcstat_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
+    netdata_thread_create(dcstat_threads.thread, dcstat_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
                           ebpf_dcstat_read_hash, em);
 
     netdata_publish_dcstat_t publish;
     memset(&publish, 0, sizeof(publish));
-    int apps = em->apps_charts;
     int cgroups = em->cgroup_charts;
     int update_every = em->update_every;
     heartbeat_t hb;
     heartbeat_init(&hb);
     usec_t step = update_every * USEC_PER_SEC;
-    while (!close_ebpf_plugin) {
+    while (!ebpf_exit_plugin) {
         (void)heartbeat_next(&hb, step);
+        if (ebpf_exit_plugin)
+            break;
 
+        netdata_apps_integration_flags_t apps = em->apps_charts;
         pthread_mutex_lock(&collect_data_mutex);
         if (apps)
             read_apps_table();
@@ -1025,7 +1032,7 @@ static void dcstat_collector(ebpf_module_t *em)
 
         dcstat_send_global(&publish);
 
-        if (apps)
+        if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
             ebpf_dcache_send_apps_data(apps_groups_root_target);
 
         if (cgroups)
@@ -1110,8 +1117,8 @@ static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
 {
     int ret = 0;
     if (em->load == EBPF_LOAD_LEGACY) {
-        probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
-        if (!probe_links) {
+        em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
+        if (!em->probe_links) {
             ret = -1;
         }
     }
@@ -1142,7 +1149,7 @@ static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
  */
 void *ebpf_dcstat_thread(void *ptr)
 {
-    netdata_thread_cleanup_push(ebpf_dcstat_cleanup, ptr);
+    netdata_thread_cleanup_push(ebpf_dcstat_exit, ptr);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
     em->maps = dcstat_maps;

+ 40 - 34
collectors/ebpf.plugin/ebpf_disk.c

@@ -25,9 +25,6 @@ char *tracepoint_block_type = { "block"} ;
 char *tracepoint_block_issue = { "block_rq_issue" };
 char *tracepoint_block_rq_complete = { "block_rq_complete" };
 
-static struct bpf_link **probe_links = NULL;
-static struct bpf_object *objects = NULL;
-
 static int was_block_issue_enabled = 0;
 static int was_block_rq_complete_enabled = 0;
 
@@ -35,12 +32,11 @@ static char **dimensions = NULL;
 static netdata_syscall_stat_t disk_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
 static netdata_publish_syscall_t disk_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
 
-static int read_thread_closed = 1;
-
 static netdata_idx_t *disk_hash_values = NULL;
 static struct netdata_static_thread disk_threads = {"DISK KERNEL",
                                                     NULL, NULL, 1, NULL,
                                                     NULL, NULL };
+static enum ebpf_threads_status ebpf_disk_exited = NETDATA_THREAD_EBPF_RUNNING;
 
 ebpf_publish_disk_t *plot_disks = NULL;
 pthread_mutex_t plot_mutex;
@@ -428,25 +424,37 @@ static void ebpf_cleanup_disk_list()
 }
 
 /**
- * Clean up the main thread.
+ * Disk exit.
+ *
+ * Cancel child and exit.
  *
  * @param ptr thread data.
  */
-static void ebpf_disk_cleanup(void *ptr)
+static void ebpf_disk_exit(void *ptr)
 {
-    ebpf_disk_disable_tracepoints();
+    ebpf_module_t *em = (ebpf_module_t *)ptr;
+    if (!em->enabled) {
+        em->enabled = NETDATA_MAIN_THREAD_EXITED;
+        return;
+    }
+
+    ebpf_disk_exited = NETDATA_THREAD_EBPF_STOPPING;
+}
 
+/**
+ * Disk Cleanup
+ *
+ * Clean up allocated memory.
+ *
+ * @param ptr thread data.
+ */
+static void ebpf_disk_cleanup(void *ptr)
+{
     ebpf_module_t *em = (ebpf_module_t *)ptr;
-    if (!em->enabled)
+    if (ebpf_disk_exited != NETDATA_THREAD_EBPF_STOPPED)
         return;
 
-    heartbeat_t hb;
-    heartbeat_init(&hb);
-    uint32_t tick = 2 * USEC_PER_MS;
-    while (!read_thread_closed) {
-        usec_t dt = heartbeat_next(&hb, tick);
-        UNUSED(dt);
-    }
+    ebpf_disk_disable_tracepoints();
 
     if (dimensions)
         ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
@@ -458,16 +466,8 @@ static void ebpf_disk_cleanup(void *ptr)
     ebpf_cleanup_plot_disks();
     ebpf_cleanup_disk_list();
 
-    if (probe_links) {
-        struct bpf_program *prog;
-        size_t i = 0 ;
-        bpf_object__for_each_program(prog, objects) {
-            bpf_link__destroy(probe_links[i]);
-            i++;
-        }
-        if (objects)
-            bpf_object__close(objects);
-    }
+    disk_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
+    em->enabled = NETDATA_MAIN_THREAD_EXITED;
 }
 
 /*****************************************************************
@@ -583,19 +583,25 @@ static void read_hard_disk_tables(int table)
  */
 void *ebpf_disk_read_hash(void *ptr)
 {
+    netdata_thread_cleanup_push(ebpf_disk_cleanup, ptr);
     heartbeat_t hb;
     heartbeat_init(&hb);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
 
     usec_t step = NETDATA_LATENCY_DISK_SLEEP_MS * em->update_every;
-    while (!close_ebpf_plugin) {
+    while (ebpf_disk_exited == NETDATA_THREAD_EBPF_RUNNING) {
         usec_t dt = heartbeat_next(&hb, step);
         (void)dt;
+        if (ebpf_disk_exited == NETDATA_THREAD_EBPF_STOPPING)
+            break;
 
         read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd);
     }
 
+    ebpf_disk_exited = NETDATA_THREAD_EBPF_STOPPED;
+
+    netdata_thread_cleanup_pop(1);
     return NULL;
 }
 
@@ -725,16 +731,17 @@ static void disk_collector(ebpf_module_t *em)
     disk_threads.thread = mallocz(sizeof(netdata_thread_t));
     disk_threads.start_routine = ebpf_disk_read_hash;
 
-    netdata_thread_create(disk_threads.thread, disk_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
+    netdata_thread_create(disk_threads.thread, disk_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
                           ebpf_disk_read_hash, em);
 
     int update_every = em->update_every;
-    read_thread_closed = 0;
     heartbeat_t hb;
     heartbeat_init(&hb);
     usec_t step = update_every * USEC_PER_SEC;
-    while (!close_ebpf_plugin) {
+    while (!ebpf_exit_plugin) {
         (void)heartbeat_next(&hb, step);
+        if (ebpf_exit_plugin)
+            break;
 
         pthread_mutex_lock(&lock);
         ebpf_remove_pointer_from_plot_disk(em);
@@ -744,7 +751,6 @@ static void disk_collector(ebpf_module_t *em)
 
         ebpf_update_disks(em);
     }
-    read_thread_closed = 1;
 }
 
 /*****************************************************************
@@ -794,7 +800,7 @@ static int ebpf_disk_enable_tracepoints()
  */
 void *ebpf_disk_thread(void *ptr)
 {
-    netdata_thread_cleanup_push(ebpf_disk_cleanup, ptr);
+    netdata_thread_cleanup_push(ebpf_disk_exit, ptr);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
     em->maps = disk_maps;
@@ -819,8 +825,8 @@ void *ebpf_disk_thread(void *ptr)
         goto enddisk;
     }
 
-    probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
-    if (!probe_links) {
+    em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
+    if (!em->probe_links) {
         em->enabled = 0;
         goto enddisk;
     }

+ 40 - 34
collectors/ebpf.plugin/ebpf_fd.c

@@ -29,12 +29,9 @@ struct config fd_config = { .first_section = NULL, .last_section = NULL, .mutex
                            .index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare },
                                      .rwlock = AVL_LOCK_INITIALIZER } };
 
-static struct bpf_link **probe_links = NULL;
-static struct bpf_object *objects = NULL;
-
 struct netdata_static_thread fd_thread = {"FD KERNEL", NULL, NULL, 1, NULL,
                                           NULL,  NULL};
-static int read_thread_closed = 1;
+static enum ebpf_threads_status ebpf_fd_exited = NETDATA_THREAD_EBPF_RUNNING;
 static netdata_idx_t fd_hash_values[NETDATA_FD_COUNTER];
 static netdata_idx_t *fd_values = NULL;
 
@@ -47,6 +44,24 @@ netdata_fd_stat_t **fd_pid = NULL;
  *
  *****************************************************************/
 
+/**
+ * FD Exit
+ *
+ * Cancel child thread and exit.
+ *
+ * @param ptr thread data.
+ */
+static void ebpf_fd_exit(void *ptr)
+{
+    ebpf_module_t *em = (ebpf_module_t *)ptr;
+    if (!em->enabled) {
+        em->enabled = NETDATA_MAIN_THREAD_EXITED;
+        return;
+    }
+
+    ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPING;
+}
+
 /**
  * Clean up the main thread.
  *
@@ -55,32 +70,16 @@ netdata_fd_stat_t **fd_pid = NULL;
 static void ebpf_fd_cleanup(void *ptr)
 {
     ebpf_module_t *em = (ebpf_module_t *)ptr;
-    if (!em->enabled)
+    if (ebpf_fd_exited != NETDATA_THREAD_EBPF_STOPPED)
         return;
 
-    heartbeat_t hb;
-    heartbeat_init(&hb);
-    uint32_t tick = 2 * USEC_PER_MS;
-    while (!read_thread_closed) {
-        usec_t dt = heartbeat_next(&hb, tick);
-        UNUSED(dt);
-    }
-
     ebpf_cleanup_publish_syscall(fd_publish_aggregated);
     freez(fd_thread.thread);
     freez(fd_values);
     freez(fd_vector);
 
-    if (probe_links) {
-        struct bpf_program *prog;
-        size_t i = 0 ;
-        bpf_object__for_each_program(prog, objects) {
-            bpf_link__destroy(probe_links[i]);
-            i++;
-        }
-        if (objects)
-            bpf_object__close(objects);
-    }
+    fd_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
+    em->enabled = NETDATA_MAIN_THREAD_EXITED;
 }
 
 /*****************************************************************
@@ -148,21 +147,24 @@ static void read_global_table()
  */
 void *ebpf_fd_read_hash(void *ptr)
 {
-    read_thread_closed = 0;
-
+    netdata_thread_cleanup_push(ebpf_fd_cleanup, ptr);
     heartbeat_t hb;
     heartbeat_init(&hb);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
     usec_t step = NETDATA_FD_SLEEP_MS * em->update_every;
-    while (!close_ebpf_plugin) {
+    while (ebpf_fd_exited == NETDATA_THREAD_EBPF_RUNNING) {
         usec_t dt = heartbeat_next(&hb, step);
         (void)dt;
+        if (ebpf_fd_exited == NETDATA_THREAD_EBPF_STOPPING)
+            break;
 
         read_global_table();
     }
 
-    read_thread_closed = 1;
+    ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPED;
+
+    netdata_thread_cleanup_pop(1);
     return NULL;
 }
 
@@ -652,17 +654,19 @@ static void fd_collector(ebpf_module_t *em)
     fd_thread.thread = mallocz(sizeof(netdata_thread_t));
     fd_thread.start_routine = ebpf_fd_read_hash;
 
-    netdata_thread_create(fd_thread.thread, fd_thread.name, NETDATA_THREAD_OPTION_JOINABLE,
+    netdata_thread_create(fd_thread.thread, fd_thread.name, NETDATA_THREAD_OPTION_DEFAULT,
                           ebpf_fd_read_hash, em);
 
-    int apps = em->apps_charts;
     int cgroups = em->cgroup_charts;
     heartbeat_t hb;
     heartbeat_init(&hb);
     usec_t step = em->update_every * USEC_PER_SEC;
-    while (!close_ebpf_plugin) {
+    while (!ebpf_exit_plugin) {
         (void)heartbeat_next(&hb, step);
+        if (ebpf_exit_plugin)
+            break;
 
+        netdata_apps_integration_flags_t apps = em->apps_charts;
         pthread_mutex_lock(&collect_data_mutex);
         if (apps)
             read_apps_table();
@@ -674,7 +678,7 @@ static void fd_collector(ebpf_module_t *em)
 
         ebpf_fd_send_data(em);
 
-        if (apps)
+        if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
             ebpf_fd_send_apps_data(em, apps_groups_root_target);
 
         if (cgroups)
@@ -740,6 +744,8 @@ void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr)
                                    ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
                                    root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
     }
+
+    em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
 }
 
 /**
@@ -815,7 +821,7 @@ static void ebpf_fd_allocate_global_vectors(int apps)
  */
 void *ebpf_fd_thread(void *ptr)
 {
-    netdata_thread_cleanup_push(ebpf_fd_cleanup, ptr);
+    netdata_thread_cleanup_push(ebpf_fd_exit, ptr);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
     em->maps = fd_maps;
@@ -825,8 +831,8 @@ void *ebpf_fd_thread(void *ptr)
 
     ebpf_fd_allocate_global_vectors(em->apps_charts);
 
-    probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
-    if (!probe_links) {
+    em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
+    if (!em->probe_links) {
         em->enabled = CONFIG_BOOLEAN_NO;
         goto endfd;
     }

+ 39 - 73
collectors/ebpf.plugin/ebpf_filesystem.c

@@ -30,67 +30,11 @@ static ebpf_local_maps_t fs_maps[] = {{.name = "tbl_ext4", .internal_input = NET
                                        .type = NETDATA_EBPF_MAP_CONTROLLER,
                                        .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
 
-ebpf_filesystem_partitions_t localfs[] =
-    {{.filesystem = "ext4",
-      .optional_filesystem = NULL,
-      .family = "ext4",
-      .objects = NULL,
-      .probe_links = NULL,
-      .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
-      .enabled = CONFIG_BOOLEAN_YES,
-      .addresses = {.function = NULL, .addr = 0},
-      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
-     {.filesystem = "xfs",
-      .optional_filesystem = NULL,
-      .family = "xfs",
-      .objects = NULL,
-      .probe_links = NULL,
-      .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
-      .enabled = CONFIG_BOOLEAN_YES,
-      .addresses = {.function = NULL, .addr = 0},
-      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
-     {.filesystem = "nfs",
-      .optional_filesystem = "nfs4",
-      .family = "nfs",
-      .objects = NULL,
-      .probe_links = NULL,
-      .flags = NETDATA_FILESYSTEM_ATTR_CHARTS,
-      .enabled = CONFIG_BOOLEAN_YES,
-      .addresses = {.function = NULL, .addr = 0},
-      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
-     {.filesystem = "zfs",
-      .optional_filesystem = NULL,
-      .family = "zfs",
-      .objects = NULL,
-      .probe_links = NULL,
-      .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
-      .enabled = CONFIG_BOOLEAN_YES,
-      .addresses = {.function = NULL, .addr = 0},
-      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
-     {.filesystem = "btrfs",
-      .optional_filesystem = NULL,
-      .family = "btrfs",
-      .objects = NULL,
-      .probe_links = NULL,
-      .flags = NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE,
-      .enabled = CONFIG_BOOLEAN_YES,
-      .addresses = {.function = "btrfs_file_operations", .addr = 0},
-      .kernels =  NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10},
-     {.filesystem = NULL,
-      .optional_filesystem = NULL,
-      .family = NULL,
-      .objects = NULL,
-      .probe_links = NULL,
-      .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
-      .enabled = CONFIG_BOOLEAN_YES,
-      .addresses = {.function = NULL, .addr = 0},
-      .kernels = 0}};
-
 struct netdata_static_thread filesystem_threads = {"EBPF FS READ",
                                                    NULL, NULL, 1, NULL,
                                                    NULL, NULL };
+static enum ebpf_threads_status ebpf_fs_exited = NETDATA_THREAD_EBPF_RUNNING;
 
-static int read_thread_closed = 1;
 static netdata_syscall_stat_t filesystem_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
 static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
 
@@ -381,6 +325,7 @@ void ebpf_filesystem_cleanup_ebpf_data()
                 bpf_link__destroy(probe_links[j]);
                 j++;
             }
+            freez(probe_links);
             if (efp->objects)
                 bpf_object__close(efp->objects);
         }
@@ -388,24 +333,36 @@ void ebpf_filesystem_cleanup_ebpf_data()
 }
 
 /**
- * Clean up the main thread.
+ * Filesystem exit
+ *
+ * Cancel child thread.
  *
  * @param ptr thread data.
  */
-static void ebpf_filesystem_cleanup(void *ptr)
+static void ebpf_filesystem_exit(void *ptr)
 {
     ebpf_module_t *em = (ebpf_module_t *)ptr;
-    if (!em->enabled)
+    if (!em->enabled) {
+        em->enabled = NETDATA_MAIN_THREAD_EXITED;
         return;
-
-    heartbeat_t hb;
-    heartbeat_init(&hb);
-    uint32_t tick = 2*USEC_PER_MS;
-    while (!read_thread_closed) {
-        usec_t dt = heartbeat_next(&hb, tick);
-        UNUSED(dt);
     }
 
+    ebpf_fs_exited = NETDATA_THREAD_EBPF_STOPPING;
+}
+
+/**
+ * File system cleanup
+ *
+ * Clean up allocated thread.
+ *
+ * @param ptr thread data.
+ */
+static void ebpf_filesystem_cleanup(void *ptr)
+{
+    ebpf_module_t *em = (ebpf_module_t *)ptr;
+    if (ebpf_fs_exited != NETDATA_THREAD_EBPF_STOPPED)
+        return;
+
     freez(filesystem_threads.thread);
     ebpf_cleanup_publish_syscall(filesystem_publish_aggregated);
 
@@ -413,6 +370,9 @@ static void ebpf_filesystem_cleanup(void *ptr)
     if (dimensions)
         ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
     freez(filesystem_hash_values);
+
+    filesystem_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
+    em->enabled = NETDATA_MAIN_THREAD_EXITED;
 }
 
 /*****************************************************************
@@ -516,16 +476,18 @@ static void read_filesystem_tables()
  */
 void *ebpf_filesystem_read_hash(void *ptr)
 {
+    netdata_thread_cleanup_push(ebpf_filesystem_cleanup, ptr);
     ebpf_module_t *em = (ebpf_module_t *)ptr;
-    read_thread_closed = 0;
 
     heartbeat_t hb;
     heartbeat_init(&hb);
     usec_t step = NETDATA_FILESYSTEM_READ_SLEEP_MS * em->update_every;
     int update_every = em->update_every;
-    while (!close_ebpf_plugin) {
+    while (ebpf_fs_exited == NETDATA_THREAD_EBPF_RUNNING) {
         usec_t dt = heartbeat_next(&hb, step);
         (void)dt;
+        if (ebpf_fs_exited == NETDATA_THREAD_EBPF_STOPPING)
+            break;
 
         (void) ebpf_update_partitions(em);
         ebpf_obsolete_fs_charts(update_every);
@@ -537,7 +499,9 @@ void *ebpf_filesystem_read_hash(void *ptr)
         read_filesystem_tables();
     }
 
-    read_thread_closed = 1;
+    ebpf_fs_exited = NETDATA_THREAD_EBPF_STOPPED;
+
+    netdata_thread_cleanup_pop(1);
     return NULL;
 }
 
@@ -579,14 +543,16 @@ static void filesystem_collector(ebpf_module_t *em)
     filesystem_threads.start_routine = ebpf_filesystem_read_hash;
 
     netdata_thread_create(filesystem_threads.thread, filesystem_threads.name,
-                          NETDATA_THREAD_OPTION_JOINABLE, ebpf_filesystem_read_hash, em);
+                          NETDATA_THREAD_OPTION_DEFAULT, ebpf_filesystem_read_hash, em);
 
     int update_every = em->update_every;
     heartbeat_t hb;
     heartbeat_init(&hb);
     usec_t step = update_every * USEC_PER_SEC;
-    while (!close_ebpf_plugin || em->optional) {
+    while (!ebpf_exit_plugin) {
         (void)heartbeat_next(&hb, step);
+        if (ebpf_exit_plugin)
+            break;
 
         pthread_mutex_lock(&lock);
 
@@ -631,7 +597,7 @@ static void ebpf_update_filesystem()
  */
 void *ebpf_filesystem_thread(void *ptr)
 {
-    netdata_thread_cleanup_push(ebpf_filesystem_cleanup, ptr);
+    netdata_thread_cleanup_push(ebpf_filesystem_exit, ptr);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
     em->maps = fs_maps;

+ 0 - 20
collectors/ebpf.plugin/ebpf_filesystem.h

@@ -43,26 +43,6 @@ enum netdata_filesystem_table {
     NETDATA_ADDR_FS_TABLE
 };
 
-typedef struct ebpf_filesystem_partitions {
-    char *filesystem;
-    char *optional_filesystem;
-    char *family;
-    char *family_name;
-    struct bpf_object *objects;
-    struct bpf_link **probe_links;
-
-    netdata_ebpf_histogram_t hread;
-    netdata_ebpf_histogram_t hwrite;
-    netdata_ebpf_histogram_t hopen;
-    netdata_ebpf_histogram_t hadditional;
-
-    uint32_t flags;
-    uint32_t enabled;
-
-    ebpf_addresses_t addresses;
-    uint64_t kernels;
-} ebpf_filesystem_partitions_t;
-
 extern void *ebpf_filesystem_thread(void *ptr);
 extern struct config fs_config;
 

+ 42 - 38
collectors/ebpf.plugin/ebpf_hardirq.c

@@ -125,11 +125,6 @@ static hardirq_static_val_t hardirq_static_vals[] = {
     },
 };
 
-static struct bpf_link **probe_links = NULL;
-static struct bpf_object *objects = NULL;
-
-static int read_thread_closed = 1;
-
 // store for "published" data from the reader thread, which the collector
 // thread will write to netdata agent.
 static avl_tree_lock hardirq_pub;
@@ -143,45 +138,49 @@ static hardirq_ebpf_static_val_t *hardirq_ebpf_static_vals = NULL;
 static struct netdata_static_thread hardirq_threads = {"HARDIRQ KERNEL",
                                                     NULL, NULL, 1, NULL,
                                                     NULL, NULL };
+static enum ebpf_threads_status ebpf_hardirq_exited = NETDATA_THREAD_EBPF_RUNNING;
 
 /**
- * Clean up the main thread.
+ * Hardirq Exit
+ *
+ * Cancel child and exit.
  *
  * @param ptr thread data.
  */
-static void hardirq_cleanup(void *ptr)
+static void hardirq_exit(void *ptr)
 {
-    for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) {
-        ebpf_disable_tracepoint(&hardirq_tracepoints[i]);
-    }
-
     ebpf_module_t *em = (ebpf_module_t *)ptr;
     if (!em->enabled) {
+        em->enabled = NETDATA_MAIN_THREAD_EXITED;
         return;
     }
 
-    heartbeat_t hb;
-    heartbeat_init(&hb);
-    uint32_t tick = 1 * USEC_PER_MS;
-    while (!read_thread_closed) {
-        usec_t dt = heartbeat_next(&hb, tick);
-        UNUSED(dt);
-    }
+    ebpf_hardirq_exited = NETDATA_THREAD_EBPF_STOPPING;
+}
 
+/**
+ * Hardirq clean up
+ *
+ * Clean up allocated memory.
+ *
+ * @param ptr thread data.
+ */
+static void hardirq_cleanup(void *ptr)
+{
+    ebpf_module_t *em = (ebpf_module_t *)ptr;
+
+    if (ebpf_hardirq_exited != NETDATA_THREAD_EBPF_STOPPED)
+        return;
+
+    freez(hardirq_threads.thread);
+    for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) {
+        ebpf_disable_tracepoint(&hardirq_tracepoints[i]);
+    }
     freez(hardirq_ebpf_vals);
     freez(hardirq_ebpf_static_vals);
-    freez(hardirq_threads.thread);
 
-    if (probe_links) {
-        struct bpf_program *prog;
-        size_t i = 0 ;
-        bpf_object__for_each_program(prog, objects) {
-            bpf_link__destroy(probe_links[i]);
-            i++;
-        }
-        if (objects)
-            bpf_object__close(objects);
-    }
+    hardirq_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
+    em->enabled = NETDATA_MAIN_THREAD_EXITED;
 }
 
 /*****************************************************************
@@ -317,23 +316,25 @@ static void hardirq_read_latency_static_map(int mapfd)
  */
 static void *hardirq_reader(void *ptr)
 {
-    read_thread_closed = 0;
-
+    netdata_thread_cleanup_push(hardirq_cleanup, ptr);
     heartbeat_t hb;
     heartbeat_init(&hb);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
 
     usec_t step = NETDATA_HARDIRQ_SLEEP_MS * em->update_every;
-    while (!close_ebpf_plugin) {
+    while (ebpf_hardirq_exited == NETDATA_THREAD_EBPF_RUNNING) {
         usec_t dt = heartbeat_next(&hb, step);
         UNUSED(dt);
+        if (ebpf_hardirq_exited == NETDATA_THREAD_EBPF_STOPPING)
+            break;
 
         hardirq_read_latency_map(hardirq_maps[HARDIRQ_MAP_LATENCY].map_fd);
         hardirq_read_latency_static_map(hardirq_maps[HARDIRQ_MAP_LATENCY_STATIC].map_fd);
     }
+    ebpf_hardirq_exited = NETDATA_THREAD_EBPF_STOPPED;
 
-    read_thread_closed = 1;
+    netdata_thread_cleanup_pop(1);
     return NULL;
 }
 
@@ -420,7 +421,7 @@ static void hardirq_collector(ebpf_module_t *em)
     netdata_thread_create(
         hardirq_threads.thread,
         hardirq_threads.name,
-        NETDATA_THREAD_OPTION_JOINABLE,
+        NETDATA_THREAD_OPTION_DEFAULT,
         hardirq_reader,
         em
     );
@@ -436,8 +437,11 @@ static void hardirq_collector(ebpf_module_t *em)
     heartbeat_t hb;
     heartbeat_init(&hb);
     usec_t step = em->update_every * USEC_PER_SEC;
-    while (!close_ebpf_plugin) {
+    //This will be cancelled by its parent
+    while (!ebpf_exit_plugin) {
         (void)heartbeat_next(&hb, step);
+        if (ebpf_exit_plugin)
+            break;
 
         pthread_mutex_lock(&lock);
 
@@ -463,7 +467,7 @@ static void hardirq_collector(ebpf_module_t *em)
  */
 void *ebpf_hardirq_thread(void *ptr)
 {
-    netdata_thread_cleanup_push(hardirq_cleanup, ptr);
+    netdata_thread_cleanup_push(hardirq_exit, ptr);
 
     ebpf_module_t *em = (ebpf_module_t *)ptr;
     em->maps = hardirq_maps;
@@ -477,8 +481,8 @@ void *ebpf_hardirq_thread(void *ptr)
         goto endhardirq;
     }
 
-    probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
-    if (!probe_links) {
+    em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
+    if (!em->probe_links) {
         em->enabled = CONFIG_BOOLEAN_NO;
         goto endhardirq;
     }

Some files were not shown because too many files changed in this diff