ebpf_fd.c 41 KB

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