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