ebpf_dcstat.c 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "ebpf.h"
  3. #include "ebpf_dcstat.h"
  4. static char *dcstat_counter_dimension_name[NETDATA_DCSTAT_IDX_END] = { "ratio", "reference", "slow", "miss" };
  5. static netdata_syscall_stat_t dcstat_counter_aggregated_data[NETDATA_DCSTAT_IDX_END];
  6. static netdata_publish_syscall_t dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_END];
  7. netdata_dcstat_pid_t *dcstat_vector = NULL;
  8. static netdata_idx_t dcstat_hash_values[NETDATA_DCSTAT_IDX_END];
  9. static netdata_idx_t *dcstat_values = NULL;
  10. struct config dcstat_config = { .first_section = NULL,
  11. .last_section = NULL,
  12. .mutex = NETDATA_MUTEX_INITIALIZER,
  13. .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
  14. .rwlock = AVL_LOCK_INITIALIZER } };
  15. ebpf_local_maps_t dcstat_maps[] = {{.name = "dcstat_global", .internal_input = NETDATA_DIRECTORY_CACHE_END,
  16. .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
  17. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
  18. #ifdef LIBBPF_MAJOR_VERSION
  19. .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
  20. #endif
  21. },
  22. {.name = "dcstat_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
  23. .user_input = 0,
  24. .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
  25. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
  26. #ifdef LIBBPF_MAJOR_VERSION
  27. .map_type = BPF_MAP_TYPE_PERCPU_HASH
  28. #endif
  29. },
  30. {.name = "dcstat_ctrl", .internal_input = NETDATA_CONTROLLER_END,
  31. .user_input = 0,
  32. .type = NETDATA_EBPF_MAP_CONTROLLER,
  33. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
  34. #ifdef LIBBPF_MAJOR_VERSION
  35. .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
  36. #endif
  37. },
  38. {.name = NULL, .internal_input = 0, .user_input = 0,
  39. .type = NETDATA_EBPF_MAP_CONTROLLER,
  40. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
  41. #ifdef LIBBPF_MAJOR_VERSION
  42. .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
  43. #endif
  44. }};
  45. static ebpf_specify_name_t dc_optional_name[] = { {.program_name = "netdata_lookup_fast",
  46. .function_to_attach = "lookup_fast",
  47. .optional = NULL,
  48. .retprobe = CONFIG_BOOLEAN_NO},
  49. {.program_name = NULL}};
  50. netdata_ebpf_targets_t dc_targets[] = { {.name = "lookup_fast", .mode = EBPF_LOAD_TRAMPOLINE},
  51. {.name = "d_lookup", .mode = EBPF_LOAD_TRAMPOLINE},
  52. {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
  53. #ifdef NETDATA_DEV_MODE
  54. int dcstat_disable_priority;
  55. #endif
  56. #ifdef LIBBPF_MAJOR_VERSION
  57. /**
  58. * Disable probe
  59. *
  60. * Disable all probes to use exclusively another method.
  61. *
  62. * @param obj is the main structure for bpf objects
  63. */
  64. static inline void ebpf_dc_disable_probes(struct dc_bpf *obj)
  65. {
  66. bpf_program__set_autoload(obj->progs.netdata_lookup_fast_kprobe, false);
  67. bpf_program__set_autoload(obj->progs.netdata_d_lookup_kretprobe, false);
  68. bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false);
  69. }
  70. /*
  71. * Disable trampoline
  72. *
  73. * Disable all trampoline to use exclusively another method.
  74. *
  75. * @param obj is the main structure for bpf objects.
  76. */
  77. static inline void ebpf_dc_disable_trampoline(struct dc_bpf *obj)
  78. {
  79. bpf_program__set_autoload(obj->progs.netdata_lookup_fast_fentry, false);
  80. bpf_program__set_autoload(obj->progs.netdata_d_lookup_fexit, false);
  81. bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false);
  82. }
  83. /**
  84. * Set trampoline target
  85. *
  86. * Set the targets we will monitor.
  87. *
  88. * @param obj is the main structure for bpf objects.
  89. */
  90. static void ebpf_dc_set_trampoline_target(struct dc_bpf *obj)
  91. {
  92. bpf_program__set_attach_target(obj->progs.netdata_lookup_fast_fentry, 0,
  93. dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name);
  94. bpf_program__set_attach_target(obj->progs.netdata_d_lookup_fexit, 0,
  95. dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
  96. bpf_program__set_attach_target(obj->progs.netdata_dcstat_release_task_fentry, 0,
  97. EBPF_COMMON_FNCT_CLEAN_UP);
  98. }
  99. /**
  100. * Mount Attach Probe
  101. *
  102. * Attach probes to target
  103. *
  104. * @param obj is the main structure for bpf objects.
  105. *
  106. * @return It returns 0 on success and -1 otherwise.
  107. */
  108. static int ebpf_dc_attach_probes(struct dc_bpf *obj)
  109. {
  110. obj->links.netdata_d_lookup_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_d_lookup_kretprobe,
  111. true,
  112. dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
  113. int ret = libbpf_get_error(obj->links.netdata_d_lookup_kretprobe);
  114. if (ret)
  115. return -1;
  116. char *lookup_name = (dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional) ?
  117. dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional :
  118. dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name ;
  119. obj->links.netdata_lookup_fast_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_lookup_fast_kprobe,
  120. false,
  121. lookup_name);
  122. ret = libbpf_get_error(obj->links.netdata_lookup_fast_kprobe);
  123. if (ret)
  124. return -1;
  125. obj->links.netdata_dcstat_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_dcstat_release_task_kprobe,
  126. false,
  127. EBPF_COMMON_FNCT_CLEAN_UP);
  128. ret = libbpf_get_error(obj->links.netdata_dcstat_release_task_kprobe);
  129. if (ret)
  130. return -1;
  131. return 0;
  132. }
  133. /**
  134. * Adjust Map Size
  135. *
  136. * Resize maps according input from users.
  137. *
  138. * @param obj is the main structure for bpf objects.
  139. * @param em structure with configuration
  140. */
  141. static void ebpf_dc_adjust_map(struct dc_bpf *obj, ebpf_module_t *em)
  142. {
  143. ebpf_update_map_size(obj->maps.dcstat_pid, &dcstat_maps[NETDATA_DCSTAT_PID_STATS],
  144. em, bpf_map__name(obj->maps.dcstat_pid));
  145. ebpf_update_map_type(obj->maps.dcstat_global, &dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS]);
  146. ebpf_update_map_type(obj->maps.dcstat_pid, &dcstat_maps[NETDATA_DCSTAT_PID_STATS]);
  147. ebpf_update_map_type(obj->maps.dcstat_ctrl, &dcstat_maps[NETDATA_DCSTAT_CTRL]);
  148. }
  149. /**
  150. * Set hash tables
  151. *
  152. * Set the values for maps according the value given by kernel.
  153. *
  154. * @param obj is the main structure for bpf objects.
  155. */
  156. static void ebpf_dc_set_hash_tables(struct dc_bpf *obj)
  157. {
  158. dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_global);
  159. dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_pid);
  160. dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd = bpf_map__fd(obj->maps.dcstat_ctrl);
  161. }
  162. /**
  163. * Update Load
  164. *
  165. * For directory cache, some distributions change the function name, and we do not have condition to use
  166. * TRAMPOLINE like other functions.
  167. *
  168. * @param em structure with configuration
  169. *
  170. * @return When then symbols were not modified, it returns TRAMPOLINE, else it returns RETPROBE.
  171. */
  172. netdata_ebpf_program_loaded_t ebpf_dc_update_load(ebpf_module_t *em)
  173. {
  174. if (!strcmp(dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional,
  175. dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach))
  176. return EBPF_LOAD_TRAMPOLINE;
  177. if (em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode != EBPF_LOAD_RETPROBE)
  178. netdata_log_info("When your kernel was compiled the symbol %s was modified, instead to use `trampoline`, the plugin will use `probes`.",
  179. dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach);
  180. return EBPF_LOAD_RETPROBE;
  181. }
  182. /**
  183. * Disable Release Task
  184. *
  185. * Disable release task when apps is not enabled.
  186. *
  187. * @param obj is the main structure for bpf objects.
  188. */
  189. static void ebpf_dc_disable_release_task(struct dc_bpf *obj)
  190. {
  191. bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false);
  192. bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false);
  193. }
  194. /**
  195. * Load and attach
  196. *
  197. * Load and attach the eBPF code in kernel.
  198. *
  199. * @param obj is the main structure for bpf objects.
  200. * @param em structure with configuration
  201. *
  202. * @return it returns 0 on success and -1 otherwise
  203. */
  204. static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em)
  205. {
  206. netdata_ebpf_program_loaded_t test = ebpf_dc_update_load(em);
  207. if (test == EBPF_LOAD_TRAMPOLINE) {
  208. ebpf_dc_disable_probes(obj);
  209. ebpf_dc_set_trampoline_target(obj);
  210. } else {
  211. ebpf_dc_disable_trampoline(obj);
  212. }
  213. ebpf_dc_adjust_map(obj, em);
  214. if (!em->apps_charts && !em->cgroup_charts)
  215. ebpf_dc_disable_release_task(obj);
  216. int ret = dc_bpf__load(obj);
  217. if (ret) {
  218. return ret;
  219. }
  220. ret = (test == EBPF_LOAD_TRAMPOLINE) ? dc_bpf__attach(obj) : ebpf_dc_attach_probes(obj);
  221. if (!ret) {
  222. ebpf_dc_set_hash_tables(obj);
  223. ebpf_update_controller(dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd, em);
  224. }
  225. return ret;
  226. }
  227. #endif
  228. /*****************************************************************
  229. *
  230. * COMMON FUNCTIONS
  231. *
  232. *****************************************************************/
  233. /**
  234. * Update publish
  235. *
  236. * Update publish values before to write dimension.
  237. *
  238. * @param out structure that will receive data.
  239. * @param cache_access number of access to directory cache.
  240. * @param not_found number of files not found on the file system
  241. */
  242. void dcstat_update_publish(netdata_publish_dcstat_t *out, uint64_t cache_access, uint64_t not_found)
  243. {
  244. NETDATA_DOUBLE successful_access = (NETDATA_DOUBLE) (((long long)cache_access) - ((long long)not_found));
  245. NETDATA_DOUBLE ratio = (cache_access) ? successful_access/(NETDATA_DOUBLE)cache_access : 0;
  246. out->ratio = (long long )(ratio*100);
  247. }
  248. /*****************************************************************
  249. *
  250. * FUNCTIONS TO CLOSE THE THREAD
  251. *
  252. *****************************************************************/
  253. static void ebpf_obsolete_specific_dc_charts(char *type, int update_every);
  254. /**
  255. * Obsolete services
  256. *
  257. * Obsolete all service charts created
  258. *
  259. * @param em a pointer to `struct ebpf_module`
  260. */
  261. static void ebpf_obsolete_dc_services(ebpf_module_t *em)
  262. {
  263. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  264. NETDATA_DC_HIT_CHART,
  265. "Percentage of files inside directory cache",
  266. EBPF_COMMON_DIMENSION_PERCENTAGE,
  267. NETDATA_DIRECTORY_CACHE_SUBMENU,
  268. NETDATA_EBPF_CHART_TYPE_LINE,
  269. NETDATA_SYSTEMD_DC_HIT_RATIO_CONTEXT,
  270. 21200,
  271. em->update_every);
  272. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  273. NETDATA_DC_REFERENCE_CHART,
  274. "Count file access",
  275. EBPF_COMMON_DIMENSION_FILES,
  276. NETDATA_DIRECTORY_CACHE_SUBMENU,
  277. NETDATA_EBPF_CHART_TYPE_LINE,
  278. NETDATA_SYSTEMD_DC_REFERENCE_CONTEXT,
  279. 21201,
  280. em->update_every);
  281. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  282. NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  283. "Files not present inside directory cache",
  284. EBPF_COMMON_DIMENSION_FILES,
  285. NETDATA_DIRECTORY_CACHE_SUBMENU,
  286. NETDATA_EBPF_CHART_TYPE_LINE,
  287. NETDATA_SYSTEMD_DC_NOT_CACHE_CONTEXT,
  288. 21202,
  289. em->update_every);
  290. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  291. NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  292. "Files not found",
  293. EBPF_COMMON_DIMENSION_FILES,
  294. NETDATA_DIRECTORY_CACHE_SUBMENU,
  295. NETDATA_EBPF_CHART_TYPE_LINE,
  296. NETDATA_SYSTEMD_DC_NOT_FOUND_CONTEXT,
  297. 21202,
  298. em->update_every);
  299. }
  300. /**
  301. * Obsolete cgroup chart
  302. *
  303. * Send obsolete for all charts created before to close.
  304. *
  305. * @param em a pointer to `struct ebpf_module`
  306. */
  307. static inline void ebpf_obsolete_dc_cgroup_charts(ebpf_module_t *em) {
  308. pthread_mutex_lock(&mutex_cgroup_shm);
  309. ebpf_obsolete_dc_services(em);
  310. ebpf_cgroup_target_t *ect;
  311. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  312. if (ect->systemd)
  313. continue;
  314. ebpf_obsolete_specific_dc_charts(ect->name, em->update_every);
  315. }
  316. pthread_mutex_unlock(&mutex_cgroup_shm);
  317. }
  318. /**
  319. * Obsolette apps charts
  320. *
  321. * Obsolete apps charts.
  322. *
  323. * @param em a pointer to the structure with the default values.
  324. */
  325. void ebpf_obsolete_dc_apps_charts(struct ebpf_module *em)
  326. {
  327. ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
  328. NETDATA_DC_HIT_CHART,
  329. "Percentage of files inside directory cache",
  330. EBPF_COMMON_DIMENSION_PERCENTAGE,
  331. NETDATA_DIRECTORY_CACHE_SUBMENU,
  332. NETDATA_EBPF_CHART_TYPE_LINE,
  333. NULL,
  334. 20100,
  335. em->update_every);
  336. ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
  337. NETDATA_DC_REFERENCE_CHART,
  338. "Count file access",
  339. EBPF_COMMON_DIMENSION_FILES,
  340. NETDATA_DIRECTORY_CACHE_SUBMENU,
  341. NETDATA_EBPF_CHART_TYPE_STACKED,
  342. NULL,
  343. 20101,
  344. em->update_every);
  345. ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
  346. NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  347. "Files not present inside directory cache",
  348. EBPF_COMMON_DIMENSION_FILES,
  349. NETDATA_DIRECTORY_CACHE_SUBMENU,
  350. NETDATA_EBPF_CHART_TYPE_STACKED,
  351. NULL,
  352. 20102,
  353. em->update_every);
  354. ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
  355. NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  356. "Files not found",
  357. EBPF_COMMON_DIMENSION_FILES,
  358. NETDATA_DIRECTORY_CACHE_SUBMENU,
  359. NETDATA_EBPF_CHART_TYPE_STACKED,
  360. NULL,
  361. 20103,
  362. em->update_every);
  363. }
  364. /**
  365. * Obsolete global
  366. *
  367. * Obsolete global charts created by thread.
  368. *
  369. * @param em a pointer to `struct ebpf_module`
  370. */
  371. static void ebpf_obsolete_dc_global(ebpf_module_t *em)
  372. {
  373. ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
  374. NETDATA_DC_HIT_CHART,
  375. "Percentage of files inside directory cache",
  376. EBPF_COMMON_DIMENSION_PERCENTAGE,
  377. NETDATA_DIRECTORY_CACHE_SUBMENU,
  378. NETDATA_EBPF_CHART_TYPE_LINE,
  379. NULL,
  380. 21200,
  381. em->update_every);
  382. ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
  383. NETDATA_DC_REFERENCE_CHART,
  384. "Variables used to calculate hit ratio.",
  385. EBPF_COMMON_DIMENSION_FILES,
  386. NETDATA_DIRECTORY_CACHE_SUBMENU,
  387. NETDATA_EBPF_CHART_TYPE_LINE,
  388. NULL,
  389. 21201,
  390. em->update_every);
  391. }
  392. /**
  393. * DCstat exit
  394. *
  395. * Cancel child and exit.
  396. *
  397. * @param ptr thread data.
  398. */
  399. static void ebpf_dcstat_exit(void *ptr)
  400. {
  401. ebpf_module_t *em = (ebpf_module_t *)ptr;
  402. if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
  403. pthread_mutex_lock(&lock);
  404. if (em->cgroup_charts) {
  405. ebpf_obsolete_dc_cgroup_charts(em);
  406. fflush(stdout);
  407. }
  408. if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
  409. ebpf_obsolete_dc_apps_charts(em);
  410. }
  411. ebpf_obsolete_dc_global(em);
  412. #ifdef NETDATA_DEV_MODE
  413. if (ebpf_aral_dcstat_pid)
  414. ebpf_statistic_obsolete_aral_chart(em, dcstat_disable_priority);
  415. #endif
  416. fflush(stdout);
  417. pthread_mutex_unlock(&lock);
  418. }
  419. ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
  420. #ifdef LIBBPF_MAJOR_VERSION
  421. if (dc_bpf_obj) {
  422. dc_bpf__destroy(dc_bpf_obj);
  423. dc_bpf_obj = NULL;
  424. }
  425. #endif
  426. if (em->objects){
  427. ebpf_unload_legacy_code(em->objects, em->probe_links);
  428. em->objects = NULL;
  429. em->probe_links = NULL;
  430. }
  431. pthread_mutex_lock(&ebpf_exit_cleanup);
  432. em->enabled = NETDATA_THREAD_EBPF_STOPPED;
  433. ebpf_update_stats(&plugin_statistics, em);
  434. pthread_mutex_unlock(&ebpf_exit_cleanup);
  435. }
  436. /*****************************************************************
  437. *
  438. * APPS
  439. *
  440. *****************************************************************/
  441. /**
  442. * Create apps charts
  443. *
  444. * Call ebpf_create_chart to create the charts on apps submenu.
  445. *
  446. * @param em a pointer to the structure with the default values.
  447. */
  448. void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr)
  449. {
  450. struct ebpf_target *root = ptr;
  451. ebpf_create_charts_on_apps(NETDATA_DC_HIT_CHART,
  452. "Percentage of files inside directory cache",
  453. EBPF_COMMON_DIMENSION_PERCENTAGE,
  454. NETDATA_DIRECTORY_CACHE_SUBMENU,
  455. NETDATA_EBPF_CHART_TYPE_LINE,
  456. 20100,
  457. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  458. root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  459. ebpf_create_charts_on_apps(NETDATA_DC_REFERENCE_CHART,
  460. "Count file access",
  461. EBPF_COMMON_DIMENSION_FILES,
  462. NETDATA_DIRECTORY_CACHE_SUBMENU,
  463. NETDATA_EBPF_CHART_TYPE_STACKED,
  464. 20101,
  465. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  466. root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  467. ebpf_create_charts_on_apps(NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  468. "Files not present inside directory cache",
  469. EBPF_COMMON_DIMENSION_FILES,
  470. NETDATA_DIRECTORY_CACHE_SUBMENU,
  471. NETDATA_EBPF_CHART_TYPE_STACKED,
  472. 20102,
  473. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  474. root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  475. ebpf_create_charts_on_apps(NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  476. "Files not found",
  477. EBPF_COMMON_DIMENSION_FILES,
  478. NETDATA_DIRECTORY_CACHE_SUBMENU,
  479. NETDATA_EBPF_CHART_TYPE_STACKED,
  480. 20103,
  481. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  482. root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  483. em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
  484. }
  485. /*****************************************************************
  486. *
  487. * MAIN LOOP
  488. *
  489. *****************************************************************/
  490. /**
  491. * Apps Accumulator
  492. *
  493. * Sum all values read from kernel and store in the first address.
  494. *
  495. * @param out the vector with read values.
  496. * @param maps_per_core do I need to read all cores?
  497. */
  498. static void dcstat_apps_accumulator(netdata_dcstat_pid_t *out, int maps_per_core)
  499. {
  500. int i, end = (maps_per_core) ? ebpf_nprocs : 1;
  501. netdata_dcstat_pid_t *total = &out[0];
  502. for (i = 1; i < end; i++) {
  503. netdata_dcstat_pid_t *w = &out[i];
  504. total->cache_access += w->cache_access;
  505. total->file_system += w->file_system;
  506. total->not_found += w->not_found;
  507. }
  508. }
  509. /**
  510. * Save PID values
  511. *
  512. * Save the current values inside the structure
  513. *
  514. * @param out vector used to plot charts
  515. * @param publish vector with values read from hash tables.
  516. */
  517. static inline void dcstat_save_pid_values(netdata_publish_dcstat_t *out, netdata_dcstat_pid_t *publish)
  518. {
  519. memcpy(&out->curr, &publish[0], sizeof(netdata_dcstat_pid_t));
  520. }
  521. /**
  522. * Fill PID
  523. *
  524. * Fill PID structures
  525. *
  526. * @param current_pid pid that we are collecting data
  527. * @param out values read from hash tables;
  528. */
  529. static void dcstat_fill_pid(uint32_t current_pid, netdata_dcstat_pid_t *publish)
  530. {
  531. netdata_publish_dcstat_t *curr = dcstat_pid[current_pid];
  532. if (!curr) {
  533. curr = ebpf_publish_dcstat_get();
  534. dcstat_pid[current_pid] = curr;
  535. }
  536. dcstat_save_pid_values(curr, publish);
  537. }
  538. /**
  539. * Read Directory Cache APPS table
  540. *
  541. * Read the apps table and store data inside the structure.
  542. *
  543. * @param maps_per_core do I need to read all cores?
  544. */
  545. static void read_dc_apps_table(int maps_per_core)
  546. {
  547. netdata_dcstat_pid_t *cv = dcstat_vector;
  548. uint32_t key;
  549. struct ebpf_pid_stat *pids = ebpf_root_of_pids;
  550. int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
  551. size_t length = sizeof(netdata_dcstat_pid_t);
  552. if (maps_per_core)
  553. length *= ebpf_nprocs;
  554. while (pids) {
  555. key = pids->pid;
  556. if (bpf_map_lookup_elem(fd, &key, cv)) {
  557. pids = pids->next;
  558. continue;
  559. }
  560. dcstat_apps_accumulator(cv, maps_per_core);
  561. dcstat_fill_pid(key, cv);
  562. // We are cleaning to avoid passing data read from one process to other.
  563. memset(cv, 0, length);
  564. pids = pids->next;
  565. }
  566. }
  567. /**
  568. * Update cgroup
  569. *
  570. * Update cgroup data based in collected PID.
  571. *
  572. * @param maps_per_core do I need to read all cores?
  573. */
  574. static void ebpf_update_dc_cgroup(int maps_per_core)
  575. {
  576. netdata_dcstat_pid_t *cv = dcstat_vector;
  577. int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
  578. size_t length = sizeof(netdata_dcstat_pid_t)*ebpf_nprocs;
  579. ebpf_cgroup_target_t *ect;
  580. pthread_mutex_lock(&mutex_cgroup_shm);
  581. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  582. struct pid_on_target2 *pids;
  583. for (pids = ect->pids; pids; pids = pids->next) {
  584. int pid = pids->pid;
  585. netdata_dcstat_pid_t *out = &pids->dc;
  586. if (likely(dcstat_pid) && dcstat_pid[pid]) {
  587. netdata_publish_dcstat_t *in = dcstat_pid[pid];
  588. memcpy(out, &in->curr, sizeof(netdata_dcstat_pid_t));
  589. } else {
  590. memset(cv, 0, length);
  591. if (bpf_map_lookup_elem(fd, &pid, cv)) {
  592. continue;
  593. }
  594. dcstat_apps_accumulator(cv, maps_per_core);
  595. memcpy(out, cv, sizeof(netdata_dcstat_pid_t));
  596. }
  597. }
  598. }
  599. pthread_mutex_unlock(&mutex_cgroup_shm);
  600. }
  601. /**
  602. * Read global table
  603. *
  604. * Read the table with number of calls for all functions
  605. *
  606. * @param stats vector used to read data from control table.
  607. * @param maps_per_core do I need to read all cores?
  608. */
  609. static void ebpf_dc_read_global_tables(netdata_idx_t *stats, int maps_per_core)
  610. {
  611. ebpf_read_global_table_stats(dcstat_hash_values,
  612. dcstat_values,
  613. dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd,
  614. maps_per_core,
  615. NETDATA_KEY_DC_REFERENCE,
  616. NETDATA_DIRECTORY_CACHE_END);
  617. ebpf_read_global_table_stats(stats,
  618. dcstat_values,
  619. dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd,
  620. maps_per_core,
  621. NETDATA_CONTROLLER_PID_TABLE_ADD,
  622. NETDATA_CONTROLLER_END);
  623. }
  624. /**
  625. * Cachestat sum PIDs
  626. *
  627. * Sum values for all PIDs associated to a group
  628. *
  629. * @param publish output structure.
  630. * @param root structure with listed IPs
  631. */
  632. void ebpf_dcstat_sum_pids(netdata_publish_dcstat_t *publish, struct ebpf_pid_on_target *root)
  633. {
  634. memset(&publish->curr, 0, sizeof(netdata_dcstat_pid_t));
  635. netdata_dcstat_pid_t *dst = &publish->curr;
  636. while (root) {
  637. int32_t pid = root->pid;
  638. netdata_publish_dcstat_t *w = dcstat_pid[pid];
  639. if (w) {
  640. netdata_dcstat_pid_t *src = &w->curr;
  641. dst->cache_access += src->cache_access;
  642. dst->file_system += src->file_system;
  643. dst->not_found += src->not_found;
  644. }
  645. root = root->next;
  646. }
  647. }
  648. /**
  649. * Send data to Netdata calling auxiliary functions.
  650. *
  651. * @param root the target list.
  652. */
  653. void ebpf_dcache_send_apps_data(struct ebpf_target *root)
  654. {
  655. struct ebpf_target *w;
  656. collected_number value;
  657. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_DC_HIT_CHART);
  658. for (w = root; w; w = w->next) {
  659. if (unlikely(w->exposed && w->processes)) {
  660. ebpf_dcstat_sum_pids(&w->dcstat, w->root_pid);
  661. uint64_t cache = w->dcstat.curr.cache_access;
  662. uint64_t not_found = w->dcstat.curr.not_found;
  663. dcstat_update_publish(&w->dcstat, cache, not_found);
  664. value = (collected_number) w->dcstat.ratio;
  665. write_chart_dimension(w->name, value);
  666. }
  667. }
  668. write_end_chart();
  669. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_DC_REFERENCE_CHART);
  670. for (w = root; w; w = w->next) {
  671. if (unlikely(w->exposed && w->processes)) {
  672. if (w->dcstat.curr.cache_access < w->dcstat.prev.cache_access) {
  673. w->dcstat.prev.cache_access = 0;
  674. }
  675. w->dcstat.cache_access = (long long)w->dcstat.curr.cache_access - (long long)w->dcstat.prev.cache_access;
  676. value = (collected_number) w->dcstat.cache_access;
  677. write_chart_dimension(w->name, value);
  678. w->dcstat.prev.cache_access = w->dcstat.curr.cache_access;
  679. }
  680. }
  681. write_end_chart();
  682. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_DC_REQUEST_NOT_CACHE_CHART);
  683. for (w = root; w; w = w->next) {
  684. if (unlikely(w->exposed && w->processes)) {
  685. if (w->dcstat.curr.file_system < w->dcstat.prev.file_system) {
  686. w->dcstat.prev.file_system = 0;
  687. }
  688. value = (collected_number) (!w->dcstat.cache_access) ? 0 :
  689. (long long )w->dcstat.curr.file_system - (long long)w->dcstat.prev.file_system;
  690. write_chart_dimension(w->name, value);
  691. w->dcstat.prev.file_system = w->dcstat.curr.file_system;
  692. }
  693. }
  694. write_end_chart();
  695. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_DC_REQUEST_NOT_FOUND_CHART);
  696. for (w = root; w; w = w->next) {
  697. if (unlikely(w->exposed && w->processes)) {
  698. if (w->dcstat.curr.not_found < w->dcstat.prev.not_found) {
  699. w->dcstat.prev.not_found = 0;
  700. }
  701. value = (collected_number) (!w->dcstat.cache_access) ? 0 :
  702. (long long)w->dcstat.curr.not_found - (long long)w->dcstat.prev.not_found;
  703. write_chart_dimension(w->name, value);
  704. w->dcstat.prev.not_found = w->dcstat.curr.not_found;
  705. }
  706. }
  707. write_end_chart();
  708. }
  709. /**
  710. * Send global
  711. *
  712. * Send global charts to Netdata
  713. */
  714. static void dcstat_send_global(netdata_publish_dcstat_t *publish)
  715. {
  716. dcstat_update_publish(publish, dcstat_hash_values[NETDATA_KEY_DC_REFERENCE],
  717. dcstat_hash_values[NETDATA_KEY_DC_MISS]);
  718. netdata_publish_syscall_t *ptr = dcstat_counter_publish_aggregated;
  719. netdata_idx_t value = dcstat_hash_values[NETDATA_KEY_DC_REFERENCE];
  720. if (value != ptr[NETDATA_DCSTAT_IDX_REFERENCE].pcall) {
  721. ptr[NETDATA_DCSTAT_IDX_REFERENCE].ncall = value - ptr[NETDATA_DCSTAT_IDX_REFERENCE].pcall;
  722. ptr[NETDATA_DCSTAT_IDX_REFERENCE].pcall = value;
  723. value = dcstat_hash_values[NETDATA_KEY_DC_SLOW];
  724. ptr[NETDATA_DCSTAT_IDX_SLOW].ncall = value - ptr[NETDATA_DCSTAT_IDX_SLOW].pcall;
  725. ptr[NETDATA_DCSTAT_IDX_SLOW].pcall = value;
  726. value = dcstat_hash_values[NETDATA_KEY_DC_MISS];
  727. ptr[NETDATA_DCSTAT_IDX_MISS].ncall = value - ptr[NETDATA_DCSTAT_IDX_MISS].pcall;
  728. ptr[NETDATA_DCSTAT_IDX_MISS].pcall = value;
  729. } else {
  730. ptr[NETDATA_DCSTAT_IDX_REFERENCE].ncall = 0;
  731. ptr[NETDATA_DCSTAT_IDX_SLOW].ncall = 0;
  732. ptr[NETDATA_DCSTAT_IDX_MISS].ncall = 0;
  733. }
  734. ebpf_one_dimension_write_charts(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_HIT_CHART,
  735. ptr[NETDATA_DCSTAT_IDX_RATIO].dimension, publish->ratio);
  736. write_count_chart(
  737. NETDATA_DC_REFERENCE_CHART, NETDATA_FILESYSTEM_FAMILY,
  738. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 3);
  739. }
  740. /**
  741. * Create specific directory cache charts
  742. *
  743. * Create charts for cgroup/application.
  744. *
  745. * @param type the chart type.
  746. * @param update_every value to overwrite the update frequency set by the server.
  747. */
  748. static void ebpf_create_specific_dc_charts(char *type, int update_every)
  749. {
  750. ebpf_create_chart(type, NETDATA_DC_HIT_CHART, "Percentage of files inside directory cache",
  751. EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
  752. NETDATA_CGROUP_DC_HIT_RATIO_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  753. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5700,
  754. ebpf_create_global_dimension,
  755. dcstat_counter_publish_aggregated, 1, update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  756. ebpf_create_chart(type, NETDATA_DC_REFERENCE_CHART, "Count file access",
  757. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  758. NETDATA_CGROUP_DC_REFERENCE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  759. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5701,
  760. ebpf_create_global_dimension,
  761. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 1,
  762. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  763. ebpf_create_chart(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  764. "Files not present inside directory cache",
  765. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  766. NETDATA_CGROUP_DC_NOT_CACHE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  767. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5702,
  768. ebpf_create_global_dimension,
  769. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_SLOW], 1,
  770. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  771. ebpf_create_chart(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  772. "Files not found",
  773. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  774. NETDATA_CGROUP_DC_NOT_FOUND_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  775. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5703,
  776. ebpf_create_global_dimension,
  777. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_MISS], 1,
  778. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  779. }
  780. /**
  781. * Obsolete specific directory cache charts
  782. *
  783. * Obsolete charts for cgroup/application.
  784. *
  785. * @param type the chart type.
  786. * @param update_every value to overwrite the update frequency set by the server.
  787. */
  788. static void ebpf_obsolete_specific_dc_charts(char *type, int update_every)
  789. {
  790. ebpf_write_chart_obsolete(type, NETDATA_DC_HIT_CHART,
  791. "Percentage of files inside directory cache",
  792. EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
  793. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_HIT_RATIO_CONTEXT,
  794. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5700, update_every);
  795. ebpf_write_chart_obsolete(type, NETDATA_DC_REFERENCE_CHART,
  796. "Count file access",
  797. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  798. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_REFERENCE_CONTEXT,
  799. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5701, update_every);
  800. ebpf_write_chart_obsolete(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  801. "Files not present inside directory cache",
  802. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  803. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_NOT_CACHE_CONTEXT,
  804. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5702, update_every);
  805. ebpf_write_chart_obsolete(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  806. "Files not found",
  807. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  808. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_NOT_FOUND_CONTEXT,
  809. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5703, update_every);
  810. }
  811. /**
  812. * Cachestat sum PIDs
  813. *
  814. * Sum values for all PIDs associated to a group
  815. *
  816. * @param publish output structure.
  817. * @param root structure with listed IPs
  818. */
  819. void ebpf_dc_sum_cgroup_pids(netdata_publish_dcstat_t *publish, struct pid_on_target2 *root)
  820. {
  821. memset(&publish->curr, 0, sizeof(netdata_dcstat_pid_t));
  822. netdata_dcstat_pid_t *dst = &publish->curr;
  823. while (root) {
  824. netdata_dcstat_pid_t *src = &root->dc;
  825. dst->cache_access += src->cache_access;
  826. dst->file_system += src->file_system;
  827. dst->not_found += src->not_found;
  828. root = root->next;
  829. }
  830. }
  831. /**
  832. * Calc chart values
  833. *
  834. * Do necessary math to plot charts.
  835. */
  836. void ebpf_dc_calc_chart_values()
  837. {
  838. ebpf_cgroup_target_t *ect;
  839. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  840. ebpf_dc_sum_cgroup_pids(&ect->publish_dc, ect->pids);
  841. uint64_t cache = ect->publish_dc.curr.cache_access;
  842. uint64_t not_found = ect->publish_dc.curr.not_found;
  843. dcstat_update_publish(&ect->publish_dc, cache, not_found);
  844. ect->publish_dc.cache_access = (long long)ect->publish_dc.curr.cache_access -
  845. (long long)ect->publish_dc.prev.cache_access;
  846. ect->publish_dc.prev.cache_access = ect->publish_dc.curr.cache_access;
  847. if (ect->publish_dc.curr.not_found < ect->publish_dc.prev.not_found) {
  848. ect->publish_dc.prev.not_found = 0;
  849. }
  850. }
  851. }
  852. /**
  853. * Create Systemd directory cache Charts
  854. *
  855. * Create charts when systemd is enabled
  856. *
  857. * @param update_every value to overwrite the update frequency set by the server.
  858. **/
  859. static void ebpf_create_systemd_dc_charts(int update_every)
  860. {
  861. ebpf_create_charts_on_systemd(NETDATA_DC_HIT_CHART,
  862. "Percentage of files inside directory cache",
  863. EBPF_COMMON_DIMENSION_PERCENTAGE,
  864. NETDATA_DIRECTORY_CACHE_SUBMENU,
  865. NETDATA_EBPF_CHART_TYPE_LINE,
  866. 21200,
  867. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  868. NETDATA_SYSTEMD_DC_HIT_RATIO_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  869. update_every);
  870. ebpf_create_charts_on_systemd(NETDATA_DC_REFERENCE_CHART,
  871. "Count file access",
  872. EBPF_COMMON_DIMENSION_FILES,
  873. NETDATA_DIRECTORY_CACHE_SUBMENU,
  874. NETDATA_EBPF_CHART_TYPE_LINE,
  875. 21201,
  876. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  877. NETDATA_SYSTEMD_DC_REFERENCE_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  878. update_every);
  879. ebpf_create_charts_on_systemd(NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  880. "Files not present inside directory cache",
  881. EBPF_COMMON_DIMENSION_FILES,
  882. NETDATA_DIRECTORY_CACHE_SUBMENU,
  883. NETDATA_EBPF_CHART_TYPE_LINE,
  884. 21202,
  885. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  886. NETDATA_SYSTEMD_DC_NOT_CACHE_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  887. update_every);
  888. ebpf_create_charts_on_systemd(NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  889. "Files not found",
  890. EBPF_COMMON_DIMENSION_FILES,
  891. NETDATA_DIRECTORY_CACHE_SUBMENU,
  892. NETDATA_EBPF_CHART_TYPE_LINE,
  893. 21202,
  894. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  895. NETDATA_SYSTEMD_DC_NOT_FOUND_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  896. update_every);
  897. }
  898. /**
  899. * Send Directory Cache charts
  900. *
  901. * Send collected data to Netdata.
  902. */
  903. static void ebpf_send_systemd_dc_charts()
  904. {
  905. collected_number value;
  906. ebpf_cgroup_target_t *ect;
  907. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_HIT_CHART);
  908. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  909. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  910. write_chart_dimension(ect->name, (long long) ect->publish_dc.ratio);
  911. }
  912. }
  913. write_end_chart();
  914. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REFERENCE_CHART);
  915. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  916. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  917. write_chart_dimension(ect->name, (long long) ect->publish_dc.cache_access);
  918. }
  919. }
  920. write_end_chart();
  921. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REQUEST_NOT_CACHE_CHART);
  922. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  923. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  924. value = (collected_number) (!ect->publish_dc.cache_access) ? 0 :
  925. (long long )ect->publish_dc.curr.file_system - (long long)ect->publish_dc.prev.file_system;
  926. ect->publish_dc.prev.file_system = ect->publish_dc.curr.file_system;
  927. write_chart_dimension(ect->name, (long long) value);
  928. }
  929. }
  930. write_end_chart();
  931. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REQUEST_NOT_FOUND_CHART);
  932. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  933. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  934. value = (collected_number) (!ect->publish_dc.cache_access) ? 0 :
  935. (long long)ect->publish_dc.curr.not_found - (long long)ect->publish_dc.prev.not_found;
  936. ect->publish_dc.prev.not_found = ect->publish_dc.curr.not_found;
  937. write_chart_dimension(ect->name, (long long) value);
  938. }
  939. }
  940. write_end_chart();
  941. }
  942. /**
  943. * Send Directory Cache charts
  944. *
  945. * Send collected data to Netdata.
  946. *
  947. */
  948. static void ebpf_send_specific_dc_data(char *type, netdata_publish_dcstat_t *pdc)
  949. {
  950. collected_number value;
  951. write_begin_chart(type, NETDATA_DC_HIT_CHART);
  952. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_RATIO].name,
  953. (long long) pdc->ratio);
  954. write_end_chart();
  955. write_begin_chart(type, NETDATA_DC_REFERENCE_CHART);
  956. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE].name,
  957. (long long) pdc->cache_access);
  958. write_end_chart();
  959. value = (collected_number) (!pdc->cache_access) ? 0 :
  960. (long long )pdc->curr.file_system - (long long)pdc->prev.file_system;
  961. pdc->prev.file_system = pdc->curr.file_system;
  962. write_begin_chart(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART);
  963. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_SLOW].name, (long long) value);
  964. write_end_chart();
  965. value = (collected_number) (!pdc->cache_access) ? 0 :
  966. (long long)pdc->curr.not_found - (long long)pdc->prev.not_found;
  967. pdc->prev.not_found = pdc->curr.not_found;
  968. write_begin_chart(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART);
  969. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_MISS].name, (long long) value);
  970. write_end_chart();
  971. }
  972. /**
  973. * Send data to Netdata calling auxiliary functions.
  974. *
  975. * @param update_every value to overwrite the update frequency set by the server.
  976. */
  977. void ebpf_dc_send_cgroup_data(int update_every)
  978. {
  979. if (!ebpf_cgroup_pids)
  980. return;
  981. pthread_mutex_lock(&mutex_cgroup_shm);
  982. ebpf_cgroup_target_t *ect;
  983. ebpf_dc_calc_chart_values();
  984. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  985. if (has_systemd) {
  986. if (send_cgroup_chart) {
  987. ebpf_create_systemd_dc_charts(update_every);
  988. }
  989. ebpf_send_systemd_dc_charts();
  990. }
  991. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  992. if (ect->systemd)
  993. continue;
  994. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_DC_CHART) && ect->updated) {
  995. ebpf_create_specific_dc_charts(ect->name, update_every);
  996. ect->flags |= NETDATA_EBPF_CGROUP_HAS_DC_CHART;
  997. }
  998. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_DC_CHART) {
  999. if (ect->updated) {
  1000. ebpf_send_specific_dc_data(ect->name, &ect->publish_dc);
  1001. } else {
  1002. ebpf_obsolete_specific_dc_charts(ect->name, update_every);
  1003. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_DC_CHART;
  1004. }
  1005. }
  1006. }
  1007. pthread_mutex_unlock(&mutex_cgroup_shm);
  1008. }
  1009. /**
  1010. * Main loop for this collector.
  1011. */
  1012. static void dcstat_collector(ebpf_module_t *em)
  1013. {
  1014. netdata_publish_dcstat_t publish;
  1015. memset(&publish, 0, sizeof(publish));
  1016. int cgroups = em->cgroup_charts;
  1017. int update_every = em->update_every;
  1018. heartbeat_t hb;
  1019. heartbeat_init(&hb);
  1020. int counter = update_every - 1;
  1021. int maps_per_core = em->maps_per_core;
  1022. uint32_t running_time = 0;
  1023. uint32_t lifetime = em->lifetime;
  1024. netdata_idx_t *stats = em->hash_table_stats;
  1025. memset(stats, 0, sizeof(em->hash_table_stats));
  1026. while (!ebpf_exit_plugin && running_time < lifetime) {
  1027. (void)heartbeat_next(&hb, USEC_PER_SEC);
  1028. if (ebpf_exit_plugin || ++counter != update_every)
  1029. continue;
  1030. counter = 0;
  1031. netdata_apps_integration_flags_t apps = em->apps_charts;
  1032. ebpf_dc_read_global_tables(stats, maps_per_core);
  1033. pthread_mutex_lock(&collect_data_mutex);
  1034. if (apps)
  1035. read_dc_apps_table(maps_per_core);
  1036. if (cgroups)
  1037. ebpf_update_dc_cgroup(maps_per_core);
  1038. pthread_mutex_lock(&lock);
  1039. dcstat_send_global(&publish);
  1040. if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
  1041. ebpf_dcache_send_apps_data(apps_groups_root_target);
  1042. #ifdef NETDATA_DEV_MODE
  1043. if (ebpf_aral_dcstat_pid)
  1044. ebpf_send_data_aral_chart(ebpf_aral_dcstat_pid, em);
  1045. #endif
  1046. if (cgroups)
  1047. ebpf_dc_send_cgroup_data(update_every);
  1048. pthread_mutex_unlock(&lock);
  1049. pthread_mutex_unlock(&collect_data_mutex);
  1050. pthread_mutex_lock(&ebpf_exit_cleanup);
  1051. if (running_time && !em->running_time)
  1052. running_time = update_every;
  1053. else
  1054. running_time += update_every;
  1055. em->running_time = running_time;
  1056. pthread_mutex_unlock(&ebpf_exit_cleanup);
  1057. }
  1058. }
  1059. /*****************************************************************
  1060. *
  1061. * INITIALIZE THREAD
  1062. *
  1063. *****************************************************************/
  1064. /**
  1065. * Create filesystem charts
  1066. *
  1067. * Call ebpf_create_chart to create the charts for the collector.
  1068. *
  1069. * @param update_every value to overwrite the update frequency set by the server.
  1070. */
  1071. static void ebpf_create_dc_global_charts(int update_every)
  1072. {
  1073. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_HIT_CHART,
  1074. "Percentage of files inside directory cache",
  1075. EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
  1076. NULL,
  1077. NETDATA_EBPF_CHART_TYPE_LINE,
  1078. 21200,
  1079. ebpf_create_global_dimension,
  1080. dcstat_counter_publish_aggregated, 1, update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  1081. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_REFERENCE_CHART,
  1082. "Variables used to calculate hit ratio.",
  1083. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  1084. NULL,
  1085. NETDATA_EBPF_CHART_TYPE_LINE,
  1086. 21201,
  1087. ebpf_create_global_dimension,
  1088. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 3,
  1089. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  1090. fflush(stdout);
  1091. }
  1092. /**
  1093. * Allocate vectors used with this thread.
  1094. *
  1095. * We are not testing the return, because callocz does this and shutdown the software
  1096. * case it was not possible to allocate.
  1097. *
  1098. * @param apps is apps enabled?
  1099. */
  1100. static void ebpf_dcstat_allocate_global_vectors(int apps)
  1101. {
  1102. if (apps) {
  1103. ebpf_dcstat_aral_init();
  1104. dcstat_pid = callocz((size_t)pid_max, sizeof(netdata_publish_dcstat_t *));
  1105. dcstat_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_dcstat_pid_t));
  1106. }
  1107. dcstat_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
  1108. memset(dcstat_counter_aggregated_data, 0, NETDATA_DCSTAT_IDX_END * sizeof(netdata_syscall_stat_t));
  1109. memset(dcstat_counter_publish_aggregated, 0, NETDATA_DCSTAT_IDX_END * sizeof(netdata_publish_syscall_t));
  1110. }
  1111. /*****************************************************************
  1112. *
  1113. * MAIN THREAD
  1114. *
  1115. *****************************************************************/
  1116. /*
  1117. * Load BPF
  1118. *
  1119. * Load BPF files.
  1120. *
  1121. * @param em the structure with configuration
  1122. */
  1123. static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
  1124. {
  1125. #ifdef LIBBPF_MAJOR_VERSION
  1126. ebpf_define_map_type(dcstat_maps, em->maps_per_core, running_on_kernel);
  1127. #endif
  1128. int ret = 0;
  1129. ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode);
  1130. if (em->load & EBPF_LOAD_LEGACY) {
  1131. em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
  1132. if (!em->probe_links) {
  1133. ret = -1;
  1134. }
  1135. }
  1136. #ifdef LIBBPF_MAJOR_VERSION
  1137. else {
  1138. dc_bpf_obj = dc_bpf__open();
  1139. if (!dc_bpf_obj)
  1140. ret = -1;
  1141. else
  1142. ret = ebpf_dc_load_and_attach(dc_bpf_obj, em);
  1143. }
  1144. #endif
  1145. if (ret)
  1146. netdata_log_error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
  1147. return ret;
  1148. }
  1149. /**
  1150. * Directory Cache thread
  1151. *
  1152. * Thread used to make dcstat thread
  1153. *
  1154. * @param ptr a pointer to `struct ebpf_module`
  1155. *
  1156. * @return It always returns NULL
  1157. */
  1158. void *ebpf_dcstat_thread(void *ptr)
  1159. {
  1160. netdata_thread_cleanup_push(ebpf_dcstat_exit, ptr);
  1161. ebpf_module_t *em = (ebpf_module_t *)ptr;
  1162. em->maps = dcstat_maps;
  1163. ebpf_update_pid_table(&dcstat_maps[NETDATA_DCSTAT_PID_STATS], em);
  1164. ebpf_update_names(dc_optional_name, em);
  1165. #ifdef LIBBPF_MAJOR_VERSION
  1166. ebpf_adjust_thread_load(em, default_btf);
  1167. #endif
  1168. if (ebpf_dcstat_load_bpf(em)) {
  1169. goto enddcstat;
  1170. }
  1171. ebpf_dcstat_allocate_global_vectors(em->apps_charts);
  1172. int algorithms[NETDATA_DCSTAT_IDX_END] = {
  1173. NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX,
  1174. NETDATA_EBPF_ABSOLUTE_IDX
  1175. };
  1176. ebpf_global_labels(dcstat_counter_aggregated_data, dcstat_counter_publish_aggregated,
  1177. dcstat_counter_dimension_name, dcstat_counter_dimension_name,
  1178. algorithms, NETDATA_DCSTAT_IDX_END);
  1179. pthread_mutex_lock(&lock);
  1180. ebpf_create_dc_global_charts(em->update_every);
  1181. ebpf_update_stats(&plugin_statistics, em);
  1182. ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
  1183. #ifdef NETDATA_DEV_MODE
  1184. if (ebpf_aral_dcstat_pid)
  1185. dcstat_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_DCSTAT_ARAL_NAME, em);
  1186. #endif
  1187. pthread_mutex_unlock(&lock);
  1188. dcstat_collector(em);
  1189. enddcstat:
  1190. ebpf_update_disabled_plugin_stats(em);
  1191. netdata_thread_cleanup_pop(1);
  1192. return NULL;
  1193. }