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