ebpf_fd.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "ebpf.h"
  3. #include "ebpf_fd.h"
  4. static char *fd_dimension_names[NETDATA_FD_SYSCALL_END] = { "open", "close" };
  5. static char *fd_id_names[NETDATA_FD_SYSCALL_END] = { "do_sys_open", "__close_fd" };
  6. static netdata_syscall_stat_t fd_aggregated_data[NETDATA_FD_SYSCALL_END];
  7. static netdata_publish_syscall_t fd_publish_aggregated[NETDATA_FD_SYSCALL_END];
  8. static ebpf_local_maps_t fd_maps[] = {{.name = "tbl_fd_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
  9. .user_input = 0,
  10. .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
  11. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  12. {.name = "tbl_fd_global", .internal_input = NETDATA_KEY_END_VECTOR,
  13. .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
  14. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  15. {.name = "fd_ctrl", .internal_input = NETDATA_CONTROLLER_END,
  16. .user_input = 0,
  17. .type = NETDATA_EBPF_MAP_CONTROLLER,
  18. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  19. {.name = NULL, .internal_input = 0, .user_input = 0,
  20. .type = NETDATA_EBPF_MAP_CONTROLLER,
  21. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
  22. struct config fd_config = { .first_section = NULL, .last_section = NULL, .mutex = NETDATA_MUTEX_INITIALIZER,
  23. .index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare },
  24. .rwlock = AVL_LOCK_INITIALIZER } };
  25. struct netdata_static_thread fd_thread = {"FD KERNEL",
  26. .config_section = NULL,
  27. .config_name = NULL,
  28. .env_name = NULL,
  29. .enabled = 1,
  30. .thread = NULL,
  31. .init_routine = NULL,
  32. .start_routine = NULL};
  33. static enum ebpf_threads_status ebpf_fd_exited = NETDATA_THREAD_EBPF_RUNNING;
  34. static netdata_idx_t fd_hash_values[NETDATA_FD_COUNTER];
  35. static netdata_idx_t *fd_values = NULL;
  36. netdata_fd_stat_t *fd_vector = NULL;
  37. netdata_fd_stat_t **fd_pid = NULL;
  38. netdata_ebpf_targets_t fd_targets[] = { {.name = "open", .mode = EBPF_LOAD_TRAMPOLINE},
  39. {.name = "close", .mode = EBPF_LOAD_TRAMPOLINE},
  40. {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
  41. #ifdef LIBBPF_MAJOR_VERSION
  42. #include "includes/fd.skel.h" // BTF code
  43. static struct fd_bpf *bpf_obj = NULL;
  44. /**
  45. * Disable probe
  46. *
  47. * Disable all probes to use exclusively another method.
  48. *
  49. * @param obj is the main structure for bpf objects
  50. */
  51. static inline void ebpf_fd_disable_probes(struct fd_bpf *obj)
  52. {
  53. bpf_program__set_autoload(obj->progs.netdata_sys_open_kprobe, false);
  54. bpf_program__set_autoload(obj->progs.netdata_sys_open_kretprobe, false);
  55. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false);
  56. if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
  57. bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
  58. bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
  59. bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
  60. } else {
  61. bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
  62. bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false);
  63. bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
  64. }
  65. }
  66. /*
  67. * Disable specific probe
  68. *
  69. * Disable probes according the kernel version
  70. *
  71. * @param obj is the main structure for bpf objects
  72. */
  73. static inline void ebpf_disable_specific_probes(struct fd_bpf *obj)
  74. {
  75. if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
  76. bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
  77. bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
  78. } else {
  79. bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false);
  80. bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
  81. }
  82. }
  83. /*
  84. * Disable trampoline
  85. *
  86. * Disable all trampoline to use exclusively another method.
  87. *
  88. * @param obj is the main structure for bpf objects.
  89. */
  90. static inline void ebpf_disable_trampoline(struct fd_bpf *obj)
  91. {
  92. bpf_program__set_autoload(obj->progs.netdata_sys_open_fentry, false);
  93. bpf_program__set_autoload(obj->progs.netdata_sys_open_fexit, false);
  94. bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false);
  95. bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false);
  96. bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false);
  97. bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false);
  98. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
  99. }
  100. /*
  101. * Disable specific trampoline
  102. *
  103. * Disable trampoline according to kernel version.
  104. *
  105. * @param obj is the main structure for bpf objects.
  106. */
  107. static inline void ebpf_disable_specific_trampoline(struct fd_bpf *obj)
  108. {
  109. if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
  110. bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false);
  111. bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false);
  112. } else {
  113. bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false);
  114. bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false);
  115. }
  116. }
  117. /**
  118. * Set trampoline target
  119. *
  120. * Set the targets we will monitor.
  121. *
  122. * @param obj is the main structure for bpf objects.
  123. */
  124. static void ebpf_set_trampoline_target(struct fd_bpf *obj)
  125. {
  126. bpf_program__set_attach_target(obj->progs.netdata_sys_open_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
  127. bpf_program__set_attach_target(obj->progs.netdata_sys_open_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
  128. bpf_program__set_attach_target(obj->progs.netdata_release_task_fd_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP);
  129. if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
  130. bpf_program__set_attach_target(
  131. obj->progs.netdata_close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  132. bpf_program__set_attach_target(obj->progs.netdata_close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  133. } else {
  134. bpf_program__set_attach_target(
  135. obj->progs.netdata___close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  136. bpf_program__set_attach_target(
  137. obj->progs.netdata___close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  138. }
  139. }
  140. /**
  141. * Mount Attach Probe
  142. *
  143. * Attach probes to target
  144. *
  145. * @param obj is the main structure for bpf objects.
  146. *
  147. * @return It returns 0 on success and -1 otherwise.
  148. */
  149. static int ebpf_fd_attach_probe(struct fd_bpf *obj)
  150. {
  151. obj->links.netdata_sys_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kprobe, false,
  152. fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
  153. int ret = libbpf_get_error(obj->links.netdata_sys_open_kprobe);
  154. if (ret)
  155. return -1;
  156. obj->links.netdata_sys_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kretprobe, true,
  157. fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
  158. ret = libbpf_get_error(obj->links.netdata_sys_open_kretprobe);
  159. if (ret)
  160. return -1;
  161. obj->links.netdata_release_task_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_fd_kprobe,
  162. false,
  163. EBPF_COMMON_FNCT_CLEAN_UP);
  164. ret = libbpf_get_error(obj->links.netdata_release_task_fd_kprobe);
  165. if (ret)
  166. return -1;
  167. if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
  168. obj->links.netdata_close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kretprobe, true,
  169. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  170. ret = libbpf_get_error(obj->links.netdata_close_fd_kretprobe);
  171. if (ret)
  172. return -1;
  173. obj->links.netdata_close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kprobe, false,
  174. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  175. ret = libbpf_get_error(obj->links.netdata_close_fd_kprobe);
  176. if (ret)
  177. return -1;
  178. } else {
  179. obj->links.netdata___close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kretprobe,
  180. true,
  181. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  182. ret = libbpf_get_error(obj->links.netdata___close_fd_kretprobe);
  183. if (ret)
  184. return -1;
  185. obj->links.netdata___close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kprobe,
  186. false,
  187. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  188. ret = libbpf_get_error(obj->links.netdata___close_fd_kprobe);
  189. if (ret)
  190. return -1;
  191. }
  192. return 0;
  193. }
  194. /**
  195. * Set target values
  196. *
  197. * Set pointers used to laod data.
  198. */
  199. static void ebpf_fd_set_target_values()
  200. {
  201. static char *close_targets[] = {"close_fd", "__close_fd"};
  202. static char *open_targets[] = {"do_sys_openat2", "do_sys_open"};
  203. if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
  204. fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[0];
  205. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[0];
  206. } else {
  207. fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[1];
  208. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[1];
  209. }
  210. }
  211. /**
  212. * Set hash tables
  213. *
  214. * Set the values for maps according the value given by kernel.
  215. *
  216. * @param obj is the main structure for bpf objects.
  217. */
  218. static void ebpf_fd_set_hash_tables(struct fd_bpf *obj)
  219. {
  220. fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_global);
  221. fd_maps[NETDATA_FD_PID_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_pid);
  222. fd_maps[NETDATA_FD_CONTROLLER].map_fd = bpf_map__fd(obj->maps.fd_ctrl);
  223. }
  224. /**
  225. * Adjust Map Size
  226. *
  227. * Resize maps according input from users.
  228. *
  229. * @param obj is the main structure for bpf objects.
  230. * @param em structure with configuration
  231. */
  232. static void ebpf_fd_adjust_map_size(struct fd_bpf *obj, ebpf_module_t *em)
  233. {
  234. ebpf_update_map_size(obj->maps.tbl_fd_pid, &fd_maps[NETDATA_FD_PID_STATS],
  235. em, bpf_map__name(obj->maps.tbl_fd_pid));
  236. }
  237. /**
  238. * Disable Release Task
  239. *
  240. * Disable release task when apps is not enabled.
  241. *
  242. * @param obj is the main structure for bpf objects.
  243. */
  244. static void ebpf_fd_disable_release_task(struct fd_bpf *obj)
  245. {
  246. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false);
  247. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
  248. }
  249. /**
  250. * Load and attach
  251. *
  252. * Load and attach the eBPF code in kernel.
  253. *
  254. * @param obj is the main structure for bpf objects.
  255. * @param em structure with configuration
  256. *
  257. * @return it returns 0 on succes and -1 otherwise
  258. */
  259. static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
  260. {
  261. netdata_ebpf_targets_t *mt = em->targets;
  262. netdata_ebpf_program_loaded_t test = mt[NETDATA_FD_SYSCALL_OPEN].mode;
  263. ebpf_fd_set_target_values();
  264. if (test == EBPF_LOAD_TRAMPOLINE) {
  265. ebpf_fd_disable_probes(obj);
  266. ebpf_disable_specific_trampoline(obj);
  267. ebpf_set_trampoline_target(obj);
  268. // TODO: Remove this in next PR, because this specific trampoline has an error.
  269. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
  270. } else {
  271. ebpf_disable_trampoline(obj);
  272. ebpf_disable_specific_probes(obj);
  273. }
  274. ebpf_fd_adjust_map_size(obj, em);
  275. if (!em->apps_charts && !em->cgroup_charts)
  276. ebpf_fd_disable_release_task(obj);
  277. int ret = fd_bpf__load(obj);
  278. if (ret) {
  279. return ret;
  280. }
  281. ret = (test == EBPF_LOAD_TRAMPOLINE) ? fd_bpf__attach(obj) : ebpf_fd_attach_probe(obj);
  282. if (!ret) {
  283. ebpf_fd_set_hash_tables(obj);
  284. ebpf_update_controller(fd_maps[NETDATA_CACHESTAT_CTRL].map_fd, em);
  285. }
  286. return ret;
  287. }
  288. #endif
  289. /*****************************************************************
  290. *
  291. * FUNCTIONS TO CLOSE THE THREAD
  292. *
  293. *****************************************************************/
  294. /**
  295. * FD Exit
  296. *
  297. * Cancel child thread and exit.
  298. *
  299. * @param ptr thread data.
  300. */
  301. static void ebpf_fd_exit(void *ptr)
  302. {
  303. ebpf_module_t *em = (ebpf_module_t *)ptr;
  304. if (!em->enabled) {
  305. em->enabled = NETDATA_MAIN_THREAD_EXITED;
  306. return;
  307. }
  308. ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPING;
  309. }
  310. /**
  311. * Clean up the main thread.
  312. *
  313. * @param ptr thread data.
  314. */
  315. static void ebpf_fd_cleanup(void *ptr)
  316. {
  317. ebpf_module_t *em = (ebpf_module_t *)ptr;
  318. if (ebpf_fd_exited != NETDATA_THREAD_EBPF_STOPPED)
  319. return;
  320. ebpf_cleanup_publish_syscall(fd_publish_aggregated);
  321. freez(fd_thread.thread);
  322. freez(fd_values);
  323. freez(fd_vector);
  324. #ifdef LIBBPF_MAJOR_VERSION
  325. if (bpf_obj)
  326. fd_bpf__destroy(bpf_obj);
  327. #endif
  328. fd_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
  329. em->enabled = NETDATA_MAIN_THREAD_EXITED;
  330. }
  331. /*****************************************************************
  332. *
  333. * MAIN LOOP
  334. *
  335. *****************************************************************/
  336. /**
  337. * Send data to Netdata calling auxiliary functions.
  338. *
  339. * @param em the structure with thread information
  340. */
  341. static void ebpf_fd_send_data(ebpf_module_t *em)
  342. {
  343. fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].ncall = fd_hash_values[NETDATA_KEY_CALLS_DO_SYS_OPEN];
  344. fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].nerr = fd_hash_values[NETDATA_KEY_ERROR_DO_SYS_OPEN];
  345. fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].ncall = fd_hash_values[NETDATA_KEY_CALLS_CLOSE_FD];
  346. fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].nerr = fd_hash_values[NETDATA_KEY_ERROR_CLOSE_FD];
  347. write_count_chart(NETDATA_FILE_OPEN_CLOSE_COUNT, NETDATA_FILESYSTEM_FAMILY, fd_publish_aggregated,
  348. NETDATA_FD_SYSCALL_END);
  349. if (em->mode < MODE_ENTRY) {
  350. write_err_chart(NETDATA_FILE_OPEN_ERR_COUNT, NETDATA_FILESYSTEM_FAMILY,
  351. fd_publish_aggregated, NETDATA_FD_SYSCALL_END);
  352. }
  353. }
  354. /**
  355. * Read global counter
  356. *
  357. * Read the table with number of calls for all functions
  358. */
  359. static void read_global_table()
  360. {
  361. uint32_t idx;
  362. netdata_idx_t *val = fd_hash_values;
  363. netdata_idx_t *stored = fd_values;
  364. int fd = fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd;
  365. for (idx = NETDATA_KEY_CALLS_DO_SYS_OPEN; idx < NETDATA_FD_COUNTER; idx++) {
  366. if (!bpf_map_lookup_elem(fd, &idx, stored)) {
  367. int i;
  368. int end = ebpf_nprocs;
  369. netdata_idx_t total = 0;
  370. for (i = 0; i < end; i++)
  371. total += stored[i];
  372. val[idx] = total;
  373. }
  374. }
  375. }
  376. /**
  377. * File descriptor read hash
  378. *
  379. * This is the thread callback.
  380. * This thread is necessary, because we cannot freeze the whole plugin to read the data.
  381. *
  382. * @param ptr It is a NULL value for this thread.
  383. *
  384. * @return It always returns NULL.
  385. */
  386. void *ebpf_fd_read_hash(void *ptr)
  387. {
  388. netdata_thread_cleanup_push(ebpf_fd_cleanup, ptr);
  389. heartbeat_t hb;
  390. heartbeat_init(&hb);
  391. ebpf_module_t *em = (ebpf_module_t *)ptr;
  392. usec_t step = NETDATA_FD_SLEEP_MS * em->update_every;
  393. while (ebpf_fd_exited == NETDATA_THREAD_EBPF_RUNNING) {
  394. usec_t dt = heartbeat_next(&hb, step);
  395. (void)dt;
  396. if (ebpf_fd_exited == NETDATA_THREAD_EBPF_STOPPING)
  397. break;
  398. read_global_table();
  399. }
  400. ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPED;
  401. netdata_thread_cleanup_pop(1);
  402. return NULL;
  403. }
  404. /**
  405. * Apps Accumulator
  406. *
  407. * Sum all values read from kernel and store in the first address.
  408. *
  409. * @param out the vector with read values.
  410. */
  411. static void fd_apps_accumulator(netdata_fd_stat_t *out)
  412. {
  413. int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
  414. netdata_fd_stat_t *total = &out[0];
  415. for (i = 1; i < end; i++) {
  416. netdata_fd_stat_t *w = &out[i];
  417. total->open_call += w->open_call;
  418. total->close_call += w->close_call;
  419. total->open_err += w->open_err;
  420. total->close_err += w->close_err;
  421. }
  422. }
  423. /**
  424. * Fill PID
  425. *
  426. * Fill PID structures
  427. *
  428. * @param current_pid pid that we are collecting data
  429. * @param out values read from hash tables;
  430. */
  431. static void fd_fill_pid(uint32_t current_pid, netdata_fd_stat_t *publish)
  432. {
  433. netdata_fd_stat_t *curr = fd_pid[current_pid];
  434. if (!curr) {
  435. curr = callocz(1, sizeof(netdata_fd_stat_t));
  436. fd_pid[current_pid] = curr;
  437. }
  438. memcpy(curr, &publish[0], sizeof(netdata_fd_stat_t));
  439. }
  440. /**
  441. * Read APPS table
  442. *
  443. * Read the apps table and store data inside the structure.
  444. */
  445. static void read_apps_table()
  446. {
  447. netdata_fd_stat_t *fv = fd_vector;
  448. uint32_t key;
  449. struct pid_stat *pids = root_of_pids;
  450. int fd = fd_maps[NETDATA_FD_PID_STATS].map_fd;
  451. size_t length = sizeof(netdata_fd_stat_t) * ebpf_nprocs;
  452. while (pids) {
  453. key = pids->pid;
  454. if (bpf_map_lookup_elem(fd, &key, fv)) {
  455. pids = pids->next;
  456. continue;
  457. }
  458. fd_apps_accumulator(fv);
  459. fd_fill_pid(key, fv);
  460. // We are cleaning to avoid passing data read from one process to other.
  461. memset(fv, 0, length);
  462. pids = pids->next;
  463. }
  464. }
  465. /**
  466. * Update cgroup
  467. *
  468. * Update cgroup data based in
  469. */
  470. static void ebpf_update_fd_cgroup()
  471. {
  472. ebpf_cgroup_target_t *ect ;
  473. netdata_fd_stat_t *fv = fd_vector;
  474. int fd = fd_maps[NETDATA_FD_PID_STATS].map_fd;
  475. size_t length = sizeof(netdata_fd_stat_t) * ebpf_nprocs;
  476. pthread_mutex_lock(&mutex_cgroup_shm);
  477. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  478. struct pid_on_target2 *pids;
  479. for (pids = ect->pids; pids; pids = pids->next) {
  480. int pid = pids->pid;
  481. netdata_fd_stat_t *out = &pids->fd;
  482. if (likely(fd_pid) && fd_pid[pid]) {
  483. netdata_fd_stat_t *in = fd_pid[pid];
  484. memcpy(out, in, sizeof(netdata_fd_stat_t));
  485. } else {
  486. memset(fv, 0, length);
  487. if (!bpf_map_lookup_elem(fd, &pid, fv)) {
  488. fd_apps_accumulator(fv);
  489. memcpy(out, fv, sizeof(netdata_fd_stat_t));
  490. }
  491. }
  492. }
  493. }
  494. pthread_mutex_unlock(&mutex_cgroup_shm);
  495. }
  496. /**
  497. * Sum PIDs
  498. *
  499. * Sum values for all targets.
  500. *
  501. * @param fd the output
  502. * @param root list of pids
  503. */
  504. static void ebpf_fd_sum_pids(netdata_fd_stat_t *fd, struct pid_on_target *root)
  505. {
  506. uint32_t open_call = 0;
  507. uint32_t close_call = 0;
  508. uint32_t open_err = 0;
  509. uint32_t close_err = 0;
  510. while (root) {
  511. int32_t pid = root->pid;
  512. netdata_fd_stat_t *w = fd_pid[pid];
  513. if (w) {
  514. open_call += w->open_call;
  515. close_call += w->close_call;
  516. open_err += w->open_err;
  517. close_err += w->close_err;
  518. }
  519. root = root->next;
  520. }
  521. // These conditions were added, because we are using incremental algorithm
  522. fd->open_call = (open_call >= fd->open_call) ? open_call : fd->open_call;
  523. fd->close_call = (close_call >= fd->close_call) ? close_call : fd->close_call;
  524. fd->open_err = (open_err >= fd->open_err) ? open_err : fd->open_err;
  525. fd->close_err = (close_err >= fd->close_err) ? close_err : fd->close_err;
  526. }
  527. /**
  528. * Send data to Netdata calling auxiliary functions.
  529. *
  530. * @param em the structure with thread information
  531. * @param root the target list.
  532. */
  533. void ebpf_fd_send_apps_data(ebpf_module_t *em, struct target *root)
  534. {
  535. struct target *w;
  536. for (w = root; w; w = w->next) {
  537. if (unlikely(w->exposed && w->processes)) {
  538. ebpf_fd_sum_pids(&w->fd, w->root_pid);
  539. }
  540. }
  541. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN);
  542. for (w = root; w; w = w->next) {
  543. if (unlikely(w->exposed && w->processes)) {
  544. write_chart_dimension(w->name, w->fd.open_call);
  545. }
  546. }
  547. write_end_chart();
  548. if (em->mode < MODE_ENTRY) {
  549. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
  550. for (w = root; w; w = w->next) {
  551. if (unlikely(w->exposed && w->processes)) {
  552. write_chart_dimension(w->name, w->fd.open_err);
  553. }
  554. }
  555. write_end_chart();
  556. }
  557. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSED);
  558. for (w = root; w; w = w->next) {
  559. if (unlikely(w->exposed && w->processes)) {
  560. write_chart_dimension(w->name, w->fd.close_call);
  561. }
  562. }
  563. write_end_chart();
  564. if (em->mode < MODE_ENTRY) {
  565. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
  566. for (w = root; w; w = w->next) {
  567. if (unlikely(w->exposed && w->processes)) {
  568. write_chart_dimension(w->name, w->fd.close_err);
  569. }
  570. }
  571. write_end_chart();
  572. }
  573. }
  574. /**
  575. * Sum PIDs
  576. *
  577. * Sum values for all targets.
  578. *
  579. * @param fd structure used to store data
  580. * @param pids input data
  581. */
  582. static void ebpf_fd_sum_cgroup_pids(netdata_fd_stat_t *fd, struct pid_on_target2 *pids)
  583. {
  584. netdata_fd_stat_t accumulator;
  585. memset(&accumulator, 0, sizeof(accumulator));
  586. while (pids) {
  587. netdata_fd_stat_t *w = &pids->fd;
  588. accumulator.open_err += w->open_err;
  589. accumulator.open_call += w->open_call;
  590. accumulator.close_call += w->close_call;
  591. accumulator.close_err += w->close_err;
  592. pids = pids->next;
  593. }
  594. fd->open_call = (accumulator.open_call >= fd->open_call) ? accumulator.open_call : fd->open_call;
  595. fd->open_err = (accumulator.open_err >= fd->open_err) ? accumulator.open_err : fd->open_err;
  596. fd->close_call = (accumulator.close_call >= fd->close_call) ? accumulator.close_call : fd->close_call;
  597. fd->close_err = (accumulator.close_err >= fd->close_err) ? accumulator.close_err : fd->close_err;
  598. }
  599. /**
  600. * Create specific file descriptor charts
  601. *
  602. * Create charts for cgroup/application.
  603. *
  604. * @param type the chart type.
  605. * @param em the main thread structure.
  606. */
  607. static void ebpf_create_specific_fd_charts(char *type, ebpf_module_t *em)
  608. {
  609. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN, "Number of open files",
  610. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  611. NETDATA_CGROUP_FD_OPEN_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  612. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5400,
  613. ebpf_create_global_dimension,
  614. &fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN],
  615. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  616. if (em->mode < MODE_ENTRY) {
  617. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR, "Fails to open files",
  618. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  619. NETDATA_CGROUP_FD_OPEN_ERR_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  620. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5401,
  621. ebpf_create_global_dimension,
  622. &fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN],
  623. 1, em->update_every,
  624. NETDATA_EBPF_MODULE_NAME_SWAP);
  625. }
  626. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSED, "Files closed",
  627. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  628. NETDATA_CGROUP_FD_CLOSE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  629. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5402,
  630. ebpf_create_global_dimension,
  631. &fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE],
  632. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  633. if (em->mode < MODE_ENTRY) {
  634. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR, "Fails to close files",
  635. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  636. NETDATA_CGROUP_FD_CLOSE_ERR_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  637. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5403,
  638. ebpf_create_global_dimension,
  639. &fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE],
  640. 1, em->update_every,
  641. NETDATA_EBPF_MODULE_NAME_SWAP);
  642. }
  643. }
  644. /**
  645. * Obsolete specific file descriptor charts
  646. *
  647. * Obsolete charts for cgroup/application.
  648. *
  649. * @param type the chart type.
  650. * @param em the main thread structure.
  651. */
  652. static void ebpf_obsolete_specific_fd_charts(char *type, ebpf_module_t *em)
  653. {
  654. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_OPEN, "Number of open files",
  655. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
  656. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_OPEN_CONTEXT,
  657. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5400, em->update_every);
  658. if (em->mode < MODE_ENTRY) {
  659. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR, "Fails to open files",
  660. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
  661. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_OPEN_ERR_CONTEXT,
  662. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5401, em->update_every);
  663. }
  664. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_CLOSED, "Files closed",
  665. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
  666. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_CLOSE_CONTEXT,
  667. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5402, em->update_every);
  668. if (em->mode < MODE_ENTRY) {
  669. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR, "Fails to close files",
  670. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
  671. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_CLOSE_ERR_CONTEXT,
  672. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5403, em->update_every);
  673. }
  674. }
  675. /*
  676. * Send specific file descriptor data
  677. *
  678. * Send data for specific cgroup/apps.
  679. *
  680. * @param type chart type
  681. * @param values structure with values that will be sent to netdata
  682. */
  683. static void ebpf_send_specific_fd_data(char *type, netdata_fd_stat_t *values, ebpf_module_t *em)
  684. {
  685. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN);
  686. write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].name, (long long)values->open_call);
  687. write_end_chart();
  688. if (em->mode < MODE_ENTRY) {
  689. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
  690. write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].name, (long long)values->open_err);
  691. write_end_chart();
  692. }
  693. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSED);
  694. write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].name, (long long)values->close_call);
  695. write_end_chart();
  696. if (em->mode < MODE_ENTRY) {
  697. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
  698. write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].name, (long long)values->close_err);
  699. write_end_chart();
  700. }
  701. }
  702. /**
  703. * Create systemd file descriptor charts
  704. *
  705. * Create charts when systemd is enabled
  706. *
  707. * @param em the main collector structure
  708. **/
  709. static void ebpf_create_systemd_fd_charts(ebpf_module_t *em)
  710. {
  711. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_OPEN, "Number of open files",
  712. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  713. NETDATA_EBPF_CHART_TYPE_STACKED, 20061,
  714. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_OPEN_CONTEXT,
  715. NETDATA_EBPF_MODULE_NAME_PROCESS, em->update_every);
  716. if (em->mode < MODE_ENTRY) {
  717. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR, "Fails to open files",
  718. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  719. NETDATA_EBPF_CHART_TYPE_STACKED, 20062,
  720. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_OPEN_ERR_CONTEXT,
  721. NETDATA_EBPF_MODULE_NAME_PROCESS, em->update_every);
  722. }
  723. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_CLOSED, "Files closed",
  724. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  725. NETDATA_EBPF_CHART_TYPE_STACKED, 20063,
  726. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_CLOSE_CONTEXT,
  727. NETDATA_EBPF_MODULE_NAME_PROCESS, em->update_every);
  728. if (em->mode < MODE_ENTRY) {
  729. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR, "Fails to close files",
  730. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  731. NETDATA_EBPF_CHART_TYPE_STACKED, 20064,
  732. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_CLOSE_ERR_CONTEXT,
  733. NETDATA_EBPF_MODULE_NAME_PROCESS, em->update_every);
  734. }
  735. }
  736. /**
  737. * Send Systemd charts
  738. *
  739. * Send collected data to Netdata.
  740. *
  741. * @param em the main collector structure
  742. *
  743. * @return It returns the status for chart creation, if it is necessary to remove a specific dimension zero is returned
  744. * otherwise function returns 1 to avoid chart recreation
  745. */
  746. static int ebpf_send_systemd_fd_charts(ebpf_module_t *em)
  747. {
  748. int ret = 1;
  749. ebpf_cgroup_target_t *ect;
  750. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN);
  751. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  752. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  753. write_chart_dimension(ect->name, ect->publish_systemd_fd.open_call);
  754. } else if (unlikely(ect->systemd))
  755. ret = 0;
  756. }
  757. write_end_chart();
  758. if (em->mode < MODE_ENTRY) {
  759. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
  760. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  761. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  762. write_chart_dimension(ect->name, ect->publish_systemd_fd.open_err);
  763. }
  764. }
  765. write_end_chart();
  766. }
  767. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSED);
  768. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  769. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  770. write_chart_dimension(ect->name, ect->publish_systemd_fd.close_call);
  771. }
  772. }
  773. write_end_chart();
  774. if (em->mode < MODE_ENTRY) {
  775. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
  776. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  777. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  778. write_chart_dimension(ect->name, ect->publish_systemd_fd.close_err);
  779. }
  780. }
  781. write_end_chart();
  782. }
  783. return ret;
  784. }
  785. /**
  786. * Send data to Netdata calling auxiliary functions.
  787. *
  788. * @param em the main collector structure
  789. */
  790. static void ebpf_fd_send_cgroup_data(ebpf_module_t *em)
  791. {
  792. if (!ebpf_cgroup_pids)
  793. return;
  794. pthread_mutex_lock(&mutex_cgroup_shm);
  795. ebpf_cgroup_target_t *ect;
  796. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  797. ebpf_fd_sum_cgroup_pids(&ect->publish_systemd_fd, ect->pids);
  798. }
  799. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  800. if (has_systemd) {
  801. static int systemd_charts = 0;
  802. if (!systemd_charts) {
  803. ebpf_create_systemd_fd_charts(em);
  804. systemd_charts = 1;
  805. }
  806. systemd_charts = ebpf_send_systemd_fd_charts(em);
  807. }
  808. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  809. if (ect->systemd)
  810. continue;
  811. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_FD_CHART) && ect->updated) {
  812. ebpf_create_specific_fd_charts(ect->name, em);
  813. ect->flags |= NETDATA_EBPF_CGROUP_HAS_FD_CHART;
  814. }
  815. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_FD_CHART ) {
  816. if (ect->updated) {
  817. ebpf_send_specific_fd_data(ect->name, &ect->publish_systemd_fd, em);
  818. } else {
  819. ebpf_obsolete_specific_fd_charts(ect->name, em);
  820. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_FD_CHART;
  821. }
  822. }
  823. }
  824. pthread_mutex_unlock(&mutex_cgroup_shm);
  825. }
  826. /**
  827. * Main loop for this collector.
  828. */
  829. static void fd_collector(ebpf_module_t *em)
  830. {
  831. fd_thread.thread = mallocz(sizeof(netdata_thread_t));
  832. fd_thread.start_routine = ebpf_fd_read_hash;
  833. netdata_thread_create(fd_thread.thread, fd_thread.name, NETDATA_THREAD_OPTION_DEFAULT,
  834. ebpf_fd_read_hash, em);
  835. int cgroups = em->cgroup_charts;
  836. heartbeat_t hb;
  837. heartbeat_init(&hb);
  838. usec_t step = em->update_every * USEC_PER_SEC;
  839. while (!ebpf_exit_plugin) {
  840. (void)heartbeat_next(&hb, step);
  841. if (ebpf_exit_plugin)
  842. break;
  843. netdata_apps_integration_flags_t apps = em->apps_charts;
  844. pthread_mutex_lock(&collect_data_mutex);
  845. if (apps)
  846. read_apps_table();
  847. if (cgroups)
  848. ebpf_update_fd_cgroup();
  849. pthread_mutex_lock(&lock);
  850. ebpf_fd_send_data(em);
  851. if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
  852. ebpf_fd_send_apps_data(em, apps_groups_root_target);
  853. if (cgroups)
  854. ebpf_fd_send_cgroup_data(em);
  855. pthread_mutex_unlock(&lock);
  856. pthread_mutex_unlock(&collect_data_mutex);
  857. }
  858. }
  859. /*****************************************************************
  860. *
  861. * CREATE CHARTS
  862. *
  863. *****************************************************************/
  864. /**
  865. * Create apps charts
  866. *
  867. * Call ebpf_create_chart to create the charts on apps submenu.
  868. *
  869. * @param em a pointer to the structure with the default values.
  870. */
  871. void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr)
  872. {
  873. struct target *root = ptr;
  874. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_OPEN,
  875. "Number of open files",
  876. EBPF_COMMON_DIMENSION_CALL,
  877. NETDATA_APPS_FILE_GROUP,
  878. NETDATA_EBPF_CHART_TYPE_STACKED,
  879. 20061,
  880. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  881. root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  882. if (em->mode < MODE_ENTRY) {
  883. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR,
  884. "Fails to open files",
  885. EBPF_COMMON_DIMENSION_CALL,
  886. NETDATA_APPS_FILE_GROUP,
  887. NETDATA_EBPF_CHART_TYPE_STACKED,
  888. 20062,
  889. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  890. root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  891. }
  892. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_CLOSED,
  893. "Files closed",
  894. EBPF_COMMON_DIMENSION_CALL,
  895. NETDATA_APPS_FILE_GROUP,
  896. NETDATA_EBPF_CHART_TYPE_STACKED,
  897. 20063,
  898. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  899. root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  900. if (em->mode < MODE_ENTRY) {
  901. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR,
  902. "Fails to close files",
  903. EBPF_COMMON_DIMENSION_CALL,
  904. NETDATA_APPS_FILE_GROUP,
  905. NETDATA_EBPF_CHART_TYPE_STACKED,
  906. 20064,
  907. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  908. root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  909. }
  910. em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
  911. }
  912. /**
  913. * Create global charts
  914. *
  915. * Call ebpf_create_chart to create the charts for the collector.
  916. *
  917. * @param em a pointer to the structure with the default values.
  918. */
  919. static void ebpf_create_fd_global_charts(ebpf_module_t *em)
  920. {
  921. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  922. NETDATA_FILE_OPEN_CLOSE_COUNT,
  923. "Open and close calls",
  924. EBPF_COMMON_DIMENSION_CALL,
  925. NETDATA_FILE_GROUP,
  926. NULL,
  927. NETDATA_EBPF_CHART_TYPE_LINE,
  928. NETDATA_CHART_PRIO_EBPF_FD_CHARTS,
  929. ebpf_create_global_dimension,
  930. fd_publish_aggregated,
  931. NETDATA_FD_SYSCALL_END,
  932. em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  933. if (em->mode < MODE_ENTRY) {
  934. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  935. NETDATA_FILE_OPEN_ERR_COUNT,
  936. "Open fails",
  937. EBPF_COMMON_DIMENSION_CALL,
  938. NETDATA_FILE_GROUP,
  939. NULL,
  940. NETDATA_EBPF_CHART_TYPE_LINE,
  941. NETDATA_CHART_PRIO_EBPF_FD_CHARTS + 1,
  942. ebpf_create_global_dimension,
  943. fd_publish_aggregated,
  944. NETDATA_FD_SYSCALL_END,
  945. em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  946. }
  947. }
  948. /*****************************************************************
  949. *
  950. * MAIN THREAD
  951. *
  952. *****************************************************************/
  953. /**
  954. * Allocate vectors used with this thread.
  955. *
  956. * We are not testing the return, because callocz does this and shutdown the software
  957. * case it was not possible to allocate.
  958. *
  959. * @param apps is apps enabled?
  960. */
  961. static void ebpf_fd_allocate_global_vectors(int apps)
  962. {
  963. if (apps)
  964. fd_pid = callocz((size_t)pid_max, sizeof(netdata_fd_stat_t *));
  965. fd_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_fd_stat_t));
  966. fd_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
  967. }
  968. /*
  969. * Load BPF
  970. *
  971. * Load BPF files.
  972. *
  973. * @param em the structure with configuration
  974. */
  975. static int ebpf_fd_load_bpf(ebpf_module_t *em)
  976. {
  977. int ret = 0;
  978. ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_FD_SYSCALL_OPEN].mode);
  979. if (em->load & EBPF_LOAD_LEGACY) {
  980. em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
  981. if (!em->probe_links) {
  982. em->enabled = CONFIG_BOOLEAN_NO;
  983. ret = -1;
  984. }
  985. }
  986. #ifdef LIBBPF_MAJOR_VERSION
  987. else {
  988. bpf_obj = fd_bpf__open();
  989. if (!bpf_obj)
  990. ret = -1;
  991. else
  992. ret = ebpf_fd_load_and_attach(bpf_obj, em);
  993. }
  994. #endif
  995. if (ret)
  996. error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
  997. return ret;
  998. }
  999. /**
  1000. * Directory Cache thread
  1001. *
  1002. * Thread used to make dcstat thread
  1003. *
  1004. * @param ptr a pointer to `struct ebpf_module`
  1005. *
  1006. * @return It always returns NULL
  1007. */
  1008. void *ebpf_fd_thread(void *ptr)
  1009. {
  1010. netdata_thread_cleanup_push(ebpf_fd_exit, ptr);
  1011. ebpf_module_t *em = (ebpf_module_t *)ptr;
  1012. em->maps = fd_maps;
  1013. if (!em->enabled)
  1014. goto endfd;
  1015. #ifdef LIBBPF_MAJOR_VERSION
  1016. ebpf_adjust_thread_load(em, default_btf);
  1017. #endif
  1018. if (ebpf_fd_load_bpf(em))
  1019. goto endfd;
  1020. ebpf_fd_allocate_global_vectors(em->apps_charts);
  1021. int algorithms[NETDATA_FD_SYSCALL_END] = {
  1022. NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX
  1023. };
  1024. ebpf_global_labels(fd_aggregated_data, fd_publish_aggregated, fd_dimension_names, fd_id_names,
  1025. algorithms, NETDATA_FD_SYSCALL_END);
  1026. pthread_mutex_lock(&lock);
  1027. ebpf_create_fd_global_charts(em);
  1028. ebpf_update_stats(&plugin_statistics, em);
  1029. pthread_mutex_unlock(&lock);
  1030. fd_collector(em);
  1031. endfd:
  1032. if (!em->enabled)
  1033. ebpf_update_disabled_plugin_stats(em);
  1034. netdata_thread_cleanup_pop(1);
  1035. return NULL;
  1036. }