ebpf_dcstat.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420
  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. "",
  266. "Percentage of files inside directory cache",
  267. EBPF_COMMON_DIMENSION_PERCENTAGE,
  268. NETDATA_DIRECTORY_CACHE_SUBMENU,
  269. NETDATA_EBPF_CHART_TYPE_LINE,
  270. NETDATA_SYSTEMD_DC_HIT_RATIO_CONTEXT,
  271. 21200,
  272. em->update_every);
  273. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  274. NETDATA_DC_REFERENCE_CHART,
  275. "",
  276. "Count file access",
  277. EBPF_COMMON_DIMENSION_FILES,
  278. NETDATA_DIRECTORY_CACHE_SUBMENU,
  279. NETDATA_EBPF_CHART_TYPE_LINE,
  280. NETDATA_SYSTEMD_DC_REFERENCE_CONTEXT,
  281. 21201,
  282. em->update_every);
  283. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  284. NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  285. "",
  286. "Files not present inside directory cache",
  287. EBPF_COMMON_DIMENSION_FILES,
  288. NETDATA_DIRECTORY_CACHE_SUBMENU,
  289. NETDATA_EBPF_CHART_TYPE_LINE,
  290. NETDATA_SYSTEMD_DC_NOT_CACHE_CONTEXT,
  291. 21202,
  292. em->update_every);
  293. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  294. NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  295. "",
  296. "Files not found",
  297. EBPF_COMMON_DIMENSION_FILES,
  298. NETDATA_DIRECTORY_CACHE_SUBMENU,
  299. NETDATA_EBPF_CHART_TYPE_LINE,
  300. NETDATA_SYSTEMD_DC_NOT_FOUND_CONTEXT,
  301. 21202,
  302. em->update_every);
  303. }
  304. /**
  305. * Obsolete cgroup chart
  306. *
  307. * Send obsolete for all charts created before to close.
  308. *
  309. * @param em a pointer to `struct ebpf_module`
  310. */
  311. static inline void ebpf_obsolete_dc_cgroup_charts(ebpf_module_t *em) {
  312. pthread_mutex_lock(&mutex_cgroup_shm);
  313. ebpf_obsolete_dc_services(em);
  314. ebpf_cgroup_target_t *ect;
  315. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  316. if (ect->systemd)
  317. continue;
  318. ebpf_obsolete_specific_dc_charts(ect->name, em->update_every);
  319. }
  320. pthread_mutex_unlock(&mutex_cgroup_shm);
  321. }
  322. /**
  323. * Obsolette apps charts
  324. *
  325. * Obsolete apps charts.
  326. *
  327. * @param em a pointer to the structure with the default values.
  328. */
  329. void ebpf_obsolete_dc_apps_charts(struct ebpf_module *em)
  330. {
  331. struct ebpf_target *w;
  332. int update_every = em->update_every;
  333. for (w = apps_groups_root_target; w; w = w->next) {
  334. if (unlikely(!(w->charts_created & (1<<EBPF_MODULE_DCSTAT_IDX))))
  335. continue;
  336. ebpf_write_chart_obsolete(NETDATA_APP_FAMILY,
  337. w->clean_name,
  338. "_ebpf_dc_hit",
  339. "Percentage of files inside directory cache.",
  340. EBPF_COMMON_DIMENSION_PERCENTAGE,
  341. NETDATA_DIRECTORY_CACHE_SUBMENU,
  342. NETDATA_EBPF_CHART_TYPE_LINE,
  343. "app.ebpf_dc_hit",
  344. 20265,
  345. update_every);
  346. ebpf_write_chart_obsolete(NETDATA_APP_FAMILY,
  347. w->clean_name,
  348. "_ebpf_dc_reference",
  349. "Count file access.",
  350. EBPF_COMMON_DIMENSION_FILES,
  351. NETDATA_DIRECTORY_CACHE_SUBMENU,
  352. NETDATA_EBPF_CHART_TYPE_STACKED,
  353. "app.ebpf_dc_reference",
  354. 20266,
  355. update_every);
  356. ebpf_write_chart_obsolete(NETDATA_APP_FAMILY,
  357. w->clean_name,
  358. "_ebpf_not_cache",
  359. "Files not present inside directory cache.",
  360. EBPF_COMMON_DIMENSION_FILES,
  361. NETDATA_DIRECTORY_CACHE_SUBMENU,
  362. NETDATA_EBPF_CHART_TYPE_STACKED,
  363. "app.ebpf_dc_not_cache",
  364. 20267,
  365. update_every);
  366. ebpf_write_chart_obsolete(NETDATA_APP_FAMILY,
  367. w->clean_name,
  368. "_ebpf_not_found",
  369. "Files not found.",
  370. EBPF_COMMON_DIMENSION_FILES,
  371. NETDATA_DIRECTORY_CACHE_SUBMENU,
  372. NETDATA_EBPF_CHART_TYPE_STACKED,
  373. "app.ebpf_dc_not_found",
  374. 20268,
  375. update_every);
  376. w->charts_created &= ~(1<<EBPF_MODULE_DCSTAT_IDX);
  377. }
  378. }
  379. /**
  380. * Obsolete global
  381. *
  382. * Obsolete global charts created by thread.
  383. *
  384. * @param em a pointer to `struct ebpf_module`
  385. */
  386. static void ebpf_obsolete_dc_global(ebpf_module_t *em)
  387. {
  388. ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
  389. NETDATA_DC_HIT_CHART,
  390. "",
  391. "Percentage of files inside directory cache",
  392. EBPF_COMMON_DIMENSION_PERCENTAGE,
  393. NETDATA_DIRECTORY_CACHE_SUBMENU,
  394. NETDATA_EBPF_CHART_TYPE_LINE,
  395. NULL,
  396. 21200,
  397. em->update_every);
  398. ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
  399. NETDATA_DC_REFERENCE_CHART,
  400. "",
  401. "Variables used to calculate hit ratio.",
  402. EBPF_COMMON_DIMENSION_FILES,
  403. NETDATA_DIRECTORY_CACHE_SUBMENU,
  404. NETDATA_EBPF_CHART_TYPE_LINE,
  405. NULL,
  406. 21201,
  407. em->update_every);
  408. }
  409. /**
  410. * DCstat exit
  411. *
  412. * Cancel child and exit.
  413. *
  414. * @param ptr thread data.
  415. */
  416. static void ebpf_dcstat_exit(void *ptr)
  417. {
  418. ebpf_module_t *em = (ebpf_module_t *)ptr;
  419. if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
  420. pthread_mutex_lock(&lock);
  421. if (em->cgroup_charts) {
  422. ebpf_obsolete_dc_cgroup_charts(em);
  423. fflush(stdout);
  424. }
  425. if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
  426. ebpf_obsolete_dc_apps_charts(em);
  427. }
  428. ebpf_obsolete_dc_global(em);
  429. #ifdef NETDATA_DEV_MODE
  430. if (ebpf_aral_dcstat_pid)
  431. ebpf_statistic_obsolete_aral_chart(em, dcstat_disable_priority);
  432. #endif
  433. fflush(stdout);
  434. pthread_mutex_unlock(&lock);
  435. }
  436. ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
  437. #ifdef LIBBPF_MAJOR_VERSION
  438. if (dc_bpf_obj) {
  439. dc_bpf__destroy(dc_bpf_obj);
  440. dc_bpf_obj = NULL;
  441. }
  442. #endif
  443. if (em->objects){
  444. ebpf_unload_legacy_code(em->objects, em->probe_links);
  445. em->objects = NULL;
  446. em->probe_links = NULL;
  447. }
  448. pthread_mutex_lock(&ebpf_exit_cleanup);
  449. em->enabled = NETDATA_THREAD_EBPF_STOPPED;
  450. ebpf_update_stats(&plugin_statistics, em);
  451. pthread_mutex_unlock(&ebpf_exit_cleanup);
  452. }
  453. /*****************************************************************
  454. *
  455. * APPS
  456. *
  457. *****************************************************************/
  458. /**
  459. * Create apps charts
  460. *
  461. * Call ebpf_create_chart to create the charts on apps submenu.
  462. *
  463. * @param em a pointer to the structure with the default values.
  464. */
  465. void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr)
  466. {
  467. struct ebpf_target *root = ptr;
  468. struct ebpf_target *w;
  469. int update_every = em->update_every;
  470. for (w = root; w; w = w->next) {
  471. if (unlikely(!w->exposed))
  472. continue;
  473. ebpf_write_chart_cmd(NETDATA_APP_FAMILY,
  474. w->clean_name,
  475. "_ebpf_dc_hit",
  476. "Percentage of files inside directory cache.",
  477. EBPF_COMMON_DIMENSION_PERCENTAGE,
  478. NETDATA_DIRECTORY_CACHE_SUBMENU,
  479. NETDATA_EBPF_CHART_TYPE_LINE,
  480. "app.ebpf_dc_hit",
  481. 20265,
  482. update_every,
  483. NETDATA_EBPF_MODULE_NAME_DCSTAT);
  484. ebpf_create_chart_labels("app_group", w->name, 0);
  485. ebpf_commit_label();
  486. fprintf(stdout, "DIMENSION ratio '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  487. ebpf_write_chart_cmd(NETDATA_APP_FAMILY,
  488. w->clean_name,
  489. "_ebpf_dc_reference",
  490. "Count file access.",
  491. EBPF_COMMON_DIMENSION_FILES,
  492. NETDATA_DIRECTORY_CACHE_SUBMENU,
  493. NETDATA_EBPF_CHART_TYPE_STACKED,
  494. "app.ebpf_dc_reference",
  495. 20266,
  496. update_every,
  497. NETDATA_EBPF_MODULE_NAME_DCSTAT);
  498. ebpf_create_chart_labels("app_group", w->name, 0);
  499. ebpf_commit_label();
  500. fprintf(stdout, "DIMENSION files '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  501. ebpf_write_chart_cmd(NETDATA_APP_FAMILY,
  502. w->clean_name,
  503. "_ebpf_not_cache",
  504. "Files not present inside directory cache.",
  505. EBPF_COMMON_DIMENSION_FILES,
  506. NETDATA_DIRECTORY_CACHE_SUBMENU,
  507. NETDATA_EBPF_CHART_TYPE_STACKED,
  508. "app.ebpf_dc_not_cache",
  509. 20267,
  510. update_every,
  511. NETDATA_EBPF_MODULE_NAME_DCSTAT);
  512. ebpf_create_chart_labels("app_group", w->name, 0);
  513. ebpf_commit_label();
  514. fprintf(stdout, "DIMENSION files '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  515. ebpf_write_chart_cmd(NETDATA_APP_FAMILY,
  516. w->clean_name,
  517. "_ebpf_not_found",
  518. "Files not found.",
  519. EBPF_COMMON_DIMENSION_FILES,
  520. NETDATA_DIRECTORY_CACHE_SUBMENU,
  521. NETDATA_EBPF_CHART_TYPE_STACKED,
  522. "app.ebpf_dc_not_found",
  523. 20268,
  524. update_every,
  525. NETDATA_EBPF_MODULE_NAME_DCSTAT);
  526. ebpf_create_chart_labels("app_group", w->name, 0);
  527. ebpf_commit_label();
  528. fprintf(stdout, "DIMENSION files '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  529. w->charts_created |= 1<<EBPF_MODULE_DCSTAT_IDX;
  530. }
  531. em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
  532. }
  533. /*****************************************************************
  534. *
  535. * MAIN LOOP
  536. *
  537. *****************************************************************/
  538. /**
  539. * Apps Accumulator
  540. *
  541. * Sum all values read from kernel and store in the first address.
  542. *
  543. * @param out the vector with read values.
  544. * @param maps_per_core do I need to read all cores?
  545. */
  546. static void dcstat_apps_accumulator(netdata_dcstat_pid_t *out, int maps_per_core)
  547. {
  548. int i, end = (maps_per_core) ? ebpf_nprocs : 1;
  549. netdata_dcstat_pid_t *total = &out[0];
  550. for (i = 1; i < end; i++) {
  551. netdata_dcstat_pid_t *w = &out[i];
  552. total->cache_access += w->cache_access;
  553. total->file_system += w->file_system;
  554. total->not_found += w->not_found;
  555. }
  556. }
  557. /**
  558. * Save PID values
  559. *
  560. * Save the current values inside the structure
  561. *
  562. * @param out vector used to plot charts
  563. * @param publish vector with values read from hash tables.
  564. */
  565. static inline void dcstat_save_pid_values(netdata_publish_dcstat_t *out, netdata_dcstat_pid_t *publish)
  566. {
  567. memcpy(&out->curr, &publish[0], sizeof(netdata_dcstat_pid_t));
  568. }
  569. /**
  570. * Fill PID
  571. *
  572. * Fill PID structures
  573. *
  574. * @param current_pid pid that we are collecting data
  575. * @param out values read from hash tables;
  576. */
  577. static void dcstat_fill_pid(uint32_t current_pid, netdata_dcstat_pid_t *publish)
  578. {
  579. netdata_publish_dcstat_t *curr = dcstat_pid[current_pid];
  580. if (!curr) {
  581. curr = ebpf_publish_dcstat_get();
  582. dcstat_pid[current_pid] = curr;
  583. }
  584. dcstat_save_pid_values(curr, publish);
  585. }
  586. /**
  587. * Read Directory Cache APPS table
  588. *
  589. * Read the apps table and store data inside the structure.
  590. *
  591. * @param maps_per_core do I need to read all cores?
  592. */
  593. static void read_dc_apps_table(int maps_per_core)
  594. {
  595. netdata_dcstat_pid_t *cv = dcstat_vector;
  596. uint32_t key;
  597. struct ebpf_pid_stat *pids = ebpf_root_of_pids;
  598. int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
  599. size_t length = sizeof(netdata_dcstat_pid_t);
  600. if (maps_per_core)
  601. length *= ebpf_nprocs;
  602. while (pids) {
  603. key = pids->pid;
  604. if (bpf_map_lookup_elem(fd, &key, cv)) {
  605. pids = pids->next;
  606. continue;
  607. }
  608. dcstat_apps_accumulator(cv, maps_per_core);
  609. dcstat_fill_pid(key, cv);
  610. // We are cleaning to avoid passing data read from one process to other.
  611. memset(cv, 0, length);
  612. pids = pids->next;
  613. }
  614. }
  615. /**
  616. * Update cgroup
  617. *
  618. * Update cgroup data based in collected PID.
  619. *
  620. * @param maps_per_core do I need to read all cores?
  621. */
  622. static void ebpf_update_dc_cgroup(int maps_per_core)
  623. {
  624. netdata_dcstat_pid_t *cv = dcstat_vector;
  625. int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
  626. size_t length = sizeof(netdata_dcstat_pid_t)*ebpf_nprocs;
  627. ebpf_cgroup_target_t *ect;
  628. pthread_mutex_lock(&mutex_cgroup_shm);
  629. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  630. struct pid_on_target2 *pids;
  631. for (pids = ect->pids; pids; pids = pids->next) {
  632. int pid = pids->pid;
  633. netdata_dcstat_pid_t *out = &pids->dc;
  634. if (likely(dcstat_pid) && dcstat_pid[pid]) {
  635. netdata_publish_dcstat_t *in = dcstat_pid[pid];
  636. memcpy(out, &in->curr, sizeof(netdata_dcstat_pid_t));
  637. } else {
  638. memset(cv, 0, length);
  639. if (bpf_map_lookup_elem(fd, &pid, cv)) {
  640. continue;
  641. }
  642. dcstat_apps_accumulator(cv, maps_per_core);
  643. memcpy(out, cv, sizeof(netdata_dcstat_pid_t));
  644. }
  645. }
  646. }
  647. pthread_mutex_unlock(&mutex_cgroup_shm);
  648. }
  649. /**
  650. * Read global table
  651. *
  652. * Read the table with number of calls for all functions
  653. *
  654. * @param stats vector used to read data from control table.
  655. * @param maps_per_core do I need to read all cores?
  656. */
  657. static void ebpf_dc_read_global_tables(netdata_idx_t *stats, int maps_per_core)
  658. {
  659. ebpf_read_global_table_stats(dcstat_hash_values,
  660. dcstat_values,
  661. dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd,
  662. maps_per_core,
  663. NETDATA_KEY_DC_REFERENCE,
  664. NETDATA_DIRECTORY_CACHE_END);
  665. ebpf_read_global_table_stats(stats,
  666. dcstat_values,
  667. dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd,
  668. maps_per_core,
  669. NETDATA_CONTROLLER_PID_TABLE_ADD,
  670. NETDATA_CONTROLLER_END);
  671. }
  672. /**
  673. * Cachestat sum PIDs
  674. *
  675. * Sum values for all PIDs associated to a group
  676. *
  677. * @param publish output structure.
  678. * @param root structure with listed IPs
  679. */
  680. void ebpf_dcstat_sum_pids(netdata_publish_dcstat_t *publish, struct ebpf_pid_on_target *root)
  681. {
  682. memset(&publish->curr, 0, sizeof(netdata_dcstat_pid_t));
  683. netdata_dcstat_pid_t *dst = &publish->curr;
  684. while (root) {
  685. int32_t pid = root->pid;
  686. netdata_publish_dcstat_t *w = dcstat_pid[pid];
  687. if (w) {
  688. netdata_dcstat_pid_t *src = &w->curr;
  689. dst->cache_access += src->cache_access;
  690. dst->file_system += src->file_system;
  691. dst->not_found += src->not_found;
  692. }
  693. root = root->next;
  694. }
  695. }
  696. /**
  697. * Send data to Netdata calling auxiliary functions.
  698. *
  699. * @param root the target list.
  700. */
  701. void ebpf_dcache_send_apps_data(struct ebpf_target *root)
  702. {
  703. struct ebpf_target *w;
  704. collected_number value;
  705. for (w = root; w; w = w->next) {
  706. if (unlikely(!(w->charts_created & (1<<EBPF_MODULE_DCSTAT_IDX))))
  707. continue;
  708. ebpf_dcstat_sum_pids(&w->dcstat, w->root_pid);
  709. uint64_t cache = w->dcstat.curr.cache_access;
  710. uint64_t not_found = w->dcstat.curr.not_found;
  711. dcstat_update_publish(&w->dcstat, cache, not_found);
  712. value = (collected_number) w->dcstat.ratio;
  713. ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_dc_hit");
  714. write_chart_dimension("ratio", value);
  715. ebpf_write_end_chart();
  716. if (w->dcstat.curr.cache_access < w->dcstat.prev.cache_access) {
  717. w->dcstat.prev.cache_access = 0;
  718. }
  719. w->dcstat.cache_access = (long long)w->dcstat.curr.cache_access - (long long)w->dcstat.prev.cache_access;
  720. ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_dc_reference");
  721. value = (collected_number) w->dcstat.cache_access;
  722. write_chart_dimension("files", value);
  723. ebpf_write_end_chart();
  724. w->dcstat.prev.cache_access = w->dcstat.curr.cache_access;
  725. if (w->dcstat.curr.file_system < w->dcstat.prev.file_system) {
  726. w->dcstat.prev.file_system = 0;
  727. }
  728. value = (collected_number) (!w->dcstat.cache_access) ? 0 :
  729. (long long )w->dcstat.curr.file_system - (long long)w->dcstat.prev.file_system;
  730. ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_not_cache");
  731. write_chart_dimension("files", value);
  732. ebpf_write_end_chart();
  733. w->dcstat.prev.file_system = w->dcstat.curr.file_system;
  734. if (w->dcstat.curr.not_found < w->dcstat.prev.not_found) {
  735. w->dcstat.prev.not_found = 0;
  736. }
  737. value = (collected_number) (!w->dcstat.cache_access) ? 0 :
  738. (long long)w->dcstat.curr.not_found - (long long)w->dcstat.prev.not_found;
  739. ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_not_found");
  740. write_chart_dimension("files", value);
  741. ebpf_write_end_chart();
  742. w->dcstat.prev.not_found = w->dcstat.curr.not_found;
  743. }
  744. }
  745. /**
  746. * Send global
  747. *
  748. * Send global charts to Netdata
  749. */
  750. static void dcstat_send_global(netdata_publish_dcstat_t *publish)
  751. {
  752. dcstat_update_publish(publish, dcstat_hash_values[NETDATA_KEY_DC_REFERENCE],
  753. dcstat_hash_values[NETDATA_KEY_DC_MISS]);
  754. netdata_publish_syscall_t *ptr = dcstat_counter_publish_aggregated;
  755. netdata_idx_t value = dcstat_hash_values[NETDATA_KEY_DC_REFERENCE];
  756. if (value != ptr[NETDATA_DCSTAT_IDX_REFERENCE].pcall) {
  757. ptr[NETDATA_DCSTAT_IDX_REFERENCE].ncall = value - ptr[NETDATA_DCSTAT_IDX_REFERENCE].pcall;
  758. ptr[NETDATA_DCSTAT_IDX_REFERENCE].pcall = value;
  759. value = dcstat_hash_values[NETDATA_KEY_DC_SLOW];
  760. ptr[NETDATA_DCSTAT_IDX_SLOW].ncall = value - ptr[NETDATA_DCSTAT_IDX_SLOW].pcall;
  761. ptr[NETDATA_DCSTAT_IDX_SLOW].pcall = value;
  762. value = dcstat_hash_values[NETDATA_KEY_DC_MISS];
  763. ptr[NETDATA_DCSTAT_IDX_MISS].ncall = value - ptr[NETDATA_DCSTAT_IDX_MISS].pcall;
  764. ptr[NETDATA_DCSTAT_IDX_MISS].pcall = value;
  765. } else {
  766. ptr[NETDATA_DCSTAT_IDX_REFERENCE].ncall = 0;
  767. ptr[NETDATA_DCSTAT_IDX_SLOW].ncall = 0;
  768. ptr[NETDATA_DCSTAT_IDX_MISS].ncall = 0;
  769. }
  770. ebpf_one_dimension_write_charts(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_HIT_CHART,
  771. ptr[NETDATA_DCSTAT_IDX_RATIO].dimension, publish->ratio);
  772. write_count_chart(
  773. NETDATA_DC_REFERENCE_CHART, NETDATA_FILESYSTEM_FAMILY,
  774. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 3);
  775. }
  776. /**
  777. * Create specific directory cache charts
  778. *
  779. * Create charts for cgroup/application.
  780. *
  781. * @param type the chart type.
  782. * @param update_every value to overwrite the update frequency set by the server.
  783. */
  784. static void ebpf_create_specific_dc_charts(char *type, int update_every)
  785. {
  786. ebpf_create_chart(type, NETDATA_DC_HIT_CHART, "Percentage of files inside directory cache",
  787. EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
  788. NETDATA_CGROUP_DC_HIT_RATIO_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  789. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5700,
  790. ebpf_create_global_dimension,
  791. dcstat_counter_publish_aggregated, 1, update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  792. ebpf_create_chart(type, NETDATA_DC_REFERENCE_CHART, "Count file access",
  793. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  794. NETDATA_CGROUP_DC_REFERENCE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  795. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5701,
  796. ebpf_create_global_dimension,
  797. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 1,
  798. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  799. ebpf_create_chart(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  800. "Files not present inside directory cache",
  801. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  802. NETDATA_CGROUP_DC_NOT_CACHE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  803. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5702,
  804. ebpf_create_global_dimension,
  805. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_SLOW], 1,
  806. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  807. ebpf_create_chart(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  808. "Files not found",
  809. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  810. NETDATA_CGROUP_DC_NOT_FOUND_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  811. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5703,
  812. ebpf_create_global_dimension,
  813. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_MISS], 1,
  814. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  815. }
  816. /**
  817. * Obsolete specific directory cache charts
  818. *
  819. * Obsolete charts for cgroup/application.
  820. *
  821. * @param type the chart type.
  822. * @param update_every value to overwrite the update frequency set by the server.
  823. */
  824. static void ebpf_obsolete_specific_dc_charts(char *type, int update_every)
  825. {
  826. ebpf_write_chart_obsolete(type, NETDATA_DC_HIT_CHART,
  827. "",
  828. "Percentage of files inside directory cache",
  829. EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
  830. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_HIT_RATIO_CONTEXT,
  831. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5700, update_every);
  832. ebpf_write_chart_obsolete(type, NETDATA_DC_REFERENCE_CHART,
  833. "",
  834. "Count file access",
  835. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  836. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_REFERENCE_CONTEXT,
  837. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5701, update_every);
  838. ebpf_write_chart_obsolete(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  839. "",
  840. "Files not present inside directory cache",
  841. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  842. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_NOT_CACHE_CONTEXT,
  843. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5702, update_every);
  844. ebpf_write_chart_obsolete(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  845. "",
  846. "Files not found",
  847. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  848. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_NOT_FOUND_CONTEXT,
  849. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5703, update_every);
  850. }
  851. /**
  852. * Cachestat sum PIDs
  853. *
  854. * Sum values for all PIDs associated to a group
  855. *
  856. * @param publish output structure.
  857. * @param root structure with listed IPs
  858. */
  859. void ebpf_dc_sum_cgroup_pids(netdata_publish_dcstat_t *publish, struct pid_on_target2 *root)
  860. {
  861. memset(&publish->curr, 0, sizeof(netdata_dcstat_pid_t));
  862. netdata_dcstat_pid_t *dst = &publish->curr;
  863. while (root) {
  864. netdata_dcstat_pid_t *src = &root->dc;
  865. dst->cache_access += src->cache_access;
  866. dst->file_system += src->file_system;
  867. dst->not_found += src->not_found;
  868. root = root->next;
  869. }
  870. }
  871. /**
  872. * Calc chart values
  873. *
  874. * Do necessary math to plot charts.
  875. */
  876. void ebpf_dc_calc_chart_values()
  877. {
  878. ebpf_cgroup_target_t *ect;
  879. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  880. ebpf_dc_sum_cgroup_pids(&ect->publish_dc, ect->pids);
  881. uint64_t cache = ect->publish_dc.curr.cache_access;
  882. uint64_t not_found = ect->publish_dc.curr.not_found;
  883. dcstat_update_publish(&ect->publish_dc, cache, not_found);
  884. ect->publish_dc.cache_access = (long long)ect->publish_dc.curr.cache_access -
  885. (long long)ect->publish_dc.prev.cache_access;
  886. ect->publish_dc.prev.cache_access = ect->publish_dc.curr.cache_access;
  887. if (ect->publish_dc.curr.not_found < ect->publish_dc.prev.not_found) {
  888. ect->publish_dc.prev.not_found = 0;
  889. }
  890. }
  891. }
  892. /**
  893. * Create Systemd directory cache Charts
  894. *
  895. * Create charts when systemd is enabled
  896. *
  897. * @param update_every value to overwrite the update frequency set by the server.
  898. **/
  899. static void ebpf_create_systemd_dc_charts(int update_every)
  900. {
  901. ebpf_create_charts_on_systemd(NETDATA_DC_HIT_CHART,
  902. "Percentage of files inside directory cache",
  903. EBPF_COMMON_DIMENSION_PERCENTAGE,
  904. NETDATA_DIRECTORY_CACHE_SUBMENU,
  905. NETDATA_EBPF_CHART_TYPE_LINE,
  906. 21200,
  907. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  908. NETDATA_SYSTEMD_DC_HIT_RATIO_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  909. update_every);
  910. ebpf_create_charts_on_systemd(NETDATA_DC_REFERENCE_CHART,
  911. "Count file access",
  912. EBPF_COMMON_DIMENSION_FILES,
  913. NETDATA_DIRECTORY_CACHE_SUBMENU,
  914. NETDATA_EBPF_CHART_TYPE_LINE,
  915. 21201,
  916. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  917. NETDATA_SYSTEMD_DC_REFERENCE_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  918. update_every);
  919. ebpf_create_charts_on_systemd(NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  920. "Files not present inside directory cache",
  921. EBPF_COMMON_DIMENSION_FILES,
  922. NETDATA_DIRECTORY_CACHE_SUBMENU,
  923. NETDATA_EBPF_CHART_TYPE_LINE,
  924. 21202,
  925. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  926. NETDATA_SYSTEMD_DC_NOT_CACHE_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  927. update_every);
  928. ebpf_create_charts_on_systemd(NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  929. "Files not found",
  930. EBPF_COMMON_DIMENSION_FILES,
  931. NETDATA_DIRECTORY_CACHE_SUBMENU,
  932. NETDATA_EBPF_CHART_TYPE_LINE,
  933. 21202,
  934. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  935. NETDATA_SYSTEMD_DC_NOT_FOUND_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  936. update_every);
  937. }
  938. /**
  939. * Send Directory Cache charts
  940. *
  941. * Send collected data to Netdata.
  942. */
  943. static void ebpf_send_systemd_dc_charts()
  944. {
  945. collected_number value;
  946. ebpf_cgroup_target_t *ect;
  947. ebpf_write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_HIT_CHART, "");
  948. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  949. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  950. write_chart_dimension(ect->name, (long long) ect->publish_dc.ratio);
  951. }
  952. }
  953. ebpf_write_end_chart();
  954. ebpf_write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REFERENCE_CHART, "");
  955. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  956. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  957. write_chart_dimension(ect->name, (long long) ect->publish_dc.cache_access);
  958. }
  959. }
  960. ebpf_write_end_chart();
  961. ebpf_write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REQUEST_NOT_CACHE_CHART, "");
  962. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  963. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  964. value = (collected_number) (!ect->publish_dc.cache_access) ? 0 :
  965. (long long )ect->publish_dc.curr.file_system - (long long)ect->publish_dc.prev.file_system;
  966. ect->publish_dc.prev.file_system = ect->publish_dc.curr.file_system;
  967. write_chart_dimension(ect->name, (long long) value);
  968. }
  969. }
  970. ebpf_write_end_chart();
  971. ebpf_write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REQUEST_NOT_FOUND_CHART, "");
  972. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  973. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  974. value = (collected_number) (!ect->publish_dc.cache_access) ? 0 :
  975. (long long)ect->publish_dc.curr.not_found - (long long)ect->publish_dc.prev.not_found;
  976. ect->publish_dc.prev.not_found = ect->publish_dc.curr.not_found;
  977. write_chart_dimension(ect->name, (long long) value);
  978. }
  979. }
  980. ebpf_write_end_chart();
  981. }
  982. /**
  983. * Send Directory Cache charts
  984. *
  985. * Send collected data to Netdata.
  986. *
  987. */
  988. static void ebpf_send_specific_dc_data(char *type, netdata_publish_dcstat_t *pdc)
  989. {
  990. collected_number value;
  991. ebpf_write_begin_chart(type, NETDATA_DC_HIT_CHART, "");
  992. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_RATIO].name,
  993. (long long) pdc->ratio);
  994. ebpf_write_end_chart();
  995. ebpf_write_begin_chart(type, NETDATA_DC_REFERENCE_CHART, "");
  996. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE].name,
  997. (long long) pdc->cache_access);
  998. ebpf_write_end_chart();
  999. value = (collected_number) (!pdc->cache_access) ? 0 :
  1000. (long long )pdc->curr.file_system - (long long)pdc->prev.file_system;
  1001. pdc->prev.file_system = pdc->curr.file_system;
  1002. ebpf_write_begin_chart(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART, "");
  1003. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_SLOW].name, (long long) value);
  1004. ebpf_write_end_chart();
  1005. value = (collected_number) (!pdc->cache_access) ? 0 :
  1006. (long long)pdc->curr.not_found - (long long)pdc->prev.not_found;
  1007. pdc->prev.not_found = pdc->curr.not_found;
  1008. ebpf_write_begin_chart(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART, "");
  1009. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_MISS].name, (long long) value);
  1010. ebpf_write_end_chart();
  1011. }
  1012. /**
  1013. * Send data to Netdata calling auxiliary functions.
  1014. *
  1015. * @param update_every value to overwrite the update frequency set by the server.
  1016. */
  1017. void ebpf_dc_send_cgroup_data(int update_every)
  1018. {
  1019. if (!ebpf_cgroup_pids)
  1020. return;
  1021. pthread_mutex_lock(&mutex_cgroup_shm);
  1022. ebpf_cgroup_target_t *ect;
  1023. ebpf_dc_calc_chart_values();
  1024. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  1025. if (has_systemd) {
  1026. if (send_cgroup_chart) {
  1027. ebpf_create_systemd_dc_charts(update_every);
  1028. }
  1029. ebpf_send_systemd_dc_charts();
  1030. }
  1031. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  1032. if (ect->systemd)
  1033. continue;
  1034. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_DC_CHART) && ect->updated) {
  1035. ebpf_create_specific_dc_charts(ect->name, update_every);
  1036. ect->flags |= NETDATA_EBPF_CGROUP_HAS_DC_CHART;
  1037. }
  1038. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_DC_CHART) {
  1039. if (ect->updated) {
  1040. ebpf_send_specific_dc_data(ect->name, &ect->publish_dc);
  1041. } else {
  1042. ebpf_obsolete_specific_dc_charts(ect->name, update_every);
  1043. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_DC_CHART;
  1044. }
  1045. }
  1046. }
  1047. pthread_mutex_unlock(&mutex_cgroup_shm);
  1048. }
  1049. /**
  1050. * Main loop for this collector.
  1051. */
  1052. static void dcstat_collector(ebpf_module_t *em)
  1053. {
  1054. netdata_publish_dcstat_t publish;
  1055. memset(&publish, 0, sizeof(publish));
  1056. int cgroups = em->cgroup_charts;
  1057. int update_every = em->update_every;
  1058. heartbeat_t hb;
  1059. heartbeat_init(&hb);
  1060. int counter = update_every - 1;
  1061. int maps_per_core = em->maps_per_core;
  1062. uint32_t running_time = 0;
  1063. uint32_t lifetime = em->lifetime;
  1064. netdata_idx_t *stats = em->hash_table_stats;
  1065. memset(stats, 0, sizeof(em->hash_table_stats));
  1066. while (!ebpf_plugin_exit && running_time < lifetime) {
  1067. (void)heartbeat_next(&hb, USEC_PER_SEC);
  1068. if (ebpf_plugin_exit || ++counter != update_every)
  1069. continue;
  1070. counter = 0;
  1071. netdata_apps_integration_flags_t apps = em->apps_charts;
  1072. ebpf_dc_read_global_tables(stats, maps_per_core);
  1073. pthread_mutex_lock(&collect_data_mutex);
  1074. if (apps)
  1075. read_dc_apps_table(maps_per_core);
  1076. if (cgroups)
  1077. ebpf_update_dc_cgroup(maps_per_core);
  1078. pthread_mutex_lock(&lock);
  1079. dcstat_send_global(&publish);
  1080. if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
  1081. ebpf_dcache_send_apps_data(apps_groups_root_target);
  1082. #ifdef NETDATA_DEV_MODE
  1083. if (ebpf_aral_dcstat_pid)
  1084. ebpf_send_data_aral_chart(ebpf_aral_dcstat_pid, em);
  1085. #endif
  1086. if (cgroups)
  1087. ebpf_dc_send_cgroup_data(update_every);
  1088. pthread_mutex_unlock(&lock);
  1089. pthread_mutex_unlock(&collect_data_mutex);
  1090. pthread_mutex_lock(&ebpf_exit_cleanup);
  1091. if (running_time && !em->running_time)
  1092. running_time = update_every;
  1093. else
  1094. running_time += update_every;
  1095. em->running_time = running_time;
  1096. pthread_mutex_unlock(&ebpf_exit_cleanup);
  1097. }
  1098. }
  1099. /*****************************************************************
  1100. *
  1101. * INITIALIZE THREAD
  1102. *
  1103. *****************************************************************/
  1104. /**
  1105. * Create filesystem charts
  1106. *
  1107. * Call ebpf_create_chart to create the charts for the collector.
  1108. *
  1109. * @param update_every value to overwrite the update frequency set by the server.
  1110. */
  1111. static void ebpf_create_dc_global_charts(int update_every)
  1112. {
  1113. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_HIT_CHART,
  1114. "Percentage of files inside directory cache",
  1115. EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
  1116. NULL,
  1117. NETDATA_EBPF_CHART_TYPE_LINE,
  1118. 21200,
  1119. ebpf_create_global_dimension,
  1120. dcstat_counter_publish_aggregated, 1, update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  1121. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_REFERENCE_CHART,
  1122. "Variables used to calculate hit ratio.",
  1123. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  1124. NULL,
  1125. NETDATA_EBPF_CHART_TYPE_LINE,
  1126. 21201,
  1127. ebpf_create_global_dimension,
  1128. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 3,
  1129. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  1130. fflush(stdout);
  1131. }
  1132. /**
  1133. * Allocate vectors used with this thread.
  1134. *
  1135. * We are not testing the return, because callocz does this and shutdown the software
  1136. * case it was not possible to allocate.
  1137. *
  1138. * @param apps is apps enabled?
  1139. */
  1140. static void ebpf_dcstat_allocate_global_vectors(int apps)
  1141. {
  1142. if (apps) {
  1143. ebpf_dcstat_aral_init();
  1144. dcstat_pid = callocz((size_t)pid_max, sizeof(netdata_publish_dcstat_t *));
  1145. dcstat_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_dcstat_pid_t));
  1146. }
  1147. dcstat_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
  1148. memset(dcstat_counter_aggregated_data, 0, NETDATA_DCSTAT_IDX_END * sizeof(netdata_syscall_stat_t));
  1149. memset(dcstat_counter_publish_aggregated, 0, NETDATA_DCSTAT_IDX_END * sizeof(netdata_publish_syscall_t));
  1150. }
  1151. /*****************************************************************
  1152. *
  1153. * MAIN THREAD
  1154. *
  1155. *****************************************************************/
  1156. /*
  1157. * Load BPF
  1158. *
  1159. * Load BPF files.
  1160. *
  1161. * @param em the structure with configuration
  1162. */
  1163. static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
  1164. {
  1165. #ifdef LIBBPF_MAJOR_VERSION
  1166. ebpf_define_map_type(dcstat_maps, em->maps_per_core, running_on_kernel);
  1167. #endif
  1168. int ret = 0;
  1169. ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode);
  1170. if (em->load & EBPF_LOAD_LEGACY) {
  1171. em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
  1172. if (!em->probe_links) {
  1173. ret = -1;
  1174. }
  1175. }
  1176. #ifdef LIBBPF_MAJOR_VERSION
  1177. else {
  1178. dc_bpf_obj = dc_bpf__open();
  1179. if (!dc_bpf_obj)
  1180. ret = -1;
  1181. else
  1182. ret = ebpf_dc_load_and_attach(dc_bpf_obj, em);
  1183. }
  1184. #endif
  1185. if (ret)
  1186. netdata_log_error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->info.thread_name);
  1187. return ret;
  1188. }
  1189. /**
  1190. * Directory Cache thread
  1191. *
  1192. * Thread used to make dcstat thread
  1193. *
  1194. * @param ptr a pointer to `struct ebpf_module`
  1195. *
  1196. * @return It always returns NULL
  1197. */
  1198. void *ebpf_dcstat_thread(void *ptr)
  1199. {
  1200. netdata_thread_cleanup_push(ebpf_dcstat_exit, ptr);
  1201. ebpf_module_t *em = (ebpf_module_t *)ptr;
  1202. em->maps = dcstat_maps;
  1203. ebpf_update_pid_table(&dcstat_maps[NETDATA_DCSTAT_PID_STATS], em);
  1204. ebpf_update_names(dc_optional_name, em);
  1205. #ifdef LIBBPF_MAJOR_VERSION
  1206. ebpf_adjust_thread_load(em, default_btf);
  1207. #endif
  1208. if (ebpf_dcstat_load_bpf(em)) {
  1209. goto enddcstat;
  1210. }
  1211. ebpf_dcstat_allocate_global_vectors(em->apps_charts);
  1212. int algorithms[NETDATA_DCSTAT_IDX_END] = {
  1213. NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX,
  1214. NETDATA_EBPF_ABSOLUTE_IDX
  1215. };
  1216. ebpf_global_labels(dcstat_counter_aggregated_data, dcstat_counter_publish_aggregated,
  1217. dcstat_counter_dimension_name, dcstat_counter_dimension_name,
  1218. algorithms, NETDATA_DCSTAT_IDX_END);
  1219. pthread_mutex_lock(&lock);
  1220. ebpf_create_dc_global_charts(em->update_every);
  1221. ebpf_update_stats(&plugin_statistics, em);
  1222. ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
  1223. #ifdef NETDATA_DEV_MODE
  1224. if (ebpf_aral_dcstat_pid)
  1225. dcstat_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_DCSTAT_ARAL_NAME, em);
  1226. #endif
  1227. pthread_mutex_unlock(&lock);
  1228. dcstat_collector(em);
  1229. enddcstat:
  1230. ebpf_update_disabled_plugin_stats(em);
  1231. netdata_thread_cleanup_pop(1);
  1232. return NULL;
  1233. }