master
c 3,020 lines 102 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "ebpf.h"
4 #include "ebpf_vfs.h"
5 #include "libbpf_api/ebpf_library.h"
6 #include <stddef.h>
7
8 static char *vfs_dimension_names[NETDATA_KEY_PUBLISH_VFS_END] = {"delete", "read", "write", "fsync", "open", "create"};
9 static char *vfs_id_names[NETDATA_KEY_PUBLISH_VFS_END] =
10 {"vfs_unlink", "vfs_read", "vfs_write", "vfs_fsync", "vfs_open", "vfs_create"};
11
12 static netdata_idx_t *vfs_hash_values = NULL;
13 static netdata_syscall_stat_t vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_END];
14 static netdata_publish_syscall_t vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_END];
15 netdata_ebpf_vfs_t *vfs_vector = NULL;
16
17 static ebpf_local_maps_t vfs_maps[] = {
18 {.name = "tbl_vfs_pid",
19 .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
20 .user_input = 0,
21 .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
22 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
23 #ifdef LIBBPF_MAJOR_VERSION
24 .map_type = BPF_MAP_TYPE_PERCPU_HASH
25 #endif
26 },
27 {.name = "tbl_vfs_stats",
28 .internal_input = NETDATA_VFS_COUNTER,
29 .user_input = 0,
30 .type = NETDATA_EBPF_MAP_STATIC,
31 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
32 #ifdef LIBBPF_MAJOR_VERSION
33 .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
34 #endif
35 },
36 {.name = "vfs_ctrl",
37 .internal_input = NETDATA_CONTROLLER_END,
38 .user_input = 0,
39 .type = NETDATA_EBPF_MAP_CONTROLLER,
40 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
41 #ifdef LIBBPF_MAJOR_VERSION
42 .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
43 #endif
44 },
45 {.name = NULL,
46 .internal_input = 0,
47 .user_input = 0,
48 #ifdef LIBBPF_MAJOR_VERSION
49 .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
50 #endif
51 }};
52
53 struct netdata_static_thread ebpf_read_vfs = {
54 .name = "EBPF_READ_VFS",
55 .config_section = NULL,
56 .config_name = NULL,
57 .env_name = NULL,
58 .enabled = 1,
59 .thread = NULL,
60 .init_routine = NULL,
61 .start_routine = NULL};
62
63 struct config vfs_config = APPCONFIG_INITIALIZER;
64
65 netdata_ebpf_targets_t vfs_targets[] = {
66 {.name = "vfs_write", .mode = EBPF_LOAD_TRAMPOLINE},
67 {.name = "vfs_writev", .mode = EBPF_LOAD_TRAMPOLINE},
68 {.name = "vfs_read", .mode = EBPF_LOAD_TRAMPOLINE},
69 {.name = "vfs_readv", .mode = EBPF_LOAD_TRAMPOLINE},
70 {.name = "vfs_unlink", .mode = EBPF_LOAD_TRAMPOLINE},
71 {.name = "vfs_fsync", .mode = EBPF_LOAD_TRAMPOLINE},
72 {.name = "vfs_open", .mode = EBPF_LOAD_TRAMPOLINE},
73 {.name = "vfs_create", .mode = EBPF_LOAD_TRAMPOLINE},
74 {.name = "release_task", .mode = EBPF_LOAD_TRAMPOLINE},
75 {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
76
77 #ifdef LIBBPF_MAJOR_VERSION
78 /**
79 * Disable probe
80 *
81 * Disable all probes to use exclusively another method.
82 *
83 * @param obj is the main structure for bpf objects
84 */
85 static void ebpf_vfs_disable_probes(struct vfs_bpf *obj)
86 {
87 bpf_program__set_autoload(obj->progs.netdata_vfs_write_kprobe, false);
88 bpf_program__set_autoload(obj->progs.netdata_vfs_write_kretprobe, false);
89 bpf_program__set_autoload(obj->progs.netdata_vfs_writev_kprobe, false);
90 bpf_program__set_autoload(obj->progs.netdata_vfs_writev_kretprobe, false);
91 bpf_program__set_autoload(obj->progs.netdata_vfs_read_kprobe, false);
92 bpf_program__set_autoload(obj->progs.netdata_vfs_read_kretprobe, false);
93 bpf_program__set_autoload(obj->progs.netdata_vfs_readv_kprobe, false);
94 bpf_program__set_autoload(obj->progs.netdata_vfs_readv_kretprobe, false);
95 bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_kprobe, false);
96 bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_kretprobe, false);
97 bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_kprobe, false);
98 bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_kretprobe, false);
99 bpf_program__set_autoload(obj->progs.netdata_vfs_open_kprobe, false);
100 bpf_program__set_autoload(obj->progs.netdata_vfs_open_kretprobe, false);
101 bpf_program__set_autoload(obj->progs.netdata_vfs_create_kprobe, false);
102 bpf_program__set_autoload(obj->progs.netdata_vfs_create_kretprobe, false);
103 }
104
105 /*
106 * Disable trampoline
107 *
108 * Disable all trampoline to use exclusively another method.
109 *
110 * @param obj is the main structure for bpf objects.
111 */
112 static void ebpf_vfs_disable_trampoline(struct vfs_bpf *obj)
113 {
114 bpf_program__set_autoload(obj->progs.netdata_vfs_write_fentry, false);
115 bpf_program__set_autoload(obj->progs.netdata_vfs_write_fexit, false);
116 bpf_program__set_autoload(obj->progs.netdata_vfs_writev_fentry, false);
117 bpf_program__set_autoload(obj->progs.netdata_vfs_writev_fexit, false);
118 bpf_program__set_autoload(obj->progs.netdata_vfs_read_fentry, false);
119 bpf_program__set_autoload(obj->progs.netdata_vfs_read_fexit, false);
120 bpf_program__set_autoload(obj->progs.netdata_vfs_readv_fentry, false);
121 bpf_program__set_autoload(obj->progs.netdata_vfs_readv_fexit, false);
122 bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_fentry, false);
123 bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_fentry, false);
124 bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_fexit, false);
125 bpf_program__set_autoload(obj->progs.netdata_vfs_open_fentry, false);
126 bpf_program__set_autoload(obj->progs.netdata_vfs_open_fexit, false);
127 bpf_program__set_autoload(obj->progs.netdata_vfs_create_fentry, false);
128 }
129
130 /**
131 * Set trampoline target
132 *
133 * Set the targets we will monitor.
134 *
135 * @param obj is the main structure for bpf objects.
136 */
137 static void ebpf_vfs_set_trampoline_target(struct vfs_bpf *obj)
138 {
139 bpf_program__set_attach_target(obj->progs.netdata_vfs_write_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
140
141 bpf_program__set_attach_target(obj->progs.netdata_vfs_write_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
142
143 bpf_program__set_attach_target(obj->progs.netdata_vfs_writev_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
144
145 bpf_program__set_attach_target(obj->progs.netdata_vfs_writev_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
146
147 bpf_program__set_attach_target(obj->progs.netdata_vfs_read_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_READ].name);
148
149 bpf_program__set_attach_target(obj->progs.netdata_vfs_read_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_READ].name);
150
151 bpf_program__set_attach_target(obj->progs.netdata_vfs_readv_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_READV].name);
152
153 bpf_program__set_attach_target(obj->progs.netdata_vfs_readv_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_READV].name);
154
155 bpf_program__set_attach_target(obj->progs.netdata_vfs_unlink_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_UNLINK].name);
156
157 bpf_program__set_attach_target(obj->progs.netdata_vfs_fsync_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
158
159 bpf_program__set_attach_target(obj->progs.netdata_vfs_fsync_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
160
161 bpf_program__set_attach_target(obj->progs.netdata_vfs_open_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
162
163 bpf_program__set_attach_target(obj->progs.netdata_vfs_open_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
164
165 bpf_program__set_attach_target(obj->progs.netdata_vfs_create_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
166 }
167
168 /**
169 * Attach Probe
170 *
171 * Attach probes to target
172 *
173 * @param obj is the main structure for bpf objects.
174 *
175 * @return It returns 0 on success and -1 otherwise.
176 */
177 static int ebpf_vfs_attach_probe(struct vfs_bpf *obj)
178 {
179 obj->links.netdata_vfs_write_kprobe = bpf_program__attach_kprobe(
180 obj->progs.netdata_vfs_write_kprobe, false, vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
181 long ret = libbpf_get_error(obj->links.netdata_vfs_write_kprobe);
182 if (ret)
183 return -1;
184
185 obj->links.netdata_vfs_write_kretprobe = bpf_program__attach_kprobe(
186 obj->progs.netdata_vfs_write_kretprobe, true, vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
187 ret = libbpf_get_error(obj->links.netdata_vfs_write_kretprobe);
188 if (ret)
189 return -1;
190
191 obj->links.netdata_vfs_writev_kprobe = bpf_program__attach_kprobe(
192 obj->progs.netdata_vfs_writev_kprobe, false, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
193 ret = libbpf_get_error(obj->links.netdata_vfs_writev_kprobe);
194 if (ret)
195 return -1;
196
197 obj->links.netdata_vfs_writev_kretprobe = bpf_program__attach_kprobe(
198 obj->progs.netdata_vfs_writev_kretprobe, true, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
199 ret = libbpf_get_error(obj->links.netdata_vfs_writev_kretprobe);
200 if (ret)
201 return -1;
202
203 obj->links.netdata_vfs_read_kprobe =
204 bpf_program__attach_kprobe(obj->progs.netdata_vfs_read_kprobe, false, vfs_targets[NETDATA_EBPF_VFS_READ].name);
205 ret = libbpf_get_error(obj->links.netdata_vfs_read_kprobe);
206 if (ret)
207 return -1;
208
209 obj->links.netdata_vfs_read_kretprobe = bpf_program__attach_kprobe(
210 obj->progs.netdata_vfs_read_kretprobe, true, vfs_targets[NETDATA_EBPF_VFS_READ].name);
211 ret = libbpf_get_error(obj->links.netdata_vfs_read_kretprobe);
212 if (ret)
213 return -1;
214
215 obj->links.netdata_vfs_readv_kprobe = bpf_program__attach_kprobe(
216 obj->progs.netdata_vfs_readv_kprobe, false, vfs_targets[NETDATA_EBPF_VFS_READV].name);
217 ret = libbpf_get_error(obj->links.netdata_vfs_readv_kprobe);
218 if (ret)
219 return -1;
220
221 obj->links.netdata_vfs_readv_kretprobe = bpf_program__attach_kprobe(
222 obj->progs.netdata_vfs_readv_kretprobe, true, vfs_targets[NETDATA_EBPF_VFS_READV].name);
223 ret = libbpf_get_error(obj->links.netdata_vfs_readv_kretprobe);
224 if (ret)
225 return -1;
226
227 obj->links.netdata_vfs_unlink_kprobe = bpf_program__attach_kprobe(
228 obj->progs.netdata_vfs_unlink_kprobe, false, vfs_targets[NETDATA_EBPF_VFS_UNLINK].name);
229 ret = libbpf_get_error(obj->links.netdata_vfs_unlink_kprobe);
230 if (ret)
231 return -1;
232
233 obj->links.netdata_vfs_unlink_kretprobe = bpf_program__attach_kprobe(
234 obj->progs.netdata_vfs_unlink_kretprobe, true, vfs_targets[NETDATA_EBPF_VFS_UNLINK].name);
235 ret = libbpf_get_error(obj->links.netdata_vfs_unlink_kretprobe);
236 if (ret)
237 return -1;
238
239 obj->links.netdata_vfs_fsync_kprobe = bpf_program__attach_kprobe(
240 obj->progs.netdata_vfs_fsync_kprobe, false, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
241 ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kprobe);
242 if (ret)
243 return -1;
244
245 obj->links.netdata_vfs_fsync_kretprobe = bpf_program__attach_kprobe(
246 obj->progs.netdata_vfs_fsync_kretprobe, true, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
247 ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kretprobe);
248 if (ret)
249 return -1;
250
251 obj->links.netdata_vfs_open_kprobe =
252 bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kprobe, false, vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
253 ret = libbpf_get_error(obj->links.netdata_vfs_open_kprobe);
254 if (ret)
255 return -1;
256
257 obj->links.netdata_vfs_open_kretprobe = bpf_program__attach_kprobe(
258 obj->progs.netdata_vfs_open_kretprobe, true, vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
259 ret = libbpf_get_error(obj->links.netdata_vfs_open_kretprobe);
260 if (ret)
261 return -1;
262
263 obj->links.netdata_vfs_create_kprobe = bpf_program__attach_kprobe(
264 obj->progs.netdata_vfs_create_kprobe, false, vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
265 ret = libbpf_get_error(obj->links.netdata_vfs_create_kprobe);
266 if (ret)
267 return -1;
268
269 obj->links.netdata_vfs_create_kretprobe = bpf_program__attach_kprobe(
270 obj->progs.netdata_vfs_create_kretprobe, true, vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
271 ret = libbpf_get_error(obj->links.netdata_vfs_create_kretprobe);
272 if (ret)
273 return -1;
274
275 return 0;
276 }
277
278 /**
279 * Adjust Size
280 *
281 * Resize maps according input from users.
282 *
283 * @param obj is the main structure for bpf objects.
284 * @param em structure with configuration
285 */
286 static void ebpf_vfs_adjust_map(struct vfs_bpf *obj, ebpf_module_t *em)
287 {
288 ebpf_update_map_size(obj->maps.tbl_vfs_pid, &vfs_maps[NETDATA_VFS_PID], em, bpf_map__name(obj->maps.tbl_vfs_pid));
289
290 ebpf_update_map_type(obj->maps.tbl_vfs_pid, &vfs_maps[NETDATA_VFS_PID]);
291 ebpf_update_map_type(obj->maps.tbl_vfs_stats, &vfs_maps[NETDATA_VFS_ALL]);
292 ebpf_update_map_type(obj->maps.vfs_ctrl, &vfs_maps[NETDATA_VFS_CTRL]);
293 }
294
295 /**
296 * Set hash tables
297 *
298 * Set the values for maps according the value given by kernel.
299 *
300 * @param obj is the main structure for bpf objects.
301 */
302 static void ebpf_vfs_set_hash_tables(struct vfs_bpf *obj)
303 {
304 vfs_maps[NETDATA_VFS_ALL].map_fd = bpf_map__fd(obj->maps.tbl_vfs_stats);
305 vfs_maps[NETDATA_VFS_PID].map_fd = bpf_map__fd(obj->maps.tbl_vfs_pid);
306 vfs_maps[NETDATA_VFS_CTRL].map_fd = bpf_map__fd(obj->maps.vfs_ctrl);
307 }
308
309 /**
310 * Load and attach
311 *
312 * Load and attach the eBPF code in kernel.
313 *
314 * @param obj is the main structure for bpf objects.
315 * @param em structure with configuration
316 *
317 * @return it returns 0 on success and -1 otherwise
318 */
319 static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *em)
320 {
321 netdata_ebpf_targets_t *mt = em->targets;
322 netdata_ebpf_program_loaded_t test = mt[NETDATA_EBPF_VFS_WRITE].mode;
323
324 if (test == EBPF_LOAD_TRAMPOLINE) {
325 ebpf_vfs_disable_probes(obj);
326
327 ebpf_vfs_set_trampoline_target(obj);
328 } else {
329 ebpf_vfs_disable_trampoline(obj);
330 }
331
332 ebpf_vfs_adjust_map(obj, em);
333
334 int ret = vfs_bpf__load(obj);
335 if (ret) {
336 return ret;
337 }
338
339 ret = (test == EBPF_LOAD_TRAMPOLINE) ? vfs_bpf__attach(obj) : ebpf_vfs_attach_probe(obj);
340 if (!ret) {
341 ebpf_vfs_set_hash_tables(obj);
342
343 ebpf_update_controller(vfs_maps[NETDATA_VFS_CTRL].map_fd, em);
344 }
345
346 return ret;
347 }
348 #endif
349
350 /*****************************************************************
351 *
352 * FUNCTIONS TO CLOSE THE THREAD
353 *
354 *****************************************************************/
355
356 static void ebpf_obsolete_specific_vfs_charts(char *type, ebpf_module_t *em);
357
358 /**
359 * Obsolete services
360 *
361 * Obsolete all service charts created
362 *
363 * @param em a pointer to `struct ebpf_module`
364 */
365 static void ebpf_obsolete_vfs_services(ebpf_module_t *em, char *id)
366 {
367 ebpf_write_chart_obsolete(
368 id,
369 NETDATA_SYSCALL_APPS_FILE_DELETED,
370 "",
371 "Files deleted",
372 EBPF_COMMON_UNITS_CALLS_PER_SEC,
373 NETDATA_VFS_GROUP,
374 NETDATA_EBPF_CHART_TYPE_STACKED,
375 NETDATA_SYSTEMD_VFS_UNLINK_CONTEXT,
376 20065,
377 em->update_every);
378
379 ebpf_write_chart_obsolete(
380 id,
381 NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS,
382 "",
383 "Write to disk",
384 EBPF_COMMON_UNITS_CALLS_PER_SEC,
385 NETDATA_VFS_GROUP,
386 NETDATA_EBPF_CHART_TYPE_STACKED,
387 NETDATA_SYSTEMD_VFS_WRITE_CONTEXT,
388 20066,
389 em->update_every);
390
391 if (em->mode < MODE_ENTRY) {
392 ebpf_write_chart_obsolete(
393 id,
394 NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR,
395 "",
396 "Fails to write",
397 EBPF_COMMON_UNITS_CALLS_PER_SEC,
398 NETDATA_VFS_GROUP,
399 NETDATA_EBPF_CHART_TYPE_STACKED,
400 NETDATA_SYSTEMD_VFS_WRITE_ERROR_CONTEXT,
401 20067,
402 em->update_every);
403 }
404
405 ebpf_write_chart_obsolete(
406 id,
407 NETDATA_SYSCALL_APPS_VFS_READ_CALLS,
408 "",
409 "Read from disk",
410 EBPF_COMMON_UNITS_CALLS_PER_SEC,
411 NETDATA_VFS_GROUP,
412 NETDATA_EBPF_CHART_TYPE_STACKED,
413 NETDATA_SYSTEMD_VFS_READ_CONTEXT,
414 20068,
415 em->update_every);
416
417 if (em->mode < MODE_ENTRY) {
418 ebpf_write_chart_obsolete(
419 id,
420 NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR,
421 "",
422 "Fails to read",
423 EBPF_COMMON_UNITS_CALLS_PER_SEC,
424 NETDATA_VFS_GROUP,
425 NETDATA_EBPF_CHART_TYPE_STACKED,
426 NETDATA_SYSTEMD_VFS_READ_ERROR_CONTEXT,
427 20069,
428 em->update_every);
429 }
430
431 ebpf_write_chart_obsolete(
432 id,
433 NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES,
434 "",
435 "Bytes written on disk",
436 EBPF_COMMON_UNITS_BYTES,
437 NETDATA_VFS_GROUP,
438 NETDATA_EBPF_CHART_TYPE_STACKED,
439 NETDATA_SYSTEMD_VFS_WRITE_BYTES_CONTEXT,
440 20070,
441 em->update_every);
442
443 ebpf_write_chart_obsolete(
444 id,
445 NETDATA_SYSCALL_APPS_VFS_READ_BYTES,
446 "",
447 "Bytes read from disk",
448 EBPF_COMMON_UNITS_BYTES,
449 NETDATA_VFS_GROUP,
450 NETDATA_EBPF_CHART_TYPE_STACKED,
451 NETDATA_SYSTEMD_VFS_READ_BYTES_CONTEXT,
452 20071,
453 em->update_every);
454
455 ebpf_write_chart_obsolete(
456 id,
457 NETDATA_SYSCALL_APPS_VFS_FSYNC,
458 "",
459 "Calls to vfs_fsync.",
460 EBPF_COMMON_UNITS_CALLS_PER_SEC,
461 NETDATA_VFS_GROUP,
462 NETDATA_EBPF_CHART_TYPE_STACKED,
463 NETDATA_SYSTEMD_VFS_FSYNC_CONTEXT,
464 20072,
465 em->update_every);
466
467 if (em->mode < MODE_ENTRY) {
468 ebpf_write_chart_obsolete(
469 id,
470 NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR,
471 "",
472 "Sync error",
473 EBPF_COMMON_UNITS_CALLS_PER_SEC,
474 NETDATA_VFS_GROUP,
475 NETDATA_EBPF_CHART_TYPE_STACKED,
476 NETDATA_SYSTEMD_VFS_FSYNC_ERROR_CONTEXT,
477 20073,
478 em->update_every);
479 }
480
481 ebpf_write_chart_obsolete(
482 id,
483 NETDATA_SYSCALL_APPS_VFS_OPEN,
484 "",
485 "Calls to vfs_open.",
486 EBPF_COMMON_UNITS_CALLS_PER_SEC,
487 NETDATA_VFS_GROUP,
488 NETDATA_EBPF_CHART_TYPE_STACKED,
489 NETDATA_SYSTEMD_VFS_OPEN_CONTEXT,
490 20074,
491 em->update_every);
492
493 if (em->mode < MODE_ENTRY) {
494 ebpf_write_chart_obsolete(
495 id,
496 NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR,
497 "",
498 "Open error",
499 EBPF_COMMON_UNITS_CALLS_PER_SEC,
500 NETDATA_VFS_GROUP,
501 NETDATA_EBPF_CHART_TYPE_STACKED,
502 NETDATA_SYSTEMD_VFS_OPEN_ERROR_CONTEXT,
503 20075,
504 em->update_every);
505 }
506
507 ebpf_write_chart_obsolete(
508 id,
509 NETDATA_SYSCALL_APPS_VFS_CREATE,
510 "",
511 "Calls to vfs_create.",
512 EBPF_COMMON_UNITS_CALLS_PER_SEC,
513 NETDATA_VFS_GROUP,
514 NETDATA_EBPF_CHART_TYPE_STACKED,
515 NETDATA_SYSTEMD_VFS_CREATE_CONTEXT,
516 20076,
517 em->update_every);
518
519 if (em->mode < MODE_ENTRY) {
520 ebpf_write_chart_obsolete(
521 id,
522 NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR,
523 "",
524 "Create error",
525 EBPF_COMMON_UNITS_CALLS_PER_SEC,
526 NETDATA_VFS_GROUP,
527 NETDATA_EBPF_CHART_TYPE_STACKED,
528 NETDATA_SYSTEMD_VFS_CREATE_ERROR_CONTEXT,
529 20077,
530 em->update_every);
531 }
532 }
533
534 /**
535 * Obsolete cgroup chart
536 *
537 * Send obsolete for all charts created before to close.
538 *
539 * @param em a pointer to `struct ebpf_module`
540 */
541 static inline void ebpf_obsolete_vfs_cgroup_charts(ebpf_module_t *em)
542 {
543 netdata_mutex_lock(&mutex_cgroup_shm);
544
545 ebpf_cgroup_target_t *ect;
546 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
547 if (ect->systemd) {
548 ebpf_obsolete_vfs_services(em, ect->name);
549
550 continue;
551 }
552
553 ebpf_obsolete_specific_vfs_charts(ect->name, em);
554 }
555 netdata_mutex_unlock(&mutex_cgroup_shm);
556 }
557
558 /**
559 * Obsolette apps charts
560 *
561 * Obsolete apps charts.
562 *
563 * @param em a pointer to the structure with the default values.
564 */
565 void ebpf_obsolete_vfs_apps_charts(struct ebpf_module *em)
566 {
567 int order = 20275;
568 struct ebpf_target *w;
569 int update_every = em->update_every;
570 netdata_mutex_lock(&collect_data_mutex);
571 for (w = apps_groups_root_target; w; w = w->next) {
572 if (unlikely(!(w->charts_created & (1 << EBPF_MODULE_VFS_IDX))))
573 continue;
574
575 ebpf_write_chart_obsolete(
576 NETDATA_APP_FAMILY,
577 w->clean_name,
578 "_ebpf_call_vfs_unlink",
579 "Files deleted.",
580 EBPF_COMMON_UNITS_CALLS_PER_SEC,
581 NETDATA_VFS_GROUP,
582 NETDATA_EBPF_CHART_TYPE_STACKED,
583 "app.ebpf_call_vfs_unlink",
584 order++,
585 update_every);
586
587 ebpf_write_chart_obsolete(
588 NETDATA_APP_FAMILY,
589 w->clean_name,
590 "_ebpf_call_vfs_write",
591 "Write to disk.",
592 EBPF_COMMON_UNITS_CALLS_PER_SEC,
593 NETDATA_VFS_GROUP,
594 NETDATA_EBPF_CHART_TYPE_STACKED,
595 "app.ebpf_call_vfs_write",
596 order++,
597 update_every);
598
599 if (em->mode < MODE_ENTRY) {
600 ebpf_write_chart_obsolete(
601 NETDATA_APP_FAMILY,
602 w->clean_name,
603 "_ebpf_call_vfs_write_error",
604 "Fails to write.",
605 EBPF_COMMON_UNITS_CALLS_PER_SEC,
606 NETDATA_VFS_GROUP,
607 NETDATA_EBPF_CHART_TYPE_STACKED,
608 "app.ebpf_call_vfs_write_error",
609 order++,
610 update_every);
611 }
612
613 ebpf_write_chart_obsolete(
614 NETDATA_APP_FAMILY,
615 w->clean_name,
616 "_ebpf_call_vfs_read",
617 "Read from disk.",
618 EBPF_COMMON_UNITS_CALLS_PER_SEC,
619 NETDATA_VFS_GROUP,
620 NETDATA_EBPF_CHART_TYPE_STACKED,
621 "app.ebpf_call_vfs_read",
622 order++,
623 update_every);
624
625 if (em->mode < MODE_ENTRY) {
626 ebpf_write_chart_obsolete(
627 NETDATA_APP_FAMILY,
628 w->clean_name,
629 "_ebpf_call_vfs_read_error",
630 "Fails to read.",
631 EBPF_COMMON_UNITS_CALLS_PER_SEC,
632 NETDATA_VFS_GROUP,
633 NETDATA_EBPF_CHART_TYPE_STACKED,
634 "app.ebpf_call_vfs_read_error",
635 order++,
636 update_every);
637 }
638
639 ebpf_write_chart_obsolete(
640 NETDATA_APP_FAMILY,
641 w->clean_name,
642 "_ebpf_call_vfs_write_bytes",
643 "Bytes written on disk.",
644 EBPF_COMMON_UNITS_BYTES,
645 NETDATA_VFS_GROUP,
646 NETDATA_EBPF_CHART_TYPE_STACKED,
647 "app.ebpf_call_vfs_write_bytes",
648 order++,
649 update_every);
650
651 ebpf_write_chart_obsolete(
652 NETDATA_APP_FAMILY,
653 w->clean_name,
654 "_ebpf_call_vfs_read_bytes",
655 "Bytes read from disk.",
656 EBPF_COMMON_UNITS_BYTES,
657 NETDATA_VFS_GROUP,
658 NETDATA_EBPF_CHART_TYPE_STACKED,
659 "app.ebpf_call_vfs_read_bytes",
660 order++,
661 update_every);
662
663 ebpf_write_chart_obsolete(
664 NETDATA_APP_FAMILY,
665 w->clean_name,
666 "_ebpf_call_vfs_fsync",
667 "Calls to vfs_fsync.",
668 EBPF_COMMON_UNITS_CALLS_PER_SEC,
669 NETDATA_VFS_GROUP,
670 NETDATA_EBPF_CHART_TYPE_STACKED,
671 "app.ebpf_call_vfs_fsync",
672 order++,
673 update_every);
674
675 if (em->mode < MODE_ENTRY) {
676 ebpf_write_chart_obsolete(
677 NETDATA_APP_FAMILY,
678 w->clean_name,
679 "_ebpf_call_vfs_fsync_error",
680 "Fails to sync.",
681 EBPF_COMMON_UNITS_CALLS_PER_SEC,
682 NETDATA_VFS_GROUP,
683 NETDATA_EBPF_CHART_TYPE_STACKED,
684 "app.ebpf_call_vfs_fsync_error",
685 order++,
686 update_every);
687 }
688
689 ebpf_write_chart_obsolete(
690 NETDATA_APP_FAMILY,
691 w->clean_name,
692 "_ebpf_call_vfs_open",
693 "Calls to vfs_open.",
694 EBPF_COMMON_UNITS_CALLS_PER_SEC,
695 NETDATA_VFS_GROUP,
696 NETDATA_EBPF_CHART_TYPE_STACKED,
697 "app.ebpf_call_vfs_open",
698 order++,
699 update_every);
700
701 if (em->mode < MODE_ENTRY) {
702 ebpf_write_chart_obsolete(
703 NETDATA_APP_FAMILY,
704 w->clean_name,
705 "_ebpf_call_vfs_open_error",
706 "Fails to open.",
707 EBPF_COMMON_UNITS_CALLS_PER_SEC,
708 NETDATA_VFS_GROUP,
709 NETDATA_EBPF_CHART_TYPE_STACKED,
710 "app.ebpf_call_vfs_open_error",
711 order++,
712 update_every);
713 }
714
715 ebpf_write_chart_obsolete(
716 NETDATA_APP_FAMILY,
717 w->clean_name,
718 "_ebpf_call_vfs_create",
719 "Calls to vfs_create.",
720 EBPF_COMMON_UNITS_CALLS_PER_SEC,
721 NETDATA_VFS_GROUP,
722 NETDATA_EBPF_CHART_TYPE_STACKED,
723 "app.ebpf_call_vfs_create",
724 order++,
725 update_every);
726
727 if (em->mode < MODE_ENTRY) {
728 ebpf_write_chart_obsolete(
729 NETDATA_APP_FAMILY,
730 w->clean_name,
731 "_ebpf_call_vfs_create_error",
732 "Fails to create.",
733 EBPF_COMMON_UNITS_CALLS_PER_SEC,
734 NETDATA_VFS_GROUP,
735 NETDATA_EBPF_CHART_TYPE_STACKED,
736 "app.ebpf_call_vfs_create_error",
737 order++,
738 update_every);
739 }
740 w->charts_created &= ~(1 << EBPF_MODULE_VFS_IDX);
741 }
742 netdata_mutex_unlock(&collect_data_mutex);
743 }
744
745 /**
746 * Obsolete global
747 *
748 * Obsolete global charts created by thread.
749 *
750 * @param em a pointer to `struct ebpf_module`
751 */
752 static void ebpf_obsolete_vfs_global(ebpf_module_t *em)
753 {
754 ebpf_write_chart_obsolete(
755 NETDATA_FILESYSTEM_FAMILY,
756 NETDATA_VFS_FILE_CLEAN_COUNT,
757 "",
758 "Remove files",
759 EBPF_COMMON_UNITS_CALLS_PER_SEC,
760 NETDATA_VFS_GROUP,
761 NETDATA_EBPF_CHART_TYPE_LINE,
762 "filesystem.vfs_deleted_objects",
763 NETDATA_CHART_PRIO_FILESYSTEM_VFS_CLEAN,
764 em->update_every);
765
766 ebpf_write_chart_obsolete(
767 NETDATA_FILESYSTEM_FAMILY,
768 NETDATA_VFS_FILE_IO_COUNT,
769 "",
770 "Calls to IO",
771 EBPF_COMMON_UNITS_CALLS_PER_SEC,
772 NETDATA_VFS_GROUP,
773 NETDATA_EBPF_CHART_TYPE_LINE,
774 "filesystem.vfs_io",
775 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_COUNT,
776 em->update_every);
777
778 ebpf_write_chart_obsolete(
779 NETDATA_FILESYSTEM_FAMILY,
780 NETDATA_VFS_IO_FILE_BYTES,
781 "",
782 "Bytes written and read",
783 EBPF_COMMON_UNITS_BYTES,
784 NETDATA_VFS_GROUP,
785 NETDATA_EBPF_CHART_TYPE_LINE,
786 "filesystem.vfs_io_bytes",
787 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_BYTES,
788 em->update_every);
789
790 ebpf_write_chart_obsolete(
791 NETDATA_FILESYSTEM_FAMILY,
792 NETDATA_VFS_FSYNC,
793 "",
794 "Calls to vfs_fsync.",
795 EBPF_COMMON_UNITS_CALLS_PER_SEC,
796 NETDATA_VFS_GROUP,
797 NETDATA_EBPF_CHART_TYPE_LINE,
798 "filesystem.vfs_fsync",
799 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_FSYNC,
800 em->update_every);
801
802 ebpf_write_chart_obsolete(
803 NETDATA_FILESYSTEM_FAMILY,
804 NETDATA_VFS_OPEN,
805 "",
806 "Calls to vfs_open.",
807 EBPF_COMMON_UNITS_CALLS_PER_SEC,
808 NETDATA_VFS_GROUP,
809 NETDATA_EBPF_CHART_TYPE_LINE,
810 "filesystem.vfs_open",
811 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_OPEN,
812 em->update_every);
813
814 ebpf_write_chart_obsolete(
815 NETDATA_FILESYSTEM_FAMILY,
816 NETDATA_VFS_CREATE,
817 "",
818 "Calls to vfs_create.",
819 EBPF_COMMON_UNITS_CALLS_PER_SEC,
820 NETDATA_VFS_GROUP,
821 NETDATA_EBPF_CHART_TYPE_LINE,
822 "filesystem.vfs_create",
823 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_CREATE,
824 em->update_every);
825
826 if (em->mode < MODE_ENTRY) {
827 ebpf_write_chart_obsolete(
828 NETDATA_FILESYSTEM_FAMILY,
829 NETDATA_VFS_FILE_ERR_COUNT,
830 "",
831 "Fails to write or read",
832 EBPF_COMMON_UNITS_CALLS_PER_SEC,
833 NETDATA_VFS_GROUP,
834 NETDATA_EBPF_CHART_TYPE_LINE,
835 "filesystem.vfs_io_error",
836 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EBYTES,
837 em->update_every);
838
839 ebpf_write_chart_obsolete(
840 NETDATA_FILESYSTEM_FAMILY,
841 NETDATA_VFS_OPEN_ERR,
842 "",
843 "Fails to open a file",
844 EBPF_COMMON_UNITS_CALLS_PER_SEC,
845 NETDATA_VFS_GROUP,
846 NETDATA_EBPF_CHART_TYPE_LINE,
847 "filesystem.vfs_open_error",
848 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EOPEN,
849 em->update_every);
850
851 ebpf_write_chart_obsolete(
852 NETDATA_FILESYSTEM_FAMILY,
853 NETDATA_VFS_FSYNC_ERR,
854 "",
855 "Fails to synchronize",
856 EBPF_COMMON_UNITS_CALLS_PER_SEC,
857 NETDATA_VFS_GROUP,
858 NETDATA_EBPF_CHART_TYPE_LINE,
859 "filesystem.vfs_fsync_error",
860 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EFSYNC,
861 em->update_every);
862
863 ebpf_write_chart_obsolete(
864 NETDATA_FILESYSTEM_FAMILY,
865 NETDATA_VFS_CREATE_ERR,
866 "",
867 "Fails to create a file.",
868 EBPF_COMMON_UNITS_CALLS_PER_SEC,
869 NETDATA_VFS_GROUP,
870 NETDATA_EBPF_CHART_TYPE_LINE,
871 "filesystem.vfs_create_error",
872 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_ECREATE,
873 em->update_every);
874 }
875 }
876
877 /**
878 * Exit
879 *
880 * Cancel thread and exit.
881 *
882 * @param ptr thread data.
883 **/
884 void ebpf_vfs_unload_bpf(ebpf_module_t *em)
885 {
886 #ifdef LIBBPF_MAJOR_VERSION
887 if (vfs_bpf_obj) {
888 vfs_bpf__destroy(vfs_bpf_obj);
889 vfs_bpf_obj = NULL;
890 }
891 #endif
892 if ((em->load & EBPF_LOAD_LEGACY) && em->probe_links) {
893 ebpf_unload_legacy_code(em->objects, em->probe_links);
894 em->objects = NULL;
895 em->probe_links = NULL;
896 }
897 }
898
899 static void ebpf_vfs_exit(void *pptr)
900 {
901 ebpf_module_t *em = CLEANUP_FUNCTION_GET_PTR(pptr);
902 if (!em)
903 return;
904
905 netdata_mutex_lock(&lock);
906 collect_pids &= ~(1 << EBPF_MODULE_VFS_IDX);
907 netdata_mutex_unlock(&lock);
908
909 if (ebpf_read_vfs.thread)
910 nd_thread_signal_cancel(ebpf_read_vfs.thread);
911
912 // Drop this module's bits from the shared PID pool so its slots don't
913 // stay pinned if the plugin keeps running after the module stops.
914 if (integration_shm && ebpf_shm_sem_wait_or_stop(shm_mutex_ebpf_integration)) {
915 netdata_ebpf_sweep_shm_for_module_unsafe(NETDATA_EBPF_PIDS_VFS_IDX);
916 sem_post(shm_mutex_ebpf_integration);
917 }
918
919 if (ebpf_module_enabled_get(em) == NETDATA_THREAD_EBPF_FUNCTION_RUNNING && !ebpf_plugin_stop()) {
920 netdata_mutex_lock(&lock);
921 if (em->cgroup_charts) {
922 ebpf_obsolete_vfs_cgroup_charts(em);
923 fflush(stdout);
924 }
925
926 if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
927 ebpf_obsolete_vfs_apps_charts(em);
928 }
929
930 ebpf_obsolete_vfs_global(em);
931
932 fflush(stdout);
933 netdata_mutex_unlock(&lock);
934 }
935
936 if (!ebpf_plugin_stop() && em->functions.bpf_unload)
937 em->functions.bpf_unload(em);
938
939 netdata_mutex_lock(&ebpf_exit_cleanup);
940 ebpf_module_enabled_set(em, NETDATA_THREAD_EBPF_STOPPED);
941 netdata_mutex_unlock(&ebpf_exit_cleanup);
942 }
943
944 /*****************************************************************
945 *
946 * FUNCTIONS WITH THE MAIN LOOP
947 *
948 *****************************************************************/
949
950 /**
951 * Send data to Netdata calling auxiliary functions.
952 *
953 * @param em the structure with thread information
954 */
955 static void ebpf_vfs_send_data(ebpf_module_t *em)
956 {
957 netdata_publish_vfs_common_t pvc;
958
959 pvc.write = (long)vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_WRITE].bytes;
960 pvc.read = (long)vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_READ].bytes;
961
962 write_count_chart(
963 NETDATA_VFS_FILE_CLEAN_COUNT,
964 NETDATA_FILESYSTEM_FAMILY,
965 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK],
966 1);
967
968 write_count_chart(
969 NETDATA_VFS_FILE_IO_COUNT, NETDATA_FILESYSTEM_FAMILY, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ], 2);
970
971 if (em->mode < MODE_ENTRY) {
972 write_err_chart(
973 NETDATA_VFS_FILE_ERR_COUNT,
974 NETDATA_FILESYSTEM_FAMILY,
975 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
976 2);
977 }
978
979 write_io_chart(
980 NETDATA_VFS_IO_FILE_BYTES,
981 NETDATA_FILESYSTEM_FAMILY,
982 vfs_id_names[NETDATA_KEY_PUBLISH_VFS_WRITE],
983 (long long)pvc.write,
984 vfs_id_names[NETDATA_KEY_PUBLISH_VFS_READ],
985 (long long)pvc.read);
986
987 write_count_chart(
988 NETDATA_VFS_FSYNC, NETDATA_FILESYSTEM_FAMILY, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC], 1);
989
990 if (em->mode < MODE_ENTRY) {
991 write_err_chart(
992 NETDATA_VFS_FSYNC_ERR, NETDATA_FILESYSTEM_FAMILY, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC], 1);
993 }
994
995 write_count_chart(
996 NETDATA_VFS_OPEN, NETDATA_FILESYSTEM_FAMILY, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN], 1);
997
998 if (em->mode < MODE_ENTRY) {
999 write_err_chart(
1000 NETDATA_VFS_OPEN_ERR, NETDATA_FILESYSTEM_FAMILY, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN], 1);
1001 }
1002
1003 write_count_chart(
1004 NETDATA_VFS_CREATE, NETDATA_FILESYSTEM_FAMILY, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE], 1);
1005
1006 if (em->mode < MODE_ENTRY) {
1007 write_err_chart(
1008 NETDATA_VFS_CREATE_ERR,
1009 NETDATA_FILESYSTEM_FAMILY,
1010 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
1011 1);
1012 }
1013 }
1014
1015 /**
1016 * Read the hash table and store data to allocated vectors.
1017 *
1018 * @param stats vector used to read data from control table.
1019 * @param maps_per_core do I need to read all cores?
1020 */
1021 static void ebpf_vfs_read_global_table(netdata_idx_t *stats, int maps_per_core)
1022 {
1023 netdata_idx_t res[NETDATA_VFS_COUNTER];
1024 ebpf_read_global_table_stats(
1025 res,
1026 vfs_hash_values,
1027 vfs_maps[NETDATA_VFS_ALL].map_fd,
1028 maps_per_core,
1029 NETDATA_KEY_CALLS_VFS_WRITE,
1030 NETDATA_VFS_COUNTER);
1031
1032 ebpf_read_global_table_stats(
1033 stats,
1034 vfs_hash_values,
1035 vfs_maps[NETDATA_VFS_CTRL].map_fd,
1036 maps_per_core,
1037 NETDATA_CONTROLLER_PID_TABLE_ADD,
1038 NETDATA_CONTROLLER_END);
1039
1040 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].ncall = res[NETDATA_KEY_CALLS_VFS_UNLINK];
1041 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].ncall =
1042 res[NETDATA_KEY_CALLS_VFS_READ] + res[NETDATA_KEY_CALLS_VFS_READV];
1043 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].ncall =
1044 res[NETDATA_KEY_CALLS_VFS_WRITE] + res[NETDATA_KEY_CALLS_VFS_WRITEV];
1045 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].ncall = res[NETDATA_KEY_CALLS_VFS_FSYNC];
1046 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].ncall = res[NETDATA_KEY_CALLS_VFS_OPEN];
1047 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].ncall = res[NETDATA_KEY_CALLS_VFS_CREATE];
1048
1049 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].nerr = res[NETDATA_KEY_ERROR_VFS_UNLINK];
1050 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].nerr =
1051 res[NETDATA_KEY_ERROR_VFS_READ] + res[NETDATA_KEY_ERROR_VFS_READV];
1052 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].nerr =
1053 res[NETDATA_KEY_ERROR_VFS_WRITE] + res[NETDATA_KEY_ERROR_VFS_WRITEV];
1054 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].nerr = res[NETDATA_KEY_ERROR_VFS_FSYNC];
1055 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].nerr = res[NETDATA_KEY_ERROR_VFS_OPEN];
1056 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].nerr = res[NETDATA_KEY_ERROR_VFS_CREATE];
1057
1058 vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_WRITE].bytes =
1059 (uint64_t)res[NETDATA_KEY_BYTES_VFS_WRITE] + (uint64_t)res[NETDATA_KEY_BYTES_VFS_WRITEV];
1060 vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_READ].bytes =
1061 (uint64_t)res[NETDATA_KEY_BYTES_VFS_READ] + (uint64_t)res[NETDATA_KEY_BYTES_VFS_READV];
1062 }
1063 /**
1064 * Set VFS
1065 *
1066 * Set vfs structure with values from ebpf structure.
1067 *
1068 * @param vfs the output structure.
1069 * @param w the input data.
1070 */
1071 static inline void vfs_aggregate_set_vfs(netdata_publish_vfs_t *vfs, netdata_ebpf_vfs_t *w)
1072 {
1073 vfs->ct = w->ct;
1074 vfs->write_call = w->write_call;
1075 vfs->writev_call = w->writev_call;
1076 vfs->read_call = w->read_call;
1077 vfs->readv_call = w->readv_call;
1078 vfs->unlink_call = w->unlink_call;
1079 vfs->fsync_call = w->fsync_call;
1080 vfs->open_call = w->open_call;
1081 vfs->create_call = w->create_call;
1082 vfs->write_bytes = w->write_bytes;
1083 vfs->writev_bytes = w->writev_bytes;
1084 vfs->readv_bytes = w->readv_bytes;
1085 vfs->read_bytes = w->read_bytes;
1086 vfs->write_err = w->write_err;
1087 vfs->writev_err = w->writev_err;
1088 vfs->read_err = w->read_err;
1089 vfs->readv_err = w->readv_err;
1090 vfs->unlink_err = w->unlink_err;
1091 vfs->fsync_err = w->fsync_err;
1092 vfs->open_err = w->open_err;
1093 vfs->create_err = w->create_err;
1094 }
1095
1096 /**
1097 * Aggregate Publish VFS
1098 *
1099 * Aggregate data from w source.
1100 *
1101 * @param vfs the output structure.
1102 * @param w the input data.
1103 */
1104 static inline void vfs_aggregate_publish_vfs(netdata_publish_vfs_t *vfs, netdata_publish_vfs_t *w)
1105 {
1106 vfs->ct += w->ct;
1107 vfs->write_bytes += w->write_bytes;
1108 vfs->writev_bytes += w->writev_bytes;
1109 vfs->readv_bytes += w->readv_bytes;
1110 vfs->read_bytes += w->read_bytes;
1111
1112 vfs->write_call += w->write_call;
1113 vfs->writev_call += w->writev_call;
1114 vfs->read_call += w->read_call;
1115 vfs->readv_call += w->readv_call;
1116 vfs->unlink_call += w->unlink_call;
1117 vfs->fsync_call += w->fsync_call;
1118 vfs->open_call += w->open_call;
1119 vfs->create_call += w->create_call;
1120
1121 vfs->write_err += w->write_err;
1122 vfs->writev_err += w->writev_err;
1123 vfs->read_err += w->read_err;
1124 vfs->readv_err += w->readv_err;
1125 vfs->unlink_err += w->unlink_err;
1126 vfs->fsync_err += w->fsync_err;
1127 vfs->open_err += w->open_err;
1128 vfs->create_err += w->create_err;
1129 }
1130
1131 /**
1132 * Sum PIDs
1133 *
1134 * Sum values for all targets.
1135 *
1136 * @param swap output structure
1137 * @param root link list with structure to be used
1138 */
1139 static void ebpf_vfs_sum_pids(netdata_publish_vfs_t *vfs, struct ebpf_pid_on_target *root)
1140 {
1141 memset(vfs, 0, sizeof(netdata_publish_vfs_t));
1142
1143 for (; root; root = root->next) {
1144 uint32_t pid = root->pid;
1145 netdata_ebpf_pid_stats_t *local_pid = netdata_ebpf_lookup_shm_pointer_unsafe(pid);
1146 if (!local_pid || !(local_pid->threads & (1U << (NETDATA_EBPF_PIDS_VFS_IDX << 1))))
1147 continue;
1148
1149 netdata_publish_vfs_t *w = &local_pid->vfs;
1150
1151 vfs_aggregate_publish_vfs(vfs, w);
1152 }
1153 }
1154
1155 /**
1156 * Send data to Netdata calling auxiliary functions.
1157 *
1158 * @param em the structure with thread information
1159 * @param root the target list.
1160 */
1161 void ebpf_vfs_send_apps_data(ebpf_module_t *em, struct ebpf_target *root)
1162 {
1163 struct ebpf_target *w;
1164 netdata_mutex_lock(&collect_data_mutex);
1165 for (w = root; w; w = w->next) {
1166 if (ebpf_plugin_stop())
1167 break;
1168
1169 if (unlikely(!(w->charts_created & (1 << EBPF_MODULE_VFS_IDX))))
1170 continue;
1171
1172 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_unlink");
1173 write_chart_dimension("calls", w->vfs.unlink_call);
1174 ebpf_write_end_chart();
1175
1176 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_write");
1177 write_chart_dimension("calls", w->vfs.write_call + w->vfs.writev_call);
1178 ebpf_write_end_chart();
1179
1180 if (em->mode < MODE_ENTRY) {
1181 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_write_error");
1182 write_chart_dimension("calls", w->vfs.write_err + w->vfs.writev_err);
1183 ebpf_write_end_chart();
1184 }
1185
1186 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_read");
1187 write_chart_dimension("calls", w->vfs.read_call + w->vfs.readv_call);
1188 ebpf_write_end_chart();
1189
1190 if (em->mode < MODE_ENTRY) {
1191 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_read_error");
1192 write_chart_dimension("calls", w->vfs.read_err + w->vfs.readv_err);
1193 ebpf_write_end_chart();
1194 }
1195
1196 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_write_bytes");
1197 write_chart_dimension("writes", w->vfs.write_bytes + w->vfs.writev_bytes);
1198 ebpf_write_end_chart();
1199
1200 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_read_bytes");
1201 write_chart_dimension("reads", w->vfs.read_bytes + w->vfs.readv_bytes);
1202 ebpf_write_end_chart();
1203
1204 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_fsync");
1205 write_chart_dimension("calls", w->vfs.fsync_call);
1206 ebpf_write_end_chart();
1207
1208 if (em->mode < MODE_ENTRY) {
1209 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_fsync_error");
1210 write_chart_dimension("calls", w->vfs.fsync_err);
1211 ebpf_write_end_chart();
1212 }
1213
1214 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_open");
1215 write_chart_dimension("calls", w->vfs.open_call);
1216 ebpf_write_end_chart();
1217
1218 if (em->mode < MODE_ENTRY) {
1219 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_open_error");
1220 write_chart_dimension("calls", w->vfs.open_err);
1221 ebpf_write_end_chart();
1222 }
1223
1224 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_create");
1225 write_chart_dimension("calls", w->vfs.create_call);
1226 ebpf_write_end_chart();
1227
1228 if (em->mode < MODE_ENTRY) {
1229 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_vfs_create_error");
1230 write_chart_dimension("calls", w->vfs.create_err);
1231 ebpf_write_end_chart();
1232 }
1233 }
1234 netdata_mutex_unlock(&collect_data_mutex);
1235 }
1236
1237 /**
1238 * Apps Accumulator
1239 *
1240 * Sum all values read from kernel and store in the first address.
1241 *
1242 * @param out the vector with read values.
1243 */
1244 static void vfs_apps_accumulator(netdata_ebpf_vfs_t *out, int maps_per_core)
1245 {
1246 int i, end = (maps_per_core) ? ebpf_nprocs : 1;
1247 netdata_ebpf_vfs_t *total = &out[0];
1248 uint64_t ct = total->ct;
1249
1250 for (i = 1; i < end; i++) {
1251 if (ebpf_plugin_stop())
1252 break;
1253
1254 netdata_ebpf_vfs_t *w = &out[i];
1255
1256 total->write_bytes += w->write_bytes;
1257 total->writev_bytes += w->writev_bytes;
1258 total->readv_bytes += w->readv_bytes;
1259 total->read_bytes += w->read_bytes;
1260
1261 total->write_call += w->write_call;
1262 total->writev_call += w->writev_call;
1263 total->read_call += w->read_call;
1264 total->readv_call += w->readv_call;
1265 total->unlink_call += w->unlink_call;
1266 total->fsync_call += w->fsync_call;
1267 total->open_call += w->open_call;
1268 total->create_call += w->create_call;
1269
1270 total->write_err += w->write_err;
1271 total->writev_err += w->writev_err;
1272 total->read_err += w->read_err;
1273 total->readv_err += w->readv_err;
1274 total->unlink_err += w->unlink_err;
1275 total->fsync_err += w->fsync_err;
1276 total->open_err += w->open_err;
1277 total->create_err += w->create_err;
1278
1279 if (w->ct > ct)
1280 ct = w->ct;
1281
1282 if (!total->name[0] && w->name[0])
1283 strncpyz(total->name, w->name, sizeof(total->name) - 1);
1284 }
1285
1286 total->ct = ct;
1287 }
1288
1289 /**
1290 * Read the hash table and store data to allocated vectors.
1291 */
1292 static void ebpf_vfs_read_apps(int maps_per_core)
1293 {
1294 netdata_ebpf_vfs_t *vv = vfs_vector;
1295 int fd = vfs_maps[NETDATA_VFS_PID].map_fd;
1296 size_t length = sizeof(netdata_ebpf_vfs_t);
1297 if (maps_per_core)
1298 length *= ebpf_nprocs;
1299
1300 uint32_t key = 0, next_key = 0;
1301 while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
1302 if (ebpf_plugin_stop())
1303 break;
1304
1305 if (bpf_map_lookup_elem(fd, &key, vv) != 0) {
1306 goto end_vfs_loop;
1307 }
1308
1309 vfs_apps_accumulator(vv, maps_per_core);
1310
1311 netdata_ebpf_pid_stats_t *local_pid = netdata_ebpf_get_shm_pointer_unsafe(key, NETDATA_EBPF_PIDS_VFS_IDX);
1312 if (!local_pid)
1313 goto end_vfs_loop;
1314 netdata_publish_vfs_t *publish = &local_pid->vfs;
1315
1316 if (!publish->ct || publish->ct != vv->ct) {
1317 vfs_aggregate_set_vfs(publish, vv);
1318 } else {
1319 if (kill((pid_t)key, 0) == -1 && errno == ESRCH) {
1320 if (netdata_ebpf_reset_shm_pointer_unsafe(fd, key, NETDATA_EBPF_PIDS_VFS_IDX))
1321 memset(publish, 0, sizeof(*publish));
1322 }
1323 }
1324
1325 end_vfs_loop:
1326 // We are cleaning to avoid passing data read from one process to other.
1327 memset(vv, 0, length);
1328 key = next_key;
1329 }
1330 }
1331
1332 /**
1333 * Update cgroup
1334 *
1335 * Update cgroup data based in PID.
1336 *
1337 * @param maps_per_core do I need to read all cores?
1338 */
1339 static void read_update_vfs_cgroup()
1340 {
1341 ebpf_cgroup_target_t *ect;
1342 netdata_mutex_lock(&mutex_cgroup_shm);
1343 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
1344 if (ebpf_plugin_stop())
1345 break;
1346
1347 struct pid_on_target2 *pids;
1348 for (pids = ect->pids; pids; pids = pids->next) {
1349 uint32_t pid = pids->pid;
1350 netdata_publish_vfs_t *out = &pids->vfs;
1351 memset(out, 0, sizeof(netdata_publish_vfs_t));
1352
1353 netdata_ebpf_pid_stats_t *local_pid = netdata_ebpf_lookup_shm_pointer_unsafe(pid);
1354 if (!local_pid || !(local_pid->threads & (1U << (NETDATA_EBPF_PIDS_VFS_IDX << 1))))
1355 continue;
1356 netdata_publish_vfs_t *in = &local_pid->vfs;
1357
1358 vfs_aggregate_publish_vfs(out, in);
1359 }
1360 }
1361 netdata_mutex_unlock(&mutex_cgroup_shm);
1362 }
1363
1364 /**
1365 * Sum PIDs
1366 *
1367 * Sum values for all targets and maintain monotonicity.
1368 *
1369 * @param vfs structure used to store data
1370 * @param pids input data
1371 */
1372 static void ebpf_vfs_sum_cgroup_pids(netdata_publish_vfs_t *vfs, struct pid_on_target2 *pids)
1373 {
1374 netdata_publish_vfs_t accumulator;
1375 memset(&accumulator, 0, sizeof(accumulator));
1376
1377 while (pids) {
1378 netdata_publish_vfs_t *w = &pids->vfs;
1379
1380 accumulator.ct += w->ct;
1381 accumulator.write_bytes += w->write_bytes;
1382 accumulator.writev_bytes += w->writev_bytes;
1383 accumulator.readv_bytes += w->readv_bytes;
1384 accumulator.read_bytes += w->read_bytes;
1385
1386 accumulator.write_call += w->write_call;
1387 accumulator.writev_call += w->writev_call;
1388 accumulator.read_call += w->read_call;
1389 accumulator.readv_call += w->readv_call;
1390 accumulator.unlink_call += w->unlink_call;
1391 accumulator.fsync_call += w->fsync_call;
1392 accumulator.open_call += w->open_call;
1393 accumulator.create_call += w->create_call;
1394
1395 accumulator.write_err += w->write_err;
1396 accumulator.writev_err += w->writev_err;
1397 accumulator.read_err += w->read_err;
1398 accumulator.readv_err += w->readv_err;
1399 accumulator.unlink_err += w->unlink_err;
1400 accumulator.fsync_err += w->fsync_err;
1401 accumulator.open_err += w->open_err;
1402 accumulator.create_err += w->create_err;
1403
1404 pids = pids->next;
1405 }
1406
1407 vfs->ct = (accumulator.ct >= vfs->ct) ? accumulator.ct : vfs->ct;
1408 vfs->write_bytes = (accumulator.write_bytes >= vfs->write_bytes) ? accumulator.write_bytes : vfs->write_bytes;
1409 vfs->writev_bytes = (accumulator.writev_bytes >= vfs->writev_bytes) ? accumulator.writev_bytes : vfs->writev_bytes;
1410 vfs->readv_bytes = (accumulator.readv_bytes >= vfs->readv_bytes) ? accumulator.readv_bytes : vfs->readv_bytes;
1411 vfs->read_bytes = (accumulator.read_bytes >= vfs->read_bytes) ? accumulator.read_bytes : vfs->read_bytes;
1412
1413 vfs->write_call = (accumulator.write_call >= vfs->write_call) ? accumulator.write_call : vfs->write_call;
1414 vfs->writev_call = (accumulator.writev_call >= vfs->writev_call) ? accumulator.writev_call : vfs->writev_call;
1415 vfs->read_call = (accumulator.read_call >= vfs->read_call) ? accumulator.read_call : vfs->read_call;
1416 vfs->readv_call = (accumulator.readv_call >= vfs->readv_call) ? accumulator.readv_call : vfs->readv_call;
1417 vfs->unlink_call = (accumulator.unlink_call >= vfs->unlink_call) ? accumulator.unlink_call : vfs->unlink_call;
1418 vfs->fsync_call = (accumulator.fsync_call >= vfs->fsync_call) ? accumulator.fsync_call : vfs->fsync_call;
1419 vfs->open_call = (accumulator.open_call >= vfs->open_call) ? accumulator.open_call : vfs->open_call;
1420 vfs->create_call = (accumulator.create_call >= vfs->create_call) ? accumulator.create_call : vfs->create_call;
1421
1422 vfs->write_err = (accumulator.write_err >= vfs->write_err) ? accumulator.write_err : vfs->write_err;
1423 vfs->writev_err = (accumulator.writev_err >= vfs->writev_err) ? accumulator.writev_err : vfs->writev_err;
1424 vfs->read_err = (accumulator.read_err >= vfs->read_err) ? accumulator.read_err : vfs->read_err;
1425 vfs->readv_err = (accumulator.readv_err >= vfs->readv_err) ? accumulator.readv_err : vfs->readv_err;
1426 vfs->unlink_err = (accumulator.unlink_err >= vfs->unlink_err) ? accumulator.unlink_err : vfs->unlink_err;
1427 vfs->fsync_err = (accumulator.fsync_err >= vfs->fsync_err) ? accumulator.fsync_err : vfs->fsync_err;
1428 vfs->open_err = (accumulator.open_err >= vfs->open_err) ? accumulator.open_err : vfs->open_err;
1429 vfs->create_err = (accumulator.create_err >= vfs->create_err) ? accumulator.create_err : vfs->create_err;
1430 }
1431
1432 /**
1433 * Create specific VFS charts
1434 *
1435 * Create charts for cgroup/application.
1436 *
1437 * @param type the chart type.
1438 * @param em the main thread structure.
1439 */
1440 static void ebpf_create_specific_vfs_charts(char *type, ebpf_module_t *em)
1441 {
1442 char *label = (!strncmp(type, "cgroup_", 7)) ? &type[7] : type;
1443 ebpf_create_chart(
1444 type,
1445 NETDATA_SYSCALL_APPS_FILE_DELETED,
1446 "Files deleted",
1447 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1448 NETDATA_VFS_GROUP,
1449 NETDATA_CGROUP_VFS_UNLINK_CONTEXT,
1450 NETDATA_EBPF_CHART_TYPE_LINE,
1451 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5500,
1452 ebpf_create_global_dimension,
1453 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK],
1454 1,
1455 em->update_every,
1456 NETDATA_EBPF_MODULE_NAME_VFS);
1457 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1458 ebpf_commit_label();
1459
1460 ebpf_create_chart(
1461 type,
1462 NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS,
1463 "Write to disk",
1464 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1465 NETDATA_VFS_GROUP,
1466 NETDATA_CGROUP_VFS_WRITE_CONTEXT,
1467 NETDATA_EBPF_CHART_TYPE_LINE,
1468 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5501,
1469 ebpf_create_global_dimension,
1470 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
1471 1,
1472 em->update_every,
1473 NETDATA_EBPF_MODULE_NAME_VFS);
1474 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1475 ebpf_commit_label();
1476
1477 if (em->mode < MODE_ENTRY) {
1478 ebpf_create_chart(
1479 type,
1480 NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR,
1481 "Fails to write",
1482 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1483 NETDATA_VFS_GROUP,
1484 NETDATA_CGROUP_VFS_WRITE_ERROR_CONTEXT,
1485 NETDATA_EBPF_CHART_TYPE_LINE,
1486 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5502,
1487 ebpf_create_global_dimension,
1488 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
1489 1,
1490 em->update_every,
1491 NETDATA_EBPF_MODULE_NAME_VFS);
1492 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1493 ebpf_commit_label();
1494 }
1495
1496 ebpf_create_chart(
1497 type,
1498 NETDATA_SYSCALL_APPS_VFS_READ_CALLS,
1499 "Read from disk",
1500 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1501 NETDATA_VFS_GROUP,
1502 NETDATA_CGROUP_VFS_READ_CONTEXT,
1503 NETDATA_EBPF_CHART_TYPE_LINE,
1504 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5503,
1505 ebpf_create_global_dimension,
1506 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
1507 1,
1508 em->update_every,
1509 NETDATA_EBPF_MODULE_NAME_VFS);
1510 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1511 ebpf_commit_label();
1512
1513 if (em->mode < MODE_ENTRY) {
1514 ebpf_create_chart(
1515 type,
1516 NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR,
1517 "Fails to read",
1518 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1519 NETDATA_VFS_GROUP,
1520 NETDATA_CGROUP_VFS_READ_ERROR_CONTEXT,
1521 NETDATA_EBPF_CHART_TYPE_LINE,
1522 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5504,
1523 ebpf_create_global_dimension,
1524 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
1525 1,
1526 em->update_every,
1527 NETDATA_EBPF_MODULE_NAME_VFS);
1528 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1529 ebpf_commit_label();
1530 }
1531
1532 ebpf_create_chart(
1533 type,
1534 NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES,
1535 "Bytes written on disk",
1536 EBPF_COMMON_UNITS_BYTES,
1537 NETDATA_VFS_GROUP,
1538 NETDATA_CGROUP_VFS_WRITE_BYTES_CONTEXT,
1539 NETDATA_EBPF_CHART_TYPE_LINE,
1540 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5505,
1541 ebpf_create_global_dimension,
1542 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
1543 1,
1544 em->update_every,
1545 NETDATA_EBPF_MODULE_NAME_VFS);
1546 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1547 ebpf_commit_label();
1548
1549 ebpf_create_chart(
1550 type,
1551 NETDATA_SYSCALL_APPS_VFS_READ_BYTES,
1552 "Bytes read from disk",
1553 EBPF_COMMON_UNITS_BYTES,
1554 NETDATA_VFS_GROUP,
1555 NETDATA_CGROUP_VFS_READ_BYTES_CONTEXT,
1556 NETDATA_EBPF_CHART_TYPE_LINE,
1557 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5506,
1558 ebpf_create_global_dimension,
1559 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
1560 1,
1561 em->update_every,
1562 NETDATA_EBPF_MODULE_NAME_VFS);
1563 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1564 ebpf_commit_label();
1565
1566 ebpf_create_chart(
1567 type,
1568 NETDATA_SYSCALL_APPS_VFS_FSYNC,
1569 "Calls to vfs_fsync.",
1570 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1571 NETDATA_VFS_GROUP,
1572 NETDATA_CGROUP_VFS_FSYNC_CONTEXT,
1573 NETDATA_EBPF_CHART_TYPE_LINE,
1574 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5507,
1575 ebpf_create_global_dimension,
1576 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
1577 1,
1578 em->update_every,
1579 NETDATA_EBPF_MODULE_NAME_VFS);
1580 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1581 ebpf_commit_label();
1582
1583 if (em->mode < MODE_ENTRY) {
1584 ebpf_create_chart(
1585 type,
1586 NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR,
1587 "Sync error",
1588 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1589 NETDATA_VFS_GROUP,
1590 NETDATA_CGROUP_VFS_FSYNC_ERROR_CONTEXT,
1591 NETDATA_EBPF_CHART_TYPE_LINE,
1592 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5508,
1593 ebpf_create_global_dimension,
1594 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
1595 1,
1596 em->update_every,
1597 NETDATA_EBPF_MODULE_NAME_VFS);
1598 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1599 ebpf_commit_label();
1600 }
1601
1602 ebpf_create_chart(
1603 type,
1604 NETDATA_SYSCALL_APPS_VFS_OPEN,
1605 "Calls to vfs_open.",
1606 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1607 NETDATA_VFS_GROUP,
1608 NETDATA_CGROUP_VFS_OPEN_CONTEXT,
1609 NETDATA_EBPF_CHART_TYPE_LINE,
1610 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5509,
1611 ebpf_create_global_dimension,
1612 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
1613 1,
1614 em->update_every,
1615 NETDATA_EBPF_MODULE_NAME_VFS);
1616 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1617 ebpf_commit_label();
1618
1619 if (em->mode < MODE_ENTRY) {
1620 ebpf_create_chart(
1621 type,
1622 NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR,
1623 "Open error",
1624 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1625 NETDATA_VFS_GROUP,
1626 NETDATA_CGROUP_VFS_OPEN_ERROR_CONTEXT,
1627 NETDATA_EBPF_CHART_TYPE_LINE,
1628 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5510,
1629 ebpf_create_global_dimension,
1630 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
1631 1,
1632 em->update_every,
1633 NETDATA_EBPF_MODULE_NAME_VFS);
1634 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1635 ebpf_commit_label();
1636 }
1637
1638 ebpf_create_chart(
1639 type,
1640 NETDATA_SYSCALL_APPS_VFS_CREATE,
1641 "Calls to vfs_create.",
1642 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1643 NETDATA_VFS_GROUP,
1644 NETDATA_CGROUP_VFS_CREATE_CONTEXT,
1645 NETDATA_EBPF_CHART_TYPE_LINE,
1646 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5511,
1647 ebpf_create_global_dimension,
1648 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
1649 1,
1650 em->update_every,
1651 NETDATA_EBPF_MODULE_NAME_VFS);
1652 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1653 ebpf_commit_label();
1654
1655 if (em->mode < MODE_ENTRY) {
1656 ebpf_create_chart(
1657 type,
1658 NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR,
1659 "Create error",
1660 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1661 NETDATA_VFS_GROUP,
1662 NETDATA_CGROUP_VFS_CREATE_ERROR_CONTEXT,
1663 NETDATA_EBPF_CHART_TYPE_LINE,
1664 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5512,
1665 ebpf_create_global_dimension,
1666 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
1667 1,
1668 em->update_every,
1669 NETDATA_EBPF_MODULE_NAME_VFS);
1670 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
1671 ebpf_commit_label();
1672 }
1673 }
1674
1675 /**
1676 * Obsolete specific VFS charts
1677 *
1678 * Obsolete charts for cgroup/application.
1679 *
1680 * @param type the chart type.
1681 * @param em the main thread structure.
1682 */
1683 static void ebpf_obsolete_specific_vfs_charts(char *type, ebpf_module_t *em)
1684 {
1685 ebpf_write_chart_obsolete(
1686 type,
1687 NETDATA_SYSCALL_APPS_FILE_DELETED,
1688 "",
1689 "Files deleted",
1690 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1691 NETDATA_VFS_GROUP,
1692 NETDATA_EBPF_CHART_TYPE_LINE,
1693 NETDATA_CGROUP_VFS_UNLINK_CONTEXT,
1694 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5500,
1695 em->update_every);
1696
1697 ebpf_write_chart_obsolete(
1698 type,
1699 NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS,
1700 "",
1701 "Write to disk",
1702 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1703 NETDATA_VFS_GROUP,
1704 NETDATA_EBPF_CHART_TYPE_LINE,
1705 NETDATA_CGROUP_VFS_WRITE_CONTEXT,
1706 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5501,
1707 em->update_every);
1708
1709 if (em->mode < MODE_ENTRY) {
1710 ebpf_write_chart_obsolete(
1711 type,
1712 NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR,
1713 "",
1714 "Fails to write",
1715 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1716 NETDATA_VFS_GROUP,
1717 NETDATA_EBPF_CHART_TYPE_LINE,
1718 NETDATA_CGROUP_VFS_WRITE_ERROR_CONTEXT,
1719 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5502,
1720 em->update_every);
1721 }
1722
1723 ebpf_write_chart_obsolete(
1724 type,
1725 NETDATA_SYSCALL_APPS_VFS_READ_CALLS,
1726 "",
1727 "Read from disk",
1728 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1729 NETDATA_VFS_GROUP,
1730 NETDATA_EBPF_CHART_TYPE_LINE,
1731 NETDATA_CGROUP_VFS_READ_CONTEXT,
1732 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5503,
1733 em->update_every);
1734
1735 if (em->mode < MODE_ENTRY) {
1736 ebpf_write_chart_obsolete(
1737 type,
1738 NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR,
1739 "",
1740 "Fails to read",
1741 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1742 NETDATA_VFS_GROUP,
1743 NETDATA_EBPF_CHART_TYPE_LINE,
1744 NETDATA_CGROUP_VFS_READ_ERROR_CONTEXT,
1745 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5504,
1746 em->update_every);
1747 }
1748
1749 ebpf_write_chart_obsolete(
1750 type,
1751 NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES,
1752 "",
1753 "Bytes written on disk",
1754 EBPF_COMMON_UNITS_BYTES,
1755 NETDATA_VFS_GROUP,
1756 NETDATA_EBPF_CHART_TYPE_LINE,
1757 NETDATA_CGROUP_VFS_WRITE_BYTES_CONTEXT,
1758 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5505,
1759 em->update_every);
1760
1761 ebpf_write_chart_obsolete(
1762 type,
1763 NETDATA_SYSCALL_APPS_VFS_READ_BYTES,
1764 "",
1765 "Bytes read from disk",
1766 EBPF_COMMON_UNITS_BYTES,
1767 NETDATA_VFS_GROUP,
1768 NETDATA_EBPF_CHART_TYPE_LINE,
1769 NETDATA_CGROUP_VFS_READ_BYTES_CONTEXT,
1770 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5506,
1771 em->update_every);
1772
1773 ebpf_write_chart_obsolete(
1774 type,
1775 NETDATA_SYSCALL_APPS_VFS_FSYNC,
1776 "",
1777 "Calls to vfs_fsync.",
1778 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1779 NETDATA_VFS_GROUP,
1780 NETDATA_EBPF_CHART_TYPE_LINE,
1781 NETDATA_CGROUP_VFS_FSYNC_CONTEXT,
1782 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5507,
1783 em->update_every);
1784
1785 if (em->mode < MODE_ENTRY) {
1786 ebpf_write_chart_obsolete(
1787 type,
1788 NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR,
1789 "",
1790 "Sync error",
1791 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1792 NETDATA_VFS_GROUP,
1793 NETDATA_EBPF_CHART_TYPE_LINE,
1794 NETDATA_CGROUP_VFS_FSYNC_ERROR_CONTEXT,
1795 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5508,
1796 em->update_every);
1797 }
1798
1799 ebpf_write_chart_obsolete(
1800 type,
1801 NETDATA_SYSCALL_APPS_VFS_OPEN,
1802 "",
1803 "Calls to vfs_open.",
1804 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1805 NETDATA_VFS_GROUP,
1806 NETDATA_EBPF_CHART_TYPE_LINE,
1807 NETDATA_CGROUP_VFS_OPEN_CONTEXT,
1808 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5509,
1809 em->update_every);
1810
1811 if (em->mode < MODE_ENTRY) {
1812 ebpf_write_chart_obsolete(
1813 type,
1814 NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR,
1815 "",
1816 "Open error",
1817 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1818 NETDATA_VFS_GROUP,
1819 NETDATA_EBPF_CHART_TYPE_LINE,
1820 NETDATA_CGROUP_VFS_OPEN_ERROR_CONTEXT,
1821 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5510,
1822 em->update_every);
1823 }
1824
1825 ebpf_write_chart_obsolete(
1826 type,
1827 NETDATA_SYSCALL_APPS_VFS_CREATE,
1828 "",
1829 "Calls to vfs_create.",
1830 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1831 NETDATA_VFS_GROUP,
1832 NETDATA_EBPF_CHART_TYPE_LINE,
1833 NETDATA_CGROUP_VFS_CREATE_CONTEXT,
1834 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5511,
1835 em->update_every);
1836
1837 if (em->mode < MODE_ENTRY) {
1838 ebpf_write_chart_obsolete(
1839 type,
1840 NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR,
1841 "",
1842 "Create error",
1843 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1844 NETDATA_VFS_GROUP,
1845 NETDATA_EBPF_CHART_TYPE_LINE,
1846 NETDATA_CGROUP_VFS_CREATE_ERROR_CONTEXT,
1847 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5512,
1848 em->update_every);
1849 }
1850 }
1851
1852 /*
1853 * Send specific VFS data
1854 *
1855 * Send data for specific cgroup/apps.
1856 *
1857 * @param type chart type
1858 * @param values structure with values that will be sent to netdata
1859 */
1860 static void ebpf_send_specific_vfs_data(char *type, netdata_publish_vfs_t *values, ebpf_module_t *em)
1861 {
1862 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_DELETED, "");
1863 write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].name, (long long)values->unlink_call);
1864 ebpf_write_end_chart();
1865
1866 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "");
1867 write_chart_dimension(
1868 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
1869 (long long)values->write_call + (long long)values->writev_call);
1870 ebpf_write_end_chart();
1871
1872 if (em->mode < MODE_ENTRY) {
1873 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "");
1874 write_chart_dimension(
1875 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
1876 (long long)values->write_err + (long long)values->writev_err);
1877 ebpf_write_end_chart();
1878 }
1879
1880 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "");
1881 write_chart_dimension(
1882 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
1883 (long long)values->read_call + (long long)values->readv_call);
1884 ebpf_write_end_chart();
1885
1886 if (em->mode < MODE_ENTRY) {
1887 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "");
1888 write_chart_dimension(
1889 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
1890 (long long)values->read_err + (long long)values->readv_err);
1891 ebpf_write_end_chart();
1892 }
1893
1894 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "");
1895 write_chart_dimension(
1896 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
1897 (long long)values->write_bytes + (long long)values->writev_bytes);
1898 ebpf_write_end_chart();
1899
1900 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "");
1901 write_chart_dimension(
1902 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
1903 (long long)values->read_bytes + (long long)values->readv_bytes);
1904 ebpf_write_end_chart();
1905
1906 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC, "");
1907 write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].name, (long long)values->fsync_call);
1908 ebpf_write_end_chart();
1909
1910 if (em->mode < MODE_ENTRY) {
1911 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "");
1912 write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].name, (long long)values->fsync_err);
1913 ebpf_write_end_chart();
1914 }
1915
1916 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN, "");
1917 write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].name, (long long)values->open_call);
1918 ebpf_write_end_chart();
1919
1920 if (em->mode < MODE_ENTRY) {
1921 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "");
1922 write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].name, (long long)values->open_err);
1923 ebpf_write_end_chart();
1924 }
1925
1926 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE, "");
1927 write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].name, (long long)values->create_call);
1928 ebpf_write_end_chart();
1929
1930 if (em->mode < MODE_ENTRY) {
1931 ebpf_write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "");
1932 write_chart_dimension(
1933 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].name, (long long)values->create_err);
1934 ebpf_write_end_chart();
1935 }
1936 }
1937
1938 /**
1939 * Create Systemd Socket Charts
1940 *
1941 * Create charts when systemd is enabled
1942 *
1943 * @param em the main collector structure
1944 **/
1945 static void ebpf_create_systemd_vfs_charts(ebpf_module_t *em)
1946 {
1947 static ebpf_systemd_args_t data_vfs_unlink = {
1948 .title = "Files deleted",
1949 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
1950 .family = NETDATA_VFS_GROUP,
1951 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
1952 .order = 20065,
1953 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
1954 .context = NETDATA_SYSTEMD_VFS_UNLINK_CONTEXT,
1955 .module = NETDATA_EBPF_MODULE_NAME_VFS,
1956 .update_every = 0,
1957 .suffix = NETDATA_SYSCALL_APPS_FILE_DELETED,
1958 .dimension = "calls"};
1959
1960 static ebpf_systemd_args_t data_vfs_write = {
1961 .title = "Write to disk",
1962 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
1963 .family = NETDATA_VFS_GROUP,
1964 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
1965 .order = 20066,
1966 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
1967 .context = NETDATA_SYSTEMD_VFS_WRITE_CONTEXT,
1968 .module = NETDATA_EBPF_MODULE_NAME_VFS,
1969 .update_every = 0,
1970 .suffix = NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS,
1971 .dimension = "calls"};
1972
1973 static ebpf_systemd_args_t data_vfs_write_err = {
1974 .title = "Fails to write",
1975 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
1976 .family = NETDATA_VFS_GROUP,
1977 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
1978 .order = 20067,
1979 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
1980 .context = NETDATA_SYSTEMD_VFS_WRITE_ERROR_CONTEXT,
1981 .module = NETDATA_EBPF_MODULE_NAME_VFS,
1982 .update_every = 0,
1983 .suffix = NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR,
1984 .dimension = "calls"};
1985
1986 static ebpf_systemd_args_t data_vfs_read = {
1987 .title = "Read from disk",
1988 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
1989 .family = NETDATA_VFS_GROUP,
1990 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
1991 .order = 20068,
1992 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
1993 .context = NETDATA_SYSTEMD_VFS_READ_CONTEXT,
1994 .module = NETDATA_EBPF_MODULE_NAME_VFS,
1995 .update_every = 0,
1996 .suffix = NETDATA_SYSCALL_APPS_VFS_READ_CALLS,
1997 .dimension = "calls"};
1998
1999 static ebpf_systemd_args_t data_vfs_read_err = {
2000 .title = "Fails to read",
2001 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2002 .family = NETDATA_VFS_GROUP,
2003 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2004 .order = 20069,
2005 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2006 .context = NETDATA_SYSTEMD_VFS_READ_ERROR_CONTEXT,
2007 .module = NETDATA_EBPF_MODULE_NAME_VFS,
2008 .update_every = 0,
2009 .suffix = NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR,
2010 .dimension = "calls"};
2011
2012 static ebpf_systemd_args_t data_vfs_write_bytes = {
2013 .title = "Bytes written on disk",
2014 .units = EBPF_COMMON_UNITS_BYTES,
2015 .family = NETDATA_VFS_GROUP,
2016 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2017 .order = 20070,
2018 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2019 .context = NETDATA_SYSTEMD_VFS_WRITE_BYTES_CONTEXT,
2020 .module = NETDATA_EBPF_MODULE_NAME_VFS,
2021 .update_every = 0,
2022 .suffix = NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES,
2023 .dimension = "bytes"};
2024
2025 static ebpf_systemd_args_t data_vfs_read_bytes = {
2026 .title = "Bytes read from disk",
2027 .units = EBPF_COMMON_UNITS_BYTES,
2028 .family = NETDATA_VFS_GROUP,
2029 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2030 .order = 20071,
2031 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2032 .context = NETDATA_SYSTEMD_VFS_READ_BYTES_CONTEXT,
2033 .module = NETDATA_EBPF_MODULE_NAME_VFS,
2034 .update_every = 0,
2035 .suffix = NETDATA_SYSCALL_APPS_VFS_READ_BYTES,
2036 .dimension = "bytes"};
2037
2038 static ebpf_systemd_args_t data_vfs_fsync = {
2039 .title = "Calls to vfs_fsync.",
2040 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2041 .family = NETDATA_VFS_GROUP,
2042 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2043 .order = 20072,
2044 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2045 .context = NETDATA_SYSTEMD_VFS_FSYNC_CONTEXT,
2046 .module = NETDATA_EBPF_MODULE_NAME_VFS,
2047 .update_every = 0,
2048 .suffix = NETDATA_SYSCALL_APPS_VFS_FSYNC,
2049 .dimension = "calls"};
2050
2051 static ebpf_systemd_args_t data_vfs_fsync_err = {
2052 .title = "Sync error",
2053 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2054 .family = NETDATA_VFS_GROUP,
2055 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2056 .order = 20073,
2057 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2058 .context = NETDATA_SYSTEMD_VFS_FSYNC_ERROR_CONTEXT,
2059 .module = NETDATA_EBPF_MODULE_NAME_VFS,
2060 .update_every = 0,
2061 .suffix = NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR,
2062 .dimension = "calls"};
2063
2064 static ebpf_systemd_args_t data_vfs_open = {
2065 .title = "Calls to vfs_open.",
2066 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2067 .family = NETDATA_VFS_GROUP,
2068 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2069 .order = 20074,
2070 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2071 .context = NETDATA_SYSTEMD_VFS_OPEN_CONTEXT,
2072 .module = NETDATA_EBPF_MODULE_NAME_VFS,
2073 .update_every = 0,
2074 .suffix = NETDATA_SYSCALL_APPS_VFS_OPEN,
2075 .dimension = "calls"};
2076
2077 static ebpf_systemd_args_t data_vfs_open_err = {
2078 .title = "Open error",
2079 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2080 .family = NETDATA_VFS_GROUP,
2081 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2082 .order = 20075,
2083 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2084 .context = NETDATA_SYSTEMD_VFS_OPEN_ERROR_CONTEXT,
2085 .module = NETDATA_EBPF_MODULE_NAME_VFS,
2086 .update_every = 0,
2087 .suffix = NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR,
2088 .dimension = "calls"};
2089
2090 static ebpf_systemd_args_t data_vfs_create = {
2091 .title = "Calls to vfs_create.",
2092 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2093 .family = NETDATA_VFS_GROUP,
2094 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2095 .order = 20076,
2096 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2097 .context = NETDATA_SYSTEMD_VFS_CREATE_CONTEXT,
2098 .module = NETDATA_EBPF_MODULE_NAME_VFS,
2099 .update_every = 0,
2100 .suffix = NETDATA_SYSCALL_APPS_VFS_CREATE,
2101 .dimension = "calls"};
2102
2103 static ebpf_systemd_args_t data_vfs_create_err = {
2104 .title = "Create error",
2105 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2106 .family = NETDATA_VFS_GROUP,
2107 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2108 .order = 20077,
2109 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2110 .context = NETDATA_SYSTEMD_VFS_CREATE_ERROR_CONTEXT,
2111 .module = NETDATA_EBPF_MODULE_NAME_VFS,
2112 .update_every = 0,
2113 .suffix = NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR,
2114 .dimension = "calls"};
2115
2116 if (!data_vfs_create.update_every)
2117 data_vfs_unlink.update_every = data_vfs_write.update_every = data_vfs_write_err.update_every =
2118 data_vfs_read.update_every = data_vfs_read_err.update_every = data_vfs_write_bytes.update_every =
2119 data_vfs_read_bytes.update_every = data_vfs_fsync.update_every = data_vfs_fsync_err.update_every =
2120 data_vfs_open.update_every = data_vfs_open_err.update_every = data_vfs_create.update_every =
2121 data_vfs_create_err.update_every = em->update_every;
2122
2123 ebpf_cgroup_target_t *w;
2124 for (w = ebpf_cgroup_pids; w; w = w->next) {
2125 if (ebpf_plugin_stop())
2126 break;
2127
2128 if (unlikely(!w->systemd || w->flags & NETDATA_EBPF_SERVICES_HAS_VFS_CHART))
2129 continue;
2130
2131 data_vfs_unlink.id = data_vfs_write.id = data_vfs_write_err.id = data_vfs_read.id = data_vfs_read_err.id =
2132 data_vfs_write_bytes.id = data_vfs_read_bytes.id = data_vfs_fsync.id = data_vfs_fsync_err.id =
2133 data_vfs_open.id = data_vfs_open_err.id = data_vfs_create.id = data_vfs_create_err.id = w->name;
2134 ebpf_create_charts_on_systemd(&data_vfs_unlink);
2135
2136 ebpf_create_charts_on_systemd(&data_vfs_write);
2137
2138 ebpf_create_charts_on_systemd(&data_vfs_read);
2139
2140 ebpf_create_charts_on_systemd(&data_vfs_write_bytes);
2141
2142 ebpf_create_charts_on_systemd(&data_vfs_read_bytes);
2143
2144 ebpf_create_charts_on_systemd(&data_vfs_fsync);
2145
2146 ebpf_create_charts_on_systemd(&data_vfs_open);
2147
2148 ebpf_create_charts_on_systemd(&data_vfs_create);
2149 if (em->mode < MODE_ENTRY) {
2150 ebpf_create_charts_on_systemd(&data_vfs_write_err);
2151 ebpf_create_charts_on_systemd(&data_vfs_read_err);
2152 ebpf_create_charts_on_systemd(&data_vfs_fsync_err);
2153 ebpf_create_charts_on_systemd(&data_vfs_open_err);
2154 ebpf_create_charts_on_systemd(&data_vfs_create_err);
2155 }
2156
2157 w->flags |= NETDATA_EBPF_SERVICES_HAS_VFS_CHART;
2158 }
2159 }
2160
2161 /**
2162 * Send Systemd charts
2163 *
2164 * Send collected data to Netdata.
2165 *
2166 * @param em the main collector structure
2167 */
2168 static void ebpf_send_systemd_vfs_charts(ebpf_module_t *em)
2169 {
2170 ebpf_cgroup_target_t *ect;
2171 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
2172 if (ebpf_plugin_stop())
2173 break;
2174
2175 if (unlikely(!(ect->flags & NETDATA_EBPF_SERVICES_HAS_VFS_CHART))) {
2176 continue;
2177 }
2178
2179 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_FILE_DELETED, "");
2180 write_chart_dimension("calls", ect->publish_systemd_vfs.unlink_call);
2181 ebpf_write_end_chart();
2182
2183 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "");
2184 write_chart_dimension("calls", ect->publish_systemd_vfs.write_call + ect->publish_systemd_vfs.writev_call);
2185 ebpf_write_end_chart();
2186
2187 if (em->mode < MODE_ENTRY) {
2188 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "");
2189 write_chart_dimension("calls", ect->publish_systemd_vfs.write_err + ect->publish_systemd_vfs.writev_err);
2190 ebpf_write_end_chart();
2191 }
2192
2193 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "");
2194 write_chart_dimension("calls", ect->publish_systemd_vfs.read_call + ect->publish_systemd_vfs.readv_call);
2195 ebpf_write_end_chart();
2196
2197 if (em->mode < MODE_ENTRY) {
2198 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "");
2199 write_chart_dimension("calls", ect->publish_systemd_vfs.read_err + ect->publish_systemd_vfs.readv_err);
2200 ebpf_write_end_chart();
2201 }
2202
2203 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "");
2204 write_chart_dimension("bytes", ect->publish_systemd_vfs.write_bytes + ect->publish_systemd_vfs.writev_bytes);
2205 ebpf_write_end_chart();
2206
2207 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "");
2208 write_chart_dimension("bytes", ect->publish_systemd_vfs.read_bytes + ect->publish_systemd_vfs.readv_bytes);
2209 ebpf_write_end_chart();
2210
2211 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_FSYNC, "");
2212 write_chart_dimension("calls", ect->publish_systemd_vfs.fsync_call);
2213 ebpf_write_end_chart();
2214
2215 if (em->mode < MODE_ENTRY) {
2216 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "");
2217 write_chart_dimension("calls", ect->publish_systemd_vfs.fsync_err);
2218 ebpf_write_end_chart();
2219 }
2220
2221 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_OPEN, "");
2222 write_chart_dimension("calls", ect->publish_systemd_vfs.open_call);
2223 ebpf_write_end_chart();
2224
2225 if (em->mode < MODE_ENTRY) {
2226 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "");
2227 write_chart_dimension("calls", ect->publish_systemd_vfs.open_err);
2228 ebpf_write_end_chart();
2229 }
2230
2231 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_CREATE, "");
2232 write_chart_dimension("calls", ect->publish_systemd_vfs.create_call);
2233 ebpf_write_end_chart();
2234
2235 if (em->mode < MODE_ENTRY) {
2236 ebpf_write_begin_chart(ect->name, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "");
2237 write_chart_dimension("calls", ect->publish_systemd_vfs.create_err);
2238 ebpf_write_end_chart();
2239 }
2240 }
2241 }
2242
2243 /**
2244 * Send data to Netdata calling auxiliary functions.
2245 *
2246 * @param em the main collector structure
2247 */
2248 static void ebpf_vfs_send_cgroup_data(ebpf_module_t *em)
2249 {
2250 netdata_mutex_lock(&mutex_cgroup_shm);
2251 ebpf_cgroup_target_t *ect;
2252 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
2253 ebpf_vfs_sum_cgroup_pids(&ect->publish_systemd_vfs, ect->pids);
2254 }
2255
2256 if (ebpf_plugin_stop()) {
2257 netdata_mutex_unlock(&mutex_cgroup_shm);
2258 return;
2259 }
2260
2261 if (ebpf_cgroup_systemd_enabled_get()) {
2262 if (ebpf_send_cgroup_chart_get()) {
2263 ebpf_create_systemd_vfs_charts(em);
2264 }
2265 ebpf_send_systemd_vfs_charts(em);
2266 }
2267
2268 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
2269 if (ebpf_plugin_stop())
2270 break;
2271
2272 if (ect->systemd)
2273 continue;
2274
2275 if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_VFS_CHART) && ect->updated) {
2276 ebpf_create_specific_vfs_charts(ect->name, em);
2277 ect->flags |= NETDATA_EBPF_CGROUP_HAS_VFS_CHART;
2278 }
2279
2280 if (ect->flags & NETDATA_EBPF_CGROUP_HAS_VFS_CHART) {
2281 if (ect->updated) {
2282 ebpf_send_specific_vfs_data(ect->name, &ect->publish_systemd_vfs, em);
2283 } else {
2284 ebpf_obsolete_specific_vfs_charts(ect->name, em);
2285 ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_VFS_CHART;
2286 }
2287 }
2288 }
2289
2290 netdata_mutex_unlock(&mutex_cgroup_shm);
2291 }
2292
2293 /**
2294 * Resume apps data
2295 */
2296 void ebpf_vfs_resume_apps_data()
2297 {
2298 struct ebpf_target *w;
2299 netdata_mutex_lock(&collect_data_mutex);
2300 for (w = apps_groups_root_target; w; w = w->next) {
2301 if (ebpf_plugin_stop())
2302 break;
2303
2304 if (unlikely(!(w->charts_created & (1 << EBPF_MODULE_VFS_IDX))))
2305 continue;
2306
2307 ebpf_vfs_sum_pids(&w->vfs, w->root_pid);
2308 }
2309 netdata_mutex_unlock(&collect_data_mutex);
2310 }
2311
2312 /**
2313 * VFS thread
2314 *
2315 * Thread used to generate charts.
2316 *
2317 * @param ptr a pointer to `struct ebpf_module`
2318 *
2319 * @return It always return NULL
2320 */
2321 void ebpf_read_vfs_thread(void *ptr)
2322 {
2323 ebpf_module_t *em = (ebpf_module_t *)ptr;
2324
2325 int maps_per_core = em->maps_per_core;
2326 int update_every = em->update_every;
2327 int collect_pid = (em->apps_charts || em->cgroup_charts);
2328 if (!collect_pid)
2329 return;
2330
2331 int counter = update_every - 1;
2332
2333 uint32_t lifetime = em->lifetime;
2334 int cgroups = em->cgroup_charts;
2335 uint32_t running_time = 0;
2336 ebpf_set_pid_map_fd(NETDATA_EBPF_PIDS_VFS_IDX, vfs_maps[NETDATA_VFS_PID].map_fd);
2337 heartbeat_t hb;
2338 heartbeat_init(&hb, USEC_PER_SEC);
2339 while (!ebpf_plugin_stop() && running_time < lifetime) {
2340 if (ebpf_plugin_stop())
2341 break;
2342
2343 heartbeat_next(&hb);
2344 if (ebpf_plugin_stop())
2345 break;
2346
2347 if (++counter != update_every)
2348 continue;
2349
2350 if (!ebpf_shm_sem_wait_or_stop(shm_mutex_ebpf_integration)) {
2351 if (errno != ECANCELED)
2352 netdata_log_error("VFS: Failed to wait on semaphore.");
2353 break;
2354 }
2355 ebpf_vfs_read_apps(maps_per_core);
2356 ebpf_vfs_resume_apps_data();
2357 if (ebpf_plugin_stop()) {
2358 if (sem_post(shm_mutex_ebpf_integration))
2359 netdata_log_error("VFS: Failed to post semaphore.");
2360 break;
2361 }
2362
2363 if (cgroups && ebpf_cgroup_integration_active_get())
2364 read_update_vfs_cgroup();
2365
2366 if (sem_post(shm_mutex_ebpf_integration)) {
2367 netdata_log_error("VFS: Failed to post semaphore.");
2368 break;
2369 }
2370
2371 counter = 0;
2372
2373 if (ebpf_plugin_stop())
2374 break;
2375
2376 netdata_mutex_lock(&ebpf_exit_cleanup);
2377 running_time += update_every;
2378 em->running_time = running_time;
2379 netdata_mutex_unlock(&ebpf_exit_cleanup);
2380 }
2381 }
2382
2383 /**
2384 * Main loop for this collector.
2385 *
2386 * @param step the number of microseconds used with heart beat
2387 * @param em the structure with thread information
2388 */
2389 static void vfs_collector(ebpf_module_t *em)
2390 {
2391 int cgroups = em->cgroup_charts;
2392 int update_every = em->update_every;
2393 int counter = update_every - 1;
2394 int maps_per_core = em->maps_per_core;
2395 uint32_t running_time = 0;
2396 uint32_t lifetime = em->lifetime;
2397 netdata_idx_t *stats = em->hash_table_stats;
2398 memset(stats, 0, sizeof(em->hash_table_stats));
2399 heartbeat_t hb;
2400 heartbeat_init(&hb, USEC_PER_SEC);
2401 while (!ebpf_plugin_stop() && running_time < lifetime) {
2402 if (ebpf_plugin_stop())
2403 break;
2404
2405 heartbeat_next(&hb);
2406 if (ebpf_plugin_stop())
2407 break;
2408
2409 if (++counter != update_every)
2410 continue;
2411
2412 counter = 0;
2413 netdata_apps_integration_flags_t apps = em->apps_charts;
2414 ebpf_vfs_read_global_table(stats, maps_per_core);
2415
2416 if (ebpf_plugin_stop())
2417 break;
2418
2419 netdata_mutex_lock(&lock);
2420
2421 ebpf_vfs_send_data(em);
2422 fflush(stdout);
2423
2424 if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
2425 ebpf_vfs_send_apps_data(em, apps_groups_root_target);
2426
2427 if (ebpf_plugin_stop()) {
2428 netdata_mutex_unlock(&lock);
2429 break;
2430 }
2431
2432 if (cgroups && ebpf_cgroup_integration_active_get())
2433 ebpf_vfs_send_cgroup_data(em);
2434
2435 netdata_mutex_unlock(&lock);
2436
2437 if (ebpf_plugin_stop())
2438 break;
2439
2440 netdata_mutex_lock(&ebpf_exit_cleanup);
2441 running_time += update_every;
2442 em->running_time = running_time;
2443 netdata_mutex_unlock(&ebpf_exit_cleanup);
2444 }
2445 }
2446
2447 /*****************************************************************
2448 *
2449 * FUNCTIONS TO CREATE CHARTS
2450 *
2451 *****************************************************************/
2452
2453 /**
2454 * Create IO chart
2455 *
2456 * @param family the chart family
2457 * @param name the chart name
2458 * @param axis the axis label
2459 * @param web the group name used to attach the chart on dashboard
2460 * @param order the order number of the specified chart
2461 * @param algorithm the algorithm used to make the charts.
2462 * @param update_every value to overwrite the update frequency set by the server.
2463 */
2464 static void
2465 ebpf_create_io_chart(char *family, char *name, char *axis, char *web, int order, int algorithm, int update_every)
2466 {
2467 printf(
2468 "CHART %s.%s '' 'Bytes written and read' '%s' '%s' 'filesystem.vfs_io_bytes' line %d %d '' 'ebpf.plugin' 'filesystem'\n",
2469 family,
2470 name,
2471 axis,
2472 web,
2473 order,
2474 update_every);
2475
2476 printf(
2477 "DIMENSION %s %s %s 1 1\n",
2478 vfs_id_names[NETDATA_KEY_PUBLISH_VFS_READ],
2479 vfs_dimension_names[NETDATA_KEY_PUBLISH_VFS_READ],
2480 ebpf_algorithms[algorithm]);
2481 printf(
2482 "DIMENSION %s %s %s -1 1\n",
2483 vfs_id_names[NETDATA_KEY_PUBLISH_VFS_WRITE],
2484 vfs_dimension_names[NETDATA_KEY_PUBLISH_VFS_WRITE],
2485 ebpf_algorithms[algorithm]);
2486 }
2487
2488 /**
2489 * Create global charts
2490 *
2491 * Call ebpf_create_chart to create the charts for the collector.
2492 *
2493 * @param em a pointer to the structure with the default values.
2494 */
2495 static void ebpf_create_global_charts(ebpf_module_t *em)
2496 {
2497 ebpf_create_chart(
2498 NETDATA_FILESYSTEM_FAMILY,
2499 NETDATA_VFS_FILE_CLEAN_COUNT,
2500 "Remove files",
2501 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2502 NETDATA_VFS_GROUP,
2503 "filesystem.vfs_deleted_objects",
2504 NETDATA_EBPF_CHART_TYPE_LINE,
2505 NETDATA_CHART_PRIO_FILESYSTEM_VFS_CLEAN,
2506 ebpf_create_global_dimension,
2507 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK],
2508 1,
2509 em->update_every,
2510 NETDATA_EBPF_MODULE_NAME_VFS);
2511
2512 ebpf_create_chart(
2513 NETDATA_FILESYSTEM_FAMILY,
2514 NETDATA_VFS_FILE_IO_COUNT,
2515 "Calls to IO",
2516 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2517 NETDATA_VFS_GROUP,
2518 "filesystem.vfs_io",
2519 NETDATA_EBPF_CHART_TYPE_LINE,
2520 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_COUNT,
2521 ebpf_create_global_dimension,
2522 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
2523 2,
2524 em->update_every,
2525 NETDATA_EBPF_MODULE_NAME_VFS);
2526
2527 ebpf_create_io_chart(
2528 NETDATA_FILESYSTEM_FAMILY,
2529 NETDATA_VFS_IO_FILE_BYTES,
2530 EBPF_COMMON_UNITS_BYTES,
2531 NETDATA_VFS_GROUP,
2532 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_BYTES,
2533 NETDATA_EBPF_INCREMENTAL_IDX,
2534 em->update_every);
2535
2536 ebpf_create_chart(
2537 NETDATA_FILESYSTEM_FAMILY,
2538 NETDATA_VFS_FSYNC,
2539 "Calls to vfs_fsync.",
2540 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2541 NETDATA_VFS_GROUP,
2542 "filesystem.vfs_fsync",
2543 NETDATA_EBPF_CHART_TYPE_LINE,
2544 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_FSYNC,
2545 ebpf_create_global_dimension,
2546 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
2547 1,
2548 em->update_every,
2549 NETDATA_EBPF_MODULE_NAME_VFS);
2550
2551 ebpf_create_chart(
2552 NETDATA_FILESYSTEM_FAMILY,
2553 NETDATA_VFS_OPEN,
2554 "Calls to vfs_open.",
2555 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2556 NETDATA_VFS_GROUP,
2557 "filesystem.vfs_open",
2558 NETDATA_EBPF_CHART_TYPE_LINE,
2559 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_OPEN,
2560 ebpf_create_global_dimension,
2561 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
2562 1,
2563 em->update_every,
2564 NETDATA_EBPF_MODULE_NAME_VFS);
2565
2566 ebpf_create_chart(
2567 NETDATA_FILESYSTEM_FAMILY,
2568 NETDATA_VFS_CREATE,
2569 "Calls to vfs_create.",
2570 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2571 NETDATA_VFS_GROUP,
2572 "filesystem.vfs_create",
2573 NETDATA_EBPF_CHART_TYPE_LINE,
2574 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_CREATE,
2575 ebpf_create_global_dimension,
2576 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
2577 1,
2578 em->update_every,
2579 NETDATA_EBPF_MODULE_NAME_VFS);
2580
2581 if (em->mode < MODE_ENTRY) {
2582 ebpf_create_chart(
2583 NETDATA_FILESYSTEM_FAMILY,
2584 NETDATA_VFS_FILE_ERR_COUNT,
2585 "Fails to write or read",
2586 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2587 NETDATA_VFS_GROUP,
2588 "filesystem.vfs_io_error",
2589 NETDATA_EBPF_CHART_TYPE_LINE,
2590 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EBYTES,
2591 ebpf_create_global_dimension,
2592 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
2593 2,
2594 em->update_every,
2595 NETDATA_EBPF_MODULE_NAME_VFS);
2596
2597 ebpf_create_chart(
2598 NETDATA_FILESYSTEM_FAMILY,
2599 NETDATA_VFS_FSYNC_ERR,
2600 "Fails to synchronize",
2601 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2602 NETDATA_VFS_GROUP,
2603 "filesystem.vfs_fsync_error",
2604 NETDATA_EBPF_CHART_TYPE_LINE,
2605 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EFSYNC,
2606 ebpf_create_global_dimension,
2607 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
2608 1,
2609 em->update_every,
2610 NETDATA_EBPF_MODULE_NAME_VFS);
2611
2612 ebpf_create_chart(
2613 NETDATA_FILESYSTEM_FAMILY,
2614 NETDATA_VFS_OPEN_ERR,
2615 "Fails to open a file",
2616 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2617 NETDATA_VFS_GROUP,
2618 "filesystem.vfs_open_error",
2619 NETDATA_EBPF_CHART_TYPE_LINE,
2620 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EOPEN,
2621 ebpf_create_global_dimension,
2622 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
2623 1,
2624 em->update_every,
2625 NETDATA_EBPF_MODULE_NAME_VFS);
2626
2627 ebpf_create_chart(
2628 NETDATA_FILESYSTEM_FAMILY,
2629 NETDATA_VFS_CREATE_ERR,
2630 "Fails to create a file.",
2631 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2632 NETDATA_VFS_GROUP,
2633 "filesystem.vfs_create_error",
2634 NETDATA_EBPF_CHART_TYPE_LINE,
2635 NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_ECREATE,
2636 ebpf_create_global_dimension,
2637 &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
2638 1,
2639 em->update_every,
2640 NETDATA_EBPF_MODULE_NAME_VFS);
2641 }
2642
2643 fflush(stdout);
2644 }
2645
2646 /**
2647 * Create process apps charts
2648 *
2649 * Call ebpf_create_chart to create the charts on apps submenu.
2650 *
2651 * @param em a pointer to the structure with the default values.
2652 * @param ptr a pointer for the targets.
2653 **/
2654 void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr)
2655 {
2656 struct ebpf_target *root = ptr;
2657 struct ebpf_target *w;
2658 int order = 20275;
2659 int update_every = em->update_every;
2660 for (w = root; w; w = w->next) {
2661 if (unlikely(!w->exposed))
2662 continue;
2663
2664 ebpf_write_chart_cmd(
2665 NETDATA_APP_FAMILY,
2666 w->clean_name,
2667 "_ebpf_call_vfs_unlink",
2668 "Files deleted.",
2669 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2670 NETDATA_VFS_GROUP,
2671 NETDATA_EBPF_CHART_TYPE_STACKED,
2672 "app.ebpf_call_vfs_unlink",
2673 order++,
2674 update_every,
2675 NETDATA_EBPF_MODULE_NAME_VFS);
2676 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2677 ebpf_commit_label();
2678 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2679
2680 ebpf_write_chart_cmd(
2681 NETDATA_APP_FAMILY,
2682 w->clean_name,
2683 "_ebpf_call_vfs_write",
2684 "Write to disk.",
2685 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2686 NETDATA_VFS_GROUP,
2687 NETDATA_EBPF_CHART_TYPE_STACKED,
2688 "app.ebpf_call_vfs_write",
2689 order++,
2690 update_every,
2691 NETDATA_EBPF_MODULE_NAME_VFS);
2692 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2693 ebpf_commit_label();
2694 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2695
2696 if (em->mode < MODE_ENTRY) {
2697 ebpf_write_chart_cmd(
2698 NETDATA_APP_FAMILY,
2699 w->clean_name,
2700 "_ebpf_call_vfs_write_error",
2701 "Fails to write.",
2702 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2703 NETDATA_VFS_GROUP,
2704 NETDATA_EBPF_CHART_TYPE_STACKED,
2705 "app.ebpf_call_vfs_write_error",
2706 order++,
2707 update_every,
2708 NETDATA_EBPF_MODULE_NAME_VFS);
2709 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2710 ebpf_commit_label();
2711 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2712 }
2713
2714 ebpf_write_chart_cmd(
2715 NETDATA_APP_FAMILY,
2716 w->clean_name,
2717 "_ebpf_call_vfs_read",
2718 "Read from disk.",
2719 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2720 NETDATA_VFS_GROUP,
2721 NETDATA_EBPF_CHART_TYPE_STACKED,
2722 "app.ebpf_call_vfs_read",
2723 order++,
2724 update_every,
2725 NETDATA_EBPF_MODULE_NAME_VFS);
2726 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2727 ebpf_commit_label();
2728 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2729
2730 if (em->mode < MODE_ENTRY) {
2731 ebpf_write_chart_cmd(
2732 NETDATA_APP_FAMILY,
2733 w->clean_name,
2734 "_ebpf_call_vfs_read_error",
2735 "Fails to read.",
2736 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2737 NETDATA_VFS_GROUP,
2738 NETDATA_EBPF_CHART_TYPE_STACKED,
2739 "app.ebpf_call_vfs_read_error",
2740 order++,
2741 update_every,
2742 NETDATA_EBPF_MODULE_NAME_VFS);
2743 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2744 ebpf_commit_label();
2745 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2746 }
2747
2748 ebpf_write_chart_cmd(
2749 NETDATA_APP_FAMILY,
2750 w->clean_name,
2751 "_ebpf_call_vfs_write_bytes",
2752 "Bytes written on disk.",
2753 EBPF_COMMON_UNITS_BYTES,
2754 NETDATA_VFS_GROUP,
2755 NETDATA_EBPF_CHART_TYPE_STACKED,
2756 "app.ebpf_call_vfs_write_bytes",
2757 order++,
2758 update_every,
2759 NETDATA_EBPF_MODULE_NAME_VFS);
2760 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2761 ebpf_commit_label();
2762 fprintf(stdout, "DIMENSION writes '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2763
2764 ebpf_write_chart_cmd(
2765 NETDATA_APP_FAMILY,
2766 w->clean_name,
2767 "_ebpf_call_vfs_read_bytes",
2768 "Bytes read from disk.",
2769 EBPF_COMMON_UNITS_BYTES,
2770 NETDATA_VFS_GROUP,
2771 NETDATA_EBPF_CHART_TYPE_STACKED,
2772 "app.ebpf_call_vfs_read_bytes",
2773 order++,
2774 update_every,
2775 NETDATA_EBPF_MODULE_NAME_VFS);
2776 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2777 ebpf_commit_label();
2778 fprintf(stdout, "DIMENSION reads '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2779
2780 ebpf_write_chart_cmd(
2781 NETDATA_APP_FAMILY,
2782 w->clean_name,
2783 "_ebpf_call_vfs_fsync",
2784 "Calls to vfs_fsync.",
2785 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2786 NETDATA_VFS_GROUP,
2787 NETDATA_EBPF_CHART_TYPE_STACKED,
2788 "app.ebpf_call_vfs_fsync",
2789 order++,
2790 update_every,
2791 NETDATA_EBPF_MODULE_NAME_VFS);
2792 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2793 ebpf_commit_label();
2794 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2795
2796 if (em->mode < MODE_ENTRY) {
2797 ebpf_write_chart_cmd(
2798 NETDATA_APP_FAMILY,
2799 w->clean_name,
2800 "_ebpf_call_vfs_fsync_error",
2801 "Fails to sync.",
2802 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2803 NETDATA_VFS_GROUP,
2804 NETDATA_EBPF_CHART_TYPE_STACKED,
2805 "app.ebpf_call_vfs_fsync_error",
2806 order++,
2807 update_every,
2808 NETDATA_EBPF_MODULE_NAME_VFS);
2809 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2810 ebpf_commit_label();
2811 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2812 }
2813
2814 ebpf_write_chart_cmd(
2815 NETDATA_APP_FAMILY,
2816 w->clean_name,
2817 "_ebpf_call_vfs_open",
2818 "Calls to vfs_open.",
2819 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2820 NETDATA_VFS_GROUP,
2821 NETDATA_EBPF_CHART_TYPE_STACKED,
2822 "app.ebpf_call_vfs_open",
2823 order++,
2824 update_every,
2825 NETDATA_EBPF_MODULE_NAME_VFS);
2826 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2827 ebpf_commit_label();
2828 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2829
2830 if (em->mode < MODE_ENTRY) {
2831 ebpf_write_chart_cmd(
2832 NETDATA_APP_FAMILY,
2833 w->clean_name,
2834 "_ebpf_call_vfs_open_error",
2835 "Fails to open.",
2836 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2837 NETDATA_VFS_GROUP,
2838 NETDATA_EBPF_CHART_TYPE_STACKED,
2839 "app.ebpf_call_vfs_open_error",
2840 order++,
2841 update_every,
2842 NETDATA_EBPF_MODULE_NAME_VFS);
2843 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2844 ebpf_commit_label();
2845 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2846 }
2847
2848 ebpf_write_chart_cmd(
2849 NETDATA_APP_FAMILY,
2850 w->clean_name,
2851 "_ebpf_call_vfs_create",
2852 "Calls to vfs_create.",
2853 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2854 NETDATA_VFS_GROUP,
2855 NETDATA_EBPF_CHART_TYPE_STACKED,
2856 "app.ebpf_call_vfs_create",
2857 order++,
2858 update_every,
2859 NETDATA_EBPF_MODULE_NAME_VFS);
2860 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2861 ebpf_commit_label();
2862 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2863
2864 if (em->mode < MODE_ENTRY) {
2865 ebpf_write_chart_cmd(
2866 NETDATA_APP_FAMILY,
2867 w->clean_name,
2868 "_ebpf_call_vfs_create_error",
2869 "Fails to create a file.",
2870 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2871 NETDATA_VFS_GROUP,
2872 NETDATA_EBPF_CHART_TYPE_STACKED,
2873 "app.ebpf_call_vfs_create_error",
2874 order++,
2875 update_every,
2876 NETDATA_EBPF_MODULE_NAME_VFS);
2877 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
2878 ebpf_commit_label();
2879 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2880 }
2881
2882 w->charts_created |= 1 << EBPF_MODULE_VFS_IDX;
2883 }
2884
2885 em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
2886 }
2887
2888 /*****************************************************************
2889 *
2890 * FUNCTIONS TO START THREAD
2891 *
2892 *****************************************************************/
2893
2894 /**
2895 * Allocate vectors used with this thread.
2896 * We are not testing the return, because callocz does this and shutdown the software
2897 * case it was not possible to allocate.
2898 *
2899 * @param apps is apps enabled?
2900 */
2901 static void ebpf_vfs_allocate_global_vectors()
2902 {
2903 vfs_vector = callocz(ebpf_nprocs, sizeof(netdata_ebpf_vfs_t));
2904
2905 memset(vfs_aggregated_data, 0, sizeof(vfs_aggregated_data));
2906 memset(vfs_publish_aggregated, 0, sizeof(vfs_publish_aggregated));
2907
2908 vfs_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
2909 }
2910
2911 /*****************************************************************
2912 *
2913 * EBPF VFS THREAD
2914 *
2915 *****************************************************************/
2916
2917 /*
2918 * Load BPF
2919 *
2920 * Load BPF files.
2921 *
2922 * @param em the structure with configuration
2923 */
2924 static int ebpf_vfs_load_bpf(ebpf_module_t *em)
2925 {
2926 #ifdef LIBBPF_MAJOR_VERSION
2927 ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
2928 #endif
2929
2930 int ret = 0;
2931 ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_EBPF_VFS_WRITE].mode);
2932 if (em->load & EBPF_LOAD_LEGACY) {
2933 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
2934 if (!em->probe_links) {
2935 ret = -1;
2936 }
2937 }
2938 #ifdef LIBBPF_MAJOR_VERSION
2939 else {
2940 vfs_bpf_obj = vfs_bpf__open();
2941 if (!vfs_bpf_obj)
2942 ret = -1;
2943 else {
2944 ret = ebpf_vfs_load_and_attach(vfs_bpf_obj, em);
2945 if (ret) {
2946 vfs_bpf__destroy(vfs_bpf_obj);
2947 vfs_bpf_obj = NULL;
2948 }
2949 }
2950 }
2951 #endif
2952
2953 return ret;
2954 }
2955
2956 /**
2957 * Process thread
2958 *
2959 * Thread used to generate process charts.
2960 *
2961 * @param ptr a pointer to `struct ebpf_module`
2962 *
2963 * @return It always return NULL
2964 */
2965 void ebpf_vfs_thread(void *ptr)
2966 {
2967 ebpf_set_pid_map_fd(NETDATA_EBPF_PIDS_VFS_IDX, -1);
2968 ebpf_module_t *em = (ebpf_module_t *)ptr;
2969
2970 CLEANUP_FUNCTION_REGISTER(ebpf_vfs_exit) cleanup_ptr = em;
2971
2972 if (!ebpf_module_thread_has_valid_state(em)) {
2973 goto endvfs;
2974 }
2975
2976 em->maps = vfs_maps;
2977
2978 ebpf_update_pid_table(&vfs_maps[NETDATA_VFS_PID], em);
2979
2980 ebpf_vfs_allocate_global_vectors();
2981
2982 #ifdef LIBBPF_MAJOR_VERSION
2983 ebpf_adjust_thread_load(em, default_btf);
2984 #endif
2985 if (ebpf_vfs_load_bpf(em)) {
2986 goto endvfs;
2987 }
2988 ebpf_mark_program_loaded();
2989
2990 int algorithms[NETDATA_KEY_PUBLISH_VFS_END] = {
2991 NETDATA_EBPF_INCREMENTAL_IDX,
2992 NETDATA_EBPF_INCREMENTAL_IDX,
2993 NETDATA_EBPF_INCREMENTAL_IDX,
2994 NETDATA_EBPF_INCREMENTAL_IDX,
2995 NETDATA_EBPF_INCREMENTAL_IDX,
2996 NETDATA_EBPF_INCREMENTAL_IDX};
2997
2998 ebpf_global_labels(
2999 vfs_aggregated_data,
3000 vfs_publish_aggregated,
3001 vfs_dimension_names,
3002 vfs_id_names,
3003 algorithms,
3004 NETDATA_KEY_PUBLISH_VFS_END);
3005
3006 netdata_mutex_lock(&lock);
3007 ebpf_create_global_charts(em);
3008 ebpf_update_stats(&plugin_statistics, em);
3009 ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
3010
3011 netdata_mutex_unlock(&lock);
3012
3013 ebpf_read_vfs.thread =
3014 nd_thread_create(ebpf_read_vfs.name, NETDATA_THREAD_OPTION_DEFAULT, ebpf_read_vfs_thread, em);
3015
3016 vfs_collector(em);
3017
3018 endvfs:
3019 ebpf_update_disabled_plugin_stats(em);
3020 }