@cryptotaxi247 / netdata-1 / commits / 9f30cd577

Memory management eBPF (#14462)

thiagoftsm committed Feb 21, 2023 at 13:58 UTC 9f30cd5776fffcddcac7ec81d57db386ccd3414d
16 files changed +273 -460
collectors/ebpf.plugin/ebpf.c
+4 -7
@@ -435,9 +435,6 @@ ebpf_sync_syscalls_t local_syscalls[] = {
435 };
436
437
438 -// Link with apps.plugin
439 -ebpf_process_stat_t *global_process_stat = NULL;
440 -
438 // Link with cgroup.plugin
439 netdata_ebpf_cgroup_shm_t shm_ebpf_cgroup = {NULL, NULL};
440 int shm_fd_ebpf_cgroup = -1;
@@ -876,9 +873,9 @@ void ebpf_create_chart(char *type,
873 * @param module chart module name, this is the eBPF thread.
874 */
875 void ebpf_create_charts_on_apps(char *id, char *title, char *units, char *family, char *charttype, int order,
879 - char *algorithm, struct target *root, int update_every, char *module)
876 + char *algorithm, struct ebpf_target *root, int update_every, char *module)
877 {
881 - struct target *w;
878 + struct ebpf_target *w;
879 ebpf_write_chart_cmd(NETDATA_APPS_FAMILY, id, title, units, family, charttype, NULL, order,
880 update_every, module);
881
@@ -1386,8 +1383,8 @@ static void ebpf_allocate_common_vectors()
1383 return;
1384 }
1385
1389 - all_pids = callocz((size_t)pid_max, sizeof(struct pid_stat *));
1390 - global_process_stat = callocz((size_t)ebpf_nprocs, sizeof(ebpf_process_stat_t));
1386 + ebpf_all_pids = callocz((size_t)pid_max, sizeof(struct ebpf_pid_stat *));
1387 + ebpf_aral_init();
1388 }
1389
1390 /**
collectors/ebpf.plugin/ebpf.h
+3 -4
@@ -235,7 +235,7 @@ void ebpf_create_charts_on_apps(char *name,
235 char *charttype,
236 int order,
237 char *algorithm,
238 - struct target *root,
238 + struct ebpf_target *root,
239 int update_every,
240 char *module);
241
@@ -264,16 +264,15 @@ void ebpf_pid_file(char *filename, size_t length);
264
265 // Common variables
266 extern int debug_enabled;
267 -extern struct pid_stat *root_of_pids;
267 +extern struct ebpf_pid_stat *ebpf_root_of_pids;
268 extern ebpf_cgroup_target_t *ebpf_cgroup_pids;
269 extern char *ebpf_algorithms[];
270 extern struct config collector_config;
271 -extern ebpf_process_stat_t *global_process_stat;
271 extern netdata_ebpf_cgroup_shm_t shm_ebpf_cgroup;
272 extern int shm_fd_ebpf_cgroup;
273 extern sem_t *shm_sem_ebpf_cgroup;
274 extern pthread_mutex_t mutex_cgroup_shm;
276 -extern size_t all_pids_count;
275 +extern size_t ebpf_all_pids_count;
276 extern ebpf_plugin_stats_t plugin_statistics;
277 #ifdef LIBBPF_MAJOR_VERSION
278 extern struct btf *default_btf;
collectors/ebpf.plugin/ebpf_apps.c
+154 -84
@@ -4,6 +4,84 @@
4 #include "ebpf_socket.h"
5 #include "ebpf_apps.h"
6
7 +// ----------------------------------------------------------------------------
8 +// ARAL vectors used to speed up processing
9 +ARAL *ebpf_aral_apps_pid_stat;
10 +ARAL *ebpf_aral_process_stat;
11 +
12 +/**
13 + * eBPF ARAL Init
14 + *
15 + * Initiallize array allocator that will be used when integration with apps and ebpf is created.
16 + */
17 +void ebpf_aral_init(void)
18 +{
19 + size_t max_elements = NETDATA_EBPF_ALLOC_MAX_PID;
20 + if (max_elements < NETDATA_EBPF_ALLOC_MIN_ELEMENTS) {
21 + error("Number of elements given is too small, adjusting it for %d", NETDATA_EBPF_ALLOC_MIN_ELEMENTS);
22 + max_elements = NETDATA_EBPF_ALLOC_MIN_ELEMENTS;
23 + }
24 +
25 + ebpf_aral_apps_pid_stat = aral_create("ebpf-pid_stat", sizeof(struct ebpf_pid_stat),
26 + 0, max_elements,
27 + NULL, NULL, NULL, false, false);
28 +
29 + ebpf_aral_process_stat = aral_create("ebpf-proc_stat", sizeof(ebpf_process_stat_t),
30 + 0, max_elements,
31 + NULL, NULL, NULL, false, false);
32 +#ifdef NETDATA_DEV_MODE
33 + info("Plugin is using ARAL with values %d", NETDATA_EBPF_ALLOC_MAX_PID);
34 +#endif
35 +}
36 +
37 +/**
38 + * eBPF pid stat get
39 + *
40 + * Get a ebpf_pid_stat entry to be used with a specific PID.
41 + *
42 + * @return it returns the address on success.
43 + */
44 +struct ebpf_pid_stat *ebpf_pid_stat_get(void)
45 +{
46 + struct ebpf_pid_stat *target = aral_mallocz(ebpf_aral_apps_pid_stat);
47 + memset(target, 0, sizeof(struct ebpf_pid_stat));
48 + return target;
49 +}
50 +
51 +/**
52 + * eBPF target release
53 + *
54 + * @param stat Release a target after usage.
55 + */
56 +void ebpf_pid_stat_release(struct ebpf_pid_stat *stat)
57 +{
58 + aral_freez(ebpf_aral_apps_pid_stat, stat);
59 +}
60 +
61 +/**
62 + * eBPF process stat get
63 + *
64 + * Get a ebpf_pid_stat entry to be used with a specific PID.
65 + *
66 + * @return it returns the address on success.
67 + */
68 +ebpf_process_stat_t *ebpf_process_stat_get(void)
69 +{
70 + ebpf_process_stat_t *target = aral_mallocz(ebpf_aral_process_stat);
71 + memset(target, 0, sizeof(ebpf_process_stat_t));
72 + return target;
73 +}
74 +
75 +/**
76 + * eBPF process release
77 + *
78 + * @param stat Release a target after usage.
79 + */
80 +void ebpf_process_stat_release(ebpf_process_stat_t *stat)
81 +{
82 + aral_freez(ebpf_aral_process_stat, stat);
83 +}
84 +
85 // ----------------------------------------------------------------------------
86 // internal flags
87 // handled in code (automatically set)
@@ -49,7 +127,7 @@ int ebpf_read_hash_table(void *ep, int fd, uint32_t pid)
127 *
128 * @return
129 */
52 -size_t read_bandwidth_statistic_using_pid_on_target(ebpf_bandwidth_t **ep, int fd, struct pid_on_target *pids)
130 +size_t read_bandwidth_statistic_using_pid_on_target(ebpf_bandwidth_t **ep, int fd, struct ebpf_pid_on_target *pids)
131 {
132 size_t count = 0;
133 while (pids) {
@@ -120,19 +198,19 @@ int am_i_running_as_root()
198 *
199 * @return it returns the number of structures that was reset.
200 */
123 -size_t zero_all_targets(struct target *root)
201 +size_t zero_all_targets(struct ebpf_target *root)
202 {
125 - struct target *w;
203 + struct ebpf_target *w;
204 size_t count = 0;
205
206 for (w = root; w; w = w->next) {
207 count++;
208
209 if (unlikely(w->root_pid)) {
132 - struct pid_on_target *pid_on_target = w->root_pid;
210 + struct ebpf_pid_on_target *pid_on_target = w->root_pid;
211
212 while (pid_on_target) {
135 - struct pid_on_target *pid_on_target_to_free = pid_on_target;
213 + struct ebpf_pid_on_target *pid_on_target_to_free = pid_on_target;
214 pid_on_target = pid_on_target->next;
215 freez(pid_on_target_to_free);
216 }
@@ -149,9 +227,9 @@ size_t zero_all_targets(struct target *root)
227 *
228 * @param agrt the pointer to be cleaned.
229 */
152 -void clean_apps_groups_target(struct target *agrt)
230 +void clean_apps_groups_target(struct ebpf_target *agrt)
231 {
154 - struct target *current_target;
232 + struct ebpf_target *current_target;
233 while (agrt) {
234 current_target = agrt;
235 agrt = current_target->target;
@@ -170,7 +248,7 @@ void clean_apps_groups_target(struct target *agrt)
248 *
249 * @return It returns the target on success and NULL otherwise
250 */
173 -struct target *get_apps_groups_target(struct target **agrt, const char *id, struct target *target, const char *name)
251 +struct ebpf_target *get_apps_groups_target(struct ebpf_target **agrt, const char *id, struct ebpf_target *target, const char *name)
252 {
253 int tdebug = 0, thidden = target ? target->hidden : 0, ends_with = 0;
254 const char *nid = id;
@@ -188,9 +266,9 @@ struct target *get_apps_groups_target(struct target **agrt, const char *id, stru
266 uint32_t hash = simple_hash(id);
267
268 // find if it already exists
191 - struct target *w, *last = *agrt;
269 + struct ebpf_target *w, *last = *agrt;
270 for (w = *agrt; w; w = w->next) {
193 - if (w->idhash == hash && strncmp(nid, w->id, MAX_NAME) == 0)
271 + if (w->idhash == hash && strncmp(nid, w->id, EBPF_MAX_NAME) == 0)
272 return w;
273
274 last = w;
@@ -215,18 +293,18 @@ struct target *get_apps_groups_target(struct target **agrt, const char *id, stru
293 "Internal Error: request to link process '%s' to target '%s' which is linked to target '%s'", id,
294 target->id, target->target->id);
295
218 - w = callocz(1, sizeof(struct target));
219 - strncpyz(w->id, nid, MAX_NAME);
296 + w = callocz(1, sizeof(struct ebpf_target));
297 + strncpyz(w->id, nid, EBPF_MAX_NAME);
298 w->idhash = simple_hash(w->id);
299
300 if (unlikely(!target))
301 // copy the name
224 - strncpyz(w->name, name, MAX_NAME);
302 + strncpyz(w->name, name, EBPF_MAX_NAME);
303 else
304 // copy the id
227 - strncpyz(w->name, nid, MAX_NAME);
305 + strncpyz(w->name, nid, EBPF_MAX_NAME);
306
229 - strncpyz(w->compare, nid, MAX_COMPARE_NAME);
307 + strncpyz(w->compare, nid, EBPF_MAX_COMPARE_NAME);
308 size_t len = strlen(w->compare);
309 if (w->compare[len - 1] == '*') {
310 w->compare[len - 1] = '\0';
@@ -267,7 +345,7 @@ struct target *get_apps_groups_target(struct target **agrt, const char *id, stru
345 *
346 * @return It returns 0 on success and -1 otherwise
347 */
270 -int ebpf_read_apps_groups_conf(struct target **agdt, struct target **agrt, const char *path, const char *file)
348 +int ebpf_read_apps_groups_conf(struct ebpf_target **agdt, struct ebpf_target **agrt, const char *path, const char *file)
349 {
350 char filename[FILENAME_MAX + 1];
351
@@ -297,7 +375,7 @@ int ebpf_read_apps_groups_conf(struct target **agdt, struct target **agrt, const
375 continue;
376
377 // find a possibly existing target
300 - struct target *w = NULL;
378 + struct ebpf_target *w = NULL;
379
380 // loop through all words, skipping the first one (the name)
381 for (word = 0; word < words; word++) {
@@ -312,7 +390,7 @@ int ebpf_read_apps_groups_conf(struct target **agdt, struct target **agrt, const
390 continue;
391
392 // add this target
315 - struct target *n = get_apps_groups_target(agrt, s, w, name);
393 + struct ebpf_target *n = get_apps_groups_target(agrt, s, w, name);
394 if (!n) {
395 error("Cannot create target '%s' (line %zu, word %zu)", s, line, word);
396 continue;
@@ -331,7 +409,7 @@ int ebpf_read_apps_groups_conf(struct target **agdt, struct target **agrt, const
409 if (!*agdt)
410 fatal("Cannot create default target");
411
334 - struct target *ptr = *agdt;
412 + struct ebpf_target *ptr = *agdt;
413 if (ptr->target)
414 *agdt = ptr->target;
415
@@ -345,17 +423,15 @@ int ebpf_read_apps_groups_conf(struct target **agdt, struct target **agrt, const
423 // ----------------------------------------------------------------------------
424 // string lengths
425
348 -#define MAX_COMPARE_NAME 100
349 -#define MAX_NAME 100
426 #define MAX_CMDLINE 16384
427
352 -struct pid_stat **all_pids = NULL; // to avoid allocations, we pre-allocate the
428 +struct ebpf_pid_stat **ebpf_all_pids = NULL; // to avoid allocations, we pre-allocate the
429 // the entire pid space.
354 -struct pid_stat *root_of_pids = NULL; // global list of all processes running
430 +struct ebpf_pid_stat *ebpf_root_of_pids = NULL; // global list of all processes running
431
356 -size_t all_pids_count = 0; // the number of processes running
432 +size_t ebpf_all_pids_count = 0; // the number of processes running
433
358 -struct target
434 +struct ebpf_target
435 *apps_groups_default_target = NULL, // the default target
436 *apps_groups_root_target = NULL, // apps_groups.conf defined
437 *users_root_target = NULL, // users
@@ -416,7 +492,7 @@ static inline void debug_log_dummy(void)
492 *
493 * @return It returns the status value.
494 */
419 -static inline int managed_log(struct pid_stat *p, uint32_t log, int status)
495 +static inline int managed_log(struct ebpf_pid_stat *p, uint32_t log, int status)
496 {
497 if (unlikely(!status)) {
498 // error("command failed log %u, errno %d", log, errno);
@@ -476,23 +552,23 @@ static inline int managed_log(struct pid_stat *p, uint32_t log, int status)
552 *
553 * @return It returns the pid entry structure
554 */
479 -static inline struct pid_stat *get_pid_entry(pid_t pid)
555 +static inline struct ebpf_pid_stat *get_pid_entry(pid_t pid)
556 {
481 - if (unlikely(all_pids[pid]))
482 - return all_pids[pid];
557 + if (unlikely(ebpf_all_pids[pid]))
558 + return ebpf_all_pids[pid];
559
484 - struct pid_stat *p = callocz(1, sizeof(struct pid_stat));
560 + struct ebpf_pid_stat *p = ebpf_pid_stat_get();
561
486 - if (likely(root_of_pids))
487 - root_of_pids->prev = p;
562 + if (likely(ebpf_root_of_pids))
563 + ebpf_root_of_pids->prev = p;
564
489 - p->next = root_of_pids;
490 - root_of_pids = p;
565 + p->next = ebpf_root_of_pids;
566 + ebpf_root_of_pids = p;
567
568 p->pid = pid;
569
494 - all_pids[pid] = p;
495 - all_pids_count++;
570 + ebpf_all_pids[pid] = p;
571 + ebpf_all_pids_count++;
572
573 return p;
574 }
@@ -502,14 +578,14 @@ static inline struct pid_stat *get_pid_entry(pid_t pid)
578 *
579 * @param p the pid_stat structure to assign for a target.
580 */
505 -static inline void assign_target_to_pid(struct pid_stat *p)
581 +static inline void assign_target_to_pid(struct ebpf_pid_stat *p)
582 {
583 targets_assignment_counter++;
584
585 uint32_t hash = simple_hash(p->comm);
586 size_t pclen = strlen(p->comm);
587
512 - struct target *w;
588 + struct ebpf_target *w;
589 for (w = apps_groups_root_target; w; w = w->next) {
590 // if(debug_enabled || (p->target && p->target->debug_enabled)) debug_log_int("\t\tcomparing '%s' with '%s'", w->compare, p->comm);
591
@@ -543,11 +619,11 @@ static inline void assign_target_to_pid(struct pid_stat *p)
619 /**
620 * Read cmd line from /proc/PID/cmdline
621 *
546 - * @param p the pid_stat_structure.
622 + * @param p the ebpf_pid_stat_structure.
623 *
624 * @return It returns 1 on success and 0 otherwise.
625 */
550 -static inline int read_proc_pid_cmdline(struct pid_stat *p)
626 +static inline int read_proc_pid_cmdline(struct ebpf_pid_stat *p)
627 {
628 static char cmdline[MAX_CMDLINE + 1];
629
@@ -596,7 +672,7 @@ cleanup:
672 * @param p the pid stat structure to store the data.
673 * @param ptr an useless argument.
674 */
599 -static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr)
675 +static inline int read_proc_pid_stat(struct ebpf_pid_stat *p, void *ptr)
676 {
677 UNUSED(ptr);
678
@@ -640,7 +716,7 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr)
716 debug_log("\tJust added %d (%s)", p->pid, comm);
717 }
718
643 - strncpyz(p->comm, comm, MAX_COMPARE_NAME);
719 + strncpyz(p->comm, comm, EBPF_MAX_COMPARE_NAME);
720
721 // /proc/<pid>/cmdline
722 if (likely(proc_pid_cmdline_is_needed))
@@ -673,7 +749,7 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr)
749 return 0;
750 }
751
676 - struct pid_stat *p = get_pid_entry(pid);
752 + struct ebpf_pid_stat *p = get_pid_entry(pid);
753 if (unlikely(!p || p->read))
754 return 0;
755 p->read = 1;
@@ -701,11 +777,11 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr)
777 */
778 static inline void link_all_processes_to_their_parents(void)
779 {
704 - struct pid_stat *p, *pp;
780 + struct ebpf_pid_stat *p, *pp;
781
782 // link all children to their parents
783 // and update children count on parents
708 - for (p = root_of_pids; p; p = p->next) {
784 + for (p = ebpf_root_of_pids; p; p = p->next) {
785 // for each process found
786
787 p->sortlist = 0;
@@ -716,7 +792,7 @@ static inline void link_all_processes_to_their_parents(void)
792 continue;
793 }
794
719 - pp = all_pids[p->ppid];
795 + pp = ebpf_all_pids[p->ppid];
796 if (likely(pp)) {
797 p->parent = pp;
798 pp->children_count++;
@@ -738,7 +814,7 @@ static inline void link_all_processes_to_their_parents(void)
814 */
815 static void apply_apps_groups_targets_inheritance(void)
816 {
741 - struct pid_stat *p = NULL;
817 + struct ebpf_pid_stat *p = NULL;
818
819 // children that do not have a target
820 // inherit their target from their parent
@@ -747,7 +823,7 @@ static void apply_apps_groups_targets_inheritance(void)
823 if (unlikely(debug_enabled))
824 loops++;
825 found = 0;
750 - for (p = root_of_pids; p; p = p->next) {
826 + for (p = ebpf_root_of_pids; p; p = p->next) {
827 // if this process does not have a target
828 // and it has a parent
829 // and its parent has a target
@@ -773,7 +849,7 @@ static void apply_apps_groups_targets_inheritance(void)
849 loops++;
850 found = 0;
851
776 - for (p = root_of_pids; p; p = p->next) {
852 + for (p = ebpf_root_of_pids; p; p = p->next) {
853 if (unlikely(!p->sortlist && !p->children_count))
854 p->sortlist = sortlist++;
855
@@ -809,17 +885,17 @@ static void apply_apps_groups_targets_inheritance(void)
885 }
886
887 // init goes always to default target
812 - if (all_pids[INIT_PID])
813 - all_pids[INIT_PID]->target = apps_groups_default_target;
888 + if (ebpf_all_pids[INIT_PID])
889 + ebpf_all_pids[INIT_PID]->target = apps_groups_default_target;
890
891 // pid 0 goes always to default target
816 - if (all_pids[0])
817 - all_pids[0]->target = apps_groups_default_target;
892 + if (ebpf_all_pids[0])
893 + ebpf_all_pids[0]->target = apps_groups_default_target;
894
895 // give a default target on all top level processes
896 if (unlikely(debug_enabled))
897 loops++;
822 - for (p = root_of_pids; p; p = p->next) {
898 + for (p = ebpf_root_of_pids; p; p = p->next) {
899 // if the process is not merged itself
900 // then is is a top level process
901 if (unlikely(!p->merged && !p->target))
@@ -830,8 +906,8 @@ static void apply_apps_groups_targets_inheritance(void)
906 p->sortlist = sortlist++;
907 }
908
833 - if (all_pids[1])
834 - all_pids[1]->sortlist = sortlist++;
909 + if (ebpf_all_pids[1])
910 + ebpf_all_pids[1]->sortlist = sortlist++;
911
912 // give a target to all merged child processes
913 found = 1;
@@ -839,7 +915,7 @@ static void apply_apps_groups_targets_inheritance(void)
915 if (unlikely(debug_enabled))
916 loops++;
917 found = 0;
842 - for (p = root_of_pids; p; p = p->next) {
918 + for (p = ebpf_root_of_pids; p; p = p->next) {
919 if (unlikely(!p->target && p->merged && p->parent && p->parent->target)) {
920 p->target = p->parent->target;
921 found++;
@@ -860,9 +936,9 @@ static void apply_apps_groups_targets_inheritance(void)
936 *
937 * @param root the targets that will be updated.
938 */
863 -static inline void post_aggregate_targets(struct target *root)
939 +static inline void post_aggregate_targets(struct ebpf_target *root)
940 {
865 - struct target *w;
941 + struct ebpf_target *w;
942 for (w = root; w; w = w->next) {
943 if (w->collected_starttime) {
944 if (!w->starttime || w->collected_starttime < w->starttime) {
@@ -881,7 +957,7 @@ static inline void post_aggregate_targets(struct target *root)
957 */
958 static inline void del_pid_entry(pid_t pid)
959 {
884 - struct pid_stat *p = all_pids[pid];
960 + struct ebpf_pid_stat *p = ebpf_all_pids[pid];
961
962 if (unlikely(!p)) {
963 error("attempted to free pid %d that is not allocated.", pid);
@@ -890,8 +966,8 @@ static inline void del_pid_entry(pid_t pid)
966
967 debug_log("process %d %s exited, deleting it.", pid, p->comm);
968
893 - if (root_of_pids == p)
894 - root_of_pids = p->next;
969 + if (ebpf_root_of_pids == p)
970 + ebpf_root_of_pids = p->next;
971
972 if (p->next)
973 p->next->prev = p->prev;
@@ -903,10 +979,10 @@ static inline void del_pid_entry(pid_t pid)
979 freez(p->io_filename);
980 freez(p->cmdline_filename);
981 freez(p->cmdline);
906 - freez(p);
982 + ebpf_pid_stat_release(p);
983
908 - all_pids[pid] = NULL;
909 - all_pids_count--;
984 + ebpf_all_pids[pid] = NULL;
985 + ebpf_all_pids_count--;
986 }
987
988 /**
@@ -921,9 +997,9 @@ static inline void del_pid_entry(pid_t pid)
997 */
998 int get_pid_comm(pid_t pid, size_t n, char *dest)
999 {
924 - struct pid_stat *stat;
1000 + struct ebpf_pid_stat *stat;
1001
926 - stat = all_pids[pid];
1002 + stat = ebpf_all_pids[pid];
1003 if (unlikely(stat == NULL)) {
1004 return -1;
1005 }
@@ -991,9 +1067,9 @@ void cleanup_variables_from_other_threads(uint32_t pid)
1067 */
1068 void cleanup_exited_pids()
1069 {
994 - struct pid_stat *p = NULL;
1070 + struct ebpf_pid_stat *p = NULL;
1071
996 - for (p = root_of_pids; p;) {
1072 + for (p = ebpf_root_of_pids; p;) {
1073 if (!p->updated && (!p->keep || p->keeploops > 0)) {
1074 if (unlikely(debug_enabled && (p->keep || p->keeploops)))
1075 debug_log(" > CLEANUP cannot keep exited process %d (%s) anymore - removing it.", p->pid, p->comm);
@@ -1002,12 +1078,9 @@ void cleanup_exited_pids()
1078 p = p->next;
1079
1080 // Clean process structure
1005 - freez(global_process_stats[r]);
1081 + ebpf_process_stat_release(global_process_stats[r]);
1082 global_process_stats[r] = NULL;
1083
1008 - freez(current_apps_data[r]);
1009 - current_apps_data[r] = NULL;
1010 -
1084 cleanup_variables_from_other_threads(r);
1085
1086 del_pid_entry(r);
@@ -1060,7 +1133,7 @@ static inline void read_proc_filesystem()
1133 * @param p the pid with information to update
1134 * @param o never used
1135 */
1063 -static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p, struct target *o)
1136 +static inline void aggregate_pid_on_target(struct ebpf_target *w, struct ebpf_pid_stat *p, struct ebpf_target *o)
1137 {
1138 UNUSED(o);
1139
@@ -1075,7 +1148,7 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p,
1148 }
1149
1150 w->processes++;
1078 - struct pid_on_target *pid_on_target = mallocz(sizeof(struct pid_on_target));
1151 + struct ebpf_pid_on_target *pid_on_target = mallocz(sizeof(struct ebpf_pid_on_target));
1152 pid_on_target->pid = p->pid;
1153 pid_on_target->next = w->root_pid;
1154 w->root_pid = pid_on_target;
@@ -1091,10 +1164,10 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p,
1164 */
1165 void collect_data_for_all_processes(int tbl_pid_stats_fd)
1166 {
1094 - if (unlikely(!all_pids))
1167 + if (unlikely(!ebpf_all_pids))
1168 return;
1169
1097 - struct pid_stat *pids = root_of_pids; // global list of all processes running
1170 + struct ebpf_pid_stat *pids = ebpf_root_of_pids; // global list of all processes running
1171 while (pids) {
1172 if (pids->updated_twice) {
1173 pids->read = 0; // mark it as not read, so that collect_data_for_pid() will read it
@@ -1113,24 +1186,21 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd)
1186 read_proc_filesystem();
1187
1188 uint32_t key;
1116 - pids = root_of_pids; // global list of all processes running
1189 + pids = ebpf_root_of_pids; // global list of all processes running
1190 // while (bpf_map_get_next_key(tbl_pid_stats_fd, &key, &next_key) == 0) {
1191 while (pids) {
1192 key = pids->pid;
1193 ebpf_process_stat_t *w = global_process_stats[key];
1194 if (!w) {
1122 - w = callocz(1, sizeof(ebpf_process_stat_t));
1195 + w = ebpf_process_stat_get();
1196 global_process_stats[key] = w;
1197 }
1198
1199 if (bpf_map_lookup_elem(tbl_pid_stats_fd, &key, w)) {
1200 // Clean Process structures
1128 - freez(w);
1201 + ebpf_process_stat_release(w);
1202 global_process_stats[key] = NULL;
1203
1131 - freez(current_apps_data[key]);
1132 - current_apps_data[key] = NULL;
1133 -
1204 cleanup_variables_from_other_threads(key);
1205
1206 pids = pids->next;
@@ -1148,7 +1218,7 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd)
1218
1219 // this has to be done, before the cleanup
1220 // // concentrate everything on the targets
1151 - for (pids = root_of_pids; pids; pids = pids->next)
1221 + for (pids = ebpf_root_of_pids; pids; pids = pids->next)
1222 aggregate_pid_on_target(pids->target, pids, NULL);
1223
1224 post_aggregate_targets(apps_groups_root_target);
collectors/ebpf.plugin/ebpf_apps.h
+49 -252
@@ -3,7 +3,6 @@
3 #ifndef NETDATA_EBPF_APPS_H
4 #define NETDATA_EBPF_APPS_H 1
5
6 -#include "libnetdata/threads/threads.h"
6 #include "libnetdata/locks/locks.h"
7 #include "libnetdata/avl/avl.h"
8 #include "libnetdata/clocks/clocks.h"
@@ -34,92 +33,21 @@
33 #include "ebpf_swap.h"
34 #include "ebpf_vfs.h"
35
37 -#define MAX_COMPARE_NAME 100
38 -#define MAX_NAME 100
39 -
40 -// ----------------------------------------------------------------------------
41 -// process_pid_stat
42 -//
43 -// Fields read from the kernel ring for a specific PID
44 -//
45 -typedef struct process_pid_stat {
46 - uint64_t pid_tgid; // Unique identifier
47 - uint32_t pid; // process id
48 -
49 - // Count number of calls done for specific function
50 - uint32_t open_call;
51 - uint32_t write_call;
52 - uint32_t writev_call;
53 - uint32_t read_call;
54 - uint32_t readv_call;
55 - uint32_t unlink_call;
56 - uint32_t exit_call;
57 - uint32_t release_call;
58 - uint32_t fork_call;
59 - uint32_t clone_call;
60 - uint32_t close_call;
61 -
62 - // Count number of bytes written or read
63 - uint64_t write_bytes;
64 - uint64_t writev_bytes;
65 - uint64_t readv_bytes;
66 - uint64_t read_bytes;
67 -
68 - // Count number of errors for the specified function
69 - uint32_t open_err;
70 - uint32_t write_err;
71 - uint32_t writev_err;
72 - uint32_t read_err;
73 - uint32_t readv_err;
74 - uint32_t unlink_err;
75 - uint32_t fork_err;
76 - uint32_t clone_err;
77 - uint32_t close_err;
78 -} process_pid_stat_t;
79 -
80 -// ----------------------------------------------------------------------------
81 -// socket_bandwidth
82 -//
83 -// Fields read from the kernel ring for a specific PID
84 -//
85 -typedef struct socket_bandwidth {
86 - uint64_t first;
87 - uint64_t ct;
88 - uint64_t sent;
89 - uint64_t received;
90 - unsigned char removed;
91 -} socket_bandwidth_t;
36 +#define EBPF_MAX_COMPARE_NAME 100
37 +#define EBPF_MAX_NAME 100
38
39 // ----------------------------------------------------------------------------
40 // pid_stat
41 //
96 -// structure to store data for each process running
97 -// see: man proc for the description of the fields
98 -
99 -struct pid_fd {
100 - int fd;
101 -
102 -#ifndef __FreeBSD__
103 - ino_t inode;
104 - char *filename;
105 - uint32_t link_hash;
106 - size_t cache_iterations_counter;
107 - size_t cache_iterations_reset;
108 -#endif
109 -};
110 -
111 -struct target {
112 - char compare[MAX_COMPARE_NAME + 1];
42 +struct ebpf_target {
43 + char compare[EBPF_MAX_COMPARE_NAME + 1];
44 uint32_t comparehash;
45 size_t comparelen;
46
116 - char id[MAX_NAME + 1];
47 + char id[EBPF_MAX_NAME + 1];
48 uint32_t idhash;
49
119 - char name[MAX_NAME + 1];
120 -
121 - uid_t uid;
122 - gid_t gid;
50 + char name[EBPF_MAX_NAME + 1];
51
52 // Changes made to simplify integration between apps and eBPF.
53 netdata_publish_cachestat_t cachestat;
@@ -129,58 +57,9 @@ struct target {
57 netdata_fd_stat_t fd;
58 netdata_publish_shm_t shm;
59
132 - /* These variables are not necessary for eBPF collector
133 - kernel_uint_t minflt;
134 - kernel_uint_t cminflt;
135 - kernel_uint_t majflt;
136 - kernel_uint_t cmajflt;
137 - kernel_uint_t utime;
138 - kernel_uint_t stime;
139 - kernel_uint_t gtime;
140 - kernel_uint_t cutime;
141 - kernel_uint_t cstime;
142 - kernel_uint_t cgtime;
143 - kernel_uint_t num_threads;
144 - // kernel_uint_t rss;
145 -
146 - kernel_uint_t status_vmsize;
147 - kernel_uint_t status_vmrss;
148 - kernel_uint_t status_vmshared;
149 - kernel_uint_t status_rssfile;
150 - kernel_uint_t status_rssshmem;
151 - kernel_uint_t status_vmswap;
152 -
153 - kernel_uint_t io_logical_bytes_read;
154 - kernel_uint_t io_logical_bytes_written;
155 - // kernel_uint_t io_read_calls;
156 - // kernel_uint_t io_write_calls;
157 - kernel_uint_t io_storage_bytes_read;
158 - kernel_uint_t io_storage_bytes_written;
159 - // kernel_uint_t io_cancelled_write_bytes;
160 -
161 - int *target_fds;
162 - int target_fds_size;
163 -
164 - kernel_uint_t openfiles;
165 - kernel_uint_t openpipes;
166 - kernel_uint_t opensockets;
167 - kernel_uint_t openinotifies;
168 - kernel_uint_t openeventfds;
169 - kernel_uint_t opentimerfds;
170 - kernel_uint_t opensignalfds;
171 - kernel_uint_t openeventpolls;
172 - kernel_uint_t openother;
173 - */
174 -
60 kernel_uint_t starttime;
61 kernel_uint_t collected_starttime;
62
178 - /*
179 - kernel_uint_t uptime_min;
180 - kernel_uint_t uptime_sum;
181 - kernel_uint_t uptime_max;
182 - */
183 -
63 unsigned int processes; // how many processes have been merged to this
64 int exposed; // if set, we have sent this to netdata
65 int hidden; // if set, we set the hidden flag on the dimension
@@ -189,20 +68,20 @@ struct target {
68 int starts_with; // if set, the compare string matches only the
69 // beginning of the command
70
192 - struct pid_on_target *root_pid; // list of aggregated pids for target debugging
71 + struct ebpf_pid_on_target *root_pid; // list of aggregated pids for target debugging
72
194 - struct target *target; // the one that will be reported to netdata
195 - struct target *next;
73 + struct ebpf_target *target; // the one that will be reported to netdata
74 + struct ebpf_target *next;
75 };
76
198 -extern struct target *apps_groups_default_target;
199 -extern struct target *apps_groups_root_target;
200 -extern struct target *users_root_target;
201 -extern struct target *groups_root_target;
77 +extern struct ebpf_target *apps_groups_default_target;
78 +extern struct ebpf_target *apps_groups_root_target;
79 +extern struct ebpf_target *users_root_target;
80 +extern struct ebpf_target *groups_root_target;
81
203 -struct pid_stat {
82 +struct ebpf_pid_stat {
83 int32_t pid;
205 - char comm[MAX_COMPARE_NAME + 1];
84 + char comm[EBPF_MAX_COMPARE_NAME + 1];
85 char *cmdline;
86
87 uint32_t log_thrown;
@@ -210,96 +89,6 @@ struct pid_stat {
89 // char state;
90 int32_t ppid;
91
213 - // int32_t pgrp;
214 - // int32_t session;
215 - // int32_t tty_nr;
216 - // int32_t tpgid;
217 - // uint64_t flags;
218 -
219 - /*
220 - // these are raw values collected
221 - kernel_uint_t minflt_raw;
222 - kernel_uint_t cminflt_raw;
223 - kernel_uint_t majflt_raw;
224 - kernel_uint_t cmajflt_raw;
225 - kernel_uint_t utime_raw;
226 - kernel_uint_t stime_raw;
227 - kernel_uint_t gtime_raw; // guest_time
228 - kernel_uint_t cutime_raw;
229 - kernel_uint_t cstime_raw;
230 - kernel_uint_t cgtime_raw; // cguest_time
231 -
232 - // these are rates
233 - kernel_uint_t minflt;
234 - kernel_uint_t cminflt;
235 - kernel_uint_t majflt;
236 - kernel_uint_t cmajflt;
237 - kernel_uint_t utime;
238 - kernel_uint_t stime;
239 - kernel_uint_t gtime;
240 - kernel_uint_t cutime;
241 - kernel_uint_t cstime;
242 - kernel_uint_t cgtime;
243 -
244 - // int64_t priority;
245 - // int64_t nice;
246 - int32_t num_threads;
247 - // int64_t itrealvalue;
248 - kernel_uint_t collected_starttime;
249 - // kernel_uint_t vsize;
250 - // kernel_uint_t rss;
251 - // kernel_uint_t rsslim;
252 - // kernel_uint_t starcode;
253 - // kernel_uint_t endcode;
254 - // kernel_uint_t startstack;
255 - // kernel_uint_t kstkesp;
256 - // kernel_uint_t kstkeip;
257 - // uint64_t signal;
258 - // uint64_t blocked;
259 - // uint64_t sigignore;
260 - // uint64_t sigcatch;
261 - // uint64_t wchan;
262 - // uint64_t nswap;
263 - // uint64_t cnswap;
264 - // int32_t exit_signal;
265 - // int32_t processor;
266 - // uint32_t rt_priority;
267 - // uint32_t policy;
268 - // kernel_uint_t delayacct_blkio_ticks;
269 -
270 - uid_t uid;
271 - gid_t gid;
272 -
273 - kernel_uint_t status_vmsize;
274 - kernel_uint_t status_vmrss;
275 - kernel_uint_t status_vmshared;
276 - kernel_uint_t status_rssfile;
277 - kernel_uint_t status_rssshmem;
278 - kernel_uint_t status_vmswap;
279 -#ifndef __FreeBSD__
280 - ARL_BASE *status_arl;
281 -#endif
282 -
283 - kernel_uint_t io_logical_bytes_read_raw;
284 - kernel_uint_t io_logical_bytes_written_raw;
285 - // kernel_uint_t io_read_calls_raw;
286 - // kernel_uint_t io_write_calls_raw;
287 - kernel_uint_t io_storage_bytes_read_raw;
288 - kernel_uint_t io_storage_bytes_written_raw;
289 - // kernel_uint_t io_cancelled_write_bytes_raw;
290 -
291 - kernel_uint_t io_logical_bytes_read;
292 - kernel_uint_t io_logical_bytes_written;
293 - // kernel_uint_t io_read_calls;
294 - // kernel_uint_t io_write_calls;
295 - kernel_uint_t io_storage_bytes_read;
296 - kernel_uint_t io_storage_bytes_written;
297 - // kernel_uint_t io_cancelled_write_bytes;
298 - */
299 -
300 - struct pid_fd *fds; // array of fds it uses
301 - size_t fds_size; // the size of the fds array
302 -
92 int children_count; // number of processes directly referencing this
93 unsigned char keep : 1; // 1 when we need to keep this process in memory even after it exited
94 int keeploops; // increases by 1 every time keep is 1 and updated 0
@@ -312,28 +101,21 @@ struct pid_stat {
101
102 // each process gets a unique number
103
315 - struct target *target; // app_groups.conf targets
316 - struct target *user_target; // uid based targets
317 - struct target *group_target; // gid based targets
104 + struct ebpf_target *target; // app_groups.conf targets
105 + struct ebpf_target *user_target; // uid based targets
106 + struct ebpf_target *group_target; // gid based targets
107
108 usec_t stat_collected_usec;
109 usec_t last_stat_collected_usec;
110
322 - usec_t io_collected_usec;
323 - usec_t last_io_collected_usec;
324 -
325 - kernel_uint_t uptime;
326 -
327 - char *fds_dirname; // the full directory name in /proc/PID/fd
328 -
111 char *stat_filename;
112 char *status_filename;
113 char *io_filename;
114 char *cmdline_filename;
115
334 - struct pid_stat *parent;
335 - struct pid_stat *prev;
336 - struct pid_stat *next;
116 + struct ebpf_pid_stat *parent;
117 + struct ebpf_pid_stat *prev;
118 + struct ebpf_pid_stat *next;
119 };
120
121 // ----------------------------------------------------------------------------
@@ -344,15 +126,15 @@ struct pid_stat {
126 //
127 // - Each entry in /etc/apps_groups.conf creates a target.
128 // - Each user and group used by a process in the system, creates a target.
347 -struct pid_on_target {
129 +struct ebpf_pid_on_target {
130 int32_t pid;
349 - struct pid_on_target *next;
131 + struct ebpf_pid_on_target *next;
132 };
133
134 // ----------------------------------------------------------------------------
135 // Structures used to read information from kernel ring
136 typedef struct ebpf_process_stat {
355 - uint64_t pid_tgid;
137 + uint64_t pid_tgid; // This cannot be removed, because it is used inside kernel ring.
138 uint32_t pid;
139
140 //Counter
@@ -406,16 +188,16 @@ static inline void debug_log_int(const char *fmt, ...)
188 // ----------------------------------------------------------------------------
189 // Exported variabled and functions
190 //
409 -extern struct pid_stat **all_pids;
191 +extern struct ebpf_pid_stat **ebpf_all_pids;
192
411 -int ebpf_read_apps_groups_conf(struct target **apps_groups_default_target,
412 - struct target **apps_groups_root_target,
413 - const char *path,
414 - const char *file);
193 +int ebpf_read_apps_groups_conf(struct ebpf_target **apps_groups_default_target,
194 + struct ebpf_target **apps_groups_root_target,
195 + const char *path,
196 + const char *file);
197
416 -void clean_apps_groups_target(struct target *apps_groups_root_target);
198 +void clean_apps_groups_target(struct ebpf_target *apps_groups_root_target);
199
418 -size_t zero_all_targets(struct target *root);
200 +size_t zero_all_targets(struct ebpf_target *root);
201
202 int am_i_running_as_root();
203
@@ -427,15 +209,30 @@ int get_pid_comm(pid_t pid, size_t n, char *dest);
209
210 size_t read_processes_statistic_using_pid_on_target(ebpf_process_stat_t **ep,
211 int fd,
430 - struct pid_on_target *pids);
212 + struct ebpf_pid_on_target *pids);
213
432 -size_t read_bandwidth_statistic_using_pid_on_target(ebpf_bandwidth_t **ep, int fd, struct pid_on_target *pids);
214 +size_t read_bandwidth_statistic_using_pid_on_target(ebpf_bandwidth_t **ep, int fd, struct ebpf_pid_on_target *pids);
215
216 void collect_data_for_all_processes(int tbl_pid_stats_fd);
217
218 extern ebpf_process_stat_t **global_process_stats;
437 -extern ebpf_process_publish_apps_t **current_apps_data;
219 extern netdata_publish_cachestat_t **cachestat_pid;
220 extern netdata_publish_dcstat_t **dcstat_pid;
221
222 +// The default value is at least 32 times smaller than maximum number of PIDs allowed on system,
223 +// this is only possible because we are using ARAL (https://github.com/netdata/netdata/tree/master/libnetdata/aral).
224 +#ifndef NETDATA_EBPF_ALLOC_MAX_PID
225 +# define NETDATA_EBPF_ALLOC_MAX_PID 1024
226 +#endif
227 +#define NETDATA_EBPF_ALLOC_MIN_ELEMENTS 256
228 +
229 +extern void ebpf_aral_init(void);
230 +
231 +extern struct ebpf_pid_stat *ebpf_target_get(void);
232 +
233 +extern ebpf_process_stat_t *ebpf_process_stat_get(void);
234 +extern void ebpf_process_stat_release(ebpf_process_stat_t *stat);
235 +
236 +#include "libnetdata/threads/threads.h"
237 +
238 #endif /* NETDATA_EBPF_APPS_H */
collectors/ebpf.plugin/ebpf_cachestat.c
+5 -5
@@ -521,7 +521,7 @@ static void read_apps_table()
521 {
522 netdata_cachestat_pid_t *cv = cachestat_vector;
523 uint32_t key;
524 - struct pid_stat *pids = root_of_pids;
524 + struct ebpf_pid_stat *pids = ebpf_root_of_pids;
525 int fd = cachestat_maps[NETDATA_CACHESTAT_PID_STATS].map_fd;
526 size_t length = sizeof(netdata_cachestat_pid_t)*ebpf_nprocs;
527 while (pids) {
@@ -589,7 +589,7 @@ static void ebpf_update_cachestat_cgroup()
589 */
590 void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
591 {
592 - struct target *root = ptr;
592 + struct ebpf_target *root = ptr;
593 ebpf_create_charts_on_apps(NETDATA_CACHESTAT_HIT_RATIO_CHART,
594 "Hit ratio",
595 EBPF_COMMON_DIMENSION_PERCENTAGE,
@@ -694,7 +694,7 @@ static void cachestat_send_global(netdata_publish_cachestat_t *publish)
694 * @param publish output structure.
695 * @param root structure with listed IPs
696 */
697 -void ebpf_cachestat_sum_pids(netdata_publish_cachestat_t *publish, struct pid_on_target *root)
697 +void ebpf_cachestat_sum_pids(netdata_publish_cachestat_t *publish, struct ebpf_pid_on_target *root)
698 {
699 memcpy(&publish->prev, &publish->current,sizeof(publish->current));
700 memset(&publish->current, 0, sizeof(publish->current));
@@ -720,9 +720,9 @@ void ebpf_cachestat_sum_pids(netdata_publish_cachestat_t *publish, struct pid_on
720 *
721 * @param root the target list.
722 */
723 -void ebpf_cache_send_apps_data(struct target *root)
723 +void ebpf_cache_send_apps_data(struct ebpf_target *root)
724 {
725 - struct target *w;
725 + struct ebpf_target *w;
726 collected_number value;
727
728 write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_CACHESTAT_HIT_RATIO_CHART);
collectors/ebpf.plugin/ebpf_dcstat.c
+5 -5
@@ -342,7 +342,7 @@ static void ebpf_dcstat_exit(void *ptr)
342 */
343 void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr)
344 {
345 - struct target *root = ptr;
345 + struct ebpf_target *root = ptr;
346 ebpf_create_charts_on_apps(NETDATA_DC_HIT_CHART,
347 "Percentage of files inside directory cache",
348 EBPF_COMMON_DIMENSION_PERCENTAGE,
@@ -448,7 +448,7 @@ static void read_apps_table()
448 {
449 netdata_dcstat_pid_t *cv = dcstat_vector;
450 uint32_t key;
451 - struct pid_stat *pids = root_of_pids;
451 + struct ebpf_pid_stat *pids = ebpf_root_of_pids;
452 int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
453 size_t length = sizeof(netdata_dcstat_pid_t)*ebpf_nprocs;
454 while (pids) {
@@ -540,7 +540,7 @@ static void ebpf_dc_read_global_table()
540 * @param publish output structure.
541 * @param root structure with listed IPs
542 */
543 -void ebpf_dcstat_sum_pids(netdata_publish_dcstat_t *publish, struct pid_on_target *root)
543 +void ebpf_dcstat_sum_pids(netdata_publish_dcstat_t *publish, struct ebpf_pid_on_target *root)
544 {
545 memset(&publish->curr, 0, sizeof(netdata_dcstat_pid_t));
546 netdata_dcstat_pid_t *dst = &publish->curr;
@@ -563,9 +563,9 @@ void ebpf_dcstat_sum_pids(netdata_publish_dcstat_t *publish, struct pid_on_targe
563 *
564 * @param root the target list.
565 */
566 -void ebpf_dcache_send_apps_data(struct target *root)
566 +void ebpf_dcache_send_apps_data(struct ebpf_target *root)
567 {
568 - struct target *w;
568 + struct ebpf_target *w;
569 collected_number value;
570
571 write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_DC_HIT_CHART);
collectors/ebpf.plugin/ebpf_fd.c
+5 -5
@@ -495,7 +495,7 @@ static void read_apps_table()
495 {
496 netdata_fd_stat_t *fv = fd_vector;
497 uint32_t key;
498 - struct pid_stat *pids = root_of_pids;
498 + struct ebpf_pid_stat *pids = ebpf_root_of_pids;
499 int fd = fd_maps[NETDATA_FD_PID_STATS].map_fd;
500 size_t length = sizeof(netdata_fd_stat_t) * ebpf_nprocs;
501 while (pids) {
@@ -560,7 +560,7 @@ static void ebpf_update_fd_cgroup()
560 * @param fd the output
561 * @param root list of pids
562 */
563 -static void ebpf_fd_sum_pids(netdata_fd_stat_t *fd, struct pid_on_target *root)
563 +static void ebpf_fd_sum_pids(netdata_fd_stat_t *fd, struct ebpf_pid_on_target *root)
564 {
565 uint32_t open_call = 0;
566 uint32_t close_call = 0;
@@ -593,9 +593,9 @@ static void ebpf_fd_sum_pids(netdata_fd_stat_t *fd, struct pid_on_target *root)
593 * @param em the structure with thread information
594 * @param root the target list.
595 */
596 -void ebpf_fd_send_apps_data(ebpf_module_t *em, struct target *root)
596 +void ebpf_fd_send_apps_data(ebpf_module_t *em, struct ebpf_target *root)
597 {
598 - struct target *w;
598 + struct ebpf_target *w;
599 for (w = root; w; w = w->next) {
600 if (unlikely(w->exposed && w->processes)) {
601 ebpf_fd_sum_pids(&w->fd, w->root_pid);
@@ -972,7 +972,7 @@ static void fd_collector(ebpf_module_t *em)
972 */
973 void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr)
974 {
975 - struct target *root = ptr;
975 + struct ebpf_target *root = ptr;
976 ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_OPEN,
977 "Number of open files",
978 EBPF_COMMON_DIMENSION_CALL,
collectors/ebpf.plugin/ebpf_oomkill.c
+4 -4
@@ -54,11 +54,11 @@ static void oomkill_cleanup(void *ptr)
54 static void oomkill_write_data(int32_t *keys, uint32_t total)
55 {
56 // for each app, see if it was OOM killed. record as 1 if so otherwise 0.
57 - struct target *w;
57 + struct ebpf_target *w;
58 for (w = apps_groups_root_target; w != NULL; w = w->next) {
59 if (likely(w->exposed && w->processes)) {
60 bool was_oomkilled = false;
61 - struct pid_on_target *pids = w->root_pid;
61 + struct ebpf_pid_on_target *pids = w->root_pid;
62 while (pids) {
63 uint32_t j;
64 for (j = 0; j < total; j++) {
@@ -334,7 +334,7 @@ static void oomkill_collector(ebpf_module_t *em)
334 */
335 void ebpf_oomkill_create_apps_charts(struct ebpf_module *em, void *ptr)
336 {
337 - struct target *root = ptr;
337 + struct ebpf_target *root = ptr;
338 ebpf_create_charts_on_apps(NETDATA_OOMKILL_CHART,
339 "OOM kills",
340 EBPF_COMMON_DIMENSION_KILLS,
@@ -361,7 +361,7 @@ void *ebpf_oomkill_thread(void *ptr)
361 em->maps = oomkill_maps;
362
363 #define NETDATA_DEFAULT_OOM_DISABLED_MSG "Disabling OOMKILL thread, because"
364 - if (unlikely(!all_pids || !em->apps_charts)) {
364 + if (unlikely(!ebpf_all_pids || !em->apps_charts)) {
365 // When we are not running integration with apps, we won't fill necessary variables for this thread to run, so
366 // we need to disable it.
367 if (em->thread->enabled)
collectors/ebpf.plugin/ebpf_process.c
+21 -59
@@ -43,7 +43,6 @@ static netdata_syscall_stat_t process_aggregated_data[NETDATA_KEY_PUBLISH_PROCES
43 static netdata_publish_syscall_t process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_END];
44
45 ebpf_process_stat_t **global_process_stats = NULL;
46 -ebpf_process_publish_apps_t **current_apps_data = NULL;
46
47 int process_enabled = 0;
48 bool publish_internal_metrics = true;
@@ -138,19 +137,19 @@ static void ebpf_process_send_data(ebpf_module_t *em)
137 * Sum values for pid
138 *
139 * @param root the structure with all available PIDs
141 - *
140 * @param offset the address that we are reading
141 *
142 * @return it returns the sum of all PIDs
143 */
146 -long long ebpf_process_sum_values_for_pids(struct pid_on_target *root, size_t offset)
144 +long long ebpf_process_sum_values_for_pids(struct ebpf_pid_on_target *root, size_t offset)
145 {
146 long long ret = 0;
147 while (root) {
148 int32_t pid = root->pid;
151 - ebpf_process_publish_apps_t *w = current_apps_data[pid];
149 + ebpf_process_stat_t *w = global_process_stats[pid];
150 if (w) {
153 - ret += get_value_from_structure((char *)w, offset);
151 + uint32_t *value = (uint32_t *)((char *)w + offset);
152 + ret += *value;
153 }
154
155 root = root->next;
@@ -166,13 +165,13 @@ long long ebpf_process_sum_values_for_pids(struct pid_on_target *root, size_t of
165 */
166 void ebpf_process_remove_pids()
167 {
169 - struct pid_stat *pids = root_of_pids;
168 + struct ebpf_pid_stat *pids = ebpf_root_of_pids;
169 int pid_fd = process_maps[NETDATA_PROCESS_PID_TABLE].map_fd;
170 while (pids) {
171 uint32_t pid = pids->pid;
172 ebpf_process_stat_t *w = global_process_stats[pid];
173 if (w) {
175 - freez(w);
174 + ebpf_process_stat_release(w);
175 global_process_stats[pid] = NULL;
176 bpf_map_delete_elem(pid_fd, &pid);
177 }
@@ -186,15 +185,15 @@ void ebpf_process_remove_pids()
185 *
186 * @param root the target list.
187 */
189 -void ebpf_process_send_apps_data(struct target *root, ebpf_module_t *em)
188 +void ebpf_process_send_apps_data(struct ebpf_target *root, ebpf_module_t *em)
189 {
191 - struct target *w;
190 + struct ebpf_target *w;
191 collected_number value;
192
193 write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_PROCESS);
194 for (w = root; w; w = w->next) {
195 if (unlikely(w->exposed && w->processes)) {
197 - value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_publish_apps_t, create_process));
196 + value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t, create_process));
197 write_chart_dimension(w->name, value);
198 }
199 }
@@ -203,7 +202,7 @@ void ebpf_process_send_apps_data(struct target *root, ebpf_module_t *em)
202 write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_THREAD);
203 for (w = root; w; w = w->next) {
204 if (unlikely(w->exposed && w->processes)) {
206 - value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_publish_apps_t, create_thread));
205 + value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t, create_thread));
206 write_chart_dimension(w->name, value);
207 }
208 }
@@ -212,8 +211,8 @@ void ebpf_process_send_apps_data(struct target *root, ebpf_module_t *em)
211 write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_EXIT);
212 for (w = root; w; w = w->next) {
213 if (unlikely(w->exposed && w->processes)) {
215 - value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_publish_apps_t,
216 - call_do_exit));
214 + value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t,
215 + exit_call));
216 write_chart_dimension(w->name, value);
217 }
218 }
@@ -222,8 +221,8 @@ void ebpf_process_send_apps_data(struct target *root, ebpf_module_t *em)
221 write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_CLOSE);
222 for (w = root; w; w = w->next) {
223 if (unlikely(w->exposed && w->processes)) {
225 - value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_publish_apps_t,
226 - call_release_task));
224 + value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t,
225 + release_call));
226 write_chart_dimension(w->name, value);
227 }
228 }
@@ -233,7 +232,7 @@ void ebpf_process_send_apps_data(struct target *root, ebpf_module_t *em)
232 write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_ERROR);
233 for (w = root; w; w = w->next) {
234 if (unlikely(w->exposed && w->processes)) {
236 - value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_publish_apps_t,
235 + value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t,
236 task_err));
237 write_chart_dimension(w->name, value);
238 }
@@ -283,38 +282,6 @@ static void read_hash_global_tables()
282 process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_CLONE].ecall = res[NETDATA_KEY_ERROR_SYS_CLONE];
283 }
284
286 -/**
287 - * Read the hash table and store data to allocated vectors.
288 - */
289 -static void ebpf_process_update_apps_data()
290 -{
291 - struct pid_stat *pids = root_of_pids;
292 - while (pids) {
293 - uint32_t current_pid = pids->pid;
294 - ebpf_process_stat_t *ps = global_process_stats[current_pid];
295 - if (!ps) {
296 - pids = pids->next;
297 - continue;
298 - }
299 -
300 - ebpf_process_publish_apps_t *cad = current_apps_data[current_pid];
301 - if (!cad) {
302 - cad = callocz(1, sizeof(ebpf_process_publish_apps_t));
303 - current_apps_data[current_pid] = cad;
304 - }
305 -
306 - //Read data
307 - cad->call_do_exit = ps->exit_call;
308 - cad->call_release_task = ps->release_call;
309 - cad->create_process = ps->create_process;
310 - cad->create_thread = ps->create_thread;
311 -
312 - cad->task_err = ps->task_err;
313 -
314 - pids = pids->next;
315 - }
316 -}
317 -
285 /**
286 * Update cgroup
287 *
@@ -532,7 +499,7 @@ static void ebpf_create_statistic_charts(ebpf_module_t *em)
499 */
500 void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
501 {
535 - struct target *root = ptr;
502 + struct ebpf_target *root = ptr;
503 ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_TASK_PROCESS,
504 "Process started",
505 EBPF_COMMON_DIMENSION_CALL,
@@ -591,12 +558,12 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
558 *
559 * @param root a pointer for the targets.
560 */
594 -static void ebpf_create_apps_charts(struct target *root)
561 +static void ebpf_create_apps_charts(struct ebpf_target *root)
562 {
596 - if (unlikely(!all_pids))
563 + if (unlikely(!ebpf_all_pids))
564 return;
565
599 - struct target *w;
566 + struct ebpf_target *w;
567 int newly_added = 0;
568
569 for (w = root; w; w = w->next) {
@@ -604,7 +571,7 @@ static void ebpf_create_apps_charts(struct target *root)
571 continue;
572
573 if (unlikely(w->processes && (debug_enabled || w->debug_enabled))) {
607 - struct pid_on_target *pid_on_target;
574 + struct ebpf_pid_on_target *pid_on_target;
575
576 fprintf(
577 stderr, "ebpf.plugin: target '%s' has aggregated %u process%s:", w->name, w->processes,
@@ -1079,11 +1046,7 @@ static void process_collector(ebpf_module_t *em)
1046 pthread_mutex_lock(&collect_data_mutex);
1047
1048 ebpf_create_apps_charts(apps_groups_root_target);
1082 - if (all_pids_count > 0) {
1083 - if (apps_enabled) {
1084 - ebpf_process_update_apps_data();
1085 - }
1086 -
1049 + if (ebpf_all_pids_count > 0) {
1050 if (cgroups && shm_ebpf_cgroup.header) {
1051 ebpf_update_process_cgroup();
1052 }
@@ -1133,7 +1096,6 @@ static void ebpf_process_allocate_global_vectors(size_t length)
1096 process_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
1097
1098 global_process_stats = callocz((size_t)pid_max, sizeof(ebpf_process_stat_t *));
1136 - current_apps_data = callocz((size_t)pid_max, sizeof(ebpf_process_publish_apps_t *));
1099 }
1100
1101 static void change_syscalls()
collectors/ebpf.plugin/ebpf_process.h
-11
@@ -85,17 +85,6 @@ typedef enum netdata_publish_process {
85 NETDATA_KEY_PUBLISH_PROCESS_END
86 } netdata_publish_process_t;
87
88 -typedef struct ebpf_process_publish_apps {
89 - // Number of calls during the last read
90 - uint64_t call_do_exit;
91 - uint64_t call_release_task;
92 - uint64_t create_process;
93 - uint64_t create_thread;
94 -
95 - // Number of errors during the last read
96 - uint64_t task_err;
97 -} ebpf_process_publish_apps_t;
98 -
88 enum ebpf_process_tables {
89 NETDATA_PROCESS_PID_TABLE,
90 NETDATA_PROCESS_GLOBAL_TABLE,
collectors/ebpf.plugin/ebpf_shm.c
+5 -5
@@ -411,7 +411,7 @@ static void read_apps_table()
411 {
412 netdata_publish_shm_t *cv = shm_vector;
413 uint32_t key;
414 - struct pid_stat *pids = root_of_pids;
414 + struct ebpf_pid_stat *pids = ebpf_root_of_pids;
415 int fd = shm_maps[NETDATA_PID_SHM_TABLE].map_fd;
416 size_t length = sizeof(netdata_publish_shm_t)*ebpf_nprocs;
417 while (pids) {
@@ -487,7 +487,7 @@ static void ebpf_shm_read_global_table()
487 /**
488 * Sum values for all targets.
489 */
490 -static void ebpf_shm_sum_pids(netdata_publish_shm_t *shm, struct pid_on_target *root)
490 +static void ebpf_shm_sum_pids(netdata_publish_shm_t *shm, struct ebpf_pid_on_target *root)
491 {
492 while (root) {
493 int32_t pid = root->pid;
@@ -513,9 +513,9 @@ static void ebpf_shm_sum_pids(netdata_publish_shm_t *shm, struct pid_on_target *
513 *
514 * @param root the target list.
515 */
516 -void ebpf_shm_send_apps_data(struct target *root)
516 +void ebpf_shm_send_apps_data(struct ebpf_target *root)
517 {
518 - struct target *w;
518 + struct ebpf_target *w;
519 for (w = root; w; w = w->next) {
520 if (unlikely(w->exposed && w->processes)) {
521 ebpf_shm_sum_pids(&w->shm, w->root_pid);
@@ -895,7 +895,7 @@ static void shm_collector(ebpf_module_t *em)
895 */
896 void ebpf_shm_create_apps_charts(struct ebpf_module *em, void *ptr)
897 {
898 - struct target *root = ptr;
898 + struct ebpf_target *root = ptr;
899 ebpf_create_charts_on_apps(NETDATA_SHMGET_CHART,
900 "Calls to syscall <code>shmget(2)</code>.",
901 EBPF_COMMON_DIMENSION_CALL,
collectors/ebpf.plugin/ebpf_socket.c
+5 -5
@@ -958,7 +958,7 @@ static void ebpf_socket_send_data(ebpf_module_t *em)
958 *
959 * @return it returns the sum of all PIDs
960 */
961 -long long ebpf_socket_sum_values_for_pids(struct pid_on_target *root, size_t offset)
961 +long long ebpf_socket_sum_values_for_pids(struct ebpf_pid_on_target *root, size_t offset)
962 {
963 long long ret = 0;
964 while (root) {
@@ -980,11 +980,11 @@ long long ebpf_socket_sum_values_for_pids(struct pid_on_target *root, size_t off
980 * @param em the structure with thread information
981 * @param root the target list.
982 */
983 -void ebpf_socket_send_apps_data(ebpf_module_t *em, struct target *root)
983 +void ebpf_socket_send_apps_data(ebpf_module_t *em, struct ebpf_target *root)
984 {
985 UNUSED(em);
986
987 - struct target *w;
987 + struct ebpf_target *w;
988 collected_number value;
989
990 write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_CONNECTION_TCP_V4);
@@ -1217,7 +1217,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
1217 */
1218 void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
1219 {
1220 - struct target *root = ptr;
1220 + struct ebpf_target *root = ptr;
1221 int order = 20080;
1222 ebpf_create_charts_on_apps(NETDATA_NET_APPS_CONNECTION_TCP_V4,
1223 "Calls to tcp_v4_connection", EBPF_COMMON_DIMENSION_CONNECTIONS,
@@ -2275,7 +2275,7 @@ static void ebpf_socket_update_apps_data()
2275 int fd = socket_maps[NETDATA_SOCKET_TABLE_BANDWIDTH].map_fd;
2276 ebpf_bandwidth_t *eb = bandwidth_vector;
2277 uint32_t key;
2278 - struct pid_stat *pids = root_of_pids;
2278 + struct ebpf_pid_stat *pids = ebpf_root_of_pids;
2279 while (pids) {
2280 key = pids->pid;
2281
collectors/ebpf.plugin/ebpf_swap.c
+5 -5
@@ -341,7 +341,7 @@ static void read_apps_table()
341 {
342 netdata_publish_swap_t *cv = swap_vector;
343 uint32_t key;
344 - struct pid_stat *pids = root_of_pids;
344 + struct ebpf_pid_stat *pids = ebpf_root_of_pids;
345 int fd = swap_maps[NETDATA_PID_SWAP_TABLE].map_fd;
346 size_t length = sizeof(netdata_publish_swap_t)*ebpf_nprocs;
347 while (pids) {
@@ -410,7 +410,7 @@ static void ebpf_swap_read_global_table()
410 * @param swap
411 * @param root
412 */
413 -static void ebpf_swap_sum_pids(netdata_publish_swap_t *swap, struct pid_on_target *root)
413 +static void ebpf_swap_sum_pids(netdata_publish_swap_t *swap, struct ebpf_pid_on_target *root)
414 {
415 uint64_t local_read = 0;
416 uint64_t local_write = 0;
@@ -435,9 +435,9 @@ static void ebpf_swap_sum_pids(netdata_publish_swap_t *swap, struct pid_on_targe
435 *
436 * @param root the target list.
437 */
438 -void ebpf_swap_send_apps_data(struct target *root)
438 +void ebpf_swap_send_apps_data(struct ebpf_target *root)
439 {
440 - struct target *w;
440 + struct ebpf_target *w;
441 for (w = root; w; w = w->next) {
442 if (unlikely(w->exposed && w->processes)) {
443 ebpf_swap_sum_pids(&w->swap, w->root_pid);
@@ -707,7 +707,7 @@ static void swap_collector(ebpf_module_t *em)
707 */
708 void ebpf_swap_create_apps_charts(struct ebpf_module *em, void *ptr)
709 {
710 - struct target *root = ptr;
710 + struct ebpf_target *root = ptr;
711 ebpf_create_charts_on_apps(NETDATA_MEM_SWAP_READ_CHART,
712 "Calls to function <code>swap_readpage</code>.",
713 EBPF_COMMON_DIMENSION_CALL,
collectors/ebpf.plugin/ebpf_vfs.c
+5 -5
@@ -540,7 +540,7 @@ static void ebpf_vfs_read_global_table()
540 * @param swap output structure
541 * @param root link list with structure to be used
542 */
543 -static void ebpf_vfs_sum_pids(netdata_publish_vfs_t *vfs, struct pid_on_target *root)
543 +static void ebpf_vfs_sum_pids(netdata_publish_vfs_t *vfs, struct ebpf_pid_on_target *root)
544 {
545 netdata_publish_vfs_t accumulator;
546 memset(&accumulator, 0, sizeof(accumulator));
@@ -606,9 +606,9 @@ static void ebpf_vfs_sum_pids(netdata_publish_vfs_t *vfs, struct pid_on_target *
606 * @param em the structure with thread information
607 * @param root the target list.
608 */
609 -void ebpf_vfs_send_apps_data(ebpf_module_t *em, struct target *root)
609 +void ebpf_vfs_send_apps_data(ebpf_module_t *em, struct ebpf_target *root)
610 {
611 - struct target *w;
611 + struct ebpf_target *w;
612 for (w = root; w; w = w->next) {
613 if (unlikely(w->exposed && w->processes)) {
614 ebpf_vfs_sum_pids(&w->vfs, w->root_pid);
@@ -787,7 +787,7 @@ static void vfs_fill_pid(uint32_t current_pid, netdata_publish_vfs_t *publish)
787 */
788 static void ebpf_vfs_read_apps()
789 {
790 - struct pid_stat *pids = root_of_pids;
790 + struct ebpf_pid_stat *pids = ebpf_root_of_pids;
791 netdata_publish_vfs_t *vv = vfs_vector;
792 int fd = vfs_maps[NETDATA_VFS_PID].map_fd;
793 size_t length = sizeof(netdata_publish_vfs_t) * ebpf_nprocs;
@@ -1683,7 +1683,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
1683 **/
1684 void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr)
1685 {
1686 - struct target *root = ptr;
1686 + struct ebpf_target *root = ptr;
1687
1688 ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_DELETED,
1689 "Files deleted",
libnetdata/libnetdata.c
-4
@@ -225,10 +225,6 @@ void posix_memfree(void *ptr) {
225 libc_free(ptr);
226 }
227
228 -#define MALLOC_ALIGNMENT (sizeof(uintptr_t) * 2)
229 -#define size_t_atomic_count(op, var, size) __atomic_## op ##_fetch(&(var), size, __ATOMIC_RELAXED)
230 -#define size_t_atomic_bytes(op, var, size) __atomic_## op ##_fetch(&(var), ((size) % MALLOC_ALIGNMENT)?((size) + MALLOC_ALIGNMENT - ((size) % MALLOC_ALIGNMENT)):(size), __ATOMIC_RELAXED)
231 -
228 struct malloc_header_signature {
229 uint32_t magic;
230 uint32_t size;
libnetdata/libnetdata.h
+3
@@ -32,6 +32,9 @@ extern "C" {
32 #define OS_FREEBSD 2
33 #define OS_MACOS 3
34
35 +#define MALLOC_ALIGNMENT (sizeof(uintptr_t) * 2)
36 +#define size_t_atomic_count(op, var, size) __atomic_## op ##_fetch(&(var), size, __ATOMIC_RELAXED)
37 +#define size_t_atomic_bytes(op, var, size) __atomic_## op ##_fetch(&(var), ((size) % MALLOC_ALIGNMENT)?((size) + MALLOC_ALIGNMENT - ((size) % MALLOC_ALIGNMENT)):(size), __ATOMIC_RELAXED)
38
39 // ----------------------------------------------------------------------------
40 // system include files for all netdata C programs