@cryptotaxi247 / netdata-1 / commits / b8eaf1085

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

thiagoftsm committed Aug 5, 2022 at 15:07 UTC b8eaf108538615e45346ba8edec6a2fcce16298e
25 files changed +1266 -1111
collectors/ebpf.plugin/ebpf.c
+269 -150
@@ -18,8 +18,6 @@ char *ebpf_plugin_dir = PLUGINS_DIR;
18 static char *ebpf_configured_log_dir = LOG_DIR;
19
20 char *ebpf_algorithms[] = {"absolute", "incremental"};
21 -static int thread_finished = 0;
22 -int close_ebpf_plugin = 0;
21 struct config collector_config = { .first_section = NULL,
22 .last_section = NULL,
23 .mutex = NETDATA_MUTEX_INITIALIZER,
@@ -29,7 +27,6 @@ struct config collector_config = { .first_section = NULL,
27 int running_on_kernel = 0;
28 int ebpf_nprocs;
29 int isrh = 0;
32 -uint32_t finalized_threads = 1;
30
31 pthread_mutex_t lock;
32 pthread_mutex_t collect_data_mutex;
@@ -37,132 +34,264 @@ pthread_cond_t collect_data_cond_var;
34
35 ebpf_module_t ebpf_modules[] = {
36 { .thread_name = "process", .config_name = "process", .enabled = 0, .start_routine = ebpf_process_thread,
40 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
37 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
38 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
39 .apps_routine = ebpf_process_create_apps_charts, .maps = NULL,
40 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &process_config,
41 .config_file = NETDATA_PROCESS_CONFIG_FILE,
42 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10,
46 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
43 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
44 { .thread_name = "socket", .config_name = "socket", .enabled = 0, .start_routine = ebpf_socket_thread,
48 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
45 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
46 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
47 .apps_routine = ebpf_socket_create_apps_charts, .maps = NULL,
48 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &socket_config,
49 .config_file = NETDATA_NETWORK_CONFIG_FILE,
50 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
54 - .load = EBPF_LOAD_LEGACY, .targets = socket_targets},
51 + .load = EBPF_LOAD_LEGACY, .targets = socket_targets, .probe_links = NULL, .objects = NULL},
52 { .thread_name = "cachestat", .config_name = "cachestat", .enabled = 0, .start_routine = ebpf_cachestat_thread,
56 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
53 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
54 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
55 .apps_routine = ebpf_cachestat_create_apps_charts, .maps = NULL,
56 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &cachestat_config,
57 .config_file = NETDATA_CACHESTAT_CONFIG_FILE,
61 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18|
62 - NETDATA_V5_4 | NETDATA_V5_15 | NETDATA_V5_16,
63 - .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets},
58 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18| NETDATA_V5_4 | NETDATA_V5_15 |
59 + NETDATA_V5_16,
60 + .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets, .probe_links = NULL, .objects = NULL},
61 { .thread_name = "sync", .config_name = "sync", .enabled = 0, .start_routine = ebpf_sync_thread,
65 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
62 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
63 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
64 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &sync_config,
65 .config_file = NETDATA_SYNC_CONFIG_FILE,
66 // All syscalls have the same kernels
67 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
71 - .load = EBPF_LOAD_LEGACY, .targets = sync_targets},
68 + .load = EBPF_LOAD_LEGACY, .targets = sync_targets, .probe_links = NULL, .objects = NULL},
69 { .thread_name = "dc", .config_name = "dc", .enabled = 0, .start_routine = ebpf_dcstat_thread,
73 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
70 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
71 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
72 .apps_routine = ebpf_dcstat_create_apps_charts, .maps = NULL,
73 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &dcstat_config,
74 .config_file = NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE,
75 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
79 - .load = EBPF_LOAD_LEGACY, .targets = dc_targets},
76 + .load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL},
77 { .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
81 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
78 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
79 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
80 .apps_routine = ebpf_swap_create_apps_charts, .maps = NULL,
81 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
82 .config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE,
83 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
87 - .load = EBPF_LOAD_LEGACY, .targets = swap_targets},
84 + .load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL},
85 { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
89 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
86 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
87 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
88 .apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL,
89 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config,
90 .config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE,
91 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
95 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
92 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
93 { .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread,
97 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
94 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
95 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
96 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config,
97 .config_file = NETDATA_FILESYSTEM_CONFIG_FILE,
98 //We are setting kernels as zero, because we load eBPF programs according the kernel running.
102 - .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL },
99 + .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL },
100 { .thread_name = "disk", .config_name = "disk", .enabled = 0, .start_routine = ebpf_disk_thread,
104 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
101 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
102 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
103 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config,
104 .config_file = NETDATA_DISK_CONFIG_FILE,
105 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
109 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
106 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
107 { .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread,
111 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
108 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
109 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
110 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config,
111 .config_file = NETDATA_MOUNT_CONFIG_FILE,
112 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
116 - .load = EBPF_LOAD_LEGACY, .targets = mount_targets},
113 + .load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL},
114 { .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread,
118 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
115 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
116 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
117 .apps_routine = ebpf_fd_create_apps_charts, .maps = NULL,
118 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fd_config,
119 .config_file = NETDATA_FD_CONFIG_FILE,
120 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11,
124 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
121 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
122 { .thread_name = "hardirq", .config_name = "hardirq", .enabled = 0, .start_routine = ebpf_hardirq_thread,
126 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
123 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
124 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
125 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &hardirq_config,
126 .config_file = NETDATA_HARDIRQ_CONFIG_FILE,
127 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
131 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
128 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
129 { .thread_name = "softirq", .config_name = "softirq", .enabled = 0, .start_routine = ebpf_softirq_thread,
133 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
130 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
131 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
132 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &softirq_config,
133 .config_file = NETDATA_SOFTIRQ_CONFIG_FILE,
134 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
138 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
135 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
136 { .thread_name = "oomkill", .config_name = "oomkill", .enabled = 0, .start_routine = ebpf_oomkill_thread,
140 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
137 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
138 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
139 .apps_routine = ebpf_oomkill_create_apps_charts, .maps = NULL,
140 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &oomkill_config,
141 .config_file = NETDATA_OOMKILL_CONFIG_FILE,
142 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
146 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
143 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
144 { .thread_name = "shm", .config_name = "shm", .enabled = 0, .start_routine = ebpf_shm_thread,
148 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
145 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
146 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
147 .apps_routine = ebpf_shm_create_apps_charts, .maps = NULL,
148 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &shm_config,
149 .config_file = NETDATA_DIRECTORY_SHM_CONFIG_FILE,
150 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
154 - .load = EBPF_LOAD_LEGACY, .targets = shm_targets},
151 + .load = EBPF_LOAD_LEGACY, .targets = shm_targets, .probe_links = NULL, .objects = NULL},
152 { .thread_name = "mdflush", .config_name = "mdflush", .enabled = 0, .start_routine = ebpf_mdflush_thread,
156 - .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
153 + .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
154 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
155 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mdflush_config,
156 .config_file = NETDATA_DIRECTORY_MDFLUSH_CONFIG_FILE,
157 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
161 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
158 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
159 { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_every = EBPF_DEFAULT_UPDATE_EVERY,
163 - .global_charts = 0, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
160 + .global_charts = 0, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
161 .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, .pid_map_size = 0, .names = NULL,
165 - .cfg = NULL, .config_name = NULL, .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL},
162 + .cfg = NULL, .config_name = NULL, .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL,
163 + .objects = NULL},
164 +};
165 +
166 +struct netdata_static_thread ebpf_threads[] = {
167 + {"EBPF PROCESS", NULL, NULL, 1,
168 + NULL, NULL, NULL},
169 + {"EBPF SOCKET" , NULL, NULL, 1,
170 + NULL, NULL, NULL},
171 + {"EBPF CACHESTAT" , NULL, NULL, 1,
172 + NULL, NULL, NULL},
173 + {"EBPF SYNC" , NULL, NULL, 1,
174 + NULL, NULL, NULL},
175 + {"EBPF DCSTAT" , NULL, NULL, 1,
176 + NULL, NULL, NULL},
177 + {"EBPF SWAP" , NULL, NULL, 1,
178 + NULL, NULL, NULL},
179 + {"EBPF VFS" , NULL, NULL, 1,
180 + NULL, NULL, NULL},
181 + {"EBPF FILESYSTEM" , NULL, NULL, 1,
182 + NULL, NULL, NULL},
183 + {"EBPF DISK" , NULL, NULL, 1,
184 + NULL, NULL, NULL},
185 + {"EBPF MOUNT" , NULL, NULL, 1,
186 + NULL, NULL, NULL},
187 + {"EBPF FD" , NULL, NULL, 1,
188 + NULL, NULL, NULL},
189 + {"EBPF HARDIRQ" , NULL, NULL, 1,
190 + NULL, NULL, NULL},
191 + {"EBPF SOFTIRQ" , NULL, NULL, 1,
192 + NULL, NULL, NULL},
193 + {"EBPF OOMKILL" , NULL, NULL, 1,
194 + NULL, NULL, NULL},
195 + {"EBPF SHM" , NULL, NULL, 1,
196 + NULL, NULL, NULL},
197 + {"EBPF MDFLUSH" , NULL, NULL, 1,
198 + NULL, NULL, NULL},
199 + {NULL , NULL, NULL, 0,
200 + NULL, NULL, NULL}
201 +};
202 +
203 +ebpf_filesystem_partitions_t localfs[] =
204 + {{.filesystem = "ext4",
205 + .optional_filesystem = NULL,
206 + .family = "ext4",
207 + .objects = NULL,
208 + .probe_links = NULL,
209 + .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
210 + .enabled = CONFIG_BOOLEAN_YES,
211 + .addresses = {.function = NULL, .addr = 0},
212 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
213 + {.filesystem = "xfs",
214 + .optional_filesystem = NULL,
215 + .family = "xfs",
216 + .objects = NULL,
217 + .probe_links = NULL,
218 + .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
219 + .enabled = CONFIG_BOOLEAN_YES,
220 + .addresses = {.function = NULL, .addr = 0},
221 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
222 + {.filesystem = "nfs",
223 + .optional_filesystem = "nfs4",
224 + .family = "nfs",
225 + .objects = NULL,
226 + .probe_links = NULL,
227 + .flags = NETDATA_FILESYSTEM_ATTR_CHARTS,
228 + .enabled = CONFIG_BOOLEAN_YES,
229 + .addresses = {.function = NULL, .addr = 0},
230 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
231 + {.filesystem = "zfs",
232 + .optional_filesystem = NULL,
233 + .family = "zfs",
234 + .objects = NULL,
235 + .probe_links = NULL,
236 + .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
237 + .enabled = CONFIG_BOOLEAN_YES,
238 + .addresses = {.function = NULL, .addr = 0},
239 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
240 + {.filesystem = "btrfs",
241 + .optional_filesystem = NULL,
242 + .family = "btrfs",
243 + .objects = NULL,
244 + .probe_links = NULL,
245 + .flags = NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE,
246 + .enabled = CONFIG_BOOLEAN_YES,
247 + .addresses = {.function = "btrfs_file_operations", .addr = 0},
248 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10},
249 + {.filesystem = NULL,
250 + .optional_filesystem = NULL,
251 + .family = NULL,
252 + .objects = NULL,
253 + .probe_links = NULL,
254 + .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
255 + .enabled = CONFIG_BOOLEAN_YES,
256 + .addresses = {.function = NULL, .addr = 0},
257 + .kernels = 0}};
258 +
259 +ebpf_sync_syscalls_t local_syscalls[] = {
260 + {.syscall = NETDATA_SYSCALLS_SYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
261 +#ifdef LIBBPF_MAJOR_VERSION
262 + .sync_obj = NULL
263 +#endif
264 + },
265 + {.syscall = NETDATA_SYSCALLS_SYNCFS, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
266 +#ifdef LIBBPF_MAJOR_VERSION
267 + .sync_obj = NULL
268 +#endif
269 + },
270 + {.syscall = NETDATA_SYSCALLS_MSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
271 +#ifdef LIBBPF_MAJOR_VERSION
272 + .sync_obj = NULL
273 +#endif
274 + },
275 + {.syscall = NETDATA_SYSCALLS_FSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
276 +#ifdef LIBBPF_MAJOR_VERSION
277 + .sync_obj = NULL
278 +#endif
279 + },
280 + {.syscall = NETDATA_SYSCALLS_FDATASYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
281 +#ifdef LIBBPF_MAJOR_VERSION
282 + .sync_obj = NULL
283 +#endif
284 + },
285 + {.syscall = NETDATA_SYSCALLS_SYNC_FILE_RANGE, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
286 +#ifdef LIBBPF_MAJOR_VERSION
287 + .sync_obj = NULL
288 +#endif
289 + },
290 + {.syscall = NULL, .enabled = CONFIG_BOOLEAN_NO, .objects = NULL, .probe_links = NULL,
291 +#ifdef LIBBPF_MAJOR_VERSION
292 + .sync_obj = NULL
293 +#endif
294 + }
295 };
296
297 // Link with apps.plugin
@@ -192,18 +321,6 @@ char *btf_path = NULL;
321 *
322 *****************************************************************/
323
195 -/**
196 - * Clean Loaded Events
197 - *
198 - * This function cleans the events previous loaded on Linux.
199 -void clean_loaded_events()
200 -{
201 - int event_pid;
202 - for (event_pid = 0; ebpf_modules[event_pid].probes; event_pid++)
203 - clean_kprobe_events(NULL, (int)ebpf_modules[event_pid].thread_id, ebpf_modules[event_pid].probes);
204 -}
205 - */
206 -
324 /**
325 * Close the collector gracefully
326 *
@@ -211,64 +328,89 @@ void clean_loaded_events()
328 */
329 static void ebpf_exit(int sig)
330 {
214 - close_ebpf_plugin = 1;
215 - static int remove_pid = 0;
216 -
217 - // When both threads were not finished case I try to go in front this address, the collector will crash
218 - if (!thread_finished) {
219 - return;
331 +#ifdef LIBBPF_MAJOR_VERSION
332 + if (default_btf) {
333 + btf__free(default_btf);
334 + default_btf = NULL;
335 }
336 +#endif
337
222 - ebpf_close_cgroup_shm();
338 + char filename[FILENAME_MAX + 1];
339 + ebpf_pid_file(filename, FILENAME_MAX);
340 + if (unlink(filename))
341 + error("Cannot remove PID file %s", filename);
342
224 - /*
225 - int ret = fork();
226 - if (ret < 0) // error
227 - error("Cannot fork(), so I won't be able to clean %skprobe_events", NETDATA_DEBUGFS);
228 - else if (!ret) { // child
229 - int i;
230 - for (i = getdtablesize(); i >= 0; --i)
231 - close(i);
343 + exit(sig);
344 +}
345
233 - int fd = open("/dev/null", O_RDWR, 0);
234 - if (fd != -1) {
235 - dup2(fd, STDIN_FILENO);
236 - dup2(fd, STDOUT_FILENO);
237 - dup2(fd, STDERR_FILENO);
238 - }
346 +/**
347 + * Unload loegacy code
348 + *
349 + * @param objects objects loaded from eBPF programs
350 + * @param probe_links links from loader
351 + */
352 +static void ebpf_unload_legacy_code(struct bpf_object *objects, struct bpf_link **probe_links)
353 +{
354 + if (!probe_links || !objects)
355 + return;
356
240 - if (fd > 2)
241 - close(fd);
357 + struct bpf_program *prog;
358 + size_t j = 0 ;
359 + bpf_object__for_each_program(prog, objects) {
360 + bpf_link__destroy(probe_links[j]);
361 + j++;
362 + }
363 + freez(probe_links);
364 + if (objects)
365 + bpf_object__close(objects);
366 +}
367
243 - int sid = setsid();
244 - if (sid >= 0) {
245 - debug(D_EXIT, "Wait for father %d die", getpid());
246 - sleep_usec(200000); // Sleep 200 milliseconds to father dies.
247 - clean_loaded_events();
248 - } else {
249 - error("Cannot become session id leader, so I won't try to clean kprobe_events.\n");
368 +int ebpf_exit_plugin = 0;
369 +/**
370 + * Close the collector gracefully
371 + *
372 + * @param sig is the signal number used to close the collector
373 + */
374 +static void ebpf_stop_threads(int sig)
375 +{
376 + ebpf_exit_plugin = 1;
377 + int i;
378 + for (i = 0; ebpf_threads[i].name != NULL; i++);
379 +
380 + usec_t max = 2 * USEC_PER_SEC, step = 100000;
381 + while (i && max) {
382 + max -= step;
383 + sleep_usec(step);
384 + i = 0;
385 + int j;
386 + for (j = 0; ebpf_threads[j].name != NULL; j++) {
387 + if (ebpf_threads[j].enabled != NETDATA_MAIN_THREAD_EXITED)
388 + i++;
389 }
251 - } else { // parent
252 - exit(0);
390 }
254 - */
391
256 -#ifdef LIBBPF_MAJOR_VERSION
257 - if (default_btf) {
258 - btf__free(default_btf);
259 - default_btf = NULL;
392 + //Unload threads(except sync and filesystem)
393 + for (i = 0; ebpf_threads[i].name != NULL; i++) {
394 + if (ebpf_threads[i].enabled == NETDATA_MAIN_THREAD_EXITED && i != EBPF_MODULE_FILESYSTEM_IDX &&
395 + i != EBPF_MODULE_SYNC_IDX)
396 + ebpf_unload_legacy_code(ebpf_modules[i].objects, ebpf_modules[i].probe_links);
397 }
261 -#endif
398
263 - if (!remove_pid) {
264 - remove_pid = 1;
265 - char filename[FILENAME_MAX + 1];
266 - ebpf_pid_file(filename, FILENAME_MAX);
267 - if (unlink(filename))
268 - error("Cannot remove PID file %s", filename);
399 + //Unload filesystem
400 + if (ebpf_threads[EBPF_MODULE_FILESYSTEM_IDX].enabled == NETDATA_MAIN_THREAD_EXITED) {
401 + for (i = 0; localfs[i].filesystem != NULL; i++) {
402 + ebpf_unload_legacy_code(localfs[i].objects, localfs[i].probe_links);
403 + }
404 }
405
271 - exit(sig);
406 + //Unload Sync
407 + if (ebpf_threads[EBPF_MODULE_SYNC_IDX].enabled == NETDATA_MAIN_THREAD_EXITED) {
408 + for (i = 0; local_syscalls[i].syscall != NULL; i++) {
409 + ebpf_unload_legacy_code(local_syscalls[i].objects, local_syscalls[i].probe_links);
410 + }
411 + }
412 +
413 + ebpf_exit(sig);
414 }
415
416 /*****************************************************************
@@ -659,7 +801,7 @@ static inline void ebpf_enable_specific_chart(struct ebpf_module *em, int disabl
801 // oomkill stores data inside apps submenu, so it always need to have apps_enabled for plugin to create
802 // its chart, without this comparison eBPF.plugin will try to store invalid data when apps is disabled.
803 if (!disable_apps || !strcmp(em->thread_name, "oomkill")) {
662 - em->apps_charts = CONFIG_BOOLEAN_YES;
804 + em->apps_charts = NETDATA_EBPF_APPS_FLAG_YES;
805 }
806
807 if (!disable_cgroup) {
@@ -724,7 +866,7 @@ static inline void ebpf_disable_apps()
866 {
867 int i;
868 for (i = 0; ebpf_modules[i].thread_name; i++) {
727 - ebpf_modules[i].apps_charts = 0;
869 + ebpf_modules[i].apps_charts = NETDATA_EBPF_APPS_FLAG_NO;
870 }
871 }
872
@@ -1031,7 +1173,6 @@ int ebpf_start_pthread_variables()
1173 pthread_mutex_init(&collect_data_mutex, NULL);
1174
1175 if (pthread_cond_init(&collect_data_cond_var, NULL)) {
1034 - thread_finished++;
1176 error("Cannot start conditional variable to control Apps charts.");
1177 return -1;
1178 }
@@ -1051,7 +1192,7 @@ static inline uint32_t ebpf_am_i_collect_pids()
1192 uint32_t ret = 0;
1193 int i;
1194 for (i = 0; ebpf_modules[i].thread_name; i++) {
1054 - ret |= ebpf_modules[i].cgroup_charts | ebpf_modules[i].apps_charts;
1195 + ret |= ebpf_modules[i].cgroup_charts | (ebpf_modules[i].apps_charts & NETDATA_EBPF_APPS_FLAG_YES);
1196 }
1197
1198 return ret;
@@ -1675,7 +1816,6 @@ static void ebpf_parse_args(int argc, char **argv)
1816 &apps_groups_default_target, &apps_groups_root_target, ebpf_stock_config_dir, "groups")) {
1817 error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.",
1818 ebpf_stock_config_dir);
1678 - thread_finished++;
1819 ebpf_exit(1);
1820 }
1821 } else
@@ -1831,6 +1971,19 @@ static void ebpf_manage_pid(pid_t pid)
1971 ebpf_update_pid_file(filename, pid);
1972 }
1973
1974 +/**
1975 + * Set start routine
1976 + *
1977 + * Set static routine before threads to be created.
1978 + */
1979 + static void ebpf_set_static_routine()
1980 + {
1981 + int i;
1982 + for (i = 0; ebpf_modules[i].thread_name; i++) {
1983 + ebpf_threads[i].start_routine = ebpf_modules[i].start_routine;
1984 + }
1985 + }
1986 +
1987 /**
1988 * Entry point
1989 *
@@ -1875,16 +2028,19 @@ int main(int argc, char **argv)
2028 return 4;
2029 }
2030
1878 - signal(SIGINT, ebpf_exit);
1879 - signal(SIGTERM, ebpf_exit);
1880 - signal(SIGPIPE, ebpf_exit);
2031 + signal(SIGINT, ebpf_stop_threads);
2032 + signal(SIGQUIT, ebpf_stop_threads);
2033 + signal(SIGTERM, ebpf_stop_threads);
2034 + signal(SIGPIPE, ebpf_stop_threads);
2035
2036 if (ebpf_start_pthread_variables()) {
1883 - thread_finished++;
2037 error("Cannot start mutex to control overall charts.");
2038 ebpf_exit(5);
2039 }
2040
2041 + netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
2042 + if(verify_netdata_host_prefix() == -1) ebpf_exit(6);
2043 +
2044 ebpf_allocate_common_vectors();
2045
2046 #ifdef LIBBPF_MAJOR_VERSION
@@ -1897,44 +2053,7 @@ int main(int argc, char **argv)
2053 read_local_ports("/proc/net/udp", IPPROTO_UDP);
2054 read_local_ports("/proc/net/udp6", IPPROTO_UDP);
2055
1900 - struct netdata_static_thread ebpf_threads[] = {
1901 - {"EBPF PROCESS", NULL, NULL, 1,
1902 - NULL, NULL, ebpf_modules[EBPF_MODULE_PROCESS_IDX].start_routine},
1903 - {"EBPF SOCKET" , NULL, NULL, 1,
1904 - NULL, NULL, ebpf_modules[EBPF_MODULE_SOCKET_IDX].start_routine},
1905 - {"EBPF CACHESTAT" , NULL, NULL, 1,
1906 - NULL, NULL, ebpf_modules[EBPF_MODULE_CACHESTAT_IDX].start_routine},
1907 - {"EBPF SYNC" , NULL, NULL, 1,
1908 - NULL, NULL, ebpf_modules[EBPF_MODULE_SYNC_IDX].start_routine},
1909 - {"EBPF DCSTAT" , NULL, NULL, 1,
1910 - NULL, NULL, ebpf_modules[EBPF_MODULE_DCSTAT_IDX].start_routine},
1911 - {"EBPF SWAP" , NULL, NULL, 1,
1912 - NULL, NULL, ebpf_modules[EBPF_MODULE_SWAP_IDX].start_routine},
1913 - {"EBPF VFS" , NULL, NULL, 1,
1914 - NULL, NULL, ebpf_modules[EBPF_MODULE_VFS_IDX].start_routine},
1915 - {"EBPF FILESYSTEM" , NULL, NULL, 1,
1916 - NULL, NULL, ebpf_modules[EBPF_MODULE_FILESYSTEM_IDX].start_routine},
1917 - {"EBPF DISK" , NULL, NULL, 1,
1918 - NULL, NULL, ebpf_modules[EBPF_MODULE_DISK_IDX].start_routine},
1919 - {"EBPF MOUNT" , NULL, NULL, 1,
1920 - NULL, NULL, ebpf_modules[EBPF_MODULE_MOUNT_IDX].start_routine},
1921 - {"EBPF FD" , NULL, NULL, 1,
1922 - NULL, NULL, ebpf_modules[EBPF_MODULE_FD_IDX].start_routine},
1923 - {"EBPF HARDIRQ" , NULL, NULL, 1,
1924 - NULL, NULL, ebpf_modules[EBPF_MODULE_HARDIRQ_IDX].start_routine},
1925 - {"EBPF SOFTIRQ" , NULL, NULL, 1,
1926 - NULL, NULL, ebpf_modules[EBPF_MODULE_SOFTIRQ_IDX].start_routine},
1927 - {"EBPF OOMKILL" , NULL, NULL, 1,
1928 - NULL, NULL, ebpf_modules[EBPF_MODULE_OOMKILL_IDX].start_routine},
1929 - {"EBPF SHM" , NULL, NULL, 1,
1930 - NULL, NULL, ebpf_modules[EBPF_MODULE_SHM_IDX].start_routine},
1931 - {"EBPF MDFLUSH" , NULL, NULL, 1,
1932 - NULL, NULL, ebpf_modules[EBPF_MODULE_MDFLUSH_IDX].start_routine},
1933 - {NULL , NULL, NULL, 0,
1934 - NULL, NULL, NULL}
1935 - };
1936 -
1937 - //clean_loaded_events();
2056 + ebpf_set_static_routine();
2057
2058 int i;
2059 for (i = 0; ebpf_threads[i].name != NULL; i++) {
@@ -1943,16 +2062,16 @@ int main(int argc, char **argv)
2062
2063 ebpf_module_t *em = &ebpf_modules[i];
2064 em->thread_id = i;
1946 - netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_JOINABLE, st->start_routine, em);
2065 + netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, em);
2066 }
2067
1949 - for (i = 0; ebpf_threads[i].name != NULL; i++) {
1950 - struct netdata_static_thread *st = &ebpf_threads[i];
1951 - netdata_thread_join(*st->thread, NULL);
2068 + usec_t step = 60 * USEC_PER_SEC;
2069 + heartbeat_t hb;
2070 + heartbeat_init(&hb);
2071 + //Plugin will be killed when it receives a signal
2072 + for (;;) {
2073 + (void)heartbeat_next(&hb, step);
2074 }
2075
1954 - thread_finished++;
1955 - ebpf_exit(0);
1956 -
2076 return 0;
2077 }
collectors/ebpf.plugin/ebpf.h
+9 -2
@@ -108,6 +108,12 @@ typedef struct ebpf_tracepoint {
108 char *event;
109 } ebpf_tracepoint_t;
110
111 +enum ebpf_threads_status {
112 + NETDATA_THREAD_EBPF_RUNNING,
113 + NETDATA_THREAD_EBPF_STOPPING,
114 + NETDATA_THREAD_EBPF_STOPPED
115 +};
116 +
117 // Copied from musl header
118 #ifndef offsetof
119 #if __GNUC__ > 3
@@ -162,7 +168,6 @@ extern void *ebpf_socket_thread(void *ptr);
168
169 // Common variables
170 extern pthread_mutex_t lock;
165 -extern int close_ebpf_plugin;
171 extern int ebpf_nprocs;
172 extern int running_on_kernel;
173 extern int isrh;
@@ -265,7 +270,6 @@ extern int shm_fd_ebpf_cgroup;
270 extern sem_t *shm_sem_ebpf_cgroup;
271 extern pthread_mutex_t mutex_cgroup_shm;
272 extern size_t all_pids_count;
268 -extern uint32_t finalized_threads;
273 extern ebpf_plugin_stats_t plugin_statistics;
274 extern struct btf *default_btf;
275
@@ -281,6 +285,9 @@ extern void ebpf_write_chart_obsolete(char *type, char *id, char *title, char *u
285 char *charttype, char *context, int order, int update_every);
286 extern void write_histogram_chart(char *family, char *name, const netdata_idx_t *hist, char **dimensions, uint32_t end);
287 void ebpf_update_disabled_plugin_stats(ebpf_module_t *em);
288 +extern ebpf_filesystem_partitions_t localfs[];
289 +extern ebpf_sync_syscalls_t local_syscalls[];
290 +extern int ebpf_exit_plugin;
291
292 #define EBPF_MAX_SYNCHRONIZATION_TIME 300
293
collectors/ebpf.plugin/ebpf_apps.c
+2 -2
@@ -134,7 +134,7 @@ size_t zero_all_targets(struct target *root)
134 while (pid_on_target) {
135 struct pid_on_target *pid_on_target_to_free = pid_on_target;
136 pid_on_target = pid_on_target->next;
137 - free(pid_on_target_to_free);
137 + freez(pid_on_target_to_free);
138 }
139
140 w->root_pid = NULL;
@@ -1119,7 +1119,7 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd)
1119 key = pids->pid;
1120 ebpf_process_stat_t *w = global_process_stats[key];
1121 if (!w) {
1122 - w = mallocz(sizeof(ebpf_process_stat_t));
1122 + w = callocz(1, sizeof(ebpf_process_stat_t));
1123 global_process_stats[key] = w;
1124 }
1125
collectors/ebpf.plugin/ebpf_cachestat.c
+47 -38
@@ -5,9 +5,6 @@
5
6 netdata_publish_cachestat_t **cachestat_pid;
7
8 -static struct bpf_link **probe_links = NULL;
9 -static struct bpf_object *objects = NULL;
10 -
8 static char *cachestat_counter_dimension_name[NETDATA_CACHESTAT_END] = { "ratio", "dirty", "hit",
9 "miss" };
10 static netdata_syscall_stat_t cachestat_counter_aggregated_data[NETDATA_CACHESTAT_END];
@@ -18,8 +15,6 @@ netdata_cachestat_pid_t *cachestat_vector = NULL;
15 static netdata_idx_t cachestat_hash_values[NETDATA_CACHESTAT_END];
16 static netdata_idx_t *cachestat_values = NULL;
17
21 -static int read_thread_closed = 1;
22 -
18 struct netdata_static_thread cachestat_threads = {"CACHESTAT KERNEL",
19 NULL, NULL, 1, NULL,
20 NULL, NULL};
@@ -44,6 +39,7 @@ struct config cachestat_config = { .first_section = NULL,
39 .mutex = NETDATA_MUTEX_INITIALIZER,
40 .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
41 .rwlock = AVL_LOCK_INITIALIZER } };
42 +static enum ebpf_threads_status ebpf_cachestat_exited = NETDATA_THREAD_EBPF_RUNNING;
43
44 netdata_ebpf_targets_t cachestat_targets[] = { {.name = "add_to_page_cache_lru", .mode = EBPF_LOAD_TRAMPOLINE},
45 {.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
290 *****************************************************************/
291
292 /**
297 - * Clean up the main thread.
293 + * Cachestat exit.
294 + *
295 + * Cancel child and exit.
296 *
297 * @param ptr thread data.
298 */
301 -static void ebpf_cachestat_cleanup(void *ptr)
299 +static void ebpf_cachestat_exit(void *ptr)
300 {
301 ebpf_module_t *em = (ebpf_module_t *)ptr;
304 - if (!em->enabled)
302 + if (!em->enabled) {
303 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
304 return;
306 -
307 - heartbeat_t hb;
308 - heartbeat_init(&hb);
309 - uint32_t tick = 2*USEC_PER_MS;
310 - while (!read_thread_closed) {
311 - usec_t dt = heartbeat_next(&hb, tick);
312 - UNUSED(dt);
305 }
306
307 + ebpf_cachestat_exited = NETDATA_THREAD_EBPF_STOPPING;
308 +}
309 +
310 +/**
311 + * Cachestat cleanup
312 + *
313 + * Clean up allocated addresses.
314 + *
315 + * @param ptr thread data.
316 + */
317 +static void ebpf_cachestat_cleanup(void *ptr)
318 +{
319 + ebpf_module_t *em = (ebpf_module_t *)ptr;
320 + if (ebpf_cachestat_exited != NETDATA_THREAD_EBPF_STOPPED)
321 + return;
322 +
323 ebpf_cleanup_publish_syscall(cachestat_counter_publish_aggregated);
324
325 freez(cachestat_vector);
326 freez(cachestat_values);
327 + freez(cachestat_threads.thread);
328
320 - if (probe_links) {
321 - struct bpf_program *prog;
322 - size_t i = 0 ;
323 - bpf_object__for_each_program(prog, objects) {
324 - bpf_link__destroy(probe_links[i]);
325 - i++;
326 - }
327 - if (objects)
328 - bpf_object__close(objects);
329 - }
329 #ifdef LIBBPF_MAJOR_VERSION
331 - else if (bpf_obj)
330 + if (bpf_obj)
331 cachestat_bpf__destroy(bpf_obj);
332 #endif
333 + cachestat_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
334 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
335 }
336
337 /*****************************************************************
@@ -594,6 +595,8 @@ void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
595 20093,
596 ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
597 root, em->update_every, NETDATA_EBPF_MODULE_NAME_CACHESTAT);
598 +
599 + em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
600 }
601
602 /*****************************************************************
@@ -639,22 +642,25 @@ static void read_global_table()
642 */
643 void *ebpf_cachestat_read_hash(void *ptr)
644 {
642 - read_thread_closed = 0;
643 -
645 + netdata_thread_cleanup_push(ebpf_cachestat_cleanup, ptr);
646 heartbeat_t hb;
647 heartbeat_init(&hb);
648
649 ebpf_module_t *em = (ebpf_module_t *)ptr;
650
651 usec_t step = NETDATA_LATENCY_CACHESTAT_SLEEP_MS * em->update_every;
650 - while (!close_ebpf_plugin) {
652 + while (ebpf_cachestat_exited == NETDATA_THREAD_EBPF_RUNNING) {
653 usec_t dt = heartbeat_next(&hb, step);
654 (void)dt;
655 + if (ebpf_cachestat_exited == NETDATA_THREAD_EBPF_STOPPING)
656 + break;
657
658 read_global_table();
659 }
656 - read_thread_closed = 1;
660
661 + ebpf_cachestat_exited = NETDATA_THREAD_EBPF_STOPPED;
662 +
663 + netdata_thread_cleanup_pop(1);
664 return NULL;
665 }
666
@@ -1068,23 +1074,26 @@ void ebpf_cachestat_send_cgroup_data(int update_every)
1074 */
1075 static void cachestat_collector(ebpf_module_t *em)
1076 {
1071 - cachestat_threads.thread = mallocz(sizeof(netdata_thread_t));
1077 + cachestat_threads.thread = callocz(1, sizeof(netdata_thread_t));
1078 cachestat_threads.start_routine = ebpf_cachestat_read_hash;
1079
1074 - netdata_thread_create(cachestat_threads.thread, cachestat_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
1080 + netdata_thread_create(cachestat_threads.thread, cachestat_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
1081 ebpf_cachestat_read_hash, em);
1082
1083 netdata_publish_cachestat_t publish;
1084 memset(&publish, 0, sizeof(publish));
1079 - int apps = em->apps_charts;
1085 int cgroups = em->cgroup_charts;
1086 int update_every = em->update_every;
1087 heartbeat_t hb;
1088 heartbeat_init(&hb);
1089 usec_t step = update_every * USEC_PER_SEC;
1085 - while (!close_ebpf_plugin) {
1090 + //This will be cancelled by its parent
1091 + while (!ebpf_exit_plugin) {
1092 (void)heartbeat_next(&hb, step);
1093 + if (ebpf_exit_plugin)
1094 + break;
1095
1096 + netdata_apps_integration_flags_t apps = em->apps_charts;
1097 pthread_mutex_lock(&collect_data_mutex);
1098 if (apps)
1099 read_apps_table();
@@ -1096,7 +1105,7 @@ static void cachestat_collector(ebpf_module_t *em)
1105
1106 cachestat_send_global(&publish);
1107
1099 - if (apps)
1108 + if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
1109 ebpf_cache_send_apps_data(apps_groups_root_target);
1110
1111 if (cgroups)
@@ -1219,8 +1228,8 @@ static int ebpf_cachestat_load_bpf(ebpf_module_t *em)
1228 {
1229 int ret = 0;
1230 if (em->load == EBPF_LOAD_LEGACY) {
1222 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
1223 - if (!probe_links) {
1231 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1232 + if (!em->probe_links) {
1233 ret = -1;
1234 }
1235 }
@@ -1251,7 +1260,7 @@ static int ebpf_cachestat_load_bpf(ebpf_module_t *em)
1260 */
1261 void *ebpf_cachestat_thread(void *ptr)
1262 {
1254 - netdata_thread_cleanup_push(ebpf_cachestat_cleanup, ptr);
1263 + netdata_thread_cleanup_push(ebpf_cachestat_exit, ptr);
1264
1265 ebpf_module_t *em = (ebpf_module_t *)ptr;
1266 em->maps = cachestat_maps;
collectors/ebpf.plugin/ebpf_dcstat.c
+43 -36
@@ -10,14 +10,9 @@ static netdata_publish_syscall_t dcstat_counter_publish_aggregated[NETDATA_DCSTA
10 netdata_dcstat_pid_t *dcstat_vector = NULL;
11 netdata_publish_dcstat_t **dcstat_pid = NULL;
12
13 -static struct bpf_link **probe_links = NULL;
14 -static struct bpf_object *objects = NULL;
15 -
13 static netdata_idx_t dcstat_hash_values[NETDATA_DCSTAT_IDX_END];
14 static netdata_idx_t *dcstat_values = NULL;
15
19 -static int read_thread_closed = 1;
20 -
16 struct config dcstat_config = { .first_section = NULL,
17 .last_section = NULL,
18 .mutex = NETDATA_MUTEX_INITIALIZER,
@@ -27,6 +22,7 @@ struct config dcstat_config = { .first_section = NULL,
22 struct netdata_static_thread dcstat_threads = {"DCSTAT KERNEL",
23 NULL, NULL, 1, NULL,
24 NULL, NULL};
25 +static enum ebpf_threads_status ebpf_dcstat_exited = NETDATA_THREAD_EBPF_RUNNING;
26
27 static ebpf_local_maps_t dcstat_maps[] = {{.name = "dcstat_global", .internal_input = NETDATA_DIRECTORY_CACHE_END,
28 .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
@@ -265,6 +261,24 @@ void ebpf_dcstat_clean_names()
261 }
262 }
263
264 +/**
265 + * DCstat exit
266 + *
267 + * Cancel child and exit.
268 + *
269 + * @param ptr thread data.
270 + */
271 +static void ebpf_dcstat_exit(void *ptr)
272 +{
273 + ebpf_module_t *em = (ebpf_module_t *)ptr;
274 + if (!em->enabled) {
275 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
276 + return;
277 + }
278 +
279 + ebpf_dcstat_exited = NETDATA_THREAD_EBPF_STOPPING;
280 +}
281 +
282 /**
283 * Clean up the main thread.
284 *
@@ -273,38 +287,24 @@ void ebpf_dcstat_clean_names()
287 static void ebpf_dcstat_cleanup(void *ptr)
288 {
289 ebpf_module_t *em = (ebpf_module_t *)ptr;
276 - if (!em->enabled)
290 + if (ebpf_dcstat_exited != NETDATA_THREAD_EBPF_STOPPED)
291 return;
292
279 - heartbeat_t hb;
280 - heartbeat_init(&hb);
281 - uint32_t tick = 2 * USEC_PER_MS;
282 - while (!read_thread_closed) {
283 - usec_t dt = heartbeat_next(&hb, tick);
284 - UNUSED(dt);
285 - }
286 -
293 freez(dcstat_vector);
294 freez(dcstat_values);
295 + freez(dcstat_threads.thread);
296
297 ebpf_cleanup_publish_syscall(dcstat_counter_publish_aggregated);
298
299 ebpf_dcstat_clean_names();
300
294 - if (probe_links) {
295 - struct bpf_program *prog;
296 - size_t i = 0 ;
297 - bpf_object__for_each_program(prog, objects) {
298 - bpf_link__destroy(probe_links[i]);
299 - i++;
300 - }
301 - if (objects)
302 - bpf_object__close(objects);
303 - }
301 #ifdef LIBBPF_MAJOR_VERSION
305 - else if (bpf_obj)
302 + if (bpf_obj)
303 dc_bpf__destroy(bpf_obj);
304 #endif
305 +
306 + dcstat_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
307 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
308 }
309
310 /*****************************************************************
@@ -358,6 +358,8 @@ void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr)
358 20103,
359 ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
360 root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
361 +
362 + em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
363 }
364
365 /*****************************************************************
@@ -522,22 +524,25 @@ static void read_global_table()
524 */
525 void *ebpf_dcstat_read_hash(void *ptr)
526 {
525 - read_thread_closed = 0;
526 -
527 + netdata_thread_cleanup_push(ebpf_dcstat_cleanup, ptr);
528 heartbeat_t hb;
529 heartbeat_init(&hb);
530
531 ebpf_module_t *em = (ebpf_module_t *)ptr;
532
533 usec_t step = NETDATA_LATENCY_DCSTAT_SLEEP_MS * em->update_every;
533 - while (!close_ebpf_plugin) {
534 + while (ebpf_dcstat_exited == NETDATA_THREAD_EBPF_RUNNING) {
535 usec_t dt = heartbeat_next(&hb, step);
536 (void)dt;
537 + if (ebpf_dcstat_exited == NETDATA_THREAD_EBPF_STOPPING)
538 + break;
539
540 read_global_table();
541 }
539 - read_thread_closed = 1;
542
543 + ebpf_dcstat_exited = NETDATA_THREAD_EBPF_STOPPED;
544 +
545 + netdata_thread_cleanup_pop(1);
546 return NULL;
547 }
548
@@ -1000,20 +1005,22 @@ static void dcstat_collector(ebpf_module_t *em)
1005 dcstat_threads.thread = mallocz(sizeof(netdata_thread_t));
1006 dcstat_threads.start_routine = ebpf_dcstat_read_hash;
1007
1003 - netdata_thread_create(dcstat_threads.thread, dcstat_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
1008 + netdata_thread_create(dcstat_threads.thread, dcstat_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
1009 ebpf_dcstat_read_hash, em);
1010
1011 netdata_publish_dcstat_t publish;
1012 memset(&publish, 0, sizeof(publish));
1008 - int apps = em->apps_charts;
1013 int cgroups = em->cgroup_charts;
1014 int update_every = em->update_every;
1015 heartbeat_t hb;
1016 heartbeat_init(&hb);
1017 usec_t step = update_every * USEC_PER_SEC;
1014 - while (!close_ebpf_plugin) {
1018 + while (!ebpf_exit_plugin) {
1019 (void)heartbeat_next(&hb, step);
1020 + if (ebpf_exit_plugin)
1021 + break;
1022
1023 + netdata_apps_integration_flags_t apps = em->apps_charts;
1024 pthread_mutex_lock(&collect_data_mutex);
1025 if (apps)
1026 read_apps_table();
@@ -1025,7 +1032,7 @@ static void dcstat_collector(ebpf_module_t *em)
1032
1033 dcstat_send_global(&publish);
1034
1028 - if (apps)
1035 + if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
1036 ebpf_dcache_send_apps_data(apps_groups_root_target);
1037
1038 if (cgroups)
@@ -1110,8 +1117,8 @@ static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
1117 {
1118 int ret = 0;
1119 if (em->load == EBPF_LOAD_LEGACY) {
1113 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
1114 - if (!probe_links) {
1120 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1121 + if (!em->probe_links) {
1122 ret = -1;
1123 }
1124 }
@@ -1142,7 +1149,7 @@ static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
1149 */
1150 void *ebpf_dcstat_thread(void *ptr)
1151 {
1145 - netdata_thread_cleanup_push(ebpf_dcstat_cleanup, ptr);
1152 + netdata_thread_cleanup_push(ebpf_dcstat_exit, ptr);
1153
1154 ebpf_module_t *em = (ebpf_module_t *)ptr;
1155 em->maps = dcstat_maps;
collectors/ebpf.plugin/ebpf_disk.c
+40 -34
@@ -25,9 +25,6 @@ char *tracepoint_block_type = { "block"} ;
25 char *tracepoint_block_issue = { "block_rq_issue" };
26 char *tracepoint_block_rq_complete = { "block_rq_complete" };
27
28 -static struct bpf_link **probe_links = NULL;
29 -static struct bpf_object *objects = NULL;
30 -
28 static int was_block_issue_enabled = 0;
29 static int was_block_rq_complete_enabled = 0;
30
@@ -35,12 +32,11 @@ static char **dimensions = NULL;
32 static netdata_syscall_stat_t disk_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
33 static netdata_publish_syscall_t disk_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
34
38 -static int read_thread_closed = 1;
39 -
35 static netdata_idx_t *disk_hash_values = NULL;
36 static struct netdata_static_thread disk_threads = {"DISK KERNEL",
37 NULL, NULL, 1, NULL,
38 NULL, NULL };
39 +static enum ebpf_threads_status ebpf_disk_exited = NETDATA_THREAD_EBPF_RUNNING;
40
41 ebpf_publish_disk_t *plot_disks = NULL;
42 pthread_mutex_t plot_mutex;
@@ -428,25 +424,37 @@ static void ebpf_cleanup_disk_list()
424 }
425
426 /**
431 - * Clean up the main thread.
427 + * Disk exit.
428 + *
429 + * Cancel child and exit.
430 *
431 * @param ptr thread data.
432 */
435 -static void ebpf_disk_cleanup(void *ptr)
433 +static void ebpf_disk_exit(void *ptr)
434 {
437 - ebpf_disk_disable_tracepoints();
435 + ebpf_module_t *em = (ebpf_module_t *)ptr;
436 + if (!em->enabled) {
437 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
438 + return;
439 + }
440 +
441 + ebpf_disk_exited = NETDATA_THREAD_EBPF_STOPPING;
442 +}
443
444 +/**
445 + * Disk Cleanup
446 + *
447 + * Clean up allocated memory.
448 + *
449 + * @param ptr thread data.
450 + */
451 +static void ebpf_disk_cleanup(void *ptr)
452 +{
453 ebpf_module_t *em = (ebpf_module_t *)ptr;
440 - if (!em->enabled)
454 + if (ebpf_disk_exited != NETDATA_THREAD_EBPF_STOPPED)
455 return;
456
443 - heartbeat_t hb;
444 - heartbeat_init(&hb);
445 - uint32_t tick = 2 * USEC_PER_MS;
446 - while (!read_thread_closed) {
447 - usec_t dt = heartbeat_next(&hb, tick);
448 - UNUSED(dt);
449 - }
457 + ebpf_disk_disable_tracepoints();
458
459 if (dimensions)
460 ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
@@ -458,16 +466,8 @@ static void ebpf_disk_cleanup(void *ptr)
466 ebpf_cleanup_plot_disks();
467 ebpf_cleanup_disk_list();
468
461 - if (probe_links) {
462 - struct bpf_program *prog;
463 - size_t i = 0 ;
464 - bpf_object__for_each_program(prog, objects) {
465 - bpf_link__destroy(probe_links[i]);
466 - i++;
467 - }
468 - if (objects)
469 - bpf_object__close(objects);
470 - }
469 + disk_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
470 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
471 }
472
473 /*****************************************************************
@@ -583,19 +583,25 @@ static void read_hard_disk_tables(int table)
583 */
584 void *ebpf_disk_read_hash(void *ptr)
585 {
586 + netdata_thread_cleanup_push(ebpf_disk_cleanup, ptr);
587 heartbeat_t hb;
588 heartbeat_init(&hb);
589
590 ebpf_module_t *em = (ebpf_module_t *)ptr;
591
592 usec_t step = NETDATA_LATENCY_DISK_SLEEP_MS * em->update_every;
592 - while (!close_ebpf_plugin) {
593 + while (ebpf_disk_exited == NETDATA_THREAD_EBPF_RUNNING) {
594 usec_t dt = heartbeat_next(&hb, step);
595 (void)dt;
596 + if (ebpf_disk_exited == NETDATA_THREAD_EBPF_STOPPING)
597 + break;
598
599 read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd);
600 }
601
602 + ebpf_disk_exited = NETDATA_THREAD_EBPF_STOPPED;
603 +
604 + netdata_thread_cleanup_pop(1);
605 return NULL;
606 }
607
@@ -725,16 +731,17 @@ static void disk_collector(ebpf_module_t *em)
731 disk_threads.thread = mallocz(sizeof(netdata_thread_t));
732 disk_threads.start_routine = ebpf_disk_read_hash;
733
728 - netdata_thread_create(disk_threads.thread, disk_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
734 + netdata_thread_create(disk_threads.thread, disk_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
735 ebpf_disk_read_hash, em);
736
737 int update_every = em->update_every;
732 - read_thread_closed = 0;
738 heartbeat_t hb;
739 heartbeat_init(&hb);
740 usec_t step = update_every * USEC_PER_SEC;
736 - while (!close_ebpf_plugin) {
741 + while (!ebpf_exit_plugin) {
742 (void)heartbeat_next(&hb, step);
743 + if (ebpf_exit_plugin)
744 + break;
745
746 pthread_mutex_lock(&lock);
747 ebpf_remove_pointer_from_plot_disk(em);
@@ -744,7 +751,6 @@ static void disk_collector(ebpf_module_t *em)
751
752 ebpf_update_disks(em);
753 }
747 - read_thread_closed = 1;
754 }
755
756 /*****************************************************************
@@ -794,7 +800,7 @@ static int ebpf_disk_enable_tracepoints()
800 */
801 void *ebpf_disk_thread(void *ptr)
802 {
797 - netdata_thread_cleanup_push(ebpf_disk_cleanup, ptr);
803 + netdata_thread_cleanup_push(ebpf_disk_exit, ptr);
804
805 ebpf_module_t *em = (ebpf_module_t *)ptr;
806 em->maps = disk_maps;
@@ -819,8 +825,8 @@ void *ebpf_disk_thread(void *ptr)
825 goto enddisk;
826 }
827
822 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
823 - if (!probe_links) {
828 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
829 + if (!em->probe_links) {
830 em->enabled = 0;
831 goto enddisk;
832 }
collectors/ebpf.plugin/ebpf_fd.c
+40 -34
@@ -29,12 +29,9 @@ struct config fd_config = { .first_section = NULL, .last_section = NULL, .mutex
29 .index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare },
30 .rwlock = AVL_LOCK_INITIALIZER } };
31
32 -static struct bpf_link **probe_links = NULL;
33 -static struct bpf_object *objects = NULL;
34 -
32 struct netdata_static_thread fd_thread = {"FD KERNEL", NULL, NULL, 1, NULL,
33 NULL, NULL};
37 -static int read_thread_closed = 1;
34 +static enum ebpf_threads_status ebpf_fd_exited = NETDATA_THREAD_EBPF_RUNNING;
35 static netdata_idx_t fd_hash_values[NETDATA_FD_COUNTER];
36 static netdata_idx_t *fd_values = NULL;
37
@@ -47,6 +44,24 @@ netdata_fd_stat_t **fd_pid = NULL;
44 *
45 *****************************************************************/
46
47 +/**
48 + * FD Exit
49 + *
50 + * Cancel child thread and exit.
51 + *
52 + * @param ptr thread data.
53 + */
54 +static void ebpf_fd_exit(void *ptr)
55 +{
56 + ebpf_module_t *em = (ebpf_module_t *)ptr;
57 + if (!em->enabled) {
58 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
59 + return;
60 + }
61 +
62 + ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPING;
63 +}
64 +
65 /**
66 * Clean up the main thread.
67 *
@@ -55,32 +70,16 @@ netdata_fd_stat_t **fd_pid = NULL;
70 static void ebpf_fd_cleanup(void *ptr)
71 {
72 ebpf_module_t *em = (ebpf_module_t *)ptr;
58 - if (!em->enabled)
73 + if (ebpf_fd_exited != NETDATA_THREAD_EBPF_STOPPED)
74 return;
75
61 - heartbeat_t hb;
62 - heartbeat_init(&hb);
63 - uint32_t tick = 2 * USEC_PER_MS;
64 - while (!read_thread_closed) {
65 - usec_t dt = heartbeat_next(&hb, tick);
66 - UNUSED(dt);
67 - }
68 -
76 ebpf_cleanup_publish_syscall(fd_publish_aggregated);
77 freez(fd_thread.thread);
78 freez(fd_values);
79 freez(fd_vector);
80
74 - if (probe_links) {
75 - struct bpf_program *prog;
76 - size_t i = 0 ;
77 - bpf_object__for_each_program(prog, objects) {
78 - bpf_link__destroy(probe_links[i]);
79 - i++;
80 - }
81 - if (objects)
82 - bpf_object__close(objects);
83 - }
81 + fd_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
82 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
83 }
84
85 /*****************************************************************
@@ -148,21 +147,24 @@ static void read_global_table()
147 */
148 void *ebpf_fd_read_hash(void *ptr)
149 {
151 - read_thread_closed = 0;
152 -
150 + netdata_thread_cleanup_push(ebpf_fd_cleanup, ptr);
151 heartbeat_t hb;
152 heartbeat_init(&hb);
153
154 ebpf_module_t *em = (ebpf_module_t *)ptr;
155 usec_t step = NETDATA_FD_SLEEP_MS * em->update_every;
158 - while (!close_ebpf_plugin) {
156 + while (ebpf_fd_exited == NETDATA_THREAD_EBPF_RUNNING) {
157 usec_t dt = heartbeat_next(&hb, step);
158 (void)dt;
159 + if (ebpf_fd_exited == NETDATA_THREAD_EBPF_STOPPING)
160 + break;
161
162 read_global_table();
163 }
164
165 - read_thread_closed = 1;
165 + ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPED;
166 +
167 + netdata_thread_cleanup_pop(1);
168 return NULL;
169 }
170
@@ -652,17 +654,19 @@ static void fd_collector(ebpf_module_t *em)
654 fd_thread.thread = mallocz(sizeof(netdata_thread_t));
655 fd_thread.start_routine = ebpf_fd_read_hash;
656
655 - netdata_thread_create(fd_thread.thread, fd_thread.name, NETDATA_THREAD_OPTION_JOINABLE,
657 + netdata_thread_create(fd_thread.thread, fd_thread.name, NETDATA_THREAD_OPTION_DEFAULT,
658 ebpf_fd_read_hash, em);
659
658 - int apps = em->apps_charts;
660 int cgroups = em->cgroup_charts;
661 heartbeat_t hb;
662 heartbeat_init(&hb);
663 usec_t step = em->update_every * USEC_PER_SEC;
663 - while (!close_ebpf_plugin) {
664 + while (!ebpf_exit_plugin) {
665 (void)heartbeat_next(&hb, step);
666 + if (ebpf_exit_plugin)
667 + break;
668
669 + netdata_apps_integration_flags_t apps = em->apps_charts;
670 pthread_mutex_lock(&collect_data_mutex);
671 if (apps)
672 read_apps_table();
@@ -674,7 +678,7 @@ static void fd_collector(ebpf_module_t *em)
678
679 ebpf_fd_send_data(em);
680
677 - if (apps)
681 + if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
682 ebpf_fd_send_apps_data(em, apps_groups_root_target);
683
684 if (cgroups)
@@ -740,6 +744,8 @@ void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr)
744 ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
745 root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
746 }
747 +
748 + em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
749 }
750
751 /**
@@ -815,7 +821,7 @@ static void ebpf_fd_allocate_global_vectors(int apps)
821 */
822 void *ebpf_fd_thread(void *ptr)
823 {
818 - netdata_thread_cleanup_push(ebpf_fd_cleanup, ptr);
824 + netdata_thread_cleanup_push(ebpf_fd_exit, ptr);
825
826 ebpf_module_t *em = (ebpf_module_t *)ptr;
827 em->maps = fd_maps;
@@ -825,8 +831,8 @@ void *ebpf_fd_thread(void *ptr)
831
832 ebpf_fd_allocate_global_vectors(em->apps_charts);
833
828 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
829 - if (!probe_links) {
834 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
835 + if (!em->probe_links) {
836 em->enabled = CONFIG_BOOLEAN_NO;
837 goto endfd;
838 }
collectors/ebpf.plugin/ebpf_filesystem.c
+39 -73
@@ -30,67 +30,11 @@ static ebpf_local_maps_t fs_maps[] = {{.name = "tbl_ext4", .internal_input = NET
30 .type = NETDATA_EBPF_MAP_CONTROLLER,
31 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
32
33 -ebpf_filesystem_partitions_t localfs[] =
34 - {{.filesystem = "ext4",
35 - .optional_filesystem = NULL,
36 - .family = "ext4",
37 - .objects = NULL,
38 - .probe_links = NULL,
39 - .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
40 - .enabled = CONFIG_BOOLEAN_YES,
41 - .addresses = {.function = NULL, .addr = 0},
42 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
43 - {.filesystem = "xfs",
44 - .optional_filesystem = NULL,
45 - .family = "xfs",
46 - .objects = NULL,
47 - .probe_links = NULL,
48 - .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
49 - .enabled = CONFIG_BOOLEAN_YES,
50 - .addresses = {.function = NULL, .addr = 0},
51 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
52 - {.filesystem = "nfs",
53 - .optional_filesystem = "nfs4",
54 - .family = "nfs",
55 - .objects = NULL,
56 - .probe_links = NULL,
57 - .flags = NETDATA_FILESYSTEM_ATTR_CHARTS,
58 - .enabled = CONFIG_BOOLEAN_YES,
59 - .addresses = {.function = NULL, .addr = 0},
60 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
61 - {.filesystem = "zfs",
62 - .optional_filesystem = NULL,
63 - .family = "zfs",
64 - .objects = NULL,
65 - .probe_links = NULL,
66 - .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
67 - .enabled = CONFIG_BOOLEAN_YES,
68 - .addresses = {.function = NULL, .addr = 0},
69 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
70 - {.filesystem = "btrfs",
71 - .optional_filesystem = NULL,
72 - .family = "btrfs",
73 - .objects = NULL,
74 - .probe_links = NULL,
75 - .flags = NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE,
76 - .enabled = CONFIG_BOOLEAN_YES,
77 - .addresses = {.function = "btrfs_file_operations", .addr = 0},
78 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10},
79 - {.filesystem = NULL,
80 - .optional_filesystem = NULL,
81 - .family = NULL,
82 - .objects = NULL,
83 - .probe_links = NULL,
84 - .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
85 - .enabled = CONFIG_BOOLEAN_YES,
86 - .addresses = {.function = NULL, .addr = 0},
87 - .kernels = 0}};
88 -
33 struct netdata_static_thread filesystem_threads = {"EBPF FS READ",
34 NULL, NULL, 1, NULL,
35 NULL, NULL };
36 +static enum ebpf_threads_status ebpf_fs_exited = NETDATA_THREAD_EBPF_RUNNING;
37
93 -static int read_thread_closed = 1;
38 static netdata_syscall_stat_t filesystem_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
39 static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
40
@@ -381,6 +325,7 @@ void ebpf_filesystem_cleanup_ebpf_data()
325 bpf_link__destroy(probe_links[j]);
326 j++;
327 }
328 + freez(probe_links);
329 if (efp->objects)
330 bpf_object__close(efp->objects);
331 }
@@ -388,24 +333,36 @@ void ebpf_filesystem_cleanup_ebpf_data()
333 }
334
335 /**
391 - * Clean up the main thread.
336 + * Filesystem exit
337 + *
338 + * Cancel child thread.
339 *
340 * @param ptr thread data.
341 */
395 -static void ebpf_filesystem_cleanup(void *ptr)
342 +static void ebpf_filesystem_exit(void *ptr)
343 {
344 ebpf_module_t *em = (ebpf_module_t *)ptr;
398 - if (!em->enabled)
345 + if (!em->enabled) {
346 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
347 return;
400 -
401 - heartbeat_t hb;
402 - heartbeat_init(&hb);
403 - uint32_t tick = 2*USEC_PER_MS;
404 - while (!read_thread_closed) {
405 - usec_t dt = heartbeat_next(&hb, tick);
406 - UNUSED(dt);
348 }
349
350 + ebpf_fs_exited = NETDATA_THREAD_EBPF_STOPPING;
351 +}
352 +
353 +/**
354 + * File system cleanup
355 + *
356 + * Clean up allocated thread.
357 + *
358 + * @param ptr thread data.
359 + */
360 +static void ebpf_filesystem_cleanup(void *ptr)
361 +{
362 + ebpf_module_t *em = (ebpf_module_t *)ptr;
363 + if (ebpf_fs_exited != NETDATA_THREAD_EBPF_STOPPED)
364 + return;
365 +
366 freez(filesystem_threads.thread);
367 ebpf_cleanup_publish_syscall(filesystem_publish_aggregated);
368
@@ -413,6 +370,9 @@ static void ebpf_filesystem_cleanup(void *ptr)
370 if (dimensions)
371 ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
372 freez(filesystem_hash_values);
373 +
374 + filesystem_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
375 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
376 }
377
378 /*****************************************************************
@@ -516,16 +476,18 @@ static void read_filesystem_tables()
476 */
477 void *ebpf_filesystem_read_hash(void *ptr)
478 {
479 + netdata_thread_cleanup_push(ebpf_filesystem_cleanup, ptr);
480 ebpf_module_t *em = (ebpf_module_t *)ptr;
520 - read_thread_closed = 0;
481
482 heartbeat_t hb;
483 heartbeat_init(&hb);
484 usec_t step = NETDATA_FILESYSTEM_READ_SLEEP_MS * em->update_every;
485 int update_every = em->update_every;
526 - while (!close_ebpf_plugin) {
486 + while (ebpf_fs_exited == NETDATA_THREAD_EBPF_RUNNING) {
487 usec_t dt = heartbeat_next(&hb, step);
488 (void)dt;
489 + if (ebpf_fs_exited == NETDATA_THREAD_EBPF_STOPPING)
490 + break;
491
492 (void) ebpf_update_partitions(em);
493 ebpf_obsolete_fs_charts(update_every);
@@ -537,7 +499,9 @@ void *ebpf_filesystem_read_hash(void *ptr)
499 read_filesystem_tables();
500 }
501
540 - read_thread_closed = 1;
502 + ebpf_fs_exited = NETDATA_THREAD_EBPF_STOPPED;
503 +
504 + netdata_thread_cleanup_pop(1);
505 return NULL;
506 }
507
@@ -579,14 +543,16 @@ static void filesystem_collector(ebpf_module_t *em)
543 filesystem_threads.start_routine = ebpf_filesystem_read_hash;
544
545 netdata_thread_create(filesystem_threads.thread, filesystem_threads.name,
582 - NETDATA_THREAD_OPTION_JOINABLE, ebpf_filesystem_read_hash, em);
546 + NETDATA_THREAD_OPTION_DEFAULT, ebpf_filesystem_read_hash, em);
547
548 int update_every = em->update_every;
549 heartbeat_t hb;
550 heartbeat_init(&hb);
551 usec_t step = update_every * USEC_PER_SEC;
588 - while (!close_ebpf_plugin || em->optional) {
552 + while (!ebpf_exit_plugin) {
553 (void)heartbeat_next(&hb, step);
554 + if (ebpf_exit_plugin)
555 + break;
556
557 pthread_mutex_lock(&lock);
558
@@ -631,7 +597,7 @@ static void ebpf_update_filesystem()
597 */
598 void *ebpf_filesystem_thread(void *ptr)
599 {
634 - netdata_thread_cleanup_push(ebpf_filesystem_cleanup, ptr);
600 + netdata_thread_cleanup_push(ebpf_filesystem_exit, ptr);
601
602 ebpf_module_t *em = (ebpf_module_t *)ptr;
603 em->maps = fs_maps;
collectors/ebpf.plugin/ebpf_filesystem.h
-20
@@ -43,26 +43,6 @@ enum netdata_filesystem_table {
43 NETDATA_ADDR_FS_TABLE
44 };
45
46 -typedef struct ebpf_filesystem_partitions {
47 - char *filesystem;
48 - char *optional_filesystem;
49 - char *family;
50 - char *family_name;
51 - struct bpf_object *objects;
52 - struct bpf_link **probe_links;
53 -
54 - netdata_ebpf_histogram_t hread;
55 - netdata_ebpf_histogram_t hwrite;
56 - netdata_ebpf_histogram_t hopen;
57 - netdata_ebpf_histogram_t hadditional;
58 -
59 - uint32_t flags;
60 - uint32_t enabled;
61 -
62 - ebpf_addresses_t addresses;
63 - uint64_t kernels;
64 -} ebpf_filesystem_partitions_t;
65 -
46 extern void *ebpf_filesystem_thread(void *ptr);
47 extern struct config fs_config;
48
collectors/ebpf.plugin/ebpf_hardirq.c
+42 -38
@@ -125,11 +125,6 @@ static hardirq_static_val_t hardirq_static_vals[] = {
125 },
126 };
127
128 -static struct bpf_link **probe_links = NULL;
129 -static struct bpf_object *objects = NULL;
130 -
131 -static int read_thread_closed = 1;
132 -
128 // store for "published" data from the reader thread, which the collector
129 // thread will write to netdata agent.
130 static avl_tree_lock hardirq_pub;
@@ -143,45 +138,49 @@ static hardirq_ebpf_static_val_t *hardirq_ebpf_static_vals = NULL;
138 static struct netdata_static_thread hardirq_threads = {"HARDIRQ KERNEL",
139 NULL, NULL, 1, NULL,
140 NULL, NULL };
141 +static enum ebpf_threads_status ebpf_hardirq_exited = NETDATA_THREAD_EBPF_RUNNING;
142
143 /**
148 - * Clean up the main thread.
144 + * Hardirq Exit
145 + *
146 + * Cancel child and exit.
147 *
148 * @param ptr thread data.
149 */
152 -static void hardirq_cleanup(void *ptr)
150 +static void hardirq_exit(void *ptr)
151 {
154 - for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) {
155 - ebpf_disable_tracepoint(&hardirq_tracepoints[i]);
156 - }
157 -
152 ebpf_module_t *em = (ebpf_module_t *)ptr;
153 if (!em->enabled) {
154 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
155 return;
156 }
157
163 - heartbeat_t hb;
164 - heartbeat_init(&hb);
165 - uint32_t tick = 1 * USEC_PER_MS;
166 - while (!read_thread_closed) {
167 - usec_t dt = heartbeat_next(&hb, tick);
168 - UNUSED(dt);
169 - }
158 + ebpf_hardirq_exited = NETDATA_THREAD_EBPF_STOPPING;
159 +}
160
161 +/**
162 + * Hardirq clean up
163 + *
164 + * Clean up allocated memory.
165 + *
166 + * @param ptr thread data.
167 + */
168 +static void hardirq_cleanup(void *ptr)
169 +{
170 + ebpf_module_t *em = (ebpf_module_t *)ptr;
171 +
172 + if (ebpf_hardirq_exited != NETDATA_THREAD_EBPF_STOPPED)
173 + return;
174 +
175 + freez(hardirq_threads.thread);
176 + for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) {
177 + ebpf_disable_tracepoint(&hardirq_tracepoints[i]);
178 + }
179 freez(hardirq_ebpf_vals);
180 freez(hardirq_ebpf_static_vals);
173 - freez(hardirq_threads.thread);
181
175 - if (probe_links) {
176 - struct bpf_program *prog;
177 - size_t i = 0 ;
178 - bpf_object__for_each_program(prog, objects) {
179 - bpf_link__destroy(probe_links[i]);
180 - i++;
181 - }
182 - if (objects)
183 - bpf_object__close(objects);
184 - }
182 + hardirq_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
183 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
184 }
185
186 /*****************************************************************
@@ -317,23 +316,25 @@ static void hardirq_read_latency_static_map(int mapfd)
316 */
317 static void *hardirq_reader(void *ptr)
318 {
320 - read_thread_closed = 0;
321 -
319 + netdata_thread_cleanup_push(hardirq_cleanup, ptr);
320 heartbeat_t hb;
321 heartbeat_init(&hb);
322
323 ebpf_module_t *em = (ebpf_module_t *)ptr;
324
325 usec_t step = NETDATA_HARDIRQ_SLEEP_MS * em->update_every;
328 - while (!close_ebpf_plugin) {
326 + while (ebpf_hardirq_exited == NETDATA_THREAD_EBPF_RUNNING) {
327 usec_t dt = heartbeat_next(&hb, step);
328 UNUSED(dt);
329 + if (ebpf_hardirq_exited == NETDATA_THREAD_EBPF_STOPPING)
330 + break;
331
332 hardirq_read_latency_map(hardirq_maps[HARDIRQ_MAP_LATENCY].map_fd);
333 hardirq_read_latency_static_map(hardirq_maps[HARDIRQ_MAP_LATENCY_STATIC].map_fd);
334 }
335 + ebpf_hardirq_exited = NETDATA_THREAD_EBPF_STOPPED;
336
336 - read_thread_closed = 1;
337 + netdata_thread_cleanup_pop(1);
338 return NULL;
339 }
340
@@ -420,7 +421,7 @@ static void hardirq_collector(ebpf_module_t *em)
421 netdata_thread_create(
422 hardirq_threads.thread,
423 hardirq_threads.name,
423 - NETDATA_THREAD_OPTION_JOINABLE,
424 + NETDATA_THREAD_OPTION_DEFAULT,
425 hardirq_reader,
426 em
427 );
@@ -436,8 +437,11 @@ static void hardirq_collector(ebpf_module_t *em)
437 heartbeat_t hb;
438 heartbeat_init(&hb);
439 usec_t step = em->update_every * USEC_PER_SEC;
439 - while (!close_ebpf_plugin) {
440 + //This will be cancelled by its parent
441 + while (!ebpf_exit_plugin) {
442 (void)heartbeat_next(&hb, step);
443 + if (ebpf_exit_plugin)
444 + break;
445
446 pthread_mutex_lock(&lock);
447
@@ -463,7 +467,7 @@ static void hardirq_collector(ebpf_module_t *em)
467 */
468 void *ebpf_hardirq_thread(void *ptr)
469 {
466 - netdata_thread_cleanup_push(hardirq_cleanup, ptr);
470 + netdata_thread_cleanup_push(hardirq_exit, ptr);
471
472 ebpf_module_t *em = (ebpf_module_t *)ptr;
473 em->maps = hardirq_maps;
@@ -477,8 +481,8 @@ void *ebpf_hardirq_thread(void *ptr)
481 goto endhardirq;
482 }
483
480 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
481 - if (!probe_links) {
484 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
485 + if (!em->probe_links) {
486 em->enabled = CONFIG_BOOLEAN_NO;
487 goto endhardirq;
488 }
collectors/ebpf.plugin/ebpf_mdflush.c
+37 -33
@@ -35,48 +35,47 @@ static avl_tree_lock mdflush_pub;
35 // tmp store for mdflush values we get from a per-CPU eBPF map.
36 static mdflush_ebpf_val_t *mdflush_ebpf_vals = NULL;
37
38 -static struct bpf_link **probe_links = NULL;
39 -static struct bpf_object *objects = NULL;
40 -
41 -static int read_thread_closed = 1;
42 -
38 static struct netdata_static_thread mdflush_threads = {"MDFLUSH KERNEL",
39 NULL, NULL, 1, NULL,
40 NULL, NULL };
41 +static enum ebpf_threads_status ebpf_mdflush_exited = NETDATA_THREAD_EBPF_RUNNING;
42
43 /**
48 - * Clean up the main thread.
44 + * MDflush exit
45 + *
46 + * Cancel thread and exit.
47 *
48 * @param ptr thread data.
49 */
52 -static void mdflush_cleanup(void *ptr)
50 +static void mdflush_exit(void *ptr)
51 {
52 ebpf_module_t *em = (ebpf_module_t *)ptr;
53 if (!em->enabled) {
54 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
55 return;
56 }
57
59 - heartbeat_t hb;
60 - heartbeat_init(&hb);
61 - uint32_t tick = 1 * USEC_PER_MS;
62 - while (!read_thread_closed) {
63 - usec_t dt = heartbeat_next(&hb, tick);
64 - UNUSED(dt);
65 - }
58 + ebpf_mdflush_exited = NETDATA_THREAD_EBPF_STOPPING;
59 +}
60 +
61 +/**
62 + * CLeanup
63 + *
64 + * Clean allocated memory.
65 + *
66 + * @param ptr thread data.
67 + */
68 +static void mdflush_cleanup(void *ptr)
69 +{
70 + ebpf_module_t *em = (ebpf_module_t *)ptr;
71 + if (ebpf_mdflush_exited != NETDATA_THREAD_EBPF_STOPPED)
72 + return;
73
74 freez(mdflush_ebpf_vals);
75 freez(mdflush_threads.thread);
76
70 - if (probe_links) {
71 - struct bpf_program *prog;
72 - size_t i = 0 ;
73 - bpf_object__for_each_program(prog, objects) {
74 - bpf_link__destroy(probe_links[i]);
75 - i++;
76 - }
77 - if (objects)
78 - bpf_object__close(objects);
79 - }
77 + mdflush_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
78 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
79 }
80
81 /**
@@ -176,22 +175,25 @@ static void mdflush_read_count_map()
175 */
176 static void *mdflush_reader(void *ptr)
177 {
179 - read_thread_closed = 0;
180 -
178 + netdata_thread_cleanup_push(mdflush_cleanup, ptr);
179 heartbeat_t hb;
180 heartbeat_init(&hb);
181
182 ebpf_module_t *em = (ebpf_module_t *)ptr;
183
184 usec_t step = NETDATA_MDFLUSH_SLEEP_MS * em->update_every;
187 - while (!close_ebpf_plugin) {
185 + while (ebpf_mdflush_exited == NETDATA_THREAD_EBPF_RUNNING) {
186 usec_t dt = heartbeat_next(&hb, step);
187 UNUSED(dt);
188 + if (ebpf_mdflush_exited == NETDATA_THREAD_EBPF_STOPPING)
189 + break;
190
191 mdflush_read_count_map();
192 }
193
194 - read_thread_closed = 1;
194 + ebpf_mdflush_exited = NETDATA_THREAD_EBPF_STOPPED;
195 +
196 + netdata_thread_cleanup_pop(1);
197 return NULL;
198 }
199
@@ -249,7 +251,7 @@ static void mdflush_collector(ebpf_module_t *em)
251 netdata_thread_create(
252 mdflush_threads.thread,
253 mdflush_threads.name,
252 - NETDATA_THREAD_OPTION_JOINABLE,
254 + NETDATA_THREAD_OPTION_DEFAULT,
255 mdflush_reader,
256 em
257 );
@@ -264,8 +266,10 @@ static void mdflush_collector(ebpf_module_t *em)
266 heartbeat_t hb;
267 heartbeat_init(&hb);
268 usec_t step = em->update_every * USEC_PER_SEC;
267 - while (!close_ebpf_plugin) {
269 + while (!ebpf_exit_plugin) {
270 (void)heartbeat_next(&hb, step);
271 + if (ebpf_exit_plugin)
272 + break;
273
274 // write dims now for all hitherto discovered devices.
275 write_begin_chart("mdstat", "mdstat_flush");
@@ -284,7 +288,7 @@ static void mdflush_collector(ebpf_module_t *em)
288 */
289 void *ebpf_mdflush_thread(void *ptr)
290 {
287 - netdata_thread_cleanup_push(mdflush_cleanup, ptr);
291 + netdata_thread_cleanup_push(mdflush_exit, ptr);
292
293 ebpf_module_t *em = (ebpf_module_t *)ptr;
294 em->maps = mdflush_maps;
@@ -300,8 +304,8 @@ void *ebpf_mdflush_thread(void *ptr)
304 goto endmdflush;
305 }
306
303 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
304 - if (!probe_links) {
307 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
308 + if (!em->probe_links) {
309 em->enabled = CONFIG_BOOLEAN_NO;
310 goto endmdflush;
311 }
collectors/ebpf.plugin/ebpf_mount.c
+41 -26
@@ -18,12 +18,8 @@ struct config mount_config = { .first_section = NULL, .last_section = NULL, .mut
18 .index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare },
19 .rwlock = AVL_LOCK_INITIALIZER } };
20
21 -static int read_thread_closed = 1;
21 static netdata_idx_t *mount_values = NULL;
22
24 -static struct bpf_link **probe_links = NULL;
25 -static struct bpf_object *objects = NULL;
26 -
23 static netdata_idx_t mount_hash_values[NETDATA_MOUNT_END];
24
25 struct netdata_static_thread mount_thread = {"MOUNT KERNEL",
@@ -33,6 +29,7 @@ struct netdata_static_thread mount_thread = {"MOUNT KERNEL",
29 netdata_ebpf_targets_t mount_targets[] = { {.name = "mount", .mode = EBPF_LOAD_TRAMPOLINE},
30 {.name = "umount", .mode = EBPF_LOAD_TRAMPOLINE},
31 {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
32 +static enum ebpf_threads_status ebpf_mount_exited = NETDATA_THREAD_EBPF_RUNNING;
33
34 #ifdef LIBBPF_MAJOR_VERSION
35 #include "includes/mount.skel.h" // BTF code
@@ -227,34 +224,46 @@ static inline int ebpf_mount_load_and_attach(struct mount_bpf *obj, ebpf_module_
224 *****************************************************************/
225
226 /**
230 - * Clean up the main thread.
227 + * Mount Exit
228 + *
229 + * Cancel child thread.
230 + *
231 + * @param ptr thread data.
232 + */
233 +static void ebpf_mount_exit(void *ptr)
234 +{
235 + ebpf_module_t *em = (ebpf_module_t *)ptr;
236 + if (!em->enabled) {
237 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
238 + return;
239 + }
240 +
241 + ebpf_mount_exited = NETDATA_THREAD_EBPF_STOPPING;
242 +}
243 +
244 +/**
245 + * Mount cleanup
246 + *
247 + * Clean up allocated memory.
248 *
249 * @param ptr thread data.
250 */
251 static void ebpf_mount_cleanup(void *ptr)
252 {
253 ebpf_module_t *em = (ebpf_module_t *)ptr;
237 - if (!em->enabled)
254 + if (ebpf_mount_exited != NETDATA_THREAD_EBPF_STOPPED)
255 return;
256
257 freez(mount_thread.thread);
258 freez(mount_values);
259
243 - if (probe_links) {
244 - struct bpf_program *prog;
245 - size_t i = 0 ;
246 - bpf_object__for_each_program(prog, objects) {
247 - bpf_link__destroy(probe_links[i]);
248 - i++;
249 - }
250 - if (objects)
251 - bpf_object__close(objects);
252 - }
260 #ifdef LIBBPF_MAJOR_VERSION
254 - else if (bpf_obj)
261 + if (bpf_obj)
262 mount_bpf__destroy(bpf_obj);
263 #endif
264
265 + mount_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
266 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
267 }
268
269 /*****************************************************************
@@ -300,22 +309,26 @@ static void read_global_table()
309 */
310 void *ebpf_mount_read_hash(void *ptr)
311 {
303 - read_thread_closed = 0;
304 -
312 + netdata_thread_cleanup_push(ebpf_mount_cleanup, ptr);
313 heartbeat_t hb;
314 heartbeat_init(&hb);
315
316 ebpf_module_t *em = (ebpf_module_t *)ptr;
317
318 usec_t step = NETDATA_LATENCY_MOUNT_SLEEP_MS * em->update_every;
311 - while (!close_ebpf_plugin) {
319 + //This will be cancelled by its parent
320 + while (ebpf_mount_exited == NETDATA_THREAD_EBPF_RUNNING) {
321 usec_t dt = heartbeat_next(&hb, step);
322 (void)dt;
323 + if (ebpf_mount_exited == NETDATA_THREAD_EBPF_STOPPING)
324 + break;
325
326 read_global_table();
327 }
317 - read_thread_closed = 1;
328
329 + ebpf_mount_exited = NETDATA_THREAD_EBPF_STOPPED;
330 +
331 + netdata_thread_cleanup_pop(1);
332 return NULL;
333 }
334
@@ -349,14 +362,16 @@ static void mount_collector(ebpf_module_t *em)
362
363 mount_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
364
352 - netdata_thread_create(mount_thread.thread, mount_thread.name, NETDATA_THREAD_OPTION_JOINABLE,
365 + netdata_thread_create(mount_thread.thread, mount_thread.name, NETDATA_THREAD_OPTION_DEFAULT,
366 ebpf_mount_read_hash, em);
367
368 heartbeat_t hb;
369 heartbeat_init(&hb);
370 usec_t step = em->update_every * USEC_PER_SEC;
358 - while (!close_ebpf_plugin) {
371 + while (!ebpf_exit_plugin) {
372 (void)heartbeat_next(&hb, step);
373 + if (ebpf_exit_plugin)
374 + break;
375
376 pthread_mutex_lock(&lock);
377
@@ -421,8 +436,8 @@ static int ebpf_mount_load_bpf(ebpf_module_t *em)
436 {
437 int ret = 0;
438 if (em->load == EBPF_LOAD_LEGACY) {
424 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
425 - if (!probe_links) {
439 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
440 + if (!em->probe_links) {
441 em->enabled = CONFIG_BOOLEAN_NO;
442 ret = -1;
443 }
@@ -454,7 +469,7 @@ static int ebpf_mount_load_bpf(ebpf_module_t *em)
469 */
470 void *ebpf_mount_thread(void *ptr)
471 {
457 - netdata_thread_cleanup_push(ebpf_mount_cleanup, ptr);
472 + netdata_thread_cleanup_push(ebpf_mount_exit, ptr);
473
474 ebpf_module_t *em = (ebpf_module_t *)ptr;
475 em->maps = mount_maps;
collectors/ebpf.plugin/ebpf_oomkill.c
+13 -22
@@ -34,9 +34,6 @@ static ebpf_tracepoint_t oomkill_tracepoints[] = {
34 {.enabled = false, .class = NULL, .event = NULL}
35 };
36
37 -static struct bpf_link **probe_links = NULL;
38 -static struct bpf_object *objects = NULL;
39 -
37 static netdata_publish_syscall_t oomkill_publish_aggregated = {.name = "oomkill", .dimension = "oomkill",
38 .algorithm = "absolute",
39 .next = NULL};
@@ -49,20 +46,8 @@ static netdata_publish_syscall_t oomkill_publish_aggregated = {.name = "oomkill"
46 static void oomkill_cleanup(void *ptr)
47 {
48 ebpf_module_t *em = (ebpf_module_t *)ptr;
52 - if (!em->enabled) {
53 - return;
54 - }
49
56 - if (probe_links) {
57 - struct bpf_program *prog;
58 - size_t i = 0 ;
59 - bpf_object__for_each_program(prog, objects) {
60 - bpf_link__destroy(probe_links[i]);
61 - i++;
62 - }
63 - if (objects)
64 - bpf_object__close(objects);
65 - }
50 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
51 }
52
53 static void oomkill_write_data(int32_t *keys, uint32_t total)
@@ -320,8 +305,10 @@ static void oomkill_collector(ebpf_module_t *em)
305 heartbeat_t hb;
306 heartbeat_init(&hb);
307 usec_t step = update_every * USEC_PER_SEC;
323 - while (!close_ebpf_plugin) {
308 + while (!ebpf_exit_plugin) {
309 (void)heartbeat_next(&hb, step);
310 + if (ebpf_exit_plugin)
311 + break;
312
313 pthread_mutex_lock(&collect_data_mutex);
314 pthread_mutex_lock(&lock);
@@ -334,9 +321,11 @@ static void oomkill_collector(ebpf_module_t *em)
321 if (cgroups)
322 ebpf_oomkill_send_cgroup_data(update_every);
323
337 - write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_OOMKILL_CHART);
338 - oomkill_write_data(keys, count);
339 - write_end_chart();
324 + if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
325 + write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_OOMKILL_CHART);
326 + oomkill_write_data(keys, count);
327 + write_end_chart();
328 + }
329
330 pthread_mutex_unlock(&lock);
331 pthread_mutex_unlock(&collect_data_mutex);
@@ -361,6 +350,8 @@ void ebpf_oomkill_create_apps_charts(struct ebpf_module *em, void *ptr)
350 20020,
351 ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
352 root, em->update_every, NETDATA_EBPF_MODULE_NAME_OOMKILL);
353 +
354 + em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
355 }
356
357 /**
@@ -394,8 +385,8 @@ void *ebpf_oomkill_thread(void *ptr)
385 goto endoomkill;
386 }
387
397 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
398 - if (!probe_links) {
388 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
389 + if (!em->probe_links) {
390 em->enabled = CONFIG_BOOLEAN_NO;
391 goto endoomkill;
392 }
collectors/ebpf.plugin/ebpf_process.c
+98 -91
@@ -47,9 +47,6 @@ ebpf_process_publish_apps_t **current_apps_data = NULL;
47
48 int process_enabled = 0;
49
50 -static struct bpf_object *objects = NULL;
51 -static struct bpf_link **probe_links = NULL;
52 -
50 struct config process_config = { .first_section = NULL,
51 .last_section = NULL,
52 .mutex = NETDATA_MUTEX_INITIALIZER,
@@ -58,6 +55,7 @@ struct config process_config = { .first_section = NULL,
55
56 static struct netdata_static_thread cgroup_thread = {"EBPF CGROUP", NULL, NULL,
57 1, NULL, NULL, NULL};
58 +static enum ebpf_threads_status ebpf_process_exited = NETDATA_THREAD_EBPF_RUNNING;
59
60 static char *threads_stat[NETDATA_EBPF_THREAD_STAT_END] = {"total", "running"};
61 static char *load_event_stat[NETDATA_EBPF_LOAD_STAT_END] = {"legacy", "co-re"};
@@ -177,11 +175,9 @@ void ebpf_process_remove_pids()
175 uint32_t pid = pids->pid;
176 ebpf_process_stat_t *w = global_process_stats[pid];
177 if (w) {
180 - if (w->removeme) {
181 - freez(w);
182 - global_process_stats[pid] = NULL;
183 - bpf_map_delete_elem(pid_fd, &pid);
184 - }
178 + freez(w);
179 + global_process_stats[pid] = NULL;
180 + bpf_map_delete_elem(pid_fd, &pid);
181 }
182
183 pids = pids->next;
@@ -568,6 +564,8 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
564 root,
565 em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
566 }
567 +
568 + em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
569 }
570
571 /**
@@ -622,6 +620,72 @@ static void ebpf_create_apps_charts(struct target *root)
620 }
621 }
622
623 +/*****************************************************************
624 + *
625 + * FUNCTIONS TO CLOSE THE THREAD
626 + *
627 + *****************************************************************/
628 +
629 +/**
630 + * Process disable tracepoints
631 + *
632 + * Disable tracepoints when the plugin was responsible to enable it.
633 + */
634 +static void ebpf_process_disable_tracepoints()
635 +{
636 + char *default_message = { "Cannot disable the tracepoint" };
637 + if (!was_sched_process_exit_enabled) {
638 + if (ebpf_disable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_exit))
639 + error("%s %s/%s.", default_message, tracepoint_sched_type, tracepoint_sched_process_exit);
640 + }
641 +
642 + if (!was_sched_process_exec_enabled) {
643 + if (ebpf_disable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_exec))
644 + error("%s %s/%s.", default_message, tracepoint_sched_type, tracepoint_sched_process_exec);
645 + }
646 +
647 + if (!was_sched_process_fork_enabled) {
648 + if (ebpf_disable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_fork))
649 + error("%s %s/%s.", default_message, tracepoint_sched_type, tracepoint_sched_process_fork);
650 + }
651 +}
652 +
653 +/**
654 + * Process Exit
655 + *
656 + * Cancel child thread.
657 + *
658 + * @param ptr thread data.
659 + */
660 +static void ebpf_process_exit(void *ptr)
661 +{
662 + (void)ptr;
663 + ebpf_process_exited = NETDATA_THREAD_EBPF_STOPPING;
664 +}
665 +
666 +/**
667 + * Process cleanup
668 + *
669 + * Cleanup allocated memory.
670 + *
671 + * @param ptr thread data.
672 + */
673 +static void ebpf_process_cleanup(void *ptr)
674 +{
675 + ebpf_module_t *em = (ebpf_module_t *)ptr;
676 + if (ebpf_process_exited != NETDATA_THREAD_EBPF_STOPPED)
677 + return;
678 +
679 + ebpf_cleanup_publish_syscall(process_publish_aggregated);
680 + freez(process_hash_values);
681 + freez(cgroup_thread.thread);
682 +
683 + ebpf_process_disable_tracepoints();
684 +
685 + cgroup_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
686 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
687 +}
688 +
689 /*****************************************************************
690 *
691 * FUNCTIONS WITH THE MAIN LOOP
@@ -640,24 +704,33 @@ static void ebpf_create_apps_charts(struct target *root)
704 */
705 void *ebpf_cgroup_update_shm(void *ptr)
706 {
643 - UNUSED(ptr);
707 + netdata_thread_cleanup_push(ebpf_process_cleanup, ptr);
708 heartbeat_t hb;
709 heartbeat_init(&hb);
710
647 - usec_t step = 30 * USEC_PER_SEC;
648 - while (!close_ebpf_plugin) {
711 + usec_t step = 3 * USEC_PER_SEC;
712 + int counter = NETDATA_EBPF_CGROUP_UPDATE - 1;
713 + //This will be cancelled by its parent
714 + while (ebpf_process_exited == NETDATA_THREAD_EBPF_RUNNING) {
715 usec_t dt = heartbeat_next(&hb, step);
716 (void)dt;
651 -
652 - if (close_ebpf_plugin)
717 + if (ebpf_process_exited == NETDATA_THREAD_EBPF_STOPPING)
718 break;
719
655 - if (!shm_ebpf_cgroup.header)
656 - ebpf_map_cgroup_shared_memory();
720 + // We are using a small heartbeat time to wake up thread,
721 + // but we should not update so frequently the shared memory data
722 + if (++counter >= NETDATA_EBPF_CGROUP_UPDATE) {
723 + counter = 0;
724 + if (!shm_ebpf_cgroup.header)
725 + ebpf_map_cgroup_shared_memory();
726
658 - ebpf_parse_cgroup_shm_data();
727 + ebpf_parse_cgroup_shm_data();
728 + }
729 }
730
731 + ebpf_process_exited = NETDATA_THREAD_EBPF_STOPPED;
732 +
733 + netdata_thread_cleanup_pop(1);
734 return NULL;
735 }
736
@@ -1019,13 +1092,12 @@ static void process_collector(ebpf_module_t *em)
1092 cgroup_thread.thread = mallocz(sizeof(netdata_thread_t));
1093 cgroup_thread.start_routine = ebpf_cgroup_update_shm;
1094
1022 - netdata_thread_create(cgroup_thread.thread, cgroup_thread.name, NETDATA_THREAD_OPTION_JOINABLE,
1095 + netdata_thread_create(cgroup_thread.thread, cgroup_thread.name, NETDATA_THREAD_OPTION_DEFAULT,
1096 ebpf_cgroup_update_shm, em);
1097
1098 heartbeat_t hb;
1099 heartbeat_init(&hb);
1100 int publish_global = em->global_charts;
1028 - int apps_enabled = em->apps_charts;
1101 int cgroups = em->cgroup_charts;
1102 int thread_enabled = em->enabled;
1103 if (cgroups)
@@ -1036,9 +1108,11 @@ static void process_collector(ebpf_module_t *em)
1108 int update_every = em->update_every;
1109 int counter = update_every - 1;
1110 int update_apps_list = update_apps_every - 1;
1039 - while (!close_ebpf_plugin) {
1111 + while (!ebpf_exit_plugin) {
1112 usec_t dt = heartbeat_next(&hb, USEC_PER_SEC);
1113 (void)dt;
1114 + if (ebpf_exit_plugin)
1115 + break;
1116
1117 pthread_mutex_lock(&collect_data_mutex);
1118 if (++update_apps_list == update_apps_every) {
@@ -1055,11 +1129,10 @@ static void process_collector(ebpf_module_t *em)
1129
1130 read_hash_global_tables();
1131
1058 - int publish_apps = 0;
1132 + netdata_apps_integration_flags_t apps_enabled = em->apps_charts;
1133 pthread_mutex_lock(&collect_data_mutex);
1134 if (all_pids_count > 0) {
1135 if (apps_enabled) {
1062 - publish_apps = 1;
1136 ebpf_process_update_apps_data();
1137 }
1138
@@ -1076,7 +1149,7 @@ static void process_collector(ebpf_module_t *em)
1149 ebpf_process_send_data(em);
1150 }
1151
1079 - if (publish_apps) {
1152 + if (apps_enabled & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
1153 ebpf_process_send_apps_data(apps_groups_root_target, em);
1154 }
1155
@@ -1092,72 +1165,6 @@ static void process_collector(ebpf_module_t *em)
1165 }
1166 }
1167
1095 -/*****************************************************************
1096 - *
1097 - * FUNCTIONS TO CLOSE THE THREAD
1098 - *
1099 - *****************************************************************/
1100 -
1101 -/**
1102 - * Process disable tracepoints
1103 - *
1104 - * Disable tracepoints when the plugin was responsible to enable it.
1105 - */
1106 -static void ebpf_process_disable_tracepoints()
1107 -{
1108 - char *default_message = { "Cannot disable the tracepoint" };
1109 - if (!was_sched_process_exit_enabled) {
1110 - if (ebpf_disable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_exit))
1111 - error("%s %s/%s.", default_message, tracepoint_sched_type, tracepoint_sched_process_exit);
1112 - }
1113 -
1114 - if (!was_sched_process_exec_enabled) {
1115 - if (ebpf_disable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_exec))
1116 - error("%s %s/%s.", default_message, tracepoint_sched_type, tracepoint_sched_process_exec);
1117 - }
1118 -
1119 - if (!was_sched_process_fork_enabled) {
1120 - if (ebpf_disable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_fork))
1121 - error("%s %s/%s.", default_message, tracepoint_sched_type, tracepoint_sched_process_fork);
1122 - }
1123 -}
1124 -
1125 -/**
1126 - * Clean up the main thread.
1127 - *
1128 - * @param ptr thread data.
1129 - */
1130 -static void ebpf_process_cleanup(void *ptr)
1131 -{
1132 - UNUSED(ptr);
1133 -
1134 - heartbeat_t hb;
1135 - heartbeat_init(&hb);
1136 - uint32_t tick = 1 * USEC_PER_SEC;
1137 - while (!finalized_threads) {
1138 - usec_t dt = heartbeat_next(&hb, tick);
1139 - UNUSED(dt);
1140 - }
1141 -
1142 - ebpf_cleanup_publish_syscall(process_publish_aggregated);
1143 - freez(process_hash_values);
1144 -
1145 - ebpf_process_disable_tracepoints();
1146 -
1147 - if (probe_links) {
1148 - struct bpf_program *prog;
1149 - size_t i = 0 ;
1150 - bpf_object__for_each_program(prog, objects) {
1151 - bpf_link__destroy(probe_links[i]);
1152 - i++;
1153 - }
1154 - if (objects)
1155 - bpf_object__close(objects);
1156 - }
1157 -
1158 - freez(cgroup_thread.thread);
1159 -}
1160 -
1168 /*****************************************************************
1169 *
1170 * FUNCTIONS TO START THREAD
@@ -1281,7 +1288,7 @@ static int ebpf_process_enable_tracepoints()
1288 */
1289 void *ebpf_process_thread(void *ptr)
1290 {
1284 - netdata_thread_cleanup_push(ebpf_process_cleanup, ptr);
1291 + netdata_thread_cleanup_push(ebpf_process_exit, ptr);
1292
1293 ebpf_module_t *em = (ebpf_module_t *)ptr;
1294 em->maps = process_maps;
@@ -1297,8 +1304,8 @@ void *ebpf_process_thread(void *ptr)
1304 ebpf_update_pid_table(&process_maps[0], em);
1305
1306 set_local_pointers();
1300 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
1301 - if (!probe_links) {
1307 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1308 + if (!em->probe_links) {
1309 em->enabled = CONFIG_BOOLEAN_NO;
1310 pthread_mutex_unlock(&lock);
1311 goto endprocess;
collectors/ebpf.plugin/ebpf_process.h
+2
@@ -39,6 +39,8 @@
39 #define NETDATA_SYSTEMD_PROCESS_EXIT_CONTEXT "services.task_exit"
40 #define NETDATA_SYSTEMD_PROCESS_ERROR_CONTEXT "services.task_error"
41
42 +#define NETDATA_EBPF_CGROUP_UPDATE 10
43 +
44 // Statistical information
45 enum netdata_ebpf_thread_stats{
46 NETDATA_EBPF_THREAD_STAT_TOTAL,
collectors/ebpf.plugin/ebpf_shm.c
+43 -35
@@ -7,7 +7,6 @@ static char *shm_dimension_name[NETDATA_SHM_END] = { "get", "at", "dt", "ctl" };
7 static netdata_syscall_stat_t shm_aggregated_data[NETDATA_SHM_END];
8 static netdata_publish_syscall_t shm_publish_aggregated[NETDATA_SHM_END];
9
10 -static int read_thread_closed = 1;
10 netdata_publish_shm_t *shm_vector = NULL;
11
12 static netdata_idx_t shm_hash_values[NETDATA_SHM_END];
@@ -35,11 +34,9 @@ static ebpf_local_maps_t shm_maps[] = {{.name = "tbl_pid_shm", .internal_input =
34 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
35 {.name = NULL, .internal_input = 0, .user_input = 0}};
36
38 -static struct bpf_link **probe_links = NULL;
39 -static struct bpf_object *objects = NULL;
40 -
37 struct netdata_static_thread shm_threads = {"SHM KERNEL", NULL, NULL, 1,
38 NULL, NULL, NULL};
39 +static enum ebpf_threads_status ebpf_shm_exited = NETDATA_THREAD_EBPF_RUNNING;
40
41 netdata_ebpf_targets_t shm_targets[] = { {.name = "shmget", .mode = EBPF_LOAD_TRAMPOLINE},
42 {.name = "shmat", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -243,44 +240,48 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e
240 *****************************************************************/
241
242 /**
246 - * Clean up the main thread.
243 + * SHM Exit
244 + *
245 + * Cancel child thread.
246 *
247 * @param ptr thread data.
248 */
250 -static void ebpf_shm_cleanup(void *ptr)
249 +static void ebpf_shm_exit(void *ptr)
250 {
251 ebpf_module_t *em = (ebpf_module_t *)ptr;
252 if (!em->enabled) {
253 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
254 return;
255 }
256
257 - heartbeat_t hb;
258 - heartbeat_init(&hb);
259 - uint32_t tick = 2 * USEC_PER_MS;
260 - while (!read_thread_closed) {
261 - usec_t dt = heartbeat_next(&hb, tick);
262 - UNUSED(dt);
263 - }
257 + ebpf_shm_exited = NETDATA_THREAD_EBPF_STOPPING;
258 +}
259 +
260 +/**
261 + * SHM Cleanup
262 + *
263 + * Clean up allocated memory.
264 + *
265 + * @param ptr thread data.
266 + */
267 +static void ebpf_shm_cleanup(void *ptr)
268 +{
269 + ebpf_module_t *em = (ebpf_module_t *)ptr;
270 + if (ebpf_shm_exited != NETDATA_THREAD_EBPF_STOPPED)
271 + return;
272
273 ebpf_cleanup_publish_syscall(shm_publish_aggregated);
274
275 freez(shm_vector);
276 freez(shm_values);
277
270 - if (probe_links) {
271 - struct bpf_program *prog;
272 - size_t i = 0 ;
273 - bpf_object__for_each_program(prog, objects) {
274 - bpf_link__destroy(probe_links[i]);
275 - i++;
276 - }
277 - if (objects)
278 - bpf_object__close(objects);
279 - }
278 #ifdef LIBBPF_MAJOR_VERSION
281 - else if (bpf_obj)
279 + if (bpf_obj)
280 shm_bpf__destroy(bpf_obj);
281 #endif
282 +
283 + shm_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
284 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
285 }
286
287 /*****************************************************************
@@ -456,21 +457,24 @@ static void read_global_table()
457 */
458 void *ebpf_shm_read_hash(void *ptr)
459 {
459 - read_thread_closed = 0;
460 -
460 + netdata_thread_cleanup_push(ebpf_shm_cleanup, ptr);
461 heartbeat_t hb;
462 heartbeat_init(&hb);
463
464 ebpf_module_t *em = (ebpf_module_t *)ptr;
465 usec_t step = NETDATA_SHM_SLEEP_MS * em->update_every;
466 - while (!close_ebpf_plugin) {
466 + while (ebpf_shm_exited == NETDATA_THREAD_EBPF_RUNNING) {
467 usec_t dt = heartbeat_next(&hb, step);
468 (void)dt;
469 + if (ebpf_shm_exited == NETDATA_THREAD_EBPF_STOPPING)
470 + break;
471
472 read_global_table();
473 }
474
473 - read_thread_closed = 1;
475 + ebpf_shm_exited = NETDATA_THREAD_EBPF_STOPPED;
476 +
477 + netdata_thread_cleanup_pop(1);
478 return NULL;
479 }
480
@@ -848,20 +852,22 @@ static void shm_collector(ebpf_module_t *em)
852 netdata_thread_create(
853 shm_threads.thread,
854 shm_threads.name,
851 - NETDATA_THREAD_OPTION_JOINABLE,
855 + NETDATA_THREAD_OPTION_DEFAULT,
856 ebpf_shm_read_hash,
857 em
858 );
859
856 - int apps = em->apps_charts;
860 int cgroups = em->cgroup_charts;
861 int update_every = em->update_every;
862 heartbeat_t hb;
863 heartbeat_init(&hb);
864 usec_t step = update_every * USEC_PER_SEC;
862 - while (!close_ebpf_plugin) {
865 + while (!ebpf_exit_plugin) {
866 (void)heartbeat_next(&hb, step);
867 + if (ebpf_exit_plugin)
868 + break;
869
870 + netdata_apps_integration_flags_t apps = em->apps_charts;
871 pthread_mutex_lock(&collect_data_mutex);
872 if (apps) {
873 read_apps_table();
@@ -875,7 +881,7 @@ static void shm_collector(ebpf_module_t *em)
881
882 shm_send_global();
883
878 - if (apps) {
884 + if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
885 ebpf_shm_send_apps_data(apps_groups_root_target);
886 }
887
@@ -937,6 +943,8 @@ void ebpf_shm_create_apps_charts(struct ebpf_module *em, void *ptr)
943 20194,
944 ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
945 root, em->update_every, NETDATA_EBPF_MODULE_NAME_SHM);
946 +
947 + em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
948 }
949
950 /**
@@ -1001,8 +1009,8 @@ static int ebpf_shm_load_bpf(ebpf_module_t *em)
1009 {
1010 int ret = 0;
1011 if (em->load == EBPF_LOAD_LEGACY) {
1004 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
1005 - if (!probe_links) {
1012 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1013 + if (!em->probe_links) {
1014 em->enabled = CONFIG_BOOLEAN_NO;
1015 ret = -1;
1016 }
@@ -1032,7 +1040,7 @@ static int ebpf_shm_load_bpf(ebpf_module_t *em)
1040 */
1041 void *ebpf_shm_thread(void *ptr)
1042 {
1035 - netdata_thread_cleanup_push(ebpf_shm_cleanup, ptr);
1043 + netdata_thread_cleanup_push(ebpf_shm_exit, ptr);
1044
1045 ebpf_module_t *em = (ebpf_module_t *)ptr;
1046 em->maps = shm_maps;
collectors/ebpf.plugin/ebpf_socket.c
+244 -246
@@ -61,10 +61,8 @@ static netdata_publish_syscall_t socket_publish_aggregated[NETDATA_MAX_SOCKET_VE
61 ebpf_socket_publish_apps_t **socket_bandwidth_curr = NULL;
62 static ebpf_bandwidth_t *bandwidth_vector = NULL;
63
64 -static int socket_apps_created = 0;
64 pthread_mutex_t nv_mutex;
65 int wait_to_plot = 0;
67 -int read_thread_closed = 1;
66
67 netdata_vector_plot_t inbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
68 netdata_vector_plot_t outbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
@@ -72,9 +70,6 @@ netdata_socket_t *socket_values;
70
71 ebpf_network_viewer_port_list_t *listen_ports = NULL;
72
75 -static struct bpf_object *objects = NULL;
76 -static struct bpf_link **probe_links = NULL;
77 -
73 struct config socket_config = { .first_section = NULL,
74 .last_section = NULL,
75 .mutex = NETDATA_MUTEX_INITIALIZER,
@@ -92,6 +87,11 @@ netdata_ebpf_targets_t socket_targets[] = { {.name = "inet_csk_accept", .mode =
87 {.name = "tcp_v6_connect", .mode = EBPF_LOAD_TRAMPOLINE},
88 {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
89
90 +struct netdata_static_thread socket_threads = {"EBPF SOCKET READ",
91 + NULL, NULL, 1, NULL,
92 + NULL, NULL };
93 +static enum ebpf_threads_status ebpf_socket_exited = NETDATA_THREAD_EBPF_RUNNING;
94 +
95 #ifdef LIBBPF_MAJOR_VERSION
96 #include "includes/socket.skel.h" // BTF code
97
@@ -424,6 +424,225 @@ static inline int ebpf_socket_load_and_attach(struct socket_bpf *obj, ebpf_modul
424 return ret;
425 }
426 #endif
427 +
428 +/*****************************************************************
429 + *
430 + * FUNCTIONS TO CLOSE THE THREAD
431 + *
432 + *****************************************************************/
433 +
434 +/**
435 + * Clean internal socket plot
436 + *
437 + * Clean all structures allocated with strdupz.
438 + *
439 + * @param ptr the pointer with addresses to clean.
440 + */
441 +static inline void clean_internal_socket_plot(netdata_socket_plot_t *ptr)
442 +{
443 + freez(ptr->dimension_recv);
444 + freez(ptr->dimension_sent);
445 + freez(ptr->resolved_name);
446 + freez(ptr->dimension_retransmit);
447 +}
448 +
449 +/**
450 + * Clean socket plot
451 + *
452 + * Clean the allocated data for inbound and outbound vectors.
453 + */
454 +static void clean_allocated_socket_plot()
455 +{
456 + uint32_t i;
457 + uint32_t end = inbound_vectors.last;
458 + netdata_socket_plot_t *plot = inbound_vectors.plot;
459 + for (i = 0; i < end; i++) {
460 + clean_internal_socket_plot(&plot[i]);
461 + }
462 +
463 + clean_internal_socket_plot(&plot[inbound_vectors.last]);
464 +
465 + end = outbound_vectors.last;
466 + plot = outbound_vectors.plot;
467 + for (i = 0; i < end; i++) {
468 + clean_internal_socket_plot(&plot[i]);
469 + }
470 + clean_internal_socket_plot(&plot[outbound_vectors.last]);
471 +}
472 +
473 +/**
474 + * Clean network ports allocated during initialization.
475 + *
476 + * @param ptr a pointer to the link list.
477 + */
478 +static void clean_network_ports(ebpf_network_viewer_port_list_t *ptr)
479 +{
480 + if (unlikely(!ptr))
481 + return;
482 +
483 + while (ptr) {
484 + ebpf_network_viewer_port_list_t *next = ptr->next;
485 + freez(ptr->value);
486 + freez(ptr);
487 + ptr = next;
488 + }
489 +}
490 +
491 +/**
492 + * Clean service names
493 + *
494 + * Clean the allocated link list that stores names.
495 + *
496 + * @param names the link list.
497 + */
498 +static void clean_service_names(ebpf_network_viewer_dim_name_t *names)
499 +{
500 + if (unlikely(!names))
501 + return;
502 +
503 + while (names) {
504 + ebpf_network_viewer_dim_name_t *next = names->next;
505 + freez(names->name);
506 + freez(names);
507 + names = next;
508 + }
509 +}
510 +
511 +/**
512 + * Clean hostnames
513 + *
514 + * @param hostnames the hostnames to clean
515 + */
516 +static void clean_hostnames(ebpf_network_viewer_hostname_list_t *hostnames)
517 +{
518 + if (unlikely(!hostnames))
519 + return;
520 +
521 + while (hostnames) {
522 + ebpf_network_viewer_hostname_list_t *next = hostnames->next;
523 + freez(hostnames->value);
524 + simple_pattern_free(hostnames->value_pattern);
525 + freez(hostnames);
526 + hostnames = next;
527 + }
528 +}
529 +
530 +/**
531 + * Cleanup publish syscall
532 + *
533 + * @param nps list of structures to clean
534 + */
535 +void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps)
536 +{
537 + while (nps) {
538 + freez(nps->algorithm);
539 + nps = nps->next;
540 + }
541 +}
542 +
543 +/**
544 + * Clean port Structure
545 + *
546 + * Clean the allocated list.
547 + *
548 + * @param clean the list that will be cleaned
549 + */
550 +void clean_port_structure(ebpf_network_viewer_port_list_t **clean)
551 +{
552 + ebpf_network_viewer_port_list_t *move = *clean;
553 + while (move) {
554 + ebpf_network_viewer_port_list_t *next = move->next;
555 + freez(move->value);
556 + freez(move);
557 +
558 + move = next;
559 + }
560 + *clean = NULL;
561 +}
562 +
563 +/**
564 + * Clean IP structure
565 + *
566 + * Clean the allocated list.
567 + *
568 + * @param clean the list that will be cleaned
569 + */
570 +static void clean_ip_structure(ebpf_network_viewer_ip_list_t **clean)
571 +{
572 + ebpf_network_viewer_ip_list_t *move = *clean;
573 + while (move) {
574 + ebpf_network_viewer_ip_list_t *next = move->next;
575 + freez(move->value);
576 + freez(move);
577 +
578 + move = next;
579 + }
580 + *clean = NULL;
581 +}
582 +
583 +/**
584 + * Socket exit
585 + *
586 + * Clean up the main thread.
587 + *
588 + * @param ptr thread data.
589 + */
590 +static void ebpf_socket_exit(void *ptr)
591 +{
592 + ebpf_module_t *em = (ebpf_module_t *)ptr;
593 + if (!em->enabled) {
594 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
595 + return;
596 + }
597 +
598 + ebpf_socket_exited = NETDATA_THREAD_EBPF_STOPPING;
599 +}
600 +
601 +/**
602 + * Socket cleanup
603 + *
604 + * Clean up allocated addresses.
605 + *
606 + * @param ptr thread data.
607 + */
608 +void ebpf_socket_cleanup(void *ptr)
609 +{
610 + ebpf_module_t *em = (ebpf_module_t *)ptr;
611 + if (ebpf_socket_exited != NETDATA_THREAD_EBPF_STOPPED)
612 + return;
613 +
614 + ebpf_cleanup_publish_syscall(socket_publish_aggregated);
615 + freez(socket_hash_values);
616 +
617 + freez(bandwidth_vector);
618 +
619 + freez(socket_values);
620 + clean_allocated_socket_plot();
621 + freez(inbound_vectors.plot);
622 + freez(outbound_vectors.plot);
623 +
624 + clean_port_structure(&listen_ports);
625 +
626 + ebpf_modules[EBPF_MODULE_SOCKET_IDX].enabled = 0;
627 +
628 + clean_network_ports(network_viewer_opt.included_port);
629 + clean_network_ports(network_viewer_opt.excluded_port);
630 + clean_service_names(network_viewer_opt.names);
631 + clean_hostnames(network_viewer_opt.included_hostnames);
632 + clean_hostnames(network_viewer_opt.excluded_hostnames);
633 +
634 + pthread_mutex_destroy(&nv_mutex);
635 +
636 + freez(socket_threads.thread);
637 +
638 +#ifdef LIBBPF_MAJOR_VERSION
639 + if (bpf_obj)
640 + socket_bpf__destroy(bpf_obj);
641 +#endif
642 + socket_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
643 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
644 +}
645 +
646 /*****************************************************************
647 *
648 * PROCESS DATA AND SEND TO NETDATA
@@ -737,8 +956,6 @@ long long ebpf_socket_sum_values_for_pids(struct pid_on_target *root, size_t off
956 void ebpf_socket_send_apps_data(ebpf_module_t *em, struct target *root)
957 {
958 UNUSED(em);
740 - if (!socket_apps_created)
741 - return;
959
960 struct target *w;
961 collected_number value;
@@ -1052,7 +1269,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
1269 ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
1270 root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET);
1271
1055 - socket_apps_created = 1;
1272 + em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
1273 }
1274
1275 /**
@@ -1814,15 +2031,6 @@ static void read_socket_hash_table(int fd, int family, int network_connection)
2031
2032 key = next_key;
2033 }
1817 -
1818 - test = bpf_map_lookup_elem(fd, &next_key, values);
1819 - if (test < 0) {
1820 - return;
1821 - }
1822 -
1823 - if (network_connection) {
1824 - hash_accumulator(values, &next_key, family, end);
1825 - }
2034 }
2035
2036 /**
@@ -1929,18 +2137,20 @@ static void read_listen_table()
2137 */
2138 void *ebpf_socket_read_hash(void *ptr)
2139 {
2140 + netdata_thread_cleanup_push(ebpf_socket_cleanup, ptr);
2141 ebpf_module_t *em = (ebpf_module_t *)ptr;
2142
1934 - read_thread_closed = 0;
2143 heartbeat_t hb;
2144 heartbeat_init(&hb);
2145 usec_t step = NETDATA_SOCKET_READ_SLEEP_MS * em->update_every;
2146 int fd_ipv4 = socket_maps[NETDATA_SOCKET_TABLE_IPV4].map_fd;
2147 int fd_ipv6 = socket_maps[NETDATA_SOCKET_TABLE_IPV6].map_fd;
2148 int network_connection = em->optional;
1941 - while (!close_ebpf_plugin) {
2149 + while (ebpf_socket_exited == NETDATA_THREAD_EBPF_RUNNING) {
2150 usec_t dt = heartbeat_next(&hb, step);
2151 (void)dt;
2152 + if (ebpf_socket_exited == NETDATA_THREAD_EBPF_STOPPING)
2153 + break;
2154
2155 pthread_mutex_lock(&nv_mutex);
2156 read_listen_table();
@@ -1950,7 +2160,9 @@ void *ebpf_socket_read_hash(void *ptr)
2160 pthread_mutex_unlock(&nv_mutex);
2161 }
2162
1953 - read_thread_closed = 1;
2163 + ebpf_socket_exited = NETDATA_THREAD_EBPF_STOPPED;
2164 +
2165 + netdata_thread_cleanup_pop(1);
2166 return NULL;
2167 }
2168
@@ -2643,10 +2855,6 @@ static void ebpf_socket_send_cgroup_data(int update_every)
2855 *
2856 *****************************************************************/
2857
2646 -struct netdata_static_thread socket_threads = {"EBPF SOCKET READ",
2647 - NULL, NULL, 1, NULL,
2648 - NULL, ebpf_socket_read_hash };
2649 -
2858 /**
2859 * Main loop for this collector.
2860 *
@@ -2659,21 +2867,24 @@ static void socket_collector(usec_t step, ebpf_module_t *em)
2867 heartbeat_init(&hb);
2868
2869 socket_threads.thread = mallocz(sizeof(netdata_thread_t));
2870 + socket_threads.start_routine = ebpf_socket_read_hash;
2871
2872 netdata_thread_create(socket_threads.thread, socket_threads.name,
2664 - NETDATA_THREAD_OPTION_JOINABLE, ebpf_socket_read_hash, em);
2873 + NETDATA_THREAD_OPTION_DEFAULT, ebpf_socket_read_hash, em);
2874
2875 int cgroups = em->cgroup_charts;
2876 if (cgroups)
2877 ebpf_socket_update_cgroup_algorithm();
2878
2670 - int socket_apps_enabled = ebpf_modules[EBPF_MODULE_SOCKET_IDX].apps_charts;
2671 - int socket_global_enabled = ebpf_modules[EBPF_MODULE_SOCKET_IDX].global_charts;
2879 + int socket_global_enabled = em->global_charts;
2880 int network_connection = em->optional;
2881 int update_every = em->update_every;
2674 - while (!close_ebpf_plugin) {
2882 + while (!ebpf_exit_plugin) {
2883 (void)heartbeat_next(&hb, step);
2884 + if (ebpf_exit_plugin)
2885 + break;
2886
2887 + netdata_apps_integration_flags_t socket_apps_enabled = em->apps_charts;
2888 pthread_mutex_lock(&collect_data_mutex);
2889 if (socket_global_enabled)
2890 read_hash_global_tables();
@@ -2690,7 +2901,7 @@ static void socket_collector(usec_t step, ebpf_module_t *em)
2901 if (socket_global_enabled)
2902 ebpf_socket_send_data(em);
2903
2693 - if (socket_apps_enabled)
2904 + if (socket_apps_enabled & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
2905 ebpf_socket_send_apps_data(em, apps_groups_root_target);
2906
2907 if (cgroups)
@@ -2718,218 +2929,6 @@ static void socket_collector(usec_t step, ebpf_module_t *em)
2929 }
2930 }
2931
2721 -/*****************************************************************
2722 - *
2723 - * FUNCTIONS TO CLOSE THE THREAD
2724 - *
2725 - *****************************************************************/
2726 -
2727 -
2728 -/**
2729 - * Clean internal socket plot
2730 - *
2731 - * Clean all structures allocated with strdupz.
2732 - *
2733 - * @param ptr the pointer with addresses to clean.
2734 - */
2735 -static inline void clean_internal_socket_plot(netdata_socket_plot_t *ptr)
2736 -{
2737 - freez(ptr->dimension_recv);
2738 - freez(ptr->dimension_sent);
2739 - freez(ptr->resolved_name);
2740 - freez(ptr->dimension_retransmit);
2741 -}
2742 -
2743 -/**
2744 - * Clean socket plot
2745 - *
2746 - * Clean the allocated data for inbound and outbound vectors.
2747 - */
2748 -static void clean_allocated_socket_plot()
2749 -{
2750 - uint32_t i;
2751 - uint32_t end = inbound_vectors.last;
2752 - netdata_socket_plot_t *plot = inbound_vectors.plot;
2753 - for (i = 0; i < end; i++) {
2754 - clean_internal_socket_plot(&plot[i]);
2755 - }
2756 -
2757 - clean_internal_socket_plot(&plot[inbound_vectors.last]);
2758 -
2759 - end = outbound_vectors.last;
2760 - plot = outbound_vectors.plot;
2761 - for (i = 0; i < end; i++) {
2762 - clean_internal_socket_plot(&plot[i]);
2763 - }
2764 - clean_internal_socket_plot(&plot[outbound_vectors.last]);
2765 -}
2766 -
2767 -/**
2768 - * Clean network ports allocated during initialization.
2769 - *
2770 - * @param ptr a pointer to the link list.
2771 - */
2772 -static void clean_network_ports(ebpf_network_viewer_port_list_t *ptr)
2773 -{
2774 - if (unlikely(!ptr))
2775 - return;
2776 -
2777 - while (ptr) {
2778 - ebpf_network_viewer_port_list_t *next = ptr->next;
2779 - freez(ptr->value);
2780 - freez(ptr);
2781 - ptr = next;
2782 - }
2783 -}
2784 -
2785 -/**
2786 - * Clean service names
2787 - *
2788 - * Clean the allocated link list that stores names.
2789 - *
2790 - * @param names the link list.
2791 - */
2792 -static void clean_service_names(ebpf_network_viewer_dim_name_t *names)
2793 -{
2794 - if (unlikely(!names))
2795 - return;
2796 -
2797 - while (names) {
2798 - ebpf_network_viewer_dim_name_t *next = names->next;
2799 - freez(names->name);
2800 - freez(names);
2801 - names = next;
2802 - }
2803 -}
2804 -
2805 -/**
2806 - * Clean hostnames
2807 - *
2808 - * @param hostnames the hostnames to clean
2809 - */
2810 -static void clean_hostnames(ebpf_network_viewer_hostname_list_t *hostnames)
2811 -{
2812 - if (unlikely(!hostnames))
2813 - return;
2814 -
2815 - while (hostnames) {
2816 - ebpf_network_viewer_hostname_list_t *next = hostnames->next;
2817 - freez(hostnames->value);
2818 - simple_pattern_free(hostnames->value_pattern);
2819 - freez(hostnames);
2820 - hostnames = next;
2821 - }
2822 -}
2823 -
2824 -/**
2825 - * Cleanup publish syscall
2826 - *
2827 - * @param nps list of structures to clean
2828 - */
2829 -void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps)
2830 -{
2831 - while (nps) {
2832 - freez(nps->algorithm);
2833 - nps = nps->next;
2834 - }
2835 -}
2836 -
2837 -/**
2838 - * Clean port Structure
2839 - *
2840 - * Clean the allocated list.
2841 - *
2842 - * @param clean the list that will be cleaned
2843 - */
2844 -void clean_port_structure(ebpf_network_viewer_port_list_t **clean)
2845 -{
2846 - ebpf_network_viewer_port_list_t *move = *clean;
2847 - while (move) {
2848 - ebpf_network_viewer_port_list_t *next = move->next;
2849 - freez(move->value);
2850 - freez(move);
2851 -
2852 - move = next;
2853 - }
2854 - *clean = NULL;
2855 -}
2856 -
2857 -/**
2858 - * Clean IP structure
2859 - *
2860 - * Clean the allocated list.
2861 - *
2862 - * @param clean the list that will be cleaned
2863 - */
2864 -static void clean_ip_structure(ebpf_network_viewer_ip_list_t **clean)
2865 -{
2866 - ebpf_network_viewer_ip_list_t *move = *clean;
2867 - while (move) {
2868 - ebpf_network_viewer_ip_list_t *next = move->next;
2869 - freez(move->value);
2870 - freez(move);
2871 -
2872 - move = next;
2873 - }
2874 - *clean = NULL;
2875 -}
2876 -
2877 -/**
2878 - * Clean up the main thread.
2879 - *
2880 - * @param ptr thread data.
2881 - */
2882 -static void ebpf_socket_cleanup(void *ptr)
2883 -{
2884 - ebpf_module_t *em = (ebpf_module_t *)ptr;
2885 - if (!em->enabled)
2886 - return;
2887 -
2888 - heartbeat_t hb;
2889 - heartbeat_init(&hb);
2890 - uint32_t tick = 2*USEC_PER_MS;
2891 - while (!read_thread_closed) {
2892 - usec_t dt = heartbeat_next(&hb, tick);
2893 - UNUSED(dt);
2894 - }
2895 -
2896 - ebpf_cleanup_publish_syscall(socket_publish_aggregated);
2897 - freez(socket_hash_values);
2898 -
2899 - freez(bandwidth_vector);
2900 -
2901 - freez(socket_values);
2902 - clean_allocated_socket_plot();
2903 - freez(inbound_vectors.plot);
2904 - freez(outbound_vectors.plot);
2905 -
2906 - clean_port_structure(&listen_ports);
2907 -
2908 - ebpf_modules[EBPF_MODULE_SOCKET_IDX].enabled = 0;
2909 -
2910 - clean_network_ports(network_viewer_opt.included_port);
2911 - clean_network_ports(network_viewer_opt.excluded_port);
2912 - clean_service_names(network_viewer_opt.names);
2913 - clean_hostnames(network_viewer_opt.included_hostnames);
2914 - clean_hostnames(network_viewer_opt.excluded_hostnames);
2915 -
2916 - pthread_mutex_destroy(&nv_mutex);
2917 -
2918 - freez(socket_threads.thread);
2919 -
2920 - if (probe_links) {
2921 - struct bpf_program *prog;
2922 - size_t i = 0 ;
2923 - bpf_object__for_each_program(prog, objects) {
2924 - bpf_link__destroy(probe_links[i]);
2925 - i++;
2926 - }
2927 - if (objects)
2928 - bpf_object__close(objects);
2929 - }
2930 - finalized_threads = 1;
2931 -}
2932 -
2932 /*****************************************************************
2933 *
2934 * FUNCTIONS TO START THREAD
@@ -3877,8 +3876,8 @@ static int ebpf_socket_load_bpf(ebpf_module_t *em)
3876 int ret = 0;
3877
3878 if (em->load == EBPF_LOAD_LEGACY) {
3880 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
3881 - if (!probe_links) {
3879 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
3880 + if (!em->probe_links) {
3881 ret = -1;
3882 }
3883 }
@@ -3910,7 +3909,7 @@ static int ebpf_socket_load_bpf(ebpf_module_t *em)
3909 */
3910 void *ebpf_socket_thread(void *ptr)
3911 {
3913 - netdata_thread_cleanup_push(ebpf_socket_cleanup, ptr);
3912 + netdata_thread_cleanup_push(ebpf_socket_exit, ptr);
3913
3914 memset(&inbound_vectors.tree, 0, sizeof(avl_tree_lock));
3915 memset(&outbound_vectors.tree, 0, sizeof(avl_tree_lock));
@@ -3932,7 +3931,6 @@ void *ebpf_socket_thread(void *ptr)
3931 error("Cannot initialize local mutex");
3932 goto endsocket;
3933 }
3935 - pthread_mutex_lock(&lock);
3934
3935 ebpf_socket_allocate_global_vectors(em->apps_charts);
3936 initialize_inbound_outbound();
@@ -3959,11 +3957,11 @@ void *ebpf_socket_thread(void *ptr)
3957 socket_aggregated_data, socket_publish_aggregated, socket_dimension_names, socket_id_names,
3958 algorithms, NETDATA_MAX_SOCKET_VECTOR);
3959
3960 + pthread_mutex_lock(&lock);
3961 ebpf_create_global_charts(em);
3962
3963 ebpf_update_stats(&plugin_statistics, em);
3964
3966 - finalized_threads = 0;
3965 pthread_mutex_unlock(&lock);
3966
3967 socket_collector((usec_t)(em->update_every * USEC_PER_SEC), em);
collectors/ebpf.plugin/ebpf_socket.h
+2 -2
@@ -279,7 +279,7 @@ typedef struct netdata_socket {
279 uint32_t retransmit; // It is never used with UDP
280 uint16_t protocol;
281 uint16_t reserved;
282 -} netdata_socket_t __attribute__((__aligned__(8)));
282 +} netdata_socket_t;
283
284 typedef struct netdata_plot_values {
285 // Values used in the previous iteration
@@ -307,7 +307,7 @@ typedef struct netdata_socket_idx {
307 uint16_t sport;
308 union netdata_ip_t daddr;
309 uint16_t dport;
310 -} netdata_socket_idx_t __attribute__((__aligned__(8)));
310 +} netdata_socket_idx_t;
311
312 // Next values were defined according getnameinfo(3)
313 #define NETDATA_MAX_NETWORK_COMBINED_LENGTH 1018
collectors/ebpf.plugin/ebpf_softirq.c
+40 -36
@@ -54,52 +54,51 @@ static softirq_val_t softirq_vals[] = {
54 // tmp store for soft IRQ values we get from a per-CPU eBPF map.
55 static softirq_ebpf_val_t *softirq_ebpf_vals = NULL;
56
57 -static struct bpf_link **probe_links = NULL;
58 -static struct bpf_object *objects = NULL;
59 -
60 -static int read_thread_closed = 1;
61 -
57 static struct netdata_static_thread softirq_threads = {"SOFTIRQ KERNEL",
58 NULL, NULL, 1, NULL,
59 NULL, NULL };
60 +static enum ebpf_threads_status ebpf_softirq_exited = NETDATA_THREAD_EBPF_RUNNING;
61
62 /**
67 - * Clean up the main thread.
63 + * Exit
64 + *
65 + * Cancel thread.
66 *
67 * @param ptr thread data.
68 */
71 -static void softirq_cleanup(void *ptr)
69 +static void softirq_exit(void *ptr)
70 {
73 - for (int i = 0; softirq_tracepoints[i].class != NULL; i++) {
74 - ebpf_disable_tracepoint(&softirq_tracepoints[i]);
75 - }
76 -
71 ebpf_module_t *em = (ebpf_module_t *)ptr;
72 if (!em->enabled) {
73 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
74 return;
75 }
76
82 - heartbeat_t hb;
83 - heartbeat_init(&hb);
84 - uint32_t tick = 1 * USEC_PER_MS;
85 - while (!read_thread_closed) {
86 - usec_t dt = heartbeat_next(&hb, tick);
87 - UNUSED(dt);
88 - }
77 + ebpf_softirq_exited = NETDATA_THREAD_EBPF_STOPPING;
78 +}
79 +
80 +/**
81 + * Cleanup
82 + *
83 + * Clean up allocated memory.
84 + *
85 + * @param ptr thread data.
86 + */
87 +static void softirq_cleanup(void *ptr)
88 +{
89 + ebpf_module_t *em = (ebpf_module_t *)ptr;
90 + if (ebpf_softirq_exited != NETDATA_THREAD_EBPF_STOPPED)
91 + return;
92
90 - freez(softirq_ebpf_vals);
93 freez(softirq_threads.thread);
94
93 - if (probe_links) {
94 - struct bpf_program *prog;
95 - size_t i = 0 ;
96 - bpf_object__for_each_program(prog, objects) {
97 - bpf_link__destroy(probe_links[i]);
98 - i++;
99 - }
100 - if (objects)
101 - bpf_object__close(objects);
95 + for (int i = 0; softirq_tracepoints[i].class != NULL; i++) {
96 + ebpf_disable_tracepoint(&softirq_tracepoints[i]);
97 }
98 + freez(softirq_ebpf_vals);
99 +
100 + softirq_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
101 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
102 }
103
104 /*****************************************************************
@@ -132,22 +131,24 @@ static void softirq_read_latency_map()
131 */
132 static void *softirq_reader(void *ptr)
133 {
135 - read_thread_closed = 0;
136 -
134 + netdata_thread_cleanup_push(softirq_exit, ptr);
135 heartbeat_t hb;
136 heartbeat_init(&hb);
137
138 ebpf_module_t *em = (ebpf_module_t *)ptr;
139
140 usec_t step = NETDATA_SOFTIRQ_SLEEP_MS * em->update_every;
143 - while (!close_ebpf_plugin) {
141 + while (ebpf_softirq_exited == NETDATA_THREAD_EBPF_RUNNING) {
142 usec_t dt = heartbeat_next(&hb, step);
143 UNUSED(dt);
144 + if (ebpf_softirq_exited == NETDATA_THREAD_EBPF_STOPPING)
145 + break;
146
147 softirq_read_latency_map();
148 }
149 + ebpf_softirq_exited = NETDATA_THREAD_EBPF_STOPPED;
150
150 - read_thread_closed = 1;
151 + netdata_thread_cleanup_pop(1);
152 return NULL;
153 }
154
@@ -201,7 +202,7 @@ static void softirq_collector(ebpf_module_t *em)
202 netdata_thread_create(
203 softirq_threads.thread,
204 softirq_threads.name,
204 - NETDATA_THREAD_OPTION_JOINABLE,
205 + NETDATA_THREAD_OPTION_DEFAULT,
206 softirq_reader,
207 em
208 );
@@ -217,8 +218,11 @@ static void softirq_collector(ebpf_module_t *em)
218 heartbeat_t hb;
219 heartbeat_init(&hb);
220 usec_t step = em->update_every * USEC_PER_SEC;
220 - while (!close_ebpf_plugin) {
221 + //This will be cancelled by its parent
222 + while (!ebpf_exit_plugin) {
223 (void)heartbeat_next(&hb, step);
224 + if (ebpf_exit_plugin)
225 + break;
226
227 pthread_mutex_lock(&lock);
228
@@ -257,8 +261,8 @@ void *ebpf_softirq_thread(void *ptr)
261 goto endsoftirq;
262 }
263
260 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
261 - if (!probe_links) {
264 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
265 + if (!em->probe_links) {
266 em->enabled = CONFIG_BOOLEAN_NO;
267 goto endsoftirq;
268 }
collectors/ebpf.plugin/ebpf_swap.c
+44 -36
@@ -7,7 +7,6 @@ static char *swap_dimension_name[NETDATA_SWAP_END] = { "read", "write" };
7 static netdata_syscall_stat_t swap_aggregated_data[NETDATA_SWAP_END];
8 static netdata_publish_syscall_t swap_publish_aggregated[NETDATA_SWAP_END];
9
10 -static int read_thread_closed = 1;
10 netdata_publish_swap_t *swap_vector = NULL;
11
12 static netdata_idx_t swap_hash_values[NETDATA_SWAP_END];
@@ -35,11 +34,9 @@ static ebpf_local_maps_t swap_maps[] = {{.name = "tbl_pid_swap", .internal_input
34 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
35 {.name = NULL, .internal_input = 0, .user_input = 0}};
36
38 -static struct bpf_link **probe_links = NULL;
39 -static struct bpf_object *objects = NULL;
40 -
37 struct netdata_static_thread swap_threads = {"SWAP KERNEL", NULL, NULL, 1,
38 NULL, NULL, NULL};
39 +static enum ebpf_threads_status ebpf_swap_exited = NETDATA_THREAD_EBPF_RUNNING;
40
41 netdata_ebpf_targets_t swap_targets[] = { {.name = "swap_readpage", .mode = EBPF_LOAD_TRAMPOLINE},
42 {.name = "swap_writepage", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -196,43 +193,48 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t
193 *****************************************************************/
194
195 /**
199 - * Clean up the main thread.
196 + * Swap exit
197 + *
198 + * Cancel thread and exit.
199 *
200 * @param ptr thread data.
201 */
203 -static void ebpf_swap_cleanup(void *ptr)
202 +static void ebpf_swap_exit(void *ptr)
203 {
204 ebpf_module_t *em = (ebpf_module_t *)ptr;
206 - if (!em->enabled)
205 + if (!em->enabled) {
206 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
207 return;
208 -
209 - heartbeat_t hb;
210 - heartbeat_init(&hb);
211 - uint32_t tick = 2 * USEC_PER_MS;
212 - while (!read_thread_closed) {
213 - usec_t dt = heartbeat_next(&hb, tick);
214 - UNUSED(dt);
208 }
209
210 + ebpf_swap_exited = NETDATA_THREAD_EBPF_STOPPING;
211 +}
212 +
213 +/**
214 + * Swap cleanup
215 + *
216 + * Clean up allocated memory.
217 + *
218 + * @param ptr thread data.
219 + */
220 +static void ebpf_swap_cleanup(void *ptr)
221 +{
222 + ebpf_module_t *em = (ebpf_module_t *)ptr;
223 + if (ebpf_swap_exited != NETDATA_THREAD_EBPF_STOPPED)
224 + return;
225 +
226 ebpf_cleanup_publish_syscall(swap_publish_aggregated);
227
228 freez(swap_vector);
229 freez(swap_values);
230 + freez(swap_threads.thread);
231
222 - if (probe_links) {
223 - struct bpf_program *prog;
224 - size_t i = 0 ;
225 - bpf_object__for_each_program(prog, objects) {
226 - bpf_link__destroy(probe_links[i]);
227 - i++;
228 - }
229 - if (objects)
230 - bpf_object__close(objects);
231 - }
232 #ifdef LIBBPF_MAJOR_VERSION
233 - else if (bpf_obj)
233 + if (bpf_obj)
234 swap_bpf__destroy(bpf_obj);
235 #endif
236 + swap_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
237 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
238 }
239
240 /*****************************************************************
@@ -393,21 +395,24 @@ static void read_global_table()
395 */
396 void *ebpf_swap_read_hash(void *ptr)
397 {
396 - read_thread_closed = 0;
397 -
398 + netdata_thread_cleanup_push(ebpf_swap_cleanup, ptr);
399 heartbeat_t hb;
400 heartbeat_init(&hb);
401
402 ebpf_module_t *em = (ebpf_module_t *)ptr;
403 usec_t step = NETDATA_SWAP_SLEEP_MS * em->update_every;
403 - while (!close_ebpf_plugin) {
404 + while (ebpf_swap_exited == NETDATA_THREAD_EBPF_RUNNING) {
405 usec_t dt = heartbeat_next(&hb, step);
406 (void)dt;
407 + if (ebpf_swap_exited == NETDATA_THREAD_EBPF_STOPPING)
408 + break;
409
410 read_global_table();
411 }
412
410 - read_thread_closed = 1;
413 + ebpf_swap_exited = NETDATA_THREAD_EBPF_STOPPED;
414 +
415 + netdata_thread_cleanup_pop(1);
416 return NULL;
417 }
418
@@ -679,18 +684,20 @@ static void swap_collector(ebpf_module_t *em)
684 swap_threads.thread = mallocz(sizeof(netdata_thread_t));
685 swap_threads.start_routine = ebpf_swap_read_hash;
686
682 - netdata_thread_create(swap_threads.thread, swap_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
687 + netdata_thread_create(swap_threads.thread, swap_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
688 ebpf_swap_read_hash, em);
689
685 - int apps = em->apps_charts;
690 int cgroup = em->cgroup_charts;
691 int update_every = em->update_every;
692 heartbeat_t hb;
693 heartbeat_init(&hb);
694 usec_t step = update_every * USEC_PER_SEC;
691 - while (!close_ebpf_plugin) {
695 + while (!ebpf_exit_plugin) {
696 (void)heartbeat_next(&hb, step);
697 + if (ebpf_exit_plugin)
698 + break;
699
700 + netdata_apps_integration_flags_t apps = em->apps_charts;
701 pthread_mutex_lock(&collect_data_mutex);
702 if (apps)
703 read_apps_table();
@@ -702,7 +709,7 @@ static void swap_collector(ebpf_module_t *em)
709
710 swap_send_global();
711
705 - if (apps)
712 + if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
713 ebpf_swap_send_apps_data(apps_groups_root_target);
714
715 if (cgroup)
@@ -746,6 +753,7 @@ void ebpf_swap_create_apps_charts(struct ebpf_module *em, void *ptr)
753 20192,
754 ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
755 root, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
756 + em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
757 }
758
759 /**
@@ -805,8 +813,8 @@ static int ebpf_swap_load_bpf(ebpf_module_t *em)
813 {
814 int ret = 0;
815 if (em->load == EBPF_LOAD_LEGACY) {
808 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
809 - if (!probe_links) {
816 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
817 + if (!em->probe_links) {
818 ret = -1;
819 }
820 }
@@ -837,7 +845,7 @@ static int ebpf_swap_load_bpf(ebpf_module_t *em)
845 */
846 void *ebpf_swap_thread(void *ptr)
847 {
840 - netdata_thread_cleanup_push(ebpf_swap_cleanup, ptr);
848 + netdata_thread_cleanup_push(ebpf_swap_exit, ptr);
849
850 ebpf_module_t *em = (ebpf_module_t *)ptr;
851 em->maps = swap_maps;
collectors/ebpf.plugin/ebpf_sync.c
+83 -102
@@ -8,8 +8,6 @@ static char *sync_counter_dimension_name[NETDATA_SYNC_IDX_END] = { "sync", "sync
8 static netdata_syscall_stat_t sync_counter_aggregated_data[NETDATA_SYNC_IDX_END];
9 static netdata_publish_syscall_t sync_counter_publish_aggregated[NETDATA_SYNC_IDX_END];
10
11 -static int read_thread_closed = 1;
12 -
11 static netdata_idx_t sync_hash_values[NETDATA_SYNC_IDX_END];
12
13 struct netdata_static_thread sync_threads = {"SYNC KERNEL", NULL, NULL, 1,
@@ -43,44 +41,6 @@ struct config sync_config = { .first_section = NULL,
41 .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
42 .rwlock = AVL_LOCK_INITIALIZER } };
43
46 -ebpf_sync_syscalls_t local_syscalls[] = {
47 - {.syscall = NETDATA_SYSCALLS_SYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
48 -#ifdef LIBBPF_MAJOR_VERSION
49 - .sync_obj = NULL
50 -#endif
51 - },
52 - {.syscall = NETDATA_SYSCALLS_SYNCFS, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
53 -#ifdef LIBBPF_MAJOR_VERSION
54 - .sync_obj = NULL
55 -#endif
56 - },
57 - {.syscall = NETDATA_SYSCALLS_MSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
58 -#ifdef LIBBPF_MAJOR_VERSION
59 - .sync_obj = NULL
60 -#endif
61 - },
62 - {.syscall = NETDATA_SYSCALLS_FSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
63 -#ifdef LIBBPF_MAJOR_VERSION
64 - .sync_obj = NULL
65 -#endif
66 - },
67 - {.syscall = NETDATA_SYSCALLS_FDATASYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
68 -#ifdef LIBBPF_MAJOR_VERSION
69 - .sync_obj = NULL
70 -#endif
71 - },
72 - {.syscall = NETDATA_SYSCALLS_SYNC_FILE_RANGE, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
73 -#ifdef LIBBPF_MAJOR_VERSION
74 - .sync_obj = NULL
75 -#endif
76 - },
77 - {.syscall = NULL, .enabled = CONFIG_BOOLEAN_NO, .objects = NULL, .probe_links = NULL,
78 -#ifdef LIBBPF_MAJOR_VERSION
79 - .sync_obj = NULL
80 -#endif
81 - }
82 -};
83 -
44 netdata_ebpf_targets_t sync_targets[] = { {.name = NETDATA_SYSCALLS_SYNC, .mode = EBPF_LOAD_TRAMPOLINE},
45 {.name = NETDATA_SYSCALLS_SYNCFS, .mode = EBPF_LOAD_TRAMPOLINE},
46 {.name = NETDATA_SYSCALLS_MSYNC, .mode = EBPF_LOAD_TRAMPOLINE},
@@ -88,6 +48,7 @@ netdata_ebpf_targets_t sync_targets[] = { {.name = NETDATA_SYSCALLS_SYNC, .mode
48 {.name = NETDATA_SYSCALLS_FDATASYNC, .mode = EBPF_LOAD_TRAMPOLINE},
49 {.name = NETDATA_SYSCALLS_SYNC_FILE_RANGE, .mode = EBPF_LOAD_TRAMPOLINE},
50 {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
51 +static enum ebpf_threads_status ebpf_sync_exited = NETDATA_THREAD_EBPF_RUNNING;
52
53
54 #ifdef LIBBPF_MAJOR_VERSION
@@ -216,6 +177,76 @@ static inline int ebpf_sync_load_and_attach(struct sync_bpf *obj, ebpf_module_t
177 }
178 #endif
179
180 +/*****************************************************************
181 + *
182 + * CLEANUP THREAD
183 + *
184 + *****************************************************************/
185 +
186 +/**
187 + * Cleanup Objects
188 + *
189 + * Cleanup loaded objects when thread was initialized.
190 + */
191 +void ebpf_sync_cleanup_objects()
192 +{
193 + int i;
194 + for (i = 0; local_syscalls[i].syscall; i++) {
195 + ebpf_sync_syscalls_t *w = &local_syscalls[i];
196 + if (w->probe_links) {
197 + struct bpf_program *prog;
198 + size_t j = 0 ;
199 + bpf_object__for_each_program(prog, w->objects) {
200 + bpf_link__destroy(w->probe_links[j]);
201 + j++;
202 + }
203 + freez(w->probe_links);
204 + if (w->objects)
205 + bpf_object__close(w->objects);
206 + }
207 +#ifdef LIBBPF_MAJOR_VERSION
208 + else if (w->sync_obj)
209 + sync_bpf__destroy(w->sync_obj);
210 +#endif
211 + }
212 +}
213 +
214 +/**
215 + * Exit
216 + *
217 + * Clean up the main thread.
218 + *
219 + * @param ptr thread data.
220 + */
221 +static void ebpf_sync_exit(void *ptr)
222 +{
223 + ebpf_module_t *em = (ebpf_module_t *)ptr;
224 + if (!em->enabled) {
225 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
226 + return;
227 + }
228 +
229 + ebpf_sync_exited = NETDATA_THREAD_EBPF_STOPPING;
230 +}
231 +
232 +/**
233 + * Clean up the main thread.
234 + *
235 + * @param ptr thread data.
236 + */
237 +static void ebpf_sync_cleanup(void *ptr)
238 +{
239 + ebpf_module_t *em = (ebpf_module_t *)ptr;
240 + if (ebpf_sync_exited != NETDATA_THREAD_EBPF_STOPPED)
241 + return;
242 +
243 + ebpf_sync_cleanup_objects();
244 + freez(sync_threads.thread);
245 +
246 + sync_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
247 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
248 +}
249 +
250 /*****************************************************************
251 *
252 * INITIALIZE THREAD
@@ -334,21 +365,25 @@ static void read_global_table()
365 */
366 void *ebpf_sync_read_hash(void *ptr)
367 {
368 + netdata_thread_cleanup_push(ebpf_sync_cleanup, ptr);
369 ebpf_module_t *em = (ebpf_module_t *)ptr;
338 - read_thread_closed = 0;
370
371 heartbeat_t hb;
372 heartbeat_init(&hb);
373 usec_t step = NETDATA_EBPF_SYNC_SLEEP_MS * em->update_every;
374
344 - while (!close_ebpf_plugin) {
375 + while (ebpf_sync_exited == NETDATA_THREAD_EBPF_RUNNING) {
376 usec_t dt = heartbeat_next(&hb, step);
377 (void)dt;
378 + if (ebpf_sync_exited == NETDATA_THREAD_EBPF_STOPPING)
379 + break;
380
381 read_global_table();
382 }
350 - read_thread_closed = 1;
383
384 + ebpf_sync_exited = NETDATA_THREAD_EBPF_STOPPED;
385 +
386 + netdata_thread_cleanup_pop(1);
387 return NULL;
388 }
389
@@ -414,14 +449,16 @@ static void sync_collector(ebpf_module_t *em)
449 sync_threads.thread = mallocz(sizeof(netdata_thread_t));
450 sync_threads.start_routine = ebpf_sync_read_hash;
451
417 - netdata_thread_create(sync_threads.thread, sync_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
452 + netdata_thread_create(sync_threads.thread, sync_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
453 ebpf_sync_read_hash, em);
454
455 heartbeat_t hb;
456 heartbeat_init(&hb);
457 usec_t step = em->update_every * USEC_PER_SEC;
423 - while (!close_ebpf_plugin) {
458 + while (!ebpf_exit_plugin) {
459 (void)heartbeat_next(&hb, step);
460 + if (ebpf_exit_plugin)
461 + break;
462
463 pthread_mutex_lock(&lock);
464
@@ -432,62 +469,6 @@ static void sync_collector(ebpf_module_t *em)
469 }
470
471
435 -/*****************************************************************
436 - *
437 - * CLEANUP THREAD
438 - *
439 - *****************************************************************/
440 -
441 -/**
442 - * Cleanup Objects
443 - *
444 - * Cleanup loaded objects when thread was initialized.
445 - */
446 -void ebpf_sync_cleanup_objects()
447 -{
448 - int i;
449 - for (i = 0; local_syscalls[i].syscall; i++) {
450 - ebpf_sync_syscalls_t *w = &local_syscalls[i];
451 - if (w->probe_links) {
452 - struct bpf_program *prog;
453 - size_t j = 0 ;
454 - bpf_object__for_each_program(prog, w->objects) {
455 - bpf_link__destroy(w->probe_links[j]);
456 - j++;
457 - }
458 - if (w->objects)
459 - bpf_object__close(w->objects);
460 - }
461 -#ifdef LIBBPF_MAJOR_VERSION
462 - else if (w->sync_obj)
463 - sync_bpf__destroy(w->sync_obj);
464 -#endif
465 - }
466 -}
467 -
468 -/**
469 - * Clean up the main thread.
470 - *
471 - * @param ptr thread data.
472 - */
473 -static void ebpf_sync_cleanup(void *ptr)
474 -{
475 - ebpf_module_t *em = (ebpf_module_t *)ptr;
476 - if (!em->enabled)
477 - return;
478 -
479 - heartbeat_t hb;
480 - heartbeat_init(&hb);
481 - uint32_t tick = 2*USEC_PER_MS;
482 - while (!read_thread_closed) {
483 - usec_t dt = heartbeat_next(&hb, tick);
484 - UNUSED(dt);
485 - }
486 -
487 - ebpf_sync_cleanup_objects();
488 - freez(sync_threads.thread);
489 -}
490 -
472 /*****************************************************************
473 *
474 * MAIN THREAD
@@ -584,7 +565,7 @@ static void ebpf_sync_parse_syscalls()
565 */
566 void *ebpf_sync_thread(void *ptr)
567 {
587 - netdata_thread_cleanup_push(ebpf_sync_cleanup, ptr);
568 + netdata_thread_cleanup_push(ebpf_sync_exit, ptr);
569
570 ebpf_module_t *em = (ebpf_module_t *)ptr;
571 em->maps = sync_maps;
collectors/ebpf.plugin/ebpf_sync.h
-17
@@ -41,23 +41,6 @@ typedef enum sync_syscalls_index {
41 NETDATA_SYNC_IDX_END
42 } sync_syscalls_index_t;
43
44 -typedef struct ebpf_sync_syscalls {
45 - char *syscall;
46 - int enabled;
47 - uint32_t flags;
48 -
49 - // BTF structure
50 - struct bpf_object *objects;
51 - struct bpf_link **probe_links;
52 -
53 - // BPF structure
54 -#ifdef LIBBPF_MAJOR_VERSION
55 - struct sync_bpf *sync_obj;
56 -#else
57 - void *sync_obj;
58 -#endif
59 -} ebpf_sync_syscalls_t;
60 -
44 enum netdata_sync_charts {
45 NETDATA_SYNC_CALL,
46
collectors/ebpf.plugin/ebpf_vfs.c
+40 -35
@@ -34,20 +34,33 @@ struct config vfs_config = { .first_section = NULL,
34 .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
35 .rwlock = AVL_LOCK_INITIALIZER } };
36
37 -static struct bpf_object *objects = NULL;
38 -static struct bpf_link **probe_links = NULL;
39 -
37 struct netdata_static_thread vfs_threads = {"VFS KERNEL",
38 NULL, NULL, 1, NULL,
39 NULL, NULL};
43 -
44 -static int read_thread_closed = 1;
40 +static enum ebpf_threads_status ebpf_vfs_exited = NETDATA_THREAD_EBPF_RUNNING;
41
42 /*****************************************************************
43 *
44 * FUNCTIONS TO CLOSE THE THREAD
45 *
46 *****************************************************************/
47 +/**
48 + * Exit
49 + *
50 + * Cancel thread and exit.
51 + *
52 + * @param ptr thread data.
53 +**/
54 +static void ebpf_vfs_exit(void *ptr)
55 +{
56 + ebpf_module_t *em = (ebpf_module_t *)ptr;
57 + if (!em->enabled) {
58 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
59 + return;
60 + }
61 +
62 + ebpf_vfs_exited = NETDATA_THREAD_EBPF_STOPPING;
63 +}
64
65 /**
66 * Clean up the main thread.
@@ -57,30 +70,15 @@ static int read_thread_closed = 1;
70 static void ebpf_vfs_cleanup(void *ptr)
71 {
72 ebpf_module_t *em = (ebpf_module_t *)ptr;
60 - if (!em->enabled)
73 + if (ebpf_vfs_exited != NETDATA_THREAD_EBPF_STOPPED)
74 return;
75
63 - heartbeat_t hb;
64 - heartbeat_init(&hb);
65 - uint32_t tick = 50 * USEC_PER_MS;
66 - while (!read_thread_closed) {
67 - usec_t dt = heartbeat_next(&hb, tick);
68 - UNUSED(dt);
69 - }
70 -
76 freez(vfs_hash_values);
77 freez(vfs_vector);
78 + freez(vfs_threads.thread);
79
74 - if (probe_links) {
75 - struct bpf_program *prog;
76 - size_t i = 0 ;
77 - bpf_object__for_each_program(prog, objects) {
78 - bpf_link__destroy(probe_links[i]);
79 - i++;
80 - }
81 - if (objects)
82 - bpf_object__close(objects);
83 - }
80 + vfs_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
81 + em->enabled = NETDATA_MAIN_THREAD_EXITED;
82 }
83
84 /*****************************************************************
@@ -513,23 +511,26 @@ static void read_update_vfs_cgroup()
511 */
512 void *ebpf_vfs_read_hash(void *ptr)
513 {
516 - read_thread_closed = 0;
517 -
514 + netdata_thread_cleanup_push(ebpf_vfs_cleanup, ptr);
515 heartbeat_t hb;
516 heartbeat_init(&hb);
517
518 ebpf_module_t *em = (ebpf_module_t *)ptr;
519
520 usec_t step = NETDATA_LATENCY_VFS_SLEEP_MS * em->update_every;
524 - while (!close_ebpf_plugin) {
521 + //This will be cancelled by its parent
522 + while (ebpf_vfs_exited == NETDATA_THREAD_EBPF_RUNNING) {
523 usec_t dt = heartbeat_next(&hb, step);
524 (void)dt;
525 + if (ebpf_vfs_exited == NETDATA_THREAD_EBPF_STOPPING)
526 + break;
527
528 read_global_table();
529 }
530
531 - read_thread_closed = 1;
531 + ebpf_vfs_exited = NETDATA_THREAD_EBPF_STOPPED;
532
533 + netdata_thread_cleanup_pop(1);
534 return NULL;
535 }
536
@@ -1168,17 +1169,19 @@ static void vfs_collector(ebpf_module_t *em)
1169 vfs_threads.thread = mallocz(sizeof(netdata_thread_t));
1170 vfs_threads.start_routine = ebpf_vfs_read_hash;
1171
1171 - netdata_thread_create(vfs_threads.thread, vfs_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
1172 + netdata_thread_create(vfs_threads.thread, vfs_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
1173 ebpf_vfs_read_hash, em);
1174
1174 - int apps = em->apps_charts;
1175 int cgroups = em->cgroup_charts;
1176 heartbeat_t hb;
1177 heartbeat_init(&hb);
1178 usec_t step = em->update_every * USEC_PER_SEC;
1179 - while (!close_ebpf_plugin) {
1179 + while (!ebpf_exit_plugin) {
1180 (void)heartbeat_next(&hb, step);
1181 + if (ebpf_exit_plugin)
1182 + break;
1183
1184 + netdata_apps_integration_flags_t apps = em->apps_charts;
1185 pthread_mutex_lock(&collect_data_mutex);
1186 if (apps)
1187 ebpf_vfs_read_apps();
@@ -1191,7 +1194,7 @@ static void vfs_collector(ebpf_module_t *em)
1194 ebpf_vfs_send_data(em);
1195 fflush(stdout);
1196
1194 - if (apps)
1197 + if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
1198 ebpf_vfs_send_apps_data(em, apps_groups_root_target);
1199
1200 if (cgroups)
@@ -1505,6 +1508,8 @@ void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr)
1508 ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
1509 root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
1510 }
1511 +
1512 + em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
1513 }
1514
1515 /*****************************************************************
@@ -1549,7 +1554,7 @@ static void ebpf_vfs_allocate_global_vectors(int apps)
1554 */
1555 void *ebpf_vfs_thread(void *ptr)
1556 {
1552 - netdata_thread_cleanup_push(ebpf_vfs_cleanup, ptr);
1557 + netdata_thread_cleanup_push(ebpf_vfs_exit, ptr);
1558
1559 ebpf_module_t *em = (ebpf_module_t *)ptr;
1560 em->maps = vfs_maps;
@@ -1561,8 +1566,8 @@ void *ebpf_vfs_thread(void *ptr)
1566 if (!em->enabled)
1567 goto endvfs;
1568
1564 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
1565 - if (!probe_links) {
1569 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1570 + if (!em->probe_links) {
1571 em->enabled = CONFIG_BOOLEAN_NO;
1572 goto endvfs;
1573 }
libnetdata/ebpf/ebpf.c
+2 -2
@@ -608,7 +608,7 @@ static void ebpf_update_maps(ebpf_module_t *em, struct bpf_object *obj)
608 void ebpf_update_controller(int fd, ebpf_module_t *em)
609 {
610 uint32_t key = NETDATA_CONTROLLER_APPS_ENABLED;
611 - uint32_t value = em->apps_charts | em->cgroup_charts;
611 + uint32_t value = (em->apps_charts & NETDATA_EBPF_APPS_FLAG_YES) | em->cgroup_charts;
612 int ret = bpf_map_update_elem(fd, &key, &value, 0);
613 if (ret)
614 error("Add key(%u) for controller table failed.", key);
@@ -969,7 +969,7 @@ void ebpf_update_module_using_config(ebpf_module_t *modules)
969 EBPF_CFG_UPDATE_EVERY, modules->update_every);
970
971 modules->apps_charts = appconfig_get_boolean(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_APPLICATION,
972 - modules->apps_charts);
972 + (int) (modules->apps_charts & NETDATA_EBPF_APPS_FLAG_YES));
973
974 modules->cgroup_charts = appconfig_get_boolean(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_CGROUP,
975 modules->cgroup_charts);
libnetdata/ebpf/ebpf.h
+46 -1
@@ -213,6 +213,12 @@ typedef struct ebpf_plugin_stats {
213 uint32_t trampolines; // Number of trampolines used
214 } ebpf_plugin_stats_t;
215
216 +typedef enum netdata_apps_integration_flags {
217 + NETDATA_EBPF_APPS_FLAG_NO,
218 + NETDATA_EBPF_APPS_FLAG_YES,
219 + NETDATA_EBPF_APPS_FLAG_CHART_CREATED
220 +} netdata_apps_integration_flags_t;
221 +
222 typedef struct ebpf_module {
223 const char *thread_name;
224 const char *config_name;
@@ -220,7 +226,7 @@ typedef struct ebpf_module {
226 void *(*start_routine)(void *);
227 int update_every;
228 int global_charts;
223 - int apps_charts;
229 + netdata_apps_integration_flags_t apps_charts;
230 int cgroup_charts;
231 netdata_run_mode_t mode;
232 uint32_t thread_id;
@@ -234,6 +240,8 @@ typedef struct ebpf_module {
240 uint64_t kernels;
241 netdata_ebpf_load_mode_t load;
242 netdata_ebpf_targets_t *targets;
243 + struct bpf_link **probe_links;
244 + struct bpf_object *objects;
245 } ebpf_module_t;
246
247 extern int ebpf_get_kernel_version();
@@ -267,6 +275,43 @@ typedef struct netdata_ebpf_histogram {
275 uint64_t histogram[NETDATA_EBPF_HIST_MAX_BINS];
276 } netdata_ebpf_histogram_t;
277
278 +typedef struct ebpf_filesystem_partitions {
279 + char *filesystem;
280 + char *optional_filesystem;
281 + char *family;
282 + char *family_name;
283 + struct bpf_object *objects;
284 + struct bpf_link **probe_links;
285 +
286 + netdata_ebpf_histogram_t hread;
287 + netdata_ebpf_histogram_t hwrite;
288 + netdata_ebpf_histogram_t hopen;
289 + netdata_ebpf_histogram_t hadditional;
290 +
291 + uint32_t flags;
292 + uint32_t enabled;
293 +
294 + ebpf_addresses_t addresses;
295 + uint64_t kernels;
296 +} ebpf_filesystem_partitions_t;
297 +
298 +typedef struct ebpf_sync_syscalls {
299 + char *syscall;
300 + int enabled;
301 + uint32_t flags;
302 +
303 + // BTF structure
304 + struct bpf_object *objects;
305 + struct bpf_link **probe_links;
306 +
307 + // BPF structure
308 +#ifdef LIBBPF_MAJOR_VERSION
309 + struct sync_bpf *sync_obj;
310 +#else
311 + void *sync_obj;
312 +#endif
313 +} ebpf_sync_syscalls_t;
314 +
315 extern void ebpf_histogram_dimension_cleanup(char **ptr, size_t length);
316
317 // Tracepoint helpers